Merge remote-tracking branch 'u-boot/master' into 'u-boot-arm/master'
diff --git a/.travis.yml b/.travis.yml
index 90f0fd7..923c9dd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -107,9 +107,6 @@
         - TEST_CMD="tools/buildman/buildman mpc512x"
           INSTALL_TOOLCHAIN="ppc"
     - env:
-        - TEST_CMD="tools/buildman/buildman mpc824x"
-          INSTALL_TOOLCHAIN="ppc"
-    - env:
         - TEST_CMD="tools/buildman/buildman mpc8260"
           INSTALL_TOOLCHAIN="ppc"
     - env:
diff --git a/Kconfig b/Kconfig
index 4157da3..75bab7f 100644
--- a/Kconfig
+++ b/Kconfig
@@ -56,6 +56,25 @@
 
 	  This option is enabled by default for U-Boot.
 
+config SYS_MALLOC_F
+	bool "Enable malloc() pool before relocation"
+	default 0x400
+	help
+	  Before relocation memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
+config SYS_MALLOC_F_LEN
+	hex "Size of malloc() pool before relocation"
+	depends on SYS_MALLOC_F
+	default 0x400
+	help
+	  Before relocation memory is very limited on many platforms. Still,
+	  we can provide a small malloc() pool if needed. Driver model in
+	  particular needs this to operate, so that it can allocate the
+	  initial serial device and any others that are needed.
+
 menuconfig EXPERT
         bool "Configure standard U-Boot features (expert users)"
         help
@@ -116,8 +135,10 @@
 	depends on FIT
 
 config FIT_SIGNATURE
-	bool "Enabel signature verification of FIT uImages"
+	bool "Enable signature verification of FIT uImages"
 	depends on FIT
+	depends on DM
+	select RSA
 	help
 	  This option enables signature verification of FIT uImages,
 	  using a hash signed and verified using RSA.
@@ -138,7 +159,7 @@
 	  new boards should not use this option.
 
 config SYS_TEXT_BASE
-	depends on SPARC
+	depends on SPARC || ARC
 	hex "Text Base"
 	help
 	  TODO: Move CONFIG_SYS_TEXT_BASE for all the architecture
@@ -164,3 +185,5 @@
 source "fs/Kconfig"
 
 source "lib/Kconfig"
+
+source "test/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index 1f77359..eef70d0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -76,9 +76,7 @@
 M:	Andreas Bießmann <andreas.devel@googlemail.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-atmel.git
-F:	arch/arm/cpu/armv7/at91/
-F:	arch/arm/cpu/at91-common/
-F:	arch/arm/include/asm/arch-at91/
+F:	arch/arm/mach-at91/
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
@@ -100,8 +98,7 @@
 M:	Luka Perkov <luka.perkov@sartura.hr>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-marvell.git
-F:	arch/arm/cpu/arm926ejs/kirkwood/
-F:	arch/arm/include/asm/arch-kirkwood/
+F:	arch/arm/mach-kirkwood/
 
 ARM MARVELL PXA
 M:	Marek Vasut <marex@denx.de>
@@ -147,9 +144,7 @@
 M:	Tom Warren <twarren@nvidia.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-tegra.git
-F:	arch/arm/cpu/arm720t/tegra*/
-F:	arch/arm/cpu/armv7/tegra*/
-F:	arch/arm/cpu/tegra*/
+F:	arch/arm/mach-tegra/
 F:	arch/arm/include/asm/arch-tegra*/
 
 ARM TI
@@ -170,7 +165,7 @@
 F:	arch/arm/cpu/armv7/uniphier/
 F:	arch/arm/include/asm/arch-uniphier/
 F:	configs/ph1_*_defconfig
-F:	drivers/serial/serial_uniphier.c
+N:	uniphier
 
 ARM ZYNQ
 M:	Michal Simek <monstr@monstr.eu>
diff --git a/Makefile b/Makefile
index ea5ae8f..bd4abab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2015
-PATCHLEVEL = 01
+PATCHLEVEL = 04
 SUBLEVEL =
-EXTRAVERSION =
+EXTRAVERSION = -rc2
 NAME =
 
 # *DOCUMENTATION*
@@ -281,6 +281,11 @@
 HOSTCC       = $(call os_x_before, 10, 5, "cc", "gcc")
 HOSTCFLAGS  += $(call os_x_before, 10, 4, "-traditional-cpp")
 HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress")
+
+# since Lion (10.7) ASLR is on by default, but we use linker generated lists
+# in some host tools which is a problem then ... so disable ASLR for these
+# tools
+HOSTLDFLAGS += $(call os_x_before, 10, 7, "", "-Xlinker -no_pie")
 endif
 
 # Decide whether to build built-in, modular, or both.
@@ -729,8 +734,9 @@
 endif
 ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
 
-# We can't do this yet due to the need for binary blobs
-# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+ifneq ($(BUILD_ROM),)
+ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+endif
 
 # enable combined SPL/u-boot/dtb rules for tegra
 ifneq ($(CONFIG_TEGRA),)
@@ -776,6 +782,13 @@
 	@echo "See doc/README.generic-board for further information"
 	@echo "===================================================="
 endif
+ifeq ($(CONFIG_DM_I2C_COMPAT),y)
+	@echo "===================== WARNING ======================"
+	@echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
+	@echo "(possibly in a subsequent patch in your series)"
+	@echo "before sending patches to the mailing list."
+	@echo "===================================================="
+endif
 
 PHONY += dtbs
 dtbs dts/dt.dtb: checkdtc u-boot
@@ -849,12 +862,18 @@
 MKIMAGEFLAGS_u-boot.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
 	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
 
+MKIMAGEFLAGS_u-boot-spl.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
+	-T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
+
 MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
 		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
 
 u-boot.img u-boot.kwb u-boot.pbl: u-boot.bin FORCE
 	$(call if_changed,mkimage)
 
+u-boot-spl.kwb: u-boot.img spl/u-boot-spl.bin FORCE
+	$(call if_changed,mkimage)
+
 MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)
 
 u-boot-dtb.img: u-boot-dtb.bin FORCE
diff --git a/README b/README
index fefa71c..ba57dc5 100644
--- a/README
+++ b/README
@@ -1257,6 +1257,9 @@
 		SoC, then define this variable and provide board
 		specific code for the "hw_watchdog_reset" function.
 
+		CONFIG_AT91_HW_WDT_TIMEOUT
+		specify the timeout in seconds. default 2 seconds.
+
 - U-Boot Version:
 		CONFIG_VERSION_VARIABLE
 		If this variable is defined, an environment variable
@@ -3176,8 +3179,13 @@
 		This enables the RSA algorithm used for FIT image verification
 		in U-Boot. See doc/uImage.FIT/signature.txt for more information.
 
+		The Modular Exponentiation algorithm in RSA is implemented using
+		driver model. So CONFIG_DM needs to be enabled by default for this
+		library to function.
+
 		The signing part is build into mkimage regardless of this
-		option.
+		option. The software based modular exponentiation is built into
+		mkimage irrespective of this option.
 
 - bootcount support:
 		CONFIG_BOOTCOUNT_LIMIT
@@ -5899,9 +5907,10 @@
 option). Given an image built by mkimage, the dumpimage extracts a "data file"
 from the image:
 
-	tools/dumpimage -i image -p position data_file
-	  -i ==> extract from the 'image' a specific 'data_file', \
-	   indexed by 'position'
+	tools/dumpimage -i image -T type -p position data_file
+	  -i ==> extract from the 'image' a specific 'data_file'
+	  -T ==> set image type to 'type'
+	  -p ==> 'position' (starting at 0) of the 'data_file' inside the 'image'
 
 
 Installing a Linux Image:
diff --git a/arch/Kconfig b/arch/Kconfig
index f63cc5a..3d419bc 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -4,6 +4,7 @@
 
 config ARC
 	bool "ARC architecture"
+	select HAVE_PRIVATE_LIBGCC
 
 config ARM
 	bool "ARM architecture"
@@ -39,6 +40,7 @@
 config PPC
 	bool "PowerPC architecture"
 	select HAVE_PRIVATE_LIBGCC
+	select SUPPORT_OF_CONTROL
 
 config SANDBOX
 	bool "Sandbox"
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index c6b1efe..24f5c02 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -4,8 +4,131 @@
 config SYS_ARCH
 	default "arc"
 
+config USE_PRIVATE_LIBGCC
+	default y
+
 config SYS_CPU
-	default "arcv1"
+	default "arcv1" if ISA_ARCOMPACT
+	default "arcv2" if ISA_ARCV2
+
+choice
+	prompt "ARC Instruction Set"
+	default ISA_ARCOMPACT
+
+config ISA_ARCOMPACT
+	bool "ARCompact ISA"
+	help
+	  The original ARC ISA of ARC600/700 cores
+
+config ISA_ARCV2
+	bool "ARC ISA v2"
+	help
+	  ISA for the Next Generation ARC-HS cores
+
+endchoice
+
+choice
+	prompt "CPU selection"
+	default CPU_ARC770D if ISA_ARCOMPACT
+	default CPU_ARCHS38 if ISA_ARCV2
+
+config CPU_ARC750D
+	bool "ARC 750D"
+	select ARC_MMU_V2
+	depends on ISA_ARCOMPACT
+	help
+	  Choose this option to build an U-Boot for ARC750D CPU.
+
+config CPU_ARC770D
+	bool "ARC 770D"
+	select ARC_MMU_V3
+	depends on ISA_ARCOMPACT
+	help
+	  Choose this option to build an U-Boot for ARC770D CPU.
+
+config CPU_ARCEM6
+	bool "ARC EM6"
+	select ARC_MMU_ABSENT
+	depends on ISA_ARCV2
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS36
+	bool "ARC HS36"
+	select ARC_MMU_ABSENT
+	depends on ISA_ARCV2
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS38
+	bool "ARC HS38"
+	select ARC_MMU_V4
+	depends on ISA_ARCV2
+	help
+	  Next Generation ARC Core based on ISA-v2 ISA with MMU.
+
+endchoice
+
+choice
+	prompt "MMU Version"
+	default ARC_MMU_V3 if CPU_ARC770D
+	default ARC_MMU_V2 if CPU_ARC750D
+	default ARC_MMU_ABSENT if CPU_ARCEM6
+	default ARC_MMU_ABSENT if CPU_ARCHS36
+	default ARC_MMU_V4 if CPU_ARCHS38
+
+config ARC_MMU_ABSENT
+	bool "No MMU"
+	help
+	  No MMU
+
+config ARC_MMU_V2
+	bool "MMU v2"
+	depends on CPU_ARC750D
+	help
+	  Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio
+	  when 2 D-TLB and 1 I-TLB entries index into same 2way set.
+
+config ARC_MMU_V3
+	bool "MMU v3"
+	depends on CPU_ARC770D
+	help
+	  Introduced with ARC700 4.10: New Features
+	  Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
+	  Shared Address Spaces (SASID)
+
+config ARC_MMU_V4
+	bool "MMU v4"
+	depends on CPU_ARCHS38
+	help
+	  Introduced as a part of ARC HS38 release.
+
+endchoice
+
+config CPU_BIG_ENDIAN
+	bool "Enable Big Endian Mode"
+	default n
+	help
+	  Build kernel for Big Endian Mode of ARC CPU
+
+config SYS_ICACHE_OFF
+	bool "Do not use Instruction Cache"
+	default n
+
+config SYS_DCACHE_OFF
+	bool "Do not use Data Cache"
+	default n
+
+config ARC_CACHE_LINE_SHIFT
+	int "Cache Line Length (as power of 2)"
+	range 5 7
+	default "6"
+	depends on !SYS_DCACHE_OFF || !SYS_DCACHE_OFF
+	help
+	  Starting with ARC700 4.9, Cache line length is configurable,
+	  This option specifies "N", with Line-len = 2 power N
+	  So line lengths of 32, 64, 128 are specified by 5,6,7, respectively
+	  Linux only supports same line lengths for I and D caches.
 
 choice
 	prompt "Target select"
@@ -16,9 +139,6 @@
 config TARGET_ARCANGEL4
 	bool "Support arcangel4"
 
-config TARGET_ARCANGEL4_BE
-	bool "Support arcangel4-be"
-
 config TARGET_AXS101
 	bool "Support axs101"
 
diff --git a/arch/arc/config.mk b/arch/arc/config.mk
index 5321987..4fcd407 100644
--- a/arch/arc/config.mk
+++ b/arch/arc/config.mk
@@ -4,17 +4,22 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-ifndef CONFIG_SYS_BIG_ENDIAN
+ifndef CONFIG_CPU_BIG_ENDIAN
 CONFIG_SYS_LITTLE_ENDIAN = 1
+else
+CONFIG_SYS_BIG_ENDIAN = 1
 endif
 
 ifdef CONFIG_SYS_LITTLE_ENDIAN
 ARC_CROSS_COMPILE := arc-buildroot-linux-uclibc-
+PLATFORM_LDFLAGS += -EL
+PLATFORM_CPPFLAGS += -mlittle-endian
 endif
 
 ifdef CONFIG_SYS_BIG_ENDIAN
 ARC_CROSS_COMPILE := arceb-buildroot-linux-uclibc-
 PLATFORM_LDFLAGS += -EB
+PLATFORM_CPPFLAGS += -mbig-endian
 endif
 
 ifeq ($(CROSS_COMPILE),)
@@ -25,6 +30,26 @@
 CONFIG_MMU = 1
 endif
 
+ifdef CONFIG_CPU_ARC750D
+PLATFORM_CPPFLAGS += -marc700
+endif
+
+ifdef CONFIG_CPU_ARC770D
+PLATFORM_CPPFLAGS += -marc700 -mlock -mswape
+endif
+
+ifdef CONFIG_CPU_ARCEM6
+PLATFORM_CPPFLAGS += -marcem
+endif
+
+ifdef CONFIG_CPU_ARCHS34
+PLATFORM_CPPFLAGS += -marchs
+endif
+
+ifdef CONFIG_CPU_ARCHS38
+PLATFORM_CPPFLAGS += -marchs
+endif
+
 PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2
 
 # Needed for relocation
diff --git a/arch/arc/cpu/arcv1/config.mk b/arch/arc/cpu/arcv1/config.mk
deleted file mode 100644
index 3206ff4..0000000
--- a/arch/arc/cpu/arcv1/config.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-PLATFORM_CPPFLAGS += -mA7
diff --git a/arch/arc/cpu/arcv2/Makefile b/arch/arc/cpu/arcv2/Makefile
new file mode 100644
index 0000000..cc69e5a
--- /dev/null
+++ b/arch/arc/cpu/arcv2/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += start.o
diff --git a/arch/arc/cpu/arcv2/start.S b/arch/arc/cpu/arcv2/start.S
new file mode 100644
index 0000000..3ce6896
--- /dev/null
+++ b/arch/arc/cpu/arcv2/start.S
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/arcregs.h>
+
+/*
+ * Note on the LD/ST addressing modes with address register write-back
+ *
+ * LD.a same as LD.aw
+ *
+ * LD.a    reg1, [reg2, x]  => Pre Incr
+ *      Eff Addr for load = [reg2 + x]
+ *
+ * LD.ab   reg1, [reg2, x]  => Post Incr
+ *      Eff Addr for load = [reg2]
+ */
+
+.macro PUSH reg
+	st.a	\reg, [%sp, -4]
+.endm
+
+.macro PUSHAX aux
+	lr	%r9, [\aux]
+	PUSH	%r9
+.endm
+
+.macro  SAVE_R1_TO_R24
+	PUSH	%r1
+	PUSH	%r2
+	PUSH	%r3
+	PUSH	%r4
+	PUSH	%r5
+	PUSH	%r6
+	PUSH	%r7
+	PUSH	%r8
+	PUSH	%r9
+	PUSH	%r10
+	PUSH	%r11
+	PUSH	%r12
+	PUSH	%r13
+	PUSH	%r14
+	PUSH	%r15
+	PUSH	%r16
+	PUSH	%r17
+	PUSH	%r18
+	PUSH	%r19
+	PUSH	%r20
+	PUSH	%r21
+	PUSH	%r22
+	PUSH	%r23
+	PUSH	%r24
+.endm
+
+.macro SAVE_ALL_SYS
+	/* saving %r0 to reg->r0 in advance since weread %ecr into it */
+	st	%r0, [%sp, -8]
+	lr	%r0, [%ecr]	/* all stack addressing is manual so far */
+	st	%r0, [%sp]
+	st	%sp, [%sp, -4]
+	/* now move %sp to reg->r0 position so we can do "push" automatically */
+	sub	%sp, %sp, 8
+
+	SAVE_R1_TO_R24
+	PUSH	%r25
+	PUSH	%gp
+	PUSH	%fp
+	PUSH	%blink
+	PUSHAX	%eret
+	PUSHAX	%erstatus
+	PUSH	%lp_count
+	PUSHAX	%lp_end
+	PUSHAX	%lp_start
+	PUSHAX	%erbta
+.endm
+
+.macro SAVE_EXCEPTION_SOURCE
+#ifdef CONFIG_MMU
+	/* If MMU exists exception faulting address is loaded in EFA reg */
+	lr	%r0, [%efa]
+#else
+	/* Otherwise in ERET (exception return) reg */
+	lr	%r0, [%eret]
+#endif
+.endm
+
+.section .ivt, "a",@progbits
+.align 4
+	/* Critical system events */
+.word	_start			/* 0 - 0x000 */
+.word	memory_error		/* 1 - 0x008 */
+.word	instruction_error	/* 2 - 0x010 */
+
+	/* Exceptions */
+.word	EV_MachineCheck		/* 0x100, Fatal Machine check  (0x20) */
+.word	EV_TLBMissI		/* 0x108, Intruction TLB miss  (0x21) */
+.word	EV_TLBMissD		/* 0x110, Data TLB miss        (0x22) */
+.word	EV_TLBProtV		/* 0x118, Protection Violation (0x23)
+							or Misaligned Access  */
+.word	EV_PrivilegeV		/* 0x120, Privilege Violation  (0x24) */
+.word	EV_Trap			/* 0x128, Trap exception       (0x25) */
+.word	EV_Extension		/* 0x130, Extn Intruction Excp (0x26) */
+
+	/* Device interrupts */
+.rept	29
+	j	interrupt_handler	/* 3:31 - 0x018:0xF8 */
+.endr
+
+.text
+.globl _start
+_start:
+	/* Setup interrupt vector base that matches "__text_start" */
+	sr	__ivt_start, [ARC_AUX_INTR_VEC_BASE]
+
+	/* Setup stack pointer */
+	mov	%sp, CONFIG_SYS_INIT_SP_ADDR
+	mov	%fp, %sp
+
+	/* Clear bss */
+	mov	%r0, __bss_start
+	mov	%r1, __bss_end
+
+clear_bss:
+	st.ab	0, [%r0, 4]
+	brlt	%r0, %r1, clear_bss
+
+	/* Zero the one and only argument of "board_init_f" */
+	mov_s	%r0, 0
+	j	board_init_f
+
+memory_error:
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_memory_error
+
+instruction_error:
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_instruction_error
+
+interrupt_handler:
+	/* Todo - save and restore CPU context when interrupts will be in use */
+	bl	do_interrupt_handler
+	rtie
+
+EV_MachineCheck:
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_machine_check_fault
+
+EV_TLBMissI:
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_itlb_miss
+
+EV_TLBMissD:
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_dtlb_miss
+
+EV_TLBProtV:
+	SAVE_ALL_SYS
+	SAVE_EXCEPTION_SOURCE
+	mov	%r1, %sp
+	j	do_tlb_prot_violation
+
+EV_PrivilegeV:
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_privilege_violation
+
+EV_Trap:
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_trap
+
+EV_Extension:
+	SAVE_ALL_SYS
+	mov	%r0, %sp
+	j	do_extension
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r0 = start_addr_sp
+ * r1 = new__gd
+ * r2 = relocaddr
+ */
+.align 4
+.globl	relocate_code
+relocate_code:
+	/*
+	 * r0-r12 might be clobbered by C functions
+	 * so we use r13-r16 for storage here
+	 */
+	mov	%r13, %r0		/* save addr_sp */
+	mov	%r14, %r1		/* save addr of gd */
+	mov	%r15, %r2		/* save addr of destination */
+
+	mov	%r16, %r2		/* %r9 - relocation offset */
+	sub	%r16, %r16, __image_copy_start
+
+/* Set up the stack */
+stack_setup:
+	mov	%sp, %r13
+	mov	%fp, %sp
+
+/* Check if monitor is loaded right in place for relocation */
+	mov	%r0, __image_copy_start
+	cmp	%r0, %r15		/* skip relocation if code loaded */
+	bz	do_board_init_r		/* in target location already */
+
+/* Copy data (__image_copy_start - __image_copy_end) to new location */
+	mov	%r1, %r15
+	mov	%r2, __image_copy_end
+	sub	%r2, %r2, %r0		/* r3 <- amount of bytes to copy */
+	asr	%r2, %r2, 2		/* r3 <- amount of words to copy */
+	mov	%lp_count, %r2
+	lp	copy_end
+	ld.ab	%r2,[%r0,4]
+	st.ab	%r2,[%r1,4]
+copy_end:
+
+/* Fix relocations related issues */
+	bl	do_elf_reloc_fixups
+#ifndef CONFIG_SYS_ICACHE_OFF
+	bl	invalidate_icache_all
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+	bl	flush_dcache_all
+#endif
+
+/* Update position of intterupt vector table */
+	lr	%r0, [ARC_AUX_INTR_VEC_BASE]	/* Read current position */
+	add	%r0, %r0, %r16			/* Update address */
+	sr	%r0, [ARC_AUX_INTR_VEC_BASE]	/* Write new position */
+
+do_board_init_r:
+/* Prepare for exection of "board_init_r" in relocated monitor */
+	mov	%r2, board_init_r	/* old address of "board_init_r()" */
+	add	%r2, %r2, %r16		/* new address of "board_init_r()" */
+	mov	%r0, %r14		/* 1-st parameter: gd_t */
+	mov	%r1, %r15		/* 2-nd parameter: dest_addr */
+	j	[%r2]
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 8ace87f..6a36a81 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -7,6 +7,8 @@
 #ifndef _ASM_ARC_ARCREGS_H
 #define _ASM_ARC_ARCREGS_H
 
+#include <asm/cache.h>
+
 /*
  * ARC architecture has additional address space - auxiliary registers.
  * These registers are mostly used for configuration purposes.
@@ -21,7 +23,7 @@
 #define ARC_AUX_IC_IVIC		0x10
 #define ARC_AUX_IC_CTRL		0x11
 #define ARC_AUX_IC_IVIL		0x19
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 #define ARC_AUX_IC_PTAG		0x1E
 #endif
 #define ARC_BCR_IC_BUILD	0x77
@@ -40,7 +42,7 @@
 #define ARC_AUX_DC_IVDL		0x4A
 #define ARC_AUX_DC_FLSH		0x4B
 #define ARC_AUX_DC_FLDL		0x4C
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 #define ARC_AUX_DC_PTAG		0x5C
 #endif
 #define ARC_BCR_DC_BUILD	0x72
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index 16e7568..8a77cd9 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -9,15 +9,22 @@
 
 #include <config.h>
 
-/*
- * The current upper bound for ARC L1 data cache line sizes is 128 bytes.
- * We use that value for aligning DMA buffers unless the board config has
- * specified an alternate cache line size.
- */
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-#define ARCH_DMA_MINALIGN	CONFIG_SYS_CACHELINE_SIZE
+#ifdef CONFIG_ARC_CACHE_LINE_SHIFT
+#define CONFIG_SYS_CACHELINE_SIZE	(1 << CONFIG_ARC_CACHE_LINE_SHIFT)
+#define ARCH_DMA_MINALIGN		CONFIG_SYS_CACHELINE_SIZE
 #else
-#define ARCH_DMA_MINALIGN	128
+/* Satisfy users of ARCH_DMA_MINALIGN */
+#define ARCH_DMA_MINALIGN		128
+#endif
+
+#if defined(ARC_MMU_ABSENT)
+#define CONFIG_ARC_MMU_VER 0
+#elif defined(CONFIG_ARC_MMU_V2)
+#define CONFIG_ARC_MMU_VER 2
+#elif defined(CONFIG_ARC_MMU_V3)
+#define CONFIG_ARC_MMU_VER 3
+#elif defined(CONFIG_ARC_MMU_V4)
+#define CONFIG_ARC_MMU_VER 4
 #endif
 
 #endif /* __ASM_ARC_CACHE_H */
diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h
index e5be078..b4e9099 100644
--- a/arch/arc/include/asm/config.h
+++ b/arch/arc/include/asm/config.h
@@ -7,8 +7,10 @@
 #ifndef __ASM_ARC_CONFIG_H_
 #define __ASM_ARC_CONFIG_H_
 
+#define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_SYS_GENERIC_GLOBAL_DATA
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_LMB
 
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
index bae4419..b8028c9 100644
--- a/arch/arc/lib/Makefile
+++ b/arch/arc/lib/Makefile
@@ -20,3 +20,5 @@
 obj-y += timer.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
+
+lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o
diff --git a/arch/arc/lib/_millicodethunk.S b/arch/arc/lib/_millicodethunk.S
new file mode 100644
index 0000000..b332416
--- /dev/null
+++ b/arch/arc/lib/_millicodethunk.S
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+ /* ANSI concatenation macros.  */
+
+ #define CONCAT1(a, b) CONCAT2(a, b)
+ #define CONCAT2(a, b) a ## b
+
+ /* Use the right prefix for global labels.  */
+
+ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+#ifndef WORKING_ASSEMBLER
+#define abs_l abs
+#define asl_l asl
+#define mov_l mov
+#endif
+
+#define FUNC(X)         .type SYM(X),@function
+#define HIDDEN_FUNC(X)	FUNC(X)` .hidden X
+#define ENDFUNC0(X)     .Lfe_##X: .size X,.Lfe_##X-X
+#define ENDFUNC(X)      ENDFUNC0(X)
+
+	.section .text
+	.align 4
+	.global SYM(__st_r13_to_r15)
+	.global SYM(__st_r13_to_r16)
+	.global SYM(__st_r13_to_r17)
+	.global SYM(__st_r13_to_r18)
+	.global SYM(__st_r13_to_r19)
+	.global SYM(__st_r13_to_r20)
+	.global SYM(__st_r13_to_r21)
+	.global SYM(__st_r13_to_r22)
+	.global SYM(__st_r13_to_r23)
+	.global SYM(__st_r13_to_r24)
+	.global SYM(__st_r13_to_r25)
+	HIDDEN_FUNC(__st_r13_to_r15)
+	HIDDEN_FUNC(__st_r13_to_r16)
+	HIDDEN_FUNC(__st_r13_to_r17)
+	HIDDEN_FUNC(__st_r13_to_r18)
+	HIDDEN_FUNC(__st_r13_to_r19)
+	HIDDEN_FUNC(__st_r13_to_r20)
+	HIDDEN_FUNC(__st_r13_to_r21)
+	HIDDEN_FUNC(__st_r13_to_r22)
+	HIDDEN_FUNC(__st_r13_to_r23)
+	HIDDEN_FUNC(__st_r13_to_r24)
+	HIDDEN_FUNC(__st_r13_to_r25)
+	.align 4
+SYM(__st_r13_to_r25):
+	st r25, [sp,48]
+SYM(__st_r13_to_r24):
+	st r24, [sp,44]
+SYM(__st_r13_to_r23):
+	st r23, [sp,40]
+SYM(__st_r13_to_r22):
+	st r22, [sp,36]
+SYM(__st_r13_to_r21):
+	st r21, [sp,32]
+SYM(__st_r13_to_r20):
+	st r20, [sp,28]
+SYM(__st_r13_to_r19):
+	st r19, [sp,24]
+SYM(__st_r13_to_r18):
+	st r18, [sp,20]
+SYM(__st_r13_to_r17):
+	st r17, [sp,16]
+SYM(__st_r13_to_r16):
+	st r16, [sp,12]
+SYM(__st_r13_to_r15):
+#ifdef __ARC700__
+	st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+	st_s r15, [sp,8]
+#endif
+	st_s r14, [sp,4]
+	j_s.d [%blink]
+	st_s r13, [sp,0]
+	ENDFUNC(__st_r13_to_r15)
+	ENDFUNC(__st_r13_to_r16)
+	ENDFUNC(__st_r13_to_r17)
+	ENDFUNC(__st_r13_to_r18)
+	ENDFUNC(__st_r13_to_r19)
+	ENDFUNC(__st_r13_to_r20)
+	ENDFUNC(__st_r13_to_r21)
+	ENDFUNC(__st_r13_to_r22)
+	ENDFUNC(__st_r13_to_r23)
+	ENDFUNC(__st_r13_to_r24)
+	ENDFUNC(__st_r13_to_r25)
+
+	.section .text
+	.align 4
+;	==================================
+;	the loads
+
+	.global SYM(__ld_r13_to_r15)
+	.global SYM(__ld_r13_to_r16)
+	.global SYM(__ld_r13_to_r17)
+	.global SYM(__ld_r13_to_r18)
+	.global SYM(__ld_r13_to_r19)
+	.global SYM(__ld_r13_to_r20)
+	.global SYM(__ld_r13_to_r21)
+	.global SYM(__ld_r13_to_r22)
+	.global SYM(__ld_r13_to_r23)
+	.global SYM(__ld_r13_to_r24)
+	.global SYM(__ld_r13_to_r25)
+	HIDDEN_FUNC(__ld_r13_to_r15)
+	HIDDEN_FUNC(__ld_r13_to_r16)
+	HIDDEN_FUNC(__ld_r13_to_r17)
+	HIDDEN_FUNC(__ld_r13_to_r18)
+	HIDDEN_FUNC(__ld_r13_to_r19)
+	HIDDEN_FUNC(__ld_r13_to_r20)
+	HIDDEN_FUNC(__ld_r13_to_r21)
+	HIDDEN_FUNC(__ld_r13_to_r22)
+	HIDDEN_FUNC(__ld_r13_to_r23)
+	HIDDEN_FUNC(__ld_r13_to_r24)
+	HIDDEN_FUNC(__ld_r13_to_r25)
+SYM(__ld_r13_to_r25):
+	ld r25, [sp,48]
+SYM(__ld_r13_to_r24):
+	ld r24, [sp,44]
+SYM(__ld_r13_to_r23):
+	ld r23, [sp,40]
+SYM(__ld_r13_to_r22):
+	ld r22, [sp,36]
+SYM(__ld_r13_to_r21):
+	ld r21, [sp,32]
+SYM(__ld_r13_to_r20):
+	ld r20, [sp,28]
+SYM(__ld_r13_to_r19):
+	ld r19, [sp,24]
+SYM(__ld_r13_to_r18):
+	ld r18, [sp,20]
+SYM(__ld_r13_to_r17):
+	ld r17, [sp,16]
+SYM(__ld_r13_to_r16):
+	ld r16, [sp,12]
+SYM(__ld_r13_to_r15):
+#ifdef __ARC700__
+	ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+	ld_s r15, [sp,8]
+#endif
+	ld_s r14, [sp,4]
+	j_s.d [%blink]
+	ld_s r13, [sp,0]
+	ENDFUNC(__ld_r13_to_r15)
+	ENDFUNC(__ld_r13_to_r16)
+	ENDFUNC(__ld_r13_to_r17)
+	ENDFUNC(__ld_r13_to_r18)
+	ENDFUNC(__ld_r13_to_r19)
+	ENDFUNC(__ld_r13_to_r20)
+	ENDFUNC(__ld_r13_to_r21)
+	ENDFUNC(__ld_r13_to_r22)
+	ENDFUNC(__ld_r13_to_r23)
+	ENDFUNC(__ld_r13_to_r24)
+	ENDFUNC(__ld_r13_to_r25)
+
+	.global SYM(__ld_r13_to_r14_ret)
+	.global SYM(__ld_r13_to_r15_ret)
+	.global SYM(__ld_r13_to_r16_ret)
+	.global SYM(__ld_r13_to_r17_ret)
+	.global SYM(__ld_r13_to_r18_ret)
+	.global SYM(__ld_r13_to_r19_ret)
+	.global SYM(__ld_r13_to_r20_ret)
+	.global SYM(__ld_r13_to_r21_ret)
+	.global SYM(__ld_r13_to_r22_ret)
+	.global SYM(__ld_r13_to_r23_ret)
+	.global SYM(__ld_r13_to_r24_ret)
+	.global SYM(__ld_r13_to_r25_ret)
+	HIDDEN_FUNC(__ld_r13_to_r14_ret)
+	HIDDEN_FUNC(__ld_r13_to_r15_ret)
+	HIDDEN_FUNC(__ld_r13_to_r16_ret)
+	HIDDEN_FUNC(__ld_r13_to_r17_ret)
+	HIDDEN_FUNC(__ld_r13_to_r18_ret)
+	HIDDEN_FUNC(__ld_r13_to_r19_ret)
+	HIDDEN_FUNC(__ld_r13_to_r20_ret)
+	HIDDEN_FUNC(__ld_r13_to_r21_ret)
+	HIDDEN_FUNC(__ld_r13_to_r22_ret)
+	HIDDEN_FUNC(__ld_r13_to_r23_ret)
+	HIDDEN_FUNC(__ld_r13_to_r24_ret)
+	HIDDEN_FUNC(__ld_r13_to_r25_ret)
+	.section .text
+	.align 4
+SYM(__ld_r13_to_r25_ret):
+	ld r25, [sp,48]
+SYM(__ld_r13_to_r24_ret):
+	ld r24, [sp,44]
+SYM(__ld_r13_to_r23_ret):
+	ld r23, [sp,40]
+SYM(__ld_r13_to_r22_ret):
+	ld r22, [sp,36]
+SYM(__ld_r13_to_r21_ret):
+	ld r21, [sp,32]
+SYM(__ld_r13_to_r20_ret):
+	ld r20, [sp,28]
+SYM(__ld_r13_to_r19_ret):
+	ld r19, [sp,24]
+SYM(__ld_r13_to_r18_ret):
+	ld r18, [sp,20]
+SYM(__ld_r13_to_r17_ret):
+	ld r17, [sp,16]
+SYM(__ld_r13_to_r16_ret):
+	ld r16, [sp,12]
+SYM(__ld_r13_to_r15_ret):
+	ld r15, [sp,8]
+SYM(__ld_r13_to_r14_ret):
+	ld blink,[sp,r12]
+	ld_s r14, [sp,4]
+	ld.ab r13, [sp,r12]
+	j_s.d [%blink]
+	add_s sp,sp,4
+	ENDFUNC(__ld_r13_to_r14_ret)
+	ENDFUNC(__ld_r13_to_r15_ret)
+	ENDFUNC(__ld_r13_to_r16_ret)
+	ENDFUNC(__ld_r13_to_r17_ret)
+	ENDFUNC(__ld_r13_to_r18_ret)
+	ENDFUNC(__ld_r13_to_r19_ret)
+	ENDFUNC(__ld_r13_to_r20_ret)
+	ENDFUNC(__ld_r13_to_r21_ret)
+	ENDFUNC(__ld_r13_to_r22_ret)
+	ENDFUNC(__ld_r13_to_r23_ret)
+	ENDFUNC(__ld_r13_to_r24_ret)
+	ENDFUNC(__ld_r13_to_r25_ret)
diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c
index fa19a13..a227723 100644
--- a/arch/arc/lib/cache.c
+++ b/arch/arc/lib/cache.c
@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <asm/arcregs.h>
+#include <asm/cache.h>
 
 /* Bit values in IC_CTRL */
 #define IC_CTRL_CACHE_DISABLE	(1 << 0)
@@ -101,7 +102,7 @@
 #ifndef CONFIG_SYS_DCACHE_OFF
 static void dcache_flush_line(unsigned addr)
 {
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 	write_aux_reg(ARC_AUX_DC_PTAG, addr);
 #endif
 	write_aux_reg(ARC_AUX_DC_FLDL, addr);
@@ -115,7 +116,7 @@
 	 * Invalidate I$ for addresses range just flushed from D$.
 	 * If we try to execute data flushed above it will be valid/correct
 	 */
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 	write_aux_reg(ARC_AUX_IC_PTAG, addr);
 #endif
 	write_aux_reg(ARC_AUX_IC_IVIL, addr);
@@ -145,7 +146,7 @@
 	end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 
 	for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 		write_aux_reg(ARC_AUX_DC_PTAG, addr);
 #endif
 		write_aux_reg(ARC_AUX_DC_IVDL, addr);
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c
new file mode 100644
index 0000000..d5ad327
--- /dev/null
+++ b/arch/arc/lib/libgcc2.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "libgcc2.h"
+
+DWtype
+__ashldi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (UWtype)uu.s.low << -bm;
+	} else {
+		const UWtype carries = (UWtype) uu.s.low >> bm;
+
+		w.s.low = (UWtype)uu.s.low << b;
+		w.s.high = ((UWtype)uu.s.high << b) | carries;
+	}
+
+	return w.ll;
+}
+
+DWtype
+__ashrdi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		const UWtype carries = (UWtype) uu.s.high << bm;
+
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((UWtype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+DWtype
+__lshrdi3(DWtype u, shift_count_type b)
+{
+	if (b == 0)
+		return u;
+
+	const DWunion uu = {.ll = u};
+	const shift_count_type bm = W_TYPE_SIZE - b;
+	DWunion w;
+
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (UWtype)uu.s.high >> -bm;
+	} else {
+		const UWtype carries = (UWtype)uu.s.high << bm;
+
+		w.s.high = (UWtype)uu.s.high >> b;
+		w.s.low = ((UWtype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+	unsigned long bit = 1;
+	unsigned long res = 0;
+
+	while (den < num && bit && !(den & (1L<<31))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+
+	if (modwanted)
+		return num;
+
+	return res;
+}
+
+long
+__divsi3(long a, long b)
+{
+	int neg = 0;
+	long res;
+
+	if (a < 0) {
+		a = -a;
+		neg = !neg;
+	}
+
+	if (b < 0) {
+		b = -b;
+		neg = !neg;
+	}
+
+	res = udivmodsi4(a, b, 0);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+long
+__modsi3(long a, long b)
+{
+	int neg = 0;
+	long res;
+
+	if (a < 0) {
+		a = -a;
+		neg = 1;
+	}
+
+	if (b < 0)
+		b = -b;
+
+	res = udivmodsi4(a, b, 1);
+
+	if (neg)
+		res = -res;
+
+	return res;
+}
+
+long
+__udivsi3(long a, long b)
+{
+	return udivmodsi4(a, b, 0);
+}
+
+long
+__umodsi3(long a, long b)
+{
+	return udivmodsi4(a, b, 1);
+}
diff --git a/arch/arc/lib/libgcc2.h b/arch/arc/lib/libgcc2.h
new file mode 100644
index 0000000..8813c3b
--- /dev/null
+++ b/arch/arc/lib/libgcc2.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#define UNITS_PER_WORD 4	/* for ARC */
+#define BITS_PER_UNIT 8		/* for ARC */
+
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+
+/* Work out the largest "word" size that we can deal with on this target.  */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+       || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+   The value can be set on the command line.  */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+typedef		 int QItype	__attribute__ ((mode (QI)));
+typedef unsigned int UQItype	__attribute__ ((mode (QI)));
+typedef		 int HItype	__attribute__ ((mode (HI)));
+typedef unsigned int UHItype	__attribute__ ((mode (HI)));
+#if MIN_UNITS_PER_WORD > 1
+/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1.  */
+typedef 	 int SItype	__attribute__ ((mode (SI)));
+typedef unsigned int USItype	__attribute__ ((mode (SI)));
+#if __SIZEOF_LONG_LONG__ > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2.  */
+typedef		 int DItype	__attribute__ ((mode (DI)));
+typedef unsigned int UDItype	__attribute__ ((mode (DI)));
+#if MIN_UNITS_PER_WORD > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4.  */
+typedef		 int TItype	__attribute__ ((mode (TI)));
+typedef unsigned int UTItype	__attribute__ ((mode (TI)));
+#endif
+#endif
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD == 8
+#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
+#define Wtype	DItype
+#define UWtype	UDItype
+#define HWtype	DItype
+#define UHWtype	UDItype
+#define DWtype	TItype
+#define UDWtype	UTItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## di ## b
+#define __NDW(a,b)	__gnu_ ## a ## ti ## b
+#else
+#define __NW(a,b)	__ ## a ## di ## b
+#define __NDW(a,b)	__ ## a ## ti ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 4
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define Wtype	SItype
+#define UWtype	USItype
+#define HWtype	SItype
+#define UHWtype	USItype
+#define DWtype	DItype
+#define UDWtype	UDItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## si ## b
+#define __NDW(a,b)	__gnu_ ## a ## di ## b
+#else
+#define __NW(a,b)	__ ## a ## si ## b
+#define __NDW(a,b)	__ ## a ## di ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 2
+#define W_TYPE_SIZE (2 * BITS_PER_UNIT)
+#define Wtype	HItype
+#define UWtype	UHItype
+#define HWtype	HItype
+#define UHWtype	UHItype
+#define DWtype	SItype
+#define UDWtype	USItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## hi ## b
+#define __NDW(a,b)	__gnu_ ## a ## si ## b
+#else
+#define __NW(a,b)	__ ## a ## hi ## b
+#define __NDW(a,b)	__ ## a ## si ## b
+#endif
+#else
+#define W_TYPE_SIZE BITS_PER_UNIT
+#define Wtype	QItype
+#define UWtype  UQItype
+#define HWtype	QItype
+#define UHWtype	UQItype
+#define DWtype	HItype
+#define UDWtype	UHItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)	__gnu_ ## a ## qi ## b
+#define __NDW(a,b)	__gnu_ ## a ## hi ## b
+#else
+#define __NW(a,b)	__ ## a ## qi ## b
+#define __NDW(a,b)	__ ## a ## hi ## b
+#endif
+#endif
+
+typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+	struct DWstruct {Wtype high, low;};
+#else
+	struct DWstruct {Wtype low, high;};
+#endif
+
+/* We need this union to unpack/pack DImode values, since we don't have
+   any arithmetic yet.  Incoming DImode parameters are stored into the
+   `ll' field, and the unpacked result is read from the struct `s'.  */
+
+typedef union {
+	struct DWstruct s;
+	DWtype ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S
index fa5aac5..87bccab 100644
--- a/arch/arc/lib/memcmp.S
+++ b/arch/arc/lib/memcmp.S
@@ -29,6 +29,7 @@
 	ld.a	%r4, [%r0, 8]
 	ld.a	%r5, [%r1, 8]
 	brne	WORD2, %r12, .Lodd
+	nop
 .Loop_end:
 	asl_s	SHIFT, SHIFT, 3
 	bhs_s	.Last_cmp
@@ -105,6 +106,7 @@
 	ldb.a	%r4, [%r0, 2]
 	ldb.a	%r5, [%r1, 2]
 	brne	%r3, %r12, .Lbyte_odd
+	nop
 .Lbyte_end:
 	bcc	.Lbyte_even
 	brne	%r4, %r5, .Lbyte_even
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5eb1d03..820ba1c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -51,6 +51,13 @@
         default "sa1100" if CPU_SA1100
 	default "armv8" if ARM64
 
+config SEMIHOSTING
+	bool "support boot from semihosting"
+	help
+	  In emulated environments, semihosting is a way for
+	  the hosted environment to call out to the emulator to
+	  retrieve files from the host machine.
+
 choice
 	prompt "Target select"
 
@@ -70,17 +77,8 @@
 	bool "Support a320evb"
 	select CPU_ARM920T
 
-config TARGET_AT91RM9200EK
-	bool "Support at91rm9200ek"
-	select CPU_ARM920T
-
-config TARGET_EB_CPUX9K2
-	bool "Support eb_cpux9k2"
-	select CPU_ARM920T
-
-config TARGET_CPUAT91
-	bool "Support cpuat91"
-	select CPU_ARM920T
+config ARCH_AT91
+	bool "Atmel AT91"
 
 config TARGET_EDB93XX
 	bool "Support edb93xx"
@@ -122,100 +120,6 @@
 	bool "Support gplugd"
 	select CPU_ARM926EJS
 
-config TARGET_AFEB9260
-	bool "Support afeb9260"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9260EK
-	bool "Support at91sam9260ek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9261EK
-	bool "Support at91sam9261ek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9263EK
-	bool "Support at91sam9263ek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9M10G45EK
-	bool "Support at91sam9m10g45ek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9N12EK
-	bool "Support at91sam9n12ek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9RLEK
-	bool "Support at91sam9rlek"
-	select CPU_ARM926EJS
-
-config TARGET_AT91SAM9X5EK
-	bool "Support at91sam9x5ek"
-	select CPU_ARM926EJS
-
-config TARGET_SNAPPER9260
-	bool "Support snapper9260"
-	select CPU_ARM926EJS
-
-config TARGET_VL_MA2SC
-	bool "Support vl_ma2sc"
-	select CPU_ARM926EJS
-
-config TARGET_SBC35_A9G20
-	bool "Support sbc35_a9g20"
-	select CPU_ARM926EJS
-
-config TARGET_TNY_A9260
-	bool "Support tny_a9260"
-	select CPU_ARM926EJS
-
-config TARGET_USB_A9263
-	bool "Support usb_a9263"
-	select CPU_ARM926EJS
-
-config TARGET_ETHERNUT5
-	bool "Support ethernut5"
-	select CPU_ARM926EJS
-
-config TARGET_MEESC
-	bool "Support meesc"
-	select CPU_ARM926EJS
-
-config TARGET_OTC570
-	bool "Support otc570"
-	select CPU_ARM926EJS
-
-config TARGET_CPU9260
-	bool "Support cpu9260"
-	select CPU_ARM926EJS
-
-config TARGET_PM9261
-	bool "Support pm9261"
-	select CPU_ARM926EJS
-
-config TARGET_PM9263
-	bool "Support pm9263"
-	select CPU_ARM926EJS
-
-config TARGET_PM9G45
-	bool "Support pm9g45"
-	select CPU_ARM926EJS
-
-config TARGET_CORVUS
-	select SUPPORT_SPL
-	bool "Support corvus"
-	select CPU_ARM926EJS
-
-config TARGET_TAURUS
-	select SUPPORT_SPL
-	bool "Support taurus"
-	select CPU_ARM926EJS
-
-config TARGET_STAMP9G20
-	bool "Support stamp9g20"
-	select CPU_ARM926EJS
-
 config ARCH_DAVINCI
 	bool "TI DaVinci"
 	select CPU_ARM926EJS
@@ -229,10 +133,12 @@
 config TARGET_DB_MV784MP_GP
 	bool "Support db-mv784mp-gp"
 	select CPU_V7
+	select SUPPORT_SPL
 
 config TARGET_MAXBCM
 	bool "Support maxbcm"
 	select CPU_V7
+	select SUPPORT_SPL
 
 config TARGET_DEVKIT3250
 	bool "Support devkit3250"
@@ -404,6 +310,10 @@
 	bool "Support rpi"
 	select CPU_ARM1176
 
+config TARGET_RPI_2
+	bool "Support rpi_2"
+	select CPU_V7
+
 config TARGET_TNETV107X_EVM
 	bool "Support tnetv107x_evm"
 	select CPU_ARM1176
@@ -505,24 +415,6 @@
 	select CPU_V7
 	select SUPPORT_SPL
 
-config TARGET_SAMA5D3_XPLAINED
-	bool "Support sama5d3_xplained"
-	select CPU_V7
-	select SUPPORT_SPL
-
-config TARGET_SAMA5D3XEK
-	bool "Support sama5d3xek"
-	select CPU_V7
-	select SUPPORT_SPL
-
-config TARGET_SAMA5D4_XPLAINED
-	bool "Support sama5d4_xplained"
-	select CPU_V7
-
-config TARGET_SAMA5D4EK
-	bool "Support sama5d4ek"
-	select CPU_V7
-
 config TARGET_BCM28155_AP
 	bool "Support bcm28155_ap"
 	select CPU_V7
@@ -637,6 +529,7 @@
 config TARGET_MX6SXSABRESD
 	bool "Support mx6sxsabresd"
 	select CPU_V7
+	select SUPPORT_SPL
 
 config TARGET_GW_VENTANA
 	bool "Support gw_ventana"
@@ -663,6 +556,17 @@
 config TARGET_OT1200
 	bool "Bachmann OT1200"
 	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_PLATINUM_PICON
+	bool "Support platinum-picon"
+	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_PLATINUM_TITANIUM
+	bool "Support platinum-titanium"
+	select CPU_V7
+	select SUPPORT_SPL
 
 config OMAP34XX
 	bool "OMAP34XX SoC"
@@ -720,10 +624,19 @@
 	select CPU_ARM720T if SPL_BUILD
 	select CPU_V7 if !SPL_BUILD
 
-config TARGET_VEXPRESS_AEMV8A
+config TARGET_VEXPRESS64_AEMV8A
 	bool "Support vexpress_aemv8a"
 	select ARM64
 
+config TARGET_VEXPRESS64_BASE_FVP
+	bool "Support Versatile Express ARMv8a FVP BASE model"
+	select ARM64
+	select SEMIHOSTING
+
+config TARGET_VEXPRESS64_JUNO
+	bool "Support Versatile Express Juno Development Platform"
+	select ARM64
+
 config TARGET_LS2085A_EMU
 	bool "Support ls2085a_emu"
 	select ARM64
@@ -805,17 +718,21 @@
 
 endchoice
 
-source "arch/arm/cpu/arm926ejs/davinci/Kconfig"
+source "arch/arm/mach-at91/Kconfig"
+
+source "arch/arm/mach-davinci/Kconfig"
+
+source "arch/arm/cpu/arm1176/bcm2835/Kconfig"
 
 source "arch/arm/cpu/armv7/exynos/Kconfig"
 
-source "arch/arm/cpu/armv7/highbank/Kconfig"
+source "arch/arm/mach-highbank/Kconfig"
 
-source "arch/arm/cpu/armv7/keystone/Kconfig"
+source "arch/arm/mach-keystone/Kconfig"
 
-source "arch/arm/cpu/arm926ejs/kirkwood/Kconfig"
+source "arch/arm/mach-kirkwood/Kconfig"
 
-source "arch/arm/cpu/arm926ejs/nomadik/Kconfig"
+source "arch/arm/mach-nomadik/Kconfig"
 
 source "arch/arm/cpu/armv7/omap3/Kconfig"
 
@@ -823,17 +740,17 @@
 
 source "arch/arm/cpu/armv7/omap5/Kconfig"
 
-source "arch/arm/cpu/arm926ejs/orion5x/Kconfig"
+source "arch/arm/mach-orion5x/Kconfig"
 
 source "arch/arm/cpu/armv7/rmobile/Kconfig"
 
 source "arch/arm/cpu/armv7/s5pc1xx/Kconfig"
 
-source "arch/arm/cpu/armv7/tegra-common/Kconfig"
+source "arch/arm/mach-tegra/Kconfig"
 
 source "arch/arm/cpu/armv7/uniphier/Kconfig"
 
-source "arch/arm/cpu/arm926ejs/versatile/Kconfig"
+source "arch/arm/mach-versatile/Kconfig"
 
 source "arch/arm/cpu/armv7/zynq/Kconfig"
 
@@ -842,43 +759,25 @@
 source "board/aristainetos/Kconfig"
 source "board/BuR/kwb/Kconfig"
 source "board/BuR/tseries/Kconfig"
-source "board/BuS/eb_cpux9k2/Kconfig"
-source "board/BuS/vl_ma2sc/Kconfig"
 source "board/CarMediaLab/flea3/Kconfig"
 source "board/Marvell/aspenite/Kconfig"
 source "board/Marvell/db-mv784mp-gp/Kconfig"
 source "board/Marvell/dkb/Kconfig"
 source "board/Marvell/gplugd/Kconfig"
-source "board/afeb9260/Kconfig"
 source "board/altera/socfpga/Kconfig"
 source "board/armadeus/apf27/Kconfig"
 source "board/armltd/integrator/Kconfig"
 source "board/armltd/vexpress/Kconfig"
 source "board/armltd/vexpress64/Kconfig"
-source "board/atmel/at91rm9200ek/Kconfig"
-source "board/atmel/at91sam9260ek/Kconfig"
-source "board/atmel/at91sam9261ek/Kconfig"
-source "board/atmel/at91sam9263ek/Kconfig"
-source "board/atmel/at91sam9m10g45ek/Kconfig"
-source "board/atmel/at91sam9n12ek/Kconfig"
-source "board/atmel/at91sam9rlek/Kconfig"
-source "board/atmel/at91sam9x5ek/Kconfig"
-source "board/atmel/sama5d3_xplained/Kconfig"
-source "board/atmel/sama5d3xek/Kconfig"
-source "board/atmel/sama5d4_xplained/Kconfig"
-source "board/atmel/sama5d4ek/Kconfig"
 source "board/bachmann/ot1200/Kconfig"
 source "board/balloon3/Kconfig"
+source "board/barco/platinum/Kconfig"
 source "board/barco/titanium/Kconfig"
 source "board/bluegiga/apx4devkit/Kconfig"
-source "board/bluewater/snapper9260/Kconfig"
 source "board/boundary/nitrogen6x/Kconfig"
 source "board/broadcom/bcm28155_ap/Kconfig"
 source "board/broadcom/bcmcygnus/Kconfig"
 source "board/broadcom/bcmnsp/Kconfig"
-source "board/calao/sbc35_a9g20/Kconfig"
-source "board/calao/tny_a9260/Kconfig"
-source "board/calao/usb_a9263/Kconfig"
 source "board/cirrus/edb93xx/Kconfig"
 source "board/cm4008/Kconfig"
 source "board/cm41xx/Kconfig"
@@ -889,13 +788,8 @@
 source "board/davedenx/qong/Kconfig"
 source "board/denx/m28evk/Kconfig"
 source "board/denx/m53evk/Kconfig"
-source "board/egnite/ethernut5/Kconfig"
 source "board/embest/mx6boards/Kconfig"
-source "board/esd/meesc/Kconfig"
-source "board/esd/otc570/Kconfig"
 source "board/esg/ima3-mx53/Kconfig"
-source "board/eukrea/cpu9260/Kconfig"
-source "board/eukrea/cpuat91/Kconfig"
 source "board/faraday/a320evb/Kconfig"
 source "board/freescale/ls2085a/Kconfig"
 source "board/freescale/ls1021aqds/Kconfig"
@@ -940,18 +834,14 @@
 source "board/ppcag/bg0900/Kconfig"
 source "board/pxa255_idp/Kconfig"
 source "board/raspberrypi/rpi/Kconfig"
-source "board/ronetix/pm9261/Kconfig"
-source "board/ronetix/pm9263/Kconfig"
-source "board/ronetix/pm9g45/Kconfig"
+source "board/raspberrypi/rpi_2/Kconfig"
 source "board/samsung/smdk2410/Kconfig"
 source "board/sandisk/sansa_fuze_plus/Kconfig"
 source "board/scb9328/Kconfig"
 source "board/schulercontrol/sc_sps_1/Kconfig"
-source "board/siemens/corvus/Kconfig"
 source "board/siemens/draco/Kconfig"
 source "board/siemens/pxm2/Kconfig"
 source "board/siemens/rut/Kconfig"
-source "board/siemens/taurus/Kconfig"
 source "board/silica/pengwyn/Kconfig"
 source "board/solidrun/hummingboard/Kconfig"
 source "board/spear/spear300/Kconfig"
@@ -965,7 +855,6 @@
 source "board/sunxi/Kconfig"
 source "board/syteco/jadecpu/Kconfig"
 source "board/syteco/zmx25/Kconfig"
-source "board/taskit/stamp9g20/Kconfig"
 source "board/tbs/tbs2910/Kconfig"
 source "board/ti/am335x/Kconfig"
 source "board/ti/am43xx/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ebb7dc3..878ae26 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -2,6 +2,27 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+# Machine directory name.  This list is sorted alphanumerically
+# by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_AT91)		+= at91
+machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
+machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
+machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
+# TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
+machine-$(CONFIG_KIRKWOOD)		+= kirkwood
+# TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
+machine-$(CONFIG_ARCH_NOMADIK)		+= nomadik
+# TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
+machine-$(CONFIG_ORION5X)		+= orion5x
+machine-$(CONFIG_TEGRA)			+= tegra
+machine-$(CONFIG_ARCH_VERSATILE)	+= versatile
+
+machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
+
+PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+
+libs-y += $(machdirs)
+
 head-y := arch/arm/cpu/$(CPU)/start.o
 
 ifeq ($(CONFIG_SPL_BUILD),y)
@@ -27,3 +48,6 @@
 ifneq (,$(filter $(SOC), armada-xp kirkwood))
 libs-y += arch/arm/mvebu-common/
 endif
+
+# deprecated
+-include $(machdirs)/config.mk
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index 35d8d38..6bea3d3 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -1,6 +1 @@
-obj-$(CONFIG_AT91FAMILY) += at91-common/
-obj-$(CONFIG_TEGRA20) += tegra20-common/
-obj-$(CONFIG_TEGRA30) += tegra30-common/
-obj-$(CONFIG_TEGRA114) += tegra114-common/
-obj-$(CONFIG_TEGRA124) += tegra124-common/
-obj-$(CONFIG_TEGRA) += tegra-common/
+obj- += dummy.o
diff --git a/arch/arm/cpu/arm1176/bcm2835/Kconfig b/arch/arm/cpu/arm1176/bcm2835/Kconfig
new file mode 100644
index 0000000..162f973
--- /dev/null
+++ b/arch/arm/cpu/arm1176/bcm2835/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_RPI || TARGET_RPI_2
+
+config DM
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+endif
diff --git a/arch/arm/cpu/arm1176/bcm2835/Makefile b/arch/arm/cpu/arm1176/bcm2835/Makefile
index 0ad3690..7e5dbe1 100644
--- a/arch/arm/cpu/arm1176/bcm2835/Makefile
+++ b/arch/arm/cpu/arm1176/bcm2835/Makefile
@@ -1,15 +1,7 @@
 #
-# See file CREDITS for list of people who contributed to this
-# project.
+# (C) Copyright 2012 Stephen Warren
 #
-# 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.
+# SPDX-License-Identifier:	GPL-2.0
 #
 
 obj-y	:= lowlevel_init.o
diff --git a/arch/arm/cpu/arm720t/Makefile b/arch/arm/cpu/arm720t/Makefile
index 9f61ea2..243a123 100644
--- a/arch/arm/cpu/arm720t/Makefile
+++ b/arch/arm/cpu/arm720t/Makefile
@@ -7,9 +7,3 @@
 
 extra-y	= start.o
 obj-y	= interrupts.o cpu.o
-
-obj-$(CONFIG_TEGRA) += tegra-common/
-obj-$(CONFIG_TEGRA20) += tegra20/
-obj-$(CONFIG_TEGRA30) += tegra30/
-obj-$(CONFIG_TEGRA114) += tegra114/
-obj-$(CONFIG_TEGRA124) += tegra124/
diff --git a/arch/arm/cpu/arm720t/tegra-common/Makefile b/arch/arm/cpu/arm720t/tegra-common/Makefile
deleted file mode 100644
index a9c2b67..0000000
--- a/arch/arm/cpu/arm720t/tegra-common/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# (C) Copyright 2010,2011 Nvidia Corporation.
-#
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-$(CONFIG_SPL_BUILD) += spl.o
-obj-y	+= cpu.o
diff --git a/arch/arm/cpu/arm720t/tegra114/Makefile b/arch/arm/cpu/arm720t/tegra114/Makefile
deleted file mode 100644
index ea3e55e..0000000
--- a/arch/arm/cpu/arm720t/tegra114/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
-#
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
-#
-
-#obj-y	+= cpu.o t11x.o
-obj-y	+= cpu.o
diff --git a/arch/arm/cpu/arm720t/tegra124/Makefile b/arch/arm/cpu/arm720t/tegra124/Makefile
deleted file mode 100644
index 61abf45..0000000
--- a/arch/arm/cpu/arm720t/tegra124/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# (C) Copyright 2013-2014
-# NVIDIA Corporation <www.nvidia.com>
-#
-# SPDX-License-Identifier:     GPL-2.0+
-#
-
-obj-y	+= cpu.o
diff --git a/arch/arm/cpu/arm720t/tegra20/Makefile b/arch/arm/cpu/arm720t/tegra20/Makefile
deleted file mode 100644
index 12243fa..0000000
--- a/arch/arm/cpu/arm720t/tegra20/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# (C) Copyright 2010,2011 Nvidia Corporation.
-#
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	+= cpu.o
diff --git a/arch/arm/cpu/arm720t/tegra30/Makefile b/arch/arm/cpu/arm720t/tegra30/Makefile
deleted file mode 100644
index 6ff4c55..0000000
--- a/arch/arm/cpu/arm720t/tegra30/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
-#
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
-#
-
-obj-y	+= cpu.o
diff --git a/arch/arm/cpu/arm920t/Makefile b/arch/arm/cpu/arm920t/Makefile
index a72e5de..a16838b 100644
--- a/arch/arm/cpu/arm920t/Makefile
+++ b/arch/arm/cpu/arm920t/Makefile
@@ -11,7 +11,6 @@
 obj-$(CONFIG_USE_IRQ)	+= interrupts.o
 
 obj-$(if $(filter a320,$(SOC)),y) += a320/
-obj-$(CONFIG_AT91FAMILY) += at91/
 obj-$(CONFIG_EP93XX) += ep93xx/
 obj-$(CONFIG_IMX) += imx/
 obj-$(CONFIG_KS8695) += ks8695/
diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
index adcea9f..f5944cc 100644
--- a/arch/arm/cpu/arm926ejs/Makefile
+++ b/arch/arm/cpu/arm926ejs/Makefile
@@ -15,16 +15,10 @@
 endif
 
 obj-$(CONFIG_ARMADA100) += armada100/
-obj-$(CONFIG_AT91FAMILY) += at91/
-obj-$(CONFIG_ARCH_DAVINCI) += davinci/
-obj-$(CONFIG_KIRKWOOD) += kirkwood/
 obj-$(if $(filter lpc32xx,$(SOC)),y) += lpc32xx/
 obj-$(CONFIG_MB86R0x) += mb86r0x/
 obj-$(CONFIG_MX25) += mx25/
 obj-$(CONFIG_MX27) += mx27/
 obj-$(if $(filter mxs,$(SOC)),y) += mxs/
-obj-$(CONFIG_ARCH_NOMADIK) += nomadik/
-obj-$(CONFIG_ORION5X) += orion5x/
 obj-$(CONFIG_PANTHEON) += pantheon/
 obj-$(if $(filter spear,$(SOC)),y) += spear/
-obj-$(CONFIG_ARCH_VERSATILE) += versatile/
diff --git a/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c b/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c
deleted file mode 100644
index 16eeca7..0000000
--- a/arch/arm/cpu/arm926ejs/at91/at91cap9_devices.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * (C) Copyright 2007-2008
- * Stelian Pop <stelian@popies.net>
- * Lead Tech Design <www.leadtechdesign.com>
- *
- * (C) Copyright 2009
- * Daniel Gorsulowski <daniel.gorsulowski@esd.eu>
- * esd electronic system design gmbh <www.esd.eu>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/at91_common.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/io.h>
-
-void at91_serial0_hw_init(void)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTA, 22, 1);		/* TXD0 */
-	at91_set_a_periph(AT91_PIO_PORTA, 23, 0);		/* RXD0 */
-	writel(1 << AT91CAP9_ID_US0, &pmc->pcer);
-}
-
-void at91_serial1_hw_init(void)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTD, 0, 1);		/* TXD1 */
-	at91_set_a_periph(AT91_PIO_PORTD, 1, 0);		/* RXD1 */
-	writel(1 << AT91CAP9_ID_US1, &pmc->pcer);
-}
-
-void at91_serial2_hw_init(void)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTD, 2, 1);		/* TXD2 */
-	at91_set_a_periph(AT91_PIO_PORTD, 3, 0);		/* RXD2 */
-	writel(1 << AT91CAP9_ID_US2, &pmc->pcer);
-}
-
-void at91_serial3_hw_init(void)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);		/* DRXD */
-	at91_set_a_periph(AT91_PIO_PORTC, 31, 1);		/* DTXD */
-	writel(1 << AT91_ID_SYS, &pmc->pcer);
-}
-
-void at91_serial_hw_init(void)
-{
-#ifdef CONFIG_USART0
-	at91_serial0_hw_init();
-#endif
-
-#ifdef CONFIG_USART1
-	at91_serial1_hw_init();
-#endif
-
-#ifdef CONFIG_USART2
-	at91_serial2_hw_init();
-#endif
-
-#ifdef CONFIG_USART3	/* DBGU */
-	at91_serial3_hw_init();
-#endif
-}
-
-#ifdef CONFIG_HAS_DATAFLASH
-void at91_spi0_hw_init(unsigned long cs_mask)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_b_periph(AT91_PIO_PORTA, 0, 0);	/* SPI0_MISO */
-	at91_set_b_periph(AT91_PIO_PORTA, 1, 0);	/* SPI0_MOSI */
-	at91_set_b_periph(AT91_PIO_PORTA, 2, 0);	/* SPI0_SPCK */
-
-	/* Enable clock */
-	writel(1 << AT91CAP9_ID_SPI0, &pmc->pcer);
-
-	if (cs_mask & (1 << 0)) {
-		at91_set_b_periph(AT91_PIO_PORTA, 5, 1);
-	}
-	if (cs_mask & (1 << 1)) {
-		at91_set_b_periph(AT91_PIO_PORTA, 3, 1);
-	}
-	if (cs_mask & (1 << 2)) {
-		at91_set_b_periph(AT91_PIO_PORTD, 0, 1);
-	}
-	if (cs_mask & (1 << 3)) {
-		at91_set_b_periph(AT91_PIO_PORTD, 1, 1);
-	}
-	if (cs_mask & (1 << 4)) {
-		at91_set_pio_output(AT91_PIO_PORTA, 5, 1);
-	}
-	if (cs_mask & (1 << 5)) {
-		at91_set_pio_output(AT91_PIO_PORTA, 3, 1);
-	}
-	if (cs_mask & (1 << 6)) {
-		at91_set_pio_output(AT91_PIO_PORTD, 0, 1);
-	}
-	if (cs_mask & (1 << 7)) {
-		at91_set_pio_output(AT91_PIO_PORTD, 1, 1);
-	}
-}
-
-void at91_spi1_hw_init(unsigned long cs_mask)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTB, 12, 0);	/* SPI1_MISO */
-	at91_set_a_periph(AT91_PIO_PORTB, 13, 0);	/* SPI1_MOSI */
-	at91_set_a_periph(AT91_PIO_PORTB, 14, 0);	/* SPI1_SPCK */
-
-	/* Enable clock */
-	writel(1 << AT91CAP9_ID_SPI1, &pmc->pcer);
-
-	if (cs_mask & (1 << 0)) {
-		at91_set_a_periph(AT91_PIO_PORTB, 15, 1);
-	}
-	if (cs_mask & (1 << 1)) {
-		at91_set_a_periph(AT91_PIO_PORTB, 16, 1);
-	}
-	if (cs_mask & (1 << 2)) {
-		at91_set_a_periph(AT91_PIO_PORTB, 17, 1);
-	}
-	if (cs_mask & (1 << 3)) {
-		at91_set_a_periph(AT91_PIO_PORTB, 18, 1);
-	}
-	if (cs_mask & (1 << 4)) {
-		at91_set_pio_output(AT91_PIO_PORTB, 15, 1);
-	}
-	if (cs_mask & (1 << 5)) {
-		at91_set_pio_output(AT91_PIO_PORTB, 16, 1);
-	}
-	if (cs_mask & (1 << 6)) {
-		at91_set_pio_output(AT91_PIO_PORTB, 17, 1);
-	}
-	if (cs_mask & (1 << 7)) {
-		at91_set_pio_output(AT91_PIO_PORTB, 18, 1);
-	}
-
-}
-#endif
-
-#ifdef CONFIG_MACB
-void at91_macb_hw_init(void)
-{
-	at91_set_a_periph(AT91_PIO_PORTB, 21, 0);	/* ETXCK_EREFCK */
-	at91_set_a_periph(AT91_PIO_PORTB, 22, 0);	/* ERXDV */
-	at91_set_a_periph(AT91_PIO_PORTB, 25, 0);	/* ERX0 */
-	at91_set_a_periph(AT91_PIO_PORTB, 26, 0);	/* ERX1 */
-	at91_set_a_periph(AT91_PIO_PORTB, 27, 0);	/* ERXER */
-	at91_set_a_periph(AT91_PIO_PORTB, 28, 0);	/* ETXEN */
-	at91_set_a_periph(AT91_PIO_PORTB, 23, 0);	/* ETX0 */
-	at91_set_a_periph(AT91_PIO_PORTB, 24, 0);	/* ETX1 */
-	at91_set_a_periph(AT91_PIO_PORTB, 30, 0);	/* EMDIO */
-	at91_set_a_periph(AT91_PIO_PORTB, 29, 0);	/* EMDC */
-
-#ifndef CONFIG_RMII
-	at91_set_b_periph(AT91_PIO_PORTC, 25, 0);	/* ECRS */
-	at91_set_b_periph(AT91_PIO_PORTC, 26, 0);	/* ECOL */
-	at91_set_b_periph(AT91_PIO_PORTC, 22, 0);	/* ERX2 */
-	at91_set_b_periph(AT91_PIO_PORTC, 23, 0);	/* ERX3 */
-	at91_set_b_periph(AT91_PIO_PORTC, 27, 0);	/* ERXCK */
-	at91_set_b_periph(AT91_PIO_PORTC, 20, 0);	/* ETX2 */
-	at91_set_b_periph(AT91_PIO_PORTC, 21, 0);	/* ETX3 */
-	at91_set_b_periph(AT91_PIO_PORTC, 24, 0);	/* ETXER */
-#endif
-}
-#endif
-
-#ifdef CONFIG_AT91_CAN
-void at91_can_hw_init(void)
-{
-	at91_pmc_t	*pmc	= (at91_pmc_t *) AT91_PMC_BASE;
-
-	at91_set_a_periph(AT91_PIO_PORTA, 12, 0);	/* CAN_TX */
-	at91_set_a_periph(AT91_PIO_PORTA, 13, 1);	/* CAN_RX */
-
-	/* Enable clock */
-	writel(1 << AT91CAP9_ID_CAN, &pmc->pcer);
-}
-#endif
diff --git a/arch/arm/cpu/arm926ejs/at91/config.mk b/arch/arm/cpu/arm926ejs/at91/config.mk
deleted file mode 100644
index 370630d..0000000
--- a/arch/arm/cpu/arm926ejs/at91/config.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-PF_CPPFLAGS_TUNE := $(call cc-option,-mtune=arm926ejs,)
-PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_TUNE)
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
index d29b9aa..d7956e5 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -147,6 +147,7 @@
 	mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
 
 	mxs_spl_console_init();
+	debug("SPL: Serial Console Initialised\n");
 
 	mxs_power_init();
 
@@ -156,6 +157,11 @@
 	data->boot_mode_idx = bootmode;
 
 	mxs_power_wait_pswitch();
+
+	if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) {
+		debug("SPL: Waiting for JTAG user\n");
+		asm volatile ("x: b x");
+	}
 }
 
 /* Support aparatus */
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
index cdfcddd..96bd32f 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
@@ -18,6 +18,8 @@
 {
 	struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+	debug("SPL: Initialisating LRADC\n");
+
 	writel(LRADC_CTRL0_SFTRST, &regs->hw_lradc_ctrl0_clr);
 	writel(LRADC_CTRL0_CLKGATE, &regs->hw_lradc_ctrl0_clr);
 	writel(LRADC_CTRL0_ONCHIP_GROUNDREF, &regs->hw_lradc_ctrl0_clr);
@@ -37,9 +39,15 @@
 {
 	struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+	debug("SPL: Enabling LRADC battery measurement\n");
+
 	/* Check if the channel is present at all. */
-	if (!(readl(&regs->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT))
+	if (!(readl(&regs->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) {
+		debug("SPL: LRADC channel 7 is not present - aborting\n");
 		return;
+	}
+
+	debug("SPL: LRADC channel 7 is present - configuring\n");
 
 	writel(LRADC_CTRL1_LRADC7_IRQ_EN, &regs->hw_lradc_ctrl1_clr);
 	writel(LRADC_CTRL1_LRADC7_IRQ, &regs->hw_lradc_ctrl1_clr);
@@ -65,6 +73,7 @@
 		100, &regs->hw_lradc_delay3);
 
 	writel(0xffffffff, &regs->hw_lradc_ch7_clr);
-
 	writel(LRADC_DELAY_KICK, &regs->hw_lradc_delay3_set);
+
+	debug("SPL: LRADC channel 7 configuration complete\n");
 }
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
index 97ef67d..a744e5d 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
@@ -92,6 +92,7 @@
 
 __weak void mxs_adjust_memory_params(uint32_t *dram_vals)
 {
+	debug("SPL: Using default SDRAM parameters\n");
 }
 
 #ifdef CONFIG_MX28
@@ -99,8 +100,10 @@
 {
 	int i;
 
+	debug("SPL: Setting mx28 board specific SDRAM parameters\n");
 	mxs_adjust_memory_params(dram_vals);
 
+	debug("SPL: Applying SDRAM parameters\n");
 	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
 		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
 }
@@ -109,6 +112,7 @@
 {
 	int i;
 
+	debug("SPL: Setting mx23 board specific SDRAM parameters\n");
 	mxs_adjust_memory_params(dram_vals);
 
 	/*
@@ -120,6 +124,7 @@
 	 * HW_DRAM_CTL8 is setup as the last element.
 	 * So skip the initialization of these HW_DRAM_CTL registers.
 	 */
+	debug("SPL: Applying SDRAM parameters\n");
 	for (i = 0; i < ARRAY_SIZE(dram_vals); i++) {
 		if (i == 8 || i == 27 || i == 28 || i == 35)
 			continue;
@@ -146,6 +151,8 @@
 	const unsigned char divider = 21;
 #endif
 
+	debug("SPL: Initialising FRAC0\n");
+
 	/* Gate EMI clock */
 	writeb(CLKCTRL_FRAC_CLKGATE,
 		&clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
@@ -170,6 +177,7 @@
 		&clkctrl_regs->hw_clkctrl_clkseq_clr);
 
 	early_delay(10000);
+	debug("SPL: FRAC0 Initialised\n");
 }
 
 static void mxs_mem_setup_cpu_and_hbus(void)
@@ -177,6 +185,8 @@
 	struct mxs_clkctrl_regs *clkctrl_regs =
 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+	debug("SPL: Setting CPU and HBUS clock frequencies\n");
+
 	/* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
 	 * and ungate CPU clock */
 	writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
@@ -209,6 +219,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Configuring VDDA\n");
+
 	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
 		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
 		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
@@ -240,6 +252,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Setting mx23 VDDMEM\n");
+
 	/* We must wait before and after disabling the current limiter! */
 	early_delay(10000);
 
@@ -252,6 +266,8 @@
 
 static void mx23_mem_init(void)
 {
+	debug("SPL: Initialising mx23 SDRAM Controller\n");
+
 	/*
 	 * Reset/ungate the EMI block. This is essential, otherwise the system
 	 * suffers from memory instability. This thing is mx23 specific and is
@@ -297,6 +313,8 @@
 	struct mxs_pinctrl_regs *pinctrl_regs =
 		(struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
 
+	debug("SPL: Initialising mx28 SDRAM Controller\n");
+
 	/* Set DDR2 mode */
 	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
 		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
index 1c54ab7..c342217 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
@@ -14,6 +14,13 @@
 
 #include "mxs_init.h"
 
+#ifdef CONFIG_SYS_MXS_VDD5V_ONLY
+#define DCDC4P2_DROPOUT_CONFIG	POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+				POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2
+#else
+#define DCDC4P2_DROPOUT_CONFIG	POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+				POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL
+#endif
 /**
  * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
  *
@@ -26,6 +33,8 @@
 	struct mxs_clkctrl_regs *clkctrl_regs =
 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+	debug("SPL: Switching CPU clock to 24MHz XTAL\n");
+
 	/* Set XTAL as CPU reference clock */
 	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
 		&clkctrl_regs->hw_clkctrl_clkseq_set);
@@ -43,9 +52,23 @@
 	struct mxs_clkctrl_regs *clkctrl_regs =
 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+	debug("SPL: Switching CPU core clock source to PLL\n");
+
+	/*
+	 * TODO: Are we really? It looks like we turn on PLL0, but we then
+	 * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already
+	 * set by mxs_power_clock2xtal()). Clearing this bit here seems to
+	 * introduce some instability (causing the CPU core to hang). Maybe
+	 * we aren't giving PLL0 enough time to stabilise?
+	 */
 	setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
 			CLKCTRL_PLL0CTRL0_POWER);
 	early_delay(100);
+
+	/*
+	 * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a
+	 * wait on the PLL0 LOCK bit?
+	 */
 	setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
 			CLKCTRL_CLKSEQ_BYPASS_CPU);
 }
@@ -62,6 +85,8 @@
 	struct mxs_rtc_regs *rtc_regs =
 		(struct mxs_rtc_regs *)MXS_RTC_BASE;
 
+	debug("SPL: Setting auto-restart bit\n");
+
 	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
 	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
 		;
@@ -101,14 +126,17 @@
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
 	/* Set linear regulator 25mV below switching converter */
+	debug("SPL: Setting VDDD 25mV below DC-DC converters\n");
 	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
 			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
 			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
 
+	debug("SPL: Setting VDDA 25mV below DC-DC converters\n");
 	clrsetbits_le32(&power_regs->hw_power_vddactrl,
 			POWER_VDDACTRL_LINREG_OFFSET_MASK,
 			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
 
+	debug("SPL: Setting VDDIO 25mV below DC-DC converters\n");
 	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
 			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
 			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
@@ -127,6 +155,8 @@
 	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
 	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
 	volt *= 8;
+
+	debug("SPL: Battery Voltage = %dmV\n", volt);
 	return volt;
 }
 
@@ -154,8 +184,10 @@
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 	uint32_t volt = mxs_get_batt_volt();
 
-	if ((volt >= 2400) && (volt <= 4300))
+	if ((volt >= 2400) && (volt <= 4300)) {
+		debug("SPL: Battery is good\n");
 		return 1;
+	}
 
 	clrsetbits_le32(&power_regs->hw_power_5vctrl,
 		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
@@ -175,16 +207,21 @@
 
 	volt = mxs_get_batt_volt();
 
-	if (volt >= 3500)
+	if (volt >= 3500) {
+		debug("SPL: Battery Voltage too high\n");
 		return 0;
+	}
 
-	if (volt >= 2400)
+	if (volt >= 2400) {
+		debug("SPL: Battery is good\n");
 		return 1;
+	}
 
 	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
 		&power_regs->hw_power_charge_clr);
 	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
 
+	debug("SPL: Battery Voltage too low\n");
 	return 0;
 }
 
@@ -203,6 +240,7 @@
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
 	/* Start 5V detection */
+	debug("SPL: Starting 5V input detection comparator\n");
 	clrsetbits_le32(&power_regs->hw_power_5vctrl,
 			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
 			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
@@ -220,6 +258,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Pre-Configuring power block\n");
+
 	/* Improve efficieny and reduce transient ripple */
 	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
 		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
@@ -257,6 +297,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Configuring common 4P2 regulator params\n");
+
 	/* Setup 4P2 parameters */
 	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
 		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
@@ -268,8 +310,7 @@
 
 	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
 		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
-		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
-		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+		DCDC4P2_DROPOUT_CONFIG);
 
 	clrsetbits_le32(&power_regs->hw_power_5vctrl,
 		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
@@ -289,6 +330,8 @@
 	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
 	uint32_t prev_5v_brnout, prev_5v_droop;
 
+	debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling");
+
 	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
 				POWER_5VCTRL_PWDN_5VBRNOUT;
 	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
@@ -390,6 +433,8 @@
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 	uint32_t tmp, tmp2;
 
+	debug("SPL: Enabling 4P2 regulator\n");
+
 	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
 
 	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
@@ -407,6 +452,7 @@
 	 * gradually to avoid large inrush current from the 5V cable which can
 	 * cause transients/problems
 	 */
+	debug("SPL: Charging 4P2 capacitor\n");
 	mxs_enable_4p2_dcdc_input(0);
 
 	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
@@ -420,6 +466,8 @@
 			POWER_DCDC4P2_ENABLE_DCDC);
 		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
 			&power_regs->hw_power_5vctrl_set);
+
+		debug("SPL: Unable to recover from mx23 errata 5837\n");
 		hang();
 	}
 
@@ -433,6 +481,7 @@
 	 * current limit until the brownout status is false or until we've
 	 * reached our maximum defined 4p2 current limit.
 	 */
+	debug("SPL: Setting 4P2 brownout level\n");
 	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
 			POWER_DCDC4P2_BO_MASK,
 			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
@@ -479,8 +528,11 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Switching DC-DC converters to 4P2\n");
+
 	if (!(readl(&power_regs->hw_power_dcdc4p2) &
 		POWER_DCDC4P2_ENABLE_DCDC)) {
+		debug("SPL: Already switched - aborting\n");
 		hang();
 	}
 
@@ -509,6 +561,8 @@
 	uint32_t vdddctrl, vddactrl, vddioctrl;
 	uint32_t tmp;
 
+	debug("SPL: Powering up 4P2 regulator\n");
+
 	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
 	vddactrl = readl(&power_regs->hw_power_vddactrl);
 	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
@@ -559,6 +613,8 @@
 	if (tmp)
 		writel(POWER_CHARGE_ENABLE_LOAD,
 			&power_regs->hw_power_charge_clr);
+
+	debug("SPL: 4P2 regulator powered-up\n");
 }
 
 /**
@@ -574,6 +630,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Booting from 5V supply\n");
+
 	/*
 	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
 	 * disconnect event. FIXME
@@ -601,6 +659,9 @@
 {
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
+
+	debug("Powering Down\n");
+
 	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
 	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
 		&power_regs->hw_power_reset);
@@ -617,6 +678,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Configuring power block to boot from battery\n");
+
 	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
 	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
 
@@ -672,6 +735,8 @@
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 	uint32_t tmp;
 
+	debug("SPL: Resolving 5V conflict\n");
+
 	setbits_le32(&power_regs->hw_power_vddioctrl,
 			POWER_VDDIOCTRL_BO_OFFSET_MASK);
 
@@ -683,19 +748,27 @@
 			 * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
 			 * unreliable
 			 */
+			debug("SPL: VDDIO has a brownout\n");
 			mxs_powerdown();
 			break;
 		}
 
 		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n");
 			mxs_boot_valid_5v();
 			break;
 		} else {
+			debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n");
 			mxs_powerdown();
 			break;
 		}
 
+		/*
+		 * TODO: I can't see this being reached. We'll either
+		 * powerdown or boot from a stable 5V supply.
+		 */
 		if (tmp & POWER_STS_PSWITCH_MASK) {
+			debug("SPL: POWER_STS_PSWITCH_MASK is set\n");
 			mxs_batt_boot();
 			break;
 		}
@@ -713,21 +786,26 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Configuring power block to boot from 5V input\n");
+
 	/*
 	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
 	 * but their implementation always returns 1 so we omit it here.
 	 */
 	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		debug("SPL: 5V VDD good\n");
 		mxs_boot_valid_5v();
 		return;
 	}
 
 	early_delay(1000);
 	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		debug("SPL: 5V VDD good (after delay)\n");
 		mxs_boot_valid_5v();
 		return;
 	}
 
+	debug("SPL: 5V VDD not good\n");
 	mxs_handle_5v_conflict();
 }
 
@@ -742,6 +820,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Initialising battery brown-out level to 3.0V\n");
+
 	/* Brownout at 3V */
 	clrsetbits_le32(&power_regs->hw_power_battmonitor,
 		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
@@ -762,6 +842,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Switching VDDD to DC-DC converters\n");
+
 	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
 		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
 		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
@@ -788,6 +870,8 @@
 	struct mxs_lradc_regs *lradc_regs =
 		(struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+	debug("SPL: Configuring power source\n");
+
 	mxs_src_power_init();
 
 	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
@@ -811,6 +895,10 @@
 		mxs_batt_boot();
 	}
 
+	/*
+	 * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced
+	 * from USB VBUS
+	 */
 	mxs_power_clock2pll();
 
 	mxs_init_batt_bo();
@@ -819,6 +907,7 @@
 
 #ifdef CONFIG_MX23
 	/* Fire up the VDDMEM LinReg now that we're all set. */
+	debug("SPL: Enabling mx23 VDDMEM linear regulator\n");
 	writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
 		&power_regs->hw_power_vddmemctrl);
 #endif
@@ -838,6 +927,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Enabling output rail protection\n");
+
 	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
 		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
 
@@ -1077,6 +1168,8 @@
  */
 static void mxs_setup_batt_detect(void)
 {
+	debug("SPL: Starting battery voltage measurement logic\n");
+
 	mxs_lradc_init();
 	mxs_lradc_enable_batt_measurement();
 	early_delay(10);
@@ -1111,6 +1204,8 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Initialising Power Block\n");
+
 	mxs_ungate_power();
 
 	mxs_power_clock2xtal();
@@ -1123,9 +1218,13 @@
 	mxs_power_configure_power_source();
 	mxs_enable_output_rail_protection();
 
+	debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n");
 	mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
+
+	debug("SPL: Setting VDDD to 1V5 (brownout @ 1v0)\n");
 	mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
 #ifdef CONFIG_MX23
+	debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n");
 	mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
 #endif
 	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
@@ -1150,6 +1249,7 @@
 	struct mxs_power_regs *power_regs =
 		(struct mxs_power_regs *)MXS_POWER_BASE;
 
+	debug("SPL: Waiting for power switch input\n");
 	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
 		;
 }
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 409e6f5..b228ed6 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -32,7 +32,6 @@
 obj-$(CONFIG_KONA) += kona-common/
 obj-$(CONFIG_OMAP_COMMON) += omap-common/
 obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o
-obj-$(CONFIG_TEGRA) += tegra-common/
 
 ifneq (,$(filter s5pc1xx exynos,$(SOC)))
 obj-y += s5p-common/
@@ -40,13 +39,11 @@
 
 obj-$(if $(filter am33xx,$(SOC)),y) += am33xx/
 obj-$(if $(filter armada-xp,$(SOC)),y) += armada-xp/
-obj-$(CONFIG_AT91FAMILY) += at91/
+obj-$(CONFIG_BCM2835) += bcm2835/
 obj-$(if $(filter bcm281xx,$(SOC)),y) += bcm281xx/
 obj-$(if $(filter bcmcygnus,$(SOC)),y) += bcmcygnus/
 obj-$(if $(filter bcmnsp,$(SOC)),y) += bcmnsp/
 obj-$(CONFIG_ARCH_EXYNOS) += exynos/
-obj-$(CONFIG_ARCH_HIGHBANK) += highbank/
-obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
 obj-$(if $(filter ls102xa,$(SOC)),y) += ls102xa/
 obj-$(if $(filter mx5,$(SOC)),y) += mx5/
 obj-$(CONFIG_MX6) += mx6/
@@ -58,7 +55,6 @@
 obj-$(CONFIG_SOCFPGA) += socfpga/
 obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
 obj-$(CONFIG_ARCH_SUNXI) += sunxi/
-obj-$(CONFIG_TEGRA20) += tegra20/
 obj-$(CONFIG_U8500) += u8500/
 obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
 obj-$(CONFIG_VF610) += vf610/
diff --git a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
index 31188c8..529a119 100644
--- a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
+++ b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
@@ -118,4 +118,7 @@
 
 	/* Select the Master osc clk as Timer2 clock source */
 	writel(0x1, &cmdpll->clktimer2clk);
+
+	/* For OPP100 the mac clock should be /5. */
+	writel(0x4, &cmdpll->clkselmacclk);
 }
diff --git a/arch/arm/cpu/armv7/armada-xp/Makefile b/arch/arm/cpu/armv7/armada-xp/Makefile
index 885dcee..737159b 100644
--- a/arch/arm/cpu/armv7/armada-xp/Makefile
+++ b/arch/arm/cpu/armv7/armada-xp/Makefile
@@ -5,3 +5,5 @@
 #
 
 obj-y	= cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
diff --git a/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S b/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S
new file mode 100644
index 0000000..1febd7b
--- /dev/null
+++ b/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <version.h>
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	bx	lr
+ENDPROC(save_boot_params)
+
+/*
+ * cache_inv - invalidate Cache line
+ * r0 - dest
+ */
+	.global cache_inv
+	.type  cache_inv, %function
+	cache_inv:
+
+	stmfd   sp!, {r1-r12}
+
+	mcr     p15, 0, r0, c7, c6, 1
+
+	ldmfd   sp!, {r1-r12}
+	bx      lr
+
+
+/*
+ * flush_l1_v6 - l1 cache clean invalidate
+ * r0 - dest
+ */
+	.global flush_l1_v6
+	.type	flush_l1_v6, %function
+	flush_l1_v6:
+
+	stmfd   sp!, {r1-r12}
+
+	mcr     p15, 0, r0, c7, c10, 5	/* @ data memory barrier */
+	mcr     p15, 0, r0, c7, c14, 1	/* @ clean & invalidate D line */
+	mcr     p15, 0, r0, c7, c10, 4	/* @ data sync barrier */
+
+	ldmfd   sp!, {r1-r12}
+	bx      lr
+
+
+/*
+ * flush_l1_v7 - l1 cache clean invalidate
+ * r0 - dest
+ */
+	.global flush_l1_v7
+	.type	flush_l1_v7, %function
+	flush_l1_v7:
+
+	stmfd   sp!, {r1-r12}
+
+	dmb				/* @data memory barrier */
+	mcr     p15, 0, r0, c7, c14, 1	/* @ clean & invalidate D line */
+	dsb				/* @data sync barrier */
+
+	ldmfd   sp!, {r1-r12}
+	bx      lr
diff --git a/arch/arm/cpu/armv7/armada-xp/spl.c b/arch/arm/cpu/armv7/armada-xp/spl.c
new file mode 100644
index 0000000..402e520
--- /dev/null
+++ b/arch/arm/cpu/armv7/armada-xp/spl.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+	/* Right now only booting via SPI NOR flash is supported */
+	return BOOT_DEVICE_SPI;
+}
+
+void board_init_f(ulong dummy)
+{
+	/* Set global data pointer */
+	gd = &gdata;
+
+	/* Linux expects the internal registers to be at 0xf1000000 */
+	arch_cpu_init();
+
+	preloader_console_init();
+
+	/* First init the serdes PHY's */
+	serdes_phy_config();
+
+	/* Setup DDR */
+	ddr3_init();
+
+	board_init_r(NULL, 0);
+}
diff --git a/arch/arm/cpu/armv7/at91/config.mk b/arch/arm/cpu/armv7/at91/config.mk
deleted file mode 100644
index db60308..0000000
--- a/arch/arm/cpu/armv7/at91/config.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Copyright (C) 2014, Andreas Bießmann <andreas.devel@googlemail.com>
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-ifndef CONFIG_SPL_BUILD
-ALL-y	+= u-boot.img
-endif
diff --git a/arch/arm/cpu/armv7/at91/sama5d4_devices.c b/arch/arm/cpu/armv7/at91/sama5d4_devices.c
deleted file mode 100644
index 7469825..0000000
--- a/arch/arm/cpu/armv7/at91/sama5d4_devices.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2014 Atmel
- *		      Bo Shen <voice.shen@atmel.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/at91_common.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/clk.h>
-#include <asm/arch/sama5d4.h>
-
-char *get_cpu_name()
-{
-	unsigned int extension_id = get_extension_chip_id();
-
-	if (cpu_is_sama5d4())
-		switch (extension_id) {
-		case ARCH_EXID_SAMA5D41:
-			return "SAMA5D41";
-		case ARCH_EXID_SAMA5D42:
-			return "SAMA5D42";
-		case ARCH_EXID_SAMA5D43:
-			return "SAMA5D43";
-		case ARCH_EXID_SAMA5D44:
-			return "SAMA5D44";
-		default:
-			return "Unknown CPU type";
-		}
-	else
-		return "Unknown CPU type";
-}
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-void at91_udp_hw_init(void)
-{
-	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-
-	/* Enable UPLL clock */
-	writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
-	/* Enable UDPHS clock */
-	at91_periph_clk_enable(ATMEL_ID_UDPHS);
-}
-#endif
diff --git a/arch/arm/cpu/armv7/bcm2835/Makefile b/arch/arm/cpu/armv7/bcm2835/Makefile
new file mode 100644
index 0000000..ed1ee47
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm2835/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2012 Stephen Warren
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+src_dir := ../../arm1176/bcm2835/
+
+obj-y	:=
+obj-y	+= $(src_dir)/init.o
+obj-y	+= $(src_dir)/reset.o
+obj-y	+= $(src_dir)/timer.o
+obj-y	+= $(src_dir)/mbox.o
diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
index 01cdb7e..c56417d 100644
--- a/arch/arm/cpu/armv7/cpu.c
+++ b/arch/arm/cpu/armv7/cpu.c
@@ -53,7 +53,7 @@
 	 * After D-cache is flushed and before it is disabled there may
 	 * be some new valid entries brought into the cache. We are sure
 	 * that these lines are not dirty and will not affect our execution.
-	 * (because unwinding the call-stack and setting a bit in CP15 SCTRL
+	 * (because unwinding the call-stack and setting a bit in CP15 SCTLR
 	 * is all we did during this. We have not pushed anything on to the
 	 * stack. Neither have we affected any static data)
 	 * So just invalidate the entire d-cache again to avoid coherency
diff --git a/arch/arm/cpu/armv7/exynos/Kconfig b/arch/arm/cpu/armv7/exynos/Kconfig
index 7fcb5d2..2064efa 100644
--- a/arch/arm/cpu/armv7/exynos/Kconfig
+++ b/arch/arm/cpu/armv7/exynos/Kconfig
@@ -65,6 +65,27 @@
 config SYS_SOC
 	default "exynos"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
+config DM_SPI
+	default y if !SPL_BUILD
+
+config DM_SPI_FLASH
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config SYS_MALLOC_F
+	default y if !SPL_BUILD
+
+config SYS_MALLOC_F_LEN
+	default 0x400 if !SPL_BUILD
+
 source "board/samsung/smdkv310/Kconfig"
 source "board/samsung/trats/Kconfig"
 source "board/samsung/universal_c210/Kconfig"
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index b31c13b..c6455c2 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -20,42 +20,84 @@
  * positions of the peripheral clocks of the src and div registers
  */
 struct clk_bit_info {
+	enum periph_id id;
+	int32_t src_mask;
+	int32_t div_mask;
+	int32_t prediv_mask;
 	int8_t src_bit;
 	int8_t div_bit;
 	int8_t prediv_bit;
 };
 
-/* src_bit div_bit prediv_bit */
-static struct clk_bit_info clk_bit_info[] = {
-	{0,	0,	-1},
-	{4,	4,	-1},
-	{8,	8,	-1},
-	{12,	12,	-1},
-	{0,	0,	8},
-	{4,	16,	24},
-	{8,	0,	8},
-	{12,	16,	24},
-	{-1,	-1,	-1},
-	{16,	0,	8},
-	{20,	16,	24},
-	{24,	0,	8},
-	{0,	0,	4},
-	{4,	12,	16},
-	{-1,	-1,	-1},
-	{-1,	-1,	-1},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{-1,	24,	0},
-	{24,	0,	-1},
-	{24,	0,	-1},
-	{24,	0,	-1},
-	{24,	0,	-1},
-	{24,	0,	-1},
+static struct clk_bit_info exynos5_bit_info[] = {
+	/* periph id		s_mask	d_mask	p_mask	s_bit	d_bit	p_bit */
+	{PERIPH_ID_UART0,	0xf,	0xf,	-1,	0,	0,	-1},
+	{PERIPH_ID_UART1,	0xf,	0xf,	-1,	4,	4,	-1},
+	{PERIPH_ID_UART2,	0xf,	0xf,	-1,	8,	8,	-1},
+	{PERIPH_ID_UART3,	0xf,	0xf,	-1,	12,	12,	-1},
+	{PERIPH_ID_I2C0,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C1,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C2,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C3,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C4,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C5,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C6,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_I2C7,	-1,	0x7,	0x7,	-1,	24,	0},
+	{PERIPH_ID_SPI0,	0xf,	0xf,	0xff,	16,	0,	8},
+	{PERIPH_ID_SPI1,	0xf,	0xf,	0xff,	20,	16,	24},
+	{PERIPH_ID_SPI2,	0xf,	0xf,	0xff,	24,	0,	8},
+	{PERIPH_ID_SDMMC0,	0xf,	0xf,	0xff,	0,	0,	8},
+	{PERIPH_ID_SDMMC1,	0xf,	0xf,	0xff,	4,	16,	24},
+	{PERIPH_ID_SDMMC2,	0xf,	0xf,	0xff,	8,	0,	8},
+	{PERIPH_ID_SDMMC3,	0xf,	0xf,	0xff,	12,	16,	24},
+	{PERIPH_ID_I2S0,	0xf,	0xf,	0xff,	0,	0,	4},
+	{PERIPH_ID_I2S1,	0xf,	0xf,	0xff,	4,	12,	16},
+	{PERIPH_ID_SPI3,	0xf,	0xf,	0xff,	0,	0,	4},
+	{PERIPH_ID_SPI4,	0xf,	0xf,	0xff,	4,	12,	16},
+	{PERIPH_ID_SDMMC4,	0xf,	0xf,	0xff,	16,	0,	8},
+	{PERIPH_ID_PWM0,	0xf,	0xf,	-1,	24,	0,	-1},
+	{PERIPH_ID_PWM1,	0xf,	0xf,	-1,	24,	0,	-1},
+	{PERIPH_ID_PWM2,	0xf,	0xf,	-1,	24,	0,	-1},
+	{PERIPH_ID_PWM3,	0xf,	0xf,	-1,	24,	0,	-1},
+	{PERIPH_ID_PWM4,	0xf,	0xf,	-1,	24,	0,	-1},
+
+	{PERIPH_ID_NONE,	-1,	-1,	-1,	-1,	-1,	-1},
+};
+
+static struct clk_bit_info exynos542x_bit_info[] = {
+	/* periph id		s_mask	d_mask	p_mask	s_bit	d_bit	p_bit */
+	{PERIPH_ID_UART0,	0xf,	0xf,	-1,	4,	8,	-1},
+	{PERIPH_ID_UART1,	0xf,	0xf,	-1,	8,	12,	-1},
+	{PERIPH_ID_UART2,	0xf,	0xf,	-1,	12,	16,	-1},
+	{PERIPH_ID_UART3,	0xf,	0xf,	-1,	16,	20,	-1},
+	{PERIPH_ID_I2C0,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C1,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C2,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C3,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C4,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C5,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C6,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C7,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_SPI0,	0xf,	0xf,	0xff,	20,	20,	8},
+	{PERIPH_ID_SPI1,	0xf,	0xf,	0xff,	24,	24,	16},
+	{PERIPH_ID_SPI2,	0xf,	0xf,	0xff,	28,	28,	24},
+	{PERIPH_ID_SDMMC0,	0x7,	0x3ff,	-1,	8,	0,	-1},
+	{PERIPH_ID_SDMMC1,	0x7,	0x3ff,	-1,	12,	10,	-1},
+	{PERIPH_ID_SDMMC2,	0x7,	0x3ff,	-1,	16,	20,	-1},
+	{PERIPH_ID_I2C8,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2C9,	-1,	0x3f,	-1,	-1,	8,	-1},
+	{PERIPH_ID_I2S0,	0xf,	0xf,	0xff,	0,	0,	4},
+	{PERIPH_ID_I2S1,	0xf,	0xf,	0xff,	4,	12,	16},
+	{PERIPH_ID_SPI3,	0xf,	0xf,	0xff,	12,	16,	0},
+	{PERIPH_ID_SPI4,	0xf,	0xf,	0xff,	16,	20,	8},
+	{PERIPH_ID_PWM0,	0xf,	0xf,	-1,	24,	28,	-1},
+	{PERIPH_ID_PWM1,	0xf,	0xf,	-1,	24,	28,	-1},
+	{PERIPH_ID_PWM2,	0xf,	0xf,	-1,	24,	28,	-1},
+	{PERIPH_ID_PWM3,	0xf,	0xf,	-1,	24,	28,	-1},
+	{PERIPH_ID_PWM4,	0xf,	0xf,	-1,	24,	28,	-1},
+	{PERIPH_ID_I2C10,	-1,	0x3f,	-1,	-1,	8,	-1},
+
+	{PERIPH_ID_NONE,	-1,	-1,	-1,	-1,	-1,	-1},
 };
 
 /* Epll Clock division values to achive different frequency output */
@@ -260,112 +302,8 @@
 	return fout;
 }
 
-static unsigned long exynos5_get_periph_rate(int peripheral)
-{
-	struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
-	unsigned long sclk, sub_clk;
-	unsigned int src, div, sub_div;
-	struct exynos5_clock *clk =
-			(struct exynos5_clock *)samsung_get_base_clock();
-
-	switch (peripheral) {
-	case PERIPH_ID_UART0:
-	case PERIPH_ID_UART1:
-	case PERIPH_ID_UART2:
-	case PERIPH_ID_UART3:
-		src = readl(&clk->src_peric0);
-		div = readl(&clk->div_peric0);
-		break;
-	case PERIPH_ID_PWM0:
-	case PERIPH_ID_PWM1:
-	case PERIPH_ID_PWM2:
-	case PERIPH_ID_PWM3:
-	case PERIPH_ID_PWM4:
-		src = readl(&clk->src_peric0);
-		div = readl(&clk->div_peric3);
-		break;
-	case PERIPH_ID_I2S0:
-		src = readl(&clk->src_mau);
-		div = readl(&clk->div_mau);
-	case PERIPH_ID_SPI0:
-	case PERIPH_ID_SPI1:
-		src = readl(&clk->src_peric1);
-		div = readl(&clk->div_peric1);
-		break;
-	case PERIPH_ID_SPI2:
-		src = readl(&clk->src_peric1);
-		div = readl(&clk->div_peric2);
-		break;
-	case PERIPH_ID_SPI3:
-	case PERIPH_ID_SPI4:
-		src = readl(&clk->sclk_src_isp);
-		div = readl(&clk->sclk_div_isp);
-		break;
-	case PERIPH_ID_SDMMC0:
-	case PERIPH_ID_SDMMC1:
-	case PERIPH_ID_SDMMC2:
-	case PERIPH_ID_SDMMC3:
-		src = readl(&clk->src_fsys);
-		div = readl(&clk->div_fsys1);
-		break;
-	case PERIPH_ID_I2C0:
-	case PERIPH_ID_I2C1:
-	case PERIPH_ID_I2C2:
-	case PERIPH_ID_I2C3:
-	case PERIPH_ID_I2C4:
-	case PERIPH_ID_I2C5:
-	case PERIPH_ID_I2C6:
-	case PERIPH_ID_I2C7:
-		sclk = exynos5_get_pll_clk(MPLL);
-		sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
-								& 0x7) + 1;
-		div = ((readl(&clk->div_top0) >> bit_info->prediv_bit)
-								& 0x7) + 1;
-		return (sclk / sub_div) / div;
-	default:
-		debug("%s: invalid peripheral %d", __func__, peripheral);
-		return -1;
-	};
-
-	src = (src >> bit_info->src_bit) & 0xf;
-
-	switch (src) {
-	case EXYNOS_SRC_MPLL:
-		sclk = exynos5_get_pll_clk(MPLL);
-		break;
-	case EXYNOS_SRC_EPLL:
-		sclk = exynos5_get_pll_clk(EPLL);
-		break;
-	case EXYNOS_SRC_VPLL:
-		sclk = exynos5_get_pll_clk(VPLL);
-		break;
-	default:
-		return 0;
-	}
-
-	/* Ratio clock division for this peripheral */
-	sub_div = (div >> bit_info->div_bit) & 0xf;
-	sub_clk = sclk / (sub_div + 1);
-
-	/* Pre-ratio clock division for SDMMC0 and 2 */
-	if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) {
-		div = (div >> bit_info->prediv_bit) & 0xff;
-		return sub_clk / (div + 1);
-	}
-
-	return sub_clk;
-}
-
-unsigned long clock_get_periph_rate(int peripheral)
-{
-	if (cpu_is_exynos5())
-		return exynos5_get_periph_rate(peripheral);
-	else
-		return 0;
-}
-
-/* exynos5420: return pll clock frequency */
-static unsigned long exynos5420_get_pll_clk(int pllreg)
+/* exynos542x: return pll clock frequency */
+static unsigned long exynos542x_get_pll_clk(int pllreg)
 {
 	struct exynos5420_clock *clk =
 		(struct exynos5420_clock *)samsung_get_base_clock();
@@ -404,6 +342,231 @@
 	return exynos_get_pll_clk(pllreg, r, k);
 }
 
+static struct clk_bit_info *get_clk_bit_info(int peripheral)
+{
+	int i;
+	struct clk_bit_info *info;
+
+	if (proid_is_exynos5420() || proid_is_exynos5800())
+		info = exynos542x_bit_info;
+	else
+		info = exynos5_bit_info;
+
+	for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
+		if (info[i].id == peripheral)
+			break;
+	}
+
+	if (info[i].id == PERIPH_ID_NONE)
+		debug("ERROR: Peripheral ID %d not found\n", peripheral);
+
+	return &info[i];
+}
+
+static unsigned long exynos5_get_periph_rate(int peripheral)
+{
+	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
+	unsigned long sclk = 0;
+	unsigned int src = 0, div = 0, sub_div = 0;
+	struct exynos5_clock *clk =
+			(struct exynos5_clock *)samsung_get_base_clock();
+
+	switch (peripheral) {
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+		src = readl(&clk->src_peric0);
+		div = readl(&clk->div_peric0);
+		break;
+	case PERIPH_ID_PWM0:
+	case PERIPH_ID_PWM1:
+	case PERIPH_ID_PWM2:
+	case PERIPH_ID_PWM3:
+	case PERIPH_ID_PWM4:
+		src = readl(&clk->src_peric0);
+		div = readl(&clk->div_peric3);
+		break;
+	case PERIPH_ID_I2S0:
+		src = readl(&clk->src_mau);
+		div = sub_div = readl(&clk->div_mau);
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+		src = readl(&clk->src_peric1);
+		div = sub_div = readl(&clk->div_peric1);
+		break;
+	case PERIPH_ID_SPI2:
+		src = readl(&clk->src_peric1);
+		div = sub_div = readl(&clk->div_peric2);
+		break;
+	case PERIPH_ID_SPI3:
+	case PERIPH_ID_SPI4:
+		src = readl(&clk->sclk_src_isp);
+		div = sub_div = readl(&clk->sclk_div_isp);
+		break;
+	case PERIPH_ID_SDMMC0:
+	case PERIPH_ID_SDMMC1:
+		src = readl(&clk->src_fsys);
+		div = sub_div = readl(&clk->div_fsys1);
+		break;
+	case PERIPH_ID_SDMMC2:
+	case PERIPH_ID_SDMMC3:
+		src = readl(&clk->src_fsys);
+		div = sub_div = readl(&clk->div_fsys2);
+		break;
+	case PERIPH_ID_I2C0:
+	case PERIPH_ID_I2C1:
+	case PERIPH_ID_I2C2:
+	case PERIPH_ID_I2C3:
+	case PERIPH_ID_I2C4:
+	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
+		src = EXYNOS_SRC_MPLL;
+		div = readl(&clk->div_top0);
+		sub_div = readl(&clk->div_top1);
+		break;
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return -1;
+	};
+
+	if (bit_info->src_bit >= 0)
+		src = (src >> bit_info->src_bit) & bit_info->src_mask;
+
+	switch (src) {
+	case EXYNOS_SRC_MPLL:
+		sclk = exynos5_get_pll_clk(MPLL);
+		break;
+	case EXYNOS_SRC_EPLL:
+		sclk = exynos5_get_pll_clk(EPLL);
+		break;
+	case EXYNOS_SRC_VPLL:
+		sclk = exynos5_get_pll_clk(VPLL);
+		break;
+	default:
+		debug("%s: EXYNOS_SRC %d not supported\n", __func__, src);
+		return 0;
+	}
+
+	/* Clock divider ratio for this peripheral */
+	if (bit_info->div_bit >= 0)
+		div = (div >> bit_info->div_bit) & bit_info->div_mask;
+
+	/* Clock pre-divider ratio for this peripheral */
+	if (bit_info->prediv_bit >= 0)
+		sub_div = (sub_div >> bit_info->prediv_bit)
+			  & bit_info->prediv_mask;
+
+	/* Calculate and return required clock rate */
+	return (sclk / (div + 1)) / (sub_div + 1);
+}
+
+static unsigned long exynos542x_get_periph_rate(int peripheral)
+{
+	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
+	unsigned long sclk = 0;
+	unsigned int src = 0, div = 0, sub_div = 0;
+	struct exynos5420_clock *clk =
+			(struct exynos5420_clock *)samsung_get_base_clock();
+
+	switch (peripheral) {
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+	case PERIPH_ID_PWM0:
+	case PERIPH_ID_PWM1:
+	case PERIPH_ID_PWM2:
+	case PERIPH_ID_PWM3:
+	case PERIPH_ID_PWM4:
+		src = readl(&clk->src_peric0);
+		div = readl(&clk->div_peric0);
+		break;
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+	case PERIPH_ID_SPI2:
+		src = readl(&clk->src_peric1);
+		div = readl(&clk->div_peric1);
+		sub_div = readl(&clk->div_peric4);
+		break;
+	case PERIPH_ID_SPI3:
+	case PERIPH_ID_SPI4:
+		src = readl(&clk->src_isp);
+		div = readl(&clk->div_isp1);
+		sub_div = readl(&clk->div_isp1);
+		break;
+	case PERIPH_ID_SDMMC0:
+	case PERIPH_ID_SDMMC1:
+	case PERIPH_ID_SDMMC2:
+	case PERIPH_ID_SDMMC3:
+		src = readl(&clk->src_fsys);
+		div = readl(&clk->div_fsys1);
+		break;
+	case PERIPH_ID_I2C0:
+	case PERIPH_ID_I2C1:
+	case PERIPH_ID_I2C2:
+	case PERIPH_ID_I2C3:
+	case PERIPH_ID_I2C4:
+	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
+	case PERIPH_ID_I2C8:
+	case PERIPH_ID_I2C9:
+	case PERIPH_ID_I2C10:
+		src = EXYNOS542X_SRC_MPLL;
+		div = readl(&clk->div_top1);
+		break;
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return -1;
+	};
+
+	if (bit_info->src_bit >= 0)
+		src = (src >> bit_info->src_bit) & bit_info->src_mask;
+
+	switch (src) {
+	case EXYNOS542X_SRC_MPLL:
+		sclk = exynos542x_get_pll_clk(MPLL);
+		break;
+	case EXYNOS542X_SRC_SPLL:
+		sclk = exynos542x_get_pll_clk(SPLL);
+		break;
+	case EXYNOS542X_SRC_EPLL:
+		sclk = exynos542x_get_pll_clk(EPLL);
+		break;
+	case EXYNOS542X_SRC_RPLL:
+		sclk = exynos542x_get_pll_clk(RPLL);
+		break;
+	default:
+		debug("%s: EXYNOS542X_SRC %d not supported", __func__, src);
+		return 0;
+	}
+
+	/* Clock divider ratio for this peripheral */
+	if (bit_info->div_bit >= 0)
+		div = (div >> bit_info->div_bit) & bit_info->div_mask;
+
+	/* Clock pre-divider ratio for this peripheral */
+	if (bit_info->prediv_bit >= 0)
+		sub_div = (sub_div >> bit_info->prediv_bit)
+			  & bit_info->prediv_mask;
+
+	/* Calculate and return required clock rate */
+	return (sclk / (div + 1)) / (sub_div + 1);
+}
+
+unsigned long clock_get_periph_rate(int peripheral)
+{
+	if (cpu_is_exynos5()) {
+		if (proid_is_exynos5420() || proid_is_exynos5800())
+			return exynos542x_get_periph_rate(peripheral);
+		return exynos5_get_periph_rate(peripheral);
+	} else {
+		return 0;
+	}
+}
+
 /* exynos4: return ARM clock frequency */
 static unsigned long exynos4_get_arm_clk(void)
 {
@@ -527,27 +690,6 @@
 	return pclk;
 }
 
-/* exynos5420: return pwm clock frequency */
-static unsigned long exynos5420_get_pwm_clk(void)
-{
-	struct exynos5420_clock *clk =
-		(struct exynos5420_clock *)samsung_get_base_clock();
-	unsigned long pclk, sclk;
-	unsigned int ratio;
-
-	/*
-	 * CLK_DIV_PERIC0
-	 * PWM_RATIO [31:28]
-	 */
-	ratio = readl(&clk->div_peric0);
-	ratio = (ratio >> 28) & 0xf;
-	sclk = get_pll_clk(MPLL);
-
-	pclk = sclk / (ratio + 1);
-
-	return pclk;
-}
-
 /* exynos4: return uart clock frequency */
 static unsigned long exynos4_get_uart_clk(int dev_index)
 {
@@ -640,100 +782,6 @@
 	return uclk;
 }
 
-/* exynos5: return uart clock frequency */
-static unsigned long exynos5_get_uart_clk(int dev_index)
-{
-	struct exynos5_clock *clk =
-		(struct exynos5_clock *)samsung_get_base_clock();
-	unsigned long uclk, sclk;
-	unsigned int sel;
-	unsigned int ratio;
-
-	/*
-	 * CLK_SRC_PERIC0
-	 * UART0_SEL [3:0]
-	 * UART1_SEL [7:4]
-	 * UART2_SEL [8:11]
-	 * UART3_SEL [12:15]
-	 * UART4_SEL [16:19]
-	 * UART5_SEL [23:20]
-	 */
-	sel = readl(&clk->src_peric0);
-	sel = (sel >> (dev_index << 2)) & 0xf;
-
-	if (sel == 0x6)
-		sclk = get_pll_clk(MPLL);
-	else if (sel == 0x7)
-		sclk = get_pll_clk(EPLL);
-	else if (sel == 0x8)
-		sclk = get_pll_clk(VPLL);
-	else
-		return 0;
-
-	/*
-	 * CLK_DIV_PERIC0
-	 * UART0_RATIO [3:0]
-	 * UART1_RATIO [7:4]
-	 * UART2_RATIO [8:11]
-	 * UART3_RATIO [12:15]
-	 * UART4_RATIO [16:19]
-	 * UART5_RATIO [23:20]
-	 */
-	ratio = readl(&clk->div_peric0);
-	ratio = (ratio >> (dev_index << 2)) & 0xf;
-
-	uclk = sclk / (ratio + 1);
-
-	return uclk;
-}
-
-/* exynos5420: return uart clock frequency */
-static unsigned long exynos5420_get_uart_clk(int dev_index)
-{
-	struct exynos5420_clock *clk =
-		(struct exynos5420_clock *)samsung_get_base_clock();
-	unsigned long uclk, sclk;
-	unsigned int sel;
-	unsigned int ratio;
-
-	/*
-	 * CLK_SRC_PERIC0
-	 * UART0_SEL [6:4]
-	 * UART1_SEL [10:8]
-	 * UART2_SEL [14:12]
-	 * UART3_SEL [18:16]
-	 * generalised calculation as follows
-	 * sel = (sel >> ((dev_index * 4) + 4)) & mask;
-	 */
-	sel = readl(&clk->src_peric0);
-	sel = (sel >> ((dev_index * 4) + 4)) & 0x7;
-
-	if (sel == 0x3)
-		sclk = get_pll_clk(MPLL);
-	else if (sel == 0x6)
-		sclk = get_pll_clk(EPLL);
-	else if (sel == 0x7)
-		sclk = get_pll_clk(RPLL);
-	else
-		return 0;
-
-	/*
-	 * CLK_DIV_PERIC0
-	 * UART0_RATIO [11:8]
-	 * UART1_RATIO [15:12]
-	 * UART2_RATIO [19:16]
-	 * UART3_RATIO [23:20]
-	 * generalised calculation as follows
-	 * ratio = (ratio >> ((dev_index * 4) + 8)) & mask;
-	 */
-	ratio = readl(&clk->div_peric0);
-	ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;
-
-	uclk = sclk / (ratio + 1);
-
-	return uclk;
-}
-
 static unsigned long exynos4_get_mmc_clk(int dev_index)
 {
 	struct exynos4_clock *clk =
@@ -783,94 +831,6 @@
 	return uclk;
 }
 
-static unsigned long exynos5_get_mmc_clk(int dev_index)
-{
-	struct exynos5_clock *clk =
-		(struct exynos5_clock *)samsung_get_base_clock();
-	unsigned long uclk, sclk;
-	unsigned int sel, ratio, pre_ratio;
-	int shift = 0;
-
-	sel = readl(&clk->src_fsys);
-	sel = (sel >> (dev_index << 2)) & 0xf;
-
-	if (sel == 0x6)
-		sclk = get_pll_clk(MPLL);
-	else if (sel == 0x7)
-		sclk = get_pll_clk(EPLL);
-	else if (sel == 0x8)
-		sclk = get_pll_clk(VPLL);
-	else
-		return 0;
-
-	switch (dev_index) {
-	case 0:
-	case 1:
-		ratio = readl(&clk->div_fsys1);
-		pre_ratio = readl(&clk->div_fsys1);
-		break;
-	case 2:
-	case 3:
-		ratio = readl(&clk->div_fsys2);
-		pre_ratio = readl(&clk->div_fsys2);
-		break;
-	default:
-		return 0;
-	}
-
-	if (dev_index == 1 || dev_index == 3)
-		shift = 16;
-
-	ratio = (ratio >> shift) & 0xf;
-	pre_ratio = (pre_ratio >> (shift + 8)) & 0xff;
-	uclk = (sclk / (ratio + 1)) / (pre_ratio + 1);
-
-	return uclk;
-}
-
-static unsigned long exynos5420_get_mmc_clk(int dev_index)
-{
-	struct exynos5420_clock *clk =
-		(struct exynos5420_clock *)samsung_get_base_clock();
-	unsigned long uclk, sclk;
-	unsigned int sel, ratio;
-
-	/*
-	 * CLK_SRC_FSYS
-	 * MMC0_SEL [10:8]
-	 * MMC1_SEL [14:12]
-	 * MMC2_SEL [18:16]
-	 * generalised calculation as follows
-	 * sel = (sel >> ((dev_index * 4) + 8)) & mask
-	 */
-	sel = readl(&clk->src_fsys);
-	sel = (sel >> ((dev_index * 4) + 8)) & 0x7;
-
-	if (sel == 0x3)
-		sclk = get_pll_clk(MPLL);
-	else if (sel == 0x4)
-		sclk = get_pll_clk(SPLL);
-	else if (sel == 0x6)
-		sclk = get_pll_clk(EPLL);
-	else
-		return 0;
-
-	/*
-	 * CLK_DIV_FSYS1
-	 * MMC0_RATIO [9:0]
-	 * MMC1_RATIO [19:10]
-	 * MMC2_RATIO [29:20]
-	 * generalised calculation as follows
-	 * ratio = (ratio >> (dev_index * 10)) & mask
-	 */
-	ratio = readl(&clk->div_fsys1);
-	ratio = (ratio >> (dev_index * 10)) & 0x3ff;
-
-	uclk = (sclk / (ratio + 1));
-
-	return uclk;
-}
-
 /* exynos4: set the mmc clock */
 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
 {
@@ -1249,29 +1209,6 @@
 	clrsetbits_le32(&clk->div_lcd0, 0xf << 16, 0x1 << 16);
 }
 
-/*
- * I2C
- *
- * exynos5: obtaining the I2C clock
- */
-static unsigned long exynos5_get_i2c_clk(void)
-{
-	struct exynos5_clock *clk =
-		(struct exynos5_clock *)samsung_get_base_clock();
-	unsigned long aclk_66, aclk_66_pre, sclk;
-	unsigned int ratio;
-
-	sclk = get_pll_clk(MPLL);
-
-	ratio = (readl(&clk->div_top1)) >> 24;
-	ratio &= 0x7;
-	aclk_66_pre = sclk / (ratio + 1);
-	ratio = readl(&clk->div_top0);
-	ratio &= 0x7;
-	aclk_66 = aclk_66_pre / (ratio + 1);
-	return aclk_66;
-}
-
 int exynos5_set_epll_clk(unsigned long rate)
 {
 	unsigned int epll_con, epll_con_k;
@@ -1585,7 +1522,7 @@
 {
 	if (cpu_is_exynos5()) {
 		if (proid_is_exynos5420() || proid_is_exynos5800())
-			return exynos5420_get_pll_clk(pllreg);
+			return exynos542x_get_pll_clk(pllreg);
 		return exynos5_get_pll_clk(pllreg);
 	} else {
 		if (proid_is_exynos4412())
@@ -1608,7 +1545,7 @@
 unsigned long get_i2c_clk(void)
 {
 	if (cpu_is_exynos5()) {
-		return exynos5_get_i2c_clk();
+		return clock_get_periph_rate(PERIPH_ID_I2C0);
 	} else if (cpu_is_exynos4()) {
 		return exynos4_get_i2c_clk();
 	} else {
@@ -1620,8 +1557,6 @@
 unsigned long get_pwm_clk(void)
 {
 	if (cpu_is_exynos5()) {
-		if (proid_is_exynos5420() || proid_is_exynos5800())
-			return exynos5420_get_pwm_clk();
 		return clock_get_periph_rate(PERIPH_ID_PWM0);
 	} else {
 		if (proid_is_exynos4412())
@@ -1632,10 +1567,28 @@
 
 unsigned long get_uart_clk(int dev_index)
 {
+	enum periph_id id;
+
+	switch (dev_index) {
+	case 0:
+		id = PERIPH_ID_UART0;
+		break;
+	case 1:
+		id = PERIPH_ID_UART1;
+		break;
+	case 2:
+		id = PERIPH_ID_UART2;
+		break;
+	case 3:
+		id = PERIPH_ID_UART3;
+		break;
+	default:
+		debug("%s: invalid UART index %d", __func__, dev_index);
+		return -1;
+	}
+
 	if (cpu_is_exynos5()) {
-		if (proid_is_exynos5420() || proid_is_exynos5800())
-			return exynos5420_get_uart_clk(dev_index);
-		return exynos5_get_uart_clk(dev_index);
+		return clock_get_periph_rate(id);
 	} else {
 		if (proid_is_exynos4412())
 			return exynos4x12_get_uart_clk(dev_index);
@@ -1645,10 +1598,28 @@
 
 unsigned long get_mmc_clk(int dev_index)
 {
+	enum periph_id id;
+
+	switch (dev_index) {
+	case 0:
+		id = PERIPH_ID_SDMMC0;
+		break;
+	case 1:
+		id = PERIPH_ID_SDMMC1;
+		break;
+	case 2:
+		id = PERIPH_ID_SDMMC2;
+		break;
+	case 3:
+		id = PERIPH_ID_SDMMC3;
+		break;
+	default:
+		debug("%s: invalid MMC index %d", __func__, dev_index);
+		return -1;
+	}
+
 	if (cpu_is_exynos5()) {
-		if (proid_is_exynos5420() || proid_is_exynos5800())
-			return exynos5420_get_mmc_clk(dev_index);
-		return exynos5_get_mmc_clk(dev_index);
+		return clock_get_periph_rate(id);
 	} else {
 		return exynos4_get_mmc_clk(dev_index);
 	}
@@ -1656,6 +1627,10 @@
 
 void set_mmc_clk(int dev_index, unsigned int div)
 {
+	/* If want to set correct value, it needs to substract one from div.*/
+	if (div > 0)
+		div -= 1;
+
 	if (cpu_is_exynos5()) {
 		if (proid_is_exynos5420() || proid_is_exynos5800())
 			exynos5420_set_mmc_clk(dev_index, div);
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 94d0297..be43e22 100644
--- a/arch/arm/cpu/armv7/exynos/pinmux.c
+++ b/arch/arm/cpu/armv7/exynos/pinmux.c
@@ -266,22 +266,33 @@
 
 static void exynos5_i2c_config(int peripheral, int flags)
 {
+	int func01, func23;
+
+	 /* High-Speed I2C */
+	if (flags & PINMUX_FLAG_HS_MODE) {
+		func01 = 4;
+		func23 = 4;
+	} else {
+		func01 = 2;
+		func23 = 3;
+	}
+
 	switch (peripheral) {
 	case PERIPH_ID_I2C0:
-		gpio_cfg_pin(EXYNOS5_GPIO_B30, S5P_GPIO_FUNC(0x2));
-		gpio_cfg_pin(EXYNOS5_GPIO_B31, S5P_GPIO_FUNC(0x2));
+		gpio_cfg_pin(EXYNOS5_GPIO_B30, S5P_GPIO_FUNC(func01));
+		gpio_cfg_pin(EXYNOS5_GPIO_B31, S5P_GPIO_FUNC(func01));
 		break;
 	case PERIPH_ID_I2C1:
-		gpio_cfg_pin(EXYNOS5_GPIO_B32, S5P_GPIO_FUNC(0x2));
-		gpio_cfg_pin(EXYNOS5_GPIO_B33, S5P_GPIO_FUNC(0x2));
+		gpio_cfg_pin(EXYNOS5_GPIO_B32, S5P_GPIO_FUNC(func01));
+		gpio_cfg_pin(EXYNOS5_GPIO_B33, S5P_GPIO_FUNC(func01));
 		break;
 	case PERIPH_ID_I2C2:
-		gpio_cfg_pin(EXYNOS5_GPIO_A06, S5P_GPIO_FUNC(0x3));
-		gpio_cfg_pin(EXYNOS5_GPIO_A07, S5P_GPIO_FUNC(0x3));
+		gpio_cfg_pin(EXYNOS5_GPIO_A06, S5P_GPIO_FUNC(func23));
+		gpio_cfg_pin(EXYNOS5_GPIO_A07, S5P_GPIO_FUNC(func23));
 		break;
 	case PERIPH_ID_I2C3:
-		gpio_cfg_pin(EXYNOS5_GPIO_A12, S5P_GPIO_FUNC(0x3));
-		gpio_cfg_pin(EXYNOS5_GPIO_A13, S5P_GPIO_FUNC(0x3));
+		gpio_cfg_pin(EXYNOS5_GPIO_A12, S5P_GPIO_FUNC(func23));
+		gpio_cfg_pin(EXYNOS5_GPIO_A13, S5P_GPIO_FUNC(func23));
 		break;
 	case PERIPH_ID_I2C4:
 		gpio_cfg_pin(EXYNOS5_GPIO_A20, S5P_GPIO_FUNC(0x3));
diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c
index 1520d64..1b12051 100644
--- a/arch/arm/cpu/armv7/exynos/power.c
+++ b/arch/arm/cpu/armv7/exynos/power.c
@@ -102,10 +102,34 @@
 	}
 }
 
+static void exynos5420_set_usbdev_phy_ctrl(unsigned int enable)
+{
+	struct exynos5420_power *power =
+		(struct exynos5420_power *)samsung_get_base_power();
+
+	if (enable) {
+		/* Enabling USBDEV_PHY */
+		setbits_le32(&power->usbdev_phy_control,
+				POWER_USB_DRD_PHY_CTRL_EN);
+		setbits_le32(&power->usbdev1_phy_control,
+				POWER_USB_DRD_PHY_CTRL_EN);
+	} else {
+		/* Disabling USBDEV_PHY */
+		clrbits_le32(&power->usbdev_phy_control,
+				POWER_USB_DRD_PHY_CTRL_EN);
+		clrbits_le32(&power->usbdev1_phy_control,
+				POWER_USB_DRD_PHY_CTRL_EN);
+	}
+}
+
 void set_usbdrd_phy_ctrl(unsigned int enable)
 {
-	if (cpu_is_exynos5())
-		exynos5_set_usbdrd_phy_ctrl(enable);
+	if (cpu_is_exynos5()) {
+		if (proid_is_exynos5420() || proid_is_exynos5800())
+			exynos5420_set_usbdev_phy_ctrl(enable);
+		else
+			exynos5_set_usbdrd_phy_ctrl(enable);
+	}
 }
 
 static void exynos5_dp_phy_control(unsigned int enable)
diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c
index bc237c9..c7f943e 100644
--- a/arch/arm/cpu/armv7/exynos/spl_boot.c
+++ b/arch/arm/cpu/armv7/exynos/spl_boot.c
@@ -309,4 +309,3 @@
 	while (1)
 		;
 }
-void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c
index 7a9b03a..fef2231 100644
--- a/arch/arm/cpu/armv7/mx6/ddr.c
+++ b/arch/arm/cpu/armv7/mx6/ddr.c
@@ -12,6 +12,65 @@
 #include <asm/io.h>
 #include <asm/types.h>
 
+#if defined(CONFIG_MX6SX)
+/* Configure MX6SX mmdc iomux */
+void mx6sx_dram_iocfg(unsigned width,
+		      const struct mx6sx_iomux_ddr_regs *ddr,
+		      const struct mx6sx_iomux_grp_regs *grp)
+{
+	struct mx6sx_iomux_ddr_regs *mx6_ddr_iomux;
+	struct mx6sx_iomux_grp_regs *mx6_grp_iomux;
+
+	mx6_ddr_iomux = (struct mx6sx_iomux_ddr_regs *)MX6SX_IOM_DDR_BASE;
+	mx6_grp_iomux = (struct mx6sx_iomux_grp_regs *)MX6SX_IOM_GRP_BASE;
+
+	/* DDR IO TYPE */
+	writel(grp->grp_ddr_type, &mx6_grp_iomux->grp_ddr_type);
+	writel(grp->grp_ddrpke, &mx6_grp_iomux->grp_ddrpke);
+
+	/* CLOCK */
+	writel(ddr->dram_sdclk_0, &mx6_ddr_iomux->dram_sdclk_0);
+
+	/* ADDRESS */
+	writel(ddr->dram_cas, &mx6_ddr_iomux->dram_cas);
+	writel(ddr->dram_ras, &mx6_ddr_iomux->dram_ras);
+	writel(grp->grp_addds, &mx6_grp_iomux->grp_addds);
+
+	/* Control */
+	writel(ddr->dram_reset, &mx6_ddr_iomux->dram_reset);
+	writel(ddr->dram_sdba2, &mx6_ddr_iomux->dram_sdba2);
+	writel(ddr->dram_sdcke0, &mx6_ddr_iomux->dram_sdcke0);
+	writel(ddr->dram_sdcke1, &mx6_ddr_iomux->dram_sdcke1);
+	writel(ddr->dram_odt0, &mx6_ddr_iomux->dram_odt0);
+	writel(ddr->dram_odt1, &mx6_ddr_iomux->dram_odt1);
+	writel(grp->grp_ctlds, &mx6_grp_iomux->grp_ctlds);
+
+	/* Data Strobes */
+	writel(grp->grp_ddrmode_ctl, &mx6_grp_iomux->grp_ddrmode_ctl);
+	writel(ddr->dram_sdqs0, &mx6_ddr_iomux->dram_sdqs0);
+	writel(ddr->dram_sdqs1, &mx6_ddr_iomux->dram_sdqs1);
+	if (width >= 32) {
+		writel(ddr->dram_sdqs2, &mx6_ddr_iomux->dram_sdqs2);
+		writel(ddr->dram_sdqs3, &mx6_ddr_iomux->dram_sdqs3);
+	}
+
+	/* Data */
+	writel(grp->grp_ddrmode, &mx6_grp_iomux->grp_ddrmode);
+	writel(grp->grp_b0ds, &mx6_grp_iomux->grp_b0ds);
+	writel(grp->grp_b1ds, &mx6_grp_iomux->grp_b1ds);
+	if (width >= 32) {
+		writel(grp->grp_b2ds, &mx6_grp_iomux->grp_b2ds);
+		writel(grp->grp_b3ds, &mx6_grp_iomux->grp_b3ds);
+	}
+	writel(ddr->dram_dqm0, &mx6_ddr_iomux->dram_dqm0);
+	writel(ddr->dram_dqm1, &mx6_ddr_iomux->dram_dqm1);
+	if (width >= 32) {
+		writel(ddr->dram_dqm2, &mx6_ddr_iomux->dram_dqm2);
+		writel(ddr->dram_dqm3, &mx6_ddr_iomux->dram_dqm3);
+	}
+}
+#endif
+
 #if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
 /* Configure MX6DQ mmdc iomux */
 void mx6dq_dram_iocfg(unsigned width,
@@ -184,12 +243,19 @@
  */
 #define MR(val, ba, cmd, cs1) \
 	((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
+#ifdef CONFIG_MX6SX
+#define MMDC1(entry, value)	do {} while (0)
+#else
+#define MMDC1(entry, value) do { mmdc1->entry = value; } while (0)
+#endif
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		  const struct mx6_mmdc_calibration *calib,
 		  const struct mx6_ddr3_cfg *ddr3_cfg)
 {
 	volatile struct mmdc_p_regs *mmdc0;
+#ifndef CONFIG_MX6SX
 	volatile struct mmdc_p_regs *mmdc1;
+#endif
 	u32 val;
 	u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
 	u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
@@ -203,7 +269,9 @@
 	int cs;
 
 	mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
+#ifndef CONFIG_MX6SX
 	mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
+#endif
 
 	/* MX6D/MX6Q: 1066 MHz memory clock, clkper = 1.894ns = 1894ps */
 	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
@@ -362,12 +430,12 @@
 	mmdc0->mprddlctl = calib->p0_mprddlctl;
 	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
 	if (sysinfo->dsize > 1) {
-		mmdc1->mpwldectrl0 = calib->p1_mpwldectrl0;
-		mmdc1->mpwldectrl1 = calib->p1_mpwldectrl1;
-		mmdc1->mpdgctrl0 = calib->p1_mpdgctrl0;
-		mmdc1->mpdgctrl1 = calib->p1_mpdgctrl1;
-		mmdc1->mprddlctl = calib->p1_mprddlctl;
-		mmdc1->mpwrdlctl = calib->p1_mpwrdlctl;
+		MMDC1(mpwldectrl0, calib->p1_mpwldectrl0);
+		MMDC1(mpwldectrl1, calib->p1_mpwldectrl1);
+		MMDC1(mpdgctrl0, calib->p1_mpdgctrl0);
+		MMDC1(mpdgctrl1, calib->p1_mpdgctrl1);
+		MMDC1(mprddlctl, calib->p1_mprddlctl);
+		MMDC1(mpwrdlctl, calib->p1_mpwrdlctl);
 	}
 
 	/* Read data DQ Byte0-3 delay */
@@ -379,23 +447,23 @@
 	}
 
 	if (sysinfo->dsize > 1) {
-		mmdc1->mprddqby0dl = 0x33333333;
-		mmdc1->mprddqby1dl = 0x33333333;
-		mmdc1->mprddqby2dl = 0x33333333;
-		mmdc1->mprddqby3dl = 0x33333333;
+		MMDC1(mprddqby0dl, 0x33333333);
+		MMDC1(mprddqby1dl, 0x33333333);
+		MMDC1(mprddqby2dl, 0x33333333);
+		MMDC1(mprddqby3dl, 0x33333333);
 	}
 
 	/* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
 	val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227;
 	mmdc0->mpodtctrl = val;
 	if (sysinfo->dsize > 1)
-		mmdc1->mpodtctrl = val;
+		MMDC1(mpodtctrl, val);
 
 	/* complete calibration */
 	val = (1 << 11); /* Force measurement on delay-lines */
 	mmdc0->mpmur0 = val;
 	if (sysinfo->dsize > 1)
-		mmdc1->mpmur0 = val;
+		MMDC1(mpmur0, val);
 
 	/* Step 1: configuration request */
 	mmdc0->mdscr = (u32)(1 << 15); /* config request */
@@ -435,7 +503,7 @@
 	val = 0xa1390001; /* one-time HW ZQ calib */
 	mmdc0->mpzqhwctrl = val;
 	if (sysinfo->dsize > 1)
-		mmdc1->mpzqhwctrl = val;
+		MMDC1(mpzqhwctrl, val);
 
 	/* Step 7: Enable MMDC with desired chip select */
 	mmdc0->mdctl |= (1 << 31) |			     /* SDE_0 for CS0 */
@@ -477,7 +545,7 @@
 	val = 0xa1390003;
 	mmdc0->mpzqhwctrl = val;
 	if (sysinfo->dsize > 1)
-		mmdc1->mpzqhwctrl = val;
+		MMDC1(mpzqhwctrl, val);
 
 	/* Step 12: Configure and activate periodic refresh */
 	mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */
diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
index 5f5f497..e599a12 100644
--- a/arch/arm/cpu/armv7/mx6/soc.c
+++ b/arch/arm/cpu/armv7/mx6/soc.c
@@ -109,7 +109,7 @@
 	aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
 	aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
 #ifdef CONFIG_MX6SX
-	aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR;
+	aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR;
 #endif
 
 	/*
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c
index 8e7411d..03674e6 100644
--- a/arch/arm/cpu/armv7/omap-common/clocks-common.c
+++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c
@@ -437,12 +437,15 @@
 {
 	u32 offset_code;
 	u32 offset = volt_mv;
+#ifndef	CONFIG_DRA7XX
 	int ret = 0;
+#endif
 
 	if (!volt_mv)
 		return;
 
 	pmic->pmic_bus_init();
+#ifndef	CONFIG_DRA7XX
 	/* See if we can first get the GPIO if needed */
 	if (pmic->gpio_en)
 		ret = gpio_request(pmic->gpio, "PMIC_GPIO");
@@ -456,7 +459,7 @@
 	/* Pull the GPIO low to select SET0 register, while we program SET1 */
 	if (pmic->gpio_en)
 		gpio_direction_output(pmic->gpio, 0);
-
+#endif
 	/* convert to uV for better accuracy in the calculations */
 	offset *= 1000;
 
@@ -467,9 +470,10 @@
 
 	if (pmic->pmic_write(pmic->i2c_slave_addr, vcore_reg, offset_code))
 		printf("Scaling voltage failed for 0x%x\n", vcore_reg);
-
+#ifndef	CONFIG_DRA7XX
 	if (pmic->gpio_en)
 		gpio_direction_output(pmic->gpio, 1);
+#endif
 }
 
 static u32 optimize_vcore_voltage(struct volts const *v)
@@ -505,13 +509,79 @@
 }
 
 /*
- * Setup the voltages for vdd_mpu, vdd_core, and vdd_iva
- * We set the maximum voltages allowed here because Smart-Reflex is not
- * enabled in bootloader. Voltage initialization in the kernel will set
- * these to the nominal values after enabling Smart-Reflex
+ * Setup the voltages for the main SoC core power domains.
+ * We start with the maximum voltages allowed here, as set in the corresponding
+ * vcores_data struct, and then scale (usually down) to the fused values that
+ * are retrieved from the SoC. The scaling happens only if the efuse.reg fields
+ * are initialised.
+ * Rail grouping is supported for the DRA7xx SoCs only, therefore the code is
+ * compiled conditionally. Note that the new code writes the scaled (or zeroed)
+ * values back to the vcores_data struct for eventual reuse. Zero values mean
+ * that the corresponding rails are not controlled separately, and are not sent
+ * to the PMIC.
  */
 void scale_vcores(struct vcores_data const *vcores)
 {
+#if defined(CONFIG_DRA7XX)
+	int i;
+	struct volts *pv = (struct volts *)vcores;
+	struct volts *px;
+
+	for (i=0; i<(sizeof(struct vcores_data)/sizeof(struct volts)); i++) {
+		debug("%d -> ", pv->value);
+		if (pv->value) {
+			/* Handle non-empty members only */
+			pv->value = optimize_vcore_voltage(pv);
+     			px = (struct volts *)vcores;
+			while (px < pv) {
+				/*
+				 * Scan already handled non-empty members to see
+				 * if we have a group and find the max voltage,
+				 * which is set to the first occurance of the
+				 * particular SMPS; the other group voltages are
+				 * zeroed.
+				 */
+				if (px->value) {
+					if ((pv->pmic->i2c_slave_addr ==
+					     px->pmic->i2c_slave_addr) &&
+					    (pv->addr == px->addr)) {
+					    	/* Same PMIC, same SMPS */
+						if (pv->value > px->value)
+							px->value = pv->value;
+
+						pv->value = 0;
+					}
+		     		}
+				px++;
+			}
+		}
+	     	debug("%d\n", pv->value);
+		pv++;
+	}
+
+	debug("cor: %d\n", vcores->core.value);
+	do_scale_vcore(vcores->core.addr, vcores->core.value, vcores->core.pmic);
+	debug("mpu: %d\n", vcores->mpu.value);
+	do_scale_vcore(vcores->mpu.addr, vcores->mpu.value, vcores->mpu.pmic);
+	/* Configure MPU ABB LDO after scale */
+	abb_setup((*ctrl)->control_std_fuse_opp_vdd_mpu_2,
+		  (*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl,
+		  (*prcm)->prm_abbldo_mpu_setup,
+		  (*prcm)->prm_abbldo_mpu_ctrl,
+		  (*prcm)->prm_irqstatus_mpu_2,
+		  OMAP_ABB_MPU_TXDONE_MASK,
+		  OMAP_ABB_FAST_OPP);
+
+	/* The .mm member is not used for the DRA7xx */
+
+	debug("gpu: %d\n", vcores->gpu.value);
+	do_scale_vcore(vcores->gpu.addr, vcores->gpu.value, vcores->gpu.pmic);
+	debug("eve: %d\n", vcores->eve.value);
+	do_scale_vcore(vcores->eve.addr, vcores->eve.value, vcores->eve.pmic);
+	debug("iva: %d\n", vcores->iva.value);
+	do_scale_vcore(vcores->iva.addr, vcores->iva.value, vcores->iva.pmic);
+	/* Might need udelay(1000) here if debug is enabled to see all prints */
+#else
 	u32 val;
 
 	val = optimize_vcore_voltage(&vcores->core);
@@ -540,6 +610,7 @@
 
 	val = optimize_vcore_voltage(&vcores->iva);
 	do_scale_vcore(vcores->iva.addr, val, vcores->iva.pmic);
+#endif
 }
 
 static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode)
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index e601ba1..c01a98f 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -252,6 +252,8 @@
 {
 	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
 
+	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+	writel(regs->sdram_config_init, &emif->emif_sdram_config);
 	/*
 	 * Set SDRAM_CONFIG and PHY control registers to locked frequency
 	 * and RL =7. As the default values of the Mode Registers are not
@@ -265,7 +267,6 @@
 	writel(regs->sdram_tim2, &emif->emif_sdram_tim_2);
 	writel(regs->sdram_tim3, &emif->emif_sdram_tim_3);
 
-	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
 	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
 
 	/*
@@ -274,6 +275,7 @@
 	 */
 	if (is_dra7xx()) {
 		do_ext_phy_settings(base, regs);
+		writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
 		writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
 		writel(regs->sdram_config_init, &emif->emif_sdram_config);
 	} else {
diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
index 86c0e42..e19c7ae 100644
--- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
@@ -19,7 +19,7 @@
 ENTRY(save_boot_params)
 	ldr	r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS
 	str	r0, [r1]
-	bx	lr
+	b	save_boot_params_ret
 ENDPROC(save_boot_params)
 
 ENTRY(set_pl310_ctrl_reg)
diff --git a/arch/arm/cpu/armv7/omap3/Kconfig b/arch/arm/cpu/armv7/omap3/Kconfig
index a029379..4644098 100644
--- a/arch/arm/cpu/armv7/omap3/Kconfig
+++ b/arch/arm/cpu/armv7/omap3/Kconfig
@@ -93,6 +93,21 @@
 
 endchoice
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if DM && !SPL_BUILD
+
+config DM_SERIAL
+	default y if DM && !SPL_BUILD
+
+config SYS_MALLOC_F
+	default y if DM && !SPL_BUILD
+
+config SYS_MALLOC_F_LEN
+	default 0x400 if DM && !SPL_BUILD
+
 config SYS_SOC
 	default "omap3"
 
diff --git a/arch/arm/cpu/armv7/omap3/clock.c b/arch/arm/cpu/armv7/omap3/clock.c
index 529ad9a..006969e 100644
--- a/arch/arm/cpu/armv7/omap3/clock.c
+++ b/arch/arm/cpu/armv7/omap3/clock.c
@@ -732,11 +732,20 @@
 	setbits_le32(&prcm_base->iclken_per, 0x08);	/* ICKen GPT2 */
 	setbits_le32(&prcm_base->fclken_per, 0x08);	/* FCKen GPT2 */
 
+	/* Enable GP9 timer. */
+	setbits_le32(&prcm_base->clksel_per, 0x80);	/* GPT9 = 32kHz clk */
+	setbits_le32(&prcm_base->iclken_per, 0x400);	/* ICKen GPT9 */
+	setbits_le32(&prcm_base->fclken_per, 0x400);	/* FCKen GPT9 */
+
 #ifdef CONFIG_SYS_NS16550
 	/* Enable UART1 clocks */
 	setbits_le32(&prcm_base->fclken1_core, 0x00002000);
 	setbits_le32(&prcm_base->iclken1_core, 0x00002000);
 
+	/* Enable UART2 clocks */
+	setbits_le32(&prcm_base->fclken1_core, 0x00004000);
+	setbits_le32(&prcm_base->iclken1_core, 0x00004000);
+
 	/* UART 3 Clocks */
 	setbits_le32(&prcm_base->fclken_per, 0x00000800);
 	setbits_le32(&prcm_base->iclken_per, 0x00000800);
diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
index 78577b1..80cb263 100644
--- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
@@ -23,7 +23,7 @@
 	ldr	r5, [r0, #0x4]
 	and	r5, r5, #0xff
 	str	r5, [r4]
-	bx	lr
+	b	save_boot_params_ret
 ENDPROC(save_boot_params)
 #endif
 
diff --git a/arch/arm/cpu/armv7/omap3/sdrc.c b/arch/arm/cpu/armv7/omap3/sdrc.c
index 7a29131..4f15ac9 100644
--- a/arch/arm/cpu/armv7/omap3/sdrc.c
+++ b/arch/arm/cpu/armv7/omap3/sdrc.c
@@ -135,6 +135,9 @@
 	sdrc_actim_base0 = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE;
 	sdrc_actim_base1 = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE;
 
+	/* set some default timings */
+	timings.sharing = SDRC_SHARING;
+
 	/*
 	 * When called in the early context this may be SPL and we will
 	 * need to set all of the timings.  This ends up being board
@@ -145,6 +148,7 @@
 	 * setup CS1.
 	 */
 #ifdef CONFIG_SPL_BUILD
+	/* set/modify board-specific timings */
 	get_board_mem_timings(&timings);
 #endif
 	if (early) {
@@ -155,7 +159,7 @@
 		writel(0, &sdrc_base->sysconfig);
 
 		/* setup sdrc to ball mux */
-		writel(SDRC_SHARING, &sdrc_base->sharing);
+		writel(timings.sharing, &sdrc_base->sharing);
 
 		/* Disable Power Down of CKE because of 1 CKE on combo part */
 		writel(WAKEUPPROC | SRFRONRESET | PAGEPOLICY_HIGH,
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index 95f1686..b9734fe 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -320,6 +320,7 @@
 	.pmic_write	= omap_vc_bypass_send_value,
 };
 
+/* The TPS659038 and TPS65917 are software-compatible, use common struct */
 struct pmic_data tps659038 = {
 	.base_offset = PALMAS_SMPS_BASE_VOLT_UV,
 	.step = 10000, /* 10 mV represented in uV */
@@ -394,34 +395,38 @@
 };
 
 struct vcores_data dra722_volts = {
-	.mpu.value	= 1000,
+	.mpu.value	= VDD_MPU_DRA72x,
 	.mpu.efuse.reg	= STD_FUSE_OPP_VMIN_MPU_NOM,
-	.mpu.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
-	.mpu.addr	= 0x23,
+	.mpu.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+	.mpu.addr	= TPS65917_REG_ADDR_SMPS1,
 	.mpu.pmic	= &tps659038,
 
-	.eve.value	= 1000,
-	.eve.efuse.reg	= STD_FUSE_OPP_VMIN_DSPEVE_NOM,
-	.eve.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
-	.eve.addr	= 0x2f,
-	.eve.pmic	= &tps659038,
-
-	.gpu.value	= 1000,
-	.gpu.efuse.reg	= STD_FUSE_OPP_VMIN_GPU_NOM,
-	.gpu.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
-	.gpu.addr	= 0x2f,
-	.gpu.pmic	= &tps659038,
-
-	.core.value	= 1000,
+	.core.value	= VDD_CORE_DRA72x,
 	.core.efuse.reg	= STD_FUSE_OPP_VMIN_CORE_NOM,
 	.core.efuse.reg_bits = DRA752_EFUSE_REGBITS,
-	.core.addr	= 0x27,
+	.core.addr	= TPS65917_REG_ADDR_SMPS2,
 	.core.pmic	= &tps659038,
 
-	.iva.value	= 1000,
+	/*
+	 * The DSPEVE, GPU and IVA rails are usually grouped on DRA72x
+	 * designs and powered by TPS65917 SMPS3, as on the J6Eco EVM.
+	 */
+	.gpu.value	= VDD_GPU_DRA72x,
+	.gpu.efuse.reg	= STD_FUSE_OPP_VMIN_GPU_NOM,
+	.gpu.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+	.gpu.addr	= TPS65917_REG_ADDR_SMPS3,
+	.gpu.pmic	= &tps659038,
+
+	.eve.value	= VDD_EVE_DRA72x,
+	.eve.efuse.reg	= STD_FUSE_OPP_VMIN_DSPEVE_NOM,
+	.eve.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+	.eve.addr	= TPS65917_REG_ADDR_SMPS3,
+	.eve.pmic	= &tps659038,
+
+	.iva.value	= VDD_IVA_DRA72x,
 	.iva.efuse.reg	= STD_FUSE_OPP_VMIN_IVA_NOM,
-	.iva.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
-	.iva.addr	= 0x2f,
+	.iva.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+	.iva.addr	= TPS65917_REG_ADDR_SMPS3,
 	.iva.pmic	= &tps659038,
 };
 
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index 7d8cec0..5f8daa1 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -141,7 +141,8 @@
 	.sdram_config_init              = 0x61851ab2,
 	.sdram_config                   = 0x61851ab2,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
+	.ref_ctrl                       = 0x000040F1,
+	.ref_ctrl_final			= 0x00001035,
 	.sdram_tim1                     = 0xCCCF36B3,
 	.sdram_tim2                     = 0x308F7FDA,
 	.sdram_tim3                     = 0x027F88A8,
@@ -151,10 +152,10 @@
 	.emif_ddr_phy_ctlr_1_init       = 0x0E24400A,
 	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_3        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_4        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_5        = 0x00BB00BB,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00910091,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00950095,
+	.emif_ddr_ext_phy_ctrl_4        = 0x009B009B,
+	.emif_ddr_ext_phy_ctrl_5        = 0x009E009E,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x00000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -165,7 +166,8 @@
 	.sdram_config_init              = 0x61851B32,
 	.sdram_config                   = 0x61851B32,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
+	.ref_ctrl                       = 0x000040F1,
+	.ref_ctrl_final			= 0x00001035,
 	.sdram_tim1                     = 0xCCCF36B3,
 	.sdram_tim2                     = 0x308F7FDA,
 	.sdram_tim3                     = 0x027F88A8,
@@ -175,10 +177,10 @@
 	.emif_ddr_phy_ctlr_1_init       = 0x0E24400A,
 	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_3        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_4        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_5        = 0x00BB00BB,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00910091,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00950095,
+	.emif_ddr_ext_phy_ctrl_4        = 0x009B009B,
+	.emif_ddr_ext_phy_ctrl_5        = 0x009E009E,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x00000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -186,18 +188,19 @@
 };
 
 const struct emif_regs emif_1_regs_ddr3_666_mhz_1cs_dra_es1 = {
-	.sdram_config_init              = 0x61851AB2,
-	.sdram_config                   = 0x61851AB2,
+	.sdram_config_init              = 0x61862B32,
+	.sdram_config                   = 0x61862B32,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
-	.sdram_tim1                     = 0xCCCF36B3,
-	.sdram_tim2                     = 0x308F7FDA,
-	.sdram_tim3                     = 0x027F88A8,
+	.ref_ctrl                       = 0x0000493E,
+	.ref_ctrl_final			= 0x0000144A,
+	.sdram_tim1                     = 0xD113781C,
+	.sdram_tim2                     = 0x308F7FE3,
+	.sdram_tim3                     = 0x009F86A8,
 	.read_idle_ctrl                 = 0x00050000,
 	.zq_config                      = 0x0007190B,
 	.temp_alert_config              = 0x00000000,
-	.emif_ddr_phy_ctlr_1_init       = 0x0024400A,
-	.emif_ddr_phy_ctlr_1            = 0x0024400A,
+	.emif_ddr_phy_ctlr_1_init       = 0x0E24400D,
+	.emif_ddr_phy_ctlr_1            = 0x0E24400D,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
 	.emif_ddr_ext_phy_ctrl_2        = 0x00A400A4,
 	.emif_ddr_ext_phy_ctrl_3        = 0x00A900A9,
@@ -420,22 +423,22 @@
 
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
-	0x00BB00BB,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
+	0x00980098,
+	0x00340034,
+	0x00350035,
+	0x00340034,
+	0x00310031,
+	0x00340034,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
+	0x00480048,
+	0x004A004A,
+	0x00520052,
+	0x00550055,
+	0x00500050,
 	0x00000000,
 	0x00600020,
 	0x40010080,
@@ -449,22 +452,22 @@
 
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
-	0x00BB00BB,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
+	0x00980098,
+	0x00330033,
+	0x00330033,
+	0x002F002F,
+	0x00320032,
+	0x00310031,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
+	0x00520052,
+	0x00520052,
+	0x00470047,
+	0x00490049,
+	0x00500050,
 	0x00000000,
 	0x00600020,
 	0x40010080,
diff --git a/arch/arm/cpu/armv7/rmobile/Kconfig b/arch/arm/cpu/armv7/rmobile/Kconfig
index 6d94199..3586650 100644
--- a/arch/arm/cpu/armv7/rmobile/Kconfig
+++ b/arch/arm/cpu/armv7/rmobile/Kconfig
@@ -21,6 +21,9 @@
 config TARGET_ALT
 	bool "Alt board"
 
+config TARGET_SILK
+	bool "Silk board"
+
 endchoice
 
 config SYS_SOC
@@ -28,7 +31,7 @@
 
 config RMOBILE_EXTRAM_BOOT
 	bool "Enable boot from RAM"
-	depends on TARGET_ALT || TARGET_KOELSCH || TARGET_LAGER
+	depends on TARGET_ALT || TARGET_KOELSCH || TARGET_LAGER || TARGET_SILK
 	default n
 
 source "board/atmark-techno/armadillo-800eva/Kconfig"
@@ -37,5 +40,6 @@
 source "board/renesas/lager/Kconfig"
 source "board/kmc/kzm9g/Kconfig"
 source "board/renesas/alt/Kconfig"
+source "board/renesas/silk/Kconfig"
 
 endif
diff --git a/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S b/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S
index d47546a..a5dbbea 100644
--- a/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S
+++ b/arch/arm/cpu/armv7/rmobile/lowlevel_init_ca15.S
@@ -40,7 +40,7 @@
 	and	r1, r1, #0x7F00
 	lsrs	r1, r1, #8
 	cmp	r1, #0x4C		/* 0x4C is ID of r8a7794 */
-	beq	_exit_init_l2_a15
+	beq	_enable_actlr_smp
 
 	/* surpress wfe if ca15 */
 	tst r4, #4
@@ -64,6 +64,16 @@
 	orrne r0, r0, #0x20		/* L2CTLR[5] */
 #endif
 	mcrne p15, 1, r0, c9, c0, 2
+
+	b	_exit_init_l2_a15
+
+_enable_actlr_smp: /* R8A7794 only (CA7) */
+#ifndef CONFIG_DCACHE_OFF
+	mrc    p15, 0, r0, c1, c0, 1
+	orr    r0, r0, #0x40
+	mcr    p15, 0, r0, c1, c0, 1
+#endif
+
 _exit_init_l2_a15:
 	ldr	r3, =(CONFIG_SYS_INIT_SP_ADDR)
 	sub	sp, r3, #4
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index fdc05b9..9b49ece 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -31,9 +31,12 @@
  *************************************************************************/
 
 	.globl	reset
+	.globl	save_boot_params_ret
 
 reset:
-	bl	save_boot_params
+	/* Allow the board to save important registers */
+	b	save_boot_params
+save_boot_params_ret:
 	/*
 	 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
 	 * except if in HYP mode already
@@ -52,10 +55,10 @@
  * Continue to use ROM code vector only in OMAP4 spl)
  */
 #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
-	/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
-	mrc	p15, 0, r0, c1, c0, 0	@ Read CP15 SCTRL Register
+	/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
+	mrc	p15, 0, r0, c1, c0, 0	@ Read CP15 SCTLR Register
 	bic	r0, #CR_V		@ V = 0
-	mcr	p15, 0, r0, c1, c0, 0	@ Write CP15 SCTRL Register
+	mcr	p15, 0, r0, c1, c0, 0	@ Write CP15 SCTLR Register
 
 	/* Set vector address in CP15 VBAR register */
 	ldr	r0, =_start
@@ -96,7 +99,7 @@
  *
  *************************************************************************/
 ENTRY(save_boot_params)
-	bx	lr			@ back to my caller
+	b	save_boot_params_ret		@ back to my caller
 ENDPROC(save_boot_params)
 	.weak	save_boot_params
 
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 1c4b763..4bb12ad 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -11,12 +11,15 @@
 obj-y	+= board.o
 obj-y	+= clock.o
 obj-y	+= cpu_info.o
+obj-y	+= dram_helpers.o
 obj-y	+= pinmux.o
 obj-y	+= usbc.o
 obj-$(CONFIG_MACH_SUN6I)	+= prcm.o
 obj-$(CONFIG_MACH_SUN8I)	+= prcm.o
+obj-$(CONFIG_MACH_SUN9I)	+= prcm.o
 obj-$(CONFIG_MACH_SUN6I)	+= p2wi.o
 obj-$(CONFIG_MACH_SUN8I)	+= rsb.o
+obj-$(CONFIG_MACH_SUN9I)	+= rsb.o
 obj-$(CONFIG_MACH_SUN4I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN5I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN6I)	+= clock_sun6i.o
@@ -36,7 +39,5 @@
 obj-$(CONFIG_MACH_SUN6I)	+= dram_sun6i.o
 obj-$(CONFIG_MACH_SUN7I)	+= dram_sun4i.o
 obj-$(CONFIG_MACH_SUN8I)	+= dram_sun8i.o
-ifdef CONFIG_SPL_FEL
-obj-y	+= start.o
-endif
+obj-y	+= fel_utils.o
 endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index 6e28bcd..c02c015 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -27,6 +27,17 @@
 
 #include <linux/compiler.h>
 
+struct fel_stash {
+	uint32_t sp;
+	uint32_t lr;
+	uint32_t cpsr;
+	uint32_t sctlr;
+	uint32_t vbar;
+	uint32_t cr;
+};
+
+struct fel_stash fel_stash __attribute__((section(".data")));
+
 static int gpio_init(void)
 {
 #if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
@@ -65,6 +76,12 @@
 	return 0;
 }
 
+void spl_board_load_image(void)
+{
+	debug("Returning to FEL sp=%x, lr=%x\n", fel_stash.sp, fel_stash.lr);
+	return_to_fel(fel_stash.sp, fel_stash.lr);
+}
+
 void s_init(void)
 {
 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
@@ -95,7 +112,34 @@
  */
 u32 spl_boot_device(void)
 {
-	return BOOT_DEVICE_MMC1;
+#ifdef CONFIG_SPL_FEL
+	/*
+	 * This is the legacy compile time configuration for a special FEL
+	 * enabled build. It has many restrictions and can only boot over USB.
+	 */
+	return BOOT_DEVICE_BOARD;
+#else
+	/*
+	 * When booting from the SD card, the "eGON.BT0" signature is expected
+	 * to be found in memory at the address 0x0004 (see the "mksunxiboot"
+	 * tool, which generates this header).
+	 *
+	 * When booting in the FEL mode over USB, this signature is patched in
+	 * memory and replaced with something else by the 'fel' tool. This other
+	 * signature is selected in such a way, that it can't be present in a
+	 * valid bootable SD card image (because the BROM would refuse to
+	 * execute the SPL in this case).
+	 *
+	 * This branch is just making a decision at runtime whether to load
+	 * the main u-boot binary from the SD card (if the "eGON.BT0" signature
+	 * is found) or return to the FEL code in the BROM to wait and receive
+	 * the main u-boot binary over USB.
+	 */
+	if (readl(4) == 0x4E4F4765 && readl(8) == 0x3054422E) /* eGON.BT0 */
+		return BOOT_DEVICE_MMC1;
+	else
+		return BOOT_DEVICE_BOARD;
+#endif
 }
 
 /* No confirmation data available in SPL yet. Hardcode bootmode */
diff --git a/arch/arm/cpu/armv7/sunxi/config.mk b/arch/arm/cpu/armv7/sunxi/config.mk
index 00f5ffc..76ffec9 100644
--- a/arch/arm/cpu/armv7/sunxi/config.mk
+++ b/arch/arm/cpu/armv7/sunxi/config.mk
@@ -1,8 +1,6 @@
 # Build a combined spl + u-boot image
 ifdef CONFIG_SPL
 ifndef CONFIG_SPL_BUILD
-ifndef CONFIG_SPL_FEL
 ALL-y += u-boot-sunxi-with-spl.bin
 endif
 endif
-endif
diff --git a/arch/arm/cpu/armv7/sunxi/dram_helpers.c b/arch/arm/cpu/armv7/sunxi/dram_helpers.c
new file mode 100644
index 0000000..9a94e1b
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram_helpers.c
@@ -0,0 +1,37 @@
+/*
+ * DRAM init helper functions
+ *
+ * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/dram.h>
+
+/*
+ * Wait up to 1s for value to be set in given part of reg.
+ */
+void mctl_await_completion(u32 *reg, u32 mask, u32 val)
+{
+	unsigned long tmo = timer_get_us() + 1000000;
+
+	while ((readl(reg) & mask) != val) {
+		if (timer_get_us() > tmo)
+			panic("Timeout initialising DRAM\n");
+	}
+}
+
+/*
+ * Test if memory at offset offset matches memory at begin of DRAM
+ */
+bool mctl_mem_matches(u32 offset)
+{
+	/* Try to write different values to RAM at two addresses */
+	writel(0, CONFIG_SYS_SDRAM_BASE);
+	writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
+	/* Check if the same value is actually observed when reading back */
+	return readl(CONFIG_SYS_SDRAM_BASE) ==
+	       readl(CONFIG_SYS_SDRAM_BASE + offset);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/fel_utils.S b/arch/arm/cpu/armv7/sunxi/fel_utils.S
new file mode 100644
index 0000000..bf00335
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/fel_utils.S
@@ -0,0 +1,42 @@
+/*
+ * Utility functions for FEL mode.
+ *
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r0, =fel_stash
+	str	sp, [r0, #0]
+	str	lr, [r0, #4]
+	mrs	lr, cpsr		@ Read CPSR
+	str	lr, [r0, #8]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 SCTLR Register
+	str	lr, [r0, #12]
+	mrc	p15, 0, lr, c12, c0, 0	@ Read VBAR
+	str	lr, [r0, #16]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 Control Register
+	str	lr, [r0, #20]
+	b	save_boot_params_ret
+ENDPROC(save_boot_params)
+
+ENTRY(return_to_fel)
+	mov	sp, r0
+	mov	lr, r1
+	ldr	r0, =fel_stash
+	ldr	r1, [r0, #20]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 Control Register
+	ldr	r1, [r0, #16]
+	mcr	p15, 0, r1, c12, c0, 0	@ Write VBAR
+	ldr	r1, [r0, #12]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 SCTLR Register
+	ldr	r1, [r0, #8]
+	msr	cpsr, r1		@ Write CPSR
+	bx	lr
+ENDPROC(return_to_fel)
diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
index b72bb9d..b00befb 100644
--- a/arch/arm/cpu/armv7/sunxi/rsb.c
+++ b/arch/arm/cpu/armv7/sunxi/rsb.c
@@ -16,14 +16,27 @@
 #include <asm/arch/prcm.h>
 #include <asm/arch/rsb.h>
 
+static int rsb_set_device_mode(void);
+
 static void rsb_cfg_io(void)
 {
+#ifdef CONFIG_MACH_SUN8I
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
 	sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
 	sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
 	sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
 	sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
+#elif defined CONFIG_MACH_SUN9I
+	sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN0_R_RSB_SCK);
+	sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN1_R_RSB_SDA);
+	sunxi_gpio_set_pull(SUNXI_GPN(0), 1);
+	sunxi_gpio_set_pull(SUNXI_GPN(1), 1);
+	sunxi_gpio_set_drv(SUNXI_GPN(0), 2);
+	sunxi_gpio_set_drv(SUNXI_GPN(1), 2);
+#else
+#error unsupported MACH_SUNXI
+#endif
 }
 
 static void rsb_set_clk(void)
@@ -42,7 +55,7 @@
 	writel((cd_odly << 8) | div, &rsb->ccr);
 }
 
-void rsb_init(void)
+int rsb_init(void)
 {
 	struct sunxi_rsb_reg * const rsb =
 		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
@@ -54,6 +67,8 @@
 
 	writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);
 	rsb_set_clk();
+
+	return rsb_set_device_mode();
 }
 
 static int rsb_await_trans(void)
@@ -88,13 +103,14 @@
 	return ret;
 }
 
-int rsb_set_device_mode(u32 device_mode_data)
+static int rsb_set_device_mode(void)
 {
 	struct sunxi_rsb_reg * const rsb =
 		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
 	unsigned long tmo = timer_get_us() + 1000000;
 
-	writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
+	writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA,
+	       &rsb->dmcr);
 
 	while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
 		if (timer_get_us() > tmo)
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
deleted file mode 100644
index 928b7c1..0000000
--- a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * (C) Copyright 2013
- * Henrik Nordstrom <henrik@henriknordstrom.net>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(s_init)
-SECTIONS
-{
-	. = 0x00002000;
-
-	. = ALIGN(4);
-	.text :
-	{
-		*(.text.s_init)
-		*(.text*)
-	}
-
-	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
-
-	. = ALIGN(4);
-	.data : {
-		*(.data*)
-	}
-
-	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
-	}
-
-	. = ALIGN(4);
-	. = .;
-
-	. = ALIGN(4);
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
-	}
-
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
-	. = ALIGN(4);
-	.note.gnu.build-id :
-	{
-		*(.note.gnu.build-id)
-	}
-	_end = .;
-
-	. = ALIGN(4096);
-	.mmutable : {
-		*(.mmutable)
-	}
-
-	.bss_start __rel_dyn_start (OVERLAY) : {
-		KEEP(*(.__bss_start));
-		__bss_base = .;
-	}
-
-	.bss __bss_base (OVERLAY) : {
-		*(.bss*)
-		. = ALIGN(4);
-		__bss_limit = .;
-	}
-
-	.bss_end __bss_limit (OVERLAY) : {
-		KEEP(*(.__bss_end));
-	}
-
-	/DISCARD/ : { *(.dynstr*) }
-	/DISCARD/ : { *(.dynamic*) }
-	/DISCARD/ : { *(.plt*) }
-	/DISCARD/ : { *(.interp*) }
-	/DISCARD/ : { *(.gnu*) }
-	/DISCARD/ : { *(.note*) }
-}
diff --git a/arch/arm/cpu/armv7/tegra-common/Kconfig b/arch/arm/cpu/armv7/tegra-common/Kconfig
deleted file mode 100644
index 1446452..0000000
--- a/arch/arm/cpu/armv7/tegra-common/Kconfig
+++ /dev/null
@@ -1,28 +0,0 @@
-if TEGRA
-
-choice
-	prompt "Tegra SoC select"
-
-config TEGRA20
-	bool "Tegra20 family"
-
-config TEGRA30
-	bool "Tegra30 family"
-
-config TEGRA114
-	bool "Tegra114 family"
-
-config TEGRA124
-	bool "Tegra124 family"
-
-endchoice
-
-config USE_PRIVATE_LIBGCC
-	default y if SPL_BUILD
-
-source "arch/arm/cpu/armv7/tegra20/Kconfig"
-source "arch/arm/cpu/armv7/tegra30/Kconfig"
-source "arch/arm/cpu/armv7/tegra114/Kconfig"
-source "arch/arm/cpu/armv7/tegra124/Kconfig"
-
-endif
diff --git a/arch/arm/cpu/armv7/tegra-common/Makefile b/arch/arm/cpu/armv7/tegra-common/Makefile
deleted file mode 100644
index 463c260..0000000
--- a/arch/arm/cpu/armv7/tegra-common/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# (C) Copyright 2010,2011 Nvidia Corporation.
-#
-# (C) Copyright 2000-2003
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
diff --git a/arch/arm/cpu/armv7/tegra20/Makefile b/arch/arm/cpu/armv7/tegra20/Makefile
deleted file mode 100644
index 9b4295c..0000000
--- a/arch/arm/cpu/armv7/tegra20/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# (C) Copyright 2010,2011 Nvidia Corporation.
-#
-# (C) Copyright 2000-2003
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-$(CONFIG_PWM_TEGRA) += pwm.o
-obj-$(CONFIG_VIDEO_TEGRA) += display.o
diff --git a/arch/arm/cpu/armv7/uniphier/Kconfig b/arch/arm/cpu/armv7/uniphier/Kconfig
index 0556e4b..1a47ac9 100644
--- a/arch/arm/cpu/armv7/uniphier/Kconfig
+++ b/arch/arm/cpu/armv7/uniphier/Kconfig
@@ -48,23 +48,20 @@
 
 endchoice
 
+config SYS_MALLOC_F
+	default y
+
+config SYS_MALLOC_F_LEN
+	default 0x2000
+
 config CMD_PINMON
 	bool "Enable boot mode pins monitor command"
-	depends on !SPL_BUILD
 	default y
 	help
 	  The command "pinmon" shows the state of the boot mode pins.
 	  The boot mode pins are latched when the system reset is deasserted
 	  and determine which device the system should load a boot image from.
 
-config SOC_INIT
-	bool
-	default SPL_BUILD
-
-config DRAM_INIT
-	bool
-	default SPL_BUILD
-
 config CMD_DDRPHY_DUMP
 	bool "Enable dump command of DDR PHY parameters"
 	depends on !SPL_BUILD
@@ -74,7 +71,7 @@
 
 choice
 	prompt "DDR3 Frequency select"
-	depends on DRAM_INIT
+	depends on SPL_BUILD
 
 config DDR_FREQ_1600
 	bool "DDR3 1600"
diff --git a/arch/arm/cpu/armv7/uniphier/Makefile b/arch/arm/cpu/armv7/uniphier/Makefile
index 0546232..df418dd 100644
--- a/arch/arm/cpu/armv7/uniphier/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/Makefile
@@ -2,23 +2,32 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_SPL_BUILD) += lowlevel_init.o init_page_table.o
-obj-$(CONFIG_SPL_BUILD) += spl.o
+ifdef CONFIG_SPL_BUILD
 
-obj-y += timer.o
-obj-y += reset.o
-obj-y += cache_uniphier.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o
-obj-y += dram_init.o
-obj-$(CONFIG_DRAM_INIT) += ddrphy_training.o
+obj-y += lowlevel_init.o
+obj-y += init_page_table.o
+obj-y += spl.o
+obj-y += ddrphy_training.o
+
+else
+
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o
+obj-$(CONFIG_MISC_INIT_F) += print_misc_info.o
+obj-y += dram_init.o
+obj-y += board_common.o
 obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o
 obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o
+obj-y += reset.o
+obj-y += cache_uniphier.o
 obj-$(CONFIG_UNIPHIER_SMP) += smp.o
 obj-$(CONFIG_CMD_PINMON) += cmd_pinmon.o
 obj-$(CONFIG_CMD_DDRPHY_DUMP) += cmd_ddrphy.o
 
-obj-y += board_common.o
+endif
+
+obj-y += timer.o
+
 obj-$(CONFIG_PFC_MICRO_SUPPORT_CARD) += support_card.o
 obj-$(CONFIG_DCC_MICRO_SUPPORT_CARD) += support_card.o
 
diff --git a/arch/arm/cpu/armv7/uniphier/board_early_init_f.c b/arch/arm/cpu/armv7/uniphier/board_early_init_f.c
new file mode 100644
index 0000000..d25bbae
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/board_early_init_f.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/arch/led.h>
+#include <asm/arch/board.h>
+
+void pin_init(void);
+
+int board_early_init_f(void)
+{
+	led_write(U, 0, , );
+
+	pin_init();
+
+	led_write(U, 1, , );
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv7/uniphier/board_postclk_init.c b/arch/arm/cpu/armv7/uniphier/board_postclk_init.c
deleted file mode 100644
index 89e44bb..0000000
--- a/arch/arm/cpu/armv7/uniphier/board_postclk_init.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <linux/compiler.h>
-#include <asm/arch/led.h>
-#include <asm/arch/board.h>
-
-void __weak bcu_init(void)
-{
-};
-void sbc_init(void);
-void sg_init(void);
-void pll_init(void);
-void pin_init(void);
-void clkrst_init(void);
-
-int board_postclk_init(void)
-{
-#ifdef CONFIG_SOC_INIT
-	bcu_init();
-
-	sbc_init();
-
-	sg_init();
-
-	uniphier_board_reset();
-
-	pll_init();
-
-	uniphier_board_init();
-
-	led_write(B, 1, , );
-
-	clkrst_init();
-
-	led_write(B, 2, , );
-#endif
-	pin_init();
-
-	led_write(B, 3, , );
-
-	return 0;
-}
diff --git a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
index 3561b40..3c1b325 100644
--- a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
+++ b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
@@ -11,20 +11,17 @@
 
 static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	struct boot_device_info *table;
-	u32 mode_sel, n = 0;
-
-	mode_sel = get_boot_mode_sel();
+	int mode_sel, i;
 
 	printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF");
 
+	mode_sel = get_boot_mode_sel();
+
 	puts("Boot Mode Pin:\n");
 
-	for (table = boot_device_table; strlen(table->info); table++) {
-		printf(" %c %02x %s\n", n == mode_sel ? '*' : ' ', n,
-		       table->info);
-		n++;
-	}
+	for (i = 0; boot_device_table[i].info; i++)
+		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
+		       boot_device_table[i].info);
 
 	return 0;
 }
diff --git a/arch/arm/cpu/armv7/uniphier/dram_init.c b/arch/arm/cpu/armv7/uniphier/dram_init.c
index 7de657b..4b8c938 100644
--- a/arch/arm/cpu/armv7/uniphier/dram_init.c
+++ b/arch/arm/cpu/armv7/uniphier/dram_init.c
@@ -1,37 +1,16 @@
 /*
- * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2012-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <asm/arch/led.h>
-
-int umc_init(void);
-void enable_dpll_ssc(void);
 
 int dram_init(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
 
-#ifdef CONFIG_DRAM_INIT
-	led_write(B, 4, , );
-
-	{
-		int res;
-
-		res = umc_init();
-		if (res < 0)
-			return res;
-	}
-	led_write(B, 5, , );
-
-	enable_dpll_ssc();
-#endif
-
-	led_write(B, 6, , );
-
 	return 0;
 }
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
index 0752906..72f4663 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
@@ -2,11 +2,13 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
-obj-y += boot-mode.o
+ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
-								clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
+obj-y += bcu_init.o sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+	pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
+obj-y += boot-mode.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c
deleted file mode 100644
index 27d772e..0000000
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-	puts("Board: PH1-LD4 Board\n");
-
-	return check_support_card();
-}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
index 8206e2a..e330fda 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
@@ -2,10 +2,13 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
-obj-y += boot-mode.o
+ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += sbc_init.o sg_init.o pll_init.o clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
+obj-y += sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+	pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
+obj-y += boot-mode.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c
deleted file mode 100644
index 325a4f6..0000000
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-	puts("Board: PH1-Pro4 Board\n");
-
-	return check_support_card();
-}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
index 33bccff..c31b74b 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
@@ -45,17 +45,17 @@
 	{BOOT_DEVICE_NONE, "Reserved"},
 	{BOOT_DEVICE_NONE, "Reserved"},
 	{BOOT_DEVICE_NONE, "Reserved"},
-	{BOOT_DEVICE_NONE, ""}
+	{ /* sentinel */ }
 };
 
-u32 get_boot_mode_sel(void)
+int get_boot_mode_sel(void)
 {
 	return (readl(SG_PINMON0) >> 1) & 0x1f;
 }
 
 u32 spl_boot_device(void)
 {
-	u32 boot_mode;
+	int boot_mode;
 
 	if (boot_is_swapped())
 		return BOOT_DEVICE_NOR;
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
index 0752906..72f4663 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
@@ -2,11 +2,13 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
-obj-y += boot-mode.o
+ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
-								clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
+obj-y += bcu_init.o sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+	pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
+obj-y += boot-mode.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c
deleted file mode 100644
index 15dc289..0000000
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-	puts("Board: PH1-sLD8 Board\n");
-
-	return check_support_card();
-}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
index 2b6403f..5e80335 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
@@ -26,6 +26,15 @@
 	sg_set_pinsel(111, 1);	/* SBI0 -> RXD3 */
 #endif
 
+#ifdef CONFIG_SYS_I2C_UNIPHIER
+	{
+		u32 tmp;
+		tmp = readl(SG_IECTRL);
+		tmp |= 0xc00; /* enable SCL0, SDA0, SCL1, SDA1 */
+		writel(tmp, SG_IECTRL);
+	}
+#endif
+
 #ifdef CONFIG_NAND_DENALI
 	sg_set_pinsel(15, 0);	/* XNFRE_GB -> XNFRE_GB */
 	sg_set_pinsel(16, 0);	/* XNFWE_GB -> XNFWE_GB */
diff --git a/arch/arm/cpu/armv7/uniphier/print_misc_info.c b/arch/arm/cpu/armv7/uniphier/print_misc_info.c
new file mode 100644
index 0000000..69cfab5
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/print_misc_info.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/arch/board.h>
+
+int misc_init_f(void)
+{
+	return check_support_card();
+}
diff --git a/arch/arm/cpu/armv7/uniphier/spl.c b/arch/arm/cpu/armv7/uniphier/spl.c
index 40d28ad..8a4eafc 100644
--- a/arch/arm/cpu/armv7/uniphier/spl.c
+++ b/arch/arm/cpu/armv7/uniphier/spl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Panasonic Corporation
+ * Copyright (C) 2013-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -7,11 +7,53 @@
 
 #include <common.h>
 #include <spl.h>
+#include <linux/compiler.h>
+#include <asm/arch/led.h>
+#include <asm/arch/board.h>
+
+void __weak bcu_init(void)
+{
+};
+void sbc_init(void);
+void sg_init(void);
+void pll_init(void);
+void pin_init(void);
+void clkrst_init(void);
+int umc_init(void);
+void enable_dpll_ssc(void);
 
 void spl_board_init(void)
 {
-#if defined(CONFIG_BOARD_POSTCLK_INIT)
-	board_postclk_init();
-#endif
-	dram_init();
+	bcu_init();
+
+	sbc_init();
+
+	sg_init();
+
+	uniphier_board_reset();
+
+	pll_init();
+
+	uniphier_board_init();
+
+	led_write(L, 0, , );
+
+	clkrst_init();
+
+	led_write(L, 1, , );
+
+	{
+		int res;
+
+		res = umc_init();
+		if (res < 0) {
+			while (1)
+				;
+		}
+	}
+	led_write(L, 2, , );
+
+	enable_dpll_ssc();
+
+	led_write(L, 3, , );
 }
diff --git a/arch/arm/cpu/at91-common/Makefile b/arch/arm/cpu/at91-common/Makefile
deleted file mode 100644
index 89e1577..0000000
--- a/arch/arm/cpu/at91-common/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# (C) Copyright 2013 Atmel Corporation
-#		     Bo Shen <voice.shen@atmel.com>
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-$(CONFIG_AT91_WANTS_COMMON_PHY) += phy.o
-ifneq ($(CONFIG_SPL_BUILD),)
-obj-$(CONFIG_AT91SAM9G20) += sdram.o spl_at91.o
-obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o
-obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o
-obj-y += spl.o
-endif
diff --git a/arch/arm/dts/exynos4.dtsi b/arch/arm/dts/exynos4.dtsi
index 77fad48..7de227c 100644
--- a/arch/arm/dts/exynos4.dtsi
+++ b/arch/arm/dts/exynos4.dtsi
@@ -51,56 +51,64 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <0 0 0>;
+		reg = <0x13860000 0x100>;
+		interrupts = <0 56 0>;
 	};
 
 	i2c@13870000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <1 1 0>;
+		reg = <0x13870000 0x100>;
+		interrupts = <1 57 0>;
 	};
 
 	i2c@13880000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <2 2 0>;
+		reg = <0x13880000 0x100>;
+		interrupts = <2 58 0>;
 	};
 
 	i2c@13890000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <3 3 0>;
+		reg = <0x13890000 0x100>;
+		interrupts = <3 59 0>;
 	};
 
 	i2c@138a0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <4 4 0>;
+		reg = <0x138a0000 0x100>;
+		interrupts = <4 60 0>;
 	};
 
 	i2c@138b0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <5 5 0>;
+		reg = <0x138b0000 0x100>;
+		interrupts = <5 61 0>;
 	};
 
 	i2c@138c0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <6 6 0>;
+		reg = <0x138c0000 0x100>;
+		interrupts = <6 62 0>;
 	};
 
 	i2c@138d0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
-		interrupts = <7 7 0>;
+		reg = <0x138d0000 0x100>;
+		interrupts = <7 63 0>;
 	};
 
 	sdhci@12510000 {
@@ -143,11 +151,4 @@
 		interrupts = <0 131 0>;
 	};
 
-	gpio: gpio {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
 };
diff --git a/arch/arm/dts/exynos4210-origen.dts b/arch/arm/dts/exynos4210-origen.dts
index dd2476c..3f87761 100644
--- a/arch/arm/dts/exynos4210-origen.dts
+++ b/arch/arm/dts/exynos4210-origen.dts
@@ -36,7 +36,7 @@
 	sdhci@12530000 {
 		samsung,bus-width = <4>;
 		samsung,timing = <1 2 3>;
-		cd-gpios = <&gpio 0xA2 0>;
+		cd-gpios = <&gpk2 2 0>;
 	};
 
 	sdhci@12540000 {
diff --git a/arch/arm/dts/exynos4210-trats.dts b/arch/arm/dts/exynos4210-trats.dts
index 8c7a2c3..36d02df 100644
--- a/arch/arm/dts/exynos4210-trats.dts
+++ b/arch/arm/dts/exynos4210-trats.dts
@@ -101,7 +101,7 @@
 	sdhci@12510000 {
 		samsung,bus-width = <8>;
 		samsung,timing = <1 3 3>;
-		pwr-gpios = <&gpio 146 0>;
+		pwr-gpios = <&gpk0 2 0>;
 	};
 
 	sdhci@12520000 {
@@ -111,7 +111,7 @@
 	sdhci@12530000 {
 		samsung,bus-width = <4>;
 		samsung,timing = <1 2 3>;
-		cd-gpios = <&gpio 284 0>;
+		cd-gpios = <&gpx3 4 0>;
 	};
 
 	sdhci@12540000 {
diff --git a/arch/arm/dts/exynos4210-universal_c210.dts b/arch/arm/dts/exynos4210-universal_c210.dts
index 808c3f7..16948c9 100644
--- a/arch/arm/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/dts/exynos4210-universal_c210.dts
@@ -24,7 +24,7 @@
 	sdhci@12510000 {
 		samsung,bus-width = <8>;
 		samsung,timing = <1 3 3>;
-		pwr-gpios = <&gpio 146 0>;
+		pwr-gpios = <&gpk0 2 0>;
 	};
 
 	sdhci@12520000 {
@@ -34,7 +34,7 @@
 	sdhci@12530000 {
 		samsung,bus-width = <4>;
 		samsung,timing = <1 2 3>;
-		cd-gpios = <&gpio 284 0>;
+		cd-gpios = <&gpx3 4 0>;
 	};
 
 	sdhci@12540000 {
@@ -43,10 +43,10 @@
 
 	soft-spi {
 		compatible = "u-boot,soft-spi";
-		cs-gpio = <&gpio 235 0>;	/* Y43 */
-		sclk-gpio = <&gpio 225 0>;	/* Y31 */
-		mosi-gpio = <&gpio 227 0>;	/* Y33 */
-		miso-gpio = <&gpio 224 0>;	/* Y30 */
+		cs-gpio = <&gpy4 3 0>;
+		sclk-gpio = <&gpy3 1 0>;
+		mosi-gpio = <&gpy3 3 0>;
+		miso-gpio = <&gpy3 0 0>;
 		spi-delay-us = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts
index c78efec..582f6e5 100644
--- a/arch/arm/dts/exynos4412-odroid.dts
+++ b/arch/arm/dts/exynos4412-odroid.dts
@@ -16,6 +16,13 @@
 
 	aliases {
 		i2c0 = "/i2c@13860000";
+		i2c1 = "/i2c@13870000";
+		i2c2 = "/i2c@13880000";
+		i2c3 = "/i2c@13890000";
+		i2c4 = "/i2c@138a0000";
+		i2c5 = "/i2c@138b0000";
+		i2c6 = "/i2c@138c0000";
+		i2c7 = "/i2c@138d0000";
 		serial0 = "/serial@13800000";
 		console = "/serial@13810000";
 		mmc2 = "sdhci@12530000";
@@ -51,7 +58,7 @@
 	sdhci@12530000 {
 		samsung,bus-width = <4>;
 		samsung,timing = <1 2 3>;
-		cd-gpios = <&gpio 122 0>;
+		cd-gpios = <&gpk2 2 0>;
 	};
 
 	sdhci@12540000 {
@@ -78,4 +85,9 @@
 			reg = <0x125B0000 0x100>;
 		};
 	};
+
+	emmc-reset {
+		compatible = "samsung,emmc-reset";
+		reset-gpio = <&gpk1 2 0>;
+	};
 };
diff --git a/arch/arm/dts/exynos4412-trats2.dts b/arch/arm/dts/exynos4412-trats2.dts
index 60e4515..dd238df 100644
--- a/arch/arm/dts/exynos4412-trats2.dts
+++ b/arch/arm/dts/exynos4412-trats2.dts
@@ -416,7 +416,7 @@
 	sdhci@12510000 {
 		samsung,bus-width = <8>;
 		samsung,timing = <1 3 3>;
-		pwr-gpios = <&gpio 0x6a 0>;
+		pwr-gpios = <&gpk0 4 0>;
 		status = "disabled";
 	};
 
@@ -427,7 +427,7 @@
 	sdhci@12530000 {
 		samsung,bus-width = <4>;
 		samsung,timing = <1 2 3>;
-		cd-gpios = <&gpio 0x7a 0>;
+		cd-gpios = <&gpk2 2 0>;
 	};
 
 	sdhci@12540000 {
@@ -437,7 +437,7 @@
 	dwmmc@12550000 {
 		samsung,bus-width = <8>;
 		samsung,timing = <2 1 0>;
-		pwr-gpios = <&gpio 0x6a 0>;
+		pwr-gpios = <&gpk0 4 0>;
 		fifoth_val = <0x203f0040>;
 		bus_hz = <400000000>;
 		div = <0x3>;
diff --git a/arch/arm/dts/exynos5.dtsi b/arch/arm/dts/exynos5.dtsi
index e539068..238acb8 100644
--- a/arch/arm/dts/exynos5.dtsi
+++ b/arch/arm/dts/exynos5.dtsi
@@ -6,6 +6,7 @@
  */
 
 #include "skeleton.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	compatible = "samsung,exynos5";
@@ -247,7 +248,4 @@
 		u-boot,dm-pre-reloc;
 		id = <3>;
 	};
-
-	gpio: gpio {
-	};
 };
diff --git a/arch/arm/dts/exynos5250-arndale.dts b/arch/arm/dts/exynos5250-arndale.dts
index 202f2ea..21c0a21 100644
--- a/arch/arm/dts/exynos5250-arndale.dts
+++ b/arch/arm/dts/exynos5250-arndale.dts
@@ -15,6 +15,14 @@
 	compatible = "samsung,arndale", "samsung,exynos5250";
 
 	aliases {
+		i2c0 = "/i2c@12c60000";
+		i2c1 = "/i2c@12c70000";
+		i2c2 = "/i2c@12c80000";
+		i2c3 = "/i2c@12c90000";
+		i2c4 = "/i2c@12ca0000";
+		i2c5 = "/i2c@12cb0000";
+		i2c6 = "/i2c@12cc0000";
+		i2c7 = "/i2c@12cd0000";
 		serial0 = "/serial@12C20000";
 		console = "/serial@12C20000";
 	};
diff --git a/arch/arm/dts/exynos5250-smdk5250.dts b/arch/arm/dts/exynos5250-smdk5250.dts
index 8850409..9273562 100644
--- a/arch/arm/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/dts/exynos5250-smdk5250.dts
@@ -146,6 +146,6 @@
 	};
 
 	ehci@12110000 {
-		samsung,vbus-gpio = <&gpio 0x316 0>; /* X26 */
+		samsung,vbus-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
 	};
 };
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts
index bac5015..7d8be69 100644
--- a/arch/arm/dts/exynos5250-snow.dts
+++ b/arch/arm/dts/exynos5250-snow.dts
@@ -44,7 +44,8 @@
 			reg = <0x1e>;
 			compatible = "google,cros-ec";
 			i2c-max-frequency = <100000>;
-			ec-interrupt = <&gpio 182 1>;
+			u-boot,i2c-offset-len = <0>;
+			ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
 		};
 
 		power-regulator@48 {
@@ -68,7 +69,7 @@
 			reg = <0>;
 			compatible = "google,cros-ec";
 			spi-max-frequency = <5000000>;
-			ec-interrupt = <&gpio 182 1>;
+			ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
 			optimise-flash-write;
 			status = "disabled";
 		};
@@ -76,7 +77,7 @@
 
 	sound@3830000 {
 		samsung,codec-type = "max98095";
-		codec-enable-gpio = <&gpio 0xb7 0>;
+		codec-enable-gpio = <&gpx1 7 GPIO_ACTIVE_HIGH>;
 	};
 
 	sound@12d60000 {
@@ -131,11 +132,11 @@
 	};
 
 	ehci@12110000 {
-		samsung,vbus-gpio = <&gpio 0xb1 0>; /* X11 */
+		samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	xhci@12000000 {
-		samsung,vbus-gpio = <&gpio 0xbf 0>; /* X27 */
+		samsung,vbus-gpio = <&gpx2 7 GPIO_ACTIVE_HIGH>;
 	};
 
 	tmu@10060000 {
diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts
index d1d8735..b801de9 100644
--- a/arch/arm/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/dts/exynos5420-peach-pit.dts
@@ -17,7 +17,7 @@
 		"google,peach", "samsung,exynos5420", "samsung,exynos5";
 
 	config {
-		google,bad-wake-gpios = <&gpio 0x56 0>; /* gpx0-6 */
+		google,bad-wake-gpios = <&gpx0 6 GPIO_ACTIVE_HIGH>;
 		hwid = "PIT TEST A-A 7848";
 		lazy-init = <1>;
 	};
@@ -108,7 +108,7 @@
 			spi-half-duplex;
 			spi-max-timeout-ms = <1100>;
 			spi-frame-header = <0xec>;
-			ec-interrupt = <&gpio 93 1>; /* GPX1_5 */
+			ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
 
 			/*
 			 * This describes the flash memory within the EC. Note
@@ -124,11 +124,11 @@
 	};
 
 	xhci@12000000 {
-		samsung,vbus-gpio = <&gpio 0x40 0>; /* H00 */
+		samsung,vbus-gpio = <&gph0 0 GPIO_ACTIVE_HIGH>;
 	};
 
 	xhci@12400000 {
-		samsung,vbus-gpio = <&gpio 0x41 0>; /* H01 */
+		samsung,vbus-gpio = <&gph0 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	fimd@14400000 {
diff --git a/arch/arm/dts/exynos5422-odroidxu3.dts b/arch/arm/dts/exynos5422-odroidxu3.dts
index 79a7acd..d0a8621 100644
--- a/arch/arm/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/dts/exynos5422-odroidxu3.dts
@@ -32,7 +32,7 @@
 	};
 
 	ehci@12110000 {
-		samsung,vbus-gpio = <&gpio 0x66 0>; /* X26 */
+		samsung,vbus-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
 	};
 
 	serial@12C20000 {
@@ -46,4 +46,9 @@
 	mmc@12220000 {
 		fifoth_val = <0x201f0020>;
 	};
+
+	emmc-reset {
+		compatible = "samsung,emmc-reset";
+		reset-gpio = <&gpd1 0 0>;
+	};
 };
diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts
index e7c380f..e4bc100 100644
--- a/arch/arm/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/dts/exynos5800-peach-pi.dts
@@ -17,7 +17,7 @@
 		"google,peach", "samsung,exynos5800", "samsung,exynos5";
 
 	config {
-		google,bad-wake-gpios = <&gpio 0x56 0>; /* gpx0-6 */
+		google,bad-wake-gpios = <&gpx0 6 GPIO_ACTIVE_HIGH>;
 		hwid = "PIT TEST A-A 7848";
 		lazy-init = <1>;
 	};
@@ -32,7 +32,7 @@
 		mem-manuf = "samsung";
 		mem-type = "ddr3";
 		clock-frequency = <800000000>;
-		arm-frequency = <1700000000>;
+		arm-frequency = <900000000>;
 	};
 
 	tmu@10060000 {
@@ -102,7 +102,7 @@
 			spi-half-duplex;
 			spi-max-timeout-ms = <1100>;
 			spi-frame-header = <0xec>;
-			ec-interrupt = <&gpio 93 1>; /* GPX1_5 */
+			ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
 
 			/*
 			 * This describes the flash memory within the EC. Note
@@ -118,11 +118,11 @@
 	};
 
 	xhci@12000000 {
-		samsung,vbus-gpio = <&gpio 0x40 0>; /* H00 */
+		samsung,vbus-gpio = <&gph0 0 GPIO_ACTIVE_HIGH>;
 	};
 
 	xhci@12400000 {
-		samsung,vbus-gpio = <&gpio 0x41 0>; /* H01 */
+		samsung,vbus-gpio = <&gph0 1 GPIO_ACTIVE_HIGH>;
 	};
 
 	fimd@14400000 {
diff --git a/arch/arm/dts/tegra114-dalmore.dts b/arch/arm/dts/tegra114-dalmore.dts
index 81ad212..51ff266 100644
--- a/arch/arm/dts/tegra114-dalmore.dts
+++ b/arch/arm/dts/tegra114-dalmore.dts
@@ -57,7 +57,7 @@
 	};
 
 	sdhci@78000400 {
-		cd-gpios = <&gpio 170 1>; /* gpio PV2 */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 		bus-width = <4>;
 		status = "okay";
 	};
@@ -68,8 +68,7 @@
 	};
 
 	usb@7d008000 {
-		/* SPDIF_IN: USB_VBUS_EN1 */
-		nvidia,vbus-gpio = <&gpio 86 0>;
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
 		status = "okay";
 	};
 };
diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index 51fef54..e7b66d8 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -303,8 +303,9 @@
 
 	sdhci@700b0400 {
 		status = "okay";
-		cd-gpios = <&gpio 170 1>; /* gpio PV2 */
-		power-gpios = <&gpio 136 0>; /* gpio PR0 */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+		wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -316,12 +317,12 @@
 	usb@7d000000 {
 		status = "okay";
 		dr_mode = "otg";
-		nvidia,vbus-gpio = <&gpio 108 0>; /* gpio PN4, USB_VBUS_EN0 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb@7d008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio 109 0>; /* gpio PN5, USB_VBUS_EN1 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
 	};
 
 	regulators {
diff --git a/arch/arm/dts/tegra124-venice2.dts b/arch/arm/dts/tegra124-venice2.dts
index f7ccfc5..9e93cf9 100644
--- a/arch/arm/dts/tegra124-venice2.dts
+++ b/arch/arm/dts/tegra124-venice2.dts
@@ -72,8 +72,9 @@
 
 	sdhci@700b0400 {
 		status = "okay";
-		cd-gpios = <&gpio 170 0>; /* gpio PV2 */
-		power-gpios = <&gpio 136 0>; /* gpio PR0 */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+		wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
 		bus-width = <4>;
 	};
 
@@ -85,11 +86,11 @@
 	usb@7d000000 {
 		status = "okay";
 		dr_mode = "otg";
-		nvidia,vbus-gpio = <&gpio 108 0>; /* gpio PN4, USB_VBUS_EN0 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb@7d008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio 109 0>; /* gpio PN5, USB_VBUS_EN1 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-colibri_t20_iris.dts b/arch/arm/dts/tegra20-colibri_t20_iris.dts
index 7cf08f4..3131b92 100644
--- a/arch/arm/dts/tegra20-colibri_t20_iris.dts
+++ b/arch/arm/dts/tegra20-colibri_t20_iris.dts
@@ -22,16 +22,16 @@
 	};
 
 	usb@c5004000 {
-		nvidia,phy-reset-gpio = <&gpio 169 0>; /* PV1 */
-		nvidia,vbus-gpio = <&gpio 217 0>; /* PBB1 */
+		nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(BB, 1) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb@c5008000 {
-		nvidia,vbus-gpio = <&gpio 178 1>; /* PW2 low-active */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>;
 	};
 
 	nand-controller@70008000 {
-		nvidia,wp-gpios = <&gpio 144 0>; /* PS0 */
+		nvidia,wp-gpios = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_HIGH>;
 		nvidia,width = <8>;
 		nvidia,timing = <15 100 25 80 25 10 15 10 100>;
 
@@ -43,7 +43,7 @@
 
 	sdhci@c8000600 {
 		status = "okay";
-		cd-gpios = <&gpio 23 1>; /* gpio PC7 */
+		cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>;
 		bus-width = <4>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-harmony.dts b/arch/arm/dts/tegra20-harmony.dts
index 982a14c..e6e4229 100644
--- a/arch/arm/dts/tegra20-harmony.dts
+++ b/arch/arm/dts/tegra20-harmony.dts
@@ -37,7 +37,7 @@
 	};
 
 	nand-controller@70008000 {
-		nvidia,wp-gpios = <&gpio 23 0>;		/* PC7 */
+		nvidia,wp-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_HIGH>;
 		nvidia,width = <8>;
 		nvidia,timing = <26 100 20 80 20 10 12 10 70>;
 		nand@0 {
@@ -67,22 +67,22 @@
 	};
 
 	usb@c5004000 {
-		nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+		nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) 0>;
 	};
 
 	sdhci@c8000200 {
 		status = "okay";
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-		power-gpios = <&gpio 155 0>; /* gpio PT3 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(T, 3) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
 	sdhci@c8000600 {
 		status = "okay";
-		cd-gpios = <&gpio 58 1>; /* gpio PH2 */
-		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
-		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		cd-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
 		bus-width = <8>;
 	};
 
@@ -100,10 +100,14 @@
 		vsyncx-active-high;
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 0 0>;
-		nvidia,backlight-enable-gpios = <&gpio 13 0>;	/* PB5 */
-		nvidia,lvds-shutdown-gpios = <&gpio 10 0>;	/* PB2 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>;	/* PW0 */
-		nvidia,panel-vdd-gpios = <&gpio 22 0>;		/* PC6 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(B, 5)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(B, 2)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,panel-vdd-gpios = <&gpio TEGRA_GPIO(C, 6)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <0 0 200 0 0>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-medcom-wide.dts b/arch/arm/dts/tegra20-medcom-wide.dts
index be2ed42..b6b57ab 100644
--- a/arch/arm/dts/tegra20-medcom-wide.dts
+++ b/arch/arm/dts/tegra20-medcom-wide.dts
@@ -73,9 +73,12 @@
 
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 0 500000>;
-		nvidia,backlight-enable-gpios = <&gpio 13 0>; /* PB5 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>; /* PW0 */
-		nvidia,lvds-shutdown-gpios = <&gpio 10 0>; /* PB2 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(B, 5)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(B, 2)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <0 0 0 0>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-paz00.dts b/arch/arm/dts/tegra20-paz00.dts
index 9d735b5..16381c3 100644
--- a/arch/arm/dts/tegra20-paz00.dts
+++ b/arch/arm/dts/tegra20-paz00.dts
@@ -61,9 +61,9 @@
 
 	sdhci@c8000000 {
 		status = "okay";
-		cd-gpios = <&gpio 173 1>; /* gpio PV5 */
-		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-		power-gpios = <&gpio 169 0>; /* gpio PV1 */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -86,10 +86,14 @@
 		hsync-active-high;
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 0 0>;
-		nvidia,backlight-enable-gpios = <&gpio 164 0>;	/* PU4 */
-		nvidia,lvds-shutdown-gpios = <&gpio 102 0>;	/* PM6 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>;	/* PW0 */
-		nvidia,panel-vdd-gpios = <&gpio 4 0>;		/* PA4 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(U, 4)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(M, 6)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,panel-vdd-gpios = <&gpio TEGRA_GPIO(A, 4)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <400 4 203 17 15>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-seaboard.dts b/arch/arm/dts/tegra20-seaboard.dts
index 43b9911..10f3992 100644
--- a/arch/arm/dts/tegra20-seaboard.dts
+++ b/arch/arm/dts/tegra20-seaboard.dts
@@ -65,7 +65,7 @@
 	};
 
 	nand-controller@70008000 {
-		nvidia,wp-gpios = <&gpio 59 0>;		/* PH3 */
+		nvidia,wp-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
 		nvidia,width = <8>;
 		nvidia,timing = <26 100 20 80 20 10 12 10 70>;
 		nand@0 {
@@ -151,7 +151,7 @@
 	};
 
 	usb@c5000000 {
-		nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
 		dr_mode = "otg";
 	};
 
@@ -161,9 +161,9 @@
 
 	sdhci@c8000400 {
 		status = "okay";
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -186,10 +186,14 @@
 		hsync-active-high;
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 2 0>;
-		nvidia,backlight-enable-gpios = <&gpio 28 0>;	/* PD4 */
-		nvidia,lvds-shutdown-gpios = <&gpio 10 0>;	/* PB2 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>;	/* PW0 */
-		nvidia,panel-vdd-gpios = <&gpio 22 0>;		/* PC6 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(D, 4)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(B, 2)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,panel-vdd-gpios = <&gpio TEGRA_GPIO(C, 6)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <400 4 203 17 15>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-tamonten.dtsi b/arch/arm/dts/tegra20-tamonten.dtsi
index f379622..78449e6 100644
--- a/arch/arm/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/dts/tegra20-tamonten.dtsi
@@ -14,7 +14,8 @@
 			pll-supply = <&hdmi_pll_reg>;
 
 			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
-			nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7)
+				GPIO_ACTIVE_HIGH>;
 		};
 	};
 
@@ -280,7 +281,7 @@
 	};
 
 	nand-controller@70008000 {
-		nvidia,wp-gpios = <&gpio 23 0>; /* PC7 */
+		nvidia,wp-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_HIGH>;
 		nvidia,width = <8>;
 		nvidia,timing = <26 100 20 80 20 10 12 10 70>;
 
@@ -476,8 +477,8 @@
 	};
 
 	sdhci@c8000600 {
-		cd-gpios = <&gpio 58 1>; /* gpio PH2 */
-		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
+		cd-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 		status = "okay";
 	};
diff --git a/arch/arm/dts/tegra20-tec.dts b/arch/arm/dts/tegra20-tec.dts
index e99bd44..94ba6dc 100644
--- a/arch/arm/dts/tegra20-tec.dts
+++ b/arch/arm/dts/tegra20-tec.dts
@@ -73,9 +73,12 @@
 
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 0 500000>;
-		nvidia,backlight-enable-gpios = <&gpio 13 0>; /* PB5 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>; /* PW0 */
-		nvidia,lvds-shutdown-gpios = <&gpio 10 0>; /* PB2 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(B, 5)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(B, 2)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <0 0 0 0>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
index 1637cbd..27b118f 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -62,7 +62,7 @@
 	};
 
 	usb@c5000000 {
-		nvidia,vbus-gpio = <&gpio 170 0>; /* PV2 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb@c5004000 {
@@ -76,8 +76,8 @@
 
 	sdhci@c8000600 {
 		status = "okay";
-		cd-gpios = <&gpio 121 1>; /* gpio PP1 */
-		wp-gpios = <&gpio 122 0>; /* gpio PP2 */
+		cd-gpios = <&gpio TEGRA_GPIO(P, 1) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -111,7 +111,7 @@
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
 			enable-active-high;
-			gpio = <&gpio TEGRA_GPIO(V, 2) 0>;
+			gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 			regulator-always-on;
 			regulator-boot-on;
 		};
diff --git a/arch/arm/dts/tegra20-ventana.dts b/arch/arm/dts/tegra20-ventana.dts
index 6812203..939e567 100644
--- a/arch/arm/dts/tegra20-ventana.dts
+++ b/arch/arm/dts/tegra20-ventana.dts
@@ -61,9 +61,9 @@
 
 	sdhci@c8000400 {
 		status = "okay";
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -86,10 +86,14 @@
 		vsync-active-high;
 		nvidia,bits-per-pixel = <16>;
 		nvidia,pwm = <&pwm 2 0>;
-		nvidia,backlight-enable-gpios = <&gpio 28 0>;	/* PD4 */
-		nvidia,lvds-shutdown-gpios = <&gpio 10 0>;	/* PB2 */
-		nvidia,backlight-vdd-gpios = <&gpio 176 0>;	/* PW0 */
-		nvidia,panel-vdd-gpios = <&gpio 22 0>;		/* PC6 */
+		nvidia,backlight-enable-gpios = <&gpio TEGRA_GPIO(D, 4)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,lvds-shutdown-gpios = <&gpio TEGRA_GPIO(B, 2)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,backlight-vdd-gpios = <&gpio TEGRA_GPIO(W, 0)
+							GPIO_ACTIVE_HIGH>;
+		nvidia,panel-vdd-gpios = <&gpio TEGRA_GPIO(C, 6)
+							GPIO_ACTIVE_HIGH>;
 		nvidia,panel-timings = <0 0 200 0 0>;
 	};
 };
diff --git a/arch/arm/dts/tegra20-whistler.dts b/arch/arm/dts/tegra20-whistler.dts
index 4fd2496..c4a28eb 100644
--- a/arch/arm/dts/tegra20-whistler.dts
+++ b/arch/arm/dts/tegra20-whistler.dts
@@ -66,7 +66,7 @@
 
 	sdhci@c8000400 {
 		status = "okay";
-		wp-gpios = <&gpio 173 0>; /* gpio PV5 */
+		wp-gpios = <&gpio TEGRA_GPIO(V, 5) GPIO_ACTIVE_HIGH>;
 		bus-width = <8>;
 	};
 
diff --git a/arch/arm/dts/tegra30-apalis.dts b/arch/arm/dts/tegra30-apalis.dts
index 5bad3e7..15db0f2 100644
--- a/arch/arm/dts/tegra30-apalis.dts
+++ b/arch/arm/dts/tegra30-apalis.dts
@@ -243,13 +243,13 @@
 	sdhci@78000000 {
 		status = "okay";
 		bus-width = <4>;
-		cd-gpios = <&gpio 229 1>; /* PCC5, SD1_CD# */
+		cd-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_HIGH>;
 	};
 
 	sdhci@78000400 {
 		status = "okay";
 		bus-width = <8>;
-		cd-gpios = <&gpio 171 1>; /* PV3, MMC1_CD# */
+		cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
 	};
 
 	sdhci@78000600 {
@@ -262,20 +262,20 @@
 	usb@7d000000 {
 		status = "okay";
 		dr_mode = "peripheral";
-		nvidia,vbus-gpio = <&gpio 157 0>;	/* PT5, USBO1_EN */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>;
 	};
 
 	/* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
 	usb@7d004000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio 233 0>;	/* PDD1, USBH_EN */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
 		phy_type = "utmi";
 	};
 
 	/* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
 	usb@7d008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio 233 0>;	/* PDD1, USBH_EN */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
 	};
 
 	regulators {
diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
index 5903af6..ae83636 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -196,9 +196,9 @@
 
 	sdhci@78000000 {
 		status = "okay";
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
-		power-gpios = <&gpio 31 0>; /* gpio PD7 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(T, 3) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(D, 7) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -210,11 +210,11 @@
 	usb@7d000000 {
 		status = "okay";
 		dr_mode = "otg";
-		nvidia,vbus-gpio = <&gpio 238 0>; /* gpio DD6, PEX_L1_CLKREQ */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
 	};
 
 	usb@7d008000 {
-		nvidia,vbus-gpio = <&gpio 236 0>; /* PDD4 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
 		status = "okay";
 	};
 
diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index e13d0fb..23ca141 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -185,9 +185,9 @@
 
 	sdhci@78000000 {
 		status = "okay";
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
-		power-gpios = <&gpio 31 0>; /* gpio PD7 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(T, 3) GPIO_ACTIVE_HIGH>;
+		power-gpios = <&gpio TEGRA_GPIO(D, 7) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
@@ -197,7 +197,7 @@
 	};
 
 	usb@7d008000 {
-		nvidia,vbus-gpio = <&gpio 236 0>;	/* PDD4 */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
 		status = "okay";
 	};
 
diff --git a/arch/arm/dts/tegra30-colibri.dts b/arch/arm/dts/tegra30-colibri.dts
index 37b6abd..6cd1902 100644
--- a/arch/arm/dts/tegra30-colibri.dts
+++ b/arch/arm/dts/tegra30-colibri.dts
@@ -64,7 +64,7 @@
 	sdhci@78000200 {
 		status = "okay";
 		bus-width = <4>;
-		cd-gpios = <&gpio 23 1>; /* PC7, MMCD */
+		cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>;
 	};
 
 	sdhci@78000600 {
@@ -83,12 +83,12 @@
 	usb@7d004000 {
 		status = "okay";
 		phy_type = "utmi";
-		nvidia,vbus-gpio = <&gpio 234 0>;	/* PDD2, VBUS_LAN */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>;
 	};
 
 	/* EHCI instance 2: USB3_DP/N -> USBH_P/N */
 	usb@7d008000 {
 		status = "okay";
-		nvidia,vbus-gpio = <&gpio 178 1>;	/* PW2, USBH_PEN */
+		nvidia,vbus-gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>;
 	};
 };
diff --git a/arch/arm/dts/tegra30-tamonten.dtsi b/arch/arm/dts/tegra30-tamonten.dtsi
index c73afef..8eff627 100644
--- a/arch/arm/dts/tegra30-tamonten.dtsi
+++ b/arch/arm/dts/tegra30-tamonten.dtsi
@@ -55,8 +55,8 @@
 
 	/* SD slot on the base board */
 	sdhci@78000400 {
-		cd-gpios = <&gpio 69 1>; /* gpio PI5 */
-		wp-gpios = <&gpio 67 0>; /* gpio PI3 */
+		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+		wp-gpios = <&gpio TEGRA_GPIO(I, 3) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 	};
 
diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
index 6855878..d479be1 100644
--- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-LD4 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-ld4.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
 	model = "Panasonic UniPhier PH1-LD4 Reference Board";
@@ -46,10 +47,6 @@
 
 &i2c0 {
 	status = "okay";
-	eeprom {
-		compatible = "i2c-eeprom";
-		reg = <0x50>;
-	};
 };
 
 &usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
index 1227b62..d9e7a8c 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-Pro4 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-pro4.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
 	model = "Panasonic UniPhier PH1-Pro4 Reference Board";
@@ -48,10 +49,6 @@
 
 &i2c0 {
 	status = "okay";
-	eeprom {
-		compatible = "i2c-eeprom";
-		reg = <0x50>;
-	};
 };
 
 &usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
index fefc592..8a7f90a 100644
--- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-sLD3 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-sld3.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
 	model = "Panasonic UniPhier PH1-sLD3 Reference Board";
@@ -45,10 +46,6 @@
 
 &i2c0 {
 	status = "okay";
-	eeprom {
-		compatible = "i2c-eeprom";
-		reg = <0x50>;
-	};
 };
 
 &usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
index 9b6d95c..0cb9c47 100644
--- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-sLD8 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-sld8.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
 	model = "Panasonic UniPhier PH1-sLD8 Reference Board";
@@ -46,10 +47,6 @@
 
 &i2c0 {
 	status = "okay";
-	eeprom {
-		compatible = "i2c-eeprom";
-		reg = <0x50>;
-	};
 };
 
 &usb0 {
diff --git a/arch/arm/dts/uniphier-ref-daughter.dtsi b/arch/arm/dts/uniphier-ref-daughter.dtsi
new file mode 100644
index 0000000..0145b51
--- /dev/null
+++ b/arch/arm/dts/uniphier-ref-daughter.dtsi
@@ -0,0 +1,16 @@
+/*
+ * Device Tree Source for UniPhier Reference Daughter Board
+ *
+ * Copyright (C) 2014-2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+&i2c0 {
+	eeprom {
+		compatible = "i2c-eeprom";
+		reg = <0x50>;
+		u-boot,i2c-offset-len = <2>;
+	};
+};
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index b94b56c..523d22e 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -400,6 +400,8 @@
 struct cm_dpll {
 	unsigned int resv1;
 	unsigned int clktimer2clk;	/* offset 0x04 */
+	unsigned int resv2[11];
+	unsigned int clkselmacclk;	/* offset 0x34 */ 
 };
 #endif /* CONFIG_AM43XX */
 
diff --git a/arch/arm/include/asm/arch-armada-xp/config.h b/arch/arm/include/asm/arch-armada-xp/config.h
index 00ee775..f9fd424 100644
--- a/arch/arm/include/asm/arch-armada-xp/config.h
+++ b/arch/arm/include/asm/arch-armada-xp/config.h
@@ -31,7 +31,11 @@
 #endif /* CONFIG_SYS_KWD_CONFIG */
 
 /* Add target to build it automatically upon "make" */
+#ifdef CONFIG_SPL
+#define CONFIG_BUILD_TARGET	"u-boot-spl.kwb"
+#else
 #define CONFIG_BUILD_TARGET	"u-boot.kwb"
+#endif
 
 /* end of 16M scrubbed by training in bootrom */
 #define CONFIG_SYS_INIT_SP_ADDR		0x00FF0000
diff --git a/arch/arm/include/asm/arch-armada-xp/cpu.h b/arch/arm/include/asm/arch-armada-xp/cpu.h
index 6b60c21..4f5ff96 100644
--- a/arch/arm/include/asm/arch-armada-xp/cpu.h
+++ b/arch/arm/include/asm/arch-armada-xp/cpu.h
@@ -96,6 +96,9 @@
 	u32 irq_level;
 };
 
+/* Needed for dynamic (board-specific) mbus configuration */
+extern struct mvebu_mbus_state mbus_state;
+
 /*
  * functions
  */
@@ -103,5 +106,18 @@
 unsigned int mvebu_sdram_bs(enum memory_bank bank);
 void mvebu_sdram_size_adjust(enum memory_bank bank);
 int mvebu_mbus_probe(struct mbus_win windows[], int count);
+
+/*
+ * Highspeed SERDES PHY config init, ported from bin_hdr
+ * to mainline U-Boot
+ */
+int serdes_phy_config(void);
+
+/*
+ * DDR3 init / training code ported from Marvell bin_hdr. Now
+ * available in mainline U-Boot in:
+ * drivers/ddr/mvebu/
+ */
+int ddr3_init(void);
 #endif /* __ASSEMBLY__ */
 #endif /* _ARMADA_XP_CPU_H */
diff --git a/arch/arm/include/asm/arch-at91/at91cap9.h b/arch/arm/include/asm/arch-at91/at91cap9.h
deleted file mode 100644
index 63870bc..0000000
--- a/arch/arm/include/asm/arch-at91/at91cap9.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * [origin: Linux kernel include/asm-arm/arch-at91/at91cap9.h]
- *
- *  Copyright (C) 2007 Stelian Pop <stelian@popies.net>
- *  Copyright (C) 2007 Lead Tech Design <www.leadtechdesign.com>
- *  Copyright (C) 2007 Atmel Corporation.
- *
- * Common definitions.
- * Based on AT91CAP9 datasheet revision B (Preliminary).
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef AT91CAP9_H
-#define AT91CAP9_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS		1	/* System Peripherals */
-#define AT91CAP9_ID_PIOABCD	2	/* Parallel IO Controller A, B, C and D */
-#define AT91CAP9_ID_MPB0	3	/* MP Block Peripheral 0 */
-#define AT91CAP9_ID_MPB1	4	/* MP Block Peripheral 1 */
-#define AT91CAP9_ID_MPB2	5	/* MP Block Peripheral 2 */
-#define AT91CAP9_ID_MPB3	6	/* MP Block Peripheral 3 */
-#define AT91CAP9_ID_MPB4	7	/* MP Block Peripheral 4 */
-#define AT91CAP9_ID_US0		8	/* USART 0 */
-#define AT91CAP9_ID_US1		9	/* USART 1 */
-#define AT91CAP9_ID_US2		10	/* USART 2 */
-#define AT91CAP9_ID_MCI0	11	/* Multimedia Card Interface 0 */
-#define AT91CAP9_ID_MCI1	12	/* Multimedia Card Interface 1 */
-#define AT91CAP9_ID_CAN		13	/* CAN */
-#define AT91CAP9_ID_TWI		14	/* Two-Wire Interface */
-#define AT91CAP9_ID_SPI0	15	/* Serial Peripheral Interface 0 */
-#define AT91CAP9_ID_SPI1	16	/* Serial Peripheral Interface 0 */
-#define AT91CAP9_ID_SSC0	17	/* Serial Synchronous Controller 0 */
-#define AT91CAP9_ID_SSC1	18	/* Serial Synchronous Controller 1 */
-#define AT91CAP9_ID_AC97C	19	/* AC97 Controller */
-#define AT91CAP9_ID_TCB		20	/* Timer Counter 0, 1 and 2 */
-#define AT91CAP9_ID_PWMC	21	/* Pulse Width Modulation Controller */
-#define AT91CAP9_ID_EMAC	22	/* Ethernet */
-#define AT91CAP9_ID_AESTDES	23	/* Advanced Encryption Standard, Triple DES */
-#define AT91CAP9_ID_ADC		24	/* Analog-to-Digital Converter */
-#define AT91CAP9_ID_ISI		25	/* Image Sensor Interface */
-#define AT91CAP9_ID_LCDC	26	/* LCD Controller */
-#define AT91CAP9_ID_DMA		27	/* DMA Controller */
-#define AT91CAP9_ID_UDPHS	28	/* USB High Speed Device Port */
-#define AT91CAP9_ID_UHP		29	/* USB Host Port */
-#define AT91CAP9_ID_IRQ0	30	/* Advanced Interrupt Controller (IRQ0) */
-#define AT91CAP9_ID_IRQ1	31	/* Advanced Interrupt Controller (IRQ1) */
-
-#define AT91_PIO_BASE	0xfffff200
-#define AT91_PMC_BASE	0xfffffc00
-#define AT91_RSTC_BASE	0xfffffd00
-#define AT91_PIT_BASE	0xfffffd30
-
-/*
- * Internal Memory.
- */
-#define AT91CAP9_SRAM_BASE	0x00100000	/* Internal SRAM base address */
-#define AT91CAP9_SRAM_SIZE	(32 * SZ_1K)	/* Internal SRAM size (32Kb) */
-
-#define AT91CAP9_ROM_BASE	0x00400000	/* Internal ROM base address */
-#define AT91CAP9_ROM_SIZE	(32 * SZ_1K)	/* Internal ROM size (32Kb) */
-
-#define AT91CAP9_LCDC_BASE	0x00500000	/* LCD Controller */
-#define AT91CAP9_UDPHS_BASE	0x00600000	/* USB High Speed Device Port */
-#define AT91CAP9_UHP_BASE	0x00700000	/* USB Host controller */
-
-#define CONFIG_DRAM_BASE	AT91_CHIPSELECT_6
-
-/*
- * Cpu Name
- */
-#define CONFIG_SYS_AT91_CPU_NAME	"AT91CAP9"
-
-#endif
diff --git a/arch/arm/include/asm/arch-at91/at91cap9_matrix.h b/arch/arm/include/asm/arch-at91/at91cap9_matrix.h
deleted file mode 100644
index 009a19d..0000000
--- a/arch/arm/include/asm/arch-at91/at91cap9_matrix.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * [origin: Linux kernel include/asm-arm/arch-at91/at91cap9_matrix.h]
- *
- *  Copyright (C) 2007 Stelian Pop <stelian@popies.net>
- *  Copyright (C) 2007 Lead Tech Design <www.leadtechdesign.com>
- *  Copyright (C) 2006 Atmel Corporation.
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91CAP9 datasheet revision B (Preliminary).
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef AT91CAP9_MATRIX_H
-#define AT91CAP9_MATRIX_H
-
-#define AT91_MATRIX_MCFG0	(AT91_MATRIX + 0x00)	/* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1	(AT91_MATRIX + 0x04)	/* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2	(AT91_MATRIX + 0x08)	/* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3	(AT91_MATRIX + 0x0C)	/* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4	(AT91_MATRIX + 0x10)	/* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5	(AT91_MATRIX + 0x14)	/* Master Configuration Register 5 */
-#define AT91_MATRIX_MCFG6	(AT91_MATRIX + 0x18)	/* Master Configuration Register 6 */
-#define AT91_MATRIX_MCFG7	(AT91_MATRIX + 0x1C)	/* Master Configuration Register 7 */
-#define AT91_MATRIX_MCFG8	(AT91_MATRIX + 0x20)	/* Master Configuration Register 8 */
-#define AT91_MATRIX_MCFG9	(AT91_MATRIX + 0x24)	/* Master Configuration Register 9 */
-#define AT91_MATRIX_MCFG10	(AT91_MATRIX + 0x28)	/* Master Configuration Register 10 */
-#define AT91_MATRIX_MCFG11	(AT91_MATRIX + 0x2C)	/* Master Configuration Register 11 */
-#define		AT91_MATRIX_ULBT	(7 << 0)	/* Undefined Length Burst Type */
-#define			AT91_MATRIX_ULBT_INFINITE	(0 << 0)
-#define			AT91_MATRIX_ULBT_SINGLE		(1 << 0)
-#define			AT91_MATRIX_ULBT_FOUR		(2 << 0)
-#define			AT91_MATRIX_ULBT_EIGHT		(3 << 0)
-#define			AT91_MATRIX_ULBT_SIXTEEN	(4 << 0)
-
-#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x40)	/* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x44)	/* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x48)	/* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x4C)	/* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x50)	/* Slave Configuration Register 4 */
-#define AT91_MATRIX_SCFG5	(AT91_MATRIX + 0x54)	/* Slave Configuration Register 5 */
-#define AT91_MATRIX_SCFG6	(AT91_MATRIX + 0x58)	/* Slave Configuration Register 6 */
-#define AT91_MATRIX_SCFG7	(AT91_MATRIX + 0x5C)	/* Slave Configuration Register 7 */
-#define AT91_MATRIX_SCFG8	(AT91_MATRIX + 0x60)	/* Slave Configuration Register 8 */
-#define AT91_MATRIX_SCFG9	(AT91_MATRIX + 0x64)	/* Slave Configuration Register 9 */
-#define		AT91_MATRIX_SLOT_CYCLE		(0xff << 0)	/* Maximum Number of Allowed Cycles for a Burst */
-#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */
-#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16)
-#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16)
-#define		AT91_MATRIX_FIXED_DEFMSTR	(0xf  << 18)	/* Fixed Index of Default Master */
-#define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */
-#define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24)
-#define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24)
-
-#define AT91_MATRIX_PRAS0	(AT91_MATRIX + 0x80)	/* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRBS0	(AT91_MATRIX + 0x84)	/* Priority Register B for Slave 0 */
-#define AT91_MATRIX_PRAS1	(AT91_MATRIX + 0x88)	/* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRBS1	(AT91_MATRIX + 0x8C)	/* Priority Register B for Slave 1 */
-#define AT91_MATRIX_PRAS2	(AT91_MATRIX + 0x90)	/* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRBS2	(AT91_MATRIX + 0x94)	/* Priority Register B for Slave 2 */
-#define AT91_MATRIX_PRAS3	(AT91_MATRIX + 0x98)	/* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRBS3	(AT91_MATRIX + 0x9C)	/* Priority Register B for Slave 3 */
-#define AT91_MATRIX_PRAS4	(AT91_MATRIX + 0xA0)	/* Priority Register A for Slave 4 */
-#define AT91_MATRIX_PRBS4	(AT91_MATRIX + 0xA4)	/* Priority Register B for Slave 4 */
-#define AT91_MATRIX_PRAS5	(AT91_MATRIX + 0xA8)	/* Priority Register A for Slave 5 */
-#define AT91_MATRIX_PRBS5	(AT91_MATRIX + 0xAC)	/* Priority Register B for Slave 5 */
-#define AT91_MATRIX_PRAS6	(AT91_MATRIX + 0xB0)	/* Priority Register A for Slave 6 */
-#define AT91_MATRIX_PRBS6	(AT91_MATRIX + 0xB4)	/* Priority Register B for Slave 6 */
-#define AT91_MATRIX_PRAS7	(AT91_MATRIX + 0xB8)	/* Priority Register A for Slave 7 */
-#define AT91_MATRIX_PRBS7	(AT91_MATRIX + 0xBC)	/* Priority Register B for Slave 7 */
-#define AT91_MATRIX_PRAS8	(AT91_MATRIX + 0xC0)	/* Priority Register A for Slave 8 */
-#define AT91_MATRIX_PRBS8	(AT91_MATRIX + 0xC4)	/* Priority Register B for Slave 8 */
-#define AT91_MATRIX_PRAS9	(AT91_MATRIX + 0xC8)	/* Priority Register A for Slave 9 */
-#define AT91_MATRIX_PRBS9	(AT91_MATRIX + 0xCC)	/* Priority Register B for Slave 9 */
-#define		AT91_MATRIX_M0PR		(3 << 0)	/* Master 0 Priority */
-#define		AT91_MATRIX_M1PR		(3 << 4)	/* Master 1 Priority */
-#define		AT91_MATRIX_M2PR		(3 << 8)	/* Master 2 Priority */
-#define		AT91_MATRIX_M3PR		(3 << 12)	/* Master 3 Priority */
-#define		AT91_MATRIX_M4PR		(3 << 16)	/* Master 4 Priority */
-#define		AT91_MATRIX_M5PR		(3 << 20)	/* Master 5 Priority */
-#define		AT91_MATRIX_M6PR		(3 << 24)	/* Master 6 Priority */
-#define		AT91_MATRIX_M7PR		(3 << 28)	/* Master 7 Priority */
-#define		AT91_MATRIX_M8PR		(3 << 0)	/* Master 8 Priority (in Register B) */
-#define		AT91_MATRIX_M9PR		(3 << 4)	/* Master 9 Priority (in Register B) */
-#define		AT91_MATRIX_M10PR		(3 << 8)	/* Master 10 Priority (in Register B) */
-#define		AT91_MATRIX_M11PR		(3 << 12)	/* Master 11 Priority (in Register B) */
-
-#define AT91_MATRIX_MRCR	(AT91_MATRIX + 0x100)	/* Master Remap Control Register */
-#define		AT91_MATRIX_RCB0		(1 << 0)	/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-#define		AT91_MATRIX_RCB2		(1 << 2)
-#define		AT91_MATRIX_RCB3		(1 << 3)
-#define		AT91_MATRIX_RCB4		(1 << 4)
-#define		AT91_MATRIX_RCB5		(1 << 5)
-#define		AT91_MATRIX_RCB6		(1 << 6)
-#define		AT91_MATRIX_RCB7		(1 << 7)
-#define		AT91_MATRIX_RCB8		(1 << 8)
-#define		AT91_MATRIX_RCB9		(1 << 9)
-#define		AT91_MATRIX_RCB10		(1 << 10)
-#define		AT91_MATRIX_RCB11		(1 << 11)
-
-#define AT91_MPBS0_SFR		(AT91_MATRIX + 0x114)	/* MPBlock Slave 0 Special Function Register */
-#define AT91_MPBS1_SFR		(AT91_MATRIX + 0x11C)	/* MPBlock Slave 1 Special Function Register */
-
-#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x120)	/* EBI Chip Select Assignment Register */
-#define		AT91_MATRIX_EBI_CS1A		(1 << 1)	/* Chip Select 1 Assignment */
-#define			AT91_MATRIX_EBI_CS1A_SMC		(0 << 1)
-#define			AT91_MATRIX_EBI_CS1A_BCRAMC		(1 << 1)
-#define		AT91_MATRIX_EBI_CS3A		(1 << 3)	/* Chip Select 3 Assignment */
-#define			AT91_MATRIX_EBI_CS3A_SMC		(0 << 3)
-#define			AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA	(1 << 3)
-#define		AT91_MATRIX_EBI_CS4A		(1 << 4)	/* Chip Select 4 Assignment */
-#define			AT91_MATRIX_EBI_CS4A_SMC		(0 << 4)
-#define			AT91_MATRIX_EBI_CS4A_SMC_CF1		(1 << 4)
-#define		AT91_MATRIX_EBI_CS5A		(1 << 5)	/* Chip Select 5 Assignment */
-#define			AT91_MATRIX_EBI_CS5A_SMC		(0 << 5)
-#define			AT91_MATRIX_EBI_CS5A_SMC_CF2		(1 << 5)
-#define		AT91_MATRIX_EBI_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
-#define		AT91_MATRIX_EBI_DQSPDC		(1 << 9)	/* Data Qualifier Strobe Pull-Down Configuration */
-#define		AT91_MATRIX_EBI_VDDIOMSEL	(1 << 16)	/* Memory voltage selection */
-#define			AT91_MATRIX_EBI_VDDIOMSEL_1_8V		(0 << 16)
-#define			AT91_MATRIX_EBI_VDDIOMSEL_3_3V		(1 << 16)
-
-#define AT91_MPBS2_SFR		(AT91_MATRIX + 0x12C)	/* MPBlock Slave 2 Special Function Register */
-#define AT91_MPBS3_SFR		(AT91_MATRIX + 0x130)	/* MPBlock Slave 3 Special Function Register */
-#define AT91_APB_SFR		(AT91_MATRIX + 0x134)	/* APB Bridge Special Function Register */
-
-#endif
diff --git a/arch/arm/include/asm/arch-bcm2835/gpio.h b/arch/arm/include/asm/arch-bcm2835/gpio.h
index db42896..c8ef8f5 100644
--- a/arch/arm/include/asm/arch-bcm2835/gpio.h
+++ b/arch/arm/include/asm/arch-bcm2835/gpio.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2012 Vikram Narayananan
  * <vikram186@gmail.com>
+ * (C) Copyright 2012,2015 Stephen Warren
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -8,7 +9,11 @@
 #ifndef _BCM2835_GPIO_H_
 #define _BCM2835_GPIO_H_
 
+#ifdef CONFIG_BCM2836
+#define BCM2835_GPIO_BASE		0x3f200000
+#else
 #define BCM2835_GPIO_BASE		0x20200000
+#endif
 #define BCM2835_GPIO_COUNT		54
 
 #define BCM2835_GPIO_FSEL_MASK		0x7
diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
index 88d2ec1..04bf480 100644
--- a/arch/arm/include/asm/arch-bcm2835/mbox.h
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2012 Stephen Warren
+ * (C) Copyright 2012,2015 Stephen Warren
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -38,7 +38,11 @@
 
 /* Raw mailbox HW */
 
+#ifdef CONFIG_BCM2836
+#define BCM2835_MBOX_PHYSADDR	0x3f00b880
+#else
 #define BCM2835_MBOX_PHYSADDR	0x2000b880
+#endif
 
 struct bcm2835_mbox_regs {
 	u32 read;
@@ -121,6 +125,9 @@
 
 #define BCM2835_MBOX_TAG_GET_BOARD_REV	0x00010002
 
+#ifdef CONFIG_BCM2836
+#define BCM2836_BOARD_REV_2_B		0x4
+#else
 /*
  * 0x2..0xf from:
  * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/
@@ -141,6 +148,7 @@
 #define BCM2835_BOARD_REV_B_PLUS	0x10
 #define BCM2835_BOARD_REV_CM		0x11
 #define BCM2835_BOARD_REV_A_PLUS	0x12
+#endif
 
 struct bcm2835_mbox_tag_get_board_rev {
 	struct bcm2835_mbox_tag_hdr tag_hdr;
diff --git a/arch/arm/include/asm/arch-bcm2835/sdhci.h b/arch/arm/include/asm/arch-bcm2835/sdhci.h
index a4f867b..2a21ccb 100644
--- a/arch/arm/include/asm/arch-bcm2835/sdhci.h
+++ b/arch/arm/include/asm/arch-bcm2835/sdhci.h
@@ -1,23 +1,17 @@
 /*
- * (C) Copyright 2012 Stephen Warren
+ * (C) Copyright 2012,2015 Stephen Warren
  *
- * 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
- * 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.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef _BCM2835_SDHCI_H_
 #define _BCM2835_SDHCI_H_
 
+#ifdef CONFIG_BCM2836
+#define BCM2835_SDHCI_BASE 0x3f300000
+#else
 #define BCM2835_SDHCI_BASE 0x20300000
+#endif
 
 int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq);
 
diff --git a/arch/arm/include/asm/arch-bcm2835/timer.h b/arch/arm/include/asm/arch-bcm2835/timer.h
index c2001b6..fc7aec7 100644
--- a/arch/arm/include/asm/arch-bcm2835/timer.h
+++ b/arch/arm/include/asm/arch-bcm2835/timer.h
@@ -1,23 +1,17 @@
 /*
- * (C) Copyright 2012 Stephen Warren
+ * (C) Copyright 2012,2015 Stephen Warren
  *
- * 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
- * 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.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef _BCM2835_TIMER_H
 #define _BCM2835_TIMER_H
 
+#ifdef CONFIG_BCM2836
+#define BCM2835_TIMER_PHYSADDR	0x3f003000
+#else
 #define BCM2835_TIMER_PHYSADDR	0x20003000
+#endif
 
 struct bcm2835_timer_regs {
 	u32 cs;
diff --git a/arch/arm/include/asm/arch-bcm2835/wdog.h b/arch/arm/include/asm/arch-bcm2835/wdog.h
index 303a65f..beb6a08 100644
--- a/arch/arm/include/asm/arch-bcm2835/wdog.h
+++ b/arch/arm/include/asm/arch-bcm2835/wdog.h
@@ -1,23 +1,17 @@
 /*
- * (C) Copyright 2012 Stephen Warren
+ * (C) Copyright 2012,2015 Stephen Warren
  *
- * 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
- * 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.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef _BCM2835_TIMER_H
 #define _BCM2835_TIMER_H
 
+#ifdef CONFIG_BCM2836
+#define BCM2835_WDOG_PHYSADDR			0x3f100000
+#else
 #define BCM2835_WDOG_PHYSADDR			0x20100000
+#endif
 
 struct bcm2835_wdog_regs {
 	u32 unknown0[7];
diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
index db24dc0..2a17dfc 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -26,6 +26,10 @@
 	EXYNOS_SRC_MPLL = 6,
 	EXYNOS_SRC_EPLL,
 	EXYNOS_SRC_VPLL,
+	EXYNOS542X_SRC_MPLL = 3,
+	EXYNOS542X_SRC_SPLL,
+	EXYNOS542X_SRC_EPLL = 6,
+	EXYNOS542X_SRC_RPLL,
 };
 
 unsigned long get_pll_clk(int pllreg);
diff --git a/arch/arm/include/asm/arch-exynos/pinmux.h b/arch/arm/include/asm/arch-exynos/pinmux.h
index 0b91ef6..d0ae757 100644
--- a/arch/arm/include/asm/arch-exynos/pinmux.h
+++ b/arch/arm/include/asm/arch-exynos/pinmux.h
@@ -23,6 +23,9 @@
 	/* Flags for SROM controller */
 	PINMUX_FLAG_BANK	= 3 << 0,       /* bank number (0-3) */
 	PINMUX_FLAG_16BIT	= 1 << 2,       /* 16-bit width */
+
+	/* Flags for I2C */
+	PINMUX_FLAG_HS_MODE	= 1 << 1,       /* I2C High Speed Mode */
 };
 
 /**
diff --git a/arch/arm/include/asm/arch-lpc32xx/config.h b/arch/arm/include/asm/arch-lpc32xx/config.h
index 8f6426b..564441c 100644
--- a/arch/arm/include/asm/arch-lpc32xx/config.h
+++ b/arch/arm/include/asm/arch-lpc32xx/config.h
@@ -1,7 +1,7 @@
 /*
  * Common definitions for LPC32XX board configurations
  *
- * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com>
+ * Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,6 +9,8 @@
 #ifndef _LPC32XX_CONFIG_H
 #define _LPC32XX_CONFIG_H
 
+#define CONFIG_SYS_GENERIC_BOARD
+
 /* Basic CPU architecture */
 #define CONFIG_ARCH_CPU_INIT
 
diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h
index c968600..ae88b6e 100644
--- a/arch/arm/include/asm/arch-mx6/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx6/imx-regs.h
@@ -88,8 +88,8 @@
 #define AIPS2_ARB_BASE_ADDR             0x02100000
 #define AIPS2_ARB_END_ADDR              0x021FFFFF
 #ifdef CONFIG_MX6SX
-#define AIPS3_BASE_ADDR			0x02200000
-#define AIPS3_END_ADDR			0x022FFFFF
+#define AIPS3_ARB_BASE_ADDR             0x02200000
+#define AIPS3_ARB_END_ADDR              0x022FFFFF
 #define WEIM_ARB_BASE_ADDR              0x50000000
 #define WEIM_ARB_END_ADDR               0x57FFFFFF
 #define QSPI0_AMBA_BASE                0x60000000
@@ -624,12 +624,16 @@
 	u32	rsvd1[3];
 	u32	uid_high;
 	u32	rsvd2[3];
-	u32	rsvd3[4];
-	u32	rsvd4[4];
-	u32	rsvd5[4];
+	u32	cfg2;
+	u32	rsvd3[3];
+	u32	cfg3;
+	u32	rsvd4[3];
+	u32	cfg4;
+	u32	rsvd5[3];
 	u32	cfg5;
 	u32	rsvd6[3];
-	u32	rsvd7[4];
+	u32	cfg6;
+	u32	rsvd7[3];
 };
 
 #ifdef CONFIG_MX6SX
diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
index 5ebabfa..8e0d7d1 100644
--- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
+++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
@@ -62,6 +62,49 @@
 	u32 mpmur0;
 };
 
+#define MX6SX_IOM_DDR_BASE	0x020e0200
+struct mx6sx_iomux_ddr_regs {
+	u32 res1[59];
+	u32 dram_dqm0;
+	u32 dram_dqm1;
+	u32 dram_dqm2;
+	u32 dram_dqm3;
+	u32 dram_ras;
+	u32 dram_cas;
+	u32 res2[2];
+	u32 dram_sdwe_b;
+	u32 dram_odt0;
+	u32 dram_odt1;
+	u32 dram_sdba0;
+	u32 dram_sdba1;
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdcke1;
+	u32 dram_sdclk_0;
+	u32 dram_sdqs0;
+	u32 dram_sdqs1;
+	u32 dram_sdqs2;
+	u32 dram_sdqs3;
+	u32 dram_reset;
+};
+
+#define MX6SX_IOM_GRP_BASE	0x020e0500
+struct mx6sx_iomux_grp_regs {
+	u32 res1[61];
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 grp_ddrpke;
+	u32 grp_ddrpk;
+	u32 grp_ddrhys;
+	u32 grp_ddrmode;
+	u32 grp_b0ds;
+	u32 grp_b1ds;
+	u32 grp_ctlds;
+	u32 grp_ddr_type;
+	u32 grp_b2ds;
+	u32 grp_b3ds;
+};
+
 /*
  * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
  */
@@ -243,6 +286,9 @@
 void mx6sdl_dram_iocfg(unsigned width,
 		       const struct mx6sdl_iomux_ddr_regs *,
 		       const struct mx6sdl_iomux_grp_regs *);
+void mx6sx_dram_iocfg(unsigned width,
+		      const struct mx6sx_iomux_ddr_regs *,
+		      const struct mx6sx_iomux_grp_regs *);
 
 /* configure mx6 mmdc registers */
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h
index 062f3de..4678723 100644
--- a/arch/arm/include/asm/arch-mxs/sys_proto.h
+++ b/arch/arm/include/asm/arch-mxs/sys_proto.h
@@ -74,6 +74,23 @@
 #endif
 };
 
+#define MXS_BM_USB			0x00
+#define MXS_BM_I2C_MASTER_3V3		0x01
+#define MXS_BM_I2C_MASTER_1V8		0x11
+#define MXS_BM_SPI2_MASTER_3V3_NOR	0x02
+#define MXS_BM_SPI2_MASTER_1V8_NOR	0x12
+#define MXS_BM_SPI3_MASTER_3V3_NOR	0x03
+#define MXS_BM_SPI3_MASTER_1V8_NOR	0x13
+#define MXS_BM_NAND_3V3			0x04
+#define MXS_BM_NAND_1V8			0x14
+#define MXS_BM_JTAG			0x06
+#define MXS_BM_SPI3_MASTER_3V3_EEPROM	0x08
+#define MXS_BM_SPI3_MASTER_1V8_EEPROM	0x18
+#define MXS_BM_SDMMC0_3V3		0x09
+#define MXS_BM_SDMMC0_1V8		0x19
+#define MXS_BM_SDMMC1_3V3		0x0a
+#define MXS_BM_SDMMC1_1V8		0x1a
+
 struct mxs_spl_data {
 	uint8_t		boot_mode_idx;
 	uint32_t	mem_dram_size;
diff --git a/arch/arm/include/asm/arch-omap3/mem.h b/arch/arm/include/asm/arch-omap3/mem.h
index 0b78c1c..3ce270c 100644
--- a/arch/arm/include/asm/arch-omap3/mem.h
+++ b/arch/arm/include/asm/arch-omap3/mem.h
@@ -249,6 +249,49 @@
 #define MICRON_RASWIDTH_200	14
 #define MICRON_V_MCFG_200(size)	MCFG((size), MICRON_RASWIDTH_200)
 
+/* Samsung K4X51163PG - FGC6 (165MHz optimized) 6.06ns - from 2010.90 src */
+#define SAMSUNG_TDAL_165	5
+#define SAMSUNG_TDPL_165	2
+#define SAMSUNG_TRRD_165	2
+#define SAMSUNG_TRCD_165	3
+#define SAMSUNG_TRP_165		3
+#define SAMSUNG_TRAS_165	7
+#define SAMSUNG_TRC_165		10
+#define SAMSUNG_TRFC_165	12
+
+#define SAMSUNG_V_ACTIMA_165	\
+		ACTIM_CTRLA(SAMSUNG_TRFC_165, SAMSUNG_TRC_165,		\
+				SAMSUNG_TRAS_165, SAMSUNG_TRP_165,	\
+				SAMSUNG_TRCD_165, SAMSUNG_TRRD_165,	\
+				SAMSUNG_TDPL_165, SAMSUNG_TDAL_165)
+
+#define SAMSUNG_TWTR_165	1
+#define SAMSUNG_TCKE_165	2
+#define SAMSUNG_XSR_165		20
+#define SAMSUNG_TXP_165		5
+
+#define SAMSUNG_V_ACTIMB_165	\
+		ACTIM_CTRLB(SAMSUNG_TWTR_165, SAMSUNG_TCKE_165,	\
+				SAMSUNG_TXP_165, SAMSUNG_XSR_165)
+
+#define SAMSUNG_RASWIDTH_165	14
+#define SAMSUNG_V_MCFG_165(size) \
+	V_MCFG_RASWIDTH(SAMSUNG_RASWIDTH_165) | V_MCFG_CASWIDTH_10B | \
+	V_MCFG_ADDRMUXLEGACY_FLEX | V_MCFG_RAMSIZE(size) | \
+	V_MCFG_BANKALLOCATION_RBC | V_MCFG_RAMTYPE_DDR
+
+/* TODO: find which register these were taken from */
+
+#define SAMSUNG_BL_165				0x2
+#define SAMSUNG_SIL_165				0x0
+#define SAMSUNG_CASL_165			0x3
+#define SAMSUNG_WBST_165			0x0
+#define SAMSUNG_V_MR_165			((SAMSUNG_WBST_165 << 9) | \
+		(SAMSUNG_CASL_165 << 4) | (SAMSUNG_SIL_165 << 3) | \
+		(SAMSUNG_BL_165))
+
+#define SAMSUNG_SHARING 0x00003700
+
 /* NUMONYX part of IGEP v2 (165MHz optimized) 6.06ns */
 #define NUMONYX_TDAL_165	6	/* Twr/Tck + Trp/tck		*/
 					/* 15/6 + 18/6 = 5.5 -> 6	*/
diff --git a/arch/arm/include/asm/arch-omap3/mmc_host_def.h b/arch/arm/include/asm/arch-omap3/mmc_host_def.h
index 0ba621a..9f2896c 100644
--- a/arch/arm/include/asm/arch-omap3/mmc_host_def.h
+++ b/arch/arm/include/asm/arch-omap3/mmc_host_def.h
@@ -51,6 +51,7 @@
 #define PBIASLITEPWRDNZ0		(1 << 1)
 #define PBIASSPEEDCTRL0			(1 << 2)
 #define PBIASLITEPWRDNZ1		(1 << 9)
+#define PBIASLITEVMODE0			(1 << 0)
 
 #define CTLPROGIO1SPEEDCTRL		(1 << 20)
 
diff --git a/arch/arm/include/asm/arch-omap3/mux.h b/arch/arm/include/asm/arch-omap3/mux.h
index eba4a5c..3277b40 100644
--- a/arch/arm/include/asm/arch-omap3/mux.h
+++ b/arch/arm/include/asm/arch-omap3/mux.h
@@ -15,6 +15,12 @@
  * PTU  - Pull type Up
  * DIS  - Pull type selection is inactive
  * EN   - Pull type selection is active
+ * SB_LOW - Standby mode configuration: Output low-level
+ * SB_HI - Standby mode configuration: Output high-level
+ * SB_HIZ - Standby mode configuration: Output hi-impedence
+ * SB_PD - Standby mode pull-down enabled
+ * SB_PU - Standby mode pull-up enabled
+ * WKEN - Wakeup input enabled
  * M0   - Mode 0
  */
 
@@ -26,6 +32,13 @@
 #define EN	(1 << 3)
 #define DIS	(0 << 3)
 
+#define SB_LOW (1 << 9)
+#define SB_HI (5 << 9)
+#define SB_HIZ (2 << 9)
+#define SB_PD (1 << 12)
+#define SB_PU (3 << 12)
+#define WKEN (1 << 14)
+
 #define M0	0
 #define M1	1
 #define M2	2
@@ -36,8 +49,8 @@
 #define M7	7
 
 /*
- * To get the actual address the offset has to added
- * with OMAP34XX_CTRL_BASE to get the actual address
+ * To get the actual address the offset has to be added
+ * to OMAP34XX_CTRL_BASE
  */
 
 /*SDRC*/
@@ -78,6 +91,33 @@
 #define CONTROL_PADCONF_SDRC_DQS1	0x0074
 #define CONTROL_PADCONF_SDRC_DQS2	0x0076
 #define CONTROL_PADCONF_SDRC_DQS3	0x0078
+#define CONTROL_PADCONF_SDRC_BA0	0x05A0
+#define CONTROL_PADCONF_SDRC_BA1	0x05A2
+#define CONTROL_PADCONF_SDRC_A0		0x05A4
+#define CONTROL_PADCONF_SDRC_A1		0x05A6
+#define CONTROL_PADCONF_SDRC_A2		0x05A8
+#define CONTROL_PADCONF_SDRC_A3		0x05AA
+#define CONTROL_PADCONF_SDRC_A4		0x05AC
+#define CONTROL_PADCONF_SDRC_A5		0x05AE
+#define CONTROL_PADCONF_SDRC_A6		0x05B0
+#define CONTROL_PADCONF_SDRC_A7		0x05B2
+#define CONTROL_PADCONF_SDRC_A8		0x05B4
+#define CONTROL_PADCONF_SDRC_A9		0x05B6
+#define CONTROL_PADCONF_SDRC_A10	0x05B8
+#define CONTROL_PADCONF_SDRC_A11	0x05BA
+#define CONTROL_PADCONF_SDRC_A12	0x05BC
+#define CONTROL_PADCONF_SDRC_A13	0x05BE
+#define CONTROL_PADCONF_SDRC_A14	0x05C0
+#define CONTROL_PADCONF_SDRC_NCS0	0x05C2
+#define CONTROL_PADCONF_SDRC_NCS1	0x05C4
+#define CONTROL_PADCONF_SDRC_NCLK	0x05C6
+#define CONTROL_PADCONF_SDRC_NRAS	0x05C8
+#define CONTROL_PADCONF_SDRC_NCAS	0x05CA
+#define CONTROL_PADCONF_SDRC_NWE	0x05CC
+#define CONTROL_PADCONF_SDRC_DM0	0x05CE
+#define CONTROL_PADCONF_SDRC_DM1	0x05D0
+#define CONTROL_PADCONF_SDRC_DM2	0x05D2
+#define CONTROL_PADCONF_SDRC_DM3	0x05D4
 /*GPMC*/
 #define CONTROL_PADCONF_GPMC_A1		0x007A
 #define CONTROL_PADCONF_GPMC_A2		0x007C
@@ -89,6 +129,7 @@
 #define CONTROL_PADCONF_GPMC_A8		0x0088
 #define CONTROL_PADCONF_GPMC_A9		0x008A
 #define CONTROL_PADCONF_GPMC_A10	0x008C
+#define CONTROL_PADCONF_GPMC_A11	0x0264
 #define CONTROL_PADCONF_GPMC_D0		0x008E
 #define CONTROL_PADCONF_GPMC_D1		0x0090
 #define CONTROL_PADCONF_GPMC_D2		0x0092
@@ -323,6 +364,8 @@
 #define CONTROL_PADCONF_ETK_D13_ES2	0x05F6
 #define CONTROL_PADCONF_ETK_D14_ES2	0x05F8
 #define CONTROL_PADCONF_ETK_D15_ES2	0x05FA
+#define CONTROL_PADCONF_JTAG_RTCK	0x0A4E
+#define CONTROL_PADCONF_JTAG_TDO	0x0A50
 /*Die to Die */
 #define CONTROL_PADCONF_D2D_MCAD0	0x01E4
 #define CONTROL_PADCONF_D2D_MCAD1	0x01E6
@@ -433,6 +476,10 @@
 #define CONTROL_PADCONF_SYS_BOOT8	0x0226
 
 /* AM/DM37xx specific */
+#define CONTROL_PADCONF_GPIO112		0x0134
+#define CONTROL_PADCONF_GPIO113		0x0136
+#define CONTROL_PADCONF_GPIO114		0x0138
+#define CONTROL_PADCONF_GPIO115		0x013A
 #define CONTROL_PADCONF_GPIO127		0x0A54
 #define CONTROL_PADCONF_GPIO126		0x0A56
 #define CONTROL_PADCONF_GPIO128		0x0A58
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index 34bd8c5..bcf92fb 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -23,6 +23,7 @@
 
 /* Board SDRC timing values */
 struct board_sdrc_timings {
+	u32 sharing;
 	u32 mcfg;
 	u32 ctrla;
 	u32 ctrlb;
diff --git a/arch/arm/include/asm/arch-omap5/clock.h b/arch/arm/include/asm/arch-omap5/clock.h
index 0dc584b..f8e5630 100644
--- a/arch/arm/include/asm/arch-omap5/clock.h
+++ b/arch/arm/include/asm/arch-omap5/clock.h
@@ -236,13 +236,20 @@
 #define VDD_MPU_ES2_LOW 880
 #define VDD_MM_ES2_LOW 880
 
-/* TPS659038 Voltage settings in mv for OPP_NOMINAL */
-#define VDD_MPU_DRA752		1090
+/* DRA74x/75x voltage settings in mv for OPP_NOM per DM */
+#define VDD_MPU_DRA752		1100
 #define VDD_EVE_DRA752		1060
 #define VDD_GPU_DRA752		1060
-#define VDD_CORE_DRA752		1030
+#define VDD_CORE_DRA752		1060
 #define VDD_IVA_DRA752		1060
 
+/* DRA72x voltage settings in mv for OPP_NOM per DM */
+#define VDD_MPU_DRA72x		1100
+#define VDD_EVE_DRA72x		1060
+#define VDD_GPU_DRA72x		1060
+#define VDD_CORE_DRA72x		1060
+#define VDD_IVA_DRA72x		1060
+
 /* Efuse register offsets for DRA7xx platform */
 #define DRA752_EFUSE_BASE	0x4A002000
 #define DRA752_EFUSE_REGBITS	16
@@ -284,6 +291,13 @@
 #define TPS659038_REG_ADDR_SMPS7		0x33
 #define TPS659038_REG_ADDR_SMPS8		0x37
 
+/* TPS65917 */
+#define TPS65917_I2C_SLAVE_ADDR		0x58
+#define TPS65917_REG_ADDR_SMPS1		0x23
+#define TPS65917_REG_ADDR_SMPS2		0x27
+#define TPS65917_REG_ADDR_SMPS3		0x2F
+
+
 /* TPS */
 #define TPS62361_I2C_SLAVE_ADDR		0x60
 #define TPS62361_REG_ADDR_SET0		0x0
diff --git a/arch/arm/include/asm/arch-pantheon/gpio.h b/arch/arm/include/asm/arch-pantheon/gpio.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/arch/arm/include/asm/arch-pantheon/gpio.h
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 05fbad3..c28ee05 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -144,7 +144,16 @@
 
 #define PLL1_CFG_DEFAULT	0xa1005000
 
+#if defined CONFIG_OLD_SUNXI_KERNEL_COMPAT && defined CONFIG_MACH_SUN5I
+/*
+ * Older linux-sunxi-3.4 kernels override our PLL6 setting with 300 MHz,
+ * halving the mbus frequency, so set it to 300 MHz ourselves and base the
+ * mbus divider on that.
+ */
+#define PLL6_CFG_DEFAULT	0xa1009900
+#else
 #define PLL6_CFG_DEFAULT	0xa1009911
+#endif
 
 /* nand clock */
 #define NAND_CLK_SRC_OSC24		0
@@ -305,6 +314,8 @@
 #define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2
 #define CCM_GMAC_CTRL_GPIT_MII (0x0 << 2)
 #define CCM_GMAC_CTRL_GPIT_RGMII (0x1 << 2)
+#define CCM_GMAC_CTRL_RX_CLK_DELAY(x)	((x) << 5)
+#define CCM_GMAC_CTRL_TX_CLK_DELAY(x)	((x) << 10)
 
 #define CCM_USB_CTRL_PHY0_RST (0x1 << 0)
 #define CCM_USB_CTRL_PHY1_RST (0x1 << 1)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index e101c54..8a80385 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -243,6 +243,8 @@
 #define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2
 #define CCM_GMAC_CTRL_GPIT_MII		(0x0 << 2)
 #define CCM_GMAC_CTRL_GPIT_RGMII	(0x1 << 2)
+#define CCM_GMAC_CTRL_RX_CLK_DELAY(x)	((x) << 5)
+#define CCM_GMAC_CTRL_TX_CLK_DELAY(x)	((x) << 10)
 
 #define MDFS_CLK_DEFAULT		0x81000002 /* PLL6 / 3 */
 
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index a2a7839..04889c5 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -73,7 +73,6 @@
 #define SUNXI_CCM_BASE			(REGS_APB0_BASE + 0x0000)
 #define SUNXI_CCMMODULE_BASE		(REGS_APB0_BASE + 0x0400)
 #define SUNXI_PIO_BASE			(REGS_APB0_BASE + 0x0800)
-#define SUNXI_R_PIO_BASE		(0x08002C00)
 #define SUNXI_TIMER_BASE		(REGS_APB0_BASE + 0x0C00)
 #define SUNXI_PWM_BASE			(REGS_APB0_BASE + 0x1400)
 #define SUNXI_LRADC_BASE		(REGS_APB0_BASE + 0x1800)
@@ -92,8 +91,10 @@
 #define SUNXI_TWI4_BASE			(REGS_APB1_BASE + 0x3800)
 
 /* RCPUS Module */
-#define SUNXI_RPRCM_BASE		(REGS_RCPUS_BASE + 0x1400)
+#define SUNXI_PRCM_BASE			(REGS_RCPUS_BASE + 0x1400)
 #define SUNXI_R_UART_BASE		(REGS_RCPUS_BASE + 0x2800)
+#define SUNXI_R_PIO_BASE		(REGS_RCPUS_BASE + 0x2c00)
+#define SUNXI_RSB_BASE			(REGS_RCPUS_BASE + 0x3400)
 
 /* Misc. */
 #define SUNXI_BROM_BASE			0xFFFF0000 /* 32K */
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 7ff43e6..aedd194 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -25,31 +25,7 @@
 #endif
 
 unsigned long sunxi_dram_init(void);
-
-/*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
-{
-	unsigned long tmo = timer_get_us() + 1000000;
-
-	while ((readl(reg) & mask) != val) {
-		if (timer_get_us() > tmo)
-			panic("Timeout initialising DRAM\n");
-	}
-}
-
-/*
- * Test if memory at offset offset matches memory at begin of DRAM
- */
-static inline bool mctl_mem_matches(u32 offset)
-{
-	/* Try to write different values to RAM at two addresses */
-	writel(0, CONFIG_SYS_SDRAM_BASE);
-	writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
-	/* Check if the same value is actually observed when reading back */
-	return readl(CONFIG_SYS_SDRAM_BASE) ==
-	       readl(CONFIG_SYS_SDRAM_BASE + offset);
-}
+void mctl_await_completion(u32 *reg, u32 mask, u32 val);
+bool mctl_mem_matches(u32 offset);
 
 #endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 71cc879..f2c247d 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -45,9 +45,13 @@
  *
  * sun8i has 1 bank:
  * PL0 - PL11
+ *
+ * sun9i has 3 banks:
+ * PL0 - PL9  | PM0 - PM15  | PN0 - PN1
  */
 #define SUNXI_GPIO_L	11
 #define SUNXI_GPIO_M	12
+#define SUNXI_GPIO_N	13
 
 struct sunxi_gpio {
 	u32 cfg[4];
@@ -114,6 +118,7 @@
 	SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H),
 	SUNXI_GPIO_L_START = 352,
 	SUNXI_GPIO_M_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_L),
+	SUNXI_GPIO_N_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_M),
 	SUNXI_GPIO_AXP0_START = 1024,
 };
 
@@ -129,6 +134,7 @@
 #define SUNXI_GPI(_nr)	(SUNXI_GPIO_I_START + (_nr))
 #define SUNXI_GPL(_nr)	(SUNXI_GPIO_L_START + (_nr))
 #define SUNXI_GPM(_nr)	(SUNXI_GPIO_M_START + (_nr))
+#define SUNXI_GPN(_nr)	(SUNXI_GPIO_N_START + (_nr))
 
 #define SUNXI_GPAXP0(_nr)	(SUNXI_GPIO_AXP0_START + (_nr))
 
@@ -187,6 +193,9 @@
 #define SUN8I_GPL2_R_UART_TX	2
 #define SUN8I_GPL3_R_UART_RX	2
 
+#define SUN9I_GPN0_R_RSB_SCK	3
+#define SUN9I_GPN1_R_RSB_SDA    3
+
 /* GPIO pin pull-up/down config */
 #define SUNXI_GPIO_PULL_DISABLE	0
 #define SUNXI_GPIO_PULL_UP	1
diff --git a/arch/arm/include/asm/arch-sunxi/rsb.h b/arch/arm/include/asm/arch-sunxi/rsb.h
index 95a595a..a893466 100644
--- a/arch/arm/include/asm/arch-sunxi/rsb.h
+++ b/arch/arm/include/asm/arch-sunxi/rsb.h
@@ -37,6 +37,7 @@
 #define RSB_STAT_TERR_INT		(1 << 1)
 #define RSB_STAT_LBSY_INT		(1 << 2)
 
+#define RSB_DMCR_DEVICE_MODE_DATA	0x7c3e00
 #define RSB_DMCR_DEVICE_MODE_START	(1 << 31)
 
 #define RSB_CMD_BYTE_WRITE		0x4e
@@ -46,8 +47,7 @@
 #define RSB_DEVADDR_RUNTIME_ADDR(x)	((x) << 16)
 #define RSB_DEVADDR_DEVICE_ADDR(x)	((x) << 0)
 
-void rsb_init(void);
-int rsb_set_device_mode(u32 device_mode_data);
+int rsb_init(void);
 int rsb_set_device_address(u16 device_addr, u16 runtime_addr);
 int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data);
 int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data);
diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
index c3e636e..60a5bd8 100644
--- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -13,4 +13,14 @@
 
 void sdelay(unsigned long);
 
+/* return_to_fel() - Return to BROM from SPL
+ *
+ * This returns back into the BROM after U-Boot SPL has performed its initial
+ * init. It uses the provided lr and sp to do so.
+ *
+ * @lr:		BROM link register value (return address)
+ * @sp:		BROM stack pointer
+ */
+void return_to_fel(uint32_t lr, uint32_t sp);
+
 #endif
diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index 84e7b55..a20bdaa 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -10,6 +10,7 @@
 #define __TEGRA_MMC_H_
 
 #include <fdtdec.h>
+#include <asm/gpio.h>
 
 /* for mmc_config definition */
 #include <mmc.h>
@@ -134,9 +135,9 @@
 	int enabled;		/* 1 to enable, 0 to disable */
 	int width;		/* Bus Width, 1, 4 or 8 */
 	enum periph_id mmc_id;	/* Peripheral ID: PERIPH_ID_... */
-	struct fdt_gpio_state cd_gpio;		/* Change Detect GPIO */
-	struct fdt_gpio_state pwr_gpio;		/* Power GPIO */
-	struct fdt_gpio_state wp_gpio;		/* Write Protect GPIO */
+	struct gpio_desc cd_gpio;	/* Change Detect GPIO */
+	struct gpio_desc pwr_gpio;	/* Power GPIO */
+	struct gpio_desc wp_gpio;	/* Write Protect GPIO */
 	unsigned int version;	/* SDHCI spec. version */
 	unsigned int clock;	/* Current clock (MHz) */
 	struct mmc_config cfg;	/* mmc configuration */
diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h
index a04c84e..6feeda3 100644
--- a/arch/arm/include/asm/arch-tegra20/display.h
+++ b/arch/arm/include/asm/arch-tegra20/display.h
@@ -10,6 +10,7 @@
 
 #include <asm/arch/dc.h>
 #include <fdtdec.h>
+#include <asm/gpio.h>
 
 /* This holds information about a window which can be displayed */
 struct disp_ctl_win {
@@ -72,10 +73,10 @@
 	int pwm_channel;		/* PWM channel to use for backlight */
 	enum lcd_cache_t cache_type;
 
-	struct fdt_gpio_state backlight_en;	/* GPIO for backlight enable */
-	struct fdt_gpio_state lvds_shutdown;	/* GPIO for lvds shutdown */
-	struct fdt_gpio_state backlight_vdd;	/* GPIO for backlight vdd */
-	struct fdt_gpio_state panel_vdd;	/* GPIO for panel vdd */
+	struct gpio_desc backlight_en;	/* GPIO for backlight enable */
+	struct gpio_desc lvds_shutdown;	/* GPIO for lvds shutdown */
+	struct gpio_desc backlight_vdd;	/* GPIO for backlight vdd */
+	struct gpio_desc panel_vdd;	/* GPIO for panel vdd */
 	/*
 	 * Panel required timings
 	 * Timing 1: delay between panel_vdd-rise and data-rise
diff --git a/arch/arm/include/asm/arch-uniphier/boot-device.h b/arch/arm/include/asm/arch-uniphier/boot-device.h
index 6987f57..7a10f1c 100644
--- a/arch/arm/include/asm/arch-uniphier/boot-device.h
+++ b/arch/arm/include/asm/arch-uniphier/boot-device.h
@@ -8,7 +8,7 @@
 #ifndef _ASM_BOOT_DEVICE_H_
 #define _ASM_BOOT_DEVICE_H_
 
-u32 get_boot_mode_sel(void);
+int get_boot_mode_sel(void);
 
 struct boot_device_info {
 	u32 type;
diff --git a/arch/arm/include/asm/arch-uniphier/gpio.h b/arch/arm/include/asm/arch-uniphier/gpio.h
deleted file mode 100644
index 1fc4e19..0000000
--- a/arch/arm/include/asm/arch-uniphier/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * Dummy header file to enable CONFIG_OF_CONTROL.
- * If CONFIG_OF_CONTROL is enabled, lib/fdtdec.c is compiled.
- * It includes <asm/arch/gpio.h> via <asm/gpio.h>, so those SoCs that enable
- * OF_CONTROL must have arch/gpio.h even if GPIO is not supported.
- */
diff --git a/arch/arm/include/asm/arch-zynq/gpio.h b/arch/arm/include/asm/arch-zynq/gpio.h
index 2dbba75..a26ae87 100644
--- a/arch/arm/include/asm/arch-zynq/gpio.h
+++ b/arch/arm/include/asm/arch-zynq/gpio.h
@@ -7,19 +7,4 @@
 #ifndef _ZYNQ_GPIO_H
 #define _ZYNQ_GPIO_H
 
-inline int gpio_get_value(unsigned gpio)
-{
-	return 0;
-}
-
-inline int gpio_set_value(unsigned gpio, int val)
-{
-	return 0;
-}
-
-inline int gpio_request(unsigned gpio, const char *label)
-{
-	return 0;
-}
-
 #endif /* _ZYNQ_GPIO_H */
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 342f045..7a545ea 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -1149,6 +1149,7 @@
 	u32 sdram_config;
 	u32 sdram_config2;
 	u32 ref_ctrl;
+	u32 ref_ctrl_final;
 	u32 sdram_tim1;
 	u32 sdram_tim2;
 	u32 sdram_tim3;
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 8acd7cd..17b6f54 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -26,10 +26,14 @@
 	BOOT_DEVICE_SPI,
 	BOOT_DEVICE_SATA,
 	BOOT_DEVICE_I2C,
+	BOOT_DEVICE_BOARD,
 	BOOT_DEVICE_NONE
 };
 #endif
 
+/* Board-specific load method */
+void spl_board_load_image(void);
+
 /* Linker symbols. */
 extern char __bss_start[], __bss_end[];
 
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 89f2294..7820486 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -142,6 +142,21 @@
 
 #ifndef __ASSEMBLY__
 
+/**
+ * save_boot_params() - Save boot parameters before starting reset sequence
+ *
+ * If you provide this function it will be called immediately U-Boot starts,
+ * both for SPL and U-Boot proper.
+ *
+ * All registers are unchanged from U-Boot entry. No registers need be
+ * preserved.
+ *
+ * This is not a normal C function. There is no stack. Return by branching to
+ * save_boot_params_ret.
+ *
+ * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3);
+ */
+
 #define isb() __asm__ __volatile__ ("" : : : "memory")
 
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h
index f97f3dd..414042d 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -36,7 +36,6 @@
 
 /* board/.../... */
 int	board_init(void);
-int	dram_init (void);
 void	dram_init_banksize (void);
 
 /* cpu/.../interrupt.c */
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index d74e4b8..da8ed72 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_SEMIHOSTING) += semihosting.o
 
 obj-y	+= sections.o
+obj-y	+= stack.o
 ifdef CONFIG_ARM64
 obj-y	+= gic_64.o
 obj-y	+= interrupts_64.o
diff --git a/arch/arm/lib/stack.c b/arch/arm/lib/stack.c
new file mode 100644
index 0000000..cf10a53
--- /dev/null
+++ b/arch/arm/lib/stack.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Andreas Bießmann <andreas.devel@googlemail.com>
+ *
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2002-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_reserve_stacks(void)
+{
+#ifdef CONFIG_SPL_BUILD
+	gd->start_addr_sp -= 128;	/* leave 32 words for abort-stack */
+	gd->irq_sp = gd->start_addr_sp;
+#else
+	/* setup stack pointer for exceptions */
+	gd->irq_sp = gd->start_addr_sp;
+
+# if !defined(CONFIG_ARM64)
+#  ifdef CONFIG_USE_IRQ
+	gd->start_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ);
+	debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
+	      CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ, gd->start_addr_sp);
+
+	/* 8-byte alignment for ARM ABI compliance */
+	gd->start_addr_sp &= ~0x07;
+#  endif
+	/* leave 3 words for abort-stack, plus 1 for alignment */
+	gd->start_addr_sp -= 16;
+# endif
+#endif
+
+	return 0;
+}
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
new file mode 100644
index 0000000..30945c1
--- /dev/null
+++ b/arch/arm/mach-at91/Kconfig
@@ -0,0 +1,168 @@
+if ARCH_AT91
+
+choice
+	prompt "Atmel AT91 board select"
+
+config TARGET_AT91RM9200EK
+	bool "Atmel AT91RM9200 evaluation kit"
+	select CPU_ARM920T
+
+config TARGET_EB_CPUX9K2
+	bool "Support eb_cpux9k2"
+	select CPU_ARM920T
+
+config TARGET_CPUAT91
+	bool "Support cpuat91"
+	select CPU_ARM920T
+
+config TARGET_AT91SAM9260EK
+	bool "Atmel at91sam9260 reference board"
+	select CPU_ARM926EJS
+
+config TARGET_ETHERNUT5
+	bool "Ethernut5 board"
+	select CPU_ARM926EJS
+
+config TARGET_TNY_A9260
+	bool "Caloa TNY A9260 board"
+	select CPU_ARM926EJS
+
+config TARGET_SNAPPER9260
+	bool "Support snapper9260"
+	select CPU_ARM926EJS
+
+config TARGET_AFEB9260
+	bool "Support afeb9260"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9261EK
+	bool "Atmel at91sam9261 reference board"
+	select CPU_ARM926EJS
+
+config TARGET_PM9261
+	bool "Ronetix pm9261 board"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9263EK
+	bool "Atmel at91sam9263 reference board"
+	select CPU_ARM926EJS
+
+config TARGET_USB_A9263
+	bool "Caloa USB A9260 board"
+	select CPU_ARM926EJS
+
+config TARGET_PM9263
+	bool "Ronetix pm9263 board"
+	select CPU_ARM926EJS
+
+config TARGET_SBC35_A9G20
+	bool "Support sbc35_a9g20"
+	select CPU_ARM926EJS
+
+config TARGET_STAMP9G20
+	bool "Support stamp9g20"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9M10G45EK
+	bool "Atmel AT91SAM9M10G45-EK board"
+	select CPU_ARM926EJS
+
+config TARGET_PM9G45
+	bool "Ronetix pm9g45 board"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9N12EK
+	bool "Atmel AT91SAM9N12-EK board"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9RLEK
+	bool "Atmel at91sam9rl reference board"
+	select CPU_ARM926EJS
+
+config TARGET_AT91SAM9X5EK
+	bool "Atmel AT91SAM9X5-EK board"
+	select CPU_ARM926EJS
+
+config TARGET_SAMA5D3_XPLAINED
+	bool "SAMA5D3 Xplained board"
+	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_SAMA5D3XEK
+	bool "SAMA5D3X-EK board"
+	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_SAMA5D4_XPLAINED
+	bool "SAMA5D4 Xplained board"
+	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_SAMA5D4EK
+	bool "SAMA5D4 Evaluation Kit"
+	select CPU_V7
+	select SUPPORT_SPL
+
+config TARGET_VL_MA2SC
+	bool "Support vl_ma2sc"
+	select CPU_ARM926EJS
+
+config TARGET_MEESC
+	bool "Support meesc"
+	select CPU_ARM926EJS
+
+config TARGET_OTC570
+	bool "Support otc570"
+	select CPU_ARM926EJS
+
+config TARGET_CPU9260
+	bool "Support cpu9260"
+	select CPU_ARM926EJS
+
+config TARGET_CORVUS
+	bool "Support corvus"
+	select CPU_ARM926EJS
+	select SUPPORT_SPL
+
+config TARGET_TAURUS
+	bool "Support taurus"
+	select CPU_ARM926EJS
+	select SUPPORT_SPL
+
+endchoice
+
+config SYS_SOC
+	default "at91"
+
+source "board/atmel/at91rm9200ek/Kconfig"
+source "board/atmel/at91sam9260ek/Kconfig"
+source "board/atmel/at91sam9261ek/Kconfig"
+source "board/atmel/at91sam9263ek/Kconfig"
+source "board/atmel/at91sam9m10g45ek/Kconfig"
+source "board/atmel/at91sam9n12ek/Kconfig"
+source "board/atmel/at91sam9rlek/Kconfig"
+source "board/atmel/at91sam9x5ek/Kconfig"
+source "board/atmel/sama5d3_xplained/Kconfig"
+source "board/atmel/sama5d3xek/Kconfig"
+source "board/atmel/sama5d4_xplained/Kconfig"
+source "board/atmel/sama5d4ek/Kconfig"
+source "board/BuS/eb_cpux9k2/Kconfig"
+source "board/eukrea/cpuat91/Kconfig"
+source "board/afeb9260/Kconfig"
+source "board/bluewater/snapper9260/Kconfig"
+source "board/BuS/vl_ma2sc/Kconfig"
+source "board/calao/sbc35_a9g20/Kconfig"
+source "board/calao/tny_a9260/Kconfig"
+source "board/calao/usb_a9263/Kconfig"
+source "board/egnite/ethernut5/Kconfig"
+source "board/esd/meesc/Kconfig"
+source "board/esd/otc570/Kconfig"
+source "board/eukrea/cpu9260/Kconfig"
+source "board/ronetix/pm9261/Kconfig"
+source "board/ronetix/pm9263/Kconfig"
+source "board/ronetix/pm9g45/Kconfig"
+source "board/siemens/corvus/Kconfig"
+source "board/siemens/taurus/Kconfig"
+source "board/taskit/stamp9g20/Kconfig"
+
+endif
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
new file mode 100644
index 0000000..e596ba6
--- /dev/null
+++ b/arch/arm/mach-at91/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_AT91_WANTS_COMMON_PHY) += phy.o
+ifneq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_AT91SAM9G20) += sdram.o spl_at91.o
+obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o
+obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o
+obj-$(CONFIG_SAMA5D4) += mpddrc.o spl_atmel.o
+obj-y += spl.o
+endif
+
+obj-$(CONFIG_CPU_ARM920T)	+= arm920t/
+obj-$(CONFIG_CPU_ARM926EJS)	+= arm926ejs/
+obj-$(CONFIG_CPU_V7)		+= armv7/
diff --git a/arch/arm/cpu/arm920t/at91/Makefile b/arch/arm/mach-at91/arm920t/Makefile
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/Makefile
rename to arch/arm/mach-at91/arm920t/Makefile
diff --git a/arch/arm/cpu/arm920t/at91/at91rm9200_devices.c b/arch/arm/mach-at91/arm920t/at91rm9200_devices.c
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/at91rm9200_devices.c
rename to arch/arm/mach-at91/arm920t/at91rm9200_devices.c
diff --git a/arch/arm/cpu/arm920t/at91/clock.c b/arch/arm/mach-at91/arm920t/clock.c
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/clock.c
rename to arch/arm/mach-at91/arm920t/clock.c
diff --git a/arch/arm/cpu/arm920t/at91/cpu.c b/arch/arm/mach-at91/arm920t/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/cpu.c
rename to arch/arm/mach-at91/arm920t/cpu.c
diff --git a/arch/arm/cpu/arm920t/at91/lowlevel_init.S b/arch/arm/mach-at91/arm920t/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/lowlevel_init.S
rename to arch/arm/mach-at91/arm920t/lowlevel_init.S
diff --git a/arch/arm/cpu/arm920t/at91/reset.c b/arch/arm/mach-at91/arm920t/reset.c
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/reset.c
rename to arch/arm/mach-at91/arm920t/reset.c
diff --git a/arch/arm/cpu/arm920t/at91/timer.c b/arch/arm/mach-at91/arm920t/timer.c
similarity index 100%
rename from arch/arm/cpu/arm920t/at91/timer.c
rename to arch/arm/mach-at91/arm920t/timer.c
diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile
similarity index 94%
rename from arch/arm/cpu/arm926ejs/at91/Makefile
rename to arch/arm/mach-at91/arm926ejs/Makefile
index 698a28d..ddc323f 100644
--- a/arch/arm/cpu/arm926ejs/at91/Makefile
+++ b/arch/arm/mach-at91/arm926ejs/Makefile
@@ -5,7 +5,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_AT91CAP9)	+= at91cap9_devices.o
 obj-$(CONFIG_AT91SAM9260)	+= at91sam9260_devices.o
 obj-$(CONFIG_AT91SAM9G20)	+= at91sam9260_devices.o
 obj-$(CONFIG_AT91SAM9XE)	+= at91sam9260_devices.o
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9260_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9260_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9261_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9261_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9261_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9261_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9263_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9263_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9263_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9263_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9m10g45_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9m10g45_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9m10g45_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9n12_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9n12_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9n12_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9rl_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9rl_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9rl_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9rl_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/at91sam9x5_devices.c b/arch/arm/mach-at91/arm926ejs/at91sam9x5_devices.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/at91sam9x5_devices.c
rename to arch/arm/mach-at91/arm926ejs/at91sam9x5_devices.c
diff --git a/arch/arm/cpu/arm926ejs/at91/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/clock.c
rename to arch/arm/mach-at91/arm926ejs/clock.c
diff --git a/arch/arm/cpu/arm926ejs/at91/cpu.c b/arch/arm/mach-at91/arm926ejs/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/cpu.c
rename to arch/arm/mach-at91/arm926ejs/cpu.c
diff --git a/arch/arm/cpu/arm926ejs/at91/eflash.c b/arch/arm/mach-at91/arm926ejs/eflash.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/eflash.c
rename to arch/arm/mach-at91/arm926ejs/eflash.c
diff --git a/arch/arm/cpu/arm926ejs/at91/led.c b/arch/arm/mach-at91/arm926ejs/led.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/led.c
rename to arch/arm/mach-at91/arm926ejs/led.c
diff --git a/arch/arm/cpu/arm926ejs/at91/lowlevel_init.S b/arch/arm/mach-at91/arm926ejs/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/lowlevel_init.S
rename to arch/arm/mach-at91/arm926ejs/lowlevel_init.S
diff --git a/arch/arm/cpu/arm926ejs/at91/reset.c b/arch/arm/mach-at91/arm926ejs/reset.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/reset.c
rename to arch/arm/mach-at91/arm926ejs/reset.c
diff --git a/arch/arm/cpu/arm926ejs/at91/timer.c b/arch/arm/mach-at91/arm926ejs/timer.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/at91/timer.c
rename to arch/arm/mach-at91/arm926ejs/timer.c
diff --git a/arch/arm/cpu/armv7/at91/Makefile b/arch/arm/mach-at91/armv7/Makefile
similarity index 100%
rename from arch/arm/cpu/armv7/at91/Makefile
rename to arch/arm/mach-at91/armv7/Makefile
diff --git a/arch/arm/cpu/armv7/at91/clock.c b/arch/arm/mach-at91/armv7/clock.c
similarity index 96%
rename from arch/arm/cpu/armv7/at91/clock.c
rename to arch/arm/mach-at91/armv7/clock.c
index 2cdddb2..0bf453e 100644
--- a/arch/arm/cpu/armv7/at91/clock.c
+++ b/arch/arm/mach-at91/armv7/clock.c
@@ -130,10 +130,18 @@
 		 AT91_PMC_MCKR_PRES_MASK |
 		 AT91_PMC_MCKR_MDIV_MASK |
 		 AT91_PMC_MCKR_PLLADIV_2);
+#ifdef CPU_HAS_H32MXDIV
+	tmp &= ~AT91_PMC_MCKR_H32MXDIV;
+#endif
+
 	tmp |= mckr & (AT91_PMC_MCKR_CSS_MASK  |
 		       AT91_PMC_MCKR_PRES_MASK |
 		       AT91_PMC_MCKR_MDIV_MASK |
 		       AT91_PMC_MCKR_PLLADIV_2);
+#ifdef CPU_HAS_H32MXDIV
+	tmp |= mckr & AT91_PMC_MCKR_H32MXDIV;
+#endif
+
 	writel(tmp, &pmc->mckr);
 
 	while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
diff --git a/arch/arm/cpu/armv7/at91/cpu.c b/arch/arm/mach-at91/armv7/cpu.c
similarity index 100%
rename from arch/arm/cpu/armv7/at91/cpu.c
rename to arch/arm/mach-at91/armv7/cpu.c
diff --git a/arch/arm/cpu/armv7/at91/reset.c b/arch/arm/mach-at91/armv7/reset.c
similarity index 100%
rename from arch/arm/cpu/armv7/at91/reset.c
rename to arch/arm/mach-at91/armv7/reset.c
diff --git a/arch/arm/cpu/armv7/at91/sama5d3_devices.c b/arch/arm/mach-at91/armv7/sama5d3_devices.c
similarity index 100%
rename from arch/arm/cpu/armv7/at91/sama5d3_devices.c
rename to arch/arm/mach-at91/armv7/sama5d3_devices.c
diff --git a/arch/arm/mach-at91/armv7/sama5d4_devices.c b/arch/arm/mach-at91/armv7/sama5d4_devices.c
new file mode 100644
index 0000000..ef39cb7
--- /dev/null
+++ b/arch/arm/mach-at91/armv7/sama5d4_devices.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 Atmel
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/sama5_matrix.h>
+#include <asm/arch/sama5_sfr.h>
+#include <asm/arch/sama5d4.h>
+
+char *get_cpu_name()
+{
+	unsigned int extension_id = get_extension_chip_id();
+
+	if (cpu_is_sama5d4())
+		switch (extension_id) {
+		case ARCH_EXID_SAMA5D41:
+			return "SAMA5D41";
+		case ARCH_EXID_SAMA5D42:
+			return "SAMA5D42";
+		case ARCH_EXID_SAMA5D43:
+			return "SAMA5D43";
+		case ARCH_EXID_SAMA5D44:
+			return "SAMA5D44";
+		default:
+			return "Unknown CPU type";
+		}
+	else
+		return "Unknown CPU type";
+}
+
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+void at91_udp_hw_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+	/* Enable UPLL clock */
+	writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+	/* Enable UDPHS clock */
+	at91_periph_clk_enable(ATMEL_ID_UDPHS);
+}
+#endif
+
+#ifdef CONFIG_SPL_BUILD
+void matrix_init(void)
+{
+	struct atmel_matrix *h64mx = (struct atmel_matrix *)ATMEL_BASE_MATRIX0;
+	struct atmel_matrix *h32mx = (struct atmel_matrix *)ATMEL_BASE_MATRIX1;
+	int i;
+
+	/* Disable the write protect */
+	writel(ATMEL_MATRIX_WPMR_WPKEY & ~ATMEL_MATRIX_WPMR_WPEN, &h64mx->wpmr);
+	writel(ATMEL_MATRIX_WPMR_WPKEY & ~ATMEL_MATRIX_WPMR_WPEN, &h32mx->wpmr);
+
+	/* DDR port 1 ~ poart 7, slave number is: 4 ~ 10 */
+	for (i = 4; i <= 10; i++) {
+		writel(0x000f0f0f, &h64mx->ssr[i]);
+		writel(0x0000ffff, &h64mx->sassr[i]);
+		writel(0x0000000f, &h64mx->srtsr[i]);
+	}
+
+	/* CS3 */
+	writel(0x00c0c0c0, &h32mx->ssr[3]);
+	writel(0xff000000, &h32mx->sassr[3]);
+	writel(0xff000000, &h32mx->srtsr[3]);
+
+	/* NFC SRAM */
+	writel(0x00010101, &h32mx->ssr[4]);
+	writel(0x00000001, &h32mx->sassr[4]);
+	writel(0x00000001, &h32mx->srtsr[4]);
+
+	/* Enable the write protect */
+	writel(ATMEL_MATRIX_WPMR_WPKEY | ATMEL_MATRIX_WPMR_WPEN, &h64mx->wpmr);
+	writel(ATMEL_MATRIX_WPMR_WPKEY | ATMEL_MATRIX_WPMR_WPEN, &h32mx->wpmr);
+}
+
+void redirect_int_from_saic_to_aic(void)
+{
+	struct atmel_sfr *sfr = (struct atmel_sfr *)ATMEL_BASE_SFR;
+	u32 key32;
+
+	if (!(readl(&sfr->aicredir) & ATMEL_SFR_AICREDIR_NSAIC)) {
+		key32 = readl(&sfr->sn1) ^ ATMEL_SFR_AICREDIR_KEY;
+		writel((key32 | ATMEL_SFR_AICREDIR_NSAIC), &sfr->aicredir);
+	}
+}
+#endif
diff --git a/arch/arm/cpu/armv7/at91/timer.c b/arch/arm/mach-at91/armv7/timer.c
similarity index 100%
rename from arch/arm/cpu/armv7/at91/timer.c
rename to arch/arm/mach-at91/armv7/timer.c
diff --git a/arch/arm/mach-at91/config.mk b/arch/arm/mach-at91/config.mk
new file mode 100644
index 0000000..7168abb
--- /dev/null
+++ b/arch/arm/mach-at91/config.mk
@@ -0,0 +1,9 @@
+ifeq ($(CONFIG_CPU_ARM926EJS),y)
+PLATFORM_CPPFLAGS += $(call cc-option,-mtune=arm926ejs,)
+endif
+
+ifeq ($(CONFIG_CPU_V7),y)
+ifndef CONFIG_SPL_BUILD
+ALL-y	+= u-boot.img
+endif
+endif
diff --git a/arch/arm/include/asm/arch-at91/at91_common.h b/arch/arm/mach-at91/include/mach/at91_common.h
similarity index 95%
rename from arch/arm/include/asm/arch-at91/at91_common.h
rename to arch/arm/mach-at91/include/mach/at91_common.h
index 912e55c..efcd74e 100644
--- a/arch/arm/include/asm/arch-at91/at91_common.h
+++ b/arch/arm/mach-at91/include/mach/at91_common.h
@@ -33,5 +33,6 @@
 void at91_spl_board_init(void);
 void at91_disable_wdt(void);
 void matrix_init(void);
+void redirect_int_from_saic_to_aic(void);
 
 #endif /* AT91_COMMON_H */
diff --git a/arch/arm/include/asm/arch-at91/at91_dbu.h b/arch/arm/mach-at91/include/mach/at91_dbu.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_dbu.h
rename to arch/arm/mach-at91/include/mach/at91_dbu.h
diff --git a/arch/arm/include/asm/arch-at91/at91_eefc.h b/arch/arm/mach-at91/include/mach/at91_eefc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_eefc.h
rename to arch/arm/mach-at91/include/mach/at91_eefc.h
diff --git a/arch/arm/include/asm/arch-at91/at91_emac.h b/arch/arm/mach-at91/include/mach/at91_emac.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_emac.h
rename to arch/arm/mach-at91/include/mach/at91_emac.h
diff --git a/arch/arm/include/asm/arch-at91/at91_gpbr.h b/arch/arm/mach-at91/include/mach/at91_gpbr.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_gpbr.h
rename to arch/arm/mach-at91/include/mach/at91_gpbr.h
diff --git a/arch/arm/include/asm/arch-at91/at91_matrix.h b/arch/arm/mach-at91/include/mach/at91_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_matrix.h
rename to arch/arm/mach-at91/include/mach/at91_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91_mc.h b/arch/arm/mach-at91/include/mach/at91_mc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_mc.h
rename to arch/arm/mach-at91/include/mach/at91_mc.h
diff --git a/arch/arm/include/asm/arch-at91/at91_pdc.h b/arch/arm/mach-at91/include/mach/at91_pdc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_pdc.h
rename to arch/arm/mach-at91/include/mach/at91_pdc.h
diff --git a/arch/arm/include/asm/arch-at91/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h
similarity index 96%
rename from arch/arm/include/asm/arch-at91/at91_pio.h
rename to arch/arm/mach-at91/include/mach/at91_pio.h
index 50464ff..3012278 100644
--- a/arch/arm/include/asm/arch-at91/at91_pio.h
+++ b/arch/arm/mach-at91/include/mach/at91_pio.h
@@ -114,14 +114,10 @@
 		at91_port_t	pioa;
 		at91_port_t	piob;
 		at91_port_t	pioc;
-	#if (ATMEL_PIO_PORTS > 3)
-		at91_port_t	piod;
-	#endif
-	#if (ATMEL_PIO_PORTS > 4)
-		at91_port_t	pioe;
-	#endif
-	} ;
-	at91_port_t port[ATMEL_PIO_PORTS];
+		at91_port_t	piod;	/* not present in all hardware */
+		at91_port_t	pioe;/* not present in all hardware */
+	};
+	at91_port_t port[5];
 } at91_pio_t;
 
 #ifdef CONFIG_AT91_GPIO
diff --git a/arch/arm/include/asm/arch-at91/at91_pit.h b/arch/arm/mach-at91/include/mach/at91_pit.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_pit.h
rename to arch/arm/mach-at91/include/mach/at91_pit.h
diff --git a/arch/arm/include/asm/arch-at91/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
similarity index 95%
rename from arch/arm/include/asm/arch-at91/at91_pmc.h
rename to arch/arm/mach-at91/include/mach/at91_pmc.h
index 53b5b2e..65691ab 100644
--- a/arch/arm/include/asm/arch-at91/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -157,10 +157,8 @@
 #define		AT91_PMC_PCK		(1 <<  0)		/* Processor Clock */
 #define		AT91RM9200_PMC_UDP	(1 <<  1)		/* USB Devcice Port Clock [AT91RM9200 only] */
 #define		AT91RM9200_PMC_MCKUDP	(1 <<  2)		/* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
-#define		AT91CAP9_PMC_DDR	(1 <<  2)		/* DDR Clock [AT91CAP9 revC only] */
 #define		AT91RM9200_PMC_UHP	(1 <<  4)		/* USB Host Port Clock [AT91RM9200 only] */
 #define		AT91SAM926x_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91SAM926x only] */
-#define		AT91CAP9_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91CAP9 only] */
 #define		AT91SAM926x_PMC_UDP	(1 <<  7)		/* USB Devcice Port Clock [AT91SAM926x only] */
 #define		AT91_PMC_PCK0		(1 <<  8)		/* Programmable Clock 0 */
 #define		AT91_PMC_PCK1		(1 <<  9)		/* Programmable Clock 1 */
@@ -175,7 +173,7 @@
 #define		AT91_PMC_BIASCOUNT	(0xf << 28)		/* UTMI PLL Start-up Time */
 
 #define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */
-#define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [SAM9x, CAP9] */
+#define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [SAM9x] */
 #define		AT91_PMC_OSCOUNT	(0xff << 8)		/* Main Oscillator Start-up Time */
 
 #define		AT91_PMC_MAINF		(0xffff <<  0)		/* Main Clock Frequency */
@@ -210,7 +208,7 @@
 #define			AT91RM9200_PMC_MDIV_2		(1 << 8)
 #define			AT91RM9200_PMC_MDIV_3		(2 << 8)
 #define			AT91RM9200_PMC_MDIV_4		(3 << 8)
-#define			AT91SAM9_PMC_MDIV_1		(0 << 8)	/* [SAM9,CAP9 only] */
+#define			AT91SAM9_PMC_MDIV_1		(0 << 8)	/* [SAM9 only] */
 #define			AT91SAM9_PMC_MDIV_2		(1 << 8)
 #define			AT91SAM9_PMC_MDIV_4		(2 << 8)
 #define			AT91SAM9_PMC_MDIV_3		(3 << 8)	/* [some SAM9 only] */
@@ -230,8 +228,7 @@
 #define		AT91_PMC_LOCKA		(1 <<  1)		/* PLLA Lock */
 #define		AT91_PMC_LOCKB		(1 <<  2)		/* PLLB Lock */
 #define		AT91_PMC_MCKRDY		(1 <<  3)		/* Master Clock */
-#define		AT91_PMC_LOCKU		(1 <<  6)		/* UPLL Lock [AT91CAP9 only] */
-#define		AT91_PMC_OSCSEL		(1 <<  7)		/* Slow Clock Oscillator [AT91CAP9 revC only] */
+#define		AT91_PMC_LOCKU		(1 <<  6)		/* UPLL Lock */
 #define		AT91_PMC_PCK0RDY	(1 <<  8)		/* Programmable Clock 0 */
 #define		AT91_PMC_PCK1RDY	(1 <<  9)		/* Programmable Clock 1 */
 #define		AT91_PMC_PCK2RDY	(1 << 10)		/* Programmable Clock 2 */
diff --git a/arch/arm/include/asm/arch-at91/at91_rstc.h b/arch/arm/mach-at91/include/mach/at91_rstc.h
similarity index 93%
rename from arch/arm/include/asm/arch-at91/at91_rstc.h
rename to arch/arm/mach-at91/include/mach/at91_rstc.h
index a942342..e4eb3da 100644
--- a/arch/arm/include/asm/arch-at91/at91_rstc.h
+++ b/arch/arm/mach-at91/include/mach/at91_rstc.h
@@ -13,6 +13,8 @@
 #ifndef AT91_RSTC_H
 #define AT91_RSTC_H
 
+/* Reset Controller Status Register */
+#define AT91_ASM_RSTC_SR	(ATMEL_BASE_RSTC + 0x04)
 #define AT91_ASM_RSTC_MR	(ATMEL_BASE_RSTC + 0x08)
 
 #ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/arch-at91/at91_rtt.h b/arch/arm/mach-at91/include/mach/at91_rtt.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_rtt.h
rename to arch/arm/mach-at91/include/mach/at91_rtt.h
diff --git a/arch/arm/include/asm/arch-at91/at91_spi.h b/arch/arm/mach-at91/include/mach/at91_spi.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_spi.h
rename to arch/arm/mach-at91/include/mach/at91_spi.h
diff --git a/arch/arm/include/asm/arch-at91/at91_st.h b/arch/arm/mach-at91/include/mach/at91_st.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_st.h
rename to arch/arm/mach-at91/include/mach/at91_st.h
diff --git a/arch/arm/include/asm/arch-at91/at91_tc.h b/arch/arm/mach-at91/include/mach/at91_tc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_tc.h
rename to arch/arm/mach-at91/include/mach/at91_tc.h
diff --git a/arch/arm/include/asm/arch-at91/at91_wdt.h b/arch/arm/mach-at91/include/mach/at91_wdt.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91_wdt.h
rename to arch/arm/mach-at91/include/mach/at91_wdt.h
diff --git a/arch/arm/include/asm/arch-at91/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91rm9200.h
rename to arch/arm/mach-at91/include/mach/at91rm9200.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9260.h
rename to arch/arm/mach-at91/include/mach/at91sam9260.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9260_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9260_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9260_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9260_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9261.h
rename to arch/arm/mach-at91/include/mach/at91sam9261.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9261_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9261_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9261_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9261_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9263.h
rename to arch/arm/mach-at91/include/mach/at91sam9263.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9263_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9263_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9263_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9263_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9_matrix.h
similarity index 92%
rename from arch/arm/include/asm/arch-at91/at91sam9_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9_matrix.h
index 1b59cc6..d0bf0c2 100644
--- a/arch/arm/include/asm/arch-at91/at91sam9_matrix.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9_matrix.h
@@ -15,8 +15,6 @@
 #include <asm/arch/at91sam9263_matrix.h>
 #elif defined(CONFIG_AT91SAM9RL)
 #include <asm/arch/at91sam9rl_matrix.h>
-#elif defined(CONFIG_AT91CAP9)
-#include <asm/arch/at91cap9_matrix.h>
 #elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45)
 #include <asm/arch/at91sam9g45_matrix.h>
 #elif defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
diff --git a/arch/arm/include/asm/arch-at91/at91sam9_sdramc.h b/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9_sdramc.h
rename to arch/arm/mach-at91/include/mach/at91sam9_sdramc.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9_smc.h b/arch/arm/mach-at91/include/mach/at91sam9_smc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9_smc.h
rename to arch/arm/mach-at91/include/mach/at91sam9_smc.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9g45.h
rename to arch/arm/mach-at91/include/mach/at91sam9g45.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9g45_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9g45_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9rl.h
rename to arch/arm/mach-at91/include/mach/at91sam9rl.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9rl_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9rl_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9x5.h
rename to arch/arm/mach-at91/include/mach/at91sam9x5.h
diff --git a/arch/arm/include/asm/arch-at91/at91sam9x5_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9x5_matrix.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/at91sam9x5_matrix.h
rename to arch/arm/mach-at91/include/mach/at91sam9x5_matrix.h
diff --git a/arch/arm/include/asm/arch-at91/atmel_mpddrc.h b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/atmel_mpddrc.h
rename to arch/arm/mach-at91/include/mach/atmel_mpddrc.h
diff --git a/arch/arm/include/asm/arch-at91/atmel_serial.h b/arch/arm/mach-at91/include/mach/atmel_serial.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/atmel_serial.h
rename to arch/arm/mach-at91/include/mach/atmel_serial.h
diff --git a/arch/arm/include/asm/arch-at91/atmel_usba_udc.h b/arch/arm/mach-at91/include/mach/atmel_usba_udc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/atmel_usba_udc.h
rename to arch/arm/mach-at91/include/mach/atmel_usba_udc.h
diff --git a/arch/arm/include/asm/arch-at91/clk.h b/arch/arm/mach-at91/include/mach/clk.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/clk.h
rename to arch/arm/mach-at91/include/mach/clk.h
diff --git a/arch/arm/include/asm/arch-at91/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/gpio.h
rename to arch/arm/mach-at91/include/mach/gpio.h
diff --git a/arch/arm/include/asm/arch-at91/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
similarity index 94%
rename from arch/arm/include/asm/arch-at91/hardware.h
rename to arch/arm/mach-at91/include/mach/hardware.h
index bf0a1bd..ff6b71b 100644
--- a/arch/arm/include/asm/arch-at91/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -23,8 +23,6 @@
 # include <asm/arch/at91sam9g45.h>
 #elif defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
 # include <asm/arch/at91sam9x5.h>
-#elif defined(CONFIG_AT91CAP9)
-# include <asm/arch/at91cap9.h>
 #elif defined(CONFIG_SAMA5D3)
 # include <asm/arch/sama5d3.h>
 #elif defined(CONFIG_SAMA5D4)
diff --git a/arch/arm/mach-at91/include/mach/sama5_matrix.h b/arch/arm/mach-at91/include/mach/sama5_matrix.h
new file mode 100644
index 0000000..e324766
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sama5_matrix.h
@@ -0,0 +1,37 @@
+/*
+ * Bus Matrix header file for the SAMA5 family
+ *
+ * Copyright (C) 2014 Atmel
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SAMA5_MATRIX_H
+#define __SAMA5_MATRIX_H
+
+struct atmel_matrix {
+	u32 mcfg[16];	/* 0x00 ~ 0x3c: Master Configuration Register */
+	u32 scfg[16];	/* 0x40 ~ 0x7c: Slave Configuration Register */
+	u32 pras[16][2];/* 0x80 ~ 0xfc: Priority Register A/B */
+	u32 res1[20];	/* 0x100 ~ 0x14c */
+	u32 meier;	/* 0x150: Master Error Interrupt Enable Register */
+	u32 meidr;	/* 0x154: Master Error Interrupt Disable Register */
+	u32 meimr;	/* 0x158: Master Error Interrupt Mask Register */
+	u32 mesr;	/* 0x15c: Master Error Status Register */
+	u32 mear[16];	/* 0x160 ~ 0x19c: Master Error Address Register */
+	u32 res2[17];	/* 0x1A0 ~ 0x1E0 */
+	u32 wpmr;	/* 0x1E4: Write Protection Mode Register */
+	u32 wpsr;	/* 0x1E8: Write Protection Status Register */
+	u32 res3[5];	/* 0x1EC ~ 0x1FC */
+	u32 ssr[16];	/* 0x200 ~ 0x23c: Security Slave Register */
+	u32 sassr[16];	/* 0x240 ~ 0x27c: Security Areas Split Slave Register */
+	u32 srtsr[16];	/* 0x280 ~ 0x2bc: Security Region Top Slave */
+	u32 spselr[3];	/* 0x2c0 ~ 0x2c8: Security Peripheral Select Register */
+};
+
+/* Bit field in WPMR */
+#define ATMEL_MATRIX_WPMR_WPKEY	0x4D415400
+#define ATMEL_MATRIX_WPMR_WPEN	0x00000001
+
+#endif
diff --git a/arch/arm/mach-at91/include/mach/sama5_sfr.h b/arch/arm/mach-at91/include/mach/sama5_sfr.h
new file mode 100644
index 0000000..3081d37
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sama5_sfr.h
@@ -0,0 +1,38 @@
+/*
+ * Special Function Register (SFR)
+ *
+ * Copyright (C) 2014 Atmel
+ *		      Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SAMA5_SFR_H
+#define __SAMA5_SFR_H
+
+struct atmel_sfr {
+	u32 reserved1;	/* 0x00 */
+	u32 ddrcfg;	/* 0x04: DDR Configuration Register */
+	u32 reserved2;	/* 0x08 */
+	u32 reserved3;	/* 0x0c */
+	u32 ohciicr;	/* 0x10: OHCI Interrupt Configuration Register */
+	u32 ohciisr;	/* 0x14: OHCI Interrupt Status Register */
+	u32 reserved4[4];	/* 0x18 ~ 0x24 */
+	u32 secure;		/* 0x28: Security Configuration Register */
+	u32 reserved5[5];	/* 0x2c ~ 0x3c */
+	u32 ebicfg;		/* 0x40: EBI Configuration Register */
+	u32 reserved6[2];	/* 0x44 ~ 0x48 */
+	u32 sn0;		/* 0x4c */
+	u32 sn1;		/* 0x50 */
+	u32 aicredir;	/* 0x54 */
+};
+
+/* Bit field in DDRCFG */
+#define ATMEL_SFR_DDRCFG_FDQIEN		0x00010000
+#define ATMEL_SFR_DDRCFG_FDQSIEN	0x00020000
+
+/* Bit field in AICREDIR */
+#define ATMEL_SFR_AICREDIR_KEY		0x5F67B102
+#define ATMEL_SFR_AICREDIR_NSAIC	0x00000001
+
+#endif
diff --git a/arch/arm/include/asm/arch-at91/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/sama5d3.h
rename to arch/arm/mach-at91/include/mach/sama5d3.h
diff --git a/arch/arm/include/asm/arch-at91/sama5d3_smc.h b/arch/arm/mach-at91/include/mach/sama5d3_smc.h
similarity index 100%
rename from arch/arm/include/asm/arch-at91/sama5d3_smc.h
rename to arch/arm/mach-at91/include/mach/sama5d3_smc.h
diff --git a/arch/arm/include/asm/arch-at91/sama5d4.h b/arch/arm/mach-at91/include/mach/sama5d4.h
similarity index 99%
rename from arch/arm/include/asm/arch-at91/sama5d4.h
rename to arch/arm/mach-at91/include/mach/sama5d4.h
index d851568..f30cb5f 100644
--- a/arch/arm/include/asm/arch-at91/sama5d4.h
+++ b/arch/arm/mach-at91/include/mach/sama5d4.h
@@ -126,6 +126,8 @@
 #define ATMEL_BASE_ADC		0xfc034000
 #define ATMEL_BASE_TWI3		0xfc038000
 
+#define ATMEL_BASE_MATRIX1	0xfc054000
+
 #define ATMEL_BASE_SMC		0xfc05c000
 #define ATMEL_BASE_PMECC	(ATMEL_BASE_SMC + 0x070)
 #define ATMEL_BASE_PMERRLOC	(ATMEL_BASE_SMC + 0x500)
diff --git a/arch/arm/cpu/at91-common/mpddrc.c b/arch/arm/mach-at91/mpddrc.c
similarity index 98%
rename from arch/arm/cpu/at91-common/mpddrc.c
rename to arch/arm/mach-at91/mpddrc.c
index 44798e6..beec13d 100644
--- a/arch/arm/cpu/at91-common/mpddrc.c
+++ b/arch/arm/mach-at91/mpddrc.c
@@ -19,7 +19,7 @@
 
 static int ddr2_decodtype_is_seq(u32 cr)
 {
-#if defined(CONFIG_SAMA5D3)
+#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4)
 	if (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)
 		return 0;
 #endif
diff --git a/arch/arm/cpu/at91-common/phy.c b/arch/arm/mach-at91/phy.c
similarity index 100%
rename from arch/arm/cpu/at91-common/phy.c
rename to arch/arm/mach-at91/phy.c
diff --git a/arch/arm/cpu/at91-common/sdram.c b/arch/arm/mach-at91/sdram.c
similarity index 100%
rename from arch/arm/cpu/at91-common/sdram.c
rename to arch/arm/mach-at91/sdram.c
diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/mach-at91/spl.c
similarity index 90%
rename from arch/arm/cpu/at91-common/spl.c
rename to arch/arm/mach-at91/spl.c
index 6473320..aaa5eec 100644
--- a/arch/arm/cpu/at91-common/spl.c
+++ b/arch/arm/mach-at91/spl.c
@@ -12,12 +12,16 @@
 #include <asm/arch/clk.h>
 #include <spl.h>
 
+#if defined(CONFIG_AT91SAM9_WATCHDOG)
+void at91_disable_wdt(void) { }
+#else
 void at91_disable_wdt(void)
 {
 	struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT;
 
 	writel(AT91_WDT_MR_WDDIS, &wdt->mr);
 }
+#endif
 
 u32 spl_boot_device(void)
 {
diff --git a/arch/arm/cpu/at91-common/spl_at91.c b/arch/arm/mach-at91/spl_at91.c
similarity index 100%
rename from arch/arm/cpu/at91-common/spl_at91.c
rename to arch/arm/mach-at91/spl_at91.c
diff --git a/arch/arm/cpu/at91-common/spl_atmel.c b/arch/arm/mach-at91/spl_atmel.c
similarity index 86%
rename from arch/arm/cpu/at91-common/spl_atmel.c
rename to arch/arm/mach-at91/spl_atmel.c
index 7297530..9cc1111 100644
--- a/arch/arm/cpu/at91-common/spl_atmel.c
+++ b/arch/arm/mach-at91/spl_atmel.c
@@ -51,11 +51,23 @@
 	while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY))
 		;
 
+#ifndef CONFIG_SAMA5D4
 	tmp = readl(&pmc->mor);
 	tmp &= ~AT91_PMC_MOR_MOSCRCEN;
 	tmp &= ~AT91_PMC_MOR_KEY(0xff);
 	tmp |= AT91_PMC_MOR_KEY(0x37);
 	writel(tmp, &pmc->mor);
+#endif
+}
+
+__weak void matrix_init(void)
+{
+	/* This only be used for sama5d4 soc now */
+}
+
+__weak void redirect_int_from_saic_to_aic(void)
+{
+	/* This only be used for sama5d4 soc now */
 }
 
 void s_init(void)
@@ -70,6 +82,10 @@
 
 	at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
 
+	matrix_init();
+
+	redirect_int_from_saic_to_aic();
+
 	timer_init();
 
 	board_early_init_f();
diff --git a/arch/arm/cpu/at91-common/u-boot-spl.lds b/arch/arm/mach-at91/u-boot-spl.lds
similarity index 100%
rename from arch/arm/cpu/at91-common/u-boot-spl.lds
rename to arch/arm/mach-at91/u-boot-spl.lds
diff --git a/arch/arm/cpu/arm926ejs/davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/Kconfig
rename to arch/arm/mach-davinci/Kconfig
diff --git a/arch/arm/cpu/arm926ejs/davinci/Makefile b/arch/arm/mach-davinci/Makefile
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/Makefile
rename to arch/arm/mach-davinci/Makefile
diff --git a/arch/arm/cpu/arm926ejs/davinci/config.mk b/arch/arm/mach-davinci/config.mk
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/config.mk
rename to arch/arm/mach-davinci/config.mk
diff --git a/arch/arm/cpu/arm926ejs/davinci/cpu.c b/arch/arm/mach-davinci/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/cpu.c
rename to arch/arm/mach-davinci/cpu.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/da830_pinmux.c b/arch/arm/mach-davinci/da830_pinmux.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/da830_pinmux.c
rename to arch/arm/mach-davinci/da830_pinmux.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c b/arch/arm/mach-davinci/da850_lowlevel.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c
rename to arch/arm/mach-davinci/da850_lowlevel.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c b/arch/arm/mach-davinci/da850_pinmux.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c
rename to arch/arm/mach-davinci/da850_pinmux.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/dm355.c
rename to arch/arm/mach-davinci/dm355.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/dm365.c
rename to arch/arm/mach-davinci/dm365.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c b/arch/arm/mach-davinci/dm365_lowlevel.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/dm365_lowlevel.c
rename to arch/arm/mach-davinci/dm365_lowlevel.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/dm644x.c
rename to arch/arm/mach-davinci/dm644x.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/dm646x.c
rename to arch/arm/mach-davinci/dm646x.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/dp83848.c b/arch/arm/mach-davinci/dp83848.c
similarity index 97%
rename from arch/arm/cpu/arm926ejs/davinci/dp83848.c
rename to arch/arm/mach-davinci/dp83848.c
index 603d507..6387e95 100644
--- a/arch/arm/cpu/arm926ejs/davinci/dp83848.c
+++ b/arch/arm/mach-davinci/dp83848.c
@@ -13,7 +13,7 @@
 #include <net.h>
 #include <dp83848.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/arch/arm/cpu/arm926ejs/davinci/et1011c.c b/arch/arm/mach-davinci/et1011c.c
similarity index 94%
rename from arch/arm/cpu/arm926ejs/davinci/et1011c.c
rename to arch/arm/mach-davinci/et1011c.c
index 9d53875..151020d 100644
--- a/arch/arm/cpu/arm926ejs/davinci/et1011c.c
+++ b/arch/arm/mach-davinci/et1011c.c
@@ -10,7 +10,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/arch/arm/include/asm/arch-davinci/aintc_defs.h b/arch/arm/mach-davinci/include/mach/aintc_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/aintc_defs.h
rename to arch/arm/mach-davinci/include/mach/aintc_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/da850_lowlevel.h b/arch/arm/mach-davinci/include/mach/da850_lowlevel.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/da850_lowlevel.h
rename to arch/arm/mach-davinci/include/mach/da850_lowlevel.h
diff --git a/arch/arm/include/asm/arch-davinci/da8xx-usb.h b/arch/arm/mach-davinci/include/mach/da8xx-usb.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/da8xx-usb.h
rename to arch/arm/mach-davinci/include/mach/da8xx-usb.h
diff --git a/arch/arm/include/asm/arch-davinci/davinci_misc.h b/arch/arm/mach-davinci/include/mach/davinci_misc.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/davinci_misc.h
rename to arch/arm/mach-davinci/include/mach/davinci_misc.h
diff --git a/arch/arm/include/asm/arch-davinci/ddr2_defs.h b/arch/arm/mach-davinci/include/mach/ddr2_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/ddr2_defs.h
rename to arch/arm/mach-davinci/include/mach/ddr2_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/dm365_lowlevel.h b/arch/arm/mach-davinci/include/mach/dm365_lowlevel.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/dm365_lowlevel.h
rename to arch/arm/mach-davinci/include/mach/dm365_lowlevel.h
diff --git a/arch/arm/include/asm/arch-davinci/emac_defs.h b/arch/arm/mach-davinci/include/mach/emac_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/emac_defs.h
rename to arch/arm/mach-davinci/include/mach/emac_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/gpio.h
rename to arch/arm/mach-davinci/include/mach/gpio.h
diff --git a/arch/arm/include/asm/arch-davinci/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/hardware.h
rename to arch/arm/mach-davinci/include/mach/hardware.h
diff --git a/arch/arm/include/asm/arch-davinci/i2c_defs.h b/arch/arm/mach-davinci/include/mach/i2c_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/i2c_defs.h
rename to arch/arm/mach-davinci/include/mach/i2c_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/pinmux_defs.h b/arch/arm/mach-davinci/include/mach/pinmux_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/pinmux_defs.h
rename to arch/arm/mach-davinci/include/mach/pinmux_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/pll_defs.h b/arch/arm/mach-davinci/include/mach/pll_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/pll_defs.h
rename to arch/arm/mach-davinci/include/mach/pll_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/psc_defs.h b/arch/arm/mach-davinci/include/mach/psc_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/psc_defs.h
rename to arch/arm/mach-davinci/include/mach/psc_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/sdmmc_defs.h b/arch/arm/mach-davinci/include/mach/sdmmc_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/sdmmc_defs.h
rename to arch/arm/mach-davinci/include/mach/sdmmc_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/syscfg_defs.h b/arch/arm/mach-davinci/include/mach/syscfg_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/syscfg_defs.h
rename to arch/arm/mach-davinci/include/mach/syscfg_defs.h
diff --git a/arch/arm/include/asm/arch-davinci/timer_defs.h b/arch/arm/mach-davinci/include/mach/timer_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-davinci/timer_defs.h
rename to arch/arm/mach-davinci/include/mach/timer_defs.h
diff --git a/arch/arm/cpu/arm926ejs/davinci/ksz8873.c b/arch/arm/mach-davinci/ksz8873.c
similarity index 94%
rename from arch/arm/cpu/arm926ejs/davinci/ksz8873.c
rename to arch/arm/mach-davinci/ksz8873.c
index 4af5dd2..75af135 100644
--- a/arch/arm/cpu/arm926ejs/davinci/ksz8873.c
+++ b/arch/arm/mach-davinci/ksz8873.c
@@ -20,7 +20,7 @@
 #include <net.h>
 #include <asm/arch/emac_defs.h>
 #include <asm/io.h>
-#include "../../../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/davinci_emac.h"
 
 int ksz8873_is_phy_connected(int phy_addr)
 {
diff --git a/arch/arm/cpu/arm926ejs/davinci/lowlevel_init.S b/arch/arm/mach-davinci/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/lowlevel_init.S
rename to arch/arm/mach-davinci/lowlevel_init.S
diff --git a/arch/arm/cpu/arm926ejs/davinci/lxt972.c b/arch/arm/mach-davinci/lxt972.c
similarity index 97%
rename from arch/arm/cpu/arm926ejs/davinci/lxt972.c
rename to arch/arm/mach-davinci/lxt972.c
index c482fd9..a7356f9 100644
--- a/arch/arm/cpu/arm926ejs/davinci/lxt972.c
+++ b/arch/arm/mach-davinci/lxt972.c
@@ -14,7 +14,7 @@
 #include <miiphy.h>
 #include <lxt971a.h>
 #include <asm/arch/emac_defs.h>
-#include "../../../../../drivers/net/davinci_emac.h"
+#include "../../../drivers/net/davinci_emac.h"
 
 #ifdef CONFIG_DRIVER_TI_EMAC
 
diff --git a/arch/arm/cpu/arm926ejs/davinci/misc.c b/arch/arm/mach-davinci/misc.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/misc.c
rename to arch/arm/mach-davinci/misc.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/pinmux.c b/arch/arm/mach-davinci/pinmux.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/pinmux.c
rename to arch/arm/mach-davinci/pinmux.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/psc.c b/arch/arm/mach-davinci/psc.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/psc.c
rename to arch/arm/mach-davinci/psc.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/reset.c b/arch/arm/mach-davinci/reset.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/reset.c
rename to arch/arm/mach-davinci/reset.c
diff --git a/arch/arm/cpu/arm926ejs/davinci/spl.c b/arch/arm/mach-davinci/spl.c
similarity index 76%
rename from arch/arm/cpu/arm926ejs/davinci/spl.c
rename to arch/arm/mach-davinci/spl.c
index 59b304e..49349da 100644
--- a/arch/arm/cpu/arm926ejs/davinci/spl.c
+++ b/arch/arm/mach-davinci/spl.c
@@ -34,29 +34,14 @@
 }
 #endif /* CONFIG_SPL_LIBCOMMON_SUPPORT */
 
-void board_init_f(ulong dummy)
+void spl_board_init(void)
 {
-	/* First, setup our stack pointer. */
-	asm volatile("mov sp, %0\n" : : "r"(CONFIG_SPL_STACK));
-
-	/* Second, perform our low-level init. */
 #ifdef CONFIG_SOC_DM365
 	dm36x_lowlevel_init(0);
 #endif
 #ifdef CONFIG_SOC_DA8XX
 	arch_cpu_init();
 #endif
-
-	/* Third, we clear the BSS. */
-	memset(__bss_start, 0, __bss_end - __bss_start);
-
-	/* Finally, setup gd and move to the next step. */
-	gd = &gdata;
-	board_init_r(NULL, 0);
-}
-
-void spl_board_init(void)
-{
 	preloader_console_init();
 }
 
diff --git a/arch/arm/cpu/arm926ejs/davinci/timer.c b/arch/arm/mach-davinci/timer.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/davinci/timer.c
rename to arch/arm/mach-davinci/timer.c
diff --git a/arch/arm/cpu/armv7/highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/highbank/Kconfig
rename to arch/arm/mach-highbank/Kconfig
diff --git a/arch/arm/cpu/armv7/highbank/Makefile b/arch/arm/mach-highbank/Makefile
similarity index 100%
rename from arch/arm/cpu/armv7/highbank/Makefile
rename to arch/arm/mach-highbank/Makefile
diff --git a/arch/arm/cpu/armv7/highbank/timer.c b/arch/arm/mach-highbank/timer.c
similarity index 100%
rename from arch/arm/cpu/armv7/highbank/timer.c
rename to arch/arm/mach-highbank/timer.c
diff --git a/arch/arm/cpu/armv7/keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/Kconfig
rename to arch/arm/mach-keystone/Kconfig
diff --git a/arch/arm/cpu/armv7/keystone/Makefile b/arch/arm/mach-keystone/Makefile
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/Makefile
rename to arch/arm/mach-keystone/Makefile
diff --git a/arch/arm/cpu/armv7/keystone/clock-k2e.c b/arch/arm/mach-keystone/clock-k2e.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/clock-k2e.c
rename to arch/arm/mach-keystone/clock-k2e.c
diff --git a/arch/arm/cpu/armv7/keystone/clock-k2hk.c b/arch/arm/mach-keystone/clock-k2hk.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/clock-k2hk.c
rename to arch/arm/mach-keystone/clock-k2hk.c
diff --git a/arch/arm/cpu/armv7/keystone/clock-k2l.c b/arch/arm/mach-keystone/clock-k2l.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/clock-k2l.c
rename to arch/arm/mach-keystone/clock-k2l.c
diff --git a/arch/arm/cpu/armv7/keystone/clock.c b/arch/arm/mach-keystone/clock.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/clock.c
rename to arch/arm/mach-keystone/clock.c
diff --git a/arch/arm/cpu/armv7/keystone/cmd_clock.c b/arch/arm/mach-keystone/cmd_clock.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/cmd_clock.c
rename to arch/arm/mach-keystone/cmd_clock.c
diff --git a/arch/arm/cpu/armv7/keystone/cmd_ddr3.c b/arch/arm/mach-keystone/cmd_ddr3.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/cmd_ddr3.c
rename to arch/arm/mach-keystone/cmd_ddr3.c
diff --git a/arch/arm/cpu/armv7/keystone/cmd_mon.c b/arch/arm/mach-keystone/cmd_mon.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/cmd_mon.c
rename to arch/arm/mach-keystone/cmd_mon.c
diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/mach-keystone/ddr3.c
similarity index 98%
rename from arch/arm/cpu/armv7/keystone/ddr3.c
rename to arch/arm/mach-keystone/ddr3.c
index 923906a..dfb27b5 100644
--- a/arch/arm/cpu/armv7/keystone/ddr3.c
+++ b/arch/arm/mach-keystone/ddr3.c
@@ -263,17 +263,14 @@
 }
 #endif
 
-void ddr3_init_ecc(u32 base)
+void ddr3_init_ecc(u32 base, u32 ddr3_size)
 {
-	u32 ddr3_size;
-
 	if (!ddr3_ecc_support_rmw(base)) {
 		ddr3_disable_ecc(base);
 		return;
 	}
 
 	ddr3_ecc_init_range(base);
-	ddr3_size = ddr3_get_size();
 	ddr3_reset_data(CONFIG_SYS_SDRAM_BASE, ddr3_size);
 
 	/* mapping DDR3 ECC system interrupt from CIC2 to GIC */
diff --git a/arch/arm/include/asm/arch-keystone/clock-k2e.h b/arch/arm/mach-keystone/include/mach/clock-k2e.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/clock-k2e.h
rename to arch/arm/mach-keystone/include/mach/clock-k2e.h
diff --git a/arch/arm/include/asm/arch-keystone/clock-k2hk.h b/arch/arm/mach-keystone/include/mach/clock-k2hk.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/clock-k2hk.h
rename to arch/arm/mach-keystone/include/mach/clock-k2hk.h
diff --git a/arch/arm/include/asm/arch-keystone/clock-k2l.h b/arch/arm/mach-keystone/include/mach/clock-k2l.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/clock-k2l.h
rename to arch/arm/mach-keystone/include/mach/clock-k2l.h
diff --git a/arch/arm/include/asm/arch-keystone/clock.h b/arch/arm/mach-keystone/include/mach/clock.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/clock.h
rename to arch/arm/mach-keystone/include/mach/clock.h
diff --git a/arch/arm/include/asm/arch-keystone/clock_defs.h b/arch/arm/mach-keystone/include/mach/clock_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/clock_defs.h
rename to arch/arm/mach-keystone/include/mach/clock_defs.h
diff --git a/arch/arm/include/asm/arch-keystone/ddr3.h b/arch/arm/mach-keystone/include/mach/ddr3.h
similarity index 93%
rename from arch/arm/include/asm/arch-keystone/ddr3.h
rename to arch/arm/mach-keystone/include/mach/ddr3.h
index b044d6f..a22c237 100644
--- a/arch/arm/include/asm/arch-keystone/ddr3.h
+++ b/arch/arm/mach-keystone/include/mach/ddr3.h
@@ -48,10 +48,9 @@
 	unsigned int sdrfc;
 };
 
-void ddr3_init(void);
-int ddr3_get_size(void);
+u32 ddr3_init(void);
 void ddr3_reset_ddrphy(void);
-void ddr3_init_ecc(u32 base);
+void ddr3_init_ecc(u32 base, u32 ddr3_size);
 void ddr3_disable_ecc(u32 base);
 void ddr3_check_ecc_int(u32 base);
 int ddr3_ecc_support_rmw(u32 base);
diff --git a/arch/arm/include/asm/arch-keystone/hardware-k2e.h b/arch/arm/mach-keystone/include/mach/hardware-k2e.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/hardware-k2e.h
rename to arch/arm/mach-keystone/include/mach/hardware-k2e.h
diff --git a/arch/arm/include/asm/arch-keystone/hardware-k2hk.h b/arch/arm/mach-keystone/include/mach/hardware-k2hk.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/hardware-k2hk.h
rename to arch/arm/mach-keystone/include/mach/hardware-k2hk.h
diff --git a/arch/arm/include/asm/arch-keystone/hardware-k2l.h b/arch/arm/mach-keystone/include/mach/hardware-k2l.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/hardware-k2l.h
rename to arch/arm/mach-keystone/include/mach/hardware-k2l.h
diff --git a/arch/arm/include/asm/arch-keystone/hardware.h b/arch/arm/mach-keystone/include/mach/hardware.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/hardware.h
rename to arch/arm/mach-keystone/include/mach/hardware.h
diff --git a/arch/arm/include/asm/arch-keystone/i2c_defs.h b/arch/arm/mach-keystone/include/mach/i2c_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/i2c_defs.h
rename to arch/arm/mach-keystone/include/mach/i2c_defs.h
diff --git a/arch/arm/include/asm/arch-keystone/mon.h b/arch/arm/mach-keystone/include/mach/mon.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/mon.h
rename to arch/arm/mach-keystone/include/mach/mon.h
diff --git a/arch/arm/include/asm/arch-keystone/msmc.h b/arch/arm/mach-keystone/include/mach/msmc.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/msmc.h
rename to arch/arm/mach-keystone/include/mach/msmc.h
diff --git a/arch/arm/include/asm/arch-keystone/psc_defs.h b/arch/arm/mach-keystone/include/mach/psc_defs.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/psc_defs.h
rename to arch/arm/mach-keystone/include/mach/psc_defs.h
diff --git a/arch/arm/include/asm/arch-keystone/xhci-keystone.h b/arch/arm/mach-keystone/include/mach/xhci-keystone.h
similarity index 100%
rename from arch/arm/include/asm/arch-keystone/xhci-keystone.h
rename to arch/arm/mach-keystone/include/mach/xhci-keystone.h
diff --git a/arch/arm/cpu/armv7/keystone/init.c b/arch/arm/mach-keystone/init.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/init.c
rename to arch/arm/mach-keystone/init.c
diff --git a/arch/arm/cpu/armv7/keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/keystone.c
rename to arch/arm/mach-keystone/keystone.c
diff --git a/arch/arm/cpu/armv7/keystone/msmc.c b/arch/arm/mach-keystone/msmc.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/msmc.c
rename to arch/arm/mach-keystone/msmc.c
diff --git a/arch/arm/cpu/armv7/keystone/psc.c b/arch/arm/mach-keystone/psc.c
similarity index 100%
rename from arch/arm/cpu/armv7/keystone/psc.c
rename to arch/arm/mach-keystone/psc.c
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
similarity index 100%
rename from arch/arm/cpu/arm926ejs/kirkwood/Kconfig
rename to arch/arm/mach-kirkwood/Kconfig
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
similarity index 100%
rename from arch/arm/cpu/arm926ejs/kirkwood/Makefile
rename to arch/arm/mach-kirkwood/Makefile
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cache.c b/arch/arm/mach-kirkwood/cache.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/kirkwood/cache.c
rename to arch/arm/mach-kirkwood/cache.c
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/kirkwood/cpu.c
rename to arch/arm/mach-kirkwood/cpu.c
diff --git a/arch/arm/include/asm/arch-kirkwood/config.h b/arch/arm/mach-kirkwood/include/mach/config.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/config.h
rename to arch/arm/mach-kirkwood/include/mach/config.h
diff --git a/arch/arm/include/asm/arch-kirkwood/cpu.h b/arch/arm/mach-kirkwood/include/mach/cpu.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/cpu.h
rename to arch/arm/mach-kirkwood/include/mach/cpu.h
diff --git a/arch/arm/include/asm/arch-kirkwood/gpio.h b/arch/arm/mach-kirkwood/include/mach/gpio.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/gpio.h
rename to arch/arm/mach-kirkwood/include/mach/gpio.h
diff --git a/arch/arm/include/asm/arch-kirkwood/kw88f6192.h b/arch/arm/mach-kirkwood/include/mach/kw88f6192.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/kw88f6192.h
rename to arch/arm/mach-kirkwood/include/mach/kw88f6192.h
diff --git a/arch/arm/include/asm/arch-kirkwood/kw88f6281.h b/arch/arm/mach-kirkwood/include/mach/kw88f6281.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/kw88f6281.h
rename to arch/arm/mach-kirkwood/include/mach/kw88f6281.h
diff --git a/arch/arm/include/asm/arch-kirkwood/mpp.h b/arch/arm/mach-kirkwood/include/mach/mpp.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/mpp.h
rename to arch/arm/mach-kirkwood/include/mach/mpp.h
diff --git a/arch/arm/include/asm/arch-kirkwood/soc.h b/arch/arm/mach-kirkwood/include/mach/soc.h
similarity index 100%
rename from arch/arm/include/asm/arch-kirkwood/soc.h
rename to arch/arm/mach-kirkwood/include/mach/soc.h
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/kirkwood/mpp.c
rename to arch/arm/mach-kirkwood/mpp.c
diff --git a/arch/arm/cpu/arm926ejs/nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
similarity index 100%
rename from arch/arm/cpu/arm926ejs/nomadik/Kconfig
rename to arch/arm/mach-nomadik/Kconfig
diff --git a/arch/arm/cpu/arm926ejs/nomadik/Makefile b/arch/arm/mach-nomadik/Makefile
similarity index 100%
rename from arch/arm/cpu/arm926ejs/nomadik/Makefile
rename to arch/arm/mach-nomadik/Makefile
diff --git a/arch/arm/cpu/arm926ejs/nomadik/gpio.c b/arch/arm/mach-nomadik/gpio.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/nomadik/gpio.c
rename to arch/arm/mach-nomadik/gpio.c
diff --git a/arch/arm/include/asm/arch-nomadik/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h
similarity index 100%
rename from arch/arm/include/asm/arch-nomadik/gpio.h
rename to arch/arm/mach-nomadik/include/mach/gpio.h
diff --git a/arch/arm/include/asm/arch-nomadik/mtu.h b/arch/arm/mach-nomadik/include/mach/mtu.h
similarity index 100%
rename from arch/arm/include/asm/arch-nomadik/mtu.h
rename to arch/arm/mach-nomadik/include/mach/mtu.h
diff --git a/arch/arm/cpu/arm926ejs/nomadik/reset.S b/arch/arm/mach-nomadik/reset.S
similarity index 100%
rename from arch/arm/cpu/arm926ejs/nomadik/reset.S
rename to arch/arm/mach-nomadik/reset.S
diff --git a/arch/arm/cpu/arm926ejs/nomadik/timer.c b/arch/arm/mach-nomadik/timer.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/nomadik/timer.c
rename to arch/arm/mach-nomadik/timer.c
diff --git a/arch/arm/cpu/arm926ejs/orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/Kconfig
rename to arch/arm/mach-orion5x/Kconfig
diff --git a/arch/arm/cpu/arm926ejs/orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/Makefile
rename to arch/arm/mach-orion5x/Makefile
diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/mach-orion5x/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/cpu.c
rename to arch/arm/mach-orion5x/cpu.c
diff --git a/arch/arm/cpu/arm926ejs/orion5x/dram.c b/arch/arm/mach-orion5x/dram.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/dram.c
rename to arch/arm/mach-orion5x/dram.c
diff --git a/arch/arm/include/asm/arch-orion5x/cpu.h b/arch/arm/mach-orion5x/include/mach/cpu.h
similarity index 100%
rename from arch/arm/include/asm/arch-orion5x/cpu.h
rename to arch/arm/mach-orion5x/include/mach/cpu.h
diff --git a/arch/arm/include/asm/arch-orion5x/mv88f5182.h b/arch/arm/mach-orion5x/include/mach/mv88f5182.h
similarity index 100%
rename from arch/arm/include/asm/arch-orion5x/mv88f5182.h
rename to arch/arm/mach-orion5x/include/mach/mv88f5182.h
diff --git a/arch/arm/include/asm/arch-orion5x/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h
similarity index 100%
rename from arch/arm/include/asm/arch-orion5x/orion5x.h
rename to arch/arm/mach-orion5x/include/mach/orion5x.h
diff --git a/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S b/arch/arm/mach-orion5x/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S
rename to arch/arm/mach-orion5x/lowlevel_init.S
diff --git a/arch/arm/cpu/arm926ejs/orion5x/timer.c b/arch/arm/mach-orion5x/timer.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/orion5x/timer.c
rename to arch/arm/mach-orion5x/timer.c
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
new file mode 100644
index 0000000..3a8e2b1
--- /dev/null
+++ b/arch/arm/mach-tegra/Kconfig
@@ -0,0 +1,52 @@
+if TEGRA
+
+choice
+	prompt "Tegra SoC select"
+
+config TEGRA20
+	bool "Tegra20 family"
+
+config TEGRA30
+	bool "Tegra30 family"
+
+config TEGRA114
+	bool "Tegra114 family"
+
+config TEGRA124
+	bool "Tegra124 family"
+
+endchoice
+
+config SYS_MALLOC_F
+	default y
+
+config SYS_MALLOC_F_LEN
+	default 0x1800
+
+config USE_PRIVATE_LIBGCC
+	default y if SPL_BUILD
+
+config DM
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
+config DM_SPI
+	default y if !SPL_BUILD
+
+config DM_SPI_FLASH
+	default y if !SPL_BUILD
+
+config DM_I2C
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+source "arch/arm/mach-tegra/tegra20/Kconfig"
+source "arch/arm/mach-tegra/tegra30/Kconfig"
+source "arch/arm/mach-tegra/tegra114/Kconfig"
+source "arch/arm/mach-tegra/tegra124/Kconfig"
+
+endif
diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/mach-tegra/Makefile
similarity index 61%
rename from arch/arm/cpu/tegra-common/Makefile
rename to arch/arm/mach-tegra/Makefile
index a78869e..04cef0a 100644
--- a/arch/arm/cpu/tegra-common/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -7,6 +7,13 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifdef CONFIG_SPL_BUILD
+obj-y += spl.o
+obj-y += cpu.o
+else
+obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
+endif
+
 obj-y += ap.o
 obj-y += board.o
 obj-y += cache.o
@@ -17,3 +24,8 @@
 obj-y += xusb-padctl.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
 obj-$(CONFIG_TEGRA124) += vpr.o
+
+obj-$(CONFIG_TEGRA20) += tegra20/
+obj-$(CONFIG_TEGRA30) += tegra30/
+obj-$(CONFIG_TEGRA114) += tegra114/
+obj-$(CONFIG_TEGRA124) += tegra124/
diff --git a/arch/arm/cpu/tegra-common/ap.c b/arch/arm/mach-tegra/ap.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/ap.c
rename to arch/arm/mach-tegra/ap.c
diff --git a/arch/arm/cpu/tegra-common/board.c b/arch/arm/mach-tegra/board.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/board.c
rename to arch/arm/mach-tegra/board.c
diff --git a/arch/arm/cpu/tegra-common/cache.c b/arch/arm/mach-tegra/cache.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/cache.c
rename to arch/arm/mach-tegra/cache.c
diff --git a/arch/arm/cpu/tegra-common/clock.c b/arch/arm/mach-tegra/clock.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/clock.c
rename to arch/arm/mach-tegra/clock.c
diff --git a/arch/arm/cpu/armv7/tegra-common/cmd_enterrcm.c b/arch/arm/mach-tegra/cmd_enterrcm.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra-common/cmd_enterrcm.c
rename to arch/arm/mach-tegra/cmd_enterrcm.c
diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.c b/arch/arm/mach-tegra/cpu.c
similarity index 100%
rename from arch/arm/cpu/arm720t/tegra-common/cpu.c
rename to arch/arm/mach-tegra/cpu.c
diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.h b/arch/arm/mach-tegra/cpu.h
similarity index 100%
rename from arch/arm/cpu/arm720t/tegra-common/cpu.h
rename to arch/arm/mach-tegra/cpu.h
diff --git a/arch/arm/cpu/tegra-common/lowlevel_init.S b/arch/arm/mach-tegra/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/tegra-common/lowlevel_init.S
rename to arch/arm/mach-tegra/lowlevel_init.S
diff --git a/arch/arm/cpu/tegra-common/pinmux-common.c b/arch/arm/mach-tegra/pinmux-common.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/pinmux-common.c
rename to arch/arm/mach-tegra/pinmux-common.c
diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/mach-tegra/powergate.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/powergate.c
rename to arch/arm/mach-tegra/powergate.c
diff --git a/arch/arm/cpu/arm720t/tegra-common/spl.c b/arch/arm/mach-tegra/spl.c
similarity index 100%
rename from arch/arm/cpu/arm720t/tegra-common/spl.c
rename to arch/arm/mach-tegra/spl.c
diff --git a/arch/arm/cpu/tegra-common/sys_info.c b/arch/arm/mach-tegra/sys_info.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/sys_info.c
rename to arch/arm/mach-tegra/sys_info.c
diff --git a/arch/arm/cpu/armv7/tegra114/Kconfig b/arch/arm/mach-tegra/tegra114/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/tegra114/Kconfig
rename to arch/arm/mach-tegra/tegra114/Kconfig
diff --git a/arch/arm/cpu/tegra114-common/Makefile b/arch/arm/mach-tegra/tegra114/Makefile
similarity index 88%
rename from arch/arm/cpu/tegra114-common/Makefile
rename to arch/arm/mach-tegra/tegra114/Makefile
index d959b57..7489f5f 100644
--- a/arch/arm/cpu/tegra114-common/Makefile
+++ b/arch/arm/mach-tegra/tegra114/Makefile
@@ -1,9 +1,6 @@
 #
 # Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
 #
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
 # version 2, as published by the Free Software Foundation.
@@ -17,4 +14,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+obj-$(CONFIG_SPL_BUILD) += cpu.o
+
 obj-y	+= clock.o funcmux.o pinmux.o
diff --git a/arch/arm/cpu/tegra114-common/clock.c b/arch/arm/mach-tegra/tegra114/clock.c
similarity index 100%
rename from arch/arm/cpu/tegra114-common/clock.c
rename to arch/arm/mach-tegra/tegra114/clock.c
diff --git a/arch/arm/cpu/arm720t/tegra114/cpu.c b/arch/arm/mach-tegra/tegra114/cpu.c
similarity index 99%
rename from arch/arm/cpu/arm720t/tegra114/cpu.c
rename to arch/arm/mach-tegra/tegra114/cpu.c
index 5ed3bb9..18dc1af 100644
--- a/arch/arm/cpu/arm720t/tegra114/cpu.c
+++ b/arch/arm/mach-tegra/tegra114/cpu.c
@@ -22,7 +22,7 @@
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
-#include "../tegra-common/cpu.h"
+#include "../cpu.h"
 
 /* Tegra114-specific CPU init code */
 static void enable_cpu_power_rail(void)
diff --git a/arch/arm/cpu/tegra114-common/funcmux.c b/arch/arm/mach-tegra/tegra114/funcmux.c
similarity index 100%
rename from arch/arm/cpu/tegra114-common/funcmux.c
rename to arch/arm/mach-tegra/tegra114/funcmux.c
diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/mach-tegra/tegra114/pinmux.c
similarity index 100%
rename from arch/arm/cpu/tegra114-common/pinmux.c
rename to arch/arm/mach-tegra/tegra114/pinmux.c
diff --git a/arch/arm/cpu/armv7/tegra124/Kconfig b/arch/arm/mach-tegra/tegra124/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/tegra124/Kconfig
rename to arch/arm/mach-tegra/tegra124/Kconfig
diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/mach-tegra/tegra124/Makefile
similarity index 84%
rename from arch/arm/cpu/tegra124-common/Makefile
rename to arch/arm/mach-tegra/tegra124/Makefile
index 7b59fb1..ef2da29 100644
--- a/arch/arm/cpu/tegra124-common/Makefile
+++ b/arch/arm/mach-tegra/tegra124/Makefile
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_SPL_BUILD) += cpu.o
+
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
diff --git a/arch/arm/cpu/tegra124-common/clock.c b/arch/arm/mach-tegra/tegra124/clock.c
similarity index 100%
rename from arch/arm/cpu/tegra124-common/clock.c
rename to arch/arm/mach-tegra/tegra124/clock.c
diff --git a/arch/arm/cpu/arm720t/tegra124/cpu.c b/arch/arm/mach-tegra/tegra124/cpu.c
similarity index 99%
rename from arch/arm/cpu/arm720t/tegra124/cpu.c
rename to arch/arm/mach-tegra/tegra124/cpu.c
index 6ff6aeb..974f203 100644
--- a/arch/arm/cpu/arm720t/tegra124/cpu.c
+++ b/arch/arm/mach-tegra/tegra124/cpu.c
@@ -15,7 +15,7 @@
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/ap.h>
-#include "../tegra-common/cpu.h"
+#include "../cpu.h"
 
 /* Tegra124-specific CPU init code */
 
diff --git a/arch/arm/cpu/tegra124-common/funcmux.c b/arch/arm/mach-tegra/tegra124/funcmux.c
similarity index 100%
rename from arch/arm/cpu/tegra124-common/funcmux.c
rename to arch/arm/mach-tegra/tegra124/funcmux.c
diff --git a/arch/arm/cpu/tegra124-common/pinmux.c b/arch/arm/mach-tegra/tegra124/pinmux.c
similarity index 100%
rename from arch/arm/cpu/tegra124-common/pinmux.c
rename to arch/arm/mach-tegra/tegra124/pinmux.c
diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/mach-tegra/tegra124/xusb-padctl.c
similarity index 100%
rename from arch/arm/cpu/tegra124-common/xusb-padctl.c
rename to arch/arm/mach-tegra/tegra124/xusb-padctl.c
diff --git a/arch/arm/cpu/armv7/tegra20/Kconfig b/arch/arm/mach-tegra/tegra20/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/tegra20/Kconfig
rename to arch/arm/mach-tegra/tegra20/Kconfig
diff --git a/arch/arm/cpu/tegra20-common/Makefile b/arch/arm/mach-tegra/tegra20/Makefile
similarity index 76%
rename from arch/arm/cpu/tegra20-common/Makefile
rename to arch/arm/mach-tegra/tegra20/Makefile
index 0e4b3fc..d48f9bb 100644
--- a/arch/arm/cpu/tegra20-common/Makefile
+++ b/arch/arm/mach-tegra/tegra20/Makefile
@@ -1,12 +1,16 @@
 #
 # (C) Copyright 2010,2011 Nvidia Corporation.
 #
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifdef CONFIG_SPL_BUILD
+obj-y	+= cpu.o
+else
+obj-$(CONFIG_PWM_TEGRA) += pwm.o
+obj-$(CONFIG_VIDEO_TEGRA) += display.o
+endif
+
 # The AVP is ARMv4T architecture so we must use special compiler
 # flags for any startup files it might use.
 CFLAGS_warmboot_avp.o += -march=armv4t
diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/mach-tegra/tegra20/clock.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/clock.c
rename to arch/arm/mach-tegra/tegra20/clock.c
diff --git a/arch/arm/cpu/arm720t/tegra20/cpu.c b/arch/arm/mach-tegra/tegra20/cpu.c
similarity index 97%
rename from arch/arm/cpu/arm720t/tegra20/cpu.c
rename to arch/arm/mach-tegra/tegra20/cpu.c
index 2533899..67f49d7 100644
--- a/arch/arm/cpu/arm720t/tegra20/cpu.c
+++ b/arch/arm/mach-tegra/tegra20/cpu.c
@@ -18,7 +18,7 @@
 #include <asm/io.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/pmc.h>
-#include "../tegra-common/cpu.h"
+#include "../cpu.h"
 
 static void enable_cpu_power_rail(void)
 {
diff --git a/arch/arm/cpu/tegra20-common/crypto.c b/arch/arm/mach-tegra/tegra20/crypto.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/crypto.c
rename to arch/arm/mach-tegra/tegra20/crypto.c
diff --git a/arch/arm/cpu/tegra20-common/crypto.h b/arch/arm/mach-tegra/tegra20/crypto.h
similarity index 100%
rename from arch/arm/cpu/tegra20-common/crypto.h
rename to arch/arm/mach-tegra/tegra20/crypto.h
diff --git a/arch/arm/cpu/armv7/tegra20/display.c b/arch/arm/mach-tegra/tegra20/display.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra20/display.c
rename to arch/arm/mach-tegra/tegra20/display.c
diff --git a/arch/arm/cpu/tegra20-common/emc.c b/arch/arm/mach-tegra/tegra20/emc.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/emc.c
rename to arch/arm/mach-tegra/tegra20/emc.c
diff --git a/arch/arm/cpu/tegra20-common/funcmux.c b/arch/arm/mach-tegra/tegra20/funcmux.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/funcmux.c
rename to arch/arm/mach-tegra/tegra20/funcmux.c
diff --git a/arch/arm/cpu/tegra20-common/pinmux.c b/arch/arm/mach-tegra/tegra20/pinmux.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/pinmux.c
rename to arch/arm/mach-tegra/tegra20/pinmux.c
diff --git a/arch/arm/cpu/tegra20-common/pmu.c b/arch/arm/mach-tegra/tegra20/pmu.c
similarity index 96%
rename from arch/arm/cpu/tegra20-common/pmu.c
rename to arch/arm/mach-tegra/tegra20/pmu.c
index 36a76a2..a774246 100644
--- a/arch/arm/cpu/tegra20-common/pmu.c
+++ b/arch/arm/mach-tegra/tegra20/pmu.c
@@ -52,7 +52,7 @@
 		debug("%s: Cannot find DVC I2C bus\n", __func__);
 		return ret;
 	}
-	ret = i2c_get_chip(bus, PMI_I2C_ADDRESS, &dev);
+	ret = i2c_get_chip(bus, PMI_I2C_ADDRESS, 1, &dev);
 	if (ret) {
 		debug("%s: Cannot find DVC I2C chip\n", __func__);
 		return ret;
diff --git a/arch/arm/cpu/armv7/tegra20/pwm.c b/arch/arm/mach-tegra/tegra20/pwm.c
similarity index 100%
rename from arch/arm/cpu/armv7/tegra20/pwm.c
rename to arch/arm/mach-tegra/tegra20/pwm.c
diff --git a/arch/arm/cpu/tegra20-common/warmboot.c b/arch/arm/mach-tegra/tegra20/warmboot.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/warmboot.c
rename to arch/arm/mach-tegra/tegra20/warmboot.c
diff --git a/arch/arm/cpu/tegra20-common/warmboot_avp.c b/arch/arm/mach-tegra/tegra20/warmboot_avp.c
similarity index 100%
rename from arch/arm/cpu/tegra20-common/warmboot_avp.c
rename to arch/arm/mach-tegra/tegra20/warmboot_avp.c
diff --git a/arch/arm/cpu/tegra20-common/warmboot_avp.h b/arch/arm/mach-tegra/tegra20/warmboot_avp.h
similarity index 100%
rename from arch/arm/cpu/tegra20-common/warmboot_avp.h
rename to arch/arm/mach-tegra/tegra20/warmboot_avp.h
diff --git a/arch/arm/cpu/armv7/tegra30/Kconfig b/arch/arm/mach-tegra/tegra30/Kconfig
similarity index 100%
rename from arch/arm/cpu/armv7/tegra30/Kconfig
rename to arch/arm/mach-tegra/tegra30/Kconfig
diff --git a/arch/arm/cpu/tegra30-common/Makefile b/arch/arm/mach-tegra/tegra30/Makefile
similarity index 88%
rename from arch/arm/cpu/tegra30-common/Makefile
rename to arch/arm/mach-tegra/tegra30/Makefile
index d2d616e..bc250de 100644
--- a/arch/arm/cpu/tegra30-common/Makefile
+++ b/arch/arm/mach-tegra/tegra30/Makefile
@@ -1,9 +1,6 @@
 #
 # Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
 #
-# (C) Copyright 2000-2008
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
 # version 2, as published by the Free Software Foundation.
@@ -17,4 +14,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+obj-$(CONFIG_SPL_BUILD) += cpu.o
+
 obj-y	+= clock.o funcmux.o pinmux.o
diff --git a/arch/arm/cpu/tegra30-common/clock.c b/arch/arm/mach-tegra/tegra30/clock.c
similarity index 100%
rename from arch/arm/cpu/tegra30-common/clock.c
rename to arch/arm/mach-tegra/tegra30/clock.c
diff --git a/arch/arm/cpu/arm720t/tegra30/cpu.c b/arch/arm/mach-tegra/tegra30/cpu.c
similarity index 99%
rename from arch/arm/cpu/arm720t/tegra30/cpu.c
rename to arch/arm/mach-tegra/tegra30/cpu.c
index 9003902..c76e74c 100644
--- a/arch/arm/cpu/arm720t/tegra30/cpu.c
+++ b/arch/arm/mach-tegra/tegra30/cpu.c
@@ -22,7 +22,7 @@
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/tegra_i2c.h>
-#include "../tegra-common/cpu.h"
+#include "../cpu.h"
 
 /* Tegra30-specific CPU init code */
 void tegra_i2c_ll_write_addr(uint addr, uint config)
diff --git a/arch/arm/cpu/tegra30-common/funcmux.c b/arch/arm/mach-tegra/tegra30/funcmux.c
similarity index 100%
rename from arch/arm/cpu/tegra30-common/funcmux.c
rename to arch/arm/mach-tegra/tegra30/funcmux.c
diff --git a/arch/arm/cpu/tegra30-common/pinmux.c b/arch/arm/mach-tegra/tegra30/pinmux.c
similarity index 100%
rename from arch/arm/cpu/tegra30-common/pinmux.c
rename to arch/arm/mach-tegra/tegra30/pinmux.c
diff --git a/arch/arm/cpu/tegra-common/vpr.c b/arch/arm/mach-tegra/vpr.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/vpr.c
rename to arch/arm/mach-tegra/vpr.c
diff --git a/arch/arm/cpu/tegra-common/xusb-padctl.c b/arch/arm/mach-tegra/xusb-padctl.c
similarity index 100%
rename from arch/arm/cpu/tegra-common/xusb-padctl.c
rename to arch/arm/mach-tegra/xusb-padctl.c
diff --git a/arch/arm/cpu/arm926ejs/versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
similarity index 100%
rename from arch/arm/cpu/arm926ejs/versatile/Kconfig
rename to arch/arm/mach-versatile/Kconfig
diff --git a/arch/arm/cpu/arm926ejs/versatile/Makefile b/arch/arm/mach-versatile/Makefile
similarity index 100%
rename from arch/arm/cpu/arm926ejs/versatile/Makefile
rename to arch/arm/mach-versatile/Makefile
diff --git a/arch/arm/cpu/arm926ejs/versatile/reset.S b/arch/arm/mach-versatile/reset.S
similarity index 100%
rename from arch/arm/cpu/arm926ejs/versatile/reset.S
rename to arch/arm/mach-versatile/reset.S
diff --git a/arch/arm/cpu/arm926ejs/versatile/timer.c b/arch/arm/mach-versatile/timer.c
similarity index 100%
rename from arch/arm/cpu/arm926ejs/versatile/timer.c
rename to arch/arm/mach-versatile/timer.c
diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile
index 9dcab69..de243fe 100644
--- a/arch/arm/mvebu-common/Makefile
+++ b/arch/arm/mvebu-common/Makefile
@@ -10,3 +10,5 @@
 obj-y	+= gpio.o
 obj-$(CONFIG_ARMADA_XP) += mbus.o
 obj-y	+= timer.o
+
+obj-y	+= serdes/
diff --git a/arch/arm/mvebu-common/serdes/Makefile b/arch/arm/mvebu-common/serdes/Makefile
new file mode 100644
index 0000000..a380fee
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/Makefile
@@ -0,0 +1,6 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_SPL_BUILD)	= high_speed_env_lib.o
+obj-$(CONFIG_SPL_BUILD)	+= high_speed_env_spec.o
diff --git a/arch/arm/mvebu-common/serdes/board_env_spec.h b/arch/arm/mvebu-common/serdes/board_env_spec.h
new file mode 100644
index 0000000..36e0ed8
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/board_env_spec.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __BOARD_ENV_SPEC
+#define __BOARD_ENV_SPEC
+
+/* Board specific configuration */
+
+/* KW40 */
+#define MV_6710_DEV_ID			0x6710
+
+#define MV_6710_Z1_REV			0x0
+#define MV_6710_Z1_ID			((MV_6710_DEV_ID << 16) | MV_6710_Z1_REV)
+#define MV_6710_Z1_NAME			"MV6710 Z1"
+
+/* Armada XP Family */
+#define MV_78130_DEV_ID			0x7813
+#define MV_78160_DEV_ID			0x7816
+#define MV_78230_DEV_ID			0x7823
+#define MV_78260_DEV_ID			0x7826
+#define MV_78460_DEV_ID			0x7846
+#define MV_78000_DEV_ID			0x7888
+
+#define MV_FPGA_DEV_ID			0x2107
+
+#define MV_78XX0_Z1_REV			0x0
+
+/* boards ID numbers */
+#define BOARD_ID_BASE			0x0
+
+/* New board ID numbers */
+#define DB_88F78XX0_BP_ID		(BOARD_ID_BASE)
+#define RD_78460_SERVER_ID		(DB_88F78XX0_BP_ID + 1)
+#define DB_78X60_PCAC_ID		(RD_78460_SERVER_ID + 1)
+#define FPGA_88F78XX0_ID		(DB_78X60_PCAC_ID + 1)
+#define DB_88F78XX0_BP_REV2_ID		(FPGA_88F78XX0_ID + 1)
+#define RD_78460_NAS_ID			(DB_88F78XX0_BP_REV2_ID + 1)
+#define DB_78X60_AMC_ID			(RD_78460_NAS_ID + 1)
+#define DB_78X60_PCAC_REV2_ID		(DB_78X60_AMC_ID + 1)
+#define RD_78460_SERVER_REV2_ID		(DB_78X60_PCAC_REV2_ID + 1)
+#define DB_784MP_GP_ID			(RD_78460_SERVER_REV2_ID + 1)
+#define RD_78460_CUSTOMER_ID		(DB_784MP_GP_ID + 1)
+#define MV_MAX_BOARD_ID			(RD_78460_CUSTOMER_ID + 1)
+#define INVALID_BAORD_ID		0xFFFFFFFF
+
+/* Sample at Reset */
+#define MPP_SAMPLE_AT_RESET(id)		(0x18230 + (id * 4))
+
+/* BIOS Modes related defines */
+
+#define SAR0_BOOTWIDTH_OFFSET		3
+#define SAR0_BOOTWIDTH_MASK		(0x3 << SAR0_BOOTWIDTH_OFFSET)
+#define SAR0_BOOTSRC_OFFSET		5
+#define SAR0_BOOTSRC_MASK		(0xF << SAR0_BOOTSRC_OFFSET)
+
+#define SAR0_L2_SIZE_OFFSET		19
+#define SAR0_L2_SIZE_MASK		(0x3 << SAR0_L2_SIZE_OFFSET)
+#define SAR0_CPU_FREQ_OFFSET		21
+#define SAR0_CPU_FREQ_MASK		(0x7 << SAR0_CPU_FREQ_OFFSET)
+#define SAR0_FABRIC_FREQ_OFFSET		24
+#define SAR0_FABRIC_FREQ_MASK		(0xF << SAR0_FABRIC_FREQ_OFFSET)
+#define SAR0_CPU0CORE_OFFSET		31
+#define SAR0_CPU0CORE_MASK		(0x1 << SAR0_CPU0CORE_OFFSET)
+#define SAR1_CPU0CORE_OFFSET		0
+#define SAR1_CPU0CORE_MASK		(0x1 << SAR1_CPU0CORE_OFFSET)
+
+#define PEX_CLK_100MHZ_OFFSET		2
+#define PEX_CLK_100MHZ_MASK		(0x1 << PEX_CLK_100MHZ_OFFSET)
+
+#define SAR1_FABRIC_MODE_OFFSET		19
+#define SAR1_FABRIC_MODE_MASK		(0x1 << SAR1_FABRIC_MODE_OFFSET)
+#define SAR1_CPU_MODE_OFFSET		20
+#define SAR1_CPU_MODE_MASK		(0x1 << SAR1_CPU_MODE_OFFSET)
+
+#define SAR_CPU_FAB_GET(cpu, fab)	(((cpu & 0x7) << 21) | ((fab & 0xF) << 24))
+
+
+#define CORE_AVS_CONTROL_0REG		0x18300
+#define CORE_AVS_CONTROL_2REG		0x18308
+#define CPU_AVS_CONTROL2_REG		0x20868
+#define CPU_AVS_CONTROL0_REG		0x20860
+#define GENERAL_PURPOSE_RESERVED0_REG	0x182E0
+
+#define MSAR_TCLK_OFFS			28
+#define MSAR_TCLK_MASK			(0x1 << MSAR_TCLK_OFFS)
+
+
+/* Controler environment registers offsets */
+#define GEN_PURP_RES_1_REG		0x182F4
+#define GEN_PURP_RES_2_REG		0x182F8
+
+/* registers offsets */
+#define MV_GPP_REGS_OFFSET(unit)	(0x18100 + ((unit) * 0x40))
+#define MPP_CONTROL_REG(id)		(0x18000 + (id * 4))
+#define MV_GPP_REGS_BASE(unit)		(MV_GPP_REGS_OFFSET(unit))
+#define MV_GPP_REGS_BASE_0		(MV_GPP_REGS_OFFSET_0)
+
+#define GPP_DATA_OUT_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x00)
+#define GPP_DATA_OUT_REG_0		(MV_GPP_REGS_BASE_0 + 0x00)	/* Used in .S files */
+#define GPP_DATA_OUT_EN_REG(grp)	(MV_GPP_REGS_BASE(grp) + 0x04)
+#define GPP_BLINK_EN_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x08)
+#define GPP_DATA_IN_POL_REG(grp)	(MV_GPP_REGS_BASE(grp) + 0x0C)
+#define GPP_DATA_IN_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x10)
+#define GPP_INT_CAUSE_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x14)
+#define GPP_INT_MASK_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x18)
+#define GPP_INT_LVL_REG(grp)		(MV_GPP_REGS_BASE(grp) + 0x1C)
+#define GPP_OUT_SET_REG(grp)		(0x18130 + ((grp) * 0x40))
+#define GPP_64_66_DATA_OUT_SET_REG	0x181A4
+#define GPP_OUT_CLEAR_REG(grp)		(0x18134 + ((grp) * 0x40))
+#define GPP_64_66_DATA_OUT_CLEAR_REG	0x181B0
+#define GPP_FUNC_SELECT_REG		(MV_GPP_REGS_BASE(0) + 0x40)
+
+#define MV_GPP66			(1 << 2)
+
+/* Relevant for MV78XX0 */
+#define GPP_DATA_OUT_SET_REG		(MV_GPP_REGS_BASE(0) + 0x20)
+#define GPP_DATA_OUT_CLEAR_REG		(MV_GPP_REGS_BASE(0) + 0x24)
+
+/* This define describes the maximum number of supported PEX Interfaces */
+#define MV_PEX_MAX_IF			10
+#define MV_PEX_MAX_UNIT			4
+
+#define MV_SERDES_NUM_TO_PEX_NUM(num)	((num < 8) ? (num) : (8 + (num / 12)))
+
+#define PEX_PHY_ACCESS_REG(unit)	(0x40000 + ((unit) % 2 * 0x40000) + \
+					 ((unit)/2 * 0x2000) + 0x1B00)
+
+#define SATA_BASE_REG(port)		(0xA2000 + (port)*0x2000)
+
+#define SATA_PWR_PLL_CTRL_REG(port)	(SATA_BASE_REG(port) + 0x804)
+#define SATA_DIG_LP_ENA_REG(port)	(SATA_BASE_REG(port) + 0x88C)
+#define SATA_REF_CLK_SEL_REG(port)	(SATA_BASE_REG(port) + 0x918)
+#define SATA_COMPHY_CTRL_REG(port)	(SATA_BASE_REG(port) + 0x920)
+#define SATA_LP_PHY_EXT_CTRL_REG(port)	(SATA_BASE_REG(port) + 0x058)
+#define SATA_LP_PHY_EXT_STAT_REG(port)	(SATA_BASE_REG(port) + 0x05C)
+#define SATA_IMP_TX_SSC_CTRL_REG(port)	(SATA_BASE_REG(port) + 0x810)
+#define SATA_GEN_1_SET_0_REG(port)	(SATA_BASE_REG(port) + 0x834)
+#define SATA_GEN_1_SET_1_REG(port)	(SATA_BASE_REG(port) + 0x838)
+#define SATA_GEN_2_SET_0_REG(port)	(SATA_BASE_REG(port) + 0x83C)
+#define SATA_GEN_2_SET_1_REG(port)	(SATA_BASE_REG(port) + 0x840)
+
+#define MV_ETH_BASE_ADDR		(0x72000)
+#define MV_ETH_REGS_OFFSET(port)	(MV_ETH_BASE_ADDR - ((port) / 2) * \
+					 0x40000 + ((port) % 2) * 0x4000)
+#define MV_ETH_REGS_BASE(port)		MV_ETH_REGS_OFFSET(port)
+
+
+#define SGMII_PWR_PLL_CTRL_REG(port)	(MV_ETH_REGS_BASE(port) + 0xE04)
+#define SGMII_DIG_LP_ENA_REG(port)	(MV_ETH_REGS_BASE(port) + 0xE8C)
+#define SGMII_REF_CLK_SEL_REG(port)	(MV_ETH_REGS_BASE(port) + 0xF18)
+#define SGMII_SERDES_CFG_REG(port)	(MV_ETH_REGS_BASE(port) + 0x4A0)
+#define SGMII_SERDES_STAT_REG(port)	(MV_ETH_REGS_BASE(port) + 0x4A4)
+#define SGMII_COMPHY_CTRL_REG(port)	(MV_ETH_REGS_BASE(port) + 0xF20)
+#define QSGMII_GEN_1_SETTING_REG(port)	(MV_ETH_REGS_BASE(port) + 0xE38)
+#define QSGMII_SERDES_CFG_REG(port)	(MV_ETH_REGS_BASE(port) + 0x4a0)
+
+#define SERDES_LINE_MUX_REG_0_7		0x18270
+#define SERDES_LINE_MUX_REG_8_15	0x18274
+#define QSGMII_CONTROL_1_REG		0x18404
+
+/* SOC_CTRL_REG fields */
+#define SCR_PEX_ENA_OFFS(pex)		((pex) & 0x3)
+#define SCR_PEX_ENA_MASK(pex)		(1 << pex)
+
+#define PCIE0_QUADX1_EN			(1<<7)
+#define PCIE1_QUADX1_EN			(1<<8)
+
+#define SCR_PEX_4BY1_OFFS(pex)		((pex) + 7)
+#define SCR_PEX_4BY1_MASK(pex)		(1 << SCR_PEX_4BY1_OFFS(pex))
+
+#define PCIE1_CLK_OUT_EN_OFF		5
+#define PCIE1_CLK_OUT_EN_MASK		(1 << PCIE1_CLK_OUT_EN_OFF)
+
+#define PCIE0_CLK_OUT_EN_OFF		4
+#define PCIE0_CLK_OUT_EN_MASK		(1 << PCIE0_CLK_OUT_EN_OFF)
+
+#define SCR_PEX0_4BY1_OFFS		7
+#define SCR_PEX0_4BY1_MASK		(1 << SCR_PEX0_4BY1_OFFS)
+
+#define SCR_PEX1_4BY1_OFFS		8
+#define SCR_PEX1_4BY1_MASK		(1 << SCR_PEX1_4BY1_OFFS)
+
+
+#define MV_MISC_REGS_OFFSET		(0x18200)
+#define MV_MISC_REGS_BASE		(MV_MISC_REGS_OFFSET)
+#define SOC_CTRL_REG			(MV_MISC_REGS_BASE + 0x4)
+
+/*
+ * PCI Express Control and Status Registers
+ */
+#define MAX_PEX_DEVICES			32
+#define MAX_PEX_FUNCS			8
+#define MAX_PEX_BUSSES			256
+
+#define PXSR_PEX_BUS_NUM_OFFS		8	/* Bus Number Indication */
+#define PXSR_PEX_BUS_NUM_MASK		(0xff << PXSR_PEX_BUS_NUM_OFFS)
+
+#define PXSR_PEX_DEV_NUM_OFFS		16	/* Device Number Indication */
+#define PXSR_PEX_DEV_NUM_MASK		(0x1f << PXSR_PEX_DEV_NUM_OFFS)
+
+#define PXSR_DL_DOWN			0x1	/* DL_Down indication. */
+#define PXCAR_CONFIG_EN			(1 << 31)
+#define PEX_STATUS_AND_COMMAND		0x004
+#define PXSAC_MABORT			(1 << 29) /* Recieved Master Abort */
+
+/* PCI Express Configuration Address Register */
+
+/* PEX_CFG_ADDR_REG (PXCAR) */
+#define PXCAR_REG_NUM_OFFS		2
+#define PXCAR_REG_NUM_MAX		0x3F
+#define PXCAR_REG_NUM_MASK		(PXCAR_REG_NUM_MAX << PXCAR_REG_NUM_OFFS)
+#define PXCAR_FUNC_NUM_OFFS		8
+#define PXCAR_FUNC_NUM_MAX		0x7
+#define PXCAR_FUNC_NUM_MASK		(PXCAR_FUNC_NUM_MAX << PXCAR_FUNC_NUM_OFFS)
+#define PXCAR_DEVICE_NUM_OFFS		11
+#define PXCAR_DEVICE_NUM_MAX		0x1F
+#define PXCAR_DEVICE_NUM_MASK		(PXCAR_DEVICE_NUM_MAX << PXCAR_DEVICE_NUM_OFFS)
+#define PXCAR_BUS_NUM_OFFS		16
+#define PXCAR_BUS_NUM_MAX		0xFF
+#define PXCAR_BUS_NUM_MASK		(PXCAR_BUS_NUM_MAX << PXCAR_BUS_NUM_OFFS)
+#define PXCAR_EXT_REG_NUM_OFFS		24
+#define PXCAR_EXT_REG_NUM_MAX		0xF
+
+#define PXCAR_REAL_EXT_REG_NUM_OFFS     8
+#define PXCAR_REAL_EXT_REG_NUM_MASK     (0xF << PXCAR_REAL_EXT_REG_NUM_OFFS)
+
+
+#define PEX_CAPABILITIES_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x60)
+#define PEX_LINK_CAPABILITIES_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x6C)
+#define PEX_LINK_CTRL_STATUS_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x70)
+#define PEX_LINK_CTRL_STATUS2_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x90)
+#define PEX_CTRL_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A00)
+#define PEX_STATUS_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A04)
+#define PEX_COMPLT_TMEOUT_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x1A10)
+#define PEX_PWR_MNG_EXT_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A18)
+#define PEX_FLOW_CTRL_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A20)
+#define PEX_DYNMC_WIDTH_MNG_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x1A30)
+#define PEX_ROOT_CMPLX_SSPL_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x1A0C)
+#define PEX_RAM_PARITY_CTRL_REG(if)	((MV_PEX_IF_REGS_BASE(if)) + 0x1A50)
+#define PEX_DBG_CTRL_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A60)
+#define PEX_DBG_STATUS_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1A64)
+
+#define PXLCSR_NEG_LNK_GEN_OFFS		16	/* Negotiated Link GEN */
+#define PXLCSR_NEG_LNK_GEN_MASK		(0xf << PXLCSR_NEG_LNK_GEN_OFFS)
+#define PXLCSR_NEG_LNK_GEN_1_1		(0x1 << PXLCSR_NEG_LNK_GEN_OFFS)
+#define PXLCSR_NEG_LNK_GEN_2_0		(0x2 << PXLCSR_NEG_LNK_GEN_OFFS)
+
+#define PEX_CFG_ADDR_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x18F8)
+#define PEX_CFG_DATA_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x18FC)
+#define PEX_CAUSE_REG(if)		((MV_PEX_IF_REGS_BASE(if)) + 0x1900)
+
+#define PEX_CAPABILITY_REG		0x60
+#define PEX_DEV_CAPABILITY_REG		0x64
+#define PEX_DEV_CTRL_STAT_REG		0x68
+#define PEX_LINK_CAPABILITY_REG		0x6C
+#define PEX_LINK_CTRL_STAT_REG		0x70
+#define PEX_LINK_CTRL_STAT_2_REG	0x90
+
+#endif /* __BOARD_ENV_SPEC */
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_lib.c b/arch/arm/mvebu-common/serdes/high_speed_env_lib.c
new file mode 100644
index 0000000..702273a
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_lib.c
@@ -0,0 +1,1572 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "high_speed_env_spec.h"
+#include "board_env_spec.h"
+
+#define	SERDES_VERION	"2.1.5"
+#define ENDED_OK	"High speed PHY - Ended Successfully\n"
+
+static const u8 serdes_cfg[][SERDES_LAST_UNIT] = BIN_SERDES_CFG;
+
+extern MV_BIN_SERDES_CFG *serdes_info_tbl[];
+
+extern u8 rd78460gp_twsi_dev[];
+extern u8 db88f78xx0rev2_twsi_dev[];
+
+u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs);
+int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
+int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
+
+#define MV_BOARD_PEX_MODULE_ADDR		0x23
+#define MV_BOARD_PEX_MODULE_ID			1
+#define MV_BOARD_ETM_MODULE_ID			2
+
+#define	PEX_MODULE_DETECT		1
+#define	ETM_MODULE_DETECT               2
+
+#define PEX_MODE_GET(satr)		((satr & 0x6) >> 1)
+#define PEX_CAPABILITY_GET(satr)	(satr & 1)
+#define MV_PEX_UNIT_TO_IF(pex_unit)	((pex_unit < 3) ? (pex_unit * 4) : 9)
+
+/* Static parametes */
+static int config_module;
+static int switch_module;
+
+/* Local function */
+static u32 board_id_get(void)
+{
+#if defined(CONFIG_DB_88F78X60)
+	return DB_88F78XX0_BP_ID;
+#elif defined(CONFIG_RD_88F78460_SERVER)
+	return RD_78460_SERVER_ID;
+#elif defined(CONFIG_RD_78460_SERVER_REV2)
+	return RD_78460_SERVER_REV2_ID;
+#elif defined(CONFIG_DB_78X60_PCAC)
+	return DB_78X60_PCAC_ID;
+#elif defined(CONFIG_DB_88F78X60_REV2)
+	return DB_88F78XX0_BP_REV2_ID;
+#elif defined(CONFIG_RD_78460_NAS)
+	return RD_78460_NAS_ID;
+#elif defined(CONFIG_DB_78X60_AMC)
+	return DB_78X60_AMC_ID;
+#elif defined(CONFIG_DB_78X60_PCAC_REV2)
+	return DB_78X60_PCAC_REV2_ID;
+#elif defined(CONFIG_DB_784MP_GP)
+	return DB_784MP_GP_ID;
+#elif defined(CONFIG_RD_78460_CUSTOMER)
+	return RD_78460_CUSTOMER_ID;
+#else
+	/*
+	 * Return 0 here for custom board as this should not be used
+	 * for custom boards.
+	 */
+	return 0;
+#endif
+}
+
+static u8 board_sat_r_get(u8 dev_num, u8 reg)
+{
+	u8 data;
+	u8 *dev;
+	u32 board_id = board_id_get();
+	int ret;
+
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	switch (board_id) {
+	case DB_784MP_GP_ID:
+		dev = rd78460gp_twsi_dev;
+
+		break;
+	case DB_88F78XX0_BP_ID:
+	case DB_88F78XX0_BP_REV2_ID:
+		dev = db88f78xx0rev2_twsi_dev;
+		break;
+
+	case DB_78X60_PCAC_ID:
+	case FPGA_88F78XX0_ID:
+	case DB_78X60_PCAC_REV2_ID:
+	case RD_78460_SERVER_REV2_ID:
+	default:
+		return 0;
+	}
+
+	/* Read MPP module ID */
+	ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1);
+	if (ret)
+		return MV_ERROR;
+
+	return data;
+}
+
+static int board_modules_scan(void)
+{
+	u8 val;
+	u32 board_id = board_id_get();
+	int ret;
+
+	/* Perform scan only for DB board */
+	if ((board_id == DB_88F78XX0_BP_ID) ||
+	    (board_id == DB_88F78XX0_BP_REV2_ID)) {
+		/* reset modules flags */
+		config_module = 0;
+
+		i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+		/* SERDES module (only PEX model is supported now) */
+		ret = i2c_read(MV_BOARD_PEX_MODULE_ADDR, 0, 1, (u8 *)&val, 1);
+		if (ret)
+			return MV_ERROR;
+
+		if (val == MV_BOARD_PEX_MODULE_ID)
+			config_module = PEX_MODULE_DETECT;
+		if (val == MV_BOARD_ETM_MODULE_ID)
+			config_module = ETM_MODULE_DETECT;
+	} else if (board_id == RD_78460_NAS_ID) {
+		switch_module = 0;
+		if ((reg_read(GPP_DATA_IN_REG(2)) & MV_GPP66) == 0x0)
+			switch_module = 1;
+	}
+
+	return MV_OK;
+}
+
+u32 pex_max_unit_get(void)
+{
+	/*
+	 * TODO:
+	 * Right now only MV78460 is supported. Other SoC's might need
+	 * a different value here.
+	 */
+	return MV_PEX_MAX_UNIT;
+}
+
+u32 pex_max_if_get(void)
+{
+	/*
+	 * TODO:
+	 * Right now only MV78460 is supported. Other SoC's might need
+	 * a different value here.
+	 */
+	return MV_PEX_MAX_IF;
+}
+
+u8 board_cpu_freq_get(void)
+{
+	u32 sar;
+	u32 sar_msb;
+
+	sar = reg_read(MPP_SAMPLE_AT_RESET(0));
+	sar_msb = reg_read(MPP_SAMPLE_AT_RESET(1));
+	return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21);
+}
+
+__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+{
+	u32 board_id;
+	u32 serdes_cfg_val = 0;	/* default */
+
+	board_id = board_id_get();
+
+	switch (board_id) {
+	case DB_784MP_GP_ID:
+		serdes_cfg_val = 0;
+		break;
+	}
+
+	return &serdes_info_tbl[board_id - BOARD_ID_BASE][serdes_cfg_val];
+}
+
+u16 ctrl_model_get(void)
+{
+	/* Right now only MV78460 supported */
+	return MV_78460_DEV_ID;
+}
+
+u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info)
+{
+	if (line_num < 8)
+		return (info->line0_7 >> (line_num << 2)) & 0xF;
+	else
+		return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF;
+}
+
+int serdes_phy_config(void)
+{
+	int status = MV_OK;
+	u32 line_cfg;
+	u8 line_num;
+	/* addr/value for each line @ every setup step */
+	u32 addr[16][11], val[16][11];
+	u8 pex_unit, pex_line_num;
+	u8 sgmii_port = 0;
+	u32 tmp;
+	u32 in_direct;
+	u8 max_serdes_lines;
+	MV_BIN_SERDES_CFG *info;
+	u8 satr11;
+	u8 sata_port;
+	u8 freq;
+	u8 device_rev;
+	u32 rx_high_imp_mode;
+	u16 ctrl_mode;
+	u32 board_id = board_id_get();
+	u32 pex_if;
+	u32 pex_if_num;
+
+	/*
+	 * TODO:
+	 * Right now we only support the MV78460 with 16 serdes lines
+	 */
+	max_serdes_lines = 16;
+	if (max_serdes_lines == 0)
+		return MV_OK;
+
+	switch (board_id) {
+	case DB_78X60_AMC_ID:
+	case DB_78X60_PCAC_REV2_ID:
+	case RD_78460_CUSTOMER_ID:
+	case RD_78460_SERVER_ID:
+	case RD_78460_SERVER_REV2_ID:
+	case DB_78X60_PCAC_ID:
+		satr11 = (0x1 << 1) | 1;
+		break;
+	case FPGA_88F78XX0_ID:
+	case RD_78460_NAS_ID:
+		satr11 = (0x0 << 1) | 1;
+		break;
+	case DB_88F78XX0_BP_REV2_ID:
+	case DB_784MP_GP_ID:
+	case DB_88F78XX0_BP_ID:
+		satr11 = board_sat_r_get(1, 1);
+		if ((u8) MV_ERROR == (u8) satr11)
+			return MV_ERROR;
+		break;
+	}
+
+	board_modules_scan();
+	memset(addr, 0, sizeof(addr));
+	memset(val, 0, sizeof(val));
+
+	/* Check if DRAM is already initialized  */
+	if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
+	    (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
+		DEBUG_INIT_S("High speed PHY - Version: ");
+		DEBUG_INIT_S(SERDES_VERION);
+		DEBUG_INIT_S(" - 2nd boot - Skip\n");
+		return MV_OK;
+	}
+	DEBUG_INIT_S("High speed PHY - Version: ");
+	DEBUG_INIT_S(SERDES_VERION);
+	DEBUG_INIT_S(" (COM-PHY-V20)\n");
+
+	/*
+	 * AVS :  disable AVS for frequency less than 1333
+	 */
+	freq = board_cpu_freq_get();
+	device_rev = mv_ctrl_rev_get();
+
+	if (device_rev == 2) {	/*   for B0 only */
+		u32 cpu_avs;
+		u8 fabric_freq;
+		cpu_avs = reg_read(CPU_AVS_CONTROL2_REG);
+		DEBUG_RD_REG(CPU_AVS_CONTROL2_REG, cpu_avs);
+		cpu_avs &= ~(1 << 9);
+
+		if ((0x4 == freq) || (0xB == freq)) {
+			u32 tmp2;
+
+			tmp2 = reg_read(CPU_AVS_CONTROL0_REG);
+			DEBUG_RD_REG(CPU_AVS_CONTROL0_REG, tmp2);
+			/* cpu upper limit = 1.1V  cpu lower limit = 0.9125V  */
+			tmp2 |= 0x0FF;
+			reg_write(CPU_AVS_CONTROL0_REG, tmp2);
+			DEBUG_WR_REG(CPU_AVS_CONTROL0_REG, tmp2);
+			cpu_avs |= (1 << 9);	/* cpu avs enable */
+			cpu_avs |= (1 << 18);	/* AvsAvddDetEn enable  */
+			fabric_freq = (reg_read(MPP_SAMPLE_AT_RESET(0)) &
+				       SAR0_FABRIC_FREQ_MASK) >> SAR0_FABRIC_FREQ_OFFSET;
+			if ((0xB == freq) && (5 == fabric_freq)) {
+				u32 core_avs;
+
+				core_avs = reg_read(CORE_AVS_CONTROL_0REG);
+				DEBUG_RD_REG(CORE_AVS_CONTROL_0REG, core_avs);
+
+				/*
+				 * Set core lower limit = 0.9V &
+				 * core upper limit = 0.9125V
+				 */
+				core_avs &= ~(0xff);
+				core_avs |= 0x0E;
+				reg_write(CORE_AVS_CONTROL_0REG, core_avs);
+				DEBUG_WR_REG(CORE_AVS_CONTROL_0REG, core_avs);
+
+				core_avs = reg_read(CORE_AVS_CONTROL_2REG);
+				DEBUG_RD_REG(CORE_AVS_CONTROL_2REG, core_avs);
+				core_avs |= (1 << 9);	/*  core AVS enable  */
+				reg_write(CORE_AVS_CONTROL_2REG, core_avs);
+				DEBUG_WR_REG(CORE_AVS_CONTROL_2REG, core_avs);
+
+				tmp2 = reg_read(GENERAL_PURPOSE_RESERVED0_REG);
+				DEBUG_RD_REG(GENERAL_PURPOSE_RESERVED0_REG,
+					     tmp2);
+				tmp2 |= 0x1;	/*  AvsCoreAvddDetEn enable   */
+				reg_write(GENERAL_PURPOSE_RESERVED0_REG, tmp2);
+				DEBUG_WR_REG(GENERAL_PURPOSE_RESERVED0_REG,
+					     tmp2);
+			}
+		}
+		reg_write(CPU_AVS_CONTROL2_REG, cpu_avs);
+		DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs);
+	}
+
+	info = board_serdes_cfg_get(PEX_MODE_GET(satr11));
+	DEBUG_INIT_FULL_S("info->line0_7= 0x");
+	DEBUG_INIT_FULL_D(info->line0_7, 8);
+	DEBUG_INIT_FULL_S("   info->line8_15= 0x");
+	DEBUG_INIT_FULL_D(info->line8_15, 8);
+	DEBUG_INIT_FULL_S("\n");
+
+	if (info == NULL) {
+		DEBUG_INIT_S("Hight speed PHY Error #1\n");
+		return MV_ERROR;
+	}
+
+	if (config_module & ETM_MODULE_DETECT) {	/* step 0.9 ETM */
+		DEBUG_INIT_FULL_S("ETM module detect Step 0.9:\n");
+		reg_write(SERDES_LINE_MUX_REG_0_7, 0x11111111);
+		DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x11111111);
+		info->pex_mode[1] = PEX_BUS_DISABLED;	/* pex unit 1 is configure for ETM */
+		mdelay(100);
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d);	/* SETM0 - start calibration         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d);	/* SETM0 - start calibration         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d);	/* SETM1 - start calibration         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d);	/* SETM1 - start calibration         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801);	/* SETM0 - SATA mode & 25MHz ref clk */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801);	/* SETM0 - SATA mode & 25MHz ref clk */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801);	/* SETM1 - SATA mode & 25MHz ref clk */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801);	/* SETM1 - SATA mode & 25MHz ref clk */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF);	/* SETM0 - G3 full swing AMP         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF);	/* SETM0 - G3 full swing AMP         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF);	/* SETM1 - G3 full swing AMP         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF);	/* SETM1 - G3 full swing AMP         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800);	/* SETM0 - 40 data bit width         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800);	/* SETM0 - 40 data bit width         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800);	/* SETM1 - 40 data bit width         */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800);	/* SETM1 - 40 data bit width         */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400);	/* lane0(serdes4)                    */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400);	/* lane0(serdes4)                    */
+		reg_write(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400);	/* lane3(serdes7)                    */
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400);	/* lane3(serdes7)                    */
+	}
+
+	/* STEP -1 [PEX-Only] First phase of PEX-PIPE Configuration: */
+	DEBUG_INIT_FULL_S("Step 1: First phase of PEX-PIPE Configuration\n");
+	for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+		if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+			continue;
+
+		/* 1.   GLOB_CLK_CTRL Reset and Clock Control */
+		reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25);
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25);
+
+		/* 2.   GLOB_TEST_CTRL Test Mode Control */
+		if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) {
+			reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+				  (0xC2 << 16) | 0x200);
+			DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+				     (0xC2 << 16) | 0x200);
+		}
+
+		/* 3.   GLOB_CLK_SRC_LO Clock Source Low */
+		if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) {
+			reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+				  (0xC3 << 16) | 0x0F);
+			DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+				     (0xC3 << 16) | 0x0F);
+		}
+
+		reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC5 << 16) | 0x11F);
+		DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+			     (0xC5 << 16) | 0x11F);
+	}
+
+	/*
+	 * 2 Configure the desire PIN_PHY_GEN and do power down to the PU_PLL,
+	 * PU_RX,PU_TX. (bits[12:5])
+	 */
+	DEBUG_INIT_FULL_S("Step 2: Configure the desire PIN_PHY_GEN\n");
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		line_cfg = get_line_cfg(line_num, info);
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+			continue;
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX])
+			continue;
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+			switch (line_num) {
+			case 4:
+			case 6:
+				sata_port = 0;
+				break;
+			case 5:
+				sata_port = 1;
+				break;
+			default:
+				DEBUG_INIT_C
+				    ("SATA port error for serdes line: ",
+				     line_num, 2);
+				return MV_ERROR;
+			}
+			tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port));
+			DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+			tmp &= ~((0x1ff << 5) | 0x7);
+			tmp |= ((info->bus_speed & (1 << line_num)) != 0) ?
+				(0x11 << 5) : 0x0;
+
+			reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+			DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+			/*
+			 * 4) Configure the desire PIN_PHY_GEN and do power
+			 * down to the PU_PLL,PU_RX,PU_TX. (bits[12:5])
+			 */
+			tmp = reg_read(SGMII_SERDES_CFG_REG(0));
+			DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp);
+			tmp &= ~((0x1ff << 5) | 0x7);
+			tmp |= 0x660;
+			reg_write(SGMII_SERDES_CFG_REG(0), tmp);
+			DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp);
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+			sgmii_port = 0;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+			sgmii_port = 1;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+			sgmii_port = 2;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+			sgmii_port = 3;
+		else
+			continue;
+
+		tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port));
+		DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+		tmp &= ~((0x1ff << 5) | 0x7);
+		tmp |= (((info->bus_speed & (1 << line_num)) != 0) ?
+			(0x88 << 5) : (0x66 << 5));
+		reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+		DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+	}
+
+	/* Step 3 - QSGMII enable */
+	DEBUG_INIT_FULL_S("Step 3 QSGMII enable\n");
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		line_cfg = get_line_cfg(line_num, info);
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+			/* QSGMII Active bit set to true */
+			tmp = reg_read(QSGMII_CONTROL_1_REG);
+			DEBUG_RD_REG(QSGMII_CONTROL_1_REG, tmp);
+			tmp |= (1 << 30);
+#ifdef ERRATA_GL_6572255
+			tmp |= (1 << 27);
+#endif
+			reg_write(QSGMII_CONTROL_1_REG, tmp);
+			DEBUG_WR_REG(QSGMII_CONTROL_1_REG, tmp);
+		}
+	}
+
+	/* Step 4 - configure SERDES MUXes */
+	DEBUG_INIT_FULL_S("Step 4: Configure SERDES MUXes\n");
+	if (config_module & ETM_MODULE_DETECT) {
+		reg_write(SERDES_LINE_MUX_REG_0_7, 0x40041111);
+		DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x40041111);
+	} else {
+		reg_write(SERDES_LINE_MUX_REG_0_7, info->line0_7);
+		DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, info->line0_7);
+	}
+	reg_write(SERDES_LINE_MUX_REG_8_15, info->line8_15);
+	DEBUG_WR_REG(SERDES_LINE_MUX_REG_8_15, info->line8_15);
+
+	/* Step 5: Activate the RX High Impedance Mode  */
+	DEBUG_INIT_FULL_S("Step 5: Activate the RX High Impedance Mode\n");
+	rx_high_imp_mode = 0x8080;
+	if (device_rev == 2)	/*   for B0 only */
+		rx_high_imp_mode |= 4;
+
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		/* for each serdes lane */
+		DEBUG_INIT_FULL_S("SERDES  ");
+		DEBUG_INIT_FULL_D_10(line_num, 2);
+		line_cfg = get_line_cfg(line_num, info);
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) {
+			DEBUG_INIT_FULL_S(" unconnected ***\n");
+			continue;
+		}
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+			pex_unit = line_num >> 2;
+			pex_line_num = line_num % 4;
+			DEBUG_INIT_FULL_S(" - PEX unit ");
+			DEBUG_INIT_FULL_D_10(pex_unit, 1);
+			DEBUG_INIT_FULL_S(" line=  ");
+			DEBUG_INIT_FULL_D_10(pex_line_num, 1);
+			DEBUG_INIT_FULL_S("\n");
+
+			/* Needed for PEX_PHY_ACCESS_REG macro */
+			if ((line_num > 7) &&
+			    (info->pex_mode[3] == PEX_BUS_MODE_X8))
+				/* lines 8 - 15 are belong to PEX3 in x8 mode */
+				pex_unit = 3;
+
+			if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+				continue;
+
+			/*
+			 * 8)  Activate the RX High Impedance Mode field
+			 * (bit [2]) in register /PCIe_USB Control (Each MAC
+			 * contain different Access to reach its
+			 * Serdes-Regfile).
+			 * [PEX-Only] Set bit[12]: The analog part latches idle
+			 * if PU_TX = 1 and PU_PLL =1.
+			 */
+
+			/* Termination enable */
+			if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) {
+				in_direct = (0x48 << 16) | (pex_line_num << 24) |
+					0x1000 | rx_high_imp_mode;	/* x1 */
+			} else if ((info->pex_mode[pex_unit] ==
+				    PEX_BUS_MODE_X4) && (pex_line_num == 0))
+				in_direct = (0x48 << 16) | (pex_line_num << 24) |
+					0x1000 | (rx_high_imp_mode & 0xff);	/* x4 */
+			else
+				in_direct = 0;
+
+			if (in_direct) {
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+					  in_direct);
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+					     in_direct);
+			}
+
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+			/*
+			 * port 0 for serdes lines 4,6,  and port 1 for
+			 * serdes lines 5
+			 */
+			sata_port = line_num & 1;
+			DEBUG_INIT_FULL_S(" - SATA port  ");
+			DEBUG_INIT_FULL_D_10(sata_port, 2);
+			DEBUG_INIT_FULL_S("\n");
+			reg_write(SATA_COMPHY_CTRL_REG(sata_port),
+				  rx_high_imp_mode);
+			DEBUG_WR_REG(SATA_COMPHY_CTRL_REG(sata_port),
+				     rx_high_imp_mode);
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+			DEBUG_INIT_FULL_S(" - QSGMII\n");
+			reg_write(SGMII_COMPHY_CTRL_REG(0), rx_high_imp_mode);
+			DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(0),
+				     rx_high_imp_mode);
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+			sgmii_port = 0;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+			sgmii_port = 1;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+			sgmii_port = 2;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+			sgmii_port = 3;
+		else
+			continue;
+		DEBUG_INIT_FULL_S(" - SGMII port  ");
+		DEBUG_INIT_FULL_D_10(sgmii_port, 2);
+		DEBUG_INIT_FULL_S("\n");
+		reg_write(SGMII_COMPHY_CTRL_REG(sgmii_port), rx_high_imp_mode);
+		DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(sgmii_port),
+			     rx_high_imp_mode);
+	}			/* for each serdes lane */
+
+	/* Step 6 [PEX-Only] PEX-Main configuration (X4 or X1): */
+	DEBUG_INIT_FULL_S("Step 6: [PEX-Only] PEX-Main configuration (X4 or X1)\n");
+	tmp = reg_read(SOC_CTRL_REG);
+	DEBUG_RD_REG(SOC_CTRL_REG, tmp);
+	tmp &= 0x200;
+	if (info->pex_mode[0] == PEX_BUS_MODE_X1)
+		tmp |= PCIE0_QUADX1_EN;
+	if (info->pex_mode[1] == PEX_BUS_MODE_X1)
+		tmp |= PCIE1_QUADX1_EN;
+	if (((reg_read(MPP_SAMPLE_AT_RESET(0)) & PEX_CLK_100MHZ_MASK) >>
+	     PEX_CLK_100MHZ_OFFSET) == 0x1)
+		tmp |= (PCIE0_CLK_OUT_EN_MASK | PCIE1_CLK_OUT_EN_MASK);
+
+	reg_write(SOC_CTRL_REG, tmp);
+	DEBUG_WR_REG(SOC_CTRL_REG, tmp);
+
+	/* 6.2 PCI Express Link Capabilities */
+	DEBUG_INIT_FULL_S("Step 6.2: [PEX-Only] PCI Express Link Capabilities\n");
+
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		line_cfg = get_line_cfg(line_num, info);
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+			/*
+			 * PCI Express Control
+			 * 0xX1A00 [0]:
+			 * 0x0 X4-Link.
+			 * 0x1 X1-Link
+			 */
+			pex_unit = line_num >> 2;
+			pex_if = MV_SERDES_NUM_TO_PEX_NUM(line_num);
+			if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+				continue;
+
+			/*  set Common Clock Configuration */
+			tmp = reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if));
+			DEBUG_RD_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+			tmp |= (1 << 6);
+			reg_write(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+			DEBUG_WR_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+
+			tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if));
+			DEBUG_RD_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+			tmp &= ~(0x3FF);
+			if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1)
+				tmp |= (0x1 << 4);
+			if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)
+				tmp |= (0x4 << 4);
+			if (0 == PEX_CAPABILITY_GET(satr11))
+				tmp |= 0x1;
+			else
+				tmp |= 0x2;
+			DEBUG_INIT_FULL_S("Step 6.2: PEX ");
+			DEBUG_INIT_FULL_D(pex_if, 1);
+			DEBUG_INIT_FULL_C(" set GEN", (tmp & 3), 1);
+			reg_write(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+			DEBUG_WR_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+
+			/*
+			 * If pex is X4, no need to pass thru the other
+			 * 3X1 serdes lines
+			 */
+			if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)
+				line_num += 3;
+		}
+	}
+
+	/*
+	 * Step 7 [PEX-X4 Only] To create PEX-Link that contain 4-lanes you
+	 * need to config the register SOC_Misc/General Purpose2
+	 * (Address= 182F8)
+	 */
+	DEBUG_INIT_FULL_S("Step 7: [PEX-X4 Only] To create PEX-Link\n");
+	tmp = reg_read(GEN_PURP_RES_2_REG);
+	DEBUG_RD_REG(GEN_PURP_RES_2_REG, tmp);
+
+	tmp &= 0xFFFF0000;
+	if (info->pex_mode[0] == PEX_BUS_MODE_X4)
+		tmp |= 0x0000000F;
+
+	if (info->pex_mode[1] == PEX_BUS_MODE_X4)
+		tmp |= 0x000000F0;
+
+	if (info->pex_mode[2] == PEX_BUS_MODE_X4)
+		tmp |= 0x00000F00;
+
+	if (info->pex_mode[3] == PEX_BUS_MODE_X4)
+		tmp |= 0x0000F000;
+
+	reg_write(GEN_PURP_RES_2_REG, tmp);
+	DEBUG_WR_REG(GEN_PURP_RES_2_REG, tmp);
+
+	/* Steps  8 , 9 ,10 - use prepared REG addresses and values */
+	DEBUG_INIT_FULL_S("Steps 7,8,9,10 and 11\n");
+
+	/* Prepare PHY parameters for each step according to  MUX selection */
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		/* for each serdes lane */
+
+		line_cfg = get_line_cfg(line_num, info);
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+			continue;
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+			pex_unit = line_num >> 2;
+			pex_line_num = line_num % 4;
+
+			if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+				continue;
+			/*
+			 * 8)   Configure the desire PHY_MODE (bits [7:5])
+			 * and REF_FREF_SEL (bits[4:0]) in the register Power
+			 * and PLL Control (Each MAC contain different Access
+			 * to reach its Serdes-Regfile).
+			 */
+			if (((info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) &&
+			     (0 == pex_line_num))
+			    || ((info->pex_mode[pex_unit] == PEX_BUS_MODE_X1))) {
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+					  (0x01 << 16) | (pex_line_num << 24) |
+					  0xFC60);
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+					     (0x01 << 16) | (pex_line_num << 24)
+					     | 0xFC60);
+				/*
+				 * Step 8.1: [PEX-Only] Configure Max PLL Rate
+				 * (bit 8 in  KVCO Calibration Control and
+				 * bits[10:9] in
+				 */
+				/* Use Maximum PLL Rate(Bit 8) */
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+					  (0x02 << 16) | (1 << 31) |
+					  (pex_line_num << 24)); /* read command */
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+					     (0x02 << 16) | (1 << 31) |
+					     (pex_line_num << 24));
+				tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit));
+				DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+				tmp &= ~(1 << 31);
+				tmp |= (1 << 8);
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+
+				/* Use Maximum PLL Rate(Bits [10:9]) */
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+					  (0x81 << 16) | (1 << 31) |
+					  (pex_line_num << 24)); /* read command */
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+					     (0x81 << 16) | (1 << 31) |
+					     (pex_line_num << 24));
+				tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit));
+				DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+				tmp &= ~(1 << 31);
+				tmp |= (3 << 9);
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+			}
+
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+			/*
+			 * Port 0 for serdes lines 4,6,  and port 1 for serdes
+			 * lines 5
+			 */
+			sata_port = line_num & 1;
+
+			/*
+			 * 8) Configure the desire PHY_MODE (bits [7:5]) and
+			 * REF_FREF_SEL (bits[4:0]) in the register Power
+			 * and PLL Control (Each MAC contain different Access
+			 * to reach its Serdes-Regfile).
+			 */
+			reg_write(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801);
+			DEBUG_WR_REG(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801);
+
+			/*  9)  Configure the desire SEL_BITS  */
+			reg_write(SATA_DIG_LP_ENA_REG(sata_port), 0x400);
+			DEBUG_WR_REG(SATA_DIG_LP_ENA_REG(sata_port), 0x400);
+
+			/* 10)  Configure the desire REFCLK_SEL */
+
+			reg_write(SATA_REF_CLK_SEL_REG(sata_port), 0x400);
+			DEBUG_WR_REG(SATA_REF_CLK_SEL_REG(sata_port), 0x400);
+
+			/* 11)  Power up to the PU_PLL,PU_RX,PU_TX.   */
+			tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port));
+			DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+			tmp |= 7;
+			reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+			DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+			/*
+			 * 8)   Configure the desire PHY_MODE (bits [7:5])
+			 * and REF_FREF_SEL (bits[4:0]) in the register
+			 */
+			reg_write(SGMII_PWR_PLL_CTRL_REG(0), 0xF881);
+			DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(0), 0xF881);
+
+			/*
+			 * 9)   Configure the desire SEL_BITS (bits [11:0]
+			 * in register
+			 */
+			reg_write(SGMII_DIG_LP_ENA_REG(0), 0x400);
+			DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(0), 0x400);
+
+			/*
+			 * 10)  Configure the desire REFCLK_SEL (bit [10])
+			 * in register
+			 */
+			reg_write(SGMII_REF_CLK_SEL_REG(0), 0x400);
+			DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(0), 0x400);
+
+			/* 11)  Power up to the PU_PLL,PU_RX,PU_TX.  */
+			tmp = reg_read(SGMII_SERDES_CFG_REG(0));
+			DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp);
+			tmp |= 7;
+			reg_write(SGMII_SERDES_CFG_REG(0), tmp);
+			DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp);
+			continue;
+		}
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+			sgmii_port = 0;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+			sgmii_port = 1;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+			sgmii_port = 2;
+		else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+			sgmii_port = 3;
+		else
+			continue;
+
+		/*
+		 * 8)   Configure the desire PHY_MODE (bits [7:5]) and
+		 * REF_FREF_SEL (bits[4:0]) in the register
+		 */
+		reg_write(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881);
+		DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881);
+
+		/* 9)   Configure the desire SEL_BITS (bits [11:0] in register */
+		reg_write(SGMII_DIG_LP_ENA_REG(sgmii_port), 0);
+		DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(sgmii_port), 0);
+
+		/* 10)  Configure the desire REFCLK_SEL (bit [10]) in register  */
+		reg_write(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400);
+		DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400);
+
+		/* 11)  Power up to the PU_PLL,PU_RX,PU_TX.  */
+		tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port));
+		DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+		tmp |= 7;
+		reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+		DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+
+	}			/* for each serdes lane */
+
+	/* Step 12 [PEX-Only] Last phase of PEX-PIPE Configuration */
+	DEBUG_INIT_FULL_S("Steps 12: [PEX-Only] Last phase of PEX-PIPE Configuration\n");
+	for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+		/* for each serdes lane */
+
+		line_cfg = get_line_cfg(line_num, info);
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+			continue;
+
+		if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+			pex_unit = line_num >> 2;
+			pex_line_num = line_num % 4;
+			if (0 == pex_line_num) {
+				reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+					  (0xC1 << 16) | 0x24);
+				DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+					     (0xC1 << 16) | 0x24);
+			}
+		}
+	}
+
+	/*--------------------------------------------------------------*/
+	/* Step 13: Wait 15ms before checking results */
+	DEBUG_INIT_FULL_S("Steps 13: Wait 15ms before checking results");
+	mdelay(15);
+	tmp = 20;
+	while (tmp) {
+		status = MV_OK;
+		for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+			u32 tmp;
+			line_cfg = get_line_cfg(line_num, info);
+			if (line_cfg ==
+			    serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+				continue;
+
+			if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX])
+				continue;
+
+			if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+				/*
+				 * Port 0 for serdes lines 4,6,  and port 1
+				 * for serdes lines 5
+				 */
+				sata_port = line_num & 1;
+
+				tmp =
+				    reg_read(SATA_LP_PHY_EXT_STAT_REG
+					     (sata_port));
+				DEBUG_RD_REG(SATA_LP_PHY_EXT_STAT_REG
+					     (sata_port), tmp);
+				if ((tmp & 0x7) != 0x7)
+					status = MV_ERROR;
+				continue;
+			}
+
+			if (line_cfg ==
+			    serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+				tmp = reg_read(SGMII_SERDES_STAT_REG(0));
+				DEBUG_RD_REG(SGMII_SERDES_STAT_REG(0), tmp);
+				if ((tmp & 0x7) != 0x7)
+					status = MV_ERROR;
+				continue;
+			}
+
+			if (line_cfg ==
+			    serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+				sgmii_port = 0;
+			else if (line_cfg ==
+				 serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+				sgmii_port = 1;
+			else if (line_cfg ==
+				 serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+				sgmii_port = 2;
+			else if (line_cfg ==
+				 serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+				sgmii_port = 3;
+			else
+				continue;
+
+			tmp = reg_read(SGMII_SERDES_STAT_REG(sgmii_port));
+			DEBUG_RD_REG(SGMII_SERDES_STAT_REG(sgmii_port), tmp);
+			if ((tmp & 0x7) != 0x7)
+				status = MV_ERROR;
+		}
+
+		if (status == MV_OK)
+			break;
+		mdelay(5);
+		tmp--;
+	}
+
+	/*
+	 * Step14 [PEX-Only]  In order to configure RC/EP mode please write
+	 * to register 0x0060 bits
+	 */
+	DEBUG_INIT_FULL_S("Steps 14: [PEX-Only]  In order to configure\n");
+	for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+		if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+			continue;
+		tmp =
+		    reg_read(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)));
+		DEBUG_RD_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+			     tmp);
+		tmp &= ~(0xf << 20);
+		if (info->pex_type == MV_PEX_ROOT_COMPLEX)
+			tmp |= (0x4 << 20);
+		else
+			tmp |= (0x1 << 20);
+		reg_write(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+			  tmp);
+		DEBUG_WR_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+			     tmp);
+	}
+
+	/*
+	 * Step 15 [PEX-Only] Only for EP mode set to Zero bits 19 and 16 of
+	 * register 0x1a60
+	 */
+	DEBUG_INIT_FULL_S("Steps 15: [PEX-Only]  In order to configure\n");
+	for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+		if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+			continue;
+		if (info->pex_type == MV_PEX_END_POINT) {
+			tmp =
+			    reg_read(PEX_DBG_CTRL_REG
+				     (MV_PEX_UNIT_TO_IF(pex_unit)));
+			DEBUG_RD_REG(PEX_DBG_CTRL_REG
+				     (MV_PEX_UNIT_TO_IF(pex_unit)), tmp);
+			tmp &= 0xfff6ffff;
+			reg_write(PEX_DBG_CTRL_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+				  tmp);
+			DEBUG_WR_REG(PEX_DBG_CTRL_REG
+				     (MV_PEX_UNIT_TO_IF(pex_unit)), tmp);
+		}
+	}
+
+	if (info->serdes_m_phy_change) {
+		MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change;
+		u32 bus_speed;
+		for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+			line_cfg = get_line_cfg(line_num, info);
+			if (line_cfg ==
+			    serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+				continue;
+			serdes_m_phy_change = info->serdes_m_phy_change;
+			bus_speed = info->bus_speed & (1 << line_num);
+			while (serdes_m_phy_change->type !=
+			       SERDES_UNIT_UNCONNECTED) {
+				switch (serdes_m_phy_change->type) {
+				case SERDES_UNIT_PEX:
+					if (line_cfg != SERDES_UNIT_PEX)
+						break;
+					pex_unit = line_num >> 2;
+					pex_line_num = line_num % 4;
+					if (info->pex_mode[pex_unit] ==
+					    PEX_BUS_DISABLED)
+						break;
+					if ((info->pex_mode[pex_unit] ==
+					     PEX_BUS_MODE_X4) && pex_line_num)
+						break;
+
+					if (bus_speed) {
+						reg_write(PEX_PHY_ACCESS_REG
+							  (pex_unit),
+							  (pex_line_num << 24) |
+							  serdes_m_phy_change->val_hi_speed);
+						DEBUG_WR_REG(PEX_PHY_ACCESS_REG
+							     (pex_unit),
+							     (pex_line_num <<
+							      24) |
+							     serdes_m_phy_change->val_hi_speed);
+					} else {
+						reg_write(PEX_PHY_ACCESS_REG
+							  (pex_unit),
+							  (pex_line_num << 24) |
+							  serdes_m_phy_change->val_low_speed);
+						DEBUG_WR_REG(PEX_PHY_ACCESS_REG
+							     (pex_unit),
+							     (pex_line_num <<
+							      24) |
+							     serdes_m_phy_change->val_low_speed);
+					}
+					break;
+				case SERDES_UNIT_SATA:
+					if (line_cfg != SERDES_UNIT_SATA)
+						break;
+					/*
+					 * Port 0 for serdes lines 4,6,  and
+					 * port 1 for serdes lines 5
+					 */
+					sata_port = line_num & 1;
+					if (bus_speed) {
+						reg_write(SATA_BASE_REG
+							  (sata_port) |
+							  serdes_m_phy_change->reg_hi_speed,
+							  serdes_m_phy_change->val_hi_speed);
+						DEBUG_WR_REG(SATA_BASE_REG
+							     (sata_port) |
+							     serdes_m_phy_change->reg_hi_speed,
+							     serdes_m_phy_change->val_hi_speed);
+					} else {
+						reg_write(SATA_BASE_REG
+							  (sata_port) |
+							  serdes_m_phy_change->reg_low_speed,
+							  serdes_m_phy_change->val_low_speed);
+						DEBUG_WR_REG(SATA_BASE_REG
+							     (sata_port) |
+							     serdes_m_phy_change->reg_low_speed,
+							     serdes_m_phy_change->val_low_speed);
+					}
+					break;
+				case SERDES_UNIT_SGMII0:
+				case SERDES_UNIT_SGMII1:
+				case SERDES_UNIT_SGMII2:
+				case SERDES_UNIT_SGMII3:
+					if (line_cfg == serdes_cfg[line_num]
+					    [SERDES_UNIT_SGMII0])
+						sgmii_port = 0;
+					else if (line_cfg ==
+						 serdes_cfg[line_num]
+						 [SERDES_UNIT_SGMII1])
+						sgmii_port = 1;
+					else if (line_cfg ==
+						 serdes_cfg[line_num]
+						 [SERDES_UNIT_SGMII2])
+						sgmii_port = 2;
+					else if (line_cfg ==
+						 serdes_cfg[line_num]
+						 [SERDES_UNIT_SGMII3])
+						sgmii_port = 3;
+					else
+						break;
+					if (bus_speed) {
+						reg_write(MV_ETH_REGS_BASE
+							  (sgmii_port) |
+							  serdes_m_phy_change->reg_hi_speed,
+							  serdes_m_phy_change->val_hi_speed);
+						DEBUG_WR_REG(MV_ETH_REGS_BASE
+							     (sgmii_port) |
+							     serdes_m_phy_change->reg_hi_speed,
+							     serdes_m_phy_change->val_hi_speed);
+					} else {
+						reg_write(MV_ETH_REGS_BASE
+							  (sgmii_port) |
+							  serdes_m_phy_change->reg_low_speed,
+							  serdes_m_phy_change->val_low_speed);
+						DEBUG_WR_REG(MV_ETH_REGS_BASE
+							     (sgmii_port) |
+							     serdes_m_phy_change->reg_low_speed,
+							     serdes_m_phy_change->val_low_speed);
+					}
+					break;
+				case SERDES_UNIT_QSGMII:
+					if (line_cfg != SERDES_UNIT_QSGMII)
+						break;
+					if (bus_speed) {
+						reg_write
+						    (serdes_m_phy_change->reg_hi_speed,
+						     serdes_m_phy_change->val_hi_speed);
+						DEBUG_WR_REG
+						    (serdes_m_phy_change->reg_hi_speed,
+						     serdes_m_phy_change->val_hi_speed);
+					} else {
+						reg_write
+						    (serdes_m_phy_change->reg_low_speed,
+						     serdes_m_phy_change->val_low_speed);
+						DEBUG_WR_REG
+						    (serdes_m_phy_change->reg_low_speed,
+						     serdes_m_phy_change->val_low_speed);
+					}
+					break;
+				default:
+					break;
+				}
+				serdes_m_phy_change++;
+			}
+		}
+	}
+
+	/* Step 16 [PEX-Only] Training Enable */
+	DEBUG_INIT_FULL_S("Steps 16: [PEX-Only] Training Enable");
+	tmp = reg_read(SOC_CTRL_REG);
+	DEBUG_RD_REG(SOC_CTRL_REG, tmp);
+	tmp &= ~(0x0F);
+	for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+		reg_write(PEX_CAUSE_REG(pex_unit), 0);
+		DEBUG_WR_REG(PEX_CAUSE_REG(pex_unit), 0);
+		if (info->pex_mode[pex_unit] != PEX_BUS_DISABLED)
+			tmp |= (0x1 << pex_unit);
+	}
+	reg_write(SOC_CTRL_REG, tmp);
+	DEBUG_WR_REG(SOC_CTRL_REG, tmp);
+
+	/* Step 17: Speed change to target speed and width */
+	{
+		u32 tmp_reg, tmp_pex_reg;
+		u32 addr;
+		u32 first_busno, next_busno;
+		u32 max_link_width = 0;
+		u32 neg_link_width = 0;
+		pex_if_num = pex_max_if_get();
+		mdelay(150);
+		DEBUG_INIT_FULL_C("step 17: max_if= 0x", pex_if_num, 1);
+		next_busno = 0;
+		for (pex_if = 0; pex_if < pex_if_num; pex_if++) {
+			line_num = (pex_if <= 8) ? pex_if : 12;
+			line_cfg = get_line_cfg(line_num, info);
+			if (line_cfg != serdes_cfg[line_num][SERDES_UNIT_PEX])
+				continue;
+			pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3;
+			DEBUG_INIT_FULL_S("step 17:  PEX");
+			DEBUG_INIT_FULL_D(pex_if, 1);
+			DEBUG_INIT_FULL_C("  pex_unit= ", pex_unit, 1);
+
+			if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) {
+				DEBUG_INIT_FULL_C("PEX disabled interface ",
+						  pex_if, 1);
+				if (pex_if < 8)
+					pex_if += 3;
+				continue;
+			}
+			first_busno = next_busno;
+			if ((info->pex_type == MV_PEX_END_POINT) &&
+			    (0 == pex_if)) {
+				if ((pex_if < 8) && (info->pex_mode[pex_unit] ==
+						     PEX_BUS_MODE_X4))
+					pex_if += 3;
+				continue;
+			}
+
+			tmp = reg_read(PEX_DBG_STATUS_REG(pex_if));
+			DEBUG_RD_REG(PEX_DBG_STATUS_REG(pex_if), tmp);
+			if ((tmp & 0x7f) == 0x7e) {
+				next_busno++;
+				tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if));
+				max_link_width = tmp;
+				DEBUG_RD_REG((PEX_LINK_CAPABILITIES_REG
+					      (pex_if)), tmp);
+				max_link_width = ((max_link_width >> 4) & 0x3F);
+				neg_link_width =
+				    reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if));
+				DEBUG_RD_REG((PEX_LINK_CTRL_STATUS_REG(pex_if)),
+					     neg_link_width);
+				neg_link_width = ((neg_link_width >> 20) & 0x3F);
+				if (max_link_width > neg_link_width) {
+					tmp &= ~(0x3F << 4);
+					tmp |= (neg_link_width << 4);
+					reg_write(PEX_LINK_CAPABILITIES_REG
+						  (pex_if), tmp);
+					DEBUG_WR_REG((PEX_LINK_CAPABILITIES_REG
+						      (pex_if)), tmp);
+					mdelay(1);	/* wait 1ms before reading  capability for speed */
+					DEBUG_INIT_S("PEX");
+					DEBUG_INIT_D(pex_if, 1);
+					DEBUG_INIT_C(": change width to X",
+						     neg_link_width, 1);
+				}
+				tmp_pex_reg =
+				    reg_read((PEX_CFG_DIRECT_ACCESS
+					      (pex_if,
+					       PEX_LINK_CAPABILITY_REG)));
+				DEBUG_RD_REG((PEX_CFG_DIRECT_ACCESS
+					      (pex_if,
+					       PEX_LINK_CAPABILITY_REG)),
+					     tmp_pex_reg);
+				tmp_pex_reg &= (0xF);
+				if (tmp_pex_reg == 0x2) {
+					tmp_reg =
+					    (reg_read
+					     (PEX_CFG_DIRECT_ACCESS
+					      (pex_if,
+					       PEX_LINK_CTRL_STAT_REG)) &
+					     0xF0000) >> 16;
+					DEBUG_RD_REG(PEX_CFG_DIRECT_ACCESS
+						     (pex_if,
+						      PEX_LINK_CTRL_STAT_REG),
+						     tmp_pex_reg);
+					/* check if the link established is GEN1 */
+					if (tmp_reg == 0x1) {
+						pex_local_bus_num_set(pex_if,
+								      first_busno);
+						pex_local_dev_num_set(pex_if,
+								      1);
+
+						DEBUG_INIT_FULL_S("** Link is Gen1, check the EP capability\n");
+						/* link is Gen1, check the EP capability */
+						addr =
+						    pex_cfg_read(pex_if,
+								 first_busno, 0,
+								 0,
+								 0x34) & 0xFF;
+						DEBUG_INIT_FULL_C("pex_cfg_read: return addr=0x%x",
+						     addr, 4);
+						if (addr == 0xff) {
+							DEBUG_INIT_FULL_C("pex_cfg_read: return 0xff -->PEX (%d): Detected No Link.",
+									  pex_if, 1);
+							continue;
+						}
+						while ((pex_cfg_read
+							(pex_if, first_busno, 0,
+							 0,
+							 addr) & 0xFF) !=
+						       0x10) {
+							addr =
+							    (pex_cfg_read
+							     (pex_if,
+							      first_busno, 0, 0,
+							      addr) & 0xFF00) >>
+							    8;
+						}
+						if ((pex_cfg_read
+						     (pex_if, first_busno, 0, 0,
+						      addr + 0xC) & 0xF) >=
+						    0x2) {
+							tmp =
+							    reg_read
+							    (PEX_LINK_CTRL_STATUS2_REG
+							     (pex_if));
+							DEBUG_RD_REG
+							    (PEX_LINK_CTRL_STATUS2_REG
+							     (pex_if), tmp);
+							tmp &= ~(0x1 | 1 << 1);
+							tmp |= (1 << 1);
+							reg_write
+							    (PEX_LINK_CTRL_STATUS2_REG
+							     (pex_if), tmp);
+							DEBUG_WR_REG
+							    (PEX_LINK_CTRL_STATUS2_REG
+							     (pex_if), tmp);
+
+							tmp =
+							    reg_read
+							    (PEX_CTRL_REG
+							     (pex_if));
+							DEBUG_RD_REG
+							    (PEX_CTRL_REG
+							     (pex_if), tmp);
+							tmp |= (1 << 10);
+							reg_write(PEX_CTRL_REG
+								  (pex_if),
+								  tmp);
+							DEBUG_WR_REG
+							    (PEX_CTRL_REG
+							     (pex_if), tmp);
+							mdelay(10);	/* We need to wait 10ms before reading the PEX_DBG_STATUS_REG in order not to read the status of the former state */
+							DEBUG_INIT_FULL_S
+							    ("Gen2 client!\n");
+						} else {
+							DEBUG_INIT_FULL_S
+							    ("GEN1 client!\n");
+						}
+					}
+				}
+			} else {
+				DEBUG_INIT_FULL_S("PEX");
+				DEBUG_INIT_FULL_D(pex_if, 1);
+				DEBUG_INIT_FULL_S(" : Detected No Link. Status Reg(0x");
+				DEBUG_INIT_FULL_D(PEX_DBG_STATUS_REG(pex_if),
+						  8);
+				DEBUG_INIT_FULL_C(") = 0x", tmp, 8);
+			}
+
+			if ((pex_if < 8) &&
+			    (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+				pex_if += 3;
+		}
+	}
+
+	/* Step 18: update pex DEVICE ID */
+	{
+		u32 devId;
+		pex_if_num = pex_max_if_get();
+		ctrl_mode = ctrl_model_get();
+		for (pex_if = 0; pex_if < pex_if_num; pex_if++) {
+			pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3;
+			if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) {
+				if ((pex_if < 8) &&
+				    (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+					pex_if += 3;
+				continue;
+			}
+
+			devId = reg_read(PEX_CFG_DIRECT_ACCESS(
+						 pex_if, PEX_DEVICE_AND_VENDOR_ID));
+			devId &= 0xFFFF;
+			devId |= ((ctrl_mode << 16) & 0xffff0000);
+			DEBUG_INIT_S("Update Device ID PEX");
+			DEBUG_INIT_D(pex_if, 1);
+			DEBUG_INIT_D(devId, 8);
+			DEBUG_INIT_S("\n");
+			reg_write(PEX_CFG_DIRECT_ACCESS
+				  (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId);
+			if ((pex_if < 8) &&
+			    (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+				pex_if += 3;
+		}
+		DEBUG_INIT_S("Update PEX Device ID 0x");
+		DEBUG_INIT_D(ctrl_mode, 4);
+		DEBUG_INIT_S("0\n");
+	}
+	tmp = reg_read(PEX_DBG_STATUS_REG(0));
+	DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp);
+
+	DEBUG_INIT_S(ENDED_OK);
+	return MV_OK;
+}
+
+/* PEX configuration space read write */
+
+/*
+ * pex_cfg_read - Read from configuration space
+ *
+ * DESCRIPTION:
+ *       This function performs a 32 bit read from PEX configuration space.
+ *       It supports both type 0 and type 1 of Configuration Transactions
+ *       (local and over bridge). In order to read from local bus segment, use
+ *       bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers
+ *       will result configuration transaction of type 1 (over bridge).
+ *
+ * INPUT:
+ *       pex_if   - PEX interface number.
+ *       bus     - PEX segment bus number.
+ *       dev     - PEX device number.
+ *       func    - Function number.
+ *       offss - Register offset.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       32bit register data, 0xffffffff on error
+ *
+ */
+u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs)
+{
+	u32 pex_data = 0;
+	u32 local_dev, local_bus;
+	u32 val;
+
+	if (pex_if >= MV_PEX_MAX_IF)
+		return 0xFFFFFFFF;
+
+	if (dev >= MAX_PEX_DEVICES) {
+		DEBUG_INIT_C("pex_cfg_read: ERR. device number illigal ", dev,
+			     1);
+		return 0xFFFFFFFF;
+	}
+
+	if (func >= MAX_PEX_FUNCS) {
+		DEBUG_INIT_C("pex_cfg_read: ERR. function num illigal ", func,
+			     1);
+		return 0xFFFFFFFF;
+	}
+
+	if (bus >= MAX_PEX_BUSSES) {
+		DEBUG_INIT_C("pex_cfg_read: ERR. bus number illigal ", bus, 1);
+		return MV_ERROR;
+	}
+	val = reg_read(PEX_STATUS_REG(pex_if));
+
+	local_dev =
+	    ((val & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
+	local_bus =
+	    ((val & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
+
+	/* Speed up the process. In case on no link, return MV_ERROR */
+	if ((dev != local_dev) || (bus != local_bus)) {
+		pex_data = reg_read(PEX_STATUS_REG(pex_if));
+
+		if ((pex_data & PXSR_DL_DOWN))
+			return MV_ERROR;
+	}
+
+	/*
+	 * In PCI Express we have only one device number
+	 * and this number is the first number we encounter else that the
+	 * local_dev spec pex define return on config read/write on any device
+	 */
+	if (bus == local_bus) {
+		if (local_dev == 0) {
+			/*
+			 * If local dev is 0 then the first number we encounter
+			 * after 0 is 1
+			 */
+			if ((dev != 1) && (dev != local_dev))
+				return MV_ERROR;
+		} else {
+			/*
+			 * If local dev is not 0 then the first number we
+			 * encounter is 0
+			 */
+			if ((dev != 0) && (dev != local_dev))
+				return MV_ERROR;
+		}
+	}
+
+	/* Creating PEX address to be passed */
+	pex_data = (bus << PXCAR_BUS_NUM_OFFS);
+	pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
+	pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
+	pex_data |= (offs & PXCAR_REG_NUM_MASK);	/* lgacy register space */
+	/* extended register space */
+	pex_data |= (((offs & PXCAR_REAL_EXT_REG_NUM_MASK) >>
+		     PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
+
+	pex_data |= PXCAR_CONFIG_EN;
+
+	/* Write the address to the PEX configuration address register */
+	reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
+
+	/*
+	 * In order to let the PEX controller absorbed the address of the read
+	 * transaction we perform a validity check that the address was written
+	 */
+	if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
+		return MV_ERROR;
+
+	/* cleaning Master Abort */
+	reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
+		    PXSAC_MABORT);
+	/* Read the Data returned in the PEX Data register */
+	pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
+
+	DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
+
+	return pex_data;
+}
+
+/*
+ * pex_local_bus_num_set - Set PEX interface local bus number.
+ *
+ * DESCRIPTION:
+ *       This function sets given PEX interface its local bus number.
+ *       Note: In case the PEX interface is PEX-X, the information is read-only.
+ *
+ * INPUT:
+ *       pex_if  - PEX interface number.
+ *       bus_num - Bus number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+ *		MV_BAD_PARAM on bad parameters ,
+ *       otherwise MV_OK
+ *
+ */
+int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
+{
+	u32 val;
+
+	if (bus_num >= MAX_PEX_BUSSES) {
+		DEBUG_INIT_C("pex_local_bus_num_set: ERR. bus number illigal %d\n",
+		     bus_num, 4);
+		return MV_ERROR;
+	}
+
+	val = reg_read(PEX_STATUS_REG(pex_if));
+	val &= ~PXSR_PEX_BUS_NUM_MASK;
+	val |= (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
+	reg_write(PEX_STATUS_REG(pex_if), val);
+
+	return MV_OK;
+}
+
+/*
+ * pex_local_dev_num_set - Set PEX interface local device number.
+ *
+ * DESCRIPTION:
+ *       This function sets given PEX interface its local device number.
+ *       Note: In case the PEX interface is PEX-X, the information is read-only.
+ *
+ * INPUT:
+ *       pex_if  - PEX interface number.
+ *       dev_num - Device number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+ *		MV_BAD_PARAM on bad parameters ,
+ *       otherwise MV_OK
+ *
+ */
+int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
+{
+	u32 val;
+
+	if (pex_if >= MV_PEX_MAX_IF)
+		return MV_BAD_PARAM;
+
+	val = reg_read(PEX_STATUS_REG(pex_if));
+	val &= ~PXSR_PEX_DEV_NUM_MASK;
+	val |= (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
+	reg_write(PEX_STATUS_REG(pex_if), val);
+
+	return MV_OK;
+}
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_spec.c b/arch/arm/mvebu-common/serdes/high_speed_env_spec.c
new file mode 100644
index 0000000..115ec2c
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_spec.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "high_speed_env_spec.h"
+
+MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[] = {
+	/* SERDES TYPE, Low REG OFFS, Low REG VALUE, Hi REG OFS, Hi REG VALUE */
+	{
+		/* PEX: Change of Slew Rate port0   */
+		SERDES_UNIT_PEX, 0x0,
+		(0x0F << 16) | 0x2a21, 0x0, (0x0F << 16) | 0x2a21
+	}, {
+		/* PEX: Change PLL BW port0                   */
+		SERDES_UNIT_PEX, 0x0,
+		(0x4F << 16) | 0x6219, 0x0, (0x4F << 16) | 0x6219
+	}, {
+		/* SATA: Slew rate change port 0  */
+		SERDES_UNIT_SATA, 0x0083C, 0x8a31, 0x0083C, 0x8a31
+	}, {
+		/* SATA: Slew rate change port 0  */
+		SERDES_UNIT_SATA, 0x00834, 0xc928, 0x00834, 0xc928
+	}, {
+		/* SATA: Slew rate change port 0  */
+		SERDES_UNIT_SATA, 0x00838, 0x30f0, 0x00838, 0x30f0
+	}, {
+		/* SATA: Slew rate change port 0  */
+		SERDES_UNIT_SATA, 0x00840, 0x30f5, 0x00840, 0x30f5
+	}, {
+		/* SGMII: FFE setting Port0         */
+		SERDES_UNIT_SGMII0, 0x00E18, 0x989F, 0x00E18, 0x989F
+	}, {
+		/* SGMII: SELMUP and SELMUF Port0   */
+		SERDES_UNIT_SGMII0, 0x00E38, 0x10FA, 0x00E38, 0x10FA
+	}, {
+		/* SGMII: Amplitude new setting gen2 Port3 */
+		SERDES_UNIT_SGMII0, 0x00E34, 0xC968, 0x00E34, 0xC66C
+	}, {
+		/* QSGMII: Amplitude and slew rate change  */
+		SERDES_UNIT_QSGMII, 0x72E34, 0xaa58, 0x72E34, 0xaa58
+	}, {
+		/* QSGMII: SELMUP and SELMUF               */
+		SERDES_UNIT_QSGMII, 0x72e38, 0x10aF, 0x72e38, 0x10aF
+	}, {
+		/* QSGMII: 0x72e18                         */
+		SERDES_UNIT_QSGMII, 0x72e18, 0x98AC, 0x72e18, 0x98AC
+	}, {
+		/* Null terminated */
+		SERDES_UNIT_UNCONNECTED, 0, 0
+	}
+};
+
+MV_BIN_SERDES_CFG db88f78xx0_serdes_cfg[] = {
+	/* Z1B */
+	{MV_PEX_ROOT_COMPLEX, 0x32221111, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy},			/* Default */
+	{MV_PEX_ROOT_COMPLEX, 0x31211111, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy},			/* PEX module */
+	/* Z1A */
+	{MV_PEX_ROOT_COMPLEX, 0x32220000, 0x00000000,
+	 {PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED,
+	  PEX_BUS_DISABLED}, 0x0030, serdes_change_m_phy}, /* Default - Z1A */
+	{MV_PEX_ROOT_COMPLEX, 0x31210000, 0x00000000,
+	 {PEX_BUS_DISABLED, PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0030, serdes_change_m_phy}	/* PEX module - Z1A */
+};
+
+MV_BIN_SERDES_CFG db88f78xx0rev2_serdes_cfg[] = {
+	/* A0 */
+	{MV_PEX_ROOT_COMPLEX, 0x33221111, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Default: No Pex module, PEX0 x1, disabled */
+	{MV_PEX_ROOT_COMPLEX, 0x33211111, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x1, PEX1 x1 */
+	{MV_PEX_ROOT_COMPLEX, 0x33221111, 0x11111111,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* no Pex module, PEX0 x4, PEX1 disabled */
+	{MV_PEX_ROOT_COMPLEX, 0x33211111, 0x11111111,
+	 {PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x4, PEX1 x1 */
+	{MV_PEX_ROOT_COMPLEX, 0x11111111, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x1, PEX1 x4 */
+	{MV_PEX_ROOT_COMPLEX, 0x11111111, 0x11111111,
+	 {PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x4, PEX1 x4 */
+};
+
+MV_BIN_SERDES_CFG rd78460nas_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}, /* Default */
+	{MV_PEX_ROOT_COMPLEX, 0x33320201, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x00f4, serdes_change_m_phy}, /* Switch module */
+};
+
+MV_BIN_SERDES_CFG rd78460_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x22321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy}, /* CPU0 */
+	{MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy} /* CPU1-3 */
+};
+
+MV_BIN_SERDES_CFG rd78460server_rev2_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy}, /* CPU0 */
+	{MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy} /* CPU1-3 */
+};
+
+MV_BIN_SERDES_CFG db78X60pcac_serdes_cfg[] = {
+	{MV_PEX_END_POINT, 0x22321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy}	/* Default */
+};
+
+MV_BIN_SERDES_CFG db78X60pcacrev2_serdes_cfg[] = {
+	{MV_PEX_END_POINT, 0x23321111, 0x00000000,
+	 {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0010, serdes_change_m_phy}	/* Default */
+};
+
+MV_BIN_SERDES_CFG fpga88f78xx0_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x00000000, 0x00000000,
+	 {PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+	 0x0000, serdes_change_m_phy}	/* No PEX in FPGA */
+};
+
+MV_BIN_SERDES_CFG db78X60amc_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x33111111, 0x00010001,
+	 {PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X1},
+	 0x0030, serdes_change_m_phy}	/* Default */
+};
+
+/*
+ * ARMADA-XP CUSTOMER BOARD
+ */
+MV_BIN_SERDES_CFG rd78460customer_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x00000030, serdes_change_m_phy}, /* Default */
+	{MV_PEX_ROOT_COMPLEX, 0x33320201, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x00000030, serdes_change_m_phy}, /* Switch module */
+};
+
+MV_BIN_SERDES_CFG rd78460AXP_GP_serdes_cfg[] = {
+	{MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+	 {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+	 0x0030, serdes_change_m_phy}	/* Default */
+};
+
+MV_BIN_SERDES_CFG *serdes_info_tbl[] = {
+	db88f78xx0_serdes_cfg,
+	rd78460_serdes_cfg,
+	db78X60pcac_serdes_cfg,
+	fpga88f78xx0_serdes_cfg,
+	db88f78xx0rev2_serdes_cfg,
+	rd78460nas_serdes_cfg,
+	db78X60amc_serdes_cfg,
+	db78X60pcacrev2_serdes_cfg,
+	rd78460server_rev2_serdes_cfg,
+	rd78460AXP_GP_serdes_cfg,
+	rd78460customer_serdes_cfg
+};
+
+u8 rd78460gp_twsi_dev[] = { 0x4C, 0x4D, 0x4E };
+u8 db88f78xx0rev2_twsi_dev[] = { 0x4C, 0x4D, 0x4E, 0x4F };
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_spec.h b/arch/arm/mvebu-common/serdes/high_speed_env_spec.h
new file mode 100644
index 0000000..e5aa1b0
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_spec.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __HIGHSPEED_ENV_SPEC_H
+#define __HIGHSPEED_ENV_SPEC_H
+
+#include "../../../drivers/ddr/mvebu/ddr3_hw_training.h"
+
+typedef enum {
+	SERDES_UNIT_UNCONNECTED	= 0x0,
+	SERDES_UNIT_PEX		= 0x1,
+	SERDES_UNIT_SATA	= 0x2,
+	SERDES_UNIT_SGMII0	= 0x3,
+	SERDES_UNIT_SGMII1	= 0x4,
+	SERDES_UNIT_SGMII2	= 0x5,
+	SERDES_UNIT_SGMII3	= 0x6,
+	SERDES_UNIT_QSGMII	= 0x7,
+	SERDES_UNIT_SETM        = 0x8,
+	SERDES_LAST_UNIT
+} MV_BIN_SERDES_UNIT_INDX;
+
+
+typedef enum {
+	PEX_BUS_DISABLED	= 0,
+	PEX_BUS_MODE_X1		= 1,
+	PEX_BUS_MODE_X4		= 2,
+	PEX_BUS_MODE_X8		= 3
+} MV_PEX_UNIT_CFG;
+
+typedef enum pex_type {
+	MV_PEX_ROOT_COMPLEX,	/* root complex device */
+	MV_PEX_END_POINT	/* end point device */
+} MV_PEX_TYPE;
+
+typedef struct serdes_change_m_phy {
+	MV_BIN_SERDES_UNIT_INDX type;
+	u32 reg_low_speed;
+	u32 val_low_speed;
+	u32 reg_hi_speed;
+	u32 val_hi_speed;
+} MV_SERDES_CHANGE_M_PHY;
+
+/*
+ * Configuration per SERDES line. Each nibble is MV_SERDES_LINE_TYPE
+ */
+typedef struct board_serdes_conf {
+	MV_PEX_TYPE pex_type; /* MV_PEX_ROOT_COMPLEX MV_PEX_END_POINT */
+	u32 line0_7; /* Lines 0 to 7 SERDES MUX one nibble per line */
+	u32 line8_15; /* Lines 8 to 15 SERDES MUX one nibble per line */
+	MV_PEX_UNIT_CFG pex_mode[4];
+
+	/*
+	 * Bus speed - one bit per SERDES line:
+	 *		Low speed (0)		High speed (1)
+	 * PEX		2.5 G (10 bit)		5 G (20 bit)
+	 * SATA		1.5 G			3 G
+	 * SGMII	1.25 Gbps		3.125 Gbps
+	 */
+	u32	bus_speed;
+
+	MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change;
+} MV_BIN_SERDES_CFG;
+
+
+#define BIN_SERDES_CFG {	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 0 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1,  2}, /* Lane 1 */	\
+	{0, 1, -1 ,  2, -1, -1, -1, -1,  3}, /* Lane 2 */	\
+	{0, 1, -1 , -1,  2, -1, -1,  3, -1}, /* Lane 3 */	\
+	{0, 1,  2 , -1, -1,  3, -1, -1,  4}, /* Lane 4 */	\
+	{0, 1,  2 , -1,  3, -1, -1,  4, -1}, /* Lane 5 */	\
+	{0, 1,  2 ,  4, -1,  3, -1, -1, -1}, /* Lane 6 */	\
+	{0, 1, -1 ,  2, -1, -1,  3, -1,  4}, /* Lane 7*/	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 8 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 9 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 10 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 11 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 12 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 13 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 14 */	\
+	{0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 15 */	\
+}
+
+#endif /* __HIGHSPEED_ENV_SPEC_H */
diff --git a/arch/arm/mvebu-common/u-boot-spl.lds b/arch/arm/mvebu-common/u-boot-spl.lds
new file mode 100644
index 0000000..eee1db4
--- /dev/null
+++ b/arch/arm/mvebu-common/u-boot-spl.lds
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *	Aneesh V <aneesh@ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+		LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	.text      :
+	{
+		__start = .;
+		arch/arm/cpu/armv7/start.o	(.text*)
+		*(.text*)
+		*(.vectors)
+	} >.sram
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*_i2c_*)));
+	} >.sram
+
+	. = ALIGN(4);
+	__image_copy_end = .;
+
+	.end :
+	{
+		*(.__end)
+	}
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} >.sdram
+}
diff --git a/arch/avr32/config.mk b/arch/avr32/config.mk
index 469185e..8252f59 100644
--- a/arch/avr32/config.mk
+++ b/arch/avr32/config.mk
@@ -9,6 +9,9 @@
 CROSS_COMPILE := avr32-linux-
 endif
 
+# avr32 has generic board support
+__HAVE_ARCH_GENERIC_BOARD := y
+
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000
 
 PLATFORM_RELFLAGS	+= -ffixed-r5 -fPIC -mno-init-got -mrelax
diff --git a/arch/avr32/cpu/Makefile b/arch/avr32/cpu/Makefile
index 00cede3..e111db3 100644
--- a/arch/avr32/cpu/Makefile
+++ b/arch/avr32/cpu/Makefile
@@ -16,5 +16,6 @@
 obj-y			+= interrupts.o
 obj-$(CONFIG_PORTMUX_PIO) += portmux-pio.o
 obj-$(CONFIG_PORTMUX_GPIO) += portmux-gpio.o
+obj-y += mmc.o
 
 obj-$(if $(filter at32ap700x,$(SOC)),y) += at32ap700x/
diff --git a/arch/avr32/cpu/at32ap700x/mmu.c b/arch/avr32/cpu/at32ap700x/mmu.c
index 0e28b21..f5e62f2 100644
--- a/arch/avr32/cpu/at32ap700x/mmu.c
+++ b/arch/avr32/cpu/at32ap700x/mmu.c
@@ -7,7 +7,7 @@
 	uintptr_t	vmr_table_addr;
 
 	/* Round monitor address down to the nearest page boundary */
-	dest_addr &= PAGE_ADDR_MASK;
+	dest_addr &= MMU_PAGE_ADDR_MASK;
 
 	/* Initialize TLB entry 0 to cover the monitor, and lock it */
 	sysreg_write(TLBEHI, dest_addr | SYSREG_BIT(TLBEHI_V));
@@ -36,7 +36,7 @@
 	unsigned int fault_pgno;
 	int first, last;
 
-	fault_pgno = sysreg_read(TLBEAR) >> PAGE_SHIFT;
+	fault_pgno = sysreg_read(TLBEAR) >> MMU_PAGE_SHIFT;
 	vmr_table = (const struct mmu_vm_range *)sysreg_read(PTBR);
 
 	/* Do a binary search through the VM ranges */
@@ -60,8 +60,8 @@
 			/* Got it; let's slam it into the TLB */
 			uint32_t tlbelo;
 
-			tlbelo = vmr->phys & ~PAGE_ADDR_MASK;
-			tlbelo |= fault_pgno << PAGE_SHIFT;
+			tlbelo = vmr->phys & ~MMU_PAGE_ADDR_MASK;
+			tlbelo |= fault_pgno << MMU_PAGE_SHIFT;
 			sysreg_write(TLBELO, tlbelo);
 			__builtin_tlbw();
 
diff --git a/arch/avr32/cpu/cpu.c b/arch/avr32/cpu/cpu.c
index cef630e..cd226a6 100644
--- a/arch/avr32/cpu/cpu.c
+++ b/arch/avr32/cpu/cpu.c
@@ -27,7 +27,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int cpu_init(void)
+int arch_cpu_init(void)
 {
 	extern void _evba(void);
 
diff --git a/arch/avr32/cpu/exception.c b/arch/avr32/cpu/exception.c
index 5d1bc68..d6991f6 100644
--- a/arch/avr32/cpu/exception.c
+++ b/arch/avr32/cpu/exception.c
@@ -96,11 +96,11 @@
 	printf("CPU Mode: %s\n", cpu_modes[mode]);
 
 	/* Avoid exception loops */
-	if (regs->sp < (gd->arch.stack_end - CONFIG_STACKSIZE)
-			|| regs->sp >= gd->arch.stack_end)
+	if (regs->sp < (gd->start_addr_sp - CONFIG_STACKSIZE) ||
+	    regs->sp >= gd->start_addr_sp)
 		printf("\nStack pointer seems bogus, won't do stack dump\n");
 	else
-		dump_mem("\nStack: ", regs->sp, gd->arch.stack_end);
+		dump_mem("\nStack: ", regs->sp, gd->start_addr_sp);
 
 	panic("Unhandled exception\n");
 }
diff --git a/arch/avr32/cpu/mmc.c b/arch/avr32/cpu/mmc.c
new file mode 100644
index 0000000..b7213e4
--- /dev/null
+++ b/arch/avr32/cpu/mmc.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ * Copyright (C) 2015 Andreas Bießmann <andreas.devel@googlmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <atmel_mci.h>
+#include <asm/arch/hardware.h>
+
+/* provide cpu_mmc_init, to overwrite provide board_mmc_init */
+int cpu_mmc_init(bd_t *bd)
+{
+	/* This calls the atmel_mci_init in gen_atmel_mci.c */
+	return atmel_mci_init((void *)ATMEL_BASE_MMCI);
+}
diff --git a/arch/avr32/cpu/u-boot.lds b/arch/avr32/cpu/u-boot.lds
index cb29a22..b0180e3 100644
--- a/arch/avr32/cpu/u-boot.lds
+++ b/arch/avr32/cpu/u-boot.lds
@@ -48,9 +48,11 @@
 	_edata = .;
 
 	.bss (NOLOAD) : {
+		__bss_start = .;
 		*(.bss)
 		*(.bss.*)
 	}
 	. = ALIGN(8);
 	__bss_end = .;
+	__init_end = .;
 }
diff --git a/arch/avr32/include/asm/arch-at32ap700x/mmu.h b/arch/avr32/include/asm/arch-at32ap700x/mmu.h
index fcd9a05..4736312 100644
--- a/arch/avr32/include/asm/arch-at32ap700x/mmu.h
+++ b/arch/avr32/include/asm/arch-at32ap700x/mmu.h
@@ -13,9 +13,9 @@
 
 #include <asm/sysreg.h>
 
-#define PAGE_SHIFT	20
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#define PAGE_ADDR_MASK	(~(PAGE_SIZE - 1))
+#define MMU_PAGE_SHIFT	20
+#define MMU_PAGE_SIZE	(1UL << MMU_PAGE_SHIFT)
+#define MMU_PAGE_ADDR_MASK	(~(MMU_PAGE_SIZE - 1))
 
 #define MMU_VMR_CACHE_NONE						\
 	(SYSREG_BF(AP, 3) | SYSREG_BF(SZ, 3) | SYSREG_BIT(TLBELO_D))
diff --git a/arch/avr32/include/asm/config.h b/arch/avr32/include/asm/config.h
index 63056a4..529fe22 100644
--- a/arch/avr32/include/asm/config.h
+++ b/arch/avr32/include/asm/config.h
@@ -8,5 +8,6 @@
 #define _ASM_CONFIG_H_
 
 #define CONFIG_NEEDS_MANUAL_RELOC
+#define CONFIG_SYS_GENERIC_GLOBAL_DATA
 
 #endif
diff --git a/arch/avr32/include/asm/dma-mapping.h b/arch/avr32/include/asm/dma-mapping.h
index dbdd2fe..1cde827 100644
--- a/arch/avr32/include/asm/dma-mapping.h
+++ b/arch/avr32/include/asm/dma-mapping.h
@@ -14,7 +14,12 @@
 	DMA_TO_DEVICE		= 1,
 	DMA_FROM_DEVICE		= 2,
 };
-extern void *dma_alloc_coherent(size_t len, unsigned long *handle);
+
+static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
+{
+	*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
+	return (void *)*handle;
+}
 
 static inline unsigned long dma_map_single(volatile void *vaddr, size_t len,
 					   enum dma_data_direction dir)
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index d82fb7c..60abd00 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -8,7 +8,6 @@
 
 /* Architecture-specific global data */
 struct arch_global_data {
-	unsigned long stack_end;	/* highest stack address */
 	unsigned long cpu_hz;		/* cpu core clock frequency */
 };
 
diff --git a/arch/avr32/include/asm/u-boot.h b/arch/avr32/include/asm/u-boot.h
index 6aef808..8b047ec 100644
--- a/arch/avr32/include/asm/u-boot.h
+++ b/arch/avr32/include/asm/u-boot.h
@@ -6,6 +6,11 @@
 #ifndef __ASM_U_BOOT_H__
 #define __ASM_U_BOOT_H__ 1
 
+#ifdef CONFIG_SYS_GENERIC_BOARD
+/* Use the generic board which requires a unified bd_info */
+#include <asm-generic/u-boot.h>
+#else
+
 typedef struct bd_info {
 	unsigned char		bi_phy_id[4];
 	unsigned long		bi_board_number;
@@ -22,7 +27,12 @@
 #define bi_memstart bi_dram[0].start
 #define bi_memsize bi_dram[0].size
 
+#endif
+
 /* For image.h:image_check_target_arch() */
 #define IH_ARCH_DEFAULT IH_ARCH_AVR32
 
+int arch_cpu_init(void);
+int dram_init(void);
+
 #endif /* __ASM_U_BOOT_H__ */
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile
index bb45cbe..6750913 100644
--- a/arch/avr32/lib/Makefile
+++ b/arch/avr32/lib/Makefile
@@ -8,6 +8,9 @@
 #
 
 obj-y	+= memset.o
+ifndef CONFIG_SYS_GENERIC_BOARD
 obj-y	+= board.o
+endif
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-y	+= interrupts.o
+obj-y	+= dram_init.o
diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c
index bf0997f..99aa96e 100644
--- a/arch/avr32/lib/board.c
+++ b/arch/avr32/lib/board.c
@@ -9,7 +9,6 @@
 #include <stdio_dev.h>
 #include <version.h>
 #include <net.h>
-#include <atmel_mci.h>
 
 #ifdef CONFIG_BITBANGMII
 #include <miiphy.h>
@@ -30,6 +29,12 @@
 
 unsigned long monitor_flash_len;
 
+__weak void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size =  gd->ram_size;
+}
+
 /* Weak aliases for optional board functions */
 static int __do_nothing(void)
 {
@@ -38,57 +43,6 @@
 int board_postclk_init(void) __attribute__((weak, alias("__do_nothing")));
 int board_early_init_r(void) __attribute__((weak, alias("__do_nothing")));
 
-/* provide cpu_mmc_init, to overwrite provide board_mmc_init */
-int cpu_mmc_init(bd_t *bd)
-{
-	/* This calls the atmel_mci_init in gen_atmel_mci.c */
-	return atmel_mci_init((void *)ATMEL_BASE_MMCI);
-}
-
-#ifdef CONFIG_SYS_DMA_ALLOC_LEN
-#include <asm/arch/cacheflush.h>
-#include <asm/io.h>
-
-static unsigned long dma_alloc_start;
-static unsigned long dma_alloc_end;
-static unsigned long dma_alloc_brk;
-
-static void dma_alloc_init(void)
-{
-	unsigned long monitor_addr;
-
-	monitor_addr = CONFIG_SYS_MONITOR_BASE + gd->reloc_off;
-	dma_alloc_end = monitor_addr - CONFIG_SYS_MALLOC_LEN;
-	dma_alloc_start = dma_alloc_end - CONFIG_SYS_DMA_ALLOC_LEN;
-	dma_alloc_brk = dma_alloc_start;
-
-	printf("DMA: Using memory from 0x%08lx to 0x%08lx\n",
-	       dma_alloc_start, dma_alloc_end);
-
-	invalidate_dcache_range((unsigned long)cached(dma_alloc_start),
-				dma_alloc_end);
-}
-
-void *dma_alloc_coherent(size_t len, unsigned long *handle)
-{
-	unsigned long paddr = dma_alloc_brk;
-
-	if (dma_alloc_brk + len > dma_alloc_end)
-		return NULL;
-
-	dma_alloc_brk = ((paddr + len + CONFIG_SYS_DCACHE_LINESZ - 1)
-			 & ~(CONFIG_SYS_DCACHE_LINESZ - 1));
-
-	*handle = paddr;
-	return uncached(paddr);
-}
-#else
-static inline void dma_alloc_init(void)
-{
-
-}
-#endif
-
 static int init_baudrate(void)
 {
 	gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
@@ -134,7 +88,6 @@
 	unsigned long monitor_len;
 	unsigned long monitor_addr;
 	unsigned long addr;
-	long sdram_size;
 
 	/* Initialize the global data pointer */
 	memset(&gd_data, 0, sizeof(gd_data));
@@ -142,17 +95,17 @@
 
 	/* Perform initialization sequence */
 	board_early_init_f();
-	cpu_init();
+	arch_cpu_init();
 	board_postclk_init();
 	env_init();
 	init_baudrate();
 	serial_init();
 	console_init_f();
 	display_banner();
-	sdram_size = initdram(board_type);
+	dram_init();
 
 	/* If we have no SDRAM, we can't go on */
-	if (sdram_size <= 0)
+	if (gd->ram_size <= 0)
 		panic("No working SDRAM available\n");
 
 	/*
@@ -166,7 +119,7 @@
 	 *  - global data struct
 	 *  - stack
 	 */
-	addr = CONFIG_SYS_SDRAM_BASE + sdram_size;
+	addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
 	monitor_len = (char *)(&__bss_end) - _text;
 
 	/*
@@ -180,12 +133,6 @@
 	/* Reserve memory for malloc() */
 	addr -= CONFIG_SYS_MALLOC_LEN;
 
-#ifdef CONFIG_SYS_DMA_ALLOC_LEN
-	/* Reserve DMA memory (must be cache aligned) */
-	addr &= ~(CONFIG_SYS_DCACHE_LINESZ - 1);
-	addr -= CONFIG_SYS_DMA_ALLOC_LEN;
-#endif
-
 #ifdef CONFIG_LCD
 #ifdef CONFIG_FB_ADDR
 	printf("LCD: Frame buffer allocated at preset 0x%08x\n",
@@ -210,16 +157,11 @@
 
 	/* And finally, a new, bigger stack. */
 	new_sp = (unsigned long *)addr;
-	gd->arch.stack_end = addr;
+	gd->start_addr_sp = addr;
 	*(--new_sp) = 0;
 	*(--new_sp) = 0;
 
-	/*
-	 * Initialize the board information struct with the
-	 * information we have.
-	 */
-	bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
-	bd->bi_dram[0].size = sdram_size;
+	dram_init_banksize();
 
 	memcpy(new_gd, gd, sizeof(gd_t));
 
@@ -264,7 +206,6 @@
 	/* The malloc area is right below the monitor image in RAM */
 	mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
 			CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);
-	dma_alloc_init();
 
 	enable_interrupts();
 
diff --git a/arch/avr32/lib/dram_init.c b/arch/avr32/lib/dram_init.c
new file mode 100644
index 0000000..5078e77
--- /dev/null
+++ b/arch/avr32/lib/dram_init.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Andreas Bießmann <andreas.devel@googlemail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	/* check for the maximum amount of memory possible on AP7000 devices */
+	gd->ram_size = get_ram_size(
+		(void *)CONFIG_SYS_SDRAM_BASE,
+		(256<<20));
+	return 0;
+}
diff --git a/arch/avr32/lib/interrupts.c b/arch/avr32/lib/interrupts.c
index bacb2d1..5f3a49e 100644
--- a/arch/avr32/lib/interrupts.c
+++ b/arch/avr32/lib/interrupts.c
@@ -7,6 +7,11 @@
 
 #include <asm/sysreg.h>
 
+int interrupt_init(void)
+{
+	return 0;
+}
+
 void enable_interrupts(void)
 {
 	asm volatile("csrf	%0" : : "n"(SYSREG_GM_OFFSET));
diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c
index b7f1188..91aa5cc 100644
--- a/arch/blackfin/cpu/cpu.c
+++ b/arch/blackfin/cpu/cpu.c
@@ -24,6 +24,7 @@
 
 #include "cpu.h"
 #include "initcode.h"
+#include "exports.h"
 
 ulong bfin_poweron_retx;
 DECLARE_GLOBAL_DATA_PTR;
@@ -121,7 +122,7 @@
 	printf(" |-ram_size: %lx\n", gd->ram_size);
 	printf(" |-env_addr: %lx\n", gd->env_addr);
 	printf(" |-env_valid: %lx\n", gd->env_valid);
-	printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt));
+	printf(" |-jt(%p): %p\n", gd->jt, gd->jt->get_version);
 	printf(" \\-bd: %p\n", gd->bd);
 	printf("   |-bi_boot_params: %lx\n", bd->bi_boot_params);
 	printf("   |-bi_memstart: %lx\n", bd->bi_memstart);
diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk
index 98bbf79..2b817be 100644
--- a/arch/microblaze/config.mk
+++ b/arch/microblaze/config.mk
@@ -15,3 +15,8 @@
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
 
 PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
+
+ifeq ($(CONFIG_SPL_BUILD),)
+PLATFORM_CPPFLAGS += -fPIC
+endif
+__HAVE_ARCH_GENERIC_BOARD := y
diff --git a/arch/microblaze/cpu/exception.c b/arch/microblaze/cpu/exception.c
index 227842f..aa34f45 100644
--- a/arch/microblaze/cpu/exception.c
+++ b/arch/microblaze/cpu/exception.c
@@ -13,49 +13,52 @@
 {
 	int address = 0;
 	int state = 0;
+
 	/* loading address of exception EAR */
-	MFS (address, rear);
+	MFS(address, rear);
 	/* loading excetpion state register ESR */
-	MFS (state, resr);
-	printf ("Hardware exception at 0x%x address\n", address);
+	MFS(state, resr);
+	printf("Hardware exception at 0x%x address\n", address);
+	R17(address);
+	printf("Return address from exception 0x%x\n", address);
 	switch (state & 0x1f) {	/* mask on exception cause */
 	case 0x1:
-		puts ("Unaligned data access exception\n");
+		puts("Unaligned data access exception\n");
 		break;
 	case 0x2:
-		puts ("Illegal op-code exception\n");
+		puts("Illegal op-code exception\n");
 		break;
 	case 0x3:
-		puts ("Instruction bus error exception\n");
+		puts("Instruction bus error exception\n");
 		break;
 	case 0x4:
-		puts ("Data bus error exception\n");
+		puts("Data bus error exception\n");
 		break;
 	case 0x5:
-		puts ("Divide by zero exception\n");
+		puts("Divide by zero exception\n");
 		break;
 #ifdef MICROBLAZE_V5
 	case 0x7:
 		puts("Priviledged or stack protection violation exception\n");
 		break;
 	case 0x1000:
-		puts ("Exception in delay slot\n");
+		puts("Exception in delay slot\n");
 		break;
 #endif
 	default:
-		puts ("Undefined cause\n");
+		puts("Undefined cause\n");
 		break;
 	}
-	printf ("Unaligned %sword access\n", ((state & 0x800) ? "" : "half"));
-	printf ("Unaligned %s access\n", ((state & 0x400) ? "store" : "load"));
-	printf ("Register R%x\n", (state & 0x3E) >> 5);
-	hang ();
+	printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half"));
+	printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load"));
+	printf("Register R%x\n", (state & 0x3E) >> 5);
+	hang();
 }
 
 #ifdef CONFIG_SYS_USR_EXCEP
 void _exception_handler (void)
 {
-	puts ("User vector_exception\n");
-	hang ();
+	puts("User vector_exception\n");
+	hang();
 }
 #endif
diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c
index 9364e2f..b6d6610 100644
--- a/arch/microblaze/cpu/interrupts.c
+++ b/arch/microblaze/cpu/interrupts.c
@@ -14,10 +14,9 @@
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 
-#undef DEBUG_INT
-
 void enable_interrupts(void)
 {
+	debug("Enable interrupts for the whole CPU\n");
 	MSRSET(0x2);
 }
 
@@ -50,12 +49,11 @@
 	offset <<= irq;
 	mask = intc->ier;
 	intc->ier = (mask | offset);
-#ifdef DEBUG_INT
-	printf("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
-		intc->ier);
-	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-		intc->iar, intc->mer);
-#endif
+
+	debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
+	      intc->ier);
+	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+	      intc->iar, intc->mer);
 }
 
 static void disable_one_interrupt(int irq)
@@ -66,12 +64,11 @@
 	offset <<= irq;
 	mask = intc->ier;
 	intc->ier = (mask & ~offset);
-#ifdef DEBUG_INT
-	printf("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
-		intc->ier);
-	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-		intc->iar, intc->mer);
-#endif
+
+	debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
+	      intc->ier);
+	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+	      intc->iar, intc->mer);
 }
 
 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
@@ -88,12 +85,12 @@
 		act->handler = hdlr;
 		act->arg = arg;
 		act->count = 0;
-		enable_one_interrupt (irq);
+		enable_one_interrupt(irq);
 		return 0;
 	}
 
 	/* Disable */
-	act->handler = (interrupt_handler_t *) def_hdlr;
+	act->handler = (interrupt_handler_t *)def_hdlr;
 	act->arg = (void *)irq;
 	disable_one_interrupt(irq);
 	return 1;
@@ -107,18 +104,17 @@
 	intc->iar = 0xFFFFFFFF;
 	/* XIntc_Start - hw_interrupt enable and all interrupt enable */
 	intc->mer = 0x3;
-#ifdef DEBUG_INT
-	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-		intc->iar, intc->mer);
-#endif
+
+	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+	      intc->iar, intc->mer);
 }
 
-int interrupts_init(void)
+int interrupt_init(void)
 {
 	int i;
 
 #if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
-	intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR);
+	intc = (microblaze_intc_t *)CONFIG_SYS_INTC_0_ADDR;
 	irq_no = CONFIG_SYS_INTC_0_NUM;
 #endif
 	if (irq_no) {
@@ -130,7 +126,7 @@
 
 		/* initialize irq list */
 		for (i = 0; i < irq_no; i++) {
-			vecs[i].handler = (interrupt_handler_t *) def_hdlr;
+			vecs[i].handler = (interrupt_handler_t *)def_hdlr;
 			vecs[i].arg = (void *)i;
 			vecs[i].count = 0;
 		}
@@ -147,31 +143,29 @@
 {
 	int irqs = intc->ivr;	/* find active interrupt */
 	int mask = 1;
-#ifdef DEBUG_INT
 	int value;
-	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-		intc->iar, intc->mer);
-	R14(value);
-	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
-#endif
 	struct irq_action *act = vecs + irqs;
 
-#ifdef DEBUG_INT
-	printf
-	    ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
-	     act->handler, act->count, act->arg);
+	debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+	      intc->iar, intc->mer);
+#ifdef DEBUG
+	R14(value);
 #endif
-	act->handler (act->arg);
+	debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
+
+	debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
+	      (u32)act->handler, act->count, (u32)act->arg);
+	act->handler(act->arg);
 	act->count++;
 
 	intc->iar = mask << irqs;
 
-#ifdef DEBUG_INT
-	printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
-		intc->ier, intc->iar, intc->mer);
+	debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
+	      intc->ier, intc->iar, intc->mer);
+#ifdef DEBUG
 	R14(value);
-	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
 #endif
+	debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
 }
 
 #if defined(CONFIG_CMD_IRQ)
@@ -186,10 +180,10 @@
 		      "-----------------------------\n");
 
 		for (i = 0; i < irq_no; i++) {
-			if (act->handler != (interrupt_handler_t *) def_hdlr) {
+			if (act->handler != (interrupt_handler_t *)def_hdlr) {
 				printf("%02d  %08x  %08x  %d\n", i,
-					(int)act->handler, (int)act->arg,
-								act->count);
+				       (int)act->handler, (int)act->arg,
+				       act->count);
 			}
 			act++;
 		}
diff --git a/arch/microblaze/cpu/irq.S b/arch/microblaze/cpu/irq.S
index 2401589..5cfe151 100644
--- a/arch/microblaze/cpu/irq.S
+++ b/arch/microblaze/cpu/irq.S
@@ -11,71 +11,70 @@
 	.text
 	.global _interrupt_handler
 _interrupt_handler:
-	swi	r2, r1, -4
-	swi	r3, r1, -8
-	swi	r4, r1, -12
-	swi	r5, r1, -16
-	swi	r6, r1, -20
-	swi	r7, r1, -24
-	swi	r8, r1, -28
-	swi	r9, r1, -32
-	swi	r10, r1, -36
-	swi	r11, r1, -40
-	swi	r12, r1, -44
-	swi	r13, r1, -48
-	swi	r14, r1, -52
-	swi	r15, r1, -56
-	swi	r16, r1, -60
-	swi	r17, r1, -64
-	swi	r18, r1, -68
-	swi	r19, r1, -72
-	swi	r20, r1, -76
-	swi	r21, r1, -80
-	swi	r22, r1, -84
-	swi	r23, r1, -88
-	swi	r24, r1, -92
-	swi	r25, r1, -96
-	swi	r26, r1, -100
-	swi	r27, r1, -104
-	swi	r28, r1, -108
-	swi	r29, r1, -112
-	swi	r30, r1, -116
-	swi	r31, r1, -120
 	addik	r1, r1, -124
+	swi	r2, r1, 4
+	swi	r3, r1, 8
+	swi	r4, r1, 12
+	swi	r5, r1, 16
+	swi	r6, r1, 20
+	swi	r7, r1, 24
+	swi	r8, r1, 28
+	swi	r9, r1, 32
+	swi	r10, r1, 36
+	swi	r11, r1, 40
+	swi	r12, r1, 44
+	swi	r13, r1, 48
+	swi	r14, r1, 52
+	swi	r15, r1, 56
+	swi	r16, r1, 60
+	swi	r17, r1, 64
+	swi	r18, r1, 68
+	swi	r19, r1, 72
+	swi	r20, r1, 76
+	swi	r21, r1, 80
+	swi	r22, r1, 84
+	swi	r23, r1, 88
+	swi	r24, r1, 92
+	swi	r25, r1, 96
+	swi	r26, r1, 100
+	swi	r27, r1, 104
+	swi	r28, r1, 108
+	swi	r29, r1, 112
+	swi	r30, r1, 116
+	swi	r31, r1, 120
 	brlid	r15, interrupt_handler
 	nop
+	lwi	r31, r1, 120
+	lwi	r30, r1, 116
+	lwi	r29, r1, 112
+	lwi	r28, r1, 108
+	lwi	r27, r1, 104
+	lwi	r26, r1, 100
+	lwi	r25, r1, 96
+	lwi	r24, r1, 92
+	lwi	r23, r1, 88
+	lwi	r22, r1, 84
+	lwi	r21, r1, 80
+	lwi	r20, r1, 76
+	lwi	r19, r1, 72
+	lwi	r18, r1, 68
+	lwi	r17, r1, 64
+	lwi	r16, r1, 60
+	lwi	r15, r1, 56
+	lwi	r14, r1, 52
+	lwi	r13, r1, 48
+	lwi	r12, r1, 44
+	lwi	r11, r1, 40
+	lwi	r10, r1, 36
+	lwi	r9, r1, 32
+	lwi	r8, r1, 28
+	lwi	r7, r1, 24
+	lwi	r6, r1, 20
+	lwi	r5, r1, 16
+	lwi	r4, r1, 12
+	lwi	r3, r1, 8
+	lwi	r2, r1, 4
 	addik	r1, r1, 124
-	lwi	r31, r1, -120
-	lwi	r30, r1, -116
-	lwi	r29, r1, -112
-	lwi	r28, r1, -108
-	lwi	r27, r1, -104
-	lwi	r26, r1, -100
-	lwi	r25, r1, -96
-	lwi	r24, r1, -92
-	lwi	r23, r1, -88
-	lwi	r22, r1, -84
-	lwi	r21, r1, -80
-	lwi	r20, r1, -76
-	lwi	r19, r1, -72
-	lwi	r18, r1, -68
-	lwi	r17, r1, -64
-	lwi	r16, r1, -60
-	lwi	r15, r1, -56
-	lwi	r14, r1, -52
-	lwi	r13, r1, -48
-	lwi	r12, r1, -44
-	lwi	r11, r1, -40
-	lwi	r10, r1, -36
-	lwi	r9, r1, -32
-	lwi	r8, r1, -28
-	lwi	r7, r1, -24
-	lwi	r6, r1, -20
-	lwi	r5, r1, -16
-	lwi	r4, r1, -12
-	lwi	r3, r1, -8
-	lwi	r2, r1, -4
-
 	rtid	r14, 0
 	nop
 	.size _interrupt_handler,.-_interrupt_handler
diff --git a/arch/microblaze/cpu/spl.c b/arch/microblaze/cpu/spl.c
index 0912261..2cc0a2d 100644
--- a/arch/microblaze/cpu/spl.c
+++ b/arch/microblaze/cpu/spl.c
@@ -25,8 +25,6 @@
 /* Board initialization after bss clearance */
 void spl_board_init(void)
 {
-	gd = (gd_t *)CONFIG_SPL_STACK_ADDR;
-
 	/* enable console uart printing */
 	preloader_console_init();
 }
diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S
index 84c29e5..953d3a1 100644
--- a/arch/microblaze/cpu/start.S
+++ b/arch/microblaze/cpu/start.S
@@ -30,7 +30,11 @@
 	mts	rshr, r1
 	addi	r1, r1, -4	/* Decrement SP to top of memory */
 #else
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
+#else
 	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
+#endif
 	mts	rshr, r1
 	addi	r1, r1, -4	/* Decrement SP to top of memory */
 
@@ -129,7 +133,7 @@
 	/* Flush cache before enable cache */
 	addik	r5, r0, 0
 	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
-flush:	bralid r15, flush_cache
+	bralid r15, flush_cache
 	nop
 
 	/* enable instruction and data cache */
@@ -150,12 +154,28 @@
 	bnei    r6, 2b
 3:	/* jumping to board_init */
 #ifndef CONFIG_SPL_BUILD
+	or	r5, r0, r0	/* flags - empty */
+	addi    r31, r0, _gd
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+	addi	r6, r0, CONFIG_SYS_INIT_SP_OFFSET
+	swi	r6, r31, GD_MALLOC_BASE
+#endif
 	brai	board_init_f
 #else
+	addi	r31, r0, _gd
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+	addi	r6, r0, CONFIG_SPL_STACK_ADDR
+	swi	r6, r31, GD_MALLOC_BASE
+#endif
 	brai	board_init_r
 #endif
 1:	bri	1b
 
+ .section .bss
+.align 4
+_gd:
+         .space  GENERATED_GBL_DATA_SIZE
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * Read 16bit little endian
@@ -189,4 +209,108 @@
 	rtsd	r15, 8
 	or	r0, r0, r0
 	.end	out16
+
+/*
+ * Relocate u-boot
+ */
+	.text
+	.global	relocate_code
+	.ent	relocate_code
+	.align	2
+relocate_code:
+	/*
+	 * r5 - start_addr_sp
+	 * r6 - new_gd
+	 * r7 - reloc_addr
+	 */
+	addi	r1, r5, 0 /* Start to use new SP */
+	addi	r31, r6, 0 /* Start to use new GD */
+
+	add	r23, r0, r7 /* Move reloc addr to r23 */
+	/* Relocate text and data - r12 temp value */
+	addi	r21, r0, _start
+	addi	r22, r0, __end - 4 /* Include BSS too */
+
+	rsub	r6, r21, r22
+	or	r5, r0, r0
+1:	lw	r12, r21, r5 /* Load u-boot data */
+	sw	r12, r23, r5 /* Write zero to loc */
+	cmp	r12, r5, r6 /* Check if we have reach the end */
+	bneid	r12, 1b
+	addi	r5, r5, 4 /* Increment to next loc - relocate code */
+
+       /* R23 points to the base address. */
+	add	r23, r0, r7 /* Move reloc addr to r23 */
+	addi	r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
+	rsub	r23, r24, r23 /* keep - this is already here gd->reloc_off */
+
+	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
+	lwi	r7, r0, 0x28
+	swi	r6, r0, 0x28 /* used first unused MB vector */
+	lbui	r10, r0, 0x28 /* used first unused MB vector */
+	swi	r7, r0, 0x28
+
+#ifdef CONFIG_SYS_USR_EXCEP
+	addik	r6, r0, _exception_handler
+	addk	r6, r6, r23 /* add offset */
+	sw	r6, r1, r0
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0xa
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0xe
+	sh	r6, r0, r8
+#endif
+	addik	r6, r0, _hw_exception_handler
+	addk	r6, r6, r23 /* add offset */
+	sw	r6, r1, r0
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0x22
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0x26
+	sh	r6, r0, r8
+
+	addik	r6, r0, _interrupt_handler
+	addk	r6, r6, r23 /* add offset */
+	sw	r6, r1, r0
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0x12
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0x16
+	sh	r6, r0, r8
+
+	/* Check if GOT exist */
+	addik	r21, r23, _got_start
+	addik	r22, r23, _got_end
+	cmpu	r12, r21, r22
+	beqi	r12, 2f /* No GOT table - jump over */
+
+	/* Skip last 3 entries plus 1 because of loop boundary below */
+	addik	r22, r22, -0x10
+
+        /* Relocate the GOT. */
+3:	lw	r12, r21, r0 /* Load entry */
+	addk	r12, r12, r23 /* Add reloc offset */
+	sw	r12, r21, r0 /* Save entry back */
+
+	cmpu	r12, r21, r22 /* Check if this cross boundary */
+	bneid	r12, 3b
+	addik	r21. r21, 4
+
+	/* Update pointer to GOT */
+	mfs	r20, rpc
+	addik	r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
+	addk	r20, r20, r23
+
+	/* Flush caches to ensure consistency */
+	addik	r5, r0, 0
+	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
+	bralid	r15, flush_cache
+	nop
+
+2:	addi	r5, r31, 0 /* gd is initialized in board_r.c */
+	addi	r6, r0, CONFIG_SYS_TEXT_BASE
+	addi	r12, r23, board_init_r
+	bra	r12 /* Jump to relocated code */
+
+	.end	relocate_code
 #endif
diff --git a/arch/microblaze/cpu/u-boot-spl.lds b/arch/microblaze/cpu/u-boot-spl.lds
index 96353cd..c60336c 100644
--- a/arch/microblaze/cpu/u-boot-spl.lds
+++ b/arch/microblaze/cpu/u-boot-spl.lds
@@ -37,6 +37,12 @@
 		__data_end = .;
 	}
 
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+	__init_end = . ;
+
 	.bss ALIGN(0x4):
 	{
 		__bss_start = .;
diff --git a/arch/microblaze/cpu/u-boot.lds b/arch/microblaze/cpu/u-boot.lds
index fdad207..2502a0d 100644
--- a/arch/microblaze/cpu/u-boot.lds
+++ b/arch/microblaze/cpu/u-boot.lds
@@ -29,17 +29,23 @@
 	.data ALIGN(0x4):
 	{
 		__data_start = .;
-#ifdef CONFIG_OF_EMBED
-		dts/built-in.o (.data)
-#endif
 		*(.data)
 		__data_end = .;
 	}
 
+	.got ALIGN(4):
+	{
+		_got_start = .;
+		*(.got*)
+		. = ALIGN(4);
+		_got_end = .;
+	}
+
 	. = ALIGN(4);
 	.u_boot_list : {
 		KEEP(*(SORT(.u_boot_list*)));
 	}
+	__init_end = . ;
 
 	.bss ALIGN(0x4):
 	{
diff --git a/arch/microblaze/include/asm/asm.h b/arch/microblaze/include/asm/asm.h
index c1c3b03..11f3dd0 100644
--- a/arch/microblaze/include/asm/asm.h
+++ b/arch/microblaze/include/asm/asm.h
@@ -43,6 +43,10 @@
 #define R14(val) \
 	__asm__ __volatile__ ("addi %0, r14, 0":"=r" (val));
 
+/* get return address from interrupt */
+#define R17(val) \
+	__asm__ __volatile__ ("addi %0, r17, 0" : "=r" (val));
+
 #define NOP	__asm__ __volatile__ ("nop");
 
 /* use machine status registe USE_MSR_REG */
diff --git a/arch/microblaze/include/asm/config.h b/arch/microblaze/include/asm/config.h
index cd29734..32fd636 100644
--- a/arch/microblaze/include/asm/config.h
+++ b/arch/microblaze/include/asm/config.h
@@ -7,4 +7,11 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_
 
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_NEEDS_MANUAL_RELOC
+#endif
+
+#define CONFIG_NR_DRAM_BANKS	1
+#define CONFIG_SYS_GENERIC_BOARD
+
 #endif
diff --git a/arch/microblaze/include/asm/microblaze_intc.h b/arch/microblaze/include/asm/microblaze_intc.h
index 0fb9207..6586838 100644
--- a/arch/microblaze/include/asm/microblaze_intc.h
+++ b/arch/microblaze/include/asm/microblaze_intc.h
@@ -34,5 +34,3 @@
  */
 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr,
 				       void *arg);
-
-int interrupts_init(void);
diff --git a/arch/microblaze/include/asm/u-boot.h b/arch/microblaze/include/asm/u-boot.h
index 54d415e..66f8f95 100644
--- a/arch/microblaze/include/asm/u-boot.h
+++ b/arch/microblaze/include/asm/u-boot.h
@@ -16,16 +16,7 @@
 #ifndef _U_BOOT_H_
 #define _U_BOOT_H_
 
-typedef struct bd_info {
-	unsigned long	bi_memstart;	/* start of DRAM memory */
-	phys_size_t	bi_memsize;	/* size	 of DRAM memory in bytes */
-	unsigned long	bi_flashstart;	/* start of FLASH memory */
-	unsigned long	bi_flashsize;	/* size	 of FLASH memory */
-	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
-	unsigned long	bi_sramstart;	/* start of SRAM memory */
-	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
-	ulong		bi_boot_params; /* where this board expects params */
-} bd_t;
+#include <asm-generic/u-boot.h>
 
 /* For image.h:image_check_target_arch() */
 #define IH_ARCH_DEFAULT IH_ARCH_MICROBLAZE
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
index 339dd15..0289d0c 100644
--- a/arch/microblaze/lib/Makefile
+++ b/arch/microblaze/lib/Makefile
@@ -5,6 +5,5 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	+= board.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-y	+= muldi3.o
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
deleted file mode 100644
index 600c80a..0000000
--- a/arch/microblaze/lib/board.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * (C) Copyright 2007 Michal Simek
- * (C) Copyright 2004 Atmark Techno, Inc.
- *
- * Michal  SIMEK <monstr@monstr.eu>
- * Yasushi SHOJI <yashi@atmark-techno.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <malloc.h>
-#include <version.h>
-#include <watchdog.h>
-#include <stdio_dev.h>
-#include <serial.h>
-#include <net.h>
-#include <spi.h>
-#include <linux/compiler.h>
-#include <asm/processor.h>
-#include <asm/microblaze_intc.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static int display_banner(void)
-{
-	printf("\n\n%s\n\n", version_string);
-	return 0;
-}
-
-/*
- * All attempts to come up with a "common" initialization sequence
- * that works for all boards and architectures failed: some of the
- * requirements are just _too_ different. To get rid of the resulting
- * mess of board dependend #ifdef'ed code we now make the whole
- * initialization sequence configurable to the user.
- *
- * The requirements for any new initalization function is simple: it
- * receives a pointer to the "global data" structure as it's only
- * argument, and returns an integer return code, where 0 means
- * "continue" and != 0 means "fatal error, hang the system".
- */
-typedef int (init_fnc_t) (void);
-
-init_fnc_t *init_sequence[] = {
-	env_init,
-#ifdef CONFIG_OF_CONTROL
-	fdtdec_check_fdt,
-#endif
-	serial_init,
-#ifndef CONFIG_SPL_BUILD
-	console_init_f,
-#endif
-	display_banner,
-#ifndef CONFIG_SPL_BUILD
-	interrupts_init,
-	timer_init,
-#endif
-	NULL,
-};
-
-unsigned long monitor_flash_len;
-
-void board_init_f(ulong not_used)
-{
-	bd_t *bd;
-	init_fnc_t **init_fnc_ptr;
-	gd = (gd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
-	bd = (bd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET
-						- GENERATED_BD_INFO_SIZE);
-#if defined(CONFIG_CMD_FLASH) && !defined(CONFIG_SPL_BUILD)
-	ulong flash_size = 0;
-#endif
-	asm ("nop");	/* FIXME gd is not initialize - wait */
-	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
-	memset((void *)bd, 0, GENERATED_BD_INFO_SIZE);
-	gd->bd = bd;
-	gd->baudrate = CONFIG_BAUDRATE;
-	bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
-	bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
-	gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
-
-	monitor_flash_len = __end - __text_start;
-
-#ifdef CONFIG_OF_EMBED
-	/* Get a pointer to the FDT */
-	gd->fdt_blob = __dtb_dt_begin;
-#elif defined CONFIG_OF_SEPARATE
-	/* FDT is at end of image */
-	gd->fdt_blob = (void *)__end;
-#endif
-
-#ifndef CONFIG_SPL_BUILD
-	/* Allow the early environment to override the fdt address */
-	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
-						(uintptr_t)gd->fdt_blob);
-#endif
-
-	/*
-	 * The Malloc area is immediately below the monitor copy in DRAM
-	 * aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
-	 * as our monitory code is run from SDRAM
-	 */
-	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
-
-	serial_initialize();
-
-#ifdef CONFIG_XILINX_TB_WATCHDOG
-	hw_watchdog_init();
-#endif
-	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		WATCHDOG_RESET();
-		if ((*init_fnc_ptr) () != 0)
-			hang();
-	}
-
-#ifndef CONFIG_SPL_BUILD
-#ifdef CONFIG_OF_CONTROL
-	/* For now, put this check after the console is ready */
-	if (fdtdec_prepare_fdt())
-		panic("** No FDT - please see doc/README.fdt-control");
-	else
-		printf("DTB: 0x%x\n", (u32)gd->fdt_blob);
-#endif
-
-	puts("SDRAM :\n");
-	printf("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
-	printf("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
-	printf("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
-
-#if defined(CONFIG_CMD_FLASH)
-	puts("Flash: ");
-	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
-	flash_size = flash_init();
-	if (bd->bi_flashstart && flash_size > 0) {
-# ifdef CONFIG_SYS_FLASH_CHECKSUM
-		print_size(flash_size, "");
-		/*
-		 * Compute and print flash CRC if flashchecksum is set to 'y'
-		 *
-		 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
-		 */
-		if (getenv_yesno("flashchecksum") == 1) {
-			printf("  CRC: %08X",
-			       crc32(0, (const u8 *)bd->bi_flashstart,
-				     flash_size)
-			);
-		}
-		putc('\n');
-# else	/* !CONFIG_SYS_FLASH_CHECKSUM */
-		print_size(flash_size, "\n");
-# endif /* CONFIG_SYS_FLASH_CHECKSUM */
-		bd->bi_flashsize = flash_size;
-		bd->bi_flashoffset = bd->bi_flashstart + flash_size;
-	} else {
-		puts("Flash init FAILED");
-		bd->bi_flashstart = 0;
-		bd->bi_flashsize = 0;
-		bd->bi_flashoffset = 0;
-	}
-#endif
-
-#ifdef CONFIG_SPI
-	spi_init();
-#endif
-
-	/* relocate environment function pointers etc. */
-	env_relocate();
-
-	/* Initialize stdio devices */
-	stdio_init();
-
-	/* Initialize the jump table for applications */
-	jumptable_init();
-
-	/* Initialize the console (after the relocation and devices init) */
-	console_init_r();
-
-	board_init();
-
-	/* Initialize from environment */
-	load_addr = getenv_ulong("loadaddr", 16, load_addr);
-
-#if defined(CONFIG_CMD_NET)
-	printf("Net:   ");
-	eth_initialize(gd->bd);
-
-	uchar enetaddr[6];
-	eth_getenv_enetaddr("ethaddr", enetaddr);
-	printf("MAC:   %pM\n", enetaddr);
-#endif
-
-	/* main_loop */
-	for (;;) {
-		WATCHDOG_RESET();
-		main_loop();
-	}
-#endif /* CONFIG_SPL_BUILD */
-}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ef78929..bc4283d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -36,6 +36,7 @@
 	select SUPPORTS_BIG_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 config TARGET_DBAU1X00
 	bool "Support dbau1x00"
@@ -43,12 +44,14 @@
 	select SUPPORTS_LITTLE_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 config TARGET_PB1X00
 	bool "Support pb1x00"
 	select SUPPORTS_LITTLE_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 
 endchoice
@@ -185,6 +188,9 @@
 config SWAP_IO_SPACE
 	bool
 
+config SYS_MIPS_CACHE_INIT_RAM_LOAD
+	bool
+
 endif
 
 endmenu
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 0a9e7e6..43f0f5c 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -2,9 +2,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-head-$(CONFIG_CPU_MIPS32) := arch/mips/cpu/mips32/start.o
-head-$(CONFIG_CPU_MIPS64) := arch/mips/cpu/mips64/start.o
+head-y := arch/mips/cpu/start.o
 
-libs-$(CONFIG_CPU_MIPS32) += arch/mips/cpu/mips32/
-libs-$(CONFIG_CPU_MIPS64) += arch/mips/cpu/mips64/
+libs-y += arch/mips/cpu/
 libs-y += arch/mips/lib/
+
+libs-$(CONFIG_SOC_AU1X00) += arch/mips/mach-au1x00/
diff --git a/arch/mips/cpu/Makefile b/arch/mips/cpu/Makefile
new file mode 100644
index 0000000..fc6b455
--- /dev/null
+++ b/arch/mips/cpu/Makefile
@@ -0,0 +1,9 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+extra-y	= start.o
+
+obj-y += time.o
+obj-y += interrupts.o
+obj-y += cpu.o
diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c
new file mode 100644
index 0000000..8d3b2f5
--- /dev/null
+++ b/arch/mips/cpu/cpu.c
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <linux/compiler.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+
+void __weak _machine_restart(void)
+{
+	fprintf(stderr, "*** reset failed ***\n");
+
+	while (1)
+		/* NOP */;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	_machine_restart();
+
+	return 0;
+}
+
+void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
+{
+	write_c0_entrylo0(low0);
+	write_c0_pagemask(pagemask);
+	write_c0_entrylo1(low1);
+	write_c0_entryhi(hi);
+	write_c0_index(index);
+	tlb_write_indexed();
+}
diff --git a/arch/mips/cpu/mips32/interrupts.c b/arch/mips/cpu/interrupts.c
similarity index 100%
rename from arch/mips/cpu/mips32/interrupts.c
rename to arch/mips/cpu/interrupts.c
diff --git a/arch/mips/cpu/mips32/Makefile b/arch/mips/cpu/mips32/Makefile
deleted file mode 100644
index fa82dd3..0000000
--- a/arch/mips/cpu/mips32/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# (C) Copyright 2003-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-extra-y	= start.o
-obj-y	= cache.o
-obj-y	+= cpu.o interrupts.o time.o
-
-obj-$(CONFIG_SOC_AU1X00) += au1x00/
diff --git a/arch/mips/cpu/mips32/cache.S b/arch/mips/cpu/mips32/cache.S
deleted file mode 100644
index 22bd844..0000000
--- a/arch/mips/cpu/mips32/cache.S
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- *  Cache-handling routined for MIPS CPUs
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/cacheops.h>
-
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE
-#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
-#endif
-
-#define RA		t9
-
-#define INDEX_BASE	CKSEG0
-
-	.macro	cache_op op addr
-	.set	push
-	.set	noreorder
-	.set	mips3
-	cache	\op, 0(\addr)
-	.set	pop
-	.endm
-
-	.macro	f_fill64 dst, offset, val
-	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
-#if LONGSIZE == 4
-	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
-#endif
-	.endm
-
-/*
- * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
- */
-LEAF(mips_init_icache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear tag to invalidate */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* fill once, so data field parity is correct */
-	PTR_LI		t0, INDEX_BASE
-2:	cache_op	FILL t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* invalidate again - prudent but not strictly neccessary */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_icache)
-
-/*
- * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
- */
-LEAF(mips_init_dcache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* load from each line (in cached space) */
-	PTR_LI		t0, INDEX_BASE
-2:	LONG_L		zero, 0(t0)
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_dcache)
-
-/*
- * mips_cache_reset - low level initialisation of the primary caches
- *
- * This routine initialises the primary caches to ensure that they have good
- * parity.  It must be called by the ROM before any cached locations are used
- * to prevent the possibility of data with bad parity being written to memory.
- *
- * To initialise the instruction cache it is essential that a source of data
- * with good parity is available. This routine will initialise an area of
- * memory starting at location zero to be used as a source of parity.
- *
- * RETURNS: N/A
- *
- */
-NESTED(mips_cache_reset, 0, ra)
-	move	RA, ra
-
-#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \
-    !defined(CONFIG_SYS_CACHELINE_SIZE)
-	/* read Config1 for use below */
-	mfc0	t5, CP0_CONFIG, 1
-#endif
-
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-	li	t7, CONFIG_SYS_CACHELINE_SIZE
-	li	t8, CONFIG_SYS_CACHELINE_SIZE
-#else
-	/* Detect I-cache line size. */
-	srl	t8, t5, MIPS_CONF1_IL_SHIFT
-	andi	t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT)
-	beqz	t8, 1f
-	li	t6, 2
-	sllv	t8, t6, t8
-
-1:	/* Detect D-cache line size. */
-	srl	t7, t5, MIPS_CONF1_DL_SHIFT
-	andi	t7, t7, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
-	beqz	t7, 1f
-	li	t6, 2
-	sllv	t7, t6, t7
-1:
-#endif
-
-#ifdef CONFIG_SYS_ICACHE_SIZE
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-#else
-	/* Detect I-cache size. */
-	srl	t6, t5, MIPS_CONF1_IS_SHIFT
-	andi	t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT)
-	li	t4, 32
-	xori	t2, t6, 0x7
-	beqz	t2, 1f
-	addi	t6, t6, 1
-	sllv	t4, t4, t6
-1:	/* At this point t4 == I-cache sets. */
-	mul	t2, t4, t8
-	srl	t6, t5, MIPS_CONF1_IA_SHIFT
-	andi	t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT)
-	addi	t6, t6, 1
-	/* At this point t6 == I-cache ways. */
-	mul	t2, t2, t6
-#endif
-
-#ifdef CONFIG_SYS_DCACHE_SIZE
-	li	t3, CONFIG_SYS_DCACHE_SIZE
-#else
-	/* Detect D-cache size. */
-	srl	t6, t5, MIPS_CONF1_DS_SHIFT
-	andi	t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
-	li	t4, 32
-	xori	t3, t6, 0x7
-	beqz	t3, 1f
-	addi	t6, t6, 1
-	sllv	t4, t4, t6
-1:	/* At this point t4 == I-cache sets. */
-	mul	t3, t4, t7
-	srl	t6, t5, MIPS_CONF1_DA_SHIFT
-	andi	t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
-	addi	t6, t6, 1
-	/* At this point t6 == I-cache ways. */
-	mul	t3, t3, t6
-#endif
-
-	/* Determine the largest L1 cache size */
-#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
-#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
-	li	v0, CONFIG_SYS_ICACHE_SIZE
-#else
-	li	v0, CONFIG_SYS_DCACHE_SIZE
-#endif
-#else
-	move	v0, t2
-	sltu	t1, t2, t3
-	movn	v0, t3, t1
-#endif
-	/*
-	 * Now clear that much memory starting from zero.
-	 */
-	PTR_LI		a0, CKSEG1
-	PTR_ADDU	a1, a0, v0
-2:	PTR_ADDIU	a0, 64
-	f_fill64	a0, -64, zero
-	bne		a0, a1, 2b
-
-	/*
-	 * The caches are probably in an indeterminate state,
-	 * so we force good parity into them by doing an
-	 * invalidate, load/fill, invalidate for each line.
-	 */
-
-	/*
-	 * Assume bottom of RAM will generate good parity for the cache.
-	 */
-
-	/*
-	 * Initialize the I-cache first,
-	 */
-	move	a1, t2
-	move	a2, t8
-	PTR_LA	v1, mips_init_icache
-	jalr	v1
-
-	/*
-	 * then initialize D-cache.
-	 */
-	move	a1, t3
-	move	a2, t7
-	PTR_LA	v1, mips_init_dcache
-	jalr	v1
-
-	jr	RA
-	END(mips_cache_reset)
-
-/*
- * dcache_status - get cache status
- *
- * RETURNS: 0 - cache disabled; 1 - cache enabled
- *
- */
-LEAF(dcache_status)
-	mfc0	t0, CP0_CONFIG
-	li	t1, CONF_CM_UNCACHED
-	andi	t0, t0, CONF_CM_CMASK
-	move	v0, zero
-	beq	t0, t1, 2f
-	li	v0, 1
-2:	jr	ra
-	END(dcache_status)
-
-/*
- * dcache_disable - disable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_disable)
-	mfc0	t0, CP0_CONFIG
-	li	t1, -8
-	and	t0, t0, t1
-	ori	t0, t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_disable)
-
-/*
- * dcache_enable - enable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_enable)
-	mfc0	t0, CP0_CONFIG
-	ori	t0, CONF_CM_CMASK
-	xori	t0, CONF_CM_CMASK
-	ori	t0, CONFIG_SYS_MIPS_CACHE_MODE
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_enable)
diff --git a/arch/mips/cpu/mips32/cpu.c b/arch/mips/cpu/mips32/cpu.c
deleted file mode 100644
index 278865b..0000000
--- a/arch/mips/cpu/mips32/cpu.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <netdev.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheops.h>
-#include <asm/reboot.h>
-
-#define cache_op(op,addr)						\
-	__asm__ __volatile__(						\
-	"	.set	push					\n"	\
-	"	.set	noreorder				\n"	\
-	"	.set	mips3\n\t				\n"	\
-	"	cache	%0, %1					\n"	\
-	"	.set	pop					\n"	\
-	:								\
-	: "i" (op), "R" (*(unsigned char *)(addr)))
-
-void __attribute__((weak)) _machine_restart(void)
-{
-}
-
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	_machine_restart();
-
-	fprintf(stderr, "*** reset failed ***\n");
-	return 0;
-}
-
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-
-static inline unsigned long icache_line_size(void)
-{
-	return CONFIG_SYS_CACHELINE_SIZE;
-}
-
-static inline unsigned long dcache_line_size(void)
-{
-	return CONFIG_SYS_CACHELINE_SIZE;
-}
-
-#else /* !CONFIG_SYS_CACHELINE_SIZE */
-
-static inline unsigned long icache_line_size(void)
-{
-	unsigned long conf1, il;
-	conf1 = read_c0_config1();
-	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
-	if (!il)
-		return 0;
-	return 2 << il;
-}
-
-static inline unsigned long dcache_line_size(void)
-{
-	unsigned long conf1, dl;
-	conf1 = read_c0_config1();
-	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
-	if (!dl)
-		return 0;
-	return 2 << dl;
-}
-
-#endif /* !CONFIG_SYS_CACHELINE_SIZE */
-
-void flush_cache(ulong start_addr, ulong size)
-{
-	unsigned long ilsize = icache_line_size();
-	unsigned long dlsize = dcache_line_size();
-	unsigned long addr, aend;
-
-	/* aend will be miscalculated when size is zero, so we return here */
-	if (size == 0)
-		return;
-
-	addr = start_addr & ~(dlsize - 1);
-	aend = (start_addr + size - 1) & ~(dlsize - 1);
-
-	if (ilsize == dlsize) {
-		/* flush I-cache & D-cache simultaneously */
-		while (1) {
-			cache_op(HIT_WRITEBACK_INV_D, addr);
-			cache_op(HIT_INVALIDATE_I, addr);
-			if (addr == aend)
-				break;
-			addr += dlsize;
-		}
-		return;
-	}
-
-	/* flush D-cache */
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += dlsize;
-	}
-
-	/* flush I-cache */
-	addr = start_addr & ~(ilsize - 1);
-	aend = (start_addr + size - 1) & ~(ilsize - 1);
-	while (1) {
-		cache_op(HIT_INVALIDATE_I, addr);
-		if (addr == aend)
-			break;
-		addr += ilsize;
-	}
-}
-
-void flush_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = dcache_line_size();
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void invalidate_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = dcache_line_size();
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_INVALIDATE_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
-{
-	write_c0_entrylo0(low0);
-	write_c0_pagemask(pagemask);
-	write_c0_entrylo1(low1);
-	write_c0_entryhi(hi);
-	write_c0_index(index);
-	tlb_write_indexed();
-}
-
-int cpu_eth_init(bd_t *bis)
-{
-#ifdef CONFIG_SOC_AU1X00
-	au1x00_enet_initialize(bis);
-#endif
-	return 0;
-}
diff --git a/arch/mips/cpu/mips64/Makefile b/arch/mips/cpu/mips64/Makefile
deleted file mode 100644
index 899c319..0000000
--- a/arch/mips/cpu/mips64/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# (C) Copyright 2003-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-extra-y	= start.o
-obj-y	= cpu.o interrupts.o time.o cache.o
diff --git a/arch/mips/cpu/mips64/cache.S b/arch/mips/cpu/mips64/cache.S
deleted file mode 100644
index 36d8688..0000000
--- a/arch/mips/cpu/mips64/cache.S
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *  Cache-handling routined for MIPS CPUs
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/cacheops.h>
-
-#define RA		t9
-
-/*
- * 16kB is the maximum size of instruction and data caches on MIPS 4K,
- * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
- *
- * Note that the above size is the maximum size of primary cache. U-Boot
- * doesn't have L2 cache support for now.
- */
-#define MIPS_MAX_CACHE_SIZE	0x10000
-
-#define INDEX_BASE	CKSEG0
-
-	.macro	cache_op op addr
-	.set	push
-	.set	noreorder
-	.set	mips3
-	cache	\op, 0(\addr)
-	.set	pop
-	.endm
-
-	.macro	f_fill64 dst, offset, val
-	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
-#if LONGSIZE == 4
-	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
-#endif
-	.endm
-
-/*
- * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
- */
-LEAF(mips_init_icache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear tag to invalidate */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* fill once, so data field parity is correct */
-	PTR_LI		t0, INDEX_BASE
-2:	cache_op	FILL t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* invalidate again - prudent but not strictly neccessary */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_icache)
-
-/*
- * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
- */
-LEAF(mips_init_dcache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* load from each line (in cached space) */
-	PTR_LI		t0, INDEX_BASE
-2:	LONG_L		zero, 0(t0)
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_dcache)
-
-/*
- * mips_cache_reset - low level initialisation of the primary caches
- *
- * This routine initialises the primary caches to ensure that they have good
- * parity.  It must be called by the ROM before any cached locations are used
- * to prevent the possibility of data with bad parity being written to memory.
- *
- * To initialise the instruction cache it is essential that a source of data
- * with good parity is available. This routine will initialise an area of
- * memory starting at location zero to be used as a source of parity.
- *
- * RETURNS: N/A
- *
- */
-NESTED(mips_cache_reset, 0, ra)
-	move	RA, ra
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-	li	t3, CONFIG_SYS_DCACHE_SIZE
-	li	t8, CONFIG_SYS_CACHELINE_SIZE
-
-	li	v0, MIPS_MAX_CACHE_SIZE
-
-	/*
-	 * Now clear that much memory starting from zero.
-	 */
-	PTR_LI		a0, CKSEG1
-	PTR_ADDU	a1, a0, v0
-2:	PTR_ADDIU	a0, 64
-	f_fill64	a0, -64, zero
-	bne		a0, a1, 2b
-
-	/*
-	 * The caches are probably in an indeterminate state,
-	 * so we force good parity into them by doing an
-	 * invalidate, load/fill, invalidate for each line.
-	 */
-
-	/*
-	 * Assume bottom of RAM will generate good parity for the cache.
-	 */
-
-	/*
-	 * Initialize the I-cache first,
-	 */
-	move	a1, t2
-	move	a2, t8
-	PTR_LA	v1, mips_init_icache
-	jalr	v1
-
-	/*
-	 * then initialize D-cache.
-	 */
-	move	a1, t3
-	move	a2, t8
-	PTR_LA	v1, mips_init_dcache
-	jalr	v1
-
-	jr	RA
-	END(mips_cache_reset)
-
-/*
- * dcache_status - get cache status
- *
- * RETURNS: 0 - cache disabled; 1 - cache enabled
- *
- */
-LEAF(dcache_status)
-	mfc0	t0, CP0_CONFIG
-	li	t1, CONF_CM_UNCACHED
-	andi	t0, t0, CONF_CM_CMASK
-	move	v0, zero
-	beq	t0, t1, 2f
-	li	v0, 1
-2:	jr	ra
-	END(dcache_status)
-
-/*
- * dcache_disable - disable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_disable)
-	mfc0	t0, CP0_CONFIG
-	li	t1, -8
-	and	t0, t0, t1
-	ori	t0, t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_disable)
-
-/*
- * dcache_enable - enable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_enable)
-	mfc0	t0, CP0_CONFIG
-	ori	t0, CONF_CM_CMASK
-	xori	t0, CONF_CM_CMASK
-	ori	t0, CONF_CM_CACHABLE_NONCOHERENT
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_enable)
diff --git a/arch/mips/cpu/mips64/cpu.c b/arch/mips/cpu/mips64/cpu.c
deleted file mode 100644
index 9f45cfc..0000000
--- a/arch/mips/cpu/mips64/cpu.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <netdev.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheops.h>
-#include <asm/reboot.h>
-
-#define cache_op(op, addr)						\
-	__asm__ __volatile__(						\
-	"	.set	push\n"						\
-	"	.set	noreorder\n"					\
-	"	.set	mips64\n"					\
-	"	cache	%0, %1\n"					\
-	"	.set	pop\n"						\
-	:								\
-	: "i" (op), "R" (*(unsigned char *)(addr)))
-
-void __attribute__((weak)) _machine_restart(void)
-{
-	fprintf(stderr, "*** reset failed ***\n");
-
-	while (1)
-		/* NOP */;
-}
-
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	_machine_restart();
-
-	return 0;
-}
-
-void flush_cache(ulong start_addr, ulong size)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
-
-	/* aend will be miscalculated when size is zero, so we return here */
-	if (size == 0)
-		return;
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		cache_op(HIT_INVALIDATE_I, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void flush_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void invalidate_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_INVALIDATE_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
-{
-	write_c0_entrylo0(low0);
-	write_c0_pagemask(pagemask);
-	write_c0_entrylo1(low1);
-	write_c0_entryhi(hi);
-	write_c0_index(index);
-	tlb_write_indexed();
-}
diff --git a/arch/mips/cpu/mips64/interrupts.c b/arch/mips/cpu/mips64/interrupts.c
deleted file mode 100644
index 275fcf5..0000000
--- a/arch/mips/cpu/mips64/interrupts.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-
-int interrupt_init(void)
-{
-	return 0;
-}
-
-void enable_interrupts(void)
-{
-}
-
-int disable_interrupts(void)
-{
-	return 0;
-}
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S
deleted file mode 100644
index 471bc1e..0000000
--- a/arch/mips/cpu/mips64/start.S
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- *  Startup Code for MIPS64 CPU-core
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE
-#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
-#endif
-
-#ifndef CONFIG_SYS_INIT_SP_ADDR
-#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
-				CONFIG_SYS_INIT_SP_OFFSET)
-#endif
-
-#ifdef CONFIG_SYS_LITTLE_ENDIAN
-#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
-	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
-#else
-#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
-	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
-#endif
-
-	/*
-	 * For the moment disable interrupts, mark the kernel mode and
-	 * set ST0_KX so that the CPU does not spit fire when using
-	 * 64-bit addresses.
-	 */
-	.macro	setup_c0_status set clr
-	.set	push
-	mfc0	t0, CP0_STATUS
-	or	t0, ST0_CU0 | \set | 0x1f | \clr
-	xor	t0, 0x1f | \clr
-	mtc0	t0, CP0_STATUS
-	.set	noreorder
-	sll	zero, 3				# ehb
-	.set	pop
-	.endm
-
-	.set noreorder
-
-	.globl _start
-	.text
-_start:
-	/* U-boot entry point */
-	b	reset
-	 nop
-
-	.org 0x200
-	/* TLB refill, 32 bit task */
-1:	b	1b
-	 nop
-
-	.org 0x280
-	/* XTLB refill, 64 bit task */
-1:	b	1b
-	 nop
-
-	.org 0x300
-	/* Cache error exception */
-1:	b	1b
-	 nop
-
-	.org 0x380
-	/* General exception */
-1:	b	1b
-	 nop
-
-	.org 0x400
-	/* Catch interrupt exceptions */
-1:	b	1b
-	 nop
-
-	.org 0x480
-	/* EJTAG debug exception */
-1:	b	1b
-	 nop
-
-	.align 4
-reset:
-
-	/* Clear watch registers */
-	dmtc0	zero, CP0_WATCHLO
-	dmtc0	zero, CP0_WATCHHI
-
-	/* WP(Watch Pending), SW0/1 should be cleared */
-	mtc0	zero, CP0_CAUSE
-
-	setup_c0_status ST0_KX 0
-
-	/* Init Timer */
-	mtc0	zero, CP0_COUNT
-	mtc0	zero, CP0_COMPARE
-
-#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	/* CONFIG0 register */
-	dli	t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-#endif
-
-	/*
-	 * Initialize $gp, force 8 byte alignment of bal instruction to forbid
-	 * the compiler to put nop's between bal and _gp. This is required to
-	 * keep _gp and ra aligned to 8 byte.
-	 */
-	.align	3
-	bal	1f
-	 nop
-	.dword	_gp
-1:
-	ld	gp, 0(ra)
-
-#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	/* Initialize any external memory */
-	dla	t9, lowlevel_init
-	jalr	t9
-	 nop
-
-	/* Initialize caches... */
-	dla	t9, mips_cache_reset
-	jalr	t9
-	 nop
-
-	/* ... and enable them */
-	dli	t0, CONFIG_SYS_MIPS_CACHE_MODE
-	mtc0	t0, CP0_CONFIG
-#endif
-
-	/* Set up temporary stack */
-	dli	t0, -16
-	dli	t1, CONFIG_SYS_INIT_SP_ADDR
-	and	sp, t1, t0		# force 16 byte alignment
-	dsub	sp, sp, GD_SIZE		# reserve space for gd
-	and	sp, sp, t0		# force 16 byte alignment
-	move	k0, sp			# save gd pointer
-#ifdef CONFIG_SYS_MALLOC_F_LEN
-	dli	t2, CONFIG_SYS_MALLOC_F_LEN
-	dsub	sp, sp, t2		# reserve space for early malloc
-	and	sp, sp, t0		# force 16 byte alignment
-#endif
-	move	fp, sp
-
-	/* Clear gd */
-	move	t0, k0
-1:
-	sw	zero, 0(t0)
-	blt	t0, t1, 1b
-	 daddi	t0, 4
-
-#ifdef CONFIG_SYS_MALLOC_F_LEN
-	daddu	t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
-	sw	sp, 0(t0)
-#endif
-
-	dla	t9, board_init_f
-	jr	t9
-	 move	ra, zero
-
-/*
- * void relocate_code (addr_sp, gd, addr_moni)
- *
- * This "function" does not return, instead it continues in RAM
- * after relocating the monitor code.
- *
- * a0 = addr_sp
- * a1 = gd
- * a2 = destination address
- */
-	.globl	relocate_code
-	.ent	relocate_code
-relocate_code:
-	move	sp, a0			# set new stack pointer
-	move	fp, sp
-
-	move	s0, a1			# save gd in s0
-	move	s2, a2			# save destination address in s2
-
-	dli	t0, CONFIG_SYS_MONITOR_BASE
-	dsub	s1, s2, t0		# s1 <-- relocation offset
-
-	dla	t3, in_ram
-	ld	t2, -24(t3)		# t2 <-- __image_copy_end
-	move	t1, a2
-
-	dadd	gp, s1			# adjust gp
-
-	/*
-	 * t0 = source address
-	 * t1 = target address
-	 * t2 = source end address
-	 */
-1:
-	lw	t3, 0(t0)
-	sw	t3, 0(t1)
-	daddu	t0, 4
-	blt	t0, t2, 1b
-	 daddu	t1, 4
-
-	/* If caches were enabled, we would have to flush them here. */
-	dsub	a1, t1, s2		# a1 <-- size
-	dla	t9, flush_cache
-	jalr	t9
-	 move	a0, s2			# a0 <-- destination address
-
-	/* Jump to where we've relocated ourselves */
-	daddi	t0, s2, in_ram - _start
-	jr	t0
-	 nop
-
-	.dword	__rel_dyn_end
-	.dword	__rel_dyn_start
-	.dword	__image_copy_end
-	.dword	_GLOBAL_OFFSET_TABLE_
-	.dword	num_got_entries
-
-in_ram:
-	/*
-	 * Now we want to update GOT.
-	 *
-	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
-	 * generated by GNU ld. Skip these reserved entries from relocation.
-	 */
-	ld	t3, -8(t0)		# t3 <-- num_got_entries
-	ld	t8, -16(t0)		# t8 <-- _GLOBAL_OFFSET_TABLE_
-	dadd	t8, s1			# t8 now holds relocated _G_O_T_
-	daddi	t8, t8, 16		# skipping first two entries
-	dli	t2, 2
-1:
-	ld	t1, 0(t8)
-	beqz	t1, 2f
-	 dadd	t1, s1
-	sd	t1, 0(t8)
-2:
-	daddi	t2, 1
-	blt	t2, t3, 1b
-	 daddi	t8, 8
-
-	/* Update dynamic relocations */
-	ld	t1, -32(t0)		# t1 <-- __rel_dyn_start
-	ld	t2, -40(t0)		# t2 <-- __rel_dyn_end
-
-	b	2f			# skip first reserved entry
-	 daddi	t1, 16
-
-1:
-	lw	t8, -4(t1)		# t8 <-- relocation info
-
-	dli	t3, MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
-	bne	t8, t3, 2f		# skip non R_MIPS_REL32 entries
-	 nop
-
-	ld	t3, -16(t1)		# t3 <-- location to fix up in FLASH
-
-	ld	t8, 0(t3)		# t8 <-- original pointer
-	dadd	t8, s1			# t8 <-- adjusted pointer
-
-	dadd	t3, s1			# t3 <-- location to fix up in RAM
-	sd	t8, 0(t3)
-
-2:
-	blt	t1, t2, 1b
-	 daddi	t1, 16			# each rel.dyn entry is 16 bytes
-
-	/*
-	 * Clear BSS
-	 *
-	 * GOT is now relocated. Thus __bss_start and __bss_end can be
-	 * accessed directly via $gp.
-	 */
-	dla	t1, __bss_start		# t1 <-- __bss_start
-	dla	t2, __bss_end		# t2 <-- __bss_end
-
-1:
-	sd	zero, 0(t1)
-	blt	t1, t2, 1b
-	 daddi	t1, 8
-
-	move	a0, s0			# a0 <-- gd
-	move	a1, s2
-	dla	t9, board_init_r
-	jr	t9
-	 move	ra, zero
-
-	.end	relocate_code
diff --git a/arch/mips/cpu/mips64/time.c b/arch/mips/cpu/mips64/time.c
deleted file mode 100644
index 553da5f..0000000
--- a/arch/mips/cpu/mips64/time.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/mipsregs.h>
-
-unsigned long notrace timer_read_counter(void)
-{
-	return read_c0_count();
-}
-
-ulong notrace get_tbclk(void)
-{
-	return CONFIG_SYS_MIPS_TIMER_FREQ;
-}
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/start.S
similarity index 61%
rename from arch/mips/cpu/mips32/start.S
rename to arch/mips/cpu/start.S
index 36b92cc..3b5b622 100644
--- a/arch/mips/cpu/mips32/start.S
+++ b/arch/mips/cpu/start.S
@@ -8,6 +8,7 @@
 
 #include <asm-offsets.h>
 #include <config.h>
+#include <asm/asm.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 
@@ -20,6 +21,23 @@
 				CONFIG_SYS_INIT_SP_OFFSET)
 #endif
 
+#ifdef CONFIG_32BIT
+# define MIPS_RELOC	3
+# define STATUS_SET	0
+#endif
+
+#ifdef CONFIG_64BIT
+# ifdef CONFIG_SYS_LITTLE_ENDIAN
+#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
+	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
+# else
+#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
+	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
+# endif
+# define MIPS_RELOC	MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
+# define STATUS_SET	ST0_KX
+#endif
+
 	/*
 	 * For the moment disable interrupts, mark the kernel mode and
 	 * set ST0_KX so that the CPU does not spit fire when using
@@ -98,13 +116,13 @@
 reset:
 
 	/* Clear watch registers */
-	mtc0	zero, CP0_WATCHLO
-	mtc0	zero, CP0_WATCHHI
+	MTC0	zero, CP0_WATCHLO
+	MTC0	zero, CP0_WATCHHI
 
 	/* WP(Watch Pending), SW0/1 should be cleared */
 	mtc0	zero, CP0_CAUSE
 
-	setup_c0_status 0 0
+	setup_c0_status STATUS_SET 0
 
 	/* Init Timer */
 	mtc0	zero, CP0_COUNT
@@ -116,21 +134,26 @@
 	mtc0	t0, CP0_CONFIG
 #endif
 
-	/* Initialize $gp */
+	/*
+	 * Initialize $gp, force pointer sized alignment of bal instruction to
+	 * forbid the compiler to put nop's between bal and _gp. This is
+	 * required to keep _gp and ra aligned to 8 byte.
+	 */
+	.align	PTRLOG
 	bal	1f
 	 nop
-	.word	_gp
+	PTR	_gp
 1:
-	lw	gp, 0(ra)
+	PTR_L	gp, 0(ra)
 
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
 	/* Initialize any external memory */
-	la	t9, lowlevel_init
+	PTR_LA	t9, lowlevel_init
 	jalr	t9
 	 nop
 
 	/* Initialize caches... */
-	la	t9, mips_cache_reset
+	PTR_LA	t9, mips_cache_reset
 	jalr	t9
 	 nop
 
@@ -140,15 +163,15 @@
 #endif
 
 	/* Set up temporary stack */
-	li	t0, -16
-	li	t1, CONFIG_SYS_INIT_SP_ADDR
+	PTR_LI	t0, -16
+	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
 	and	sp, t1, t0		# force 16 byte alignment
-	sub	sp, sp, GD_SIZE		# reserve space for gd
+	PTR_SUB	sp, sp, GD_SIZE		# reserve space for gd
 	and	sp, sp, t0		# force 16 byte alignment
 	move	k0, sp			# save gd pointer
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	li	t2, CONFIG_SYS_MALLOC_F_LEN
-	sub	sp, sp, t2		# reserve space for early malloc
+	PTR_LI	t2, CONFIG_SYS_MALLOC_F_LEN
+	PTR_SUB	sp, sp, t2		# reserve space for early malloc
 	and	sp, sp, t0		# force 16 byte alignment
 #endif
 	move	fp, sp
@@ -158,14 +181,14 @@
 1:
 	sw	zero, 0(t0)
 	blt	t0, t1, 1b
-	 addi	t0, 4
+	 PTR_ADDI t0, 4
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	addu	t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
+	PTR_ADDU t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
 	sw	sp, 0(t0)
 #endif
 
-	la	t9, board_init_f
+	PTR_LA	t9, board_init_f
 	jr	t9
 	 move	ra, zero
 
@@ -188,14 +211,14 @@
 	move	s0, a1			# save gd in s0
 	move	s2, a2			# save destination address in s2
 
-	li	t0, CONFIG_SYS_MONITOR_BASE
-	sub	s1, s2, t0		# s1 <-- relocation offset
+	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
+	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
 
-	la	t3, in_ram
-	lw	t2, -12(t3)		# t2 <-- __image_copy_end
+	PTR_LA	t3, in_ram
+	PTR_L	t2, -(3 * PTRSIZE)(t3)	# t2 <-- __image_copy_end
 	move	t1, a2
 
-	add	gp, s1			# adjust gp
+	PTR_ADD	gp, s1			# adjust gp
 
 	/*
 	 * t0 = source address
@@ -205,26 +228,26 @@
 1:
 	lw	t3, 0(t0)
 	sw	t3, 0(t1)
-	addu	t0, 4
+	PTR_ADDU t0, 4
 	blt	t0, t2, 1b
-	 addu	t1, 4
+	 PTR_ADDU t1, 4
 
 	/* If caches were enabled, we would have to flush them here. */
-	sub	a1, t1, s2		# a1 <-- size
-	la	t9, flush_cache
+	PTR_SUB	a1, t1, s2		# a1 <-- size
+	PTR_LA	t9, flush_cache
 	jalr	t9
 	 move	a0, s2			# a0 <-- destination address
 
 	/* Jump to where we've relocated ourselves */
-	addi	t0, s2, in_ram - _start
+	PTR_ADDI t0, s2, in_ram - _start
 	jr	t0
 	 nop
 
-	.word	__rel_dyn_end
-	.word	__rel_dyn_start
-	.word	__image_copy_end
-	.word	_GLOBAL_OFFSET_TABLE_
-	.word	num_got_entries
+	PTR	__rel_dyn_end
+	PTR	__rel_dyn_start
+	PTR	__image_copy_end
+	PTR	_GLOBAL_OFFSET_TABLE_
+	PTR	num_got_entries
 
 in_ram:
 	/*
@@ -233,46 +256,46 @@
 	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
 	 * generated by GNU ld. Skip these reserved entries from relocation.
 	 */
-	lw	t3, -4(t0)		# t3 <-- num_got_entries
-	lw	t8, -8(t0)		# t8 <-- _GLOBAL_OFFSET_TABLE_
-	add	t8, s1			# t8 now holds relocated _G_O_T_
-	addi	t8, t8, 8		# skipping first two entries
-	li	t2, 2
+	PTR_L	t3, -(1 * PTRSIZE)(t0)	# t3 <-- num_got_entries
+	PTR_L	t8, -(2 * PTRSIZE)(t0)	# t8 <-- _GLOBAL_OFFSET_TABLE_
+	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
+	PTR_ADDI t8, t8, 2 * PTRSIZE	# skipping first two entries
+	PTR_LI	t2, 2
 1:
-	lw	t1, 0(t8)
+	PTR_L	t1, 0(t8)
 	beqz	t1, 2f
-	 add	t1, s1
-	sw	t1, 0(t8)
+	 PTR_ADD t1, s1
+	PTR_S	t1, 0(t8)
 2:
-	addi	t2, 1
+	PTR_ADDI t2, 1
 	blt	t2, t3, 1b
-	 addi	t8, 4
+	 PTR_ADDI t8, PTRSIZE
 
 	/* Update dynamic relocations */
-	lw	t1, -16(t0)		# t1 <-- __rel_dyn_start
-	lw	t2, -20(t0)		# t2 <-- __rel_dyn_end
+	PTR_L	t1, -(4 * PTRSIZE)(t0)	# t1 <-- __rel_dyn_start
+	PTR_L	t2, -(5 * PTRSIZE)(t0)	# t2 <-- __rel_dyn_end
 
 	b	2f			# skip first reserved entry
-	 addi	t1, 8
+	 PTR_ADDI t1, 2 * PTRSIZE
 
 1:
 	lw	t8, -4(t1)		# t8 <-- relocation info
 
-	li	t3, 3
-	bne	t8, t3, 2f		# skip non R_MIPS_REL32 entries
+	PTR_LI	t3, MIPS_RELOC
+	bne	t8, t3, 2f		# skip non-MIPS_RELOC entries
 	 nop
 
-	lw	t3, -8(t1)		# t3 <-- location to fix up in FLASH
+	PTR_L	t3, -(2 * PTRSIZE)(t1)	# t3 <-- location to fix up in FLASH
 
-	lw	t8, 0(t3)		# t8 <-- original pointer
-	add	t8, s1			# t8 <-- adjusted pointer
+	PTR_L	t8, 0(t3)		# t8 <-- original pointer
+	PTR_ADD	t8, s1			# t8 <-- adjusted pointer
 
-	add	t3, s1			# t3 <-- location to fix up in RAM
-	sw	t8, 0(t3)
+	PTR_ADD	t3, s1			# t3 <-- location to fix up in RAM
+	PTR_S	t8, 0(t3)
 
 2:
 	blt	t1, t2, 1b
-	 addi	t1, 8			# each rel.dyn entry is 8 bytes
+	 PTR_ADDI t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
 
 	/*
 	 * Clear BSS
@@ -280,17 +303,17 @@
 	 * GOT is now relocated. Thus __bss_start and __bss_end can be
 	 * accessed directly via $gp.
 	 */
-	la	t1, __bss_start		# t1 <-- __bss_start
-	la	t2, __bss_end		# t2 <-- __bss_end
+	PTR_LA	t1, __bss_start		# t1 <-- __bss_start
+	PTR_LA	t2, __bss_end		# t2 <-- __bss_end
 
 1:
-	sw	zero, 0(t1)
+	PTR_S	zero, 0(t1)
 	blt	t1, t2, 1b
-	 addi	t1, 4
+	 PTR_ADDI t1, PTRSIZE
 
 	move	a0, s0			# a0 <-- gd
 	move	a1, s2
-	la	t9, board_init_r
+	PTR_LA	t9, board_init_r
 	jr	t9
 	 move	ra, zero
 
diff --git a/arch/mips/cpu/mips32/time.c b/arch/mips/cpu/time.c
similarity index 100%
rename from arch/mips/cpu/mips32/time.c
rename to arch/mips/cpu/time.c
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 6464250..75ec380 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -11,6 +11,19 @@
 #ifndef	__ASM_CACHEOPS_H
 #define	__ASM_CACHEOPS_H
 
+#ifndef __ASSEMBLY__
+
+static inline void mips_cache(int op, const volatile void *addr)
+{
+#ifdef __GCC_HAVE_BUILTIN_MIPS_CACHE
+	__builtin_mips_cache(op, addr);
+#else
+	__asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr))
+#endif
+}
+
+#endif /* !__ASSEMBLY__ */
+
 /*
  * Cache Operations available on all MIPS processors with R4000-style caches
  */
diff --git a/arch/mips/include/asm/malta.h b/arch/mips/include/asm/malta.h
index 9e7c045..d9ffc15 100644
--- a/arch/mips/include/asm/malta.h
+++ b/arch/mips/include/asm/malta.h
@@ -64,4 +64,9 @@
 
 #define PCI_CFG_PIIX4_GENCFG_SERIRQ	(1 << 16)
 
+#define PCI_CFG_PIIX4_IDETIM_PRI	0x40
+#define PCI_CFG_PIIX4_IDETIM_SEC	0x42
+
+#define PCI_CFG_PIIX4_IDETIM_IDE	(1 << 15)
+
 #endif /* _MIPS_ASM_MALTA_H */
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 7f9b653..ac536da 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-y	+= cache.o
+obj-y	+= cache_init.o
 obj-y	+= io.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c
new file mode 100644
index 0000000..e245614
--- /dev/null
+++ b/arch/mips/lib/cache.c
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+
+static inline unsigned long icache_line_size(void)
+{
+	return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+	return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+#else /* !CONFIG_SYS_CACHELINE_SIZE */
+
+static inline unsigned long icache_line_size(void)
+{
+	unsigned long conf1, il;
+	conf1 = read_c0_config1();
+	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
+	if (!il)
+		return 0;
+	return 2 << il;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+	unsigned long conf1, dl;
+	conf1 = read_c0_config1();
+	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
+	if (!dl)
+		return 0;
+	return 2 << dl;
+}
+
+#endif /* !CONFIG_SYS_CACHELINE_SIZE */
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	unsigned long ilsize = icache_line_size();
+	unsigned long dlsize = dcache_line_size();
+	const void *addr, *aend;
+
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (size == 0)
+		return;
+
+	addr = (const void *)(start_addr & ~(dlsize - 1));
+	aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
+
+	if (ilsize == dlsize) {
+		/* flush I-cache & D-cache simultaneously */
+		while (1) {
+			mips_cache(HIT_WRITEBACK_INV_D, addr);
+			mips_cache(HIT_INVALIDATE_I, addr);
+			if (addr == aend)
+				break;
+			addr += dlsize;
+		}
+		return;
+	}
+
+	/* flush D-cache */
+	while (1) {
+		mips_cache(HIT_WRITEBACK_INV_D, addr);
+		if (addr == aend)
+			break;
+		addr += dlsize;
+	}
+
+	/* flush I-cache */
+	addr = (const void *)(start_addr & ~(ilsize - 1));
+	aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
+	while (1) {
+		mips_cache(HIT_INVALIDATE_I, addr);
+		if (addr == aend)
+			break;
+		addr += ilsize;
+	}
+}
+
+void flush_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = dcache_line_size();
+	const void *addr = (const void *)(start_addr & ~(lsize - 1));
+	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
+
+	while (1) {
+		mips_cache(HIT_WRITEBACK_INV_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
+
+void invalidate_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = dcache_line_size();
+	const void *addr = (const void *)(start_addr & ~(lsize - 1));
+	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
+
+	while (1) {
+		mips_cache(HIT_INVALIDATE_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S
new file mode 100644
index 0000000..137d728
--- /dev/null
+++ b/arch/mips/lib/cache_init.S
@@ -0,0 +1,241 @@
+/*
+ *  Cache-handling routined for MIPS CPUs
+ *
+ *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+#ifndef CONFIG_SYS_MIPS_CACHE_MODE
+#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
+#endif
+
+#define INDEX_BASE	CKSEG0
+
+	.macro	f_fill64 dst, offset, val
+	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
+#if LONGSIZE == 4
+	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
+#endif
+	.endm
+
+	.macro cache_loop	curr, end, line_sz, op
+10:	cache		\op, 0(\curr)
+	PTR_ADDU	\curr, \curr, \line_sz
+	bne		\curr, \end, 10b
+	.endm
+
+	.macro	l1_info		sz, line_sz, off
+	.set	push
+	.set	noat
+
+	mfc0	$1, CP0_CONFIG, 1
+
+	/* detect line size */
+	srl	\line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	\line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
+	move	\sz, zero
+	beqz	\line_sz, 10f
+	li	\sz, 2
+	sllv	\line_sz, \sz, \line_sz
+
+	/* detect associativity */
+	srl	\sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	\sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
+	addi	\sz, \sz, 1
+
+	/* sz *= line_sz */
+	mul	\sz, \sz, \line_sz
+
+	/* detect log32(sets) */
+	srl	$1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	$1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
+	addiu	$1, $1, 1
+	andi	$1, $1, 0x7
+
+	/* sz <<= log32(sets) */
+	sllv	\sz, \sz, $1
+
+	/* sz *= 32 */
+	li	$1, 32
+	mul	\sz, \sz, $1
+10:
+	.set	pop
+	.endm
+/*
+ * mips_cache_reset - low level initialisation of the primary caches
+ *
+ * This routine initialises the primary caches to ensure that they have good
+ * parity.  It must be called by the ROM before any cached locations are used
+ * to prevent the possibility of data with bad parity being written to memory.
+ *
+ * To initialise the instruction cache it is essential that a source of data
+ * with good parity is available. This routine will initialise an area of
+ * memory starting at location zero to be used as a source of parity.
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(mips_cache_reset)
+#ifdef CONFIG_SYS_ICACHE_SIZE
+	li	t2, CONFIG_SYS_ICACHE_SIZE
+	li	t8, CONFIG_SYS_CACHELINE_SIZE
+#else
+	l1_info	t2, t8, MIPS_CONF1_IA_SHIFT
+#endif
+
+#ifdef CONFIG_SYS_DCACHE_SIZE
+	li	t3, CONFIG_SYS_DCACHE_SIZE
+	li	t9, CONFIG_SYS_CACHELINE_SIZE
+#else
+	l1_info	t3, t9, MIPS_CONF1_DA_SHIFT
+#endif
+
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+
+	/* Determine the largest L1 cache size */
+#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
+#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
+	li	v0, CONFIG_SYS_ICACHE_SIZE
+#else
+	li	v0, CONFIG_SYS_DCACHE_SIZE
+#endif
+#else
+	move	v0, t2
+	sltu	t1, t2, t3
+	movn	v0, t3, t1
+#endif
+	/*
+	 * Now clear that much memory starting from zero.
+	 */
+	PTR_LI		a0, CKSEG1
+	PTR_ADDU	a1, a0, v0
+2:	PTR_ADDIU	a0, 64
+	f_fill64	a0, -64, zero
+	bne		a0, a1, 2b
+
+#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
+
+	/*
+	 * The TagLo registers used depend upon the CPU implementation, but the
+	 * architecture requires that it is safe for software to write to both
+	 * TagLo selects 0 & 2 covering supported cases.
+	 */
+	mtc0		zero, CP0_TAGLO
+	mtc0		zero, CP0_TAGLO, 2
+
+	/*
+	 * The caches are probably in an indeterminate state, so we force good
+	 * parity into them by doing an invalidate for each line. If
+	 * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to
+	 * perform a load/fill & a further invalidate for each line, assuming
+	 * that the bottom of RAM (having just been cleared) will generate good
+	 * parity for the cache.
+	 */
+
+	/*
+	 * Initialize the I-cache first,
+	 */
+	blez		t2, 1f
+	PTR_LI		t0, INDEX_BASE
+	PTR_ADDU	t1, t0, t2
+	/* clear tag to invalidate */
+	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+	/* fill once, so data field parity is correct */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t8, FILL
+	/* invalidate again - prudent but not strictly neccessary */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+#endif
+
+	/*
+	 * then initialize D-cache.
+	 */
+1:	blez		t3, 3f
+	PTR_LI		t0, INDEX_BASE
+	PTR_ADDU	t1, t0, t3
+	/* clear all tags */
+	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+	/* load from each line (in cached space) */
+	PTR_LI		t0, INDEX_BASE
+2:	LONG_L		zero, 0(t0)
+	PTR_ADDU	t0, t9
+	bne		t0, t1, 2b
+	/* clear all tags */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+#endif
+
+3:	jr	ra
+	END(mips_cache_reset)
+
+/*
+ * dcache_status - get cache status
+ *
+ * RETURNS: 0 - cache disabled; 1 - cache enabled
+ *
+ */
+LEAF(dcache_status)
+	mfc0	t0, CP0_CONFIG
+	li	t1, CONF_CM_UNCACHED
+	andi	t0, t0, CONF_CM_CMASK
+	move	v0, zero
+	beq	t0, t1, 2f
+	li	v0, 1
+2:	jr	ra
+	END(dcache_status)
+
+/*
+ * dcache_disable - disable cache
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(dcache_disable)
+	mfc0	t0, CP0_CONFIG
+	li	t1, -8
+	and	t0, t0, t1
+	ori	t0, t0, CONF_CM_UNCACHED
+	mtc0	t0, CP0_CONFIG
+	jr	ra
+	END(dcache_disable)
+
+/*
+ * dcache_enable - enable cache
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(dcache_enable)
+	mfc0	t0, CP0_CONFIG
+	ori	t0, CONF_CM_CMASK
+	xori	t0, CONF_CM_CMASK
+	ori	t0, CONFIG_SYS_MIPS_CACHE_MODE
+	mtc0	t0, CP0_CONFIG
+	jr	ra
+	END(dcache_enable)
diff --git a/arch/mips/cpu/mips32/au1x00/Makefile b/arch/mips/mach-au1x00/Makefile
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/Makefile
rename to arch/mips/mach-au1x00/Makefile
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
similarity index 98%
rename from arch/mips/cpu/mips32/au1x00/au1x00_eth.c
rename to arch/mips/mach-au1x00/au1x00_eth.c
index 4770f56..39c5b6b 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -294,3 +294,9 @@
 
 	return 1;
 }
+
+int cpu_eth_init(bd_t *bis)
+{
+	au1x00_enet_initialize(bis);
+	return 0;
+}
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_ide.c b/arch/mips/mach-au1x00/au1x00_ide.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_ide.c
rename to arch/mips/mach-au1x00/au1x00_ide.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_serial.c b/arch/mips/mach-au1x00/au1x00_serial.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_serial.c
rename to arch/mips/mach-au1x00/au1x00_serial.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c b/arch/mips/mach-au1x00/au1x00_usb_ohci.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c
rename to arch/mips/mach-au1x00/au1x00_usb_ohci.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.h b/arch/mips/mach-au1x00/au1x00_usb_ohci.h
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.h
rename to arch/mips/mach-au1x00/au1x00_usb_ohci.h
diff --git a/arch/mips/cpu/mips32/au1x00/config.mk b/arch/mips/mach-au1x00/config.mk
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/config.mk
rename to arch/mips/mach-au1x00/config.mk
diff --git a/arch/nds32/include/asm/u-boot-nds32.h b/arch/nds32/include/asm/u-boot-nds32.h
index b079086..dee5f43 100644
--- a/arch/nds32/include/asm/u-boot-nds32.h
+++ b/arch/nds32/include/asm/u-boot-nds32.h
@@ -22,7 +22,6 @@
 
 /* board/.../... */
 int	board_init(void);
-int	dram_init(void);
 
 /* cpu/.../interrupt.c */
 void	reset_timer_masked(void);
diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
index 71bb9d7..7202c3f 100644
--- a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
@@ -424,6 +424,14 @@
 	int write_recovery;
 	phys_size_t dram_size = 0;
 
+	if (IS_ENABLED(CONFIG_SYS_RAMBOOT)) {
+		/*
+		 * Reduce RAM size to avoid overwriting memory used by
+		 * current stack? Not sure what is happening.
+		 */
+		return sdram_memsize() / 2;
+	}
+
 	num_dimm_banks = sizeof(iic0_dimm_addr);
 
 	/*------------------------------------------------------------------
diff --git a/arch/powerpc/cpu/ppc4xx/config.mk b/arch/powerpc/cpu/ppc4xx/config.mk
index f87c9dc..9cb41bb 100644
--- a/arch/powerpc/cpu/ppc4xx/config.mk
+++ b/arch/powerpc/cpu/ppc4xx/config.mk
@@ -7,10 +7,7 @@
 
 PLATFORM_CPPFLAGS += -mstring -msoft-float
 
-cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h
-is440:=$(shell grep CONFIG_440 $(cfg))
-
-ifneq (,$(findstring CONFIG_440,$(is440)))
+ifneq (,$(CONFIG_440))
 PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440
 else
 PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c
index e5a0e21..5f5c720 100644
--- a/arch/powerpc/cpu/ppc4xx/cpu_init.c
+++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c
@@ -450,10 +450,12 @@
 	      PLB4Ax_ACR_RDP_4DEEP);
 #endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
 
+#ifndef CONFIG_SYS_GENERIC_BOARD
 	gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
 
 	/* Clear initial global data */
 	memset((void *)gd, 0, sizeof(gd_t));
+#endif
 }
 
 /*
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
index 09a02d7..7a0f0d2 100644
--- a/arch/powerpc/cpu/ppc4xx/start.S
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -760,6 +760,15 @@
 #endif
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
+#ifdef CONFIG_SYS_GENERIC_BOARD
+	mr	r3, r1
+	bl	board_init_f_mem
+	mr	r1, r3
+	li	r0,0
+	stwu	r0, -4(r1)
+	stwu	r0, -4(r1)
+#endif
+	li	r3, 0
 	bl	board_init_f
 	/* NOTREACHED - board_init_f() does not return */
 
@@ -1027,7 +1036,14 @@
 	GET_GOT			/* initialize GOT access			*/
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
-
+#ifdef CONFIG_SYS_GENERIC_BOARD
+	mr	r3, r1
+	bl	board_init_f_mem
+	mr	r1, r3
+	stwu	r0, -4(r1)
+	stwu	r0, -4(r1)
+#endif
+	li	r3, 0
 	bl	board_init_f	/* run first part of init code (from Flash)	*/
 	/* NOTREACHED - board_init_f() does not return */
 
diff --git a/arch/powerpc/cpu/ppc4xx/u-boot.lds b/arch/powerpc/cpu/ppc4xx/u-boot.lds
index 8773178..1980508 100644
--- a/arch/powerpc/cpu/ppc4xx/u-boot.lds
+++ b/arch/powerpc/cpu/ppc4xx/u-boot.lds
@@ -76,9 +76,13 @@
   . = ALIGN(256);
   __init_begin = .;
   .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(256);
+  .data.init : {
+	*(.data.init)
+	. = ALIGN(256);
+	LONG(0) LONG(0)		/* Extend u-boot.bin to here */
+  }
   __init_end = .;
+  _end = .;
 
 #ifndef CONFIG_SPL
 #ifdef CONFIG_440
diff --git a/arch/powerpc/dts/Makefile b/arch/powerpc/dts/Makefile
new file mode 100644
index 0000000..ad104b9
--- /dev/null
+++ b/arch/powerpc/dts/Makefile
@@ -0,0 +1,11 @@
+dtb-$(CONFIG_TARGET_CANYONLANDS) += arches.dtb canyonlands.dtb glacier.dtb
+
+targets += $(dtb-y)
+
+DTC_FLAGS += -R 4 -p 0x1000
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+	@:
+
+clean-files := *.dtb
diff --git a/arch/powerpc/dts/arches.dts b/arch/powerpc/dts/arches.dts
new file mode 100644
index 0000000..bd5ebfd
--- /dev/null
+++ b/arch/powerpc/dts/arches.dts
@@ -0,0 +1,339 @@
+/*
+ * Device Tree Source for AMCC Arches (dual 460GT board)
+ *
+ * (C) Copyright 2008 Applied Micro Circuits Corporation
+ * Victor Gallardo <vgallardo@amcc.com>
+ * Adam Graham <agraham@amcc.com>
+ *
+ * Based on the glacier.dts file
+ *   Stefan Roese <sr@denx.de>
+ *   Copyright 2008 DENX Software Engineering
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,arches";
+	compatible = "amcc,arches";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		ethernet0 = &EMAC0;
+		ethernet1 = &EMAC1;
+		ethernet2 = &EMAC2;
+		serial0 = &UART0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,460GT";
+			reg = <0x00000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+			timebase-frequency = <0>; /* Filled in by U-Boot */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			next-level-cache = <&L2C0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0x0c0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0x0d0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC2: interrupt-controller2 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <2>;
+		dcr-reg = <0x0e0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC3: interrupt-controller3 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <3>;
+		dcr-reg = <0x0f0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-460gt";
+		dcr-reg = <0x00e 0x002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-460gt";
+		dcr-reg = <0x00c 0x002>;
+	};
+
+	L2C0: l2c {
+		compatible = "ibm,l2-cache-460gt", "ibm,l2-cache";
+		dcr-reg = <0x020 0x008		/* Internal SRAM DCR's */
+			   0x030 0x008>;	/* L2 cache DCR's */
+		cache-line-size = <32>;		/* 32 bytes */
+		cache-size = <262144>;		/* L2, 256K */
+		interrupt-parent = <&UIC1>;
+		interrupts = <11 1>;
+	};
+
+	plb {
+		compatible = "ibm,plb-460gt", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <0>; /* Filled in by U-Boot */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
+			dcr-reg = <0x010 0x002>;
+		};
+
+		CRYPTO: crypto@180000 {
+			compatible = "amcc,ppc460gt-crypto", "amcc,ppc4xx-crypto";
+			reg = <4 0x00180000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x1d 0x4>;
+		};
+
+		MAL0: mcmal {
+			compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
+			dcr-reg = <0x180 0x062>;
+			num-tx-chans = <3>;
+			num-rx-chans = <24>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-parent = <&UIC2>;
+			interrupts = <	/*TXEOB*/ 0x6 0x4
+					/*RXEOB*/ 0x7 0x4
+					/*SERR*/  0x3 0x4
+					/*TXDE*/  0x4 0x4
+					/*RXDE*/  0x5 0x4>;
+			desc-base-addr-high = <0x8>;
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-460gt", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-460gt", "ibm,ebc";
+				dcr-reg = <0x012 0x002>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				/* ranges property is supplied by U-Boot */
+				interrupts = <0x6 0x4>;
+				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl256n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x02000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "root";
+						reg = <0x00200000 0x00200000>;
+					};
+					partition@400000 {
+						label = "user";
+						reg = <0x00400000 0x01b60000>;
+					};
+					partition@1f60000 {
+						label = "env";
+						reg = <0x01f60000 0x00040000>;
+					};
+					partition@1fa0000 {
+						label = "u-boot";
+						reg = <0x01fa0000 0x00060000>;
+					};
+				};
+			};
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0xef600300 0x00000008>;
+				virtual-reg = <0xef600300>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <0x1 0x4>;
+			};
+
+			IIC0: i2c@ef600700 {
+				compatible = "ibm,iic-460gt", "ibm,iic";
+				reg = <0xef600700 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x2 0x4>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				sttm@4a {
+					compatible = "ad,ad7414";
+					reg = <0x4a>;
+					interrupt-parent = <&UIC1>;
+					interrupts = <0x0 0x8>;
+				};
+			};
+
+			IIC1: i2c@ef600800 {
+				compatible = "ibm,iic-460gt", "ibm,iic";
+				reg = <0xef600800 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x3 0x4>;
+			};
+
+			TAH0: emac-tah@ef601350 {
+				compatible = "ibm,tah-460gt", "ibm,tah";
+				reg = <0xef601350 0x00000030>;
+			};
+
+			TAH1: emac-tah@ef601450 {
+				compatible = "ibm,tah-460gt", "ibm,tah";
+				reg = <0xef601450 0x00000030>;
+			};
+
+			EMAC0: ethernet@ef600e00 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC0>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+						 /*Wake*/   0x1 &UIC2 0x14 0x4>;
+				reg = <0xef600e00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "sgmii";
+				phy-map = <0xffffffff>;
+				gpcs-address = <0x0000000a>;
+				tah-device = <&TAH0>;
+				tah-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+			};
+
+			EMAC1: ethernet@ef600f00 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC1>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
+						 /*Wake*/   0x1 &UIC2 0x15 0x4>;
+				reg = <0xef600f00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <1>;
+				mal-rx-channel = <8>;
+				cell-index = <1>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "sgmii";
+				phy-map = <0x00000000>;
+				gpcs-address = <0x0000000b>;
+				tah-device = <&TAH1>;
+				tah-channel = <1>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+
+			EMAC2: ethernet@ef601100 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC2>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x12 0x4
+						 /*Wake*/   0x1 &UIC2 0x16 0x4>;
+				reg = <0xef601100 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <2>;
+				mal-rx-channel = <16>;
+				cell-index = <2>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				tx-fifo-size-gige = <16384>; /* emac2&3 only */
+				phy-mode = "sgmii";
+				phy-map = <0x00000001>;
+				gpcs-address = <0x0000000C>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/dts/canyonlands.dts b/arch/powerpc/dts/canyonlands.dts
new file mode 100644
index 0000000..0a2f5d7
--- /dev/null
+++ b/arch/powerpc/dts/canyonlands.dts
@@ -0,0 +1,561 @@
+/*
+ * Device Tree Source for AMCC Canyonlands (460EX)
+ *
+ * Copyright 2008-2009 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,canyonlands";
+	compatible = "amcc,canyonlands";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		ethernet0 = &EMAC0;
+		ethernet1 = &EMAC1;
+		serial0 = &UART0;
+		serial1 = &UART1;
+	};
+
+	chosen {
+		stdout-path = &UART0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,460EX";
+			reg = <0x00000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+			timebase-frequency = <0>; /* Filled in by U-Boot */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			next-level-cache = <&L2C0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-460ex","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0x0c0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-460ex","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0x0d0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC2: interrupt-controller2 {
+		compatible = "ibm,uic-460ex","ibm,uic";
+		interrupt-controller;
+		cell-index = <2>;
+		dcr-reg = <0x0e0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC3: interrupt-controller3 {
+		compatible = "ibm,uic-460ex","ibm,uic";
+		interrupt-controller;
+		cell-index = <3>;
+		dcr-reg = <0x0f0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-460ex";
+		dcr-reg = <0x00e 0x002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-460ex";
+		dcr-reg = <0x00c 0x002>;
+	};
+
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x160 0x003>;
+		unused-units = <0x00000100>;
+		idle-doze = <0x02000000>;
+		standby = <0xfeff791d>;
+	};
+
+	L2C0: l2c {
+		compatible = "ibm,l2-cache-460ex", "ibm,l2-cache";
+		dcr-reg = <0x020 0x008		/* Internal SRAM DCR's */
+			   0x030 0x008>;	/* L2 cache DCR's */
+		cache-line-size = <32>;		/* 32 bytes */
+		cache-size = <262144>;		/* L2, 256K */
+		interrupt-parent = <&UIC1>;
+		interrupts = <11 1>;
+	};
+
+	plb {
+		compatible = "ibm,plb-460ex", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <0>; /* Filled in by U-Boot */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-460ex", "ibm,sdram-405gp";
+			dcr-reg = <0x010 0x002>;
+		};
+
+		CRYPTO: crypto@180000 {
+			compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto";
+			reg = <4 0x00180000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x1d 0x4>;
+		};
+
+		HWRNG: hwrng@110000 {
+			compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+			reg = <4 0x00110000 0x50>;
+		};
+
+		MAL0: mcmal {
+			compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
+			dcr-reg = <0x180 0x062>;
+			num-tx-chans = <2>;
+			num-rx-chans = <16>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-parent = <&UIC2>;
+			interrupts = <	/*TXEOB*/ 0x6 0x4
+					/*RXEOB*/ 0x7 0x4
+					/*SERR*/  0x3 0x4
+					/*TXDE*/  0x4 0x4
+					/*RXDE*/  0x5 0x4>;
+		};
+
+		USB0: ehci@bffd0400 {
+			compatible = "ibm,usb-ehci-460ex", "usb-ehci";
+			interrupt-parent = <&UIC2>;
+			interrupts = <0x1d 4>;
+			reg = <4 0xbffd0400 0x90 4 0xbffd0490 0x70>;
+		};
+
+		USB1: usb@bffd0000 {
+			compatible = "ohci-le";
+			reg = <4 0xbffd0000 0x60>;
+			interrupt-parent = <&UIC2>;
+			interrupts = <0x1e 4>;
+		};
+
+		USBOTG0: usbotg@bff80000 {
+			compatible = "amcc,dwc-otg";
+			reg = <0x4 0xbff80000 0x10000>;
+			interrupt-parent = <&USBOTG0>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x1 0x2>;
+			interrupt-map = </* USB-OTG */ 0x0 &UIC2 0x1c 0x4
+					 /* HIGH-POWER */ 0x1 &UIC1 0x1a 0x8
+					 /* DMA */ 0x2 &UIC0 0xc 0x4>;
+		};
+
+		SATA0: sata@bffd1000 {
+			compatible = "amcc,sata-460ex";
+			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
+			interrupt-parent = <&UIC3>;
+			interrupts = <0x0 0x4       /* SATA */
+				      0x5 0x4>;     /* AHBDMA */
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-460ex", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-460ex", "ibm,ebc";
+				dcr-reg = <0x012 0x002>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				/* ranges property is supplied by U-Boot */
+				interrupts = <0x6 0x4>;
+				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl512n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x04000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "ramdisk";
+						reg = <0x00200000 0x01400000>;
+					};
+					partition@1600000 {
+						label = "jffs2";
+						reg = <0x01600000 0x00400000>;
+					};
+					partition@1a00000 {
+						label = "user";
+						reg = <0x01a00000 0x02560000>;
+					};
+					partition@3f60000 {
+						label = "env";
+						reg = <0x03f60000 0x00040000>;
+					};
+					partition@3fa0000 {
+						label = "u-boot";
+						reg = <0x03fa0000 0x00060000>;
+					};
+				};
+
+				cpld@2,0 {
+					compatible = "amcc,ppc460ex-bcsr";
+					reg = <2 0x0 0x9>;
+				};
+
+				ndfc@3,0 {
+					compatible = "ibm,ndfc";
+					reg = <0x00000003 0x00000000 0x00002000>;
+					ccr = <0x00001000>;
+					bank-settings = <0x80002222>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					nand {
+						#address-cells = <1>;
+						#size-cells = <1>;
+
+						partition@0 {
+							label = "u-boot";
+							reg = <0x00000000 0x00100000>;
+						};
+						partition@100000 {
+							label = "user";
+							reg = <0x00000000 0x03f00000>;
+						};
+					};
+				};
+			};
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600300 0x00000008>;
+				virtual-reg = <0xef600300>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <0x1 0x4>;
+			};
+
+			UART1: serial@ef600400 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600400 0x00000008>;
+				virtual-reg = <0xef600400>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x1 0x4>;
+			};
+
+			IIC0: i2c@ef600700 {
+				compatible = "ibm,iic-460ex", "ibm,iic";
+				reg = <0xef600700 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x2 0x4>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+                                rtc@68 {
+                                        compatible = "stm,m41t80";
+                                        reg = <0x68>;
+					interrupt-parent = <&UIC2>;
+					interrupts = <0x19 0x8>;
+                                };
+                                sttm@48 {
+                                        compatible = "ad,ad7414";
+                                        reg = <0x48>;
+					interrupt-parent = <&UIC1>;
+					interrupts = <0x14 0x8>;
+                                };
+			};
+
+			IIC1: i2c@ef600800 {
+				compatible = "ibm,iic-460ex", "ibm,iic";
+				reg = <0xef600800 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x3 0x4>;
+			};
+
+			GPIO0: gpio@ef600b00 {
+				compatible = "ibm,ppc4xx-gpio";
+				reg = <0xef600b00 0x00000048>;
+				gpio-controller;
+			};
+
+			ZMII0: emac-zmii@ef600d00 {
+				compatible = "ibm,zmii-460ex", "ibm,zmii";
+				reg = <0xef600d00 0x0000000c>;
+			};
+
+			RGMII0: emac-rgmii@ef601500 {
+				compatible = "ibm,rgmii-460ex", "ibm,rgmii";
+				reg = <0xef601500 0x00000008>;
+				has-mdio;
+			};
+
+			TAH0: emac-tah@ef601350 {
+				compatible = "ibm,tah-460ex", "ibm,tah";
+				reg = <0xef601350 0x00000030>;
+			};
+
+			TAH1: emac-tah@ef601450 {
+				compatible = "ibm,tah-460ex", "ibm,tah";
+				reg = <0xef601450 0x00000030>;
+			};
+
+			EMAC0: ethernet@ef600e00 {
+				device_type = "network";
+				compatible = "ibm,emac-460ex", "ibm,emac4sync";
+				interrupt-parent = <&EMAC0>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+						 /*Wake*/   0x1 &UIC2 0x14 0x4>;
+				reg = <0xef600e00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <0>;
+				tah-device = <&TAH0>;
+				tah-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+			};
+
+			EMAC1: ethernet@ef600f00 {
+				device_type = "network";
+				compatible = "ibm,emac-460ex", "ibm,emac4sync";
+				interrupt-parent = <&EMAC1>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
+						 /*Wake*/   0x1 &UIC2 0x15 0x4>;
+				reg = <0xef600f00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <1>;
+				mal-rx-channel = <8>;
+				cell-index = <1>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <1>;
+				tah-device = <&TAH1>;
+				tah-channel = <1>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+		};
+
+		PCIX0: pci@c0ec00000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix";
+			primary;
+			large-inbound-windows;
+			enable-msi-hole;
+			reg = <0x0000000c 0x0ec00000   0x00000008	/* Config space access */
+			       0x00000000 0x00000000 0x00000000		/* no IACK cycles */
+			       0x0000000c 0x0ed00000   0x00000004   /* Special cycles */
+			       0x0000000c 0x0ec80000 0x00000100	/* Internal registers */
+			       0x0000000c 0x0ec80100  0x000000fc>;	/* Internal messaging registers */
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000c 0x0ee00000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 0 to 0x3f */
+			bus-range = <0x0 0x3f>;
+
+			/* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x0>;
+			interrupt-map = < 0x0 0x0 0x0 0x0 &UIC1 0x0 0x8 >;
+		};
+
+		PCIE0: pciex@d00000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
+			primary;
+			port = <0x0>; /* port number */
+			reg = <0x0000000d 0x00000000 0x20000000	/* Config space access */
+			       0x0000000c 0x08010000 0x00001000>;	/* Registers */
+			dcr-reg = <0x100 0x020>;
+			sdr-base = <0x300>;
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000f 0x00000000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 40 to 0x7f */
+			bus-range = <0x40 0x7f>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &UIC3 0xc 0x4 /* swizzled int A */
+				0x0 0x0 0x0 0x2 &UIC3 0xd 0x4 /* swizzled int B */
+				0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
+				0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
+		};
+
+		PCIE1: pciex@d20000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
+			primary;
+			port = <0x1>; /* port number */
+			reg = <0x0000000d 0x20000000 0x20000000	/* Config space access */
+			       0x0000000c 0x08011000 0x00001000>;	/* Registers */
+			dcr-reg = <0x120 0x020>;
+			sdr-base = <0x340>;
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000f 0x00100000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 80 to 0xbf */
+			bus-range = <0x80 0xbf>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &UIC3 0x10 0x4 /* swizzled int A */
+				0x0 0x0 0x0 0x2 &UIC3 0x11 0x4 /* swizzled int B */
+				0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */
+				0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>;
+		};
+
+		MSI: ppc4xx-msi@C10000000 {
+			compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
+			reg = < 0xC 0x10000000 0x100>;
+			sdr-base = <0x36C>;
+			msi-data = <0x00000000>;
+			msi-mask = <0x44440000>;
+			interrupt-count = <3>;
+			interrupts = <0 1 2 3>;
+			interrupt-parent = <&UIC3>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0 &UIC3 0x18 1
+					1 &UIC3 0x19 1
+					2 &UIC3 0x1A 1
+					3 &UIC3 0x1B 1>;
+		};
+	};
+};
diff --git a/arch/powerpc/dts/glacier.dts b/arch/powerpc/dts/glacier.dts
new file mode 100644
index 0000000..bb4e819
--- /dev/null
+++ b/arch/powerpc/dts/glacier.dts
@@ -0,0 +1,582 @@
+/*
+ * Device Tree Source for AMCC Glacier (460GT)
+ *
+ * Copyright 2008-2010 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,glacier";
+	compatible = "amcc,glacier";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		ethernet0 = &EMAC0;
+		ethernet1 = &EMAC1;
+		ethernet2 = &EMAC2;
+		ethernet3 = &EMAC3;
+		serial0 = &UART0;
+		serial1 = &UART1;
+	};
+
+	chosen {
+		stdout-path = &UART0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,460GT";
+			reg = <0x00000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+			timebase-frequency = <0>; /* Filled in by U-Boot */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			next-level-cache = <&L2C0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0x0c0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0x0d0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC2: interrupt-controller2 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <2>;
+		dcr-reg = <0x0e0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC3: interrupt-controller3 {
+		compatible = "ibm,uic-460gt","ibm,uic";
+		interrupt-controller;
+		cell-index = <3>;
+		dcr-reg = <0x0f0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-460gt";
+		dcr-reg = <0x00e 0x002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-460gt";
+		dcr-reg = <0x00c 0x002>;
+	};
+
+	L2C0: l2c {
+		compatible = "ibm,l2-cache-460gt", "ibm,l2-cache";
+		dcr-reg = <0x020 0x008		/* Internal SRAM DCR's */
+			   0x030 0x008>;	/* L2 cache DCR's */
+		cache-line-size = <32>;		/* 32 bytes */
+		cache-size = <262144>;		/* L2, 256K */
+		interrupt-parent = <&UIC1>;
+		interrupts = <11 1>;
+	};
+
+	plb {
+		compatible = "ibm,plb-460gt", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <0>; /* Filled in by U-Boot */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
+			dcr-reg = <0x010 0x002>;
+		};
+
+		CRYPTO: crypto@180000 {
+			compatible = "amcc,ppc460gt-crypto", "amcc,ppc460ex-crypto",
+				"amcc,ppc4xx-crypto";
+			reg = <4 0x00180000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x1d 0x4>;
+		};
+
+		HWRNG: hwrng@110000 {
+			compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+			reg = <4 0x00110000 0x50>;
+		};
+
+		MAL0: mcmal {
+			compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
+			dcr-reg = <0x180 0x062>;
+			num-tx-chans = <4>;
+			num-rx-chans = <32>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-parent = <&UIC2>;
+			interrupts = <	/*TXEOB*/ 0x6 0x4
+					/*RXEOB*/ 0x7 0x4
+					/*SERR*/  0x3 0x4
+					/*TXDE*/  0x4 0x4
+					/*RXDE*/  0x5 0x4>;
+			desc-base-addr-high = <0x8>;
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-460gt", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-460gt", "ibm,ebc";
+				dcr-reg = <0x012 0x002>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				/* ranges property is supplied by U-Boot */
+				interrupts = <0x6 0x4>;
+				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl512n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x04000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "ramdisk";
+						reg = <0x00200000 0x01400000>;
+					};
+					partition@1600000 {
+						label = "jffs2";
+						reg = <0x01600000 0x00400000>;
+					};
+					partition@1a00000 {
+						label = "user";
+						reg = <0x01a00000 0x02560000>;
+					};
+					partition@3f60000 {
+						label = "env";
+						reg = <0x03f60000 0x00040000>;
+					};
+					partition@3fa0000 {
+						label = "u-boot";
+						reg = <0x03fa0000 0x00060000>;
+					};
+				};
+
+				ndfc@3,0 {
+					compatible = "ibm,ndfc";
+					reg = <0x00000003 0x00000000 0x00002000>;
+					ccr = <0x00001000>;
+					bank-settings = <0x80002222>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					nand {
+						#address-cells = <1>;
+						#size-cells = <1>;
+
+						partition@0 {
+							label = "u-boot";
+							reg = <0x00000000 0x00100000>;
+						};
+						partition@100000 {
+							label = "user";
+							reg = <0x00000000 0x03f00000>;
+						};
+					};
+				};
+			};
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600300 0x00000008>;
+				virtual-reg = <0xef600300>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <0x1 0x4>;
+			};
+
+			UART1: serial@ef600400 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600400 0x00000008>;
+				virtual-reg = <0xef600400>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x1 0x4>;
+			};
+
+			UART2: serial@ef600500 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600500 0x00000008>;
+				virtual-reg = <0xef600500>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <28 0x4>;
+			};
+
+			UART3: serial@ef600600 {
+				device_type = "serial";
+				reg-shift = <0>;
+				compatible = "ns16550";
+				reg = <0xef600600 0x00000008>;
+				virtual-reg = <0xef600600>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <29 0x4>;
+			};
+
+			IIC0: i2c@ef600700 {
+				compatible = "ibm,iic-460gt", "ibm,iic";
+				reg = <0xef600700 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x2 0x4>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				rtc@68 {
+					compatible = "stm,m41t80";
+					reg = <0x68>;
+					interrupt-parent = <&UIC2>;
+					interrupts = <0x19 0x8>;
+				};
+				sttm@48 {
+					compatible = "ad,ad7414";
+					reg = <0x48>;
+					interrupt-parent = <&UIC1>;
+					interrupts = <0x14 0x8>;
+				};
+			};
+
+			IIC1: i2c@ef600800 {
+				compatible = "ibm,iic-460gt", "ibm,iic";
+				reg = <0xef600800 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x3 0x4>;
+			};
+
+			ZMII0: emac-zmii@ef600d00 {
+				compatible = "ibm,zmii-460gt", "ibm,zmii";
+				reg = <0xef600d00 0x0000000c>;
+			};
+
+			RGMII0: emac-rgmii@ef601500 {
+				compatible = "ibm,rgmii-460gt", "ibm,rgmii";
+				reg = <0xef601500 0x00000008>;
+				has-mdio;
+			};
+
+			RGMII1: emac-rgmii@ef601600 {
+				compatible = "ibm,rgmii-460gt", "ibm,rgmii";
+				reg = <0xef601600 0x00000008>;
+				has-mdio;
+			};
+
+			TAH0: emac-tah@ef601350 {
+				compatible = "ibm,tah-460gt", "ibm,tah";
+				reg = <0xef601350 0x00000030>;
+			};
+
+			TAH1: emac-tah@ef601450 {
+				compatible = "ibm,tah-460gt", "ibm,tah";
+				reg = <0xef601450 0x00000030>;
+			};
+
+			EMAC0: ethernet@ef600e00 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC0>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+						 /*Wake*/   0x1 &UIC2 0x14 0x4>;
+				reg = <0xef600e00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <0>;
+				tah-device = <&TAH0>;
+				tah-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+			};
+
+			EMAC1: ethernet@ef600f00 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC1>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
+						 /*Wake*/   0x1 &UIC2 0x15 0x4>;
+				reg = <0xef600f00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <1>;
+				mal-rx-channel = <8>;
+				cell-index = <1>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <1>;
+				tah-device = <&TAH1>;
+				tah-channel = <1>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+
+			EMAC2: ethernet@ef601100 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC2>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x12 0x4
+						 /*Wake*/   0x1 &UIC2 0x16 0x4>;
+				reg = <0xef601100 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <2>;
+				mal-rx-channel = <16>;
+				cell-index = <2>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				tx-fifo-size-gige = <16384>; /* emac2&3 only */
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII1>;
+				rgmii-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+
+			EMAC3: ethernet@ef601200 {
+				device_type = "network";
+				compatible = "ibm,emac-460gt", "ibm,emac4sync";
+				interrupt-parent = <&EMAC3>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x13 0x4
+						 /*Wake*/   0x1 &UIC2 0x17 0x4>;
+				reg = <0xef601200 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <3>;
+				mal-rx-channel = <24>;
+				cell-index = <3>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				rx-fifo-size-gige = <16384>;
+				tx-fifo-size-gige = <16384>; /* emac2&3 only */
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII1>;
+				rgmii-channel = <1>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+				mdio-device = <&EMAC0>;
+			};
+		};
+
+		PCIX0: pci@c0ec00000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pcix-460gt", "ibm,plb-pcix";
+			primary;
+			large-inbound-windows;
+			enable-msi-hole;
+			reg = <0x0000000c 0x0ec00000   0x00000008	/* Config space access */
+			       0x00000000 0x00000000 0x00000000		/* no IACK cycles */
+			       0x0000000c 0x0ed00000   0x00000004   /* Special cycles */
+			       0x0000000c 0x0ec80000 0x00000100	/* Internal registers */
+			       0x0000000c 0x0ec80100  0x000000fc>;	/* Internal messaging registers */
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000c 0x0ee00000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 0 to 0x3f */
+			bus-range = <0x0 0x3f>;
+
+			/* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x0>;
+			interrupt-map = < 0x0 0x0 0x0 0x0 &UIC1 0x0 0x8 >;
+		};
+
+		PCIE0: pciex@d00000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
+			primary;
+			port = <0x0>; /* port number */
+			reg = <0x0000000d 0x00000000 0x20000000	/* Config space access */
+			       0x0000000c 0x08010000 0x00001000>;	/* Registers */
+			dcr-reg = <0x100 0x020>;
+			sdr-base = <0x300>;
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000f 0x00000000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 40 to 0x7f */
+			bus-range = <0x40 0x7f>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &UIC3 0xc 0x4 /* swizzled int A */
+				0x0 0x0 0x0 0x2 &UIC3 0xd 0x4 /* swizzled int B */
+				0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
+				0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
+		};
+
+		PCIE1: pciex@d20000000 {
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
+			primary;
+			port = <0x1>; /* port number */
+			reg = <0x0000000d 0x20000000 0x20000000	/* Config space access */
+			       0x0000000c 0x08011000 0x00001000>;	/* Registers */
+			dcr-reg = <0x120 0x020>;
+			sdr-base = <0x340>;
+
+			/* Outbound ranges, one memory and one IO,
+			 * later cannot be changed
+			 */
+			ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+				  0x02000000 0x00000000 0x00000000 0x0000000f 0x00100000 0x00000000 0x00100000
+				  0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
+
+			/* Inbound 2GB range starting at 0 */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
+
+			/* This drives busses 80 to 0xbf */
+			bus-range = <0x80 0xbf>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &UIC3 0x10 0x4 /* swizzled int A */
+				0x0 0x0 0x0 0x2 &UIC3 0x11 0x4 /* swizzled int B */
+				0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */
+				0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>;
+		};
+	};
+};
diff --git a/arch/powerpc/include/asm/arch-ppc4xx/gpio.h b/arch/powerpc/include/asm/arch-ppc4xx/gpio.h
new file mode 100644
index 0000000..3d960c3
--- /dev/null
+++ b/arch/powerpc/include/asm/arch-ppc4xx/gpio.h
@@ -0,0 +1,7 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* This is empty for now as we don't support the generic GPIO interface */
diff --git a/arch/powerpc/include/asm/linkage.h b/arch/powerpc/include/asm/linkage.h
new file mode 100644
index 0000000..559b42e
--- /dev/null
+++ b/arch/powerpc/include/asm/linkage.h
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* We don't need anything here at present */
diff --git a/arch/powerpc/include/asm/ppc460ex_gt.h b/arch/powerpc/include/asm/ppc460ex_gt.h
index f41df0d..ea019aa 100644
--- a/arch/powerpc/include/asm/ppc460ex_gt.h
+++ b/arch/powerpc/include/asm/ppc460ex_gt.h
@@ -19,10 +19,12 @@
 /* Memory mapped registers */
 #define CONFIG_SYS_PERIPHERAL_BASE	0xef600000 /* Internal Peripherals */
 
+#ifndef CONFIG_DM_SERIAL
 #define CONFIG_SYS_NS16550_COM1	(CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
 #define CONFIG_SYS_NS16550_COM2	(CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
 #define CONFIG_SYS_NS16550_COM3	(CONFIG_SYS_PERIPHERAL_BASE + 0x0500)
 #define CONFIG_SYS_NS16550_COM4	(CONFIG_SYS_PERIPHERAL_BASE + 0x0600)
+#endif
 
 #define GPIO0_BASE		(CONFIG_SYS_PERIPHERAL_BASE + 0x0b00)
 #define GPIO1_BASE		(CONFIG_SYS_PERIPHERAL_BASE + 0x0c00)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 0f62982..05b22bb 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -40,6 +40,7 @@
 obj-y	+= interrupts.o
 obj-$(CONFIG_CMD_KGDB) += kgdb.o
 obj-$(CONFIG_CMD_IDE) += ide.o
+obj-y	+= stack.o
 obj-y	+= time.o
 
 # Don't include the MPC5xxx special memcpy into the
diff --git a/arch/powerpc/lib/stack.c b/arch/powerpc/lib/stack.c
new file mode 100644
index 0000000..1985f03
--- /dev/null
+++ b/arch/powerpc/lib/stack.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Andreas Bießmann <andreas.devel@googlemail.com>
+ *
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2002-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_reserve_stacks(void)
+{
+	ulong *s;
+
+	/* setup stack pointer for exceptions */
+	gd->irq_sp = gd->start_addr_sp;
+
+	/* Clear initial stack frame */
+	s = (ulong *)gd->start_addr_sp;
+	*s = 0; /* Terminate back chain */
+	*++s = 0; /* NULL return address */
+
+	return 0;
+}
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 3057325..2098b9c 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -10,4 +10,28 @@
 config SYS_CONFIG_NAME
 	default "sandbox"
 
+config DM
+	default y
+
+config DM_GPIO
+	default y
+
+config DM_SERIAL
+	default y
+
+config DM_CROS_EC
+	default y
+
+config DM_SPI
+	default y
+
+config DM_SPI_FLASH
+	default y
+
+config DM_I2C
+	default y
+
+config DM_TEST
+	default y
+
 endmenu
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index e38a44b..7b84f02 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -5,10 +5,16 @@
 PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM -DCONFIG_SYS_GENERIC_BOARD
 PLATFORM_LIBS += -lrt
 
+# Define this to avoid linking with SDL, which requires SDL libraries
+# This can solve 'sdl-config: Command not found' errors
+ifneq ($(NO_SDL),)
+PLATFORM_CPPFLAGS += -DSANDBOX_NO_SDL
+else
 ifdef CONFIG_SANDBOX_SDL
 PLATFORM_LIBS += $(shell sdl-config --libs)
 PLATFORM_CPPFLAGS += $(shell sdl-config --cflags)
 endif
+endif
 
 # Support generic board on sandbox
 __HAVE_ARCH_GENERIC_BOARD := y
@@ -18,9 +24,3 @@
 	$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
 
 CONFIG_ARCH_DEVICE_TREE := sandbox
-
-# Define this to avoid linking with SDL, which requires SDL libraries
-# This can solve 'sdl-config: Command not found' errors
-ifneq ($(NO_SDL),)
-PLATFORM_CPPFLAGS += -DSANDBOX_NO_SDL
-endif
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 42353d8..ec01040 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <os.h>
 #include <cli.h>
+#include <malloc.h>
 #include <asm/getopt.h>
 #include <asm/io.h>
 #include <asm/sections.h>
@@ -77,11 +78,13 @@
 
 	/* Execute command if required */
 	if (state->cmd) {
+		int retval;
+
 		cli_init();
 
-		run_command_list(state->cmd, -1, 0);
+		retval = run_command_list(state->cmd, -1, 0);
 		if (!state->interactive)
-			os_exit(state->exit_type);
+			os_exit(retval);
 	}
 
 	return 0;
@@ -102,6 +105,25 @@
 }
 SANDBOX_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT");
 
+static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state,
+					  const char *arg)
+{
+	const char *fmt = "%s.dtb";
+	char *fname;
+	int len;
+
+	len = strlen(state->argv[0]) + strlen(fmt) + 1;
+	fname = os_malloc(len);
+	if (!fname)
+		return -ENOMEM;
+	snprintf(fname, len, fmt, state->argv[0]);
+	state->fdt_fname = fname;
+
+	return 0;
+}
+SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0,
+		"Use the default u-boot.dtb control FDT in U-Boot directory");
+
 static int sandbox_cmdline_cb_interactive(struct sandbox_state *state,
 					  const char *arg)
 {
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index ba73b7e..033958c 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -13,11 +13,6 @@
 static struct sandbox_state main_state;
 static struct sandbox_state *state;	/* Pointer to current state record */
 
-void state_record_exit(enum exit_type_id exit_type)
-{
-	state->exit_type = exit_type;
-}
-
 static int state_ensure_space(int extra_size)
 {
 	void *blob = state->state_fdt;
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 11748ae..9ce31bf 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -19,6 +19,7 @@
 		colour = "cyan";
 		sides = <3>;
 		character = <83>;
+		light-gpios = <&gpio_a 2>, <&gpio_b 6 0>;
 	};
 	square {
 		compatible = "demo-shape";
@@ -73,10 +74,8 @@
 
 	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>;
+		keypad,num-rows = <8>;
+		keypad,num-columns = <13>;
 		google,ghost-filter;
 		/*
 		 * Keymap entries take the form of 0xRRCCKKKK where
@@ -126,7 +125,7 @@
 			0x070b0067 0x070c0069>;
 	};
 
-	gpio_a: gpios {
+	gpio_a: gpios@0 {
 		gpio-controller;
 		compatible = "sandbox,gpio";
 		#gpio-cells = <1>;
@@ -134,6 +133,14 @@
 		num-gpios = <20>;
 	};
 
+	gpio_b: gpios@1 {
+		gpio-controller;
+		compatible = "sandbox,gpio";
+		#gpio-cells = <2>;
+		gpio-bank-name = "b";
+		num-gpios = <10>;
+	};
+
 	i2c@0 {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 32d55cc..a0c24ba 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -10,13 +10,6 @@
 #include <stdbool.h>
 #include <linux/stringify.h>
 
-/* How we exited U-Boot */
-enum exit_type_id {
-	STATE_EXIT_NORMAL,
-	STATE_EXIT_COLD_REBOOT,
-	STATE_EXIT_POWER_OFF,
-};
-
 /**
  * Selects the behavior of the serial terminal.
  *
@@ -50,7 +43,6 @@
 	const char *cmd;		/* Command to execute */
 	bool interactive;		/* Enable cmdline after execute */
 	const char *fdt_fname;		/* Filename of FDT binary */
-	enum exit_type_id exit_type;	/* How we exited U-Boot */
 	const char *parse_err;		/* Error to report from parsing */
 	int argc;			/* Program arguments */
 	char **argv;			/* Command line arguments */
@@ -139,13 +131,6 @@
 	}
 
 /**
- * Record the exit type to be reported by the test program.
- *
- * @param exit_type	Exit type to record
- */
-void state_record_exit(enum exit_type_id exit_type);
-
-/**
  * Gets a pointer to the current state.
  *
  * @return pointer to state
diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h
index d2f1b65..770ab5c 100644
--- a/arch/sandbox/include/asm/u-boot-sandbox.h
+++ b/arch/sandbox/include/asm/u-boot-sandbox.h
@@ -17,7 +17,6 @@
 
 /* board/.../... */
 int board_init(void);
-int dram_init(void);
 
 /* start.c */
 int sandbox_early_getopt_check(void);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 90e828a..35d24e4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -41,8 +41,47 @@
 	  Intel Platform Controller Hub EG20T, other system components and
 	  peripheral connectors for PCIe/SATA/USB/LAN/SD/UART/Audio/LVDS.
 
+config TARGET_MINNOWMAX
+	bool "Support Intel Minnowboard MAX"
+	help
+	  This is the Intel Minnowboard MAX. It contains an Atom E3800
+	  processor in a small form factor with Ethernet, micro-SD, USB 2,
+	  USB 3, SATA, serial console, some GPIOs and HDMI 1.3 video out.
+	  It requires some binary blobs - see README.x86 for details.
+
+	  Note that PCIE_ECAM_BASE is set up by the FSP so the value used
+	  by U-Boot matches that value.
+
+config TARGET_GALILEO
+	bool "Support Intel Galileo"
+	help
+	  This is the Intel Galileo board, which is the first in a family of
+	  Arduino-certified development and prototyping boards based on Intel
+	  architecture. It includes an Intel Quark SoC X1000 processor, a 32-bit
+	  single-core, single-thread, Intel Pentium processor instrunction set
+	  architecture (ISA) compatible, operating at speeds up to 400Mhz,
+	  along with 256MB DDR3 memory. It supports a wide range of industry
+	  standard I/O interfaces, including a full-sized mini-PCIe slot,
+	  one 100Mb Ethernet port, a microSD card slot, a USB host port and
+	  a USB client port.
+
 endchoice
 
+config DM
+	default y
+
+config DM_GPIO
+	default y
+
+config DM_SERIAL
+	default y
+
+config SYS_MALLOC_F
+	default y
+
+config SYS_MALLOC_F_LEN
+	default 0x800
+
 config RAMBASE
 	hex
 	default 0x100000
@@ -324,6 +363,54 @@
 
 endmenu
 
+config HAVE_FSP
+	bool "Add an Firmware Support Package binary"
+	help
+	  Select this option to add an Firmware Support Package binary to
+	  the resulting U-Boot image. It is a binary blob which U-Boot uses
+	  to set up SDRAM and other chipset specific initialization.
+
+	  Note: Without this binary U-Boot will not be able to set up its
+	  SDRAM so will not boot.
+
+config FSP_FILE
+	string "Firmware Support Package binary filename"
+	depends on HAVE_FSP
+	default "fsp.bin"
+	help
+	  The filename of the file to use as Firmware Support Package binary
+	  in the board directory.
+
+config FSP_ADDR
+	hex "Firmware Support Package binary location"
+	depends on HAVE_FSP
+	default 0xfffc0000
+	help
+	  FSP is not Position Independent Code (PIC) and the whole FSP has to
+	  be rebased if it is placed at a location which is different from the
+	  perferred base address specified during the FSP build. Use Intel's
+	  Binary Configuration Tool (BCT) to do the rebase.
+
+	  The default base address of 0xfffc0000 indicates that the binary must
+	  be located at offset 0xc0000 from the beginning of a 1MB flash device.
+
+config FSP_TEMP_RAM_ADDR
+	hex
+	default 0x2000000
+	help
+	  Stack top address which is used in FspInit after DRAM is ready and
+	  CAR is disabled.
+
+source "arch/x86/cpu/baytrail/Kconfig"
+
+source "arch/x86/cpu/coreboot/Kconfig"
+
+source "arch/x86/cpu/ivybridge/Kconfig"
+
+source "arch/x86/cpu/quark/Kconfig"
+
+source "arch/x86/cpu/queensbay/Kconfig"
+
 config TSC_CALIBRATION_BYPASS
 	bool "Bypass Time-Stamp Counter (TSC) calibration"
 	default n
@@ -344,16 +431,28 @@
 	help
 	  The running frequency in MHz of Time-Stamp Counter (TSC).
 
-source "arch/x86/cpu/coreboot/Kconfig"
-
-source "arch/x86/cpu/ivybridge/Kconfig"
-
-source "arch/x86/cpu/queensbay/Kconfig"
-
 source "board/coreboot/coreboot/Kconfig"
 
 source "board/google/chromebook_link/Kconfig"
 
 source "board/intel/crownbay/Kconfig"
 
+source "board/intel/minnowmax/Kconfig"
+
+source "board/intel/galileo/Kconfig"
+
+config PCIE_ECAM_BASE
+	hex
+	default 0xe0000000
+	help
+	  This is the memory-mapped address of PCI configuration space, which
+	  is only available through the Enhanced Configuration Access
+	  Mechanism (ECAM) with PCI Express. It can be set up almost
+	  anywhere. Before it is set up, it is possible to access PCI
+	  configuration space through I/O access, but memory access is more
+	  convenient. Using this, PCI can be scanned and configured. This
+	  should be set to a region that does not conflict with memory
+	  assigned to PCI devices - i.e. the memory and prefetch regions, as
+	  passed to pci_set_region().
+
 endmenu
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 62e43c0..6ded0a7 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -12,9 +12,11 @@
 obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
 obj-y	+= interrupts.o cpu.o call64.o
 
+obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
+obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
 obj-y += lapic.o
 obj-y += mtrr.o
diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig
new file mode 100644
index 0000000..e86cc01
--- /dev/null
+++ b/arch/x86/cpu/baytrail/Kconfig
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+config INTEL_BAYTRAIL
+	bool
+	select HAVE_FSP
diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
new file mode 100644
index 0000000..8914e8b
--- /dev/null
+++ b/arch/x86/cpu/baytrail/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += early_uart.o
+obj-y += fsp_configs.o
+obj-y += pci.o
+obj-y += valleyview.o
diff --git a/arch/x86/cpu/baytrail/early_uart.c b/arch/x86/cpu/baytrail/early_uart.c
new file mode 100644
index 0000000..4199210
--- /dev/null
+++ b/arch/x86/cpu/baytrail/early_uart.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+
+#define PCI_DEV_CONFIG(segbus, dev, fn) ( \
+		(((segbus) & 0xfff) << 20) | \
+		(((dev) & 0x1f) << 15) | \
+		(((fn)  & 0x07) << 12))
+
+/* Platform Controller Unit */
+#define LPC_DEV			0x1f
+#define LPC_FUNC		0
+
+/* Enable UART */
+#define UART_CONT		0x80
+
+/* SCORE Pad definitions */
+#define UART_RXD_PAD			82
+#define UART_TXD_PAD			83
+
+/* Pad base: PAD_CONF0[n]= PAD_BASE + 16 * n */
+#define GPSCORE_PAD_BASE	(IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE)
+
+/* IO Memory */
+#define IO_BASE_ADDRESS			0xfed0c000
+#define  IO_BASE_OFFSET_GPSCORE		0x0000
+#define  IO_BASE_OFFSET_GPNCORE		0x1000
+#define  IO_BASE_OFFSET_GPSSUS		0x2000
+#define IO_BASE_SIZE			0x4000
+
+static inline unsigned int score_pconf0(int pad_num)
+{
+	return GPSCORE_PAD_BASE + pad_num * 16;
+}
+
+static void score_select_func(int pad, int func)
+{
+	uint32_t reg;
+	uint32_t pconf0_addr = score_pconf0(pad);
+
+	reg = readl(pconf0_addr);
+	reg &= ~0x7;
+	reg |= func & 0x7;
+	writel(reg, pconf0_addr);
+}
+
+static void pci_write_config32(int dev, unsigned int where, u32 value)
+{
+	unsigned long addr;
+
+	addr = CONFIG_PCIE_ECAM_BASE | dev | (where & ~3);
+	writel(value, addr);
+}
+
+/* This can be called after memory-mapped PCI is working */
+int setup_early_uart(void)
+{
+	/* Enable the legacy UART hardware. */
+	pci_write_config32(PCI_DEV_CONFIG(0, LPC_DEV, LPC_FUNC), UART_CONT, 1);
+
+	/*
+	 * Set up the pads to the UART function. This allows the signals to
+	 * leave the chip
+	 */
+	score_select_func(UART_RXD_PAD, 1);
+	score_select_func(UART_TXD_PAD, 1);
+
+	/* TODO(sjg@chromium.org): Call debug_uart_init() */
+
+	return 0;
+}
diff --git a/arch/x86/cpu/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c
new file mode 100644
index 0000000..86b6926
--- /dev/null
+++ b/arch/x86/cpu/baytrail/fsp_configs.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#include <common.h>
+#include <asm/arch/fsp/azalia.h>
+#include <asm/fsp/fsp_support.h>
+
+/* ALC262 Verb Table - 10EC0262 */
+static const uint32_t verb_table_data13[] = {
+	/* Pin Complex (NID 0x11) */
+	0x01171cf0,
+	0x01171d11,
+	0x01171e11,
+	0x01171f41,
+	/* Pin Complex (NID 0x12) */
+	0x01271cf0,
+	0x01271d11,
+	0x01271e11,
+	0x01271f41,
+	/* Pin Complex (NID 0x14) */
+	0x01471c10,
+	0x01471d40,
+	0x01471e01,
+	0x01471f01,
+	/* Pin Complex (NID 0x15) */
+	0x01571cf0,
+	0x01571d11,
+	0x01571e11,
+	0x01571f41,
+	/* Pin Complex (NID 0x16) */
+	0x01671cf0,
+	0x01671d11,
+	0x01671e11,
+	0x01671f41,
+	/* Pin Complex (NID 0x18) */
+	0x01871c20,
+	0x01871d98,
+	0x01871ea1,
+	0x01871f01,
+	/* Pin Complex (NID 0x19) */
+	0x01971c21,
+	0x01971d98,
+	0x01971ea1,
+	0x01971f02,
+	/* Pin Complex (NID 0x1A) */
+	0x01a71c2f,
+	0x01a71d30,
+	0x01a71e81,
+	0x01a71f01,
+	/* Pin Complex */
+	0x01b71c1f,
+	0x01b71d40,
+	0x01b71e21,
+	0x01b71f02,
+	/* Pin Complex */
+	0x01c71cf0,
+	0x01c71d11,
+	0x01c71e11,
+	0x01c71f41,
+	/* Pin Complex */
+	0x01d71c01,
+	0x01d71dc6,
+	0x01d71e14,
+	0x01d71f40,
+	/* Pin Complex */
+	0x01e71cf0,
+	0x01e71d11,
+	0x01e71e11,
+	0x01e71f41,
+	/* Pin Complex */
+	0x01f71cf0,
+	0x01f71d11,
+	0x01f71e11,
+	0x01f71f41,
+};
+
+/*
+ * This needs to be in ROM since if we put it in CAR, FSP init loses it when
+ * it drops CAR.
+ *
+ * TODO(sjg@chromium.org): Move to device tree when FSP allows it
+ *
+ * VerbTable: (RealTek ALC262)
+ * Revision ID = 0xFF, support all steps
+ * Codec Verb Table For AZALIA
+ * Codec Address: CAd value (0/1/2)
+ * Codec Vendor: 0x10EC0262
+ */
+static const struct pch_azalia_verb_table azalia_verb_table[] = {
+	{
+		{
+			0x10ec0262,
+			0x0000,
+			0xff,
+			0x01,
+			0x000b,
+			0x0002,
+		},
+		verb_table_data13
+	}
+};
+
+const struct pch_azalia_config azalia_config = {
+	.pme_enable = 1,
+	.docking_supported = 1,
+	.docking_attached = 0,
+	.hdmi_codec_enable = 1,
+	.azalia_v_ci_enable = 1,
+	.rsvdbits = 0,
+	.azalia_verb_table_num = 1,
+	.azalia_verb_table = azalia_verb_table,
+	.reset_wait_timer_us = 300
+};
+
+void update_fsp_upd(struct upd_region *fsp_upd)
+{
+	struct memory_down_data *mem;
+
+	/*
+	 * Configure everything here to avoid the poor hard-pressed user
+	 * needing to run Intel's binary configuration tool. It may also allow
+	 * us to support the 1GB single core variant easily.
+	 *
+	 * TODO(sjg@chromium.org): Move to device tree
+	 */
+	fsp_upd->mrc_init_tseg_size = 8;
+	fsp_upd->mrc_init_mmio_size = 0x800;
+	fsp_upd->emmc_boot_mode = 0xff;
+	fsp_upd->enable_sdio = 1;
+	fsp_upd->enable_sdcard = 1;
+	fsp_upd->enable_hsuart0 = 1;
+	fsp_upd->azalia_config_ptr = (uint32_t)&azalia_config;
+	fsp_upd->enable_i2_c0 = 0;
+	fsp_upd->enable_i2_c2 = 0;
+	fsp_upd->enable_i2_c3 = 0;
+	fsp_upd->enable_i2_c4 = 0;
+	fsp_upd->enable_xhci = 0;
+	fsp_upd->igd_render_standby = 1;
+
+	mem = &fsp_upd->memory_params;
+	mem->enable_memory_down = 1;
+	mem->dram_speed = 1;
+	mem->dimm_width = 1;
+	mem->dimm_density = 2;
+	mem->dimm_tcl = 0xb;
+	mem->dimm_trpt_rcd = 0xb;
+	mem->dimm_twr = 0xc;
+	mem->dimm_twtr = 6;
+	mem->dimm_trrd = 6;
+	mem->dimm_trtp = 6;
+	mem->dimm_tfaw = 0x14;
+}
diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c
new file mode 100644
index 0000000..6c291f9
--- /dev/null
+++ b/arch/x86/cpu/baytrail/pci.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/pci.h>
+#include <asm/fsp/fsp_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_pci_setup_hose(struct pci_controller *hose)
+{
+	hose->first_busno = 0;
+	hose->last_busno = 0;
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 0,
+		       CONFIG_PCI_MEM_BUS,
+		       CONFIG_PCI_MEM_PHYS,
+		       CONFIG_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(hose->regions + 1,
+		       CONFIG_PCI_IO_BUS,
+		       CONFIG_PCI_IO_PHYS,
+		       CONFIG_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	pci_set_region(hose->regions + 2,
+		       CONFIG_PCI_PREF_BUS,
+		       CONFIG_PCI_PREF_PHYS,
+		       CONFIG_PCI_PREF_SIZE,
+		       PCI_REGION_PREFETCH);
+
+	pci_set_region(hose->regions + 3,
+		       0,
+		       0,
+		       gd->ram_size,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	hose->region_count = 4;
+}
diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c
new file mode 100644
index 0000000..a3e837d
--- /dev/null
+++ b/arch/x86/cpu/baytrail/valleyview.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <pci_ids.h>
+#include <asm/post.h>
+
+static struct pci_device_id mmc_supported[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD },
+};
+
+int cpu_mmc_init(bd_t *bis)
+{
+	printf("mmc init\n");
+	return pci_mmc_init("ValleyView SDHCI", mmc_supported,
+			    ARRAY_SIZE(mmc_supported));
+}
+
+int arch_cpu_init(void)
+{
+	int ret;
+
+	post_code(POST_CPU_INIT);
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+	timer_set_base(rdtsc());
+#endif
+
+	ret = x86_cpu_init_f();
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c
index 6cf9654..821ea25 100644
--- a/arch/x86/cpu/ivybridge/gma.c
+++ b/arch/x86/cpu/ivybridge/gma.c
@@ -758,7 +758,8 @@
 
 #ifdef CONFIG_VIDEO
 	start = get_timer(0);
-	ret = pci_run_vga_bios(dev, int15_handler, false);
+	ret = pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE |
+			       PCI_ROM_ALLOW_FALLBACK);
 	debug("BIOS ran in %lums\n", get_timer(start));
 #endif
 	/* Post VBIOS init */
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index 4963448..766b385 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -757,7 +757,7 @@
 		.mchbar = DEFAULT_MCHBAR,
 		.dmibar = DEFAULT_DMIBAR,
 		.epbar = DEFAULT_EPBAR,
-		.pciexbar = CONFIG_MMCONF_BASE_ADDRESS,
+		.pciexbar = CONFIG_PCIE_ECAM_BASE,
 		.smbusbar = SMBUS_IO_BASE,
 		.wdbbar = 0x4000000,
 		.wdbsize = 0x1000,
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig
new file mode 100644
index 0000000..bc961ef
--- /dev/null
+++ b/arch/x86/cpu/quark/Kconfig
@@ -0,0 +1,126 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+config INTEL_QUARK
+	bool
+	select HAVE_RMU
+	select TSC_CALIBRATION_BYPASS
+
+if INTEL_QUARK
+
+config HAVE_RMU
+	bool "Add a Remote Management Unit (RMU) binary"
+	help
+	  Select this option to add a Remote Management Unit (RMU) binary
+	  to the resulting U-Boot image. It is a data block (up to 64K) of
+	  machine-specific code which must be put in the flash for the RMU
+	  within the Quark SoC processor to access when powered up before
+	  system BIOS is executed.
+
+config RMU_FILE
+	string "Remote Management Unit (RMU) binary filename"
+	depends on HAVE_RMU
+	default "rmu.bin"
+	help
+	  The filename of the file to use as Remote Management Unit (RMU)
+	  binary in the board directory.
+
+config RMU_ADDR
+	hex "Remote Management Unit (RMU) binary location"
+	depends on HAVE_RMU
+	default 0xfff00000
+	help
+	  The location of the RMU binary is determined by a strap. It must be
+	  put in flash at a location matching the strap-determined base address.
+
+	  The default base address of 0xfff00000 indicates that the binary must
+	  be located at offset 0 from the beginning of a 1MB flash device.
+
+config HAVE_CMC
+	bool
+	default HAVE_RMU
+
+config CMC_FILE
+	string
+	depends on HAVE_CMC
+	default RMU_FILE
+
+config CMC_ADDR
+	hex
+	depends on HAVE_CMC
+	default RMU_ADDR
+
+config ESRAM_BASE
+	hex
+	default 0x80000000
+	help
+	  Embedded SRAM (eSRAM) memory-mapped base address.
+
+config PCIE_ECAM_BASE
+	hex
+	default 0xe0000000
+
+config RCBA_BASE
+	hex
+	default 0xfed1c000
+	help
+	  Root Complex register block memory-mapped base address.
+
+config ACPI_PM1_BASE
+	hex
+	default 0x1000
+	help
+	  ACPI Power Managment 1 (PM1) i/o-mapped base address.
+	  This device is defined in ACPI specification, with 16 bytes in size.
+
+config ACPI_PBLK_BASE
+	hex
+	default 0x1010
+	help
+	  ACPI Processor Block (PBLK) i/o-mapped base address.
+	  This device is defined in ACPI specification, with 16 bytes in size.
+
+config SPI_DMA_BASE
+	hex
+	default 0x1020
+	help
+	  SPI DMA i/o-mapped base address.
+
+config GPIO_BASE
+	hex
+	default 0x1080
+	help
+	  GPIO i/o-mapped base address.
+
+config ACPI_GPE0_BASE
+	hex
+	default 0x1100
+	help
+	  ACPI General Purpose Event 0 (GPE0) i/o-mapped base address.
+	  This device is defined in ACPI specification, with 64 bytes in size.
+
+config WDT_BASE
+	hex
+	default 0x1140
+	help
+	  Watchdog timer i/o-mapped base address.
+
+config SYS_CAR_ADDR
+	hex
+	default ESRAM_BASE
+
+config SYS_CAR_SIZE
+	hex
+	default 0x8000
+	help
+	  Space in bytes in eSRAM used as Cache-As-ARM (CAR).
+	  Note this size must not exceed eSRAM's total size.
+
+config TSC_FREQ_IN_MHZ
+	int
+	default 400
+
+endif
diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile
new file mode 100644
index 0000000..e87b424
--- /dev/null
+++ b/arch/x86/cpu/quark/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += car.o dram.o msg_port.o quark.o
+obj-y += mrc.o mrc_util.o hte.o smc.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/quark/car.S b/arch/x86/cpu/quark/car.S
new file mode 100644
index 0000000..3432ffa
--- /dev/null
+++ b/arch/x86/cpu/quark/car.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/arch/quark.h>
+#include <asm/arch/msg_port.h>
+
+.globl car_init
+car_init:
+	post_code(POST_CAR_START)
+
+	/*
+	 * Quark SoC contains an embedded 512KiB SRAM (eSRAM) that is
+	 * initialized by hardware. eSRAM is the ideal place to be used
+	 * for Cache-As-RAM (CAR) before system memory is available.
+	 *
+	 * Relocate this eSRAM to a suitable location in the physical
+	 * memory map and enable it.
+	 */
+
+	/* Host Memory Bound Register P03h:R08h */
+	mov	$((MSG_PORT_HOST_BRIDGE << 16) | (HM_BOUND << 8)), %eax
+	mov	$(DRAM_BASE + DRAM_MAX_SIZE + ESRAM_SIZE), %edx
+	lea	1f, %esp
+	jmp	msg_port_write
+1:
+
+	/* eSRAM Block Page Control Register P05h:R82h */
+	mov	$((MSG_PORT_MEM_MGR << 16) | (ESRAM_BLK_CTRL << 8)), %eax
+	mov	$(ESRAM_BLOCK_MODE | (CONFIG_ESRAM_BASE >> 24)), %edx
+	lea	2f, %esp
+	jmp	msg_port_write
+2:
+
+	post_code(POST_CAR_CPU_CACHE)
+	jmp	car_init_ret
+
+msg_port_read:
+	/*
+	 * Parameter:
+	 *   eax[23:16] - Message Port ID
+	 *   eax[15:08] - Register Address
+	 *
+	 * Return Value:
+	 *   eax - Message Port Register value
+	 *
+	 * Return Address: esp
+	 */
+
+	or	$((MSG_OP_READ << 24) | MSG_BYTE_ENABLE), %eax
+	mov	%eax, %ebx
+
+	/* Write MCR B0:D0:F0:RD0 */
+	mov	$(PCI_CFG_EN | MSG_CTRL_REG), %eax
+	mov	$PCI_REG_ADDR, %dx
+	out	%eax, %dx
+	mov	$PCI_REG_DATA, %dx
+	mov	%ebx, %eax
+	out	%eax, %dx
+
+	/* Read MDR B0:D0:F0:RD4 */
+	mov	$(PCI_CFG_EN | MSG_DATA_REG), %eax
+	mov	$PCI_REG_ADDR, %dx
+	out	%eax, %dx
+	mov	$PCI_REG_DATA, %dx
+	in	%dx, %eax
+
+	jmp	*%esp
+
+msg_port_write:
+	/*
+	 * Parameter:
+	 *   eax[23:16] - Message Port ID
+	 *   eax[15:08] - Register Address
+	 *   edx        - Message Port Register value to write
+	 *
+	 * Return Address: esp
+	 */
+
+	or	$((MSG_OP_WRITE << 24) | MSG_BYTE_ENABLE), %eax
+	mov	%eax, %esi
+	mov	%edx, %edi
+
+	/* Write MDR B0:D0:F0:RD4 */
+	mov	$(PCI_CFG_EN | MSG_DATA_REG), %eax
+	mov	$PCI_REG_ADDR, %dx
+	out	%eax, %dx
+	mov	$PCI_REG_DATA, %dx
+	mov	%edi, %eax
+	out	%eax, %dx
+
+	/* Write MCR B0:D0:F0:RD0 */
+	mov	$(PCI_CFG_EN | MSG_CTRL_REG), %eax
+	mov	$PCI_REG_ADDR, %dx
+	out	%eax, %dx
+	mov	$PCI_REG_DATA, %dx
+	mov	%esi, %eax
+	out	%eax, %dx
+
+	jmp	*%esp
diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c
new file mode 100644
index 0000000..9cac846
--- /dev/null
+++ b/arch/x86/cpu/quark/dram.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/post.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/quark.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int mrc_configure_params(struct mrc_params *mrc_params)
+{
+	const void *blob = gd->fdt_blob;
+	int node;
+	int mrc_flags;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_QRK_MRC);
+	if (node < 0) {
+		debug("%s: Cannot find MRC node\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * TODO:
+	 *
+	 * We need support fast boot (MRC cache) in the future.
+	 *
+	 * Set boot mode to cold boot for now
+	 */
+	mrc_params->boot_mode = BM_COLD;
+
+	/*
+	 * TODO:
+	 *
+	 * We need determine ECC by pin strap state
+	 *
+	 * Disable ECC by default for now
+	 */
+	mrc_params->ecc_enables = 0;
+
+	mrc_flags = fdtdec_get_int(blob, node, "flags", 0);
+	if (mrc_flags & MRC_FLAG_SCRAMBLE_EN)
+		mrc_params->scrambling_enables = 1;
+	else
+		mrc_params->scrambling_enables = 0;
+
+	mrc_params->dram_width = fdtdec_get_int(blob, node, "dram-width", 0);
+	mrc_params->ddr_speed = fdtdec_get_int(blob, node, "dram-speed", 0);
+	mrc_params->ddr_type = fdtdec_get_int(blob, node, "dram-type", 0);
+
+	mrc_params->rank_enables = fdtdec_get_int(blob, node, "rank-mask", 0);
+	mrc_params->channel_enables = fdtdec_get_int(blob, node,
+		"chan-mask", 0);
+	mrc_params->channel_width = fdtdec_get_int(blob, node,
+		"chan-width", 0);
+	mrc_params->address_mode = fdtdec_get_int(blob, node, "addr-mode", 0);
+
+	mrc_params->refresh_rate = fdtdec_get_int(blob, node,
+		"refresh-rate", 0);
+	mrc_params->sr_temp_range = fdtdec_get_int(blob, node,
+		"sr-temp-range", 0);
+	mrc_params->ron_value = fdtdec_get_int(blob, node,
+		"ron-value", 0);
+	mrc_params->rtt_nom_value = fdtdec_get_int(blob, node,
+		"rtt-nom-value", 0);
+	mrc_params->rd_odt_value = fdtdec_get_int(blob, node,
+		"rd-odt-value", 0);
+
+	mrc_params->params.density = fdtdec_get_int(blob, node,
+		"dram-density", 0);
+	mrc_params->params.cl = fdtdec_get_int(blob, node, "dram-cl", 0);
+	mrc_params->params.ras = fdtdec_get_int(blob, node, "dram-ras", 0);
+	mrc_params->params.wtr = fdtdec_get_int(blob, node, "dram-wtr", 0);
+	mrc_params->params.rrd = fdtdec_get_int(blob, node, "dram-rrd", 0);
+	mrc_params->params.faw = fdtdec_get_int(blob, node, "dram-faw", 0);
+
+	debug("MRC dram_width %d\n", mrc_params->dram_width);
+	debug("MRC rank_enables %d\n", mrc_params->rank_enables);
+	debug("MRC ddr_speed %d\n", mrc_params->ddr_speed);
+	debug("MRC flags: %s\n",
+	      (mrc_params->scrambling_enables) ? "SCRAMBLE_EN" : "");
+
+	debug("MRC density=%d tCL=%d tRAS=%d tWTR=%d tRRD=%d tFAW=%d\n",
+	      mrc_params->params.density, mrc_params->params.cl,
+	      mrc_params->params.ras, mrc_params->params.wtr,
+	      mrc_params->params.rrd, mrc_params->params.faw);
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	struct mrc_params mrc_params;
+	int ret;
+
+	memset(&mrc_params, 0, sizeof(struct mrc_params));
+	ret = mrc_configure_params(&mrc_params);
+	if (ret)
+		return ret;
+
+	/* Set up the DRAM by calling the memory reference code */
+	mrc_init(&mrc_params);
+	if (mrc_params.status)
+		return -EIO;
+
+	gd->ram_size = mrc_params.mem_size;
+	post_code(POST_DRAM);
+
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = 0;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+}
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return gd->ram_size;
+}
diff --git a/arch/x86/cpu/quark/hte.c b/arch/x86/cpu/quark/hte.c
new file mode 100644
index 0000000..372815d
--- /dev/null
+++ b/arch/x86/cpu/quark/hte.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#include <common.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "hte.h"
+
+/**
+ * Enable HTE to detect all possible errors for the given training parameters
+ * (per-bit or full byte lane).
+ */
+static void hte_enable_all_errors(void)
+{
+	msg_port_write(HTE, 0x000200A2, 0xFFFFFFFF);
+	msg_port_write(HTE, 0x000200A3, 0x000000FF);
+	msg_port_write(HTE, 0x000200A4, 0x00000000);
+}
+
+/**
+ * Go and read the HTE register in order to find any error
+ *
+ * @return: The errors detected in the HTE status register
+ */
+static u32 hte_check_errors(void)
+{
+	return msg_port_read(HTE, 0x000200A7);
+}
+
+/**
+ * Wait until HTE finishes
+ */
+static void hte_wait_for_complete(void)
+{
+	u32 tmp;
+
+	ENTERFN();
+
+	do {} while ((msg_port_read(HTE, 0x00020012) & BIT30) != 0);
+
+	tmp = msg_port_read(HTE, 0x00020011);
+	tmp |= BIT9;
+	tmp &= ~(BIT12 | BIT13);
+	msg_port_write(HTE, 0x00020011, tmp);
+
+	LEAVEFN();
+}
+
+/**
+ * Clear registers related with errors in the HTE
+ */
+static void hte_clear_error_regs(void)
+{
+	u32 tmp;
+
+	/*
+	 * Clear all HTE errors and enable error checking
+	 * for burst and chunk.
+	 */
+	tmp = msg_port_read(HTE, 0x000200A1);
+	tmp |= BIT8;
+	msg_port_write(HTE, 0x000200A1, tmp);
+}
+
+/**
+ * Execute a basic single-cache-line memory write/read/verify test using simple
+ * constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
+ *
+ * See hte_basic_write_read() which is the external visible wrapper.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ *             assumed configuration is done and we just re-run the test
+ * @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+static u16 hte_basic_data_cmp(struct mrc_params *mrc_params, u32 addr,
+			      u8 first_run, u8 mode)
+{
+	u32 pattern;
+	u32 offset;
+
+	if (first_run) {
+		msg_port_write(HTE, 0x00020020, 0x01B10021);
+		msg_port_write(HTE, 0x00020021, 0x06000000);
+		msg_port_write(HTE, 0x00020022, addr >> 6);
+		msg_port_write(HTE, 0x00020062, 0x00800015);
+		msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
+		msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
+		msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
+		msg_port_write(HTE, 0x00020061, 0x00030008);
+
+		if (mode == WRITE_TRAIN)
+			pattern = 0xC33C0000;
+		else /* READ_TRAIN */
+			pattern = 0xAA5555AA;
+
+		for (offset = 0x80; offset <= 0x8F; offset++)
+			msg_port_write(HTE, offset, pattern);
+	}
+
+	msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
+	msg_port_write(HTE, 0x00020011, 0x00011000);
+	msg_port_write(HTE, 0x00020011, 0x00011100);
+
+	hte_wait_for_complete();
+
+	/*
+	 * Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
+	 * any bytelane errors.
+	 */
+	return (hte_check_errors() >> 8) & 0xFF;
+}
+
+/**
+ * Examine a single-cache-line memory with write/read/verify test using multiple
+ * data patterns (victim-aggressor algorithm).
+ *
+ * See hte_write_stress_bit_lanes() which is the external visible wrapper.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @loop_cnt: number of test iterations
+ * @seed_victim: victim data pattern seed
+ * @seed_aggressor: aggressor data pattern seed
+ * @victim_bit: should be 0 as auto-rotate feature is in use
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ *             assumed configuration is done and we just re-run the test
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+static u16 hte_rw_data_cmp(struct mrc_params *mrc_params, u32 addr,
+			   u8 loop_cnt, u32 seed_victim, u32 seed_aggressor,
+			   u8 victim_bit, u8 first_run)
+{
+	u32 offset;
+	u32 tmp;
+
+	if (first_run) {
+		msg_port_write(HTE, 0x00020020, 0x00910024);
+		msg_port_write(HTE, 0x00020023, 0x00810024);
+		msg_port_write(HTE, 0x00020021, 0x06070000);
+		msg_port_write(HTE, 0x00020024, 0x06070000);
+		msg_port_write(HTE, 0x00020022, addr >> 6);
+		msg_port_write(HTE, 0x00020025, addr >> 6);
+		msg_port_write(HTE, 0x00020062, 0x0000002A);
+		msg_port_write(HTE, 0x00020063, seed_victim);
+		msg_port_write(HTE, 0x00020064, seed_aggressor);
+		msg_port_write(HTE, 0x00020065, seed_victim);
+
+		/*
+		 * Write the pattern buffers to select the victim bit
+		 *
+		 * Start with bit0
+		 */
+		for (offset = 0x80; offset <= 0x8F; offset++) {
+			if ((offset % 8) == victim_bit)
+				msg_port_write(HTE, offset, 0x55555555);
+			else
+				msg_port_write(HTE, offset, 0xCCCCCCCC);
+		}
+
+		msg_port_write(HTE, 0x00020061, 0x00000000);
+		msg_port_write(HTE, 0x00020066, 0x03440000);
+		msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
+	}
+
+	tmp = 0x10001000 | (loop_cnt << 16);
+	msg_port_write(HTE, 0x00020011, tmp);
+	msg_port_write(HTE, 0x00020011, tmp | BIT8);
+
+	hte_wait_for_complete();
+
+	/*
+	 * Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for
+	 * any bytelane errors.
+	 */
+	return (hte_check_errors() >> 8) & 0xFF;
+}
+
+/**
+ * Use HW HTE engine to initialize or test all memory attached to a given DUNIT.
+ * If flag is MRC_MEM_INIT, this routine writes 0s to all memory locations to
+ * initialize ECC. If flag is MRC_MEM_TEST, this routine will send an 5AA55AA5
+ * pattern to all memory locations on the RankMask and then read it back.
+ * Then it sends an A55AA55A pattern to all memory locations on the RankMask
+ * and reads it back.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @flag: MRC_MEM_INIT or MRC_MEM_TEST
+ *
+ * @return: errors register showing HTE failures. Also prints out which rank
+ *          failed the HTE test if failure occurs. For rank detection to work,
+ *          the address map must be left in its default state. If MRC changes
+ *          the address map, this function must be modified to change it back
+ *          to default at the beginning, then restore it at the end.
+ */
+u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag)
+{
+	u32 offset;
+	int test_num;
+	int i;
+
+	/*
+	 * Clear out the error registers at the start of each memory
+	 * init or memory test run.
+	 */
+	hte_clear_error_regs();
+
+	msg_port_write(HTE, 0x00020062, 0x00000015);
+
+	for (offset = 0x80; offset <= 0x8F; offset++)
+		msg_port_write(HTE, offset, ((offset & 1) ? 0xA55A : 0x5AA5));
+
+	msg_port_write(HTE, 0x00020021, 0x00000000);
+	msg_port_write(HTE, 0x00020022, (mrc_params->mem_size >> 6) - 1);
+	msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
+	msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
+	msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
+	msg_port_write(HTE, 0x00020066, 0x03000000);
+
+	switch (flag) {
+	case MRC_MEM_INIT:
+		/*
+		 * Only 1 write pass through memory is needed
+		 * to initialize ECC
+		 */
+		test_num = 1;
+		break;
+	case MRC_MEM_TEST:
+		/* Write/read then write/read with inverted pattern */
+		test_num = 4;
+		break;
+	default:
+		DPF(D_INFO, "Unknown parameter for flag: %d\n", flag);
+		return 0xFFFFFFFF;
+	}
+
+	DPF(D_INFO, "hte_mem_init");
+
+	for (i = 0; i < test_num; i++) {
+		DPF(D_INFO, ".");
+
+		if (i == 0) {
+			msg_port_write(HTE, 0x00020061, 0x00000000);
+			msg_port_write(HTE, 0x00020020, 0x00110010);
+		} else if (i == 1) {
+			msg_port_write(HTE, 0x00020061, 0x00000000);
+			msg_port_write(HTE, 0x00020020, 0x00010010);
+		} else if (i == 2) {
+			msg_port_write(HTE, 0x00020061, 0x00010100);
+			msg_port_write(HTE, 0x00020020, 0x00110010);
+		} else {
+			msg_port_write(HTE, 0x00020061, 0x00010100);
+			msg_port_write(HTE, 0x00020020, 0x00010010);
+		}
+
+		msg_port_write(HTE, 0x00020011, 0x00111000);
+		msg_port_write(HTE, 0x00020011, 0x00111100);
+
+		hte_wait_for_complete();
+
+		/* If this is a READ pass, check for errors at the end */
+		if ((i % 2) == 1) {
+			/* Return immediately if error */
+			if (hte_check_errors())
+				break;
+		}
+	}
+
+	DPF(D_INFO, "done\n");
+
+	return hte_check_errors();
+}
+
+/**
+ * Execute a basic single-cache-line memory write/read/verify test using simple
+ * constant pattern, different for READ_TRAIN and WRITE_TRAIN modes.
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ *             assumed configuration is done and we just re-run the test
+ * @mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
+			 u8 first_run, u8 mode)
+{
+	u16 errors;
+
+	ENTERFN();
+
+	/* Enable all error reporting in preparation for HTE test */
+	hte_enable_all_errors();
+	hte_clear_error_regs();
+
+	errors = hte_basic_data_cmp(mrc_params, addr, first_run, mode);
+
+	LEAVEFN();
+
+	return errors;
+}
+
+/**
+ * Examine a single-cache-line memory with write/read/verify test using multiple
+ * data patterns (victim-aggressor algorithm).
+ *
+ * @mrc_params: host structure for all MRC global data
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ *             assumed configuration is done and we just re-run the test
+ *
+ * @return: byte lane failure on each bit (for Quark only bit0 and bit1)
+ */
+u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
+			       u32 addr, u8 first_run)
+{
+	u16 errors;
+	u8 victim_bit = 0;
+
+	ENTERFN();
+
+	/* Enable all error reporting in preparation for HTE test */
+	hte_enable_all_errors();
+	hte_clear_error_regs();
+
+	/*
+	 * Loop through each bit in the bytelane.
+	 *
+	 * Each pass creates a victim bit while keeping all other bits the same
+	 * as aggressors. AVN HTE adds an auto-rotate feature which allows us
+	 * to program the entire victim/aggressor sequence in 1 step.
+	 *
+	 * The victim bit rotates on each pass so no need to have software
+	 * implement a victim bit loop like on VLV.
+	 */
+	errors = hte_rw_data_cmp(mrc_params, addr, HTE_LOOP_CNT,
+				 HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED,
+				 victim_bit, first_run);
+
+	LEAVEFN();
+
+	return errors;
+}
+
+/**
+ * Execute a basic single-cache-line memory write or read.
+ * This is just for receive enable / fine write-levelling purpose.
+ *
+ * @addr: memory adress being tested (must hit specific channel/rank)
+ * @first_run: if set then the HTE registers are configured, otherwise it is
+ *             assumed configuration is done and we just re-run the test
+ * @is_write: when non-zero memory write operation executed, otherwise read
+ */
+void hte_mem_op(u32 addr, u8 first_run, u8 is_write)
+{
+	u32 offset;
+	u32 tmp;
+
+	hte_enable_all_errors();
+	hte_clear_error_regs();
+
+	if (first_run) {
+		tmp = is_write ? 0x01110021 : 0x01010021;
+		msg_port_write(HTE, 0x00020020, tmp);
+
+		msg_port_write(HTE, 0x00020021, 0x06000000);
+		msg_port_write(HTE, 0x00020022, addr >> 6);
+		msg_port_write(HTE, 0x00020062, 0x00800015);
+		msg_port_write(HTE, 0x00020063, 0xAAAAAAAA);
+		msg_port_write(HTE, 0x00020064, 0xCCCCCCCC);
+		msg_port_write(HTE, 0x00020065, 0xF0F0F0F0);
+		msg_port_write(HTE, 0x00020061, 0x00030008);
+
+		for (offset = 0x80; offset <= 0x8F; offset++)
+			msg_port_write(HTE, offset, 0xC33C0000);
+	}
+
+	msg_port_write(HTE, 0x000200A1, 0xFFFF1000);
+	msg_port_write(HTE, 0x00020011, 0x00011000);
+	msg_port_write(HTE, 0x00020011, 0x00011100);
+
+	hte_wait_for_complete();
+}
diff --git a/arch/x86/cpu/quark/hte.h b/arch/x86/cpu/quark/hte.h
new file mode 100644
index 0000000..6577796
--- /dev/null
+++ b/arch/x86/cpu/quark/hte.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef _HTE_H_
+#define _HTE_H_
+
+enum {
+	MRC_MEM_INIT,
+	MRC_MEM_TEST
+};
+
+enum {
+	READ_TRAIN,
+	WRITE_TRAIN
+};
+
+/*
+ * EXP_LOOP_CNT field of HTE_CMD_CTL
+ *
+ * This CANNOT be less than 4!
+ */
+#define HTE_LOOP_CNT		5
+
+/* random seed for victim */
+#define HTE_LFSR_VICTIM_SEED	0xF294BA21
+
+/* random seed for aggressor */
+#define HTE_LFSR_AGRESSOR_SEED	0xEBA7492D
+
+u32 hte_mem_init(struct mrc_params *mrc_params, u8 flag);
+u16 hte_basic_write_read(struct mrc_params *mrc_params, u32 addr,
+			 u8 first_run, u8 mode);
+u16 hte_write_stress_bit_lanes(struct mrc_params *mrc_params,
+			       u32 addr, u8 first_run);
+void hte_mem_op(u32 addr, u8 first_run, u8 is_write);
+
+#endif /* _HTE_H_ */
diff --git a/arch/x86/cpu/quark/mrc.c b/arch/x86/cpu/quark/mrc.c
new file mode 100644
index 0000000..7eb34c5
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+/*
+ * This is the main Quark Memory Reference Code (MRC)
+ *
+ * These functions are generic and should work for any Quark-based board.
+ *
+ * MRC requires two data structures to be passed in which are initialized by
+ * mrc_adjust_params().
+ *
+ * The basic flow is as follows:
+ * 01) Check for supported DDR speed configuration
+ * 02) Set up Memory Manager buffer as pass-through (POR)
+ * 03) Set Channel Interleaving Mode and Channel Stride to the most aggressive
+ *     setting possible
+ * 04) Set up the Memory Controller logic
+ * 05) Set up the DDR_PHY logic
+ * 06) Initialise the DRAMs (JEDEC)
+ * 07) Perform the Receive Enable Calibration algorithm
+ * 08) Perform the Write Leveling algorithm
+ * 09) Perform the Read Training algorithm (includes internal Vref)
+ * 10) Perform the Write Training algorithm
+ * 11) Set Channel Interleaving Mode and Channel Stride to the desired settings
+ *
+ * DRAM unit configuration based on Valleyview MRC.
+ */
+
+#include <common.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "smc.h"
+
+static const struct mem_init init[] = {
+	{ 0x0101, BM_COLD | BM_FAST | BM_WARM | BM_S3, clear_self_refresh       },
+	{ 0x0200, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_timing_control  },
+	{ 0x0103, BM_COLD | BM_FAST                  , prog_decode_before_jedec },
+	{ 0x0104, BM_COLD | BM_FAST                  , perform_ddr_reset        },
+	{ 0x0300, BM_COLD | BM_FAST           | BM_S3, ddrphy_init              },
+	{ 0x0400, BM_COLD | BM_FAST                  , perform_jedec_init       },
+	{ 0x0105, BM_COLD | BM_FAST                  , set_ddr_init_complete    },
+	{ 0x0106,           BM_FAST | BM_WARM | BM_S3, restore_timings          },
+	{ 0x0106, BM_COLD                            , default_timings          },
+	{ 0x0500, BM_COLD                            , rcvn_cal                 },
+	{ 0x0600, BM_COLD                            , wr_level                 },
+	{ 0x0120, BM_COLD                            , prog_page_ctrl           },
+	{ 0x0700, BM_COLD                            , rd_train                 },
+	{ 0x0800, BM_COLD                            , wr_train                 },
+	{ 0x010b, BM_COLD                            , store_timings            },
+	{ 0x010c, BM_COLD | BM_FAST | BM_WARM | BM_S3, enable_scrambling        },
+	{ 0x010d, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_ddr_control         },
+	{ 0x010e, BM_COLD | BM_FAST | BM_WARM | BM_S3, prog_dra_drb             },
+	{ 0x010f,                     BM_WARM | BM_S3, perform_wake             },
+	{ 0x0110, BM_COLD | BM_FAST | BM_WARM | BM_S3, change_refresh_period    },
+	{ 0x0111, BM_COLD | BM_FAST | BM_WARM | BM_S3, set_auto_refresh         },
+	{ 0x0112, BM_COLD | BM_FAST | BM_WARM | BM_S3, ecc_enable               },
+	{ 0x0113, BM_COLD | BM_FAST                  , memory_test              },
+	{ 0x0114, BM_COLD | BM_FAST | BM_WARM | BM_S3, lock_registers           }
+};
+
+/* Adjust configuration parameters before initialization sequence */
+static void mrc_adjust_params(struct mrc_params *mrc_params)
+{
+	const struct dram_params *dram_params;
+	uint8_t dram_width;
+	uint32_t rank_enables;
+	uint32_t channel_width;
+
+	ENTERFN();
+
+	/* initially expect success */
+	mrc_params->status = MRC_SUCCESS;
+
+	dram_width = mrc_params->dram_width;
+	rank_enables = mrc_params->rank_enables;
+	channel_width = mrc_params->channel_width;
+
+	/*
+	 * Setup board layout (must be reviewed as is selecting static timings)
+	 * 0 == R0 (DDR3 x16), 1 == R1 (DDR3 x16),
+	 * 2 == DV (DDR3 x8), 3 == SV (DDR3 x8).
+	 */
+	if (dram_width == X8)
+		mrc_params->board_id = 2;	/* select x8 layout */
+	else
+		mrc_params->board_id = 0;	/* select x16 layout */
+
+	/* initially no memory */
+	mrc_params->mem_size = 0;
+
+	/* begin of channel settings */
+	dram_params = &mrc_params->params;
+
+	/*
+	 * Determine column bits:
+	 *
+	 * Column: 11 for 8Gbx8, else 10
+	 */
+	mrc_params->column_bits[0] =
+		((dram_params[0].density == 4) &&
+		(dram_width == X8)) ? (11) : (10);
+
+	/*
+	 * Determine row bits:
+	 *
+	 * 512Mbx16=12 512Mbx8=13
+	 * 1Gbx16=13   1Gbx8=14
+	 * 2Gbx16=14   2Gbx8=15
+	 * 4Gbx16=15   4Gbx8=16
+	 * 8Gbx16=16   8Gbx8=16
+	 */
+	mrc_params->row_bits[0] = 12 + (dram_params[0].density) +
+		(((dram_params[0].density < 4) &&
+		(dram_width == X8)) ? (1) : (0));
+
+	/*
+	 * Determine per-channel memory size:
+	 *
+	 * (For 2 RANKs, multiply by 2)
+	 * (For 16 bit data bus, divide by 2)
+	 *
+	 * DENSITY WIDTH MEM_AVAILABLE
+	 * 512Mb   x16   0x008000000 ( 128MB)
+	 * 512Mb   x8    0x010000000 ( 256MB)
+	 * 1Gb     x16   0x010000000 ( 256MB)
+	 * 1Gb     x8    0x020000000 ( 512MB)
+	 * 2Gb     x16   0x020000000 ( 512MB)
+	 * 2Gb     x8    0x040000000 (1024MB)
+	 * 4Gb     x16   0x040000000 (1024MB)
+	 * 4Gb     x8    0x080000000 (2048MB)
+	 */
+	mrc_params->channel_size[0] = (1 << dram_params[0].density);
+	mrc_params->channel_size[0] *= (dram_width == X8) ? 2 : 1;
+	mrc_params->channel_size[0] *= (rank_enables == 0x3) ? 2 : 1;
+	mrc_params->channel_size[0] *= (channel_width == X16) ? 1 : 2;
+
+	/* Determine memory size (convert number of 64MB/512Mb units) */
+	mrc_params->mem_size += mrc_params->channel_size[0] << 26;
+
+	LEAVEFN();
+}
+
+static void mrc_mem_init(struct mrc_params *mrc_params)
+{
+	int i;
+
+	ENTERFN();
+
+	/* MRC started */
+	mrc_post_code(0x01, 0x00);
+
+	if (mrc_params->boot_mode != BM_COLD) {
+		if (mrc_params->ddr_speed != mrc_params->timings.ddr_speed) {
+			/* full training required as frequency changed */
+			mrc_params->boot_mode = BM_COLD;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(init); i++) {
+		uint64_t my_tsc;
+
+		if (mrc_params->boot_mode & init[i].boot_path) {
+			uint8_t major = init[i].post_code >> 8 & 0xff;
+			uint8_t minor = init[i].post_code >> 0 & 0xff;
+			mrc_post_code(major, minor);
+
+			my_tsc = rdtsc();
+			init[i].init_fn(mrc_params);
+			DPF(D_TIME, "Execution time %llx", rdtsc() - my_tsc);
+		}
+	}
+
+	/* display the timings */
+	print_timings(mrc_params);
+
+	/* MRC complete */
+	mrc_post_code(0x01, 0xff);
+
+	LEAVEFN();
+}
+
+void mrc_init(struct mrc_params *mrc_params)
+{
+	ENTERFN();
+
+	DPF(D_INFO, "MRC Version %04x %s %s\n", MRC_VERSION,
+	    __DATE__, __TIME__);
+
+	/* Set up the data structures used by mrc_mem_init() */
+	mrc_adjust_params(mrc_params);
+
+	/* Initialize system memory */
+	mrc_mem_init(mrc_params);
+
+	LEAVEFN();
+}
diff --git a/arch/x86/cpu/quark/mrc_util.c b/arch/x86/cpu/quark/mrc_util.c
new file mode 100644
index 0000000..3a79ae5
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc_util.c
@@ -0,0 +1,1475 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#include <common.h>
+#include <asm/arch/device.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "hte.h"
+#include "smc.h"
+
+static const uint8_t vref_codes[64] = {
+	/* lowest to highest */
+	0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
+	0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
+	0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28,
+	0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+};
+
+void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
+{
+	msg_port_write(unit, addr,
+		       (msg_port_read(unit, addr) & ~(mask)) |
+		       ((data) & (mask)));
+}
+
+void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
+{
+	msg_port_alt_write(unit, addr,
+			   (msg_port_alt_read(unit, addr) & ~(mask)) |
+			   ((data) & (mask)));
+}
+
+void mrc_post_code(uint8_t major, uint8_t minor)
+{
+	/* send message to UART */
+	DPF(D_INFO, "POST: 0x%01x%02x\n", major, minor);
+
+	/* error check */
+	if (major == 0xee)
+		hang();
+}
+
+/* Delay number of nanoseconds */
+void delay_n(uint32_t ns)
+{
+	/* 1000 MHz clock has 1ns period --> no conversion required */
+	uint64_t final_tsc = rdtsc();
+
+	final_tsc += ((get_tbclk_mhz() * ns) / 1000);
+
+	while (rdtsc() < final_tsc)
+		;
+}
+
+/* Delay number of microseconds */
+void delay_u(uint32_t ms)
+{
+	/* 64-bit math is not an option, just use loops */
+	while (ms--)
+		delay_n(1000);
+}
+
+/* Select Memory Manager as the source for PRI interface */
+void select_mem_mgr(void)
+{
+	u32 dco;
+
+	ENTERFN();
+
+	dco = msg_port_read(MEM_CTLR, DCO);
+	dco &= ~BIT28;
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	LEAVEFN();
+}
+
+/* Select HTE as the source for PRI interface */
+void select_hte(void)
+{
+	u32 dco;
+
+	ENTERFN();
+
+	dco = msg_port_read(MEM_CTLR, DCO);
+	dco |= BIT28;
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	LEAVEFN();
+}
+
+/*
+ * Send DRAM command
+ * data should be formated using DCMD_Xxxx macro or emrsXCommand structure
+ */
+void dram_init_command(uint32_t data)
+{
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, data);
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, 0);
+	msg_port_setup(MSG_OP_DRAM_INIT, MEM_CTLR, 0);
+
+	DPF(D_REGWR, "WR32 %03X %08X %08X\n", MEM_CTLR, 0, data);
+}
+
+/* Send DRAM wake command using special MCU side-band WAKE opcode */
+void dram_wake_command(void)
+{
+	ENTERFN();
+
+	msg_port_setup(MSG_OP_DRAM_WAKE, MEM_CTLR, 0);
+
+	LEAVEFN();
+}
+
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+	/* send message to UART */
+	DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);
+}
+
+/*
+ * This function will program the RCVEN delays
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_rcvn(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n",
+	    channel, rank, byte_lane, pi_count);
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = (byte_lane & BIT0) ? (BIT23 | BIT22 | BIT21 | BIT20) :
+		(BIT11 | BIT10 | BIT9 | BIT8);
+	temp = (byte_lane & BIT0) ? ((pi_count / HALF_CLK) << 20) :
+		((pi_count / HALF_CLK) << 8);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+	temp = pi_count << 24;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * BL0/1 -> B01DBCTL1[08/11] (+1 select)
+	 * BL0/1 -> B01DBCTL1[02/05] (enable)
+	 */
+	reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= (byte_lane & BIT0) ? BIT5 : BIT2;
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= (byte_lane & BIT0) ? BIT11 : BIT8;
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F) {
+		training_message(channel, rank, byte_lane);
+		mrc_post_code(0xee, 0xe0);
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the current RCVEN delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= (byte_lane & BIT0) ? 20 : 8;
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = temp * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 24;
+	temp &= 0x3F;
+
+	/* Adjust PI_COUNT */
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the RDQS delays based on an absolute
+ * amount of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_rdqs(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+	DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n",
+	    channel, rank, byte_lane, pi_count);
+
+	/*
+	 * PI (1/128 MCLK)
+	 * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+	 * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+	 */
+	reg = (byte_lane & BIT0) ? B1RXDQSPICODE : B0RXDQSPICODE;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	msk = (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+	temp = pi_count << 0;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check (shouldn't go above 0x3F) */
+	if (pi_count > 0x47) {
+		training_message(channel, rank, byte_lane);
+		mrc_post_code(0xee, 0xe1);
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the current RDQS delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * PI (1/128 MCLK)
+	 * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
+	 * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
+	 */
+	reg = (byte_lane & BIT0) ? B1RXDQSPICODE : B0RXDQSPICODE;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	temp = msg_port_alt_read(DDRPHY, reg);
+
+	/* Adjust PI_COUNT */
+	pi_count = temp & 0x7F;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the WDQS delays based on an absolute
+ * amount of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wdqs(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n",
+	    channel, rank, byte_lane, pi_count);
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = (byte_lane & BIT0) ? (BIT19 | BIT18 | BIT17 | BIT16) :
+		(BIT7 | BIT6 | BIT5 | BIT4);
+	temp = pi_count / HALF_CLK;
+	temp <<= (byte_lane & BIT0) ? 16 : 4;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16);
+	temp = pi_count << 16;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * BL0/1 -> B01DBCTL1[07/10] (+1 select)
+	 * BL0/1 -> B01DBCTL1[01/04] (enable)
+	 */
+	reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= (byte_lane & BIT0) ? BIT4 : BIT1;
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= (byte_lane & BIT0) ? BIT10 : BIT7;
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F) {
+		training_message(channel, rank, byte_lane);
+		mrc_post_code(0xee, 0xe2);
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WDQS delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= (byte_lane & BIT0) ? 16 : 4;
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = (temp * HALF_CLK);
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 16;
+	temp &= 0x3F;
+
+	/* Adjust PI_COUNT */
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the WDQ delays based on an absolute
+ * number of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wdq(uint8_t channel, uint8_t rank,
+	     uint8_t byte_lane, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n",
+	    channel, rank, byte_lane, pi_count);
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = (byte_lane & BIT0) ? (BIT15 | BIT14 | BIT13 | BIT12) :
+		(BIT3 | BIT2 | BIT1 | BIT0);
+	temp = pi_count / HALF_CLK;
+	temp <<= (byte_lane & BIT0) ? 12 : 0;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	msk = (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+	temp = pi_count << 8;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * BL0/1 -> B01DBCTL1[06/09] (+1 select)
+	 * BL0/1 -> B01DBCTL1[00/03] (enable)
+	 */
+	reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= (byte_lane & BIT0) ? BIT3 : BIT0;
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= (byte_lane & BIT0) ? BIT9 : BIT6;
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F) {
+		training_message(channel, rank, byte_lane);
+		mrc_post_code(0xee, 0xe3);
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WDQ delay on the given
+ * channel, rank, byte_lane as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
+	 * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
+	 */
+	reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= (byte_lane & BIT0) ? (12) : (0);
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = temp * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
+	 * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
+	 */
+	reg = (byte_lane & BIT0) ? B1DLLPICODER0 : B0DLLPICODER0;
+	reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) +
+		(channel * DDRIODQ_CH_OFFSET));
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 8;
+	temp &= 0x3F;
+
+	/* Adjust PI_COUNT */
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the WCMD delays based on an absolute
+ * number of PIs.
+ */
+void set_wcmd(uint8_t channel, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CMDPTRREG[11:08] (0x0-0xF)
+	 */
+	reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	msk = (BIT11 | BIT10 | BIT9 | BIT8);
+	temp = pi_count / HALF_CLK;
+	temp <<= 8;
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+	 * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+	 * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+	 * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+	 * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+	 * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+	 * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+	 * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+	 */
+	reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+
+	msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+		BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+		BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+		BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+
+	temp = (pi_count << 24) | (pi_count << 16) |
+		(pi_count << 8) | (pi_count << 0);
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = CMDDLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);	/* PO */
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * CMDCFGREG0[17] (+1 select)
+	 * CMDCFGREG0[16] (enable)
+	 */
+	reg = CMDCFGREG0 + (channel * DDRIOCCC_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= BIT16;
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= BIT17;
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F)
+		mrc_post_code(0xee, 0xe4);
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WCMD delay on the given
+ * channel as an absolute PI count.
+ */
+uint32_t get_wcmd(uint8_t channel)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CMDPTRREG[11:08] (0x0-0xF)
+	 */
+	reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 8;
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = temp * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
+	 * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
+	 * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
+	 * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
+	 * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
+	 * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
+	 * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
+	 * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
+	 */
+	reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 16;
+	temp &= 0x3F;
+
+	/* Adjust PI_COUNT */
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the WCLK delays based on an absolute
+ * number of PIs.
+ */
+void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+	 * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+	 */
+	reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	msk = (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+	temp = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+	 * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+	 */
+	reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
+	reg += (channel * DDRIOCCC_CH_OFFSET);
+	msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+		BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
+	temp = (pi_count << 16) | (pi_count << 8);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = rank ? ECCB1DLLPICODER1 : ECCB1DLLPICODER1;
+	reg += (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = rank ? ECCB1DLLPICODER2 : ECCB1DLLPICODER2;
+	reg += (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = rank ? ECCB1DLLPICODER3 : ECCB1DLLPICODER3;
+	reg += (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * CCCFGREG1[11:08] (+1 select)
+	 * CCCFGREG1[03:00] (enable)
+	 */
+	reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= (BIT3 | BIT2 | BIT1 | BIT0);
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= (BIT11 | BIT10 | BIT9 | BIT8);
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F)
+		mrc_post_code(0xee, 0xe5);
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the amout of WCLK delay on the given
+ * channel, rank as an absolute PI count.
+ */
+uint32_t get_wclk(uint8_t channel, uint8_t rank)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
+	 * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
+	 */
+	reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= rank ? 12 : 8;
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = temp * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
+	 * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
+	 */
+	reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
+	reg += (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= rank ? 16 : 8;
+	temp &= 0x3F;
+
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the WCTL delays based on an absolute
+ * number of PIs.
+ *
+ * (currently doesn't comprehend rank)
+ */
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count)
+{
+	uint32_t reg;
+	uint32_t msk;
+	uint32_t temp;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CCPTRREG[31:28] (0x0-0xF)
+	 * CCPTRREG[27:24] (0x0-0xF)
+	 */
+	reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	msk = (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+	temp = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* Adjust PI_COUNT */
+	pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+	 * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+	 */
+	reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
+	msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+	temp = (pi_count << 24);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = ECCB1DLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = ECCB1DLLPICODER2 + (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+	reg = ECCB1DLLPICODER3 + (channel * DDRIOCCC_CH_OFFSET);
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/*
+	 * DEADBAND
+	 * CCCFGREG1[13:12] (+1 select)
+	 * CCCFGREG1[05:04] (enable)
+	 */
+	reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
+	msk = 0x00;
+	temp = 0x00;
+
+	/* enable */
+	msk |= (BIT5 | BIT4);
+	if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
+		temp |= msk;
+
+	/* select */
+	msk |= (BIT13 | BIT12);
+	if (pi_count < EARLY_DB)
+		temp |= msk;
+
+	mrc_alt_write_mask(DDRPHY, reg, temp, msk);
+
+	/* error check */
+	if (pi_count > 0x3F)
+		mrc_post_code(0xee, 0xe6);
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the amount of WCTL delay on the given
+ * channel, rank as an absolute PI count.
+ *
+ * (currently doesn't comprehend rank)
+ */
+uint32_t get_wctl(uint8_t channel, uint8_t rank)
+{
+	uint32_t reg;
+	uint32_t temp;
+	uint32_t pi_count;
+
+	ENTERFN();
+
+	/*
+	 * RDPTR (1/2 MCLK, 64 PIs)
+	 * CCPTRREG[31:28] (0x0-0xF)
+	 * CCPTRREG[27:24] (0x0-0xF)
+	 */
+	reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 24;
+	temp &= 0xF;
+
+	/* Adjust PI_COUNT */
+	pi_count = temp * HALF_CLK;
+
+	/*
+	 * PI (1/64 MCLK, 1 PIs)
+	 * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+	 * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
+	 */
+	reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
+	temp = msg_port_alt_read(DDRPHY, reg);
+	temp >>= 24;
+	temp &= 0x3F;
+
+	/* Adjust PI_COUNT */
+	pi_count += temp;
+
+	LEAVEFN();
+
+	return pi_count;
+}
+
+/*
+ * This function will program the internal Vref setting in a given
+ * byte lane in a given channel.
+ */
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting)
+{
+	uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
+
+	ENTERFN();
+
+	DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n",
+	    channel, byte_lane, setting);
+
+	mrc_alt_write_mask(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) +
+		((byte_lane >> 1) * DDRIODQ_BL_OFFSET)),
+		(vref_codes[setting] << 2),
+		(BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+
+	/*
+	 * need to wait ~300ns for Vref to settle
+	 * (check that this is necessary)
+	 */
+	delay_n(300);
+
+	/* ??? may need to clear pointers ??? */
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return the internal Vref setting for the given
+ * channel, byte_lane.
+ */
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane)
+{
+	uint8_t j;
+	uint32_t ret_val = sizeof(vref_codes) / 2;
+	uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
+	uint32_t temp;
+
+	ENTERFN();
+
+	temp = msg_port_alt_read(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) +
+		((byte_lane >> 1) * DDRIODQ_BL_OFFSET)));
+	temp >>= 2;
+	temp &= 0x3F;
+
+	for (j = 0; j < sizeof(vref_codes); j++) {
+		if (vref_codes[j] == temp) {
+			ret_val = j;
+			break;
+		}
+	}
+
+	LEAVEFN();
+
+	return ret_val;
+}
+
+/*
+ * This function will return a 32-bit address in the desired
+ * channel and rank.
+ */
+uint32_t get_addr(uint8_t channel, uint8_t rank)
+{
+	uint32_t offset = 0x02000000;	/* 32MB */
+
+	/* Begin product specific code */
+	if (channel > 0) {
+		DPF(D_ERROR, "ILLEGAL CHANNEL\n");
+		DEAD_LOOP();
+	}
+
+	if (rank > 1) {
+		DPF(D_ERROR, "ILLEGAL RANK\n");
+		DEAD_LOOP();
+	}
+
+	/* use 256MB lowest density as per DRP == 0x0003 */
+	offset += rank * (256 * 1024 * 1024);
+
+	return offset;
+}
+
+/*
+ * This function will sample the DQTRAINSTS registers in the given
+ * channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.
+ *
+ * It will return an encoded 32-bit date in which each bit corresponds to
+ * the sampled value on the byte lane.
+ */
+uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
+		    uint8_t rank, bool rcvn)
+{
+	uint8_t j;	/* just a counter */
+	uint8_t bl;	/* which BL in the module (always 2 per module) */
+	uint8_t bl_grp;	/* which BL module */
+	/* byte lane divisor */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+	uint32_t msk[2];	/* BLx in module */
+	/* DQTRAINSTS register contents for each sample */
+	uint32_t sampled_val[SAMPLE_SIZE];
+	uint32_t num_0s;	/* tracks the number of '0' samples */
+	uint32_t num_1s;	/* tracks the number of '1' samples */
+	uint32_t ret_val = 0x00;	/* assume all '0' samples */
+	uint32_t address = get_addr(channel, rank);
+
+	/* initialise msk[] */
+	msk[0] = rcvn ? BIT1 : BIT9;	/* BL0 */
+	msk[1] = rcvn ? BIT0 : BIT8;	/* BL1 */
+
+	/* cycle through each byte lane group */
+	for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++) {
+		/* take SAMPLE_SIZE samples */
+		for (j = 0; j < SAMPLE_SIZE; j++) {
+			hte_mem_op(address, mrc_params->first_run,
+				   rcvn ? 0 : 1);
+			mrc_params->first_run = 0;
+
+			/*
+			 * record the contents of the proper
+			 * DQTRAINSTS register
+			 */
+			sampled_val[j] = msg_port_alt_read(DDRPHY,
+				(DQTRAINSTS +
+				(bl_grp * DDRIODQ_BL_OFFSET) +
+				(channel * DDRIODQ_CH_OFFSET)));
+		}
+
+		/*
+		 * look for a majority value (SAMPLE_SIZE / 2) + 1
+		 * on the byte lane and set that value in the corresponding
+		 * ret_val bit
+		 */
+		for (bl = 0; bl < 2; bl++) {
+			num_0s = 0x00;	/* reset '0' tracker for byte lane */
+			num_1s = 0x00;	/* reset '1' tracker for byte lane */
+			for (j = 0; j < SAMPLE_SIZE; j++) {
+				if (sampled_val[j] & msk[bl])
+					num_1s++;
+				else
+					num_0s++;
+			}
+		if (num_1s > num_0s)
+			ret_val |= (1 << (bl + (bl_grp * 2)));
+		}
+	}
+
+	/*
+	 * "ret_val.0" contains the status of BL0
+	 * "ret_val.1" contains the status of BL1
+	 * "ret_val.2" contains the status of BL2
+	 * etc.
+	 */
+	return ret_val;
+}
+
+/* This function will find the rising edge transition on RCVN or WDQS */
+void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
+		      uint8_t channel, uint8_t rank, bool rcvn)
+{
+	bool all_edges_found;	/* determines stop condition */
+	bool direction[NUM_BYTE_LANES];	/* direction indicator */
+	uint8_t sample;	/* sample counter */
+	uint8_t bl;	/* byte lane counter */
+	/* byte lane divisor */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+	uint32_t sample_result[SAMPLE_CNT];	/* results of sample_dqs() */
+	uint32_t temp;
+	uint32_t transition_pattern;
+
+	ENTERFN();
+
+	/* select hte and request initial configuration */
+	select_hte();
+	mrc_params->first_run = 1;
+
+	/* Take 3 sample points (T1,T2,T3) to obtain a transition pattern */
+	for (sample = 0; sample < SAMPLE_CNT; sample++) {
+		/* program the desired delays for sample */
+		for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+			/* increase sample delay by 26 PI (0.2 CLK) */
+			if (rcvn) {
+				set_rcvn(channel, rank, bl,
+					 delay[bl] + (sample * SAMPLE_DLY));
+			} else {
+				set_wdqs(channel, rank, bl,
+					 delay[bl] + (sample * SAMPLE_DLY));
+			}
+		}
+
+		/* take samples (Tsample_i) */
+		sample_result[sample] = sample_dqs(mrc_params,
+			channel, rank, rcvn);
+
+		DPF(D_TRN,
+		    "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",
+		    (rcvn ? "RCVN" : "WDQS"), channel, rank, sample,
+		    sample * SAMPLE_DLY, sample_result[sample]);
+	}
+
+	/*
+	 * This pattern will help determine where we landed and ultimately
+	 * how to place RCVEN/WDQS.
+	 */
+	for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+		/* build transition_pattern (MSB is 1st sample) */
+		transition_pattern = 0;
+		for (sample = 0; sample < SAMPLE_CNT; sample++) {
+			transition_pattern |=
+				((sample_result[sample] & (1 << bl)) >> bl) <<
+				(SAMPLE_CNT - 1 - sample);
+		}
+
+		DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);
+
+		/*
+		 * set up to look for rising edge based on
+		 * transition_pattern
+		 */
+		switch (transition_pattern) {
+		case 0:	/* sampled 0->0->0 */
+			/* move forward from T3 looking for 0->1 */
+			delay[bl] += 2 * SAMPLE_DLY;
+			direction[bl] = FORWARD;
+			break;
+		case 1:	/* sampled 0->0->1 */
+		case 5:	/* sampled 1->0->1 (bad duty cycle) *HSD#237503* */
+			/* move forward from T2 looking for 0->1 */
+			delay[bl] += 1 * SAMPLE_DLY;
+			direction[bl] = FORWARD;
+			break;
+		case 2:	/* sampled 0->1->0 (bad duty cycle) *HSD#237503* */
+		case 3:	/* sampled 0->1->1 */
+			/* move forward from T1 looking for 0->1 */
+			delay[bl] += 0 * SAMPLE_DLY;
+			direction[bl] = FORWARD;
+			break;
+		case 4:	/* sampled 1->0->0 (assumes BL8, HSD#234975) */
+			/* move forward from T3 looking for 0->1 */
+			delay[bl] += 2 * SAMPLE_DLY;
+			direction[bl] = FORWARD;
+			break;
+		case 6:	/* sampled 1->1->0 */
+		case 7:	/* sampled 1->1->1 */
+			/* move backward from T1 looking for 1->0 */
+			delay[bl] += 0 * SAMPLE_DLY;
+			direction[bl] = BACKWARD;
+			break;
+		default:
+			mrc_post_code(0xee, 0xee);
+			break;
+		}
+
+		/* program delays */
+		if (rcvn)
+			set_rcvn(channel, rank, bl, delay[bl]);
+		else
+			set_wdqs(channel, rank, bl, delay[bl]);
+	}
+
+	/*
+	 * Based on the observed transition pattern on the byte lane,
+	 * begin looking for a rising edge with single PI granularity.
+	 */
+	do {
+		all_edges_found = true;	/* assume all byte lanes passed */
+		/* take a sample */
+		temp = sample_dqs(mrc_params, channel, rank, rcvn);
+		/* check all each byte lane for proper edge */
+		for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+			if (temp & (1 << bl)) {
+				/* sampled "1" */
+				if (direction[bl] == BACKWARD) {
+					/*
+					 * keep looking for edge
+					 * on this byte lane
+					 */
+					all_edges_found = false;
+					delay[bl] -= 1;
+					if (rcvn) {
+						set_rcvn(channel, rank,
+							 bl, delay[bl]);
+					} else {
+						set_wdqs(channel, rank,
+							 bl, delay[bl]);
+					}
+				}
+			} else {
+				/* sampled "0" */
+				if (direction[bl] == FORWARD) {
+					/*
+					 * keep looking for edge
+					 * on this byte lane
+					 */
+					all_edges_found = false;
+					delay[bl] += 1;
+					if (rcvn) {
+						set_rcvn(channel, rank,
+							 bl, delay[bl]);
+					} else {
+						set_wdqs(channel, rank,
+							 bl, delay[bl]);
+					}
+				}
+			}
+		}
+	} while (!all_edges_found);
+
+	/* restore DDR idle state */
+	dram_init_command(DCMD_PREA(rank));
+
+	DPF(D_TRN, "Delay %03X %03X %03X %03X\n",
+	    delay[0], delay[1], delay[2], delay[3]);
+
+	LEAVEFN();
+}
+
+/*
+ * This function will return a 32 bit mask that will be used to
+ * check for byte lane failures.
+ */
+uint32_t byte_lane_mask(struct mrc_params *mrc_params)
+{
+	uint32_t j;
+	uint32_t ret_val = 0x00;
+
+	/*
+	 * set ret_val based on NUM_BYTE_LANES such that you will check
+	 * only BL0 in result
+	 *
+	 * (each bit in result represents a byte lane)
+	 */
+	for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)
+		ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));
+
+	/*
+	 * HSD#235037
+	 * need to adjust the mask for 16-bit mode
+	 */
+	if (mrc_params->channel_width == X16)
+		ret_val |= (ret_val << 2);
+
+	return ret_val;
+}
+
+/*
+ * Check memory executing simple write/read/verify at the specified address.
+ *
+ * Bits in the result indicate failure on specific byte lane.
+ */
+uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address)
+{
+	uint32_t result = 0;
+	uint8_t first_run = 0;
+
+	if (mrc_params->hte_setup) {
+		mrc_params->hte_setup = 0;
+		first_run = 1;
+		select_hte();
+	}
+
+	result = hte_basic_write_read(mrc_params, address, first_run,
+				      WRITE_TRAIN);
+
+	DPF(D_TRN, "check_rw_coarse result is %x\n", result);
+
+	return result;
+}
+
+/*
+ * Check memory executing write/read/verify of many data patterns
+ * at the specified address. Bits in the result indicate failure
+ * on specific byte lane.
+ */
+uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address)
+{
+	uint32_t result;
+	uint8_t first_run = 0;
+
+	if (mrc_params->hte_setup) {
+		mrc_params->hte_setup = 0;
+		first_run = 1;
+		select_hte();
+	}
+
+	result = hte_write_stress_bit_lanes(mrc_params, address, first_run);
+
+	DPF(D_TRN, "check_bls_ex result is %x\n", result);
+
+	return result;
+}
+
+/*
+ * 32-bit LFSR with characteristic polynomial: X^32 + X^22 +X^2 + X^1
+ *
+ * The function takes pointer to previous 32 bit value and
+ * modifies it to next value.
+ */
+void lfsr32(uint32_t *lfsr_ptr)
+{
+	uint32_t bit;
+	uint32_t lfsr;
+	int i;
+
+	lfsr = *lfsr_ptr;
+
+	for (i = 0; i < 32; i++) {
+		bit = 1 ^ (lfsr & BIT0);
+		bit = bit ^ ((lfsr & BIT1) >> 1);
+		bit = bit ^ ((lfsr & BIT2) >> 2);
+		bit = bit ^ ((lfsr & BIT22) >> 22);
+
+		lfsr = ((lfsr >> 1) | (bit << 31));
+	}
+
+	*lfsr_ptr = lfsr;
+}
+
+/* Clear the pointers in a given byte lane in a given channel */
+void clear_pointers(void)
+{
+	uint8_t channel;
+	uint8_t bl;
+
+	ENTERFN();
+
+	for (channel = 0; channel < NUM_CHANNELS; channel++) {
+		for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+			mrc_alt_write_mask(DDRPHY,
+					   (B01PTRCTL1 +
+					   (channel * DDRIODQ_CH_OFFSET) +
+					   ((bl >> 1) * DDRIODQ_BL_OFFSET)),
+					   ~BIT8, BIT8);
+
+			mrc_alt_write_mask(DDRPHY,
+					   (B01PTRCTL1 +
+					   (channel * DDRIODQ_CH_OFFSET) +
+					   ((bl >> 1) * DDRIODQ_BL_OFFSET)),
+					   BIT8, BIT8);
+		}
+	}
+
+	LEAVEFN();
+}
+
+static void print_timings_internal(uint8_t algo, uint8_t channel, uint8_t rank,
+				   uint8_t bl_divisor)
+{
+	uint8_t bl;
+
+	switch (algo) {
+	case RCVN:
+		DPF(D_INFO, "\nRCVN[%02d:%02d]", channel, rank);
+		break;
+	case WDQS:
+		DPF(D_INFO, "\nWDQS[%02d:%02d]", channel, rank);
+		break;
+	case WDQX:
+		DPF(D_INFO, "\nWDQx[%02d:%02d]", channel, rank);
+		break;
+	case RDQS:
+		DPF(D_INFO, "\nRDQS[%02d:%02d]", channel, rank);
+		break;
+	case VREF:
+		DPF(D_INFO, "\nVREF[%02d:%02d]", channel, rank);
+		break;
+	case WCMD:
+		DPF(D_INFO, "\nWCMD[%02d:%02d]", channel, rank);
+		break;
+	case WCTL:
+		DPF(D_INFO, "\nWCTL[%02d:%02d]", channel, rank);
+		break;
+	case WCLK:
+		DPF(D_INFO, "\nWCLK[%02d:%02d]", channel, rank);
+		break;
+	default:
+		break;
+	}
+
+	for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+		switch (algo) {
+		case RCVN:
+			DPF(D_INFO, " %03d", get_rcvn(channel, rank, bl));
+			break;
+		case WDQS:
+			DPF(D_INFO, " %03d", get_wdqs(channel, rank, bl));
+			break;
+		case WDQX:
+			DPF(D_INFO, " %03d", get_wdq(channel, rank, bl));
+			break;
+		case RDQS:
+			DPF(D_INFO, " %03d", get_rdqs(channel, rank, bl));
+			break;
+		case VREF:
+			DPF(D_INFO, " %03d", get_vref(channel, bl));
+			break;
+		case WCMD:
+			DPF(D_INFO, " %03d", get_wcmd(channel));
+			break;
+		case WCTL:
+			DPF(D_INFO, " %03d", get_wctl(channel, rank));
+			break;
+		case WCLK:
+			DPF(D_INFO, " %03d", get_wclk(channel, rank));
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void print_timings(struct mrc_params *mrc_params)
+{
+	uint8_t algo;
+	uint8_t channel;
+	uint8_t rank;
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+	DPF(D_INFO, "\n---------------------------");
+	DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");
+	DPF(D_INFO, "\n===========================");
+
+	for (algo = 0; algo < MAX_ALGOS; algo++) {
+		for (channel = 0; channel < NUM_CHANNELS; channel++) {
+			if (mrc_params->channel_enables & (1 << channel)) {
+				for (rank = 0; rank < NUM_RANKS; rank++) {
+					if (mrc_params->rank_enables &
+						(1 << rank)) {
+						print_timings_internal(algo,
+							channel, rank,
+							bl_divisor);
+					}
+				}
+			}
+		}
+	}
+
+	DPF(D_INFO, "\n---------------------------");
+	DPF(D_INFO, "\n");
+}
diff --git a/arch/x86/cpu/quark/mrc_util.h b/arch/x86/cpu/quark/mrc_util.h
new file mode 100644
index 0000000..f0ddbce
--- /dev/null
+++ b/arch/x86/cpu/quark/mrc_util.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef _MRC_UTIL_H_
+#define _MRC_UTIL_H_
+
+/* Turn on this macro to enable MRC debugging output */
+#undef  MRC_DEBUG
+
+/* MRC Debug Support */
+#define DPF		debug_cond
+
+/* debug print type */
+
+#ifdef MRC_DEBUG
+#define D_ERROR		0x0001
+#define D_INFO		0x0002
+#define D_REGRD		0x0004
+#define D_REGWR		0x0008
+#define D_FCALL		0x0010
+#define D_TRN		0x0020
+#define D_TIME		0x0040
+#else
+#define D_ERROR		0
+#define D_INFO		0
+#define D_REGRD		0
+#define D_REGWR		0
+#define D_FCALL		0
+#define D_TRN		0
+#define D_TIME		0
+#endif
+
+#define ENTERFN(...)	debug_cond(D_FCALL, "<%s>\n", __func__)
+#define LEAVEFN(...)	debug_cond(D_FCALL, "</%s>\n", __func__)
+#define REPORTFN(...)	debug_cond(D_FCALL, "<%s/>\n", __func__)
+
+/* Generic Register Bits */
+#define BIT0		0x00000001
+#define BIT1		0x00000002
+#define BIT2		0x00000004
+#define BIT3		0x00000008
+#define BIT4		0x00000010
+#define BIT5		0x00000020
+#define BIT6		0x00000040
+#define BIT7		0x00000080
+#define BIT8		0x00000100
+#define BIT9		0x00000200
+#define BIT10		0x00000400
+#define BIT11		0x00000800
+#define BIT12		0x00001000
+#define BIT13		0x00002000
+#define BIT14		0x00004000
+#define BIT15		0x00008000
+#define BIT16		0x00010000
+#define BIT17		0x00020000
+#define BIT18		0x00040000
+#define BIT19		0x00080000
+#define BIT20		0x00100000
+#define BIT21		0x00200000
+#define BIT22		0x00400000
+#define BIT23		0x00800000
+#define BIT24		0x01000000
+#define BIT25		0x02000000
+#define BIT26		0x04000000
+#define BIT27		0x08000000
+#define BIT28		0x10000000
+#define BIT29		0x20000000
+#define BIT30		0x40000000
+#define BIT31		0x80000000
+
+/* Message Bus Port */
+#define MEM_CTLR	0x01
+#define HOST_BRIDGE	0x03
+#define MEM_MGR		0x05
+#define HTE		0x11
+#define DDRPHY		0x12
+
+/* number of sample points */
+#define SAMPLE_CNT	3
+/* number of PIs to increment per sample */
+#define SAMPLE_DLY	26
+
+enum {
+	/* indicates to decrease delays when looking for edge */
+	BACKWARD,
+	/* indicates to increase delays when looking for edge */
+	FORWARD
+};
+
+enum {
+	RCVN,
+	WDQS,
+	WDQX,
+	RDQS,
+	VREF,
+	WCMD,
+	WCTL,
+	WCLK,
+	MAX_ALGOS,
+};
+
+void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
+void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask);
+void mrc_post_code(uint8_t major, uint8_t minor);
+void delay_n(uint32_t ns);
+void delay_u(uint32_t ms);
+void select_mem_mgr(void);
+void select_hte(void);
+void dram_init_command(uint32_t data);
+void dram_wake_command(void);
+void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+
+void set_rcvn(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_rdqs(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wdqs(uint8_t channel, uint8_t rank,
+	      uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wdq(uint8_t channel, uint8_t rank,
+	     uint8_t byte_lane, uint32_t pi_count);
+uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane);
+void set_wcmd(uint8_t channel, uint32_t pi_count);
+uint32_t get_wcmd(uint8_t channel);
+void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count);
+uint32_t get_wclk(uint8_t channel, uint8_t rank);
+void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count);
+uint32_t get_wctl(uint8_t channel, uint8_t rank);
+void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting);
+uint32_t get_vref(uint8_t channel, uint8_t byte_lane);
+
+uint32_t get_addr(uint8_t channel, uint8_t rank);
+uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
+		    uint8_t rank, bool rcvn);
+void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
+		      uint8_t channel, uint8_t rank, bool rcvn);
+uint32_t byte_lane_mask(struct mrc_params *mrc_params);
+uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address);
+uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address);
+void lfsr32(uint32_t *lfsr_ptr);
+void clear_pointers(void);
+void print_timings(struct mrc_params *mrc_params);
+
+#endif /* _MRC_UTIL_H_ */
diff --git a/arch/x86/cpu/quark/msg_port.c b/arch/x86/cpu/quark/msg_port.c
new file mode 100644
index 0000000..31713e3
--- /dev/null
+++ b/arch/x86/cpu/quark/msg_port.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+
+void msg_port_setup(int op, int port, int reg)
+{
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
+			       (((op) << 24) | ((port) << 16) |
+			       (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
+}
+
+u32 msg_port_read(u8 port, u32 reg)
+{
+	u32 value;
+
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_READ, port, reg);
+	pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+	return value;
+}
+
+void msg_port_write(u8 port, u32 reg, u32 value)
+{
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_WRITE, port, reg);
+}
+
+u32 msg_port_alt_read(u8 port, u32 reg)
+{
+	u32 value;
+
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_ALT_READ, port, reg);
+	pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+	return value;
+}
+
+void msg_port_alt_write(u8 port, u32 reg, u32 value)
+{
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_ALT_WRITE, port, reg);
+}
+
+u32 msg_port_io_read(u8 port, u32 reg)
+{
+	u32 value;
+
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_IO_READ, port, reg);
+	pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+
+	return value;
+}
+
+void msg_port_io_write(u8 port, u32 reg, u32 value)
+{
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+	pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+			       reg & 0xffffff00);
+	msg_port_setup(MSG_OP_IO_WRITE, port, reg);
+}
diff --git a/arch/x86/cpu/quark/pci.c b/arch/x86/cpu/quark/pci.c
new file mode 100644
index 0000000..354e15a
--- /dev/null
+++ b/arch/x86/cpu/quark/pci.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/pci.h>
+#include <asm/arch/device.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_pci_setup_hose(struct pci_controller *hose)
+{
+	hose->first_busno = 0;
+	hose->last_busno = 0;
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 0,
+		       CONFIG_PCI_MEM_BUS,
+		       CONFIG_PCI_MEM_PHYS,
+		       CONFIG_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(hose->regions + 1,
+		       CONFIG_PCI_IO_BUS,
+		       CONFIG_PCI_IO_PHYS,
+		       CONFIG_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	pci_set_region(hose->regions + 2,
+		       CONFIG_PCI_PREF_BUS,
+		       CONFIG_PCI_PREF_PHYS,
+		       CONFIG_PCI_PREF_SIZE,
+		       PCI_REGION_PREFETCH);
+
+	pci_set_region(hose->regions + 3,
+		       0,
+		       0,
+		       gd->ram_size,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	hose->region_count = 4;
+}
+
+int board_pci_post_scan(struct pci_controller *hose)
+{
+	return 0;
+}
+
+int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+{
+	/*
+	 * TODO:
+	 *
+	 * For some unknown reason, the PCI enumeration process hangs
+	 * when it scans to the PCIe root port 0 (D23:F0) & 1 (D23:F1).
+	 *
+	 * For now we just skip these two devices, and this needs to
+	 * be revisited later.
+	 */
+	if (dev == QUARK_HOST_BRIDGE ||
+	    dev == QUARK_PCIE0 || dev == QUARK_PCIE1) {
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
new file mode 100644
index 0000000..dccf7ac
--- /dev/null
+++ b/arch/x86/cpu/quark/quark.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/arch/device.h>
+#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
+
+static struct pci_device_id mmc_supported[] = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO },
+};
+
+/*
+ * TODO:
+ *
+ * This whole routine should be removed until we fully convert the ICH SPI
+ * driver to DM and make use of DT to pass the bios control register offset
+ */
+static void unprotect_spi_flash(void)
+{
+	u32 bc;
+
+	bc = pci_read_config32(QUARK_LEGACY_BRIDGE, 0xd8);
+	bc |= 0x1;	/* unprotect the flash */
+	pci_write_config32(QUARK_LEGACY_BRIDGE, 0xd8, bc);
+}
+
+static void quark_setup_bars(void)
+{
+	/* GPIO - D31:F0:R44h */
+	pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
+			       CONFIG_GPIO_BASE | IO_BAR_EN);
+
+	/* ACPI PM1 Block - D31:F0:R48h */
+	pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
+			       CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
+
+	/* GPE0 - D31:F0:R4Ch */
+	pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
+			       CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
+
+	/* WDT - D31:F0:R84h */
+	pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
+			       CONFIG_WDT_BASE | IO_BAR_EN);
+
+	/* RCBA - D31:F0:RF0h */
+	pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA,
+			       CONFIG_RCBA_BASE | MEM_BAR_EN);
+
+	/* ACPI P Block - Msg Port 04:R70h */
+	msg_port_write(MSG_PORT_RMU, PBLK_BA,
+		       CONFIG_ACPI_PBLK_BASE | IO_BAR_EN);
+
+	/* SPI DMA - Msg Port 04:R7Ah */
+	msg_port_write(MSG_PORT_RMU, SPI_DMA_BA,
+		       CONFIG_SPI_DMA_BASE | IO_BAR_EN);
+
+	/* PCIe ECAM */
+	msg_port_write(MSG_PORT_MEM_ARBITER, AEC_CTRL,
+		       CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
+	msg_port_write(MSG_PORT_HOST_BRIDGE, HEC_REG,
+		       CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
+}
+
+int arch_cpu_init(void)
+{
+	struct pci_controller *hose;
+	int ret;
+
+	post_code(POST_CPU_INIT);
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+	timer_set_base(rdtsc());
+#endif
+
+	ret = x86_cpu_init_f();
+	if (ret)
+		return ret;
+
+	ret = pci_early_init_hose(&hose);
+	if (ret)
+		return ret;
+
+	/*
+	 * Quark SoC has some non-standard BARs (excluding PCI standard BARs)
+	 * which need be initialized with suggested values
+	 */
+	quark_setup_bars();
+
+	unprotect_spi_flash();
+
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	post_code(POST_CPU_INFO);
+	return default_print_cpuinfo();
+}
+
+void reset_cpu(ulong addr)
+{
+	/* cold reset */
+	outb(0x08, PORT_RESET);
+}
+
+int cpu_mmc_init(bd_t *bis)
+{
+	return pci_mmc_init("Quark SDHCI", mmc_supported,
+			    ARRAY_SIZE(mmc_supported));
+}
diff --git a/arch/x86/cpu/quark/smc.c b/arch/x86/cpu/quark/smc.c
new file mode 100644
index 0000000..e34bec4
--- /dev/null
+++ b/arch/x86/cpu/quark/smc.c
@@ -0,0 +1,2764 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/arch/device.h>
+#include <asm/arch/mrc.h>
+#include <asm/arch/msg_port.h>
+#include "mrc_util.h"
+#include "hte.h"
+#include "smc.h"
+
+/* t_rfc values (in picoseconds) per density */
+static const uint32_t t_rfc[5] = {
+	90000,	/* 512Mb */
+	110000,	/* 1Gb */
+	160000,	/* 2Gb */
+	300000,	/* 4Gb */
+	350000,	/* 8Gb */
+};
+
+/* t_ck clock period in picoseconds per speed index 800, 1066, 1333 */
+static const uint32_t t_ck[3] = {
+	2500,
+	1875,
+	1500
+};
+
+/* Global variables */
+static const uint16_t ddr_wclk[] = {193, 158};
+static const uint16_t ddr_wctl[] = {1, 217};
+static const uint16_t ddr_wcmd[] = {1, 220};
+
+#ifdef BACKUP_RCVN
+static const uint16_t ddr_rcvn[] = {129, 498};
+#endif
+
+#ifdef BACKUP_WDQS
+static const uint16_t ddr_wdqs[] = {65, 289};
+#endif
+
+#ifdef BACKUP_RDQS
+static const uint8_t ddr_rdqs[] = {32, 24};
+#endif
+
+#ifdef BACKUP_WDQ
+static const uint16_t ddr_wdq[] = {32, 257};
+#endif
+
+/* Stop self refresh driven by MCU */
+void clear_self_refresh(struct mrc_params *mrc_params)
+{
+	ENTERFN();
+
+	/* clear the PMSTS Channel Self Refresh bits */
+	mrc_write_mask(MEM_CTLR, PMSTS, BIT0, BIT0);
+
+	LEAVEFN();
+}
+
+/* It will initialize timing registers in the MCU (DTR0..DTR4) */
+void prog_ddr_timing_control(struct mrc_params *mrc_params)
+{
+	uint8_t tcl, wl;
+	uint8_t trp, trcd, tras, twr, twtr, trrd, trtp, tfaw;
+	uint32_t tck;
+	u32 dtr0, dtr1, dtr2, dtr3, dtr4;
+	u32 tmp1, tmp2;
+
+	ENTERFN();
+
+	/* mcu_init starts */
+	mrc_post_code(0x02, 0x00);
+
+	dtr0 = msg_port_read(MEM_CTLR, DTR0);
+	dtr1 = msg_port_read(MEM_CTLR, DTR1);
+	dtr2 = msg_port_read(MEM_CTLR, DTR2);
+	dtr3 = msg_port_read(MEM_CTLR, DTR3);
+	dtr4 = msg_port_read(MEM_CTLR, DTR4);
+
+	tck = t_ck[mrc_params->ddr_speed];	/* Clock in picoseconds */
+	tcl = mrc_params->params.cl;		/* CAS latency in clocks */
+	trp = tcl;	/* Per CAT MRC */
+	trcd = tcl;	/* Per CAT MRC */
+	tras = MCEIL(mrc_params->params.ras, tck);
+
+	/* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
+	twr = MCEIL(15000, tck);
+
+	twtr = MCEIL(mrc_params->params.wtr, tck);
+	trrd = MCEIL(mrc_params->params.rrd, tck);
+	trtp = 4;	/* Valid for 800 and 1066, use 5 for 1333 */
+	tfaw = MCEIL(mrc_params->params.faw, tck);
+
+	wl = 5 + mrc_params->ddr_speed;
+
+	dtr0 &= ~(BIT0 | BIT1);
+	dtr0 |= mrc_params->ddr_speed;
+	dtr0 &= ~(BIT12 | BIT13 | BIT14);
+	tmp1 = tcl - 5;
+	dtr0 |= ((tcl - 5) << 12);
+	dtr0 &= ~(BIT4 | BIT5 | BIT6 | BIT7);
+	dtr0 |= ((trp - 5) << 4);	/* 5 bit DRAM Clock */
+	dtr0 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+	dtr0 |= ((trcd - 5) << 8);	/* 5 bit DRAM Clock */
+
+	dtr1 &= ~(BIT0 | BIT1 | BIT2);
+	tmp2 = wl - 3;
+	dtr1 |= (wl - 3);
+	dtr1 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+	dtr1 |= ((wl + 4 + twr - 14) << 8);	/* Change to tWTP */
+	dtr1 &= ~(BIT28 | BIT29 | BIT30);
+	dtr1 |= ((MMAX(trtp, 4) - 3) << 28);	/* 4 bit DRAM Clock */
+	dtr1 &= ~(BIT24 | BIT25);
+	dtr1 |= ((trrd - 4) << 24);		/* 4 bit DRAM Clock */
+	dtr1 &= ~(BIT4 | BIT5);
+	dtr1 |= (1 << 4);
+	dtr1 &= ~(BIT20 | BIT21 | BIT22 | BIT23);
+	dtr1 |= ((tras - 14) << 20);		/* 6 bit DRAM Clock */
+	dtr1 &= ~(BIT16 | BIT17 | BIT18 | BIT19);
+	dtr1 |= ((((tfaw + 1) >> 1) - 5) << 16);/* 4 bit DRAM Clock */
+	/* Set 4 Clock CAS to CAS delay (multi-burst) */
+	dtr1 &= ~(BIT12 | BIT13);
+
+	dtr2 &= ~(BIT0 | BIT1 | BIT2);
+	dtr2 |= 1;
+	dtr2 &= ~(BIT8 | BIT9 | BIT10);
+	dtr2 |= (2 << 8);
+	dtr2 &= ~(BIT16 | BIT17 | BIT18 | BIT19);
+	dtr2 |= (2 << 16);
+
+	dtr3 &= ~(BIT0 | BIT1 | BIT2);
+	dtr3 |= 2;
+	dtr3 &= ~(BIT4 | BIT5 | BIT6);
+	dtr3 |= (2 << 4);
+
+	dtr3 &= ~(BIT8 | BIT9 | BIT10 | BIT11);
+	if (mrc_params->ddr_speed == DDRFREQ_800) {
+		/* Extended RW delay (+1) */
+		dtr3 |= ((tcl - 5 + 1) << 8);
+	} else if (mrc_params->ddr_speed == DDRFREQ_1066) {
+		/* Extended RW delay (+1) */
+		dtr3 |= ((tcl - 5 + 1) << 8);
+	}
+
+	dtr3 &= ~(BIT13 | BIT14 | BIT15 | BIT16);
+	dtr3 |= ((4 + wl + twtr - 11) << 13);
+
+	dtr3 &= ~(BIT22 | BIT23);
+	if (mrc_params->ddr_speed == DDRFREQ_800)
+		dtr3 |= ((MMAX(0, 1 - 1)) << 22);
+	else
+		dtr3 |= ((MMAX(0, 2 - 1)) << 22);
+
+	dtr4 &= ~(BIT0 | BIT1);
+	dtr4 |= 1;
+	dtr4 &= ~(BIT4 | BIT5 | BIT6);
+	dtr4 |= (1 << 4);
+	dtr4 &= ~(BIT8 | BIT9 | BIT10);
+	dtr4 |= ((1 + tmp1 - tmp2 + 2) << 8);
+	dtr4 &= ~(BIT12 | BIT13 | BIT14);
+	dtr4 |= ((1 + tmp1 - tmp2 + 2) << 12);
+	dtr4 &= ~(BIT15 | BIT16);
+
+	msg_port_write(MEM_CTLR, DTR0, dtr0);
+	msg_port_write(MEM_CTLR, DTR1, dtr1);
+	msg_port_write(MEM_CTLR, DTR2, dtr2);
+	msg_port_write(MEM_CTLR, DTR3, dtr3);
+	msg_port_write(MEM_CTLR, DTR4, dtr4);
+
+	LEAVEFN();
+}
+
+/* Configure MCU before jedec init sequence */
+void prog_decode_before_jedec(struct mrc_params *mrc_params)
+{
+	u32 drp;
+	u32 drfc;
+	u32 dcal;
+	u32 dsch;
+	u32 dpmc0;
+
+	ENTERFN();
+
+	/* Disable power saving features */
+	dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+	dpmc0 |= (BIT24 | BIT25);
+	dpmc0 &= ~(BIT16 | BIT17 | BIT18);
+	dpmc0 &= ~BIT23;
+	msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+	/* Disable out of order transactions */
+	dsch = msg_port_read(MEM_CTLR, DSCH);
+	dsch |= (BIT8 | BIT12);
+	msg_port_write(MEM_CTLR, DSCH, dsch);
+
+	/* Disable issuing the REF command */
+	drfc = msg_port_read(MEM_CTLR, DRFC);
+	drfc &= ~(BIT12 | BIT13 | BIT14);
+	msg_port_write(MEM_CTLR, DRFC, drfc);
+
+	/* Disable ZQ calibration short */
+	dcal = msg_port_read(MEM_CTLR, DCAL);
+	dcal &= ~(BIT8 | BIT9 | BIT10);
+	dcal &= ~(BIT12 | BIT13);
+	msg_port_write(MEM_CTLR, DCAL, dcal);
+
+	/*
+	 * Training performed in address mode 0, rank population has limited
+	 * impact, however simulator complains if enabled non-existing rank.
+	 */
+	drp = 0;
+	if (mrc_params->rank_enables & 1)
+		drp |= BIT0;
+	if (mrc_params->rank_enables & 2)
+		drp |= BIT1;
+	msg_port_write(MEM_CTLR, DRP, drp);
+
+	LEAVEFN();
+}
+
+/*
+ * After Cold Reset, BIOS should set COLDWAKE bit to 1 before
+ * sending the WAKE message to the Dunit.
+ *
+ * For Standby Exit, or any other mode in which the DRAM is in
+ * SR, this bit must be set to 0.
+ */
+void perform_ddr_reset(struct mrc_params *mrc_params)
+{
+	ENTERFN();
+
+	/* Set COLDWAKE bit before sending the WAKE message */
+	mrc_write_mask(MEM_CTLR, DRMC, BIT16, BIT16);
+
+	/* Send wake command to DUNIT (MUST be done before JEDEC) */
+	dram_wake_command();
+
+	/* Set default value */
+	msg_port_write(MEM_CTLR, DRMC,
+		       (mrc_params->rd_odt_value == 0 ? BIT12 : 0));
+
+	LEAVEFN();
+}
+
+
+/*
+ * This function performs some initialization on the DDRIO unit.
+ * This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
+ */
+void ddrphy_init(struct mrc_params *mrc_params)
+{
+	uint32_t temp;
+	uint8_t ch;	/* channel counter */
+	uint8_t rk;	/* rank counter */
+	uint8_t bl_grp;	/*  byte lane group counter (2 BLs per module) */
+	uint8_t bl_divisor = 1;	/* byte lane divisor */
+	/* For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333 */
+	uint8_t speed = mrc_params->ddr_speed & (BIT1 | BIT0);
+	uint8_t cas;
+	uint8_t cwl;
+
+	ENTERFN();
+
+	cas = mrc_params->params.cl;
+	cwl = 5 + mrc_params->ddr_speed;
+
+	/* ddrphy_init starts */
+	mrc_post_code(0x03, 0x00);
+
+	/*
+	 * HSD#231531
+	 * Make sure IOBUFACT is deasserted before initializing the DDR PHY
+	 *
+	 * HSD#234845
+	 * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
+	 */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* Deassert DDRPHY Initialization Complete */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMCONFIG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				~BIT20, BIT20);	/* SPID_INIT_COMPLETE=0 */
+			/* Deassert IOBUFACT */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				~BIT2, BIT2);	/* IOBUFACTRST_N=0 */
+			/* Disable WRPTR */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPTRREG + (ch * DDRIOCCC_CH_OFFSET)),
+				~BIT0, BIT0);	/* WRPTRENABLE=0 */
+		}
+	}
+
+	/* Put PHY in reset */
+	mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, BIT0);
+
+	/* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */
+
+	/* STEP0 */
+	mrc_post_code(0x03, 0x10);
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* DQ01-DQ23 */
+			for (bl_grp = 0;
+			     bl_grp < ((NUM_BYTE_LANES / bl_divisor) / 2);
+			     bl_grp++) {
+				/* Analog MUX select - IO2xCLKSEL */
+				mrc_alt_write_mask(DDRPHY,
+					(DQOBSCKEBBCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					((bl_grp) ? (0x00) : (BIT22)), (BIT22));
+
+				/* ODT Strength */
+				switch (mrc_params->rd_odt_value) {
+				case 1:
+					temp = 0x3;
+					break;	/* 60 ohm */
+				case 2:
+					temp = 0x3;
+					break;	/* 120 ohm */
+				case 3:
+					temp = 0x3;
+					break;	/* 180 ohm */
+				default:
+					temp = 0x3;
+					break;	/* 120 ohm */
+				}
+
+				/* ODT strength */
+				mrc_alt_write_mask(DDRPHY,
+					(B0RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(temp << 5), (BIT6 | BIT5));
+				/* ODT strength */
+				mrc_alt_write_mask(DDRPHY,
+					(B1RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(temp << 5), (BIT6 | BIT5));
+
+				/* Dynamic ODT/DIFFAMP */
+				temp = (((cas) << 24) | ((cas) << 16) |
+					((cas) << 8) | ((cas) << 0));
+				switch (speed) {
+				case 0:
+					temp -= 0x01010101;
+					break;	/* 800 */
+				case 1:
+					temp -= 0x02020202;
+					break;	/* 1066 */
+				case 2:
+					temp -= 0x03030303;
+					break;	/* 1333 */
+				case 3:
+					temp -= 0x04040404;
+					break;	/* 1600 */
+				}
+
+				/* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
+				mrc_alt_write_mask(DDRPHY,
+					(B01LATCTL1 +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp,
+					(BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+					BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+					BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+					BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+				switch (speed) {
+				/* HSD#234715 */
+				case 0:
+					temp = ((0x06 << 16) | (0x07 << 8));
+					break;	/* 800 */
+				case 1:
+					temp = ((0x07 << 16) | (0x08 << 8));
+					break;	/* 1066 */
+				case 2:
+					temp = ((0x09 << 16) | (0x0A << 8));
+					break;	/* 1333 */
+				case 3:
+					temp = ((0x0A << 16) | (0x0B << 8));
+					break;	/* 1600 */
+				}
+
+				/* On Duration: ODT, DIFFAMP */
+				mrc_alt_write_mask(DDRPHY,
+					(B0ONDURCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp,
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+					BIT9 | BIT8));
+				/* On Duration: ODT, DIFFAMP */
+				mrc_alt_write_mask(DDRPHY,
+					(B1ONDURCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp,
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+					BIT9 | BIT8));
+
+				switch (mrc_params->rd_odt_value) {
+				case 0:
+					/* override DIFFAMP=on, ODT=off */
+					temp = ((0x3F << 16) | (0x3f << 10));
+					break;
+				default:
+					/* override DIFFAMP=on, ODT=on */
+					temp = ((0x3F << 16) | (0x2A << 10));
+					break;
+				}
+
+				/* Override: DIFFAMP, ODT */
+				mrc_alt_write_mask(DDRPHY,
+					(B0OVRCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp,
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT15 | BIT14 | BIT13 | BIT12 |
+					BIT11 | BIT10));
+				/* Override: DIFFAMP, ODT */
+				mrc_alt_write_mask(DDRPHY,
+					(B1OVRCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp,
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT15 | BIT14 | BIT13 | BIT12 |
+					BIT11 | BIT10));
+
+				/* DLL Setup */
+
+				/* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
+				mrc_alt_write_mask(DDRPHY,
+					(B0LATCTL0 +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(((cas + 7) << 16) | ((cas - 4) << 8) |
+					((cwl - 2) << 0)),
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT12 | BIT11 | BIT10 | BIT9 |
+					BIT8 | BIT4 | BIT3 | BIT2 | BIT1 |
+					BIT0));
+				mrc_alt_write_mask(DDRPHY,
+					(B1LATCTL0 +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(((cas + 7) << 16) | ((cas - 4) << 8) |
+					((cwl - 2) << 0)),
+					(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+					BIT16 | BIT12 | BIT11 | BIT10 | BIT9 |
+					BIT8 | BIT4 | BIT3 | BIT2 | BIT1 |
+					BIT0));
+
+				/* RCVEN Bypass (PO) */
+				mrc_alt_write_mask(DDRPHY,
+					(B0RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					((0x0 << 7) | (0x0 << 0)),
+					(BIT7 | BIT0));
+				mrc_alt_write_mask(DDRPHY,
+					(B1RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					((0x0 << 7) | (0x0 << 0)),
+					(BIT7 | BIT0));
+
+				/* TX */
+				mrc_alt_write_mask(DDRPHY,
+					(DQCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT16), (BIT16));
+				mrc_alt_write_mask(DDRPHY,
+					(B01PTRCTL1 +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT8), (BIT8));
+
+				/* RX (PO) */
+				/* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
+				mrc_alt_write_mask(DDRPHY,
+					(B0VREFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					((0x03 << 2) | (0x0 << 1) | (0x0 << 0)),
+					(BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+					BIT2 | BIT1 | BIT0));
+				/* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
+				mrc_alt_write_mask(DDRPHY,
+					(B1VREFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					((0x03 << 2) | (0x0 << 1) | (0x0 << 0)),
+					(BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+					BIT2 | BIT1 | BIT0));
+				/* Per-Bit De-Skew Enable */
+				mrc_alt_write_mask(DDRPHY,
+					(B0RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(0), (BIT4));
+				/* Per-Bit De-Skew Enable */
+				mrc_alt_write_mask(DDRPHY,
+					(B1RXIOBUFCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(0), (BIT4));
+			}
+
+			/* CLKEBB */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDOBSCKEBBCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				0, (BIT23));
+
+			/* Enable tristate control of cmd/address bus */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				0, (BIT1 | BIT0));
+
+			/* ODT RCOMP */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDRCOMPODT + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x03 << 5) | (0x03 << 0)),
+				(BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 |
+				BIT3 | BIT2 | BIT1 | BIT0));
+
+			/* CMDPM* registers must be programmed in this order */
+
+			/* Turn On Delays: SFR (regulator), MPLL */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMDLYREG4 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0xFFFFU << 16) | (0xFFFF << 0)),
+				0xFFFFFFFF);
+			/*
+			 * Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3,
+			 * VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT
+			 * for_PM_MSG_gt0, MDLL Turn On
+			 */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMDLYREG3 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0xFU << 28) | (0xFFF << 16) | (0xF << 12) |
+				(0x616 << 0)), 0xFFFFFFFF);
+			/* MPLL Divider Reset Delays */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMDLYREG2 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+				(0xFF << 0)), 0xFFFFFFFF);
+			/* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMDLYREG1 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+				(0xFF << 0)), 0xFFFFFFFF);
+			/* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMDLYREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0xFFU << 24) | (0xFF << 16) | (0xFF << 8) |
+				(0xFF << 0)), 0xFFFFFFFF);
+			/* Allow PUnit signals */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMCONFIG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x6 << 8) | BIT6 | (0x4 << 0)),
+				(BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 |
+				BIT25 | BIT24 | BIT23 | BIT22 | BIT21 | BIT11 |
+				BIT10 | BIT9 | BIT8 | BIT6 | BIT3 | BIT2 |
+				BIT1 | BIT0));
+			/* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x3 << 4) | (0x7 << 0)),
+				(BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 |
+				BIT0));
+
+			/* CLK-CTL */
+			mrc_alt_write_mask(DDRPHY,
+				(CCOBSCKEBBCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				0, BIT24);	/* CLKEBB */
+			/* Buffer Enable: CS,CKE,ODT,CLK */
+			mrc_alt_write_mask(DDRPHY,
+				(CCCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x0 << 16) | (0x0 << 12) | (0x0 << 8) |
+				(0xF << 4) | BIT0),
+				(BIT19 | BIT18 | BIT17 | BIT16 | BIT15 | BIT14 |
+				BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+				BIT7 | BIT6 | BIT5 | BIT4 | BIT0));
+			/* ODT RCOMP */
+			mrc_alt_write_mask(DDRPHY,
+				(CCRCOMPODT + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x03 << 8) | (0x03 << 0)),
+				(BIT12 | BIT11 | BIT10 | BIT9 | BIT8 | BIT4 |
+				BIT3 | BIT2 | BIT1 | BIT0));
+			/* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
+			mrc_alt_write_mask(DDRPHY,
+				(CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x3 << 4) | (0x7 << 0)),
+				(BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 |
+				BIT0));
+
+			/*
+			 * COMP (RON channel specific)
+			 * - DQ/DQS/DM RON: 32 Ohm
+			 * - CTRL/CMD RON: 27 Ohm
+			 * - CLK RON: 26 Ohm
+			 */
+			/* RCOMP Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQVREFCH0 +  (ch * DDRCOMP_CH_OFFSET)),
+				((0x08 << 24) | (0x03 << 16)),
+				(BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+				BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+				BIT17 | BIT16));
+			/* RCOMP Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x0C << 24) | (0x03 << 16)),
+				(BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+				BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+				BIT17 | BIT16));
+			/* RCOMP Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x0F << 24) | (0x03 << 16)),
+				(BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+				BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+				BIT17 | BIT16));
+			/* RCOMP Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x08 << 24) | (0x03 << 16)),
+				(BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+				BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+				BIT17 | BIT16));
+			/* RCOMP Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CTLVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x0C << 24) | (0x03 << 16)),
+				(BIT29 | BIT28 | BIT27 | BIT26 | BIT25 |
+				BIT24 | BIT21 | BIT20 | BIT19 | BIT18 |
+				BIT17 | BIT16));
+
+			/* DQS Swapped Input Enable */
+			mrc_alt_write_mask(DDRPHY,
+				(COMPEN1CH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT19 | BIT17),
+				(BIT31 | BIT30 | BIT19 | BIT17 |
+				BIT15 | BIT14));
+
+			/* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
+			/* ODT Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x32 << 8) | (0x03 << 0)),
+				(BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+				BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+			/* ODT Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x32 << 8) | (0x03 << 0)),
+				(BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+				BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+			/* ODT Vref PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x0E << 8) | (0x05 << 0)),
+				(BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+				BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+
+			/*
+			 * Slew rate settings are frequency specific,
+			 * numbers below are for 800Mhz (speed == 0)
+			 * - DQ/DQS/DM/CLK SR: 4V/ns,
+			 * - CTRL/CMD SR: 1.5V/ns
+			 */
+			temp = (0x0E << 16) | (0x0E << 12) | (0x08 << 8) |
+				(0x0B << 4) | (0x0B << 0);
+			/* DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ */
+			mrc_alt_write_mask(DDRPHY,
+				(DLYSELCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				temp,
+				(BIT19 | BIT18 | BIT17 | BIT16 | BIT15 |
+				BIT14 | BIT13 | BIT12 | BIT11 | BIT10 |
+				BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 |
+				BIT3 | BIT2 | BIT1 | BIT0));
+			/* TCO Vref CLK,DQS,DQ */
+			mrc_alt_write_mask(DDRPHY,
+				(TCOVREFCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x05 << 16) | (0x05 << 8) | (0x05 << 0)),
+				(BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+				BIT16 | BIT13 | BIT12 | BIT11 | BIT10 |
+				BIT9 | BIT8 | BIT5 | BIT4 | BIT3 | BIT2 |
+				BIT1 | BIT0));
+			/* ODTCOMP CMD/CTL PU/PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CCBUFODTCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				((0x03 << 8) | (0x03 << 0)),
+				(BIT12 | BIT11 | BIT10 | BIT9 | BIT8 |
+				BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+			/* COMP */
+			mrc_alt_write_mask(DDRPHY,
+				(COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+				0, (BIT31 | BIT30 | BIT8));
+
+#ifdef BACKUP_COMPS
+			/* DQ COMP Overrides */
+			/* RCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* RCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x10 << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x10 << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+
+			/* DQS COMP Overrides */
+			/* RCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* RCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x10 << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x10 << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+
+			/* CLK COMP Overrides */
+			/* RCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0C << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* RCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0C << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x07 << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x07 << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKODTPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* ODTCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKODTPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | (0x0B << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31), (BIT31));
+
+			/* CMD COMP Overrides */
+			/* RCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0D << 16)),
+				(BIT31 | BIT21 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* RCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0D << 16)),
+				(BIT31 | BIT21 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+
+			/* CTL COMP Overrides */
+			/* RCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CTLDRVPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0D << 16)),
+				(BIT31 | BIT21 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* RCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CTLDRVPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0D << 16)),
+				(BIT31 | BIT21 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CTLDLYPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* DCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CTLDLYPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x0A << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+#else
+			/* DQ TCOCOMP Overrides */
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+
+			/* DQS TCOCOMP Overrides */
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(DQSTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+
+			/* CLK TCOCOMP Overrides */
+			/* TCOCOMP PU */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKTCOPUCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+			/* TCOCOMP PD */
+			mrc_alt_write_mask(DDRPHY,
+				(CLKTCOPDCTLCH0 + (ch * DDRCOMP_CH_OFFSET)),
+				(BIT31 | (0x1F << 16)),
+				(BIT31 | BIT20 | BIT19 |
+				BIT18 | BIT17 | BIT16));
+#endif
+
+			/* program STATIC delays */
+#ifdef BACKUP_WCMD
+			set_wcmd(ch, ddr_wcmd[PLATFORM_ID]);
+#else
+			set_wcmd(ch, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+#endif
+
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1<<rk)) {
+					set_wclk(ch, rk, ddr_wclk[PLATFORM_ID]);
+#ifdef BACKUP_WCTL
+					set_wctl(ch, rk, ddr_wctl[PLATFORM_ID]);
+#else
+					set_wctl(ch, rk, ddr_wclk[PLATFORM_ID] + HALF_CLK);
+#endif
+				}
+			}
+		}
+	}
+
+	/* COMP (non channel specific) */
+	/* RCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANADRVPUCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANADRVPDCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CMDANADRVPUCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CMDANADRVPDCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANADRVPUCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANADRVPDCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANADRVPUCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANADRVPDCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CTLANADRVPUCTL), (BIT30), (BIT30));
+	/* RCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CTLANADRVPDCTL), (BIT30), (BIT30));
+	/* ODT: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANAODTPUCTL), (BIT30), (BIT30));
+	/* ODT: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANAODTPDCTL), (BIT30), (BIT30));
+	/* ODT: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANAODTPUCTL), (BIT30), (BIT30));
+	/* ODT: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANAODTPDCTL), (BIT30), (BIT30));
+	/* ODT: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANAODTPUCTL), (BIT30), (BIT30));
+	/* ODT: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANAODTPDCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANADLYPUCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANADLYPDCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CMDANADLYPUCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CMDANADLYPDCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANADLYPUCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANADLYPDCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANADLYPUCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANADLYPDCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CTLANADLYPUCTL), (BIT30), (BIT30));
+	/* DCOMP: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CTLANADLYPDCTL), (BIT30), (BIT30));
+	/* TCO: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANATCOPUCTL), (BIT30), (BIT30));
+	/* TCO: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQANATCOPDCTL), (BIT30), (BIT30));
+	/* TCO: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANATCOPUCTL), (BIT30), (BIT30));
+	/* TCO: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (CLKANATCOPDCTL), (BIT30), (BIT30));
+	/* TCO: Dither PU Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANATCOPUCTL), (BIT30), (BIT30));
+	/* TCO: Dither PD Enable */
+	mrc_alt_write_mask(DDRPHY, (DQSANATCOPDCTL), (BIT30), (BIT30));
+	/* TCOCOMP: Pulse Count */
+	mrc_alt_write_mask(DDRPHY, (TCOCNTCTRL), (0x1 << 0), (BIT1 | BIT0));
+	/* ODT: CMD/CTL PD/PU */
+	mrc_alt_write_mask(DDRPHY,
+		(CHNLBUFSTATIC), ((0x03 << 24) | (0x03 << 16)),
+		(BIT28 | BIT27 | BIT26 | BIT25 | BIT24 |
+		BIT20 | BIT19 | BIT18 | BIT17 | BIT16));
+	/* Set 1us counter */
+	mrc_alt_write_mask(DDRPHY,
+		(MSCNTR), (0x64 << 0),
+		(BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0));
+	mrc_alt_write_mask(DDRPHY,
+		(LATCH1CTL), (0x1 << 28),
+		(BIT30 | BIT29 | BIT28));
+
+	/* Release PHY from reset */
+	mrc_alt_write_mask(DDRPHY, MASTERRSTN, BIT0, BIT0);
+
+	/* STEP1 */
+	mrc_post_code(0x03, 0x11);
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* DQ01-DQ23 */
+			for (bl_grp = 0;
+			     bl_grp < ((NUM_BYTE_LANES / bl_divisor) / 2);
+			     bl_grp++) {
+				mrc_alt_write_mask(DDRPHY,
+					(DQMDLLCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT13),
+					(BIT13));	/* Enable VREG */
+				delay_n(3);
+			}
+
+			/* ECC */
+			mrc_alt_write_mask(DDRPHY, (ECCMDLLCTL),
+				(BIT13), (BIT13));	/* Enable VREG */
+			delay_n(3);
+			/* CMD */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				(BIT13), (BIT13));	/* Enable VREG */
+			delay_n(3);
+			/* CLK-CTL */
+			mrc_alt_write_mask(DDRPHY,
+				(CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				(BIT13), (BIT13));	/* Enable VREG */
+			delay_n(3);
+		}
+	}
+
+	/* STEP2 */
+	mrc_post_code(0x03, 0x12);
+	delay_n(200);
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* DQ01-DQ23 */
+			for (bl_grp = 0;
+			     bl_grp < ((NUM_BYTE_LANES / bl_divisor) / 2);
+			     bl_grp++) {
+				mrc_alt_write_mask(DDRPHY,
+					(DQMDLLCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT17),
+					(BIT17));	/* Enable MCDLL */
+				delay_n(50);
+			}
+
+		/* ECC */
+		mrc_alt_write_mask(DDRPHY, (ECCMDLLCTL),
+			(BIT17), (BIT17));	/* Enable MCDLL */
+		delay_n(50);
+		/* CMD */
+		mrc_alt_write_mask(DDRPHY,
+			(CMDMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+			(BIT18), (BIT18));	/* Enable MCDLL */
+		delay_n(50);
+		/* CLK-CTL */
+		mrc_alt_write_mask(DDRPHY,
+			(CCMDLLCTL + (ch * DDRIOCCC_CH_OFFSET)),
+			(BIT18), (BIT18));	/* Enable MCDLL */
+		delay_n(50);
+		}
+	}
+
+	/* STEP3: */
+	mrc_post_code(0x03, 0x13);
+	delay_n(100);
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* DQ01-DQ23 */
+			for (bl_grp = 0;
+			     bl_grp < ((NUM_BYTE_LANES / bl_divisor) / 2);
+			     bl_grp++) {
+#ifdef FORCE_16BIT_DDRIO
+				temp = ((bl_grp) &&
+					(mrc_params->channel_width == X16)) ?
+					((0x1 << 12) | (0x1 << 8) |
+					(0xF << 4) | (0xF << 0)) :
+					((0xF << 12) | (0xF << 8) |
+					(0xF << 4) | (0xF << 0));
+#else
+				temp = ((0xF << 12) | (0xF << 8) |
+					(0xF << 4) | (0xF << 0));
+#endif
+				/* Enable TXDLL */
+				mrc_alt_write_mask(DDRPHY,
+					(DQDLLTXCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					temp, 0xFFFF);
+				delay_n(3);
+				/* Enable RXDLL */
+				mrc_alt_write_mask(DDRPHY,
+					(DQDLLRXCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT3 | BIT2 | BIT1 | BIT0),
+					(BIT3 | BIT2 | BIT1 | BIT0));
+				delay_n(3);
+				/* Enable RXDLL Overrides BL0 */
+				mrc_alt_write_mask(DDRPHY,
+					(B0OVRCTL +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(BIT3 | BIT2 | BIT1 | BIT0),
+					(BIT3 | BIT2 | BIT1 | BIT0));
+			}
+
+			/* ECC */
+			temp = ((0xF << 12) | (0xF << 8) |
+				(0xF << 4) | (0xF << 0));
+			mrc_alt_write_mask(DDRPHY, (ECCDLLTXCTL),
+				temp, 0xFFFF);
+			delay_n(3);
+
+			/* CMD (PO) */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDDLLTXCTL + (ch * DDRIOCCC_CH_OFFSET)),
+				temp, 0xFFFF);
+			delay_n(3);
+		}
+	}
+
+	/* STEP4 */
+	mrc_post_code(0x03, 0x14);
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* Host To Memory Clock Alignment (HMC) for 800/1066 */
+			for (bl_grp = 0;
+			     bl_grp < ((NUM_BYTE_LANES / bl_divisor) / 2);
+			     bl_grp++) {
+				/* CLK_ALIGN_MOD_ID */
+				mrc_alt_write_mask(DDRPHY,
+					(DQCLKALIGNREG2 +
+					(bl_grp * DDRIODQ_BL_OFFSET) +
+					(ch * DDRIODQ_CH_OFFSET)),
+					(bl_grp) ? (0x3) : (0x1),
+					(BIT3 | BIT2 | BIT1 | BIT0));
+			}
+
+			mrc_alt_write_mask(DDRPHY,
+				(ECCCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+				0x2,
+				(BIT3 | BIT2 | BIT1 | BIT0));
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+				0x0,
+				(BIT3 | BIT2 | BIT1 | BIT0));
+			mrc_alt_write_mask(DDRPHY,
+				(CCCLKALIGNREG2 + (ch * DDRIODQ_CH_OFFSET)),
+				0x2,
+				(BIT3 | BIT2 | BIT1 | BIT0));
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				(0x2 << 4), (BIT5 | BIT4));
+			/*
+			 * NUM_SAMPLES, MAX_SAMPLES,
+			 * MACRO_PI_STEP, MICRO_PI_STEP
+			 */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCLKALIGNREG1 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x18 << 16) | (0x10 << 8) |
+				(0x8 << 2) | (0x1 << 0)),
+				(BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 |
+				BIT16 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 |
+				BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 |
+				BIT2 | BIT1 | BIT0));
+			/* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCLKALIGNREG2 + (ch * DDRIOCCC_CH_OFFSET)),
+				((0x10 << 16) | (0x4 << 8) | (0x2 << 4)),
+				(BIT20 | BIT19 | BIT18 | BIT17 | BIT16 |
+				BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 |
+				BIT5 | BIT4));
+#ifdef HMC_TEST
+			/* START_CLK_ALIGN=1 */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				BIT24, BIT24);
+			while (msg_port_alt_read(DDRPHY,
+				(CMDCLKALIGNREG0 + (ch * DDRIOCCC_CH_OFFSET))) &
+				BIT24)
+				;	/* wait for START_CLK_ALIGN=0 */
+#endif
+
+			/* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPTRREG + (ch * DDRIOCCC_CH_OFFSET)),
+				BIT0, BIT0);	/* WRPTRENABLE=1 */
+
+			/* COMP initial */
+			/* enable bypass for CLK buffer (PO) */
+			mrc_alt_write_mask(DDRPHY,
+				(COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+				BIT5, BIT5);
+			/* Initial COMP Enable */
+			mrc_alt_write_mask(DDRPHY, (CMPCTRL),
+				(BIT0), (BIT0));
+			/* wait for Initial COMP Enable = 0 */
+			while (msg_port_alt_read(DDRPHY, (CMPCTRL)) & BIT0)
+				;
+			/* disable bypass for CLK buffer (PO) */
+			mrc_alt_write_mask(DDRPHY,
+				(COMPEN0CH0 + (ch * DDRCOMP_CH_OFFSET)),
+				~BIT5, BIT5);
+
+			/* IOBUFACT */
+
+			/* STEP4a */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDCFGREG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				BIT2, BIT2);	/* IOBUFACTRST_N=1 */
+
+			/* DDRPHY initialization complete */
+			mrc_alt_write_mask(DDRPHY,
+				(CMDPMCONFIG0 + (ch * DDRIOCCC_CH_OFFSET)),
+				BIT20, BIT20);	/* SPID_INIT_COMPLETE=1 */
+		}
+	}
+
+	LEAVEFN();
+}
+
+/* This function performs JEDEC initialization on all enabled channels */
+void perform_jedec_init(struct mrc_params *mrc_params)
+{
+	uint8_t twr, wl, rank;
+	uint32_t tck;
+	u32 dtr0;
+	u32 drp;
+	u32 drmc;
+	u32 mrs0_cmd = 0;
+	u32 emrs1_cmd = 0;
+	u32 emrs2_cmd = 0;
+	u32 emrs3_cmd = 0;
+
+	ENTERFN();
+
+	/* jedec_init starts */
+	mrc_post_code(0x04, 0x00);
+
+	/* DDR3_RESET_SET=0, DDR3_RESET_RESET=1 */
+	mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, BIT1, (BIT8 | BIT1));
+
+	/* Assert RESET# for 200us */
+	delay_u(200);
+
+	/* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
+	mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, BIT8, (BIT8 | BIT1));
+
+	dtr0 = msg_port_read(MEM_CTLR, DTR0);
+
+	/*
+	 * Set CKEVAL for populated ranks
+	 * then send NOP to each rank (#4550197)
+	 */
+
+	drp = msg_port_read(MEM_CTLR, DRP);
+	drp &= 0x3;
+
+	drmc = msg_port_read(MEM_CTLR, DRMC);
+	drmc &= 0xFFFFFFFC;
+	drmc |= (BIT4 | drp);
+
+	msg_port_write(MEM_CTLR, DRMC, drmc);
+
+	for (rank = 0; rank < NUM_RANKS; rank++) {
+		/* Skip to next populated rank */
+		if ((mrc_params->rank_enables & (1 << rank)) == 0)
+			continue;
+
+		dram_init_command(DCMD_NOP(rank));
+	}
+
+	msg_port_write(MEM_CTLR, DRMC,
+		(mrc_params->rd_odt_value == 0 ? BIT12 : 0));
+
+	/*
+	 * setup for emrs 2
+	 * BIT[15:11] --> Always "0"
+	 * BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)
+	 * BIT[08]    --> Always "0"
+	 * BIT[07]    --> SRT: use sr_temp_range
+	 * BIT[06]    --> ASR: want "Manual SR Reference" (0)
+	 * BIT[05:03] --> CWL: use oem_tCWL
+	 * BIT[02:00] --> PASR: want "Full Array" (0)
+	 */
+	emrs2_cmd |= (2 << 3);
+	wl = 5 + mrc_params->ddr_speed;
+	emrs2_cmd |= ((wl - 5) << 9);
+	emrs2_cmd |= (mrc_params->sr_temp_range << 13);
+
+	/*
+	 * setup for emrs 3
+	 * BIT[15:03] --> Always "0"
+	 * BIT[02]    --> MPR: want "Normal Operation" (0)
+	 * BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
+	 */
+	emrs3_cmd |= (3 << 3);
+
+	/*
+	 * setup for emrs 1
+	 * BIT[15:13]     --> Always "0"
+	 * BIT[12:12]     --> Qoff: want "Output Buffer Enabled" (0)
+	 * BIT[11:11]     --> TDQS: want "Disabled" (0)
+	 * BIT[10:10]     --> Always "0"
+	 * BIT[09,06,02]  --> Rtt_nom: use rtt_nom_value
+	 * BIT[08]        --> Always "0"
+	 * BIT[07]        --> WR_LVL: want "Disabled" (0)
+	 * BIT[05,01]     --> DIC: use ron_value
+	 * BIT[04:03]     --> AL: additive latency want "0" (0)
+	 * BIT[00]        --> DLL: want "Enable" (0)
+	 *
+	 * (BIT5|BIT1) set Ron value
+	 * 00 --> RZQ/6 (40ohm)
+	 * 01 --> RZQ/7 (34ohm)
+	 * 1* --> RESERVED
+	 *
+	 * (BIT9|BIT6|BIT2) set Rtt_nom value
+	 * 000 --> Disabled
+	 * 001 --> RZQ/4 ( 60ohm)
+	 * 010 --> RZQ/2 (120ohm)
+	 * 011 --> RZQ/6 ( 40ohm)
+	 * 1** --> RESERVED
+	 */
+	emrs1_cmd |= (1 << 3);
+	emrs1_cmd &= ~BIT6;
+
+	if (mrc_params->ron_value == 0)
+		emrs1_cmd |= BIT7;
+	else
+		emrs1_cmd &= ~BIT7;
+
+	if (mrc_params->rtt_nom_value == 0)
+		emrs1_cmd |= (DDR3_EMRS1_RTTNOM_40 << 6);
+	else if (mrc_params->rtt_nom_value == 1)
+		emrs1_cmd |= (DDR3_EMRS1_RTTNOM_60 << 6);
+	else if (mrc_params->rtt_nom_value == 2)
+		emrs1_cmd |= (DDR3_EMRS1_RTTNOM_120 << 6);
+
+	/* save MRS1 value (excluding control fields) */
+	mrc_params->mrs1 = emrs1_cmd >> 6;
+
+	/*
+	 * setup for mrs 0
+	 * BIT[15:13]     --> Always "0"
+	 * BIT[12]        --> PPD: for Quark (1)
+	 * BIT[11:09]     --> WR: use oem_tWR
+	 * BIT[08]        --> DLL: want "Reset" (1, self clearing)
+	 * BIT[07]        --> MODE: want "Normal" (0)
+	 * BIT[06:04,02]  --> CL: use oem_tCAS
+	 * BIT[03]        --> RD_BURST_TYPE: want "Interleave" (1)
+	 * BIT[01:00]     --> BL: want "8 Fixed" (0)
+	 * WR:
+	 * 0 --> 16
+	 * 1 --> 5
+	 * 2 --> 6
+	 * 3 --> 7
+	 * 4 --> 8
+	 * 5 --> 10
+	 * 6 --> 12
+	 * 7 --> 14
+	 * CL:
+	 * BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
+	 * BIT[06:04] use oem_tCAS-4
+	 */
+	mrs0_cmd |= BIT14;
+	mrs0_cmd |= BIT18;
+	mrs0_cmd |= ((((dtr0 >> 12) & 7) + 1) << 10);
+
+	tck = t_ck[mrc_params->ddr_speed];
+	/* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
+	twr = MCEIL(15000, tck);
+	mrs0_cmd |= ((twr - 4) << 15);
+
+	for (rank = 0; rank < NUM_RANKS; rank++) {
+		/* Skip to next populated rank */
+		if ((mrc_params->rank_enables & (1 << rank)) == 0)
+			continue;
+
+		emrs2_cmd |= (rank << 22);
+		dram_init_command(emrs2_cmd);
+
+		emrs3_cmd |= (rank << 22);
+		dram_init_command(emrs3_cmd);
+
+		emrs1_cmd |= (rank << 22);
+		dram_init_command(emrs1_cmd);
+
+		mrs0_cmd |= (rank << 22);
+		dram_init_command(mrs0_cmd);
+
+		dram_init_command(DCMD_ZQCL(rank));
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * Dunit Initialization Complete
+ *
+ * Indicates that initialization of the Dunit has completed.
+ *
+ * Memory accesses are permitted and maintenance operation begins.
+ * Until this bit is set to a 1, the memory controller will not accept
+ * DRAM requests from the MEMORY_MANAGER or HTE.
+ */
+void set_ddr_init_complete(struct mrc_params *mrc_params)
+{
+	u32 dco;
+
+	ENTERFN();
+
+	dco = msg_port_read(MEM_CTLR, DCO);
+	dco &= ~BIT28;
+	dco |= BIT31;
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	LEAVEFN();
+}
+
+/*
+ * This function will retrieve relevant timing data
+ *
+ * This data will be used on subsequent boots to speed up boot times
+ * and is required for Suspend To RAM capabilities.
+ */
+void restore_timings(struct mrc_params *mrc_params)
+{
+	uint8_t ch, rk, bl;
+	const struct mrc_timings *mt = &mrc_params->timings;
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		for (rk = 0; rk < NUM_RANKS; rk++) {
+			for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+				set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]);
+				set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]);
+				set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]);
+				set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);
+				if (rk == 0) {
+					/* VREF (RANK0 only) */
+					set_vref(ch, bl, mt->vref[ch][bl]);
+				}
+			}
+			set_wctl(ch, rk, mt->wctl[ch][rk]);
+		}
+		set_wcmd(ch, mt->wcmd[ch]);
+	}
+}
+
+/*
+ * Configure default settings normally set as part of read training
+ *
+ * Some defaults have to be set earlier as they may affect earlier
+ * training steps.
+ */
+void default_timings(struct mrc_params *mrc_params)
+{
+	uint8_t ch, rk, bl;
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		for (rk = 0; rk < NUM_RANKS; rk++) {
+			for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+				set_rdqs(ch, rk, bl, 24);
+				if (rk == 0) {
+					/* VREF (RANK0 only) */
+					set_vref(ch, bl, 32);
+				}
+			}
+		}
+	}
+}
+
+/*
+ * This function will perform our RCVEN Calibration Algorithm.
+ * We will only use the 2xCLK domain timings to perform RCVEN Calibration.
+ * All byte lanes will be calibrated "simultaneously" per channel per rank.
+ */
+void rcvn_cal(struct mrc_params *mrc_params)
+{
+	uint8_t ch;	/* channel counter */
+	uint8_t rk;	/* rank counter */
+	uint8_t bl;	/* byte lane counter */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+#ifdef R2R_SHARING
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+#ifndef BACKUP_RCVN
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+#ifdef BACKUP_RCVN
+#else
+	uint32_t temp;
+	/* absolute PI value to be programmed on the byte lane */
+	uint32_t delay[NUM_BYTE_LANES];
+	u32 dtr1, dtr1_save;
+#endif
+
+	ENTERFN();
+
+	/* rcvn_cal starts */
+	mrc_post_code(0x05, 0x00);
+
+#ifndef BACKUP_RCVN
+	/* need separate burst to sample DQS preamble */
+	dtr1 = msg_port_read(MEM_CTLR, DTR1);
+	dtr1_save = dtr1;
+	dtr1 |= BIT12;
+	msg_port_write(MEM_CTLR, DTR1, dtr1);
+#endif
+
+#ifdef R2R_SHARING
+	/* need to set "final_delay[][]" elements to "0" */
+	memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+	/* loop through each enabled channel */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* perform RCVEN Calibration on a per rank basis */
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					/*
+					 * POST_CODE here indicates the current
+					 * channel and rank being calibrated
+					 */
+					mrc_post_code(0x05, (0x10 + ((ch << 4) | rk)));
+
+#ifdef BACKUP_RCVN
+					/* et hard-coded timing values */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++)
+						set_rcvn(ch, rk, bl, ddr_rcvn[PLATFORM_ID]);
+#else
+					/* enable FIFORST */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
+						mrc_alt_write_mask(DDRPHY,
+							(B01PTRCTL1 +
+							((bl >> 1) * DDRIODQ_BL_OFFSET) +
+							(ch * DDRIODQ_CH_OFFSET)),
+							0, BIT8);
+					}
+					/* initialize the starting delay to 128 PI (cas +1 CLK) */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						/* 1x CLK domain timing is cas-4 */
+						delay[bl] = (4 + 1) * FULL_CLK;
+
+						set_rcvn(ch, rk, bl, delay[bl]);
+					}
+
+					/* now find the rising edge */
+					find_rising_edge(mrc_params, delay, ch, rk, true);
+
+					/* Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						delay[bl] += QRTR_CLK;
+						set_rcvn(ch, rk, bl, delay[bl]);
+					}
+					/* Now decrement delay by 128 PI (1 CLK) until we sample a "0" */
+					do {
+						temp = sample_dqs(mrc_params, ch, rk, true);
+						for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+							if (temp & (1 << bl)) {
+								if (delay[bl] >= FULL_CLK) {
+									delay[bl] -= FULL_CLK;
+									set_rcvn(ch, rk, bl, delay[bl]);
+								} else {
+									/* not enough delay */
+									training_message(ch, rk, bl);
+									mrc_post_code(0xEE, 0x50);
+								}
+							}
+						}
+					} while (temp & 0xFF);
+
+#ifdef R2R_SHARING
+					/* increment "num_ranks_enabled" */
+					num_ranks_enabled++;
+					/* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						delay[bl] += QRTR_CLK;
+						/* add "delay[]" values to "final_delay[][]" for rolling average */
+						final_delay[ch][bl] += delay[bl];
+						/* set timing based on rolling average values */
+						set_rcvn(ch, rk, bl, ((final_delay[ch][bl]) / num_ranks_enabled));
+					}
+#else
+					/* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						delay[bl] += QRTR_CLK;
+						set_rcvn(ch, rk, bl, delay[bl]);
+					}
+#endif
+
+					/* disable FIFORST */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
+						mrc_alt_write_mask(DDRPHY,
+							(B01PTRCTL1 +
+							((bl >> 1) * DDRIODQ_BL_OFFSET) +
+							(ch * DDRIODQ_CH_OFFSET)),
+							BIT8, BIT8);
+					}
+#endif
+				}
+			}
+		}
+	}
+
+#ifndef BACKUP_RCVN
+	/* restore original */
+	msg_port_write(MEM_CTLR, DTR1, dtr1_save);
+#endif
+
+	LEAVEFN();
+}
+
+/*
+ * This function will perform the Write Levelling algorithm
+ * (align WCLK and WDQS).
+ *
+ * This algorithm will act on each rank in each channel separately.
+ */
+void wr_level(struct mrc_params *mrc_params)
+{
+	uint8_t ch;	/* channel counter */
+	uint8_t rk;	/* rank counter */
+	uint8_t bl;	/* byte lane counter */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+
+#ifdef R2R_SHARING
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+#ifndef BACKUP_WDQS
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+#ifdef BACKUP_WDQS
+#else
+	/* determines stop condition for CRS_WR_LVL */
+	bool all_edges_found;
+	/* absolute PI value to be programmed on the byte lane */
+	uint32_t delay[NUM_BYTE_LANES];
+	/*
+	 * static makes it so the data is loaded in the heap once by shadow(),
+	 * where non-static copies the data onto the stack every time this
+	 * function is called
+	 */
+	uint32_t address;	/* address to be checked during COARSE_WR_LVL */
+	u32 dtr4, dtr4_save;
+#endif
+
+	ENTERFN();
+
+	/* wr_level starts */
+	mrc_post_code(0x06, 0x00);
+
+#ifdef R2R_SHARING
+	/* need to set "final_delay[][]" elements to "0" */
+	memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+	/* loop through each enabled channel */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			/* perform WRITE LEVELING algorithm on a per rank basis */
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					/*
+					 * POST_CODE here indicates the current
+					 * rank and channel being calibrated
+					 */
+					mrc_post_code(0x06, (0x10 + ((ch << 4) | rk)));
+
+#ifdef BACKUP_WDQS
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						set_wdqs(ch, rk, bl, ddr_wdqs[PLATFORM_ID]);
+						set_wdq(ch, rk, bl, (ddr_wdqs[PLATFORM_ID] - QRTR_CLK));
+					}
+#else
+					/*
+					 * perform a single PRECHARGE_ALL command to
+					 * make DRAM state machine go to IDLE state
+					 */
+					dram_init_command(DCMD_PREA(rk));
+
+					/*
+					 * enable Write Levelling Mode
+					 * (EMRS1 w/ Write Levelling Mode Enable)
+					 */
+					dram_init_command(DCMD_MRS1(rk, 0x0082));
+
+					/*
+					 * set ODT DRAM Full Time Termination
+					 * disable in MCU
+					 */
+
+					dtr4 = msg_port_read(MEM_CTLR, DTR4);
+					dtr4_save = dtr4;
+					dtr4 |= BIT15;
+					msg_port_write(MEM_CTLR, DTR4, dtr4);
+
+					for (bl = 0; bl < ((NUM_BYTE_LANES / bl_divisor) / 2); bl++) {
+						/*
+						 * Enable Sandy Bridge Mode (WDQ Tri-State) &
+						 * Ensure 5 WDQS pulses during Write Leveling
+						 */
+						mrc_alt_write_mask(DDRPHY,
+							DQCTL + (DDRIODQ_BL_OFFSET * bl) + (DDRIODQ_CH_OFFSET * ch),
+							(BIT28 | BIT8 | BIT6 | BIT4 | BIT2),
+							(BIT28 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+					}
+
+					/* Write Leveling Mode enabled in IO */
+					mrc_alt_write_mask(DDRPHY,
+						CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * ch),
+						BIT16, BIT16);
+
+					/* Initialize the starting delay to WCLK */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						/*
+						 * CLK0 --> RK0
+						 * CLK1 --> RK1
+						 */
+						delay[bl] = get_wclk(ch, rk);
+
+						set_wdqs(ch, rk, bl, delay[bl]);
+					}
+
+					/* now find the rising edge */
+					find_rising_edge(mrc_params, delay, ch, rk, false);
+
+					/* disable Write Levelling Mode */
+					mrc_alt_write_mask(DDRPHY,
+						CCDDR3RESETCTL + (DDRIOCCC_CH_OFFSET * ch),
+						0, BIT16);
+
+					for (bl = 0; bl < ((NUM_BYTE_LANES / bl_divisor) / 2); bl++) {
+						/* Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation */
+						mrc_alt_write_mask(DDRPHY,
+							DQCTL + (DDRIODQ_BL_OFFSET * bl) + (DDRIODQ_CH_OFFSET * ch),
+							(BIT8 | BIT6 | BIT4 | BIT2),
+							(BIT28 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
+					}
+
+					/* restore original DTR4 */
+					msg_port_write(MEM_CTLR, DTR4, dtr4_save);
+
+					/*
+					 * restore original value
+					 * (Write Levelling Mode Disable)
+					 */
+					dram_init_command(DCMD_MRS1(rk, mrc_params->mrs1));
+
+					/*
+					 * perform a single PRECHARGE_ALL command to
+					 * make DRAM state machine go to IDLE state
+					 */
+					dram_init_command(DCMD_PREA(rk));
+
+					mrc_post_code(0x06, (0x30 + ((ch << 4) | rk)));
+
+					/*
+					 * COARSE WRITE LEVEL:
+					 * check that we're on the correct clock edge
+					 */
+
+					/* hte reconfiguration request */
+					mrc_params->hte_setup = 1;
+
+					/* start CRS_WR_LVL with WDQS = WDQS + 128 PI */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						delay[bl] = get_wdqs(ch, rk, bl) + FULL_CLK;
+						set_wdqs(ch, rk, bl, delay[bl]);
+						/*
+						 * program WDQ timings based on WDQS
+						 * (WDQ = WDQS - 32 PI)
+						 */
+						set_wdq(ch, rk, bl, (delay[bl] - QRTR_CLK));
+					}
+
+					/* get an address in the targeted channel/rank */
+					address = get_addr(ch, rk);
+					do {
+						uint32_t coarse_result = 0x00;
+						uint32_t coarse_result_mask = byte_lane_mask(mrc_params);
+						/* assume pass */
+						all_edges_found = true;
+
+						mrc_params->hte_setup = 1;
+						coarse_result = check_rw_coarse(mrc_params, address);
+
+						/* check for failures and margin the byte lane back 128 PI (1 CLK) */
+						for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+							if (coarse_result & (coarse_result_mask << bl)) {
+								all_edges_found = false;
+								delay[bl] -= FULL_CLK;
+								set_wdqs(ch, rk, bl, delay[bl]);
+								/* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
+								set_wdq(ch, rk, bl, (delay[bl] - QRTR_CLK));
+							}
+						}
+					} while (!all_edges_found);
+
+#ifdef R2R_SHARING
+					/* increment "num_ranks_enabled" */
+					 num_ranks_enabled++;
+					/* accumulate "final_delay[][]" values from "delay[]" values for rolling average */
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						final_delay[ch][bl] += delay[bl];
+						set_wdqs(ch, rk, bl, ((final_delay[ch][bl]) / num_ranks_enabled));
+						/* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
+						set_wdq(ch, rk, bl, ((final_delay[ch][bl]) / num_ranks_enabled) - QRTR_CLK);
+					}
+#endif
+#endif
+				}
+			}
+		}
+	}
+
+	LEAVEFN();
+}
+
+void prog_page_ctrl(struct mrc_params *mrc_params)
+{
+	u32 dpmc0;
+
+	ENTERFN();
+
+	dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+	dpmc0 &= ~(BIT16 | BIT17 | BIT18);
+	dpmc0 |= (4 << 16);
+	dpmc0 |= BIT21;
+	msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+}
+
+/*
+ * This function will perform the READ TRAINING Algorithm on all
+ * channels/ranks/byte_lanes simultaneously to minimize execution time.
+ *
+ * The idea here is to train the VREF and RDQS (and eventually RDQ) values
+ * to achieve maximum READ margins. The algorithm will first determine the
+ * X coordinate (RDQS setting). This is done by collapsing the VREF eye
+ * until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.
+ * Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX,
+ * then average those; this will be the final X coordinate. The algorithm
+ * will then determine the Y coordinate (VREF setting). This is done by
+ * collapsing the RDQS eye until we find a minimum required VREF eye for
+ * RDQS_MIN and RDQS_MAX. Then we take the averages of the VREF eye at
+ * RDQS_MIN and RDQS_MAX, then average those; this will be the final Y
+ * coordinate.
+ *
+ * NOTE: this algorithm assumes the eye curves have a one-to-one relationship,
+ * meaning for each X the curve has only one Y and vice-a-versa.
+ */
+void rd_train(struct mrc_params *mrc_params)
+{
+	uint8_t ch;	/* channel counter */
+	uint8_t rk;	/* rank counter */
+	uint8_t bl;	/* byte lane counter */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+#ifdef BACKUP_RDQS
+#else
+	uint8_t side_x;	/* tracks LEFT/RIGHT approach vectors */
+	uint8_t side_y;	/* tracks BOTTOM/TOP approach vectors */
+	/* X coordinate data (passing RDQS values) for approach vectors */
+	uint8_t x_coordinate[2][2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	/* Y coordinate data (passing VREF values) for approach vectors */
+	uint8_t y_coordinate[2][2][NUM_CHANNELS][NUM_BYTE_LANES];
+	/* centered X (RDQS) */
+	uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	/* centered Y (VREF) */
+	uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES];
+	uint32_t address;	/* target address for check_bls_ex() */
+	uint32_t result;	/* result of check_bls_ex() */
+	uint32_t bl_mask;	/* byte lane mask for result checking */
+#ifdef R2R_SHARING
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+	/* rd_train starts */
+	mrc_post_code(0x07, 0x00);
+
+	ENTERFN();
+
+#ifdef BACKUP_RDQS
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					for (bl = 0;
+					     bl < (NUM_BYTE_LANES / bl_divisor);
+					     bl++) {
+						set_rdqs(ch, rk, bl, ddr_rdqs[PLATFORM_ID]);
+					}
+				}
+			}
+		}
+	}
+#else
+	/* initialize x/y_coordinate arrays */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					for (bl = 0;
+					     bl < (NUM_BYTE_LANES / bl_divisor);
+					     bl++) {
+						/* x_coordinate */
+						x_coordinate[L][B][ch][rk][bl] = RDQS_MIN;
+						x_coordinate[R][B][ch][rk][bl] = RDQS_MAX;
+						x_coordinate[L][T][ch][rk][bl] = RDQS_MIN;
+						x_coordinate[R][T][ch][rk][bl] = RDQS_MAX;
+						/* y_coordinate */
+						y_coordinate[L][B][ch][bl] = VREF_MIN;
+						y_coordinate[R][B][ch][bl] = VREF_MIN;
+						y_coordinate[L][T][ch][bl] = VREF_MAX;
+						y_coordinate[R][T][ch][bl] = VREF_MAX;
+					}
+				}
+			}
+		}
+	}
+
+	/* initialize other variables */
+	bl_mask = byte_lane_mask(mrc_params);
+	address = get_addr(0, 0);
+
+#ifdef R2R_SHARING
+	/* need to set "final_delay[][]" elements to "0" */
+	memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+	/* look for passing coordinates */
+	for (side_y = B; side_y <= T; side_y++) {
+		for (side_x = L; side_x <= R; side_x++) {
+			mrc_post_code(0x07, (0x10 + (side_y * 2) + (side_x)));
+
+			/* find passing values */
+			for (ch = 0; ch < NUM_CHANNELS; ch++) {
+				if (mrc_params->channel_enables & (0x1 << ch)) {
+					for (rk = 0; rk < NUM_RANKS; rk++) {
+						if (mrc_params->rank_enables &
+							(0x1 << rk)) {
+							/* set x/y_coordinate search starting settings */
+							for (bl = 0;
+							     bl < (NUM_BYTE_LANES / bl_divisor);
+							     bl++) {
+								set_rdqs(ch, rk, bl,
+									 x_coordinate[side_x][side_y][ch][rk][bl]);
+								set_vref(ch, bl,
+									 y_coordinate[side_x][side_y][ch][bl]);
+							}
+
+							/* get an address in the target channel/rank */
+							address = get_addr(ch, rk);
+
+							/* request HTE reconfiguration */
+							mrc_params->hte_setup = 1;
+
+							/* test the settings */
+							do {
+								/* result[07:00] == failing byte lane (MAX 8) */
+								result = check_bls_ex(mrc_params, address);
+
+								/* check for failures */
+								if (result & 0xFF) {
+									/* at least 1 byte lane failed */
+									for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+										if (result &
+											(bl_mask << bl)) {
+											/* adjust the RDQS values accordingly */
+											if (side_x == L)
+												x_coordinate[L][side_y][ch][rk][bl] += RDQS_STEP;
+											else
+												x_coordinate[R][side_y][ch][rk][bl] -= RDQS_STEP;
+
+											/* check that we haven't closed the RDQS_EYE too much */
+											if ((x_coordinate[L][side_y][ch][rk][bl] > (RDQS_MAX - MIN_RDQS_EYE)) ||
+												(x_coordinate[R][side_y][ch][rk][bl] < (RDQS_MIN + MIN_RDQS_EYE)) ||
+												(x_coordinate[L][side_y][ch][rk][bl] ==
+												x_coordinate[R][side_y][ch][rk][bl])) {
+												/*
+												 * not enough RDQS margin available at this VREF
+												 * update VREF values accordingly
+												 */
+												if (side_y == B)
+													y_coordinate[side_x][B][ch][bl] += VREF_STEP;
+												else
+													y_coordinate[side_x][T][ch][bl] -= VREF_STEP;
+
+												/* check that we haven't closed the VREF_EYE too much */
+												if ((y_coordinate[side_x][B][ch][bl] > (VREF_MAX - MIN_VREF_EYE)) ||
+													(y_coordinate[side_x][T][ch][bl] < (VREF_MIN + MIN_VREF_EYE)) ||
+													(y_coordinate[side_x][B][ch][bl] == y_coordinate[side_x][T][ch][bl])) {
+													/* VREF_EYE collapsed below MIN_VREF_EYE */
+													training_message(ch, rk, bl);
+													mrc_post_code(0xEE, (0x70 + (side_y * 2) + (side_x)));
+												} else {
+													/* update the VREF setting */
+													set_vref(ch, bl, y_coordinate[side_x][side_y][ch][bl]);
+													/* reset the X coordinate to begin the search at the new VREF */
+													x_coordinate[side_x][side_y][ch][rk][bl] =
+														(side_x == L) ? (RDQS_MIN) : (RDQS_MAX);
+												}
+											}
+
+											/* update the RDQS setting */
+											set_rdqs(ch, rk, bl, x_coordinate[side_x][side_y][ch][rk][bl]);
+										}
+									}
+								}
+							} while (result & 0xFF);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	mrc_post_code(0x07, 0x20);
+
+	/* find final RDQS (X coordinate) & final VREF (Y coordinate) */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						uint32_t temp1;
+						uint32_t temp2;
+
+						/* x_coordinate */
+						DPF(D_INFO,
+						    "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n",
+						    rk, bl,
+						    x_coordinate[L][T][ch][rk][bl],
+						    x_coordinate[R][T][ch][rk][bl],
+						    x_coordinate[L][B][ch][rk][bl],
+						    x_coordinate[R][B][ch][rk][bl]);
+
+						/* average the TOP side LEFT & RIGHT values */
+						temp1 = (x_coordinate[R][T][ch][rk][bl] + x_coordinate[L][T][ch][rk][bl]) / 2;
+						/* average the BOTTOM side LEFT & RIGHT values */
+						temp2 = (x_coordinate[R][B][ch][rk][bl] + x_coordinate[L][B][ch][rk][bl]) / 2;
+						/* average the above averages */
+						x_center[ch][rk][bl] = (uint8_t) ((temp1 + temp2) / 2);
+
+						/* y_coordinate */
+						DPF(D_INFO,
+						    "VREF R/L eye lane%d : %d-%d %d-%d\n",
+						    bl,
+						    y_coordinate[R][B][ch][bl],
+						    y_coordinate[R][T][ch][bl],
+						    y_coordinate[L][B][ch][bl],
+						    y_coordinate[L][T][ch][bl]);
+
+						/* average the RIGHT side TOP & BOTTOM values */
+						temp1 = (y_coordinate[R][T][ch][bl] + y_coordinate[R][B][ch][bl]) / 2;
+						/* average the LEFT side TOP & BOTTOM values */
+						temp2 = (y_coordinate[L][T][ch][bl] + y_coordinate[L][B][ch][bl]) / 2;
+						/* average the above averages */
+						y_center[ch][bl] = (uint8_t) ((temp1 + temp2) / 2);
+					}
+				}
+			}
+		}
+	}
+
+#ifdef RX_EYE_CHECK
+	/* perform an eye check */
+	for (side_y = B; side_y <= T; side_y++) {
+		for (side_x = L; side_x <= R; side_x++) {
+			mrc_post_code(0x07, (0x30 + (side_y * 2) + (side_x)));
+
+			/* update the settings for the eye check */
+			for (ch = 0; ch < NUM_CHANNELS; ch++) {
+				if (mrc_params->channel_enables & (1 << ch)) {
+					for (rk = 0; rk < NUM_RANKS; rk++) {
+						if (mrc_params->rank_enables & (1 << rk)) {
+							for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+								if (side_x == L)
+									set_rdqs(ch, rk, bl, (x_center[ch][rk][bl] - (MIN_RDQS_EYE / 2)));
+								else
+									set_rdqs(ch, rk, bl, (x_center[ch][rk][bl] + (MIN_RDQS_EYE / 2)));
+
+								if (side_y == B)
+									set_vref(ch, bl, (y_center[ch][bl] - (MIN_VREF_EYE / 2)));
+								else
+									set_vref(ch, bl, (y_center[ch][bl] + (MIN_VREF_EYE / 2)));
+							}
+						}
+					}
+				}
+			}
+
+			/* request HTE reconfiguration */
+			mrc_params->hte_setup = 1;
+
+			/* check the eye */
+			if (check_bls_ex(mrc_params, address) & 0xFF) {
+				/* one or more byte lanes failed */
+				mrc_post_code(0xEE, (0x74 + (side_x * 2) + (side_y)));
+			}
+		}
+	}
+#endif
+
+	mrc_post_code(0x07, 0x40);
+
+	/* set final placements */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+#ifdef R2R_SHARING
+					/* increment "num_ranks_enabled" */
+					num_ranks_enabled++;
+#endif
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						/* x_coordinate */
+#ifdef R2R_SHARING
+						final_delay[ch][bl] += x_center[ch][rk][bl];
+						set_rdqs(ch, rk, bl, ((final_delay[ch][bl]) / num_ranks_enabled));
+#else
+						set_rdqs(ch, rk, bl, x_center[ch][rk][bl]);
+#endif
+						/* y_coordinate */
+						set_vref(ch, bl, y_center[ch][bl]);
+					}
+				}
+			}
+		}
+	}
+#endif
+
+	LEAVEFN();
+}
+
+/*
+ * This function will perform the WRITE TRAINING Algorithm on all
+ * channels/ranks/byte_lanes simultaneously to minimize execution time.
+ *
+ * The idea here is to train the WDQ timings to achieve maximum WRITE margins.
+ * The algorithm will start with WDQ at the current WDQ setting (tracks WDQS
+ * in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data
+ * patterns pass. This is because WDQS will be aligned to WCLK by the
+ * Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window
+ * of validity.
+ */
+void wr_train(struct mrc_params *mrc_params)
+{
+	uint8_t ch;	/* channel counter */
+	uint8_t rk;	/* rank counter */
+	uint8_t bl;	/* byte lane counter */
+	uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
+#ifdef BACKUP_WDQ
+#else
+	uint8_t side;		/* LEFT/RIGHT side indicator (0=L, 1=R) */
+	uint32_t temp;		/* temporary DWORD */
+	/* 2 arrays, for L & R side passing delays */
+	uint32_t delay[2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	uint32_t address;	/* target address for check_bls_ex() */
+	uint32_t result;	/* result of check_bls_ex() */
+	uint32_t bl_mask;	/* byte lane mask for result checking */
+#ifdef R2R_SHARING
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
+	/* used to find placement for rank2rank sharing configs */
+	uint32_t num_ranks_enabled = 0;
+#endif
+#endif
+
+	/* wr_train starts */
+	mrc_post_code(0x08, 0x00);
+
+	ENTERFN();
+
+#ifdef BACKUP_WDQ
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					for (bl = 0;
+					     bl < (NUM_BYTE_LANES / bl_divisor);
+					     bl++) {
+						set_wdq(ch, rk, bl, ddr_wdq[PLATFORM_ID]);
+					}
+				}
+			}
+		}
+	}
+#else
+	/* initialize "delay" */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+					for (bl = 0;
+					     bl < (NUM_BYTE_LANES / bl_divisor);
+					     bl++) {
+						/*
+						 * want to start with
+						 * WDQ = (WDQS - QRTR_CLK)
+						 * +/- QRTR_CLK
+						 */
+						temp = get_wdqs(ch, rk, bl) - QRTR_CLK;
+						delay[L][ch][rk][bl] = temp - QRTR_CLK;
+						delay[R][ch][rk][bl] = temp + QRTR_CLK;
+					}
+				}
+			}
+		}
+	}
+
+	/* initialize other variables */
+	bl_mask = byte_lane_mask(mrc_params);
+	address = get_addr(0, 0);
+
+#ifdef R2R_SHARING
+	/* need to set "final_delay[][]" elements to "0" */
+	memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
+#endif
+
+	/*
+	 * start algorithm on the LEFT side and train each channel/bl
+	 * until no failures are observed, then repeat for the RIGHT side.
+	 */
+	for (side = L; side <= R; side++) {
+		mrc_post_code(0x08, (0x10 + (side)));
+
+		/* set starting values */
+		for (ch = 0; ch < NUM_CHANNELS; ch++) {
+			if (mrc_params->channel_enables & (1 << ch)) {
+				for (rk = 0; rk < NUM_RANKS; rk++) {
+					if (mrc_params->rank_enables &
+						(1 << rk)) {
+						for (bl = 0;
+						     bl < (NUM_BYTE_LANES / bl_divisor);
+						     bl++) {
+							set_wdq(ch, rk, bl, delay[side][ch][rk][bl]);
+						}
+					}
+				}
+			}
+		}
+
+		/* find passing values */
+		for (ch = 0; ch < NUM_CHANNELS; ch++) {
+			if (mrc_params->channel_enables & (1 << ch)) {
+				for (rk = 0; rk < NUM_RANKS; rk++) {
+					if (mrc_params->rank_enables &
+						(1 << rk)) {
+						/* get an address in the target channel/rank */
+						address = get_addr(ch, rk);
+
+						/* request HTE reconfiguration */
+						mrc_params->hte_setup = 1;
+
+						/* check the settings */
+						do {
+							/* result[07:00] == failing byte lane (MAX 8) */
+							result = check_bls_ex(mrc_params, address);
+							/* check for failures */
+							if (result & 0xFF) {
+								/* at least 1 byte lane failed */
+								for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+									if (result &
+										(bl_mask << bl)) {
+										if (side == L)
+											delay[L][ch][rk][bl] += WDQ_STEP;
+										else
+											delay[R][ch][rk][bl] -= WDQ_STEP;
+
+										/* check for algorithm failure */
+										if (delay[L][ch][rk][bl] != delay[R][ch][rk][bl]) {
+											/*
+											 * margin available
+											 * update delay setting
+											 */
+											set_wdq(ch, rk, bl,
+												delay[side][ch][rk][bl]);
+										} else {
+											/*
+											 * no margin available
+											 * notify the user and halt
+											 */
+											training_message(ch, rk, bl);
+											mrc_post_code(0xEE, (0x80 + side));
+										}
+									}
+								}
+							}
+						/* stop when all byte lanes pass */
+						} while (result & 0xFF);
+					}
+				}
+			}
+		}
+	}
+
+	/* program WDQ to the middle of passing window */
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		if (mrc_params->channel_enables & (1 << ch)) {
+			for (rk = 0; rk < NUM_RANKS; rk++) {
+				if (mrc_params->rank_enables & (1 << rk)) {
+#ifdef R2R_SHARING
+					/* increment "num_ranks_enabled" */
+					num_ranks_enabled++;
+#endif
+					for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
+						DPF(D_INFO,
+						    "WDQ eye rank%d lane%d : %d-%d\n",
+						    rk, bl,
+						    delay[L][ch][rk][bl],
+						    delay[R][ch][rk][bl]);
+
+						temp = (delay[R][ch][rk][bl] + delay[L][ch][rk][bl]) / 2;
+
+#ifdef R2R_SHARING
+						final_delay[ch][bl] += temp;
+						set_wdq(ch, rk, bl,
+							((final_delay[ch][bl]) / num_ranks_enabled));
+#else
+						set_wdq(ch, rk, bl, temp);
+#endif
+					}
+				}
+			}
+		}
+	}
+#endif
+
+	LEAVEFN();
+}
+
+/*
+ * This function will store relevant timing data
+ *
+ * This data will be used on subsequent boots to speed up boot times
+ * and is required for Suspend To RAM capabilities.
+ */
+void store_timings(struct mrc_params *mrc_params)
+{
+	uint8_t ch, rk, bl;
+	struct mrc_timings *mt = &mrc_params->timings;
+
+	for (ch = 0; ch < NUM_CHANNELS; ch++) {
+		for (rk = 0; rk < NUM_RANKS; rk++) {
+			for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
+				mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl);
+				mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl);
+				mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl);
+				mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);
+
+				if (rk == 0)
+					mt->vref[ch][bl] = get_vref(ch, bl);
+			}
+
+			mt->wctl[ch][rk] = get_wctl(ch, rk);
+		}
+
+		mt->wcmd[ch] = get_wcmd(ch);
+	}
+
+	/* need to save for a case of changing frequency after warm reset */
+	mt->ddr_speed = mrc_params->ddr_speed;
+}
+
+/*
+ * The purpose of this function is to ensure the SEC comes out of reset
+ * and IA initiates the SEC enabling Memory Scrambling.
+ */
+void enable_scrambling(struct mrc_params *mrc_params)
+{
+	uint32_t lfsr = 0;
+	uint8_t i;
+
+	if (mrc_params->scrambling_enables == 0)
+		return;
+
+	ENTERFN();
+
+	/* 32 bit seed is always stored in BIOS NVM */
+	lfsr = mrc_params->timings.scrambler_seed;
+
+	if (mrc_params->boot_mode == BM_COLD) {
+		/*
+		 * factory value is 0 and in first boot,
+		 * a clock based seed is loaded.
+		 */
+		if (lfsr == 0) {
+			/*
+			 * get seed from system clock
+			 * and make sure it is not all 1's
+			 */
+			lfsr = rdtsc() & 0x0FFFFFFF;
+		} else {
+			/*
+			 * Need to replace scrambler
+			 *
+			 * get next 32bit LFSR 16 times which is the last
+			 * part of the previous scrambler vector
+			 */
+			for (i = 0; i < 16; i++)
+				lfsr32(&lfsr);
+		}
+
+		/* save new seed */
+		mrc_params->timings.scrambler_seed = lfsr;
+	}
+
+	/*
+	 * In warm boot or S3 exit, we have the previous seed.
+	 * In cold boot, we have the last 32bit LFSR which is the new seed.
+	 */
+	lfsr32(&lfsr);	/* shift to next value */
+	msg_port_write(MEM_CTLR, SCRMSEED, (lfsr & 0x0003FFFF));
+
+	for (i = 0; i < 2; i++)
+		msg_port_write(MEM_CTLR, SCRMLO + i, (lfsr & 0xAAAAAAAA));
+
+	LEAVEFN();
+}
+
+/*
+ * Configure MCU Power Management Control Register
+ * and Scheduler Control Register
+ */
+void prog_ddr_control(struct mrc_params *mrc_params)
+{
+	u32 dsch;
+	u32 dpmc0;
+
+	ENTERFN();
+
+	dsch = msg_port_read(MEM_CTLR, DSCH);
+	dsch &= ~(BIT8 | BIT9 | BIT12);
+	msg_port_write(MEM_CTLR, DSCH, dsch);
+
+	dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+	dpmc0 &= ~BIT25;
+	dpmc0 |= (mrc_params->power_down_disable << 25);
+	dpmc0 &= ~BIT24;
+	dpmc0 &= ~(BIT16 | BIT17 | BIT18);
+	dpmc0 |= (4 << 16);
+	dpmc0 |= BIT21;
+	msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+	/* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
+	mrc_write_mask(MEM_CTLR, DPMC1, 2 << 4, BIT4 | BIT5);
+
+	LEAVEFN();
+}
+
+/*
+ * After training complete configure MCU Rank Population Register
+ * specifying: ranks enabled, device width, density, address mode
+ */
+void prog_dra_drb(struct mrc_params *mrc_params)
+{
+	u32 drp;
+	u32 dco;
+	u8 density = mrc_params->params.density;
+
+	ENTERFN();
+
+	dco = msg_port_read(MEM_CTLR, DCO);
+	dco &= ~BIT31;
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	drp = 0;
+	if (mrc_params->rank_enables & 1)
+		drp |= BIT0;
+	if (mrc_params->rank_enables & 2)
+		drp |= BIT1;
+	if (mrc_params->dram_width == X16) {
+		drp |= (1 << 4);
+		drp |= (1 << 9);
+	}
+
+	/*
+	 * Density encoding in struct dram_params: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+	 * has to be mapped RANKDENSx encoding (0=1Gb)
+	 */
+	if (density == 0)
+		density = 4;
+
+	drp |= ((density - 1) << 6);
+	drp |= ((density - 1) << 11);
+
+	/* Address mode can be overwritten if ECC enabled */
+	drp |= (mrc_params->address_mode << 14);
+
+	msg_port_write(MEM_CTLR, DRP, drp);
+
+	dco &= ~BIT28;
+	dco |= BIT31;
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	LEAVEFN();
+}
+
+/* Send DRAM wake command */
+void perform_wake(struct mrc_params *mrc_params)
+{
+	ENTERFN();
+
+	dram_wake_command();
+
+	LEAVEFN();
+}
+
+/*
+ * Configure refresh rate and short ZQ calibration interval
+ * Activate dynamic self refresh
+ */
+void change_refresh_period(struct mrc_params *mrc_params)
+{
+	u32 drfc;
+	u32 dcal;
+	u32 dpmc0;
+
+	ENTERFN();
+
+	drfc = msg_port_read(MEM_CTLR, DRFC);
+	drfc &= ~(BIT12 | BIT13 | BIT14);
+	drfc |= (mrc_params->refresh_rate << 12);
+	drfc |= BIT21;
+	msg_port_write(MEM_CTLR, DRFC, drfc);
+
+	dcal = msg_port_read(MEM_CTLR, DCAL);
+	dcal &= ~(BIT8 | BIT9 | BIT10);
+	dcal |= (3 << 8);	/* 63ms */
+	msg_port_write(MEM_CTLR, DCAL, dcal);
+
+	dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
+	dpmc0 |= (BIT23 | BIT29);
+	msg_port_write(MEM_CTLR, DPMC0, dpmc0);
+
+	LEAVEFN();
+}
+
+/*
+ * Configure DDRPHY for Auto-Refresh, Periodic Compensations,
+ * Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
+ */
+void set_auto_refresh(struct mrc_params *mrc_params)
+{
+	uint32_t channel;
+	uint32_t rank;
+	uint32_t bl;
+	uint32_t bl_divisor = 1;
+	uint32_t temp;
+
+	ENTERFN();
+
+	/*
+	 * Enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp,
+	 * ZQSPERIOD, Auto-Precharge, CKE Power-Down
+	 */
+	for (channel = 0; channel < NUM_CHANNELS; channel++) {
+		if (mrc_params->channel_enables & (1 << channel)) {
+			/* Enable Periodic RCOMPS */
+			mrc_alt_write_mask(DDRPHY, CMPCTRL, BIT1, BIT1);
+
+			/* Enable Dynamic DiffAmp & Set Read ODT Value */
+			switch (mrc_params->rd_odt_value) {
+			case 0:
+				temp = 0x3F;	/* OFF */
+				break;
+			default:
+				temp = 0x00;	/* Auto */
+				break;
+			}
+
+			for (bl = 0; bl < ((NUM_BYTE_LANES / bl_divisor) / 2); bl++) {
+				/* Override: DIFFAMP, ODT */
+				mrc_alt_write_mask(DDRPHY,
+					(B0OVRCTL + (bl * DDRIODQ_BL_OFFSET) +
+					(channel * DDRIODQ_CH_OFFSET)),
+					(0x00 << 16) | (temp << 10),
+					(BIT21 | BIT20 | BIT19 | BIT18 |
+					 BIT17 | BIT16 | BIT15 | BIT14 |
+					 BIT13 | BIT12 | BIT11 | BIT10));
+
+				/* Override: DIFFAMP, ODT */
+				mrc_alt_write_mask(DDRPHY,
+					(B1OVRCTL + (bl * DDRIODQ_BL_OFFSET) +
+					(channel * DDRIODQ_CH_OFFSET)),
+					(0x00 << 16) | (temp << 10),
+					(BIT21 | BIT20 | BIT19 | BIT18 |
+					 BIT17 | BIT16 | BIT15 | BIT14 |
+					 BIT13 | BIT12 | BIT11 | BIT10));
+			}
+
+			/* Issue ZQCS command */
+			for (rank = 0; rank < NUM_RANKS; rank++) {
+				if (mrc_params->rank_enables & (1 << rank))
+					dram_init_command(DCMD_ZQCS(rank));
+			}
+		}
+	}
+
+	clear_pointers();
+
+	LEAVEFN();
+}
+
+/*
+ * Depending on configuration enables ECC support
+ *
+ * Available memory size is decreased, and updated with 0s
+ * in order to clear error status. Address mode 2 forced.
+ */
+void ecc_enable(struct mrc_params *mrc_params)
+{
+	u32 drp;
+	u32 dsch;
+	u32 ecc_ctrl;
+
+	if (mrc_params->ecc_enables == 0)
+		return;
+
+	ENTERFN();
+
+	/* Configuration required in ECC mode */
+	drp = msg_port_read(MEM_CTLR, DRP);
+	drp &= ~(BIT14 | BIT15);
+	drp |= BIT15;
+	drp |= BIT13;
+	msg_port_write(MEM_CTLR, DRP, drp);
+
+	/* Disable new request bypass */
+	dsch = msg_port_read(MEM_CTLR, DSCH);
+	dsch |= BIT12;
+	msg_port_write(MEM_CTLR, DSCH, dsch);
+
+	/* Enable ECC */
+	ecc_ctrl = (BIT0 | BIT1 | BIT17);
+	msg_port_write(MEM_CTLR, DECCCTRL, ecc_ctrl);
+
+	/* Assume 8 bank memory, one bank is gone for ECC */
+	mrc_params->mem_size -= mrc_params->mem_size / 8;
+
+	/* For S3 resume memory content has to be preserved */
+	if (mrc_params->boot_mode != BM_S3) {
+		select_hte();
+		hte_mem_init(mrc_params, MRC_MEM_INIT);
+		select_mem_mgr();
+	}
+
+	LEAVEFN();
+}
+
+/*
+ * Execute memory test
+ * if error detected it is indicated in mrc_params->status
+ */
+void memory_test(struct mrc_params *mrc_params)
+{
+	uint32_t result = 0;
+
+	ENTERFN();
+
+	select_hte();
+	result = hte_mem_init(mrc_params, MRC_MEM_TEST);
+	select_mem_mgr();
+
+	DPF(D_INFO, "Memory test result %x\n", result);
+	mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);
+	LEAVEFN();
+}
+
+/* Lock MCU registers at the end of initialization sequence */
+void lock_registers(struct mrc_params *mrc_params)
+{
+	u32 dco;
+
+	ENTERFN();
+
+	dco = msg_port_read(MEM_CTLR, DCO);
+	dco &= ~(BIT28 | BIT29);
+	dco |= (BIT0 | BIT8);
+	msg_port_write(MEM_CTLR, DCO, dco);
+
+	LEAVEFN();
+}
diff --git a/arch/x86/cpu/quark/smc.h b/arch/x86/cpu/quark/smc.h
new file mode 100644
index 0000000..46017a1
--- /dev/null
+++ b/arch/x86/cpu/quark/smc.h
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef _SMC_H_
+#define _SMC_H_
+
+/* System Memory Controller Register Defines */
+
+/* Memory Controller Message Bus Registers Offsets */
+#define DRP			0x00
+#define DTR0			0x01
+#define DTR1			0x02
+#define DTR2			0x03
+#define DTR3			0x04
+#define DTR4			0x05
+#define DPMC0			0x06
+#define DPMC1			0x07
+#define DRFC			0x08
+#define DSCH			0x09
+#define DCAL			0x0A
+#define DRMC			0x0B
+#define PMSTS			0x0C
+#define DCO			0x0F
+#define DSTAT			0x20
+#define SSKPD0			0x4A
+#define SSKPD1			0x4B
+#define DECCCTRL		0x60
+#define DECCSTAT		0x61
+#define DECCSBECNT		0x62
+#define DECCSBECA		0x68
+#define DECCSBECS		0x69
+#define DECCDBECA		0x6A
+#define DECCDBECS		0x6B
+#define DFUSESTAT		0x70
+#define SCRMSEED		0x80
+#define SCRMLO			0x81
+#define SCRMHI			0x82
+
+/* DRAM init command */
+#define DCMD_MRS1(rnk, dat)	(0 | ((rnk) << 22) | (1 << 3) | ((dat) << 6))
+#define DCMD_REF(rnk)		(1 | ((rnk) << 22))
+#define DCMD_PRE(rnk)		(2 | ((rnk) << 22))
+#define DCMD_PREA(rnk)		(2 | ((rnk) << 22) | (BIT10 << 6))
+#define DCMD_ACT(rnk, row)	(3 | ((rnk) << 22) | ((row) << 6))
+#define DCMD_WR(rnk, col)	(4 | ((rnk) << 22) | ((col) << 6))
+#define DCMD_RD(rnk, col)	(5 | ((rnk) << 22) | ((col) << 6))
+#define DCMD_ZQCS(rnk)		(6 | ((rnk) << 22))
+#define DCMD_ZQCL(rnk)		(6 | ((rnk) << 22) | (BIT10 << 6))
+#define DCMD_NOP(rnk)		(7 | ((rnk) << 22))
+
+#define DDR3_EMRS1_DIC_40	(0)
+#define DDR3_EMRS1_DIC_34	(1)
+
+#define DDR3_EMRS1_RTTNOM_0	(0)
+#define DDR3_EMRS1_RTTNOM_60	(0x04)
+#define DDR3_EMRS1_RTTNOM_120	(0x40)
+#define DDR3_EMRS1_RTTNOM_40	(0x44)
+#define DDR3_EMRS1_RTTNOM_20	(0x200)
+#define DDR3_EMRS1_RTTNOM_30	(0x204)
+
+#define DDR3_EMRS2_RTTWR_60	(1 << 9)
+#define DDR3_EMRS2_RTTWR_120	(1 << 10)
+
+/* BEGIN DDRIO Registers */
+
+/* DDR IOs & COMPs */
+#define DDRIODQ_BL_OFFSET	0x0800
+#define DDRIODQ_CH_OFFSET	((NUM_BYTE_LANES / 2) * DDRIODQ_BL_OFFSET)
+#define DDRIOCCC_CH_OFFSET	0x0800
+#define DDRCOMP_CH_OFFSET	0x0100
+
+/* CH0-BL01-DQ */
+#define DQOBSCKEBBCTL		0x0000
+#define DQDLLTXCTL		0x0004
+#define DQDLLRXCTL		0x0008
+#define DQMDLLCTL		0x000C
+#define B0RXIOBUFCTL		0x0010
+#define B0VREFCTL		0x0014
+#define B0RXOFFSET1		0x0018
+#define B0RXOFFSET0		0x001C
+#define B1RXIOBUFCTL		0x0020
+#define B1VREFCTL		0x0024
+#define B1RXOFFSET1		0x0028
+#define B1RXOFFSET0		0x002C
+#define DQDFTCTL		0x0030
+#define DQTRAINSTS		0x0034
+#define B1DLLPICODER0		0x0038
+#define B0DLLPICODER0		0x003C
+#define B1DLLPICODER1		0x0040
+#define B0DLLPICODER1		0x0044
+#define B1DLLPICODER2		0x0048
+#define B0DLLPICODER2		0x004C
+#define B1DLLPICODER3		0x0050
+#define B0DLLPICODER3		0x0054
+#define B1RXDQSPICODE		0x0058
+#define B0RXDQSPICODE		0x005C
+#define B1RXDQPICODER32		0x0060
+#define B1RXDQPICODER10		0x0064
+#define B0RXDQPICODER32		0x0068
+#define B0RXDQPICODER10		0x006C
+#define B01PTRCTL0		0x0070
+#define B01PTRCTL1		0x0074
+#define B01DBCTL0		0x0078
+#define B01DBCTL1		0x007C
+#define B0LATCTL0		0x0080
+#define B1LATCTL0		0x0084
+#define B01LATCTL1		0x0088
+#define B0ONDURCTL		0x008C
+#define B1ONDURCTL		0x0090
+#define B0OVRCTL		0x0094
+#define B1OVRCTL		0x0098
+#define DQCTL			0x009C
+#define B0RK2RKCHGPTRCTRL	0x00A0
+#define B1RK2RKCHGPTRCTRL	0x00A4
+#define DQRK2RKCTL		0x00A8
+#define DQRK2RKPTRCTL		0x00AC
+#define B0RK2RKLAT		0x00B0
+#define B1RK2RKLAT		0x00B4
+#define DQCLKALIGNREG0		0x00B8
+#define DQCLKALIGNREG1		0x00BC
+#define DQCLKALIGNREG2		0x00C0
+#define DQCLKALIGNSTS0		0x00C4
+#define DQCLKALIGNSTS1		0x00C8
+#define DQCLKGATE		0x00CC
+#define B0COMPSLV1		0x00D0
+#define B1COMPSLV1		0x00D4
+#define B0COMPSLV2		0x00D8
+#define B1COMPSLV2		0x00DC
+#define B0COMPSLV3		0x00E0
+#define B1COMPSLV3		0x00E4
+#define DQVISALANECR0TOP	0x00E8
+#define DQVISALANECR1TOP	0x00EC
+#define DQVISACONTROLCRTOP	0x00F0
+#define DQVISALANECR0BL		0x00F4
+#define DQVISALANECR1BL		0x00F8
+#define DQVISACONTROLCRBL	0x00FC
+#define DQTIMINGCTRL		0x010C
+
+/* CH0-ECC */
+#define ECCDLLTXCTL		0x2004
+#define ECCDLLRXCTL		0x2008
+#define ECCMDLLCTL		0x200C
+#define ECCB1DLLPICODER0	0x2038
+#define ECCB1DLLPICODER1	0x2040
+#define ECCB1DLLPICODER2	0x2048
+#define ECCB1DLLPICODER3	0x2050
+#define ECCB01DBCTL0		0x2078
+#define ECCB01DBCTL1		0x207C
+#define ECCCLKALIGNREG0		0x20B8
+#define ECCCLKALIGNREG1		0x20BC
+#define ECCCLKALIGNREG2		0x20C0
+
+/* CH0-CMD */
+#define CMDOBSCKEBBCTL		0x4800
+#define CMDDLLTXCTL		0x4808
+#define CMDDLLRXCTL		0x480C
+#define CMDMDLLCTL		0x4810
+#define CMDRCOMPODT		0x4814
+#define CMDDLLPICODER0		0x4820
+#define CMDDLLPICODER1		0x4824
+#define CMDCFGREG0		0x4840
+#define CMDPTRREG		0x4844
+#define CMDCLKALIGNREG0		0x4850
+#define CMDCLKALIGNREG1		0x4854
+#define CMDCLKALIGNREG2		0x4858
+#define CMDPMCONFIG0		0x485C
+#define CMDPMDLYREG0		0x4860
+#define CMDPMDLYREG1		0x4864
+#define CMDPMDLYREG2		0x4868
+#define CMDPMDLYREG3		0x486C
+#define CMDPMDLYREG4		0x4870
+#define CMDCLKALIGNSTS0		0x4874
+#define CMDCLKALIGNSTS1		0x4878
+#define CMDPMSTS0		0x487C
+#define CMDPMSTS1		0x4880
+#define CMDCOMPSLV		0x4884
+#define CMDBONUS0		0x488C
+#define CMDBONUS1		0x4890
+#define CMDVISALANECR0		0x4894
+#define CMDVISALANECR1		0x4898
+#define CMDVISACONTROLCR	0x489C
+#define CMDCLKGATE		0x48A0
+#define CMDTIMINGCTRL		0x48A4
+
+/* CH0-CLK-CTL */
+#define CCOBSCKEBBCTL		0x5800
+#define CCRCOMPIO		0x5804
+#define CCDLLTXCTL		0x5808
+#define CCDLLRXCTL		0x580C
+#define CCMDLLCTL		0x5810
+#define CCRCOMPODT		0x5814
+#define CCDLLPICODER0		0x5820
+#define CCDLLPICODER1		0x5824
+#define CCDDR3RESETCTL		0x5830
+#define CCCFGREG0		0x5838
+#define CCCFGREG1		0x5840
+#define CCPTRREG		0x5844
+#define CCCLKALIGNREG0		0x5850
+#define CCCLKALIGNREG1		0x5854
+#define CCCLKALIGNREG2		0x5858
+#define CCPMCONFIG0		0x585C
+#define CCPMDLYREG0		0x5860
+#define CCPMDLYREG1		0x5864
+#define CCPMDLYREG2		0x5868
+#define CCPMDLYREG3		0x586C
+#define CCPMDLYREG4		0x5870
+#define CCCLKALIGNSTS0		0x5874
+#define CCCLKALIGNSTS1		0x5878
+#define CCPMSTS0		0x587C
+#define CCPMSTS1		0x5880
+#define CCCOMPSLV1		0x5884
+#define CCCOMPSLV2		0x5888
+#define CCCOMPSLV3		0x588C
+#define CCBONUS0		0x5894
+#define CCBONUS1		0x5898
+#define CCVISALANECR0		0x589C
+#define CCVISALANECR1		0x58A0
+#define CCVISACONTROLCR		0x58A4
+#define CCCLKGATE		0x58A8
+#define CCTIMINGCTL		0x58AC
+
+/* COMP */
+#define CMPCTRL			0x6800
+#define SOFTRSTCNTL		0x6804
+#define MSCNTR			0x6808
+#define NMSCNTRL		0x680C
+#define LATCH1CTL		0x6814
+#define COMPVISALANECR0		0x681C
+#define COMPVISALANECR1		0x6820
+#define COMPVISACONTROLCR	0x6824
+#define COMPBONUS0		0x6830
+#define TCOCNTCTRL		0x683C
+#define DQANAODTPUCTL		0x6840
+#define DQANAODTPDCTL		0x6844
+#define DQANADRVPUCTL		0x6848
+#define DQANADRVPDCTL		0x684C
+#define DQANADLYPUCTL		0x6850
+#define DQANADLYPDCTL		0x6854
+#define DQANATCOPUCTL		0x6858
+#define DQANATCOPDCTL		0x685C
+#define CMDANADRVPUCTL		0x6868
+#define CMDANADRVPDCTL		0x686C
+#define CMDANADLYPUCTL		0x6870
+#define CMDANADLYPDCTL		0x6874
+#define CLKANAODTPUCTL		0x6880
+#define CLKANAODTPDCTL		0x6884
+#define CLKANADRVPUCTL		0x6888
+#define CLKANADRVPDCTL		0x688C
+#define CLKANADLYPUCTL		0x6890
+#define CLKANADLYPDCTL		0x6894
+#define CLKANATCOPUCTL		0x6898
+#define CLKANATCOPDCTL		0x689C
+#define DQSANAODTPUCTL		0x68A0
+#define DQSANAODTPDCTL		0x68A4
+#define DQSANADRVPUCTL		0x68A8
+#define DQSANADRVPDCTL		0x68AC
+#define DQSANADLYPUCTL		0x68B0
+#define DQSANADLYPDCTL		0x68B4
+#define DQSANATCOPUCTL		0x68B8
+#define DQSANATCOPDCTL		0x68BC
+#define CTLANADRVPUCTL		0x68C8
+#define CTLANADRVPDCTL		0x68CC
+#define CTLANADLYPUCTL		0x68D0
+#define CTLANADLYPDCTL		0x68D4
+#define CHNLBUFSTATIC		0x68F0
+#define COMPOBSCNTRL		0x68F4
+#define COMPBUFFDBG0		0x68F8
+#define COMPBUFFDBG1		0x68FC
+#define CFGMISCCH0		0x6900
+#define COMPEN0CH0		0x6904
+#define COMPEN1CH0		0x6908
+#define COMPEN2CH0		0x690C
+#define STATLEGEN0CH0		0x6910
+#define STATLEGEN1CH0		0x6914
+#define DQVREFCH0		0x6918
+#define CMDVREFCH0		0x691C
+#define CLKVREFCH0		0x6920
+#define DQSVREFCH0		0x6924
+#define CTLVREFCH0		0x6928
+#define TCOVREFCH0		0x692C
+#define DLYSELCH0		0x6930
+#define TCODRAMBUFODTCH0	0x6934
+#define CCBUFODTCH0		0x6938
+#define RXOFFSETCH0		0x693C
+#define DQODTPUCTLCH0		0x6940
+#define DQODTPDCTLCH0		0x6944
+#define DQDRVPUCTLCH0		0x6948
+#define DQDRVPDCTLCH0		0x694C
+#define DQDLYPUCTLCH0		0x6950
+#define DQDLYPDCTLCH0		0x6954
+#define DQTCOPUCTLCH0		0x6958
+#define DQTCOPDCTLCH0		0x695C
+#define CMDDRVPUCTLCH0		0x6968
+#define CMDDRVPDCTLCH0		0x696C
+#define CMDDLYPUCTLCH0		0x6970
+#define CMDDLYPDCTLCH0		0x6974
+#define CLKODTPUCTLCH0		0x6980
+#define CLKODTPDCTLCH0		0x6984
+#define CLKDRVPUCTLCH0		0x6988
+#define CLKDRVPDCTLCH0		0x698C
+#define CLKDLYPUCTLCH0		0x6990
+#define CLKDLYPDCTLCH0		0x6994
+#define CLKTCOPUCTLCH0		0x6998
+#define CLKTCOPDCTLCH0		0x699C
+#define DQSODTPUCTLCH0		0x69A0
+#define DQSODTPDCTLCH0		0x69A4
+#define DQSDRVPUCTLCH0		0x69A8
+#define DQSDRVPDCTLCH0		0x69AC
+#define DQSDLYPUCTLCH0		0x69B0
+#define DQSDLYPDCTLCH0		0x69B4
+#define DQSTCOPUCTLCH0		0x69B8
+#define DQSTCOPDCTLCH0		0x69BC
+#define CTLDRVPUCTLCH0		0x69C8
+#define CTLDRVPDCTLCH0		0x69CC
+#define CTLDLYPUCTLCH0		0x69D0
+#define CTLDLYPDCTLCH0		0x69D4
+#define FNLUPDTCTLCH0		0x69F0
+
+/* PLL */
+#define MPLLCTRL0		0x7800
+#define MPLLCTRL1		0x7808
+#define MPLLCSR0		0x7810
+#define MPLLCSR1		0x7814
+#define MPLLCSR2		0x7820
+#define MPLLDFT			0x7828
+#define MPLLMON0CTL		0x7830
+#define MPLLMON1CTL		0x7838
+#define MPLLMON2CTL		0x783C
+#define SFRTRIM			0x7850
+#define MPLLDFTOUT0		0x7858
+#define MPLLDFTOUT1		0x785C
+#define MASTERRSTN		0x7880
+#define PLLLOCKDEL		0x7884
+#define SFRDEL			0x7888
+#define CRUVISALANECR0		0x78F0
+#define CRUVISALANECR1		0x78F4
+#define CRUVISACONTROLCR	0x78F8
+#define IOSFVISALANECR0		0x78FC
+#define IOSFVISALANECR1		0x7900
+#define IOSFVISACONTROLCR	0x7904
+
+/* END DDRIO Registers */
+
+/* DRAM Specific Message Bus OpCodes */
+#define MSG_OP_DRAM_INIT	0x68
+#define MSG_OP_DRAM_WAKE	0xCA
+
+#define SAMPLE_SIZE		6
+
+/* must be less than this number to enable early deadband */
+#define EARLY_DB		0x12
+/* must be greater than this number to enable late deadband */
+#define LATE_DB			0x34
+
+#define CHX_REGS		(11 * 4)
+#define FULL_CLK		128
+#define HALF_CLK		64
+#define QRTR_CLK		32
+
+#define MCEIL(num, den)		((uint8_t)((num + den - 1) / den))
+#define MMAX(a, b)		((a) > (b) ? (a) : (b))
+#define DEAD_LOOP()		for (;;);
+
+#define MIN_RDQS_EYE		10	/* in PI Codes */
+#define MIN_VREF_EYE		10	/* in VREF Codes */
+/* how many RDQS codes to jump while margining */
+#define RDQS_STEP		1
+/* how many VREF codes to jump while margining */
+#define VREF_STEP		1
+/* offset into "vref_codes[]" for minimum allowed VREF setting */
+#define VREF_MIN		0x00
+/* offset into "vref_codes[]" for maximum allowed VREF setting */
+#define VREF_MAX		0x3F
+#define RDQS_MIN		0x00	/* minimum RDQS delay value */
+#define RDQS_MAX		0x3F	/* maximum RDQS delay value */
+
+/* how many WDQ codes to jump while margining */
+#define WDQ_STEP		1
+
+enum {
+	B,	/* BOTTOM VREF */
+	T	/* TOP VREF */
+};
+
+enum {
+	L,	/* LEFT RDQS */
+	R	/* RIGHT RDQS */
+};
+
+/* Memory Options */
+
+/* enable STATIC timing settings for RCVN (BACKUP_MODE) */
+#undef BACKUP_RCVN
+/* enable STATIC timing settings for WDQS (BACKUP_MODE) */
+#undef BACKUP_WDQS
+/* enable STATIC timing settings for RDQS (BACKUP_MODE) */
+#undef BACKUP_RDQS
+/* enable STATIC timing settings for WDQ (BACKUP_MODE) */
+#undef BACKUP_WDQ
+/* enable *COMP overrides (BACKUP_MODE) */
+#undef BACKUP_COMPS
+/* enable the RD_TRAIN eye check */
+#undef RX_EYE_CHECK
+
+/* enable Host to Memory Clock Alignment */
+#define HMC_TEST
+/* enable multi-rank support via rank2rank sharing */
+#define R2R_SHARING
+/* disable signals not used in 16bit mode of DDRIO */
+#define FORCE_16BIT_DDRIO
+
+#define PLATFORM_ID		1
+
+void clear_self_refresh(struct mrc_params *mrc_params);
+void prog_ddr_timing_control(struct mrc_params *mrc_params);
+void prog_decode_before_jedec(struct mrc_params *mrc_params);
+void perform_ddr_reset(struct mrc_params *mrc_params);
+void ddrphy_init(struct mrc_params *mrc_params);
+void perform_jedec_init(struct mrc_params *mrc_params);
+void set_ddr_init_complete(struct mrc_params *mrc_params);
+void restore_timings(struct mrc_params *mrc_params);
+void default_timings(struct mrc_params *mrc_params);
+void rcvn_cal(struct mrc_params *mrc_params);
+void wr_level(struct mrc_params *mrc_params);
+void prog_page_ctrl(struct mrc_params *mrc_params);
+void rd_train(struct mrc_params *mrc_params);
+void wr_train(struct mrc_params *mrc_params);
+void store_timings(struct mrc_params *mrc_params);
+void enable_scrambling(struct mrc_params *mrc_params);
+void prog_ddr_control(struct mrc_params *mrc_params);
+void prog_dra_drb(struct mrc_params *mrc_params);
+void perform_wake(struct mrc_params *mrc_params);
+void change_refresh_period(struct mrc_params *mrc_params);
+void set_auto_refresh(struct mrc_params *mrc_params);
+void ecc_enable(struct mrc_params *mrc_params);
+void memory_test(struct mrc_params *mrc_params);
+void lock_registers(struct mrc_params *mrc_params);
+
+#endif /* _SMC_H_ */
diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig
index f6b5201..397e599 100644
--- a/arch/x86/cpu/queensbay/Kconfig
+++ b/arch/x86/cpu/queensbay/Kconfig
@@ -11,44 +11,6 @@
 
 if INTEL_QUEENSBAY
 
-config HAVE_FSP
-	bool "Add an Firmware Support Package binary"
-	help
-	  Select this option to add an Firmware Support Package binary to
-	  the resulting U-Boot image. It is a binary blob which U-Boot uses
-	  to set up SDRAM and other chipset specific initialization.
-
-	  Note: Without this binary U-Boot will not be able to set up its
-	  SDRAM so will not boot.
-
-config FSP_FILE
-	string "Firmware Support Package binary filename"
-	depends on HAVE_FSP
-	default "fsp.bin"
-	help
-	  The filename of the file to use as Firmware Support Package binary
-	  in the board directory.
-
-config FSP_ADDR
-	hex "Firmware Support Package binary location"
-	depends on HAVE_FSP
-	default 0xfffc0000
-	help
-	  FSP is not Position Independent Code (PIC) and the whole FSP has to
-	  be rebased if it is placed at a location which is different from the
-	  perferred base address specified during the FSP build. Use Intel's
-	  Binary Configuration Tool (BCT) to do the rebase.
-
-	  The default base address of 0xfffc0000 indicates that the binary must
-	  be located at offset 0xc0000 from the beginning of a 1MB flash device.
-
-config FSP_TEMP_RAM_ADDR
-	hex
-	default 0x2000000
-	help
-	  Stack top address which is used in FspInit after DRAM is ready and
-	  CAR is disabled.
-
 config HAVE_CMC
 	bool "Add a Chipset Micro Code state machine binary"
 	help
diff --git a/arch/x86/cpu/queensbay/Makefile b/arch/x86/cpu/queensbay/Makefile
index 2c2ec01..d8761fd 100644
--- a/arch/x86/cpu/queensbay/Makefile
+++ b/arch/x86/cpu/queensbay/Makefile
@@ -4,6 +4,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += tnc_car.o tnc_dram.o tnc.o topcliff.o
-obj-y += fsp_configs.o fsp_support.o
+obj-y += fsp_configs.o
+obj-y += tnc.o topcliff.o
 obj-$(CONFIG_PCI) += tnc_pci.o
diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c
index af28e45..78bc966 100644
--- a/arch/x86/cpu/queensbay/fsp_configs.c
+++ b/arch/x86/cpu/queensbay/fsp_configs.c
@@ -6,7 +6,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 
 void update_fsp_upd(struct upd_region *fsp_upd)
 {
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 8637cdc..30ab725 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -9,7 +9,7 @@
 #include <asm/pci.h>
 #include <asm/post.h>
 #include <asm/arch/tnc.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 #include <asm/processor.h>
 
 static void unprotect_spi_flash(void)
@@ -43,30 +43,3 @@
 
 	return 0;
 }
-
-int print_cpuinfo(void)
-{
-	post_code(POST_CPU_INFO);
-	return default_print_cpuinfo();
-}
-
-void reset_cpu(ulong addr)
-{
-	/* cold reset */
-	outb(0x06, PORT_RESET);
-}
-
-void board_final_cleanup(void)
-{
-	u32 status;
-
-	/* call into FspNotify */
-	debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
-	status = fsp_notify(NULL, INIT_PHASE_BOOT);
-	if (status != FSP_SUCCESS)
-		debug("fail, error code %x\n", status);
-	else
-		debug("OK\n");
-
-	return;
-}
diff --git a/arch/x86/cpu/queensbay/tnc_pci.c b/arch/x86/cpu/queensbay/tnc_pci.c
index 39bff49..6c291f9 100644
--- a/arch/x86/cpu/queensbay/tnc_pci.c
+++ b/arch/x86/cpu/queensbay/tnc_pci.c
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/pci.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -44,18 +44,3 @@
 
 	hose->region_count = 4;
 }
-
-int board_pci_post_scan(struct pci_controller *hose)
-{
-	u32 status;
-
-	/* call into FspNotify */
-	debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
-	status = fsp_notify(NULL, INIT_PHASE_PCI);
-	if (status != FSP_SUCCESS)
-		debug("fail, error code %x\n", status);
-	else
-		debug("OK\n");
-
-	return 0;
-}
diff --git a/arch/x86/cpu/queensbay/topcliff.c b/arch/x86/cpu/queensbay/topcliff.c
index b01422a..9faf1b9 100644
--- a/arch/x86/cpu/queensbay/topcliff.c
+++ b/arch/x86/cpu/queensbay/topcliff.c
@@ -5,43 +5,16 @@
  */
 
 #include <common.h>
-#include <errno.h>
-#include <malloc.h>
-#include <pci.h>
+#include <mmc.h>
 #include <pci_ids.h>
-#include <sdhci.h>
 
 static struct pci_device_id mmc_supported[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0 },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1 },
-	{ }
 };
 
 int cpu_mmc_init(bd_t *bis)
 {
-	struct sdhci_host *mmc_host;
-	pci_dev_t devbusfn;
-	u32 iobase;
-	int ret;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mmc_supported); i++) {
-		devbusfn =  pci_find_devices(mmc_supported, i);
-		if (devbusfn == -1)
-			return -ENODEV;
-
-		mmc_host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
-		if (!mmc_host)
-			return -ENOMEM;
-
-		mmc_host->name = "Topcliff SDHCI";
-		pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
-		mmc_host->ioaddr = (void *)iobase;
-		mmc_host->quirks = 0;
-		ret = add_sdhci(mmc_host, 0, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
+	return pci_mmc_init("Topcliff SDHCI", mmc_supported,
+			    ARRAY_SIZE(mmc_supported));
 }
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 97ed884..7a66133 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -1,5 +1,7 @@
 dtb-y += chromebook_link.dtb \
-	crownbay.dtb
+	crownbay.dtb \
+	galileo.dtb \
+	minnowmax.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts
new file mode 100644
index 0000000..66af64a
--- /dev/null
+++ b/arch/x86/dts/galileo.dts
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/mrc/quark.h>
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Intel Galileo";
+	compatible = "intel,galileo", "intel,quark";
+
+	config {
+		silent_console = <0>;
+	};
+
+	chosen {
+		stdout-path = &pciuart0;
+	};
+
+	mrc {
+		compatible = "intel,quark-mrc";
+		flags = <MRC_FLAG_SCRAMBLE_EN>;
+		dram-width = <DRAM_WIDTH_X8>;
+		dram-speed = <DRAM_FREQ_800>;
+		dram-type = <DRAM_TYPE_DDR3>;
+		rank-mask = <DRAM_RANK(0)>;
+		chan-mask = <DRAM_CHANNEL(0)>;
+		chan-width = <DRAM_CHANNEL_WIDTH_X16>;
+		addr-mode = <DRAM_ADDR_MODE0>;
+		refresh-rate = <DRAM_REFRESH_RATE_785US>;
+		sr-temp-range = <DRAM_SRT_RANGE_NORMAL>;
+		ron-value = <DRAM_RON_34OHM>;
+		rtt-nom-value = <DRAM_RTT_NOM_120OHM>;
+		rd-odt-value = <DRAM_RD_ODT_OFF>;
+		dram-density = <DRAM_DENSITY_1G>;
+		dram-cl = <6>;
+		dram-ras = <0x0000927c>;
+		dram-wtr = <0x00002710>;
+		dram-rrd = <0x00002710>;
+		dram-faw = <0x00009c40>;
+	};
+
+	pci {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		compatible = "intel,pci";
+		device_type = "pci";
+
+		pciuart0: uart@14,5 {
+			compatible = "pci8086,0936.00",
+					"pci8086,0936",
+					"pciclass,070002",
+					"pciclass,0700",
+					"x86-uart";
+			reg = <0x0000a500 0x0 0x0 0x0 0x0
+			       0x0200a510 0x0 0x0 0x0 0x0>;
+			reg-shift = <2>;
+			clock-frequency = <44236800>;
+			current-speed = <115200>;
+		};
+	};
+
+	gpioa {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0 0x20>;
+		bank-name = "A";
+	};
+
+	gpiob {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x20 0x20>;
+		bank-name = "B";
+	};
+
+	spi {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "intel,ich-spi";
+		spi-flash@0 {
+			#size-cells = <1>;
+			#address-cells = <1>;
+			reg = <0>;
+			compatible = "winbond,w25q64", "spi-flash";
+			memory-map = <0xff800000 0x00800000>;
+		};
+	};
+
+};
diff --git a/arch/x86/dts/microcode/m0130673322.dtsi b/arch/x86/dts/microcode/m0130673322.dtsi
new file mode 100644
index 0000000..90bf2fb
--- /dev/null
+++ b/arch/x86/dts/microcode/m0130673322.dtsi
@@ -0,0 +1,3284 @@
+/*
+ * ---
+ * This is a device tree fragment. Use #include to add these properties to a
+ * node.
+ *
+ * Date:
+ */
+
+compatible = "intel,microcode";
+intel,header-version = <1>;
+intel,update-revision = <0x322>;
+intel,date-code = <0x4012014>;
+intel,processor-signature = <0x30673>;
+intel,checksum = <0x17b0d914>;
+intel,loader-revision = <1>;
+intel,processor-flags = <0x1>;
+
+/* The first 48-bytes are the public header which repeats the above data */
+data = <
+	0x01000000	0x22030000	0x14200104	0x73060300
+	0x14d9b017	0x01000000	0x01000000	0xd0cb0000
+	0x00cc0000	0x00000000	0x00000000	0x00000000
+	0x00000000	0xa1000000	0x01000200	0x22030000
+	0x00000000	0x00000000	0x31031420	0x11320000
+	0x01000000	0x73060300	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x00000000	0xf4320000	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x0ae10178	0x7c98f9d1	0x41962d85	0x19391270
+	0xcf3c0336	0xc1f13d6f	0xe46abaf6	0x3b65ca6b
+	0xdb666815	0x5a17bfc4	0x4fca009d	0x099ae8b3
+	0x198e2c7d	0x7c665bbf	0xc07a1a7a	0x7dbcee26
+	0x867296b2	0xc885b6ce	0xe602baff	0x68544b14
+	0xc928c400	0x3add156d	0x531946f9	0x92a03216
+	0xda352322	0xd967ee1f	0x3c5170a7	0xf6de834e
+	0x5a2ed8b3	0x9fb8f050	0x450de17f	0xfd5ef070
+	0x4954575f	0xa3a071ab	0xb56e2afb	0xe2b48302
+	0x6655a958	0x57c9a438	0x1b2f688a	0x09309bc4
+	0x0be95612	0x529c1633	0xc48515d9	0x29eb78df
+	0x9933409f	0xda58dea9	0x58c805fd	0xbc110f5a
+	0x40780ec0	0x6ad59bb3	0xc7387fb8	0x591c1490
+	0xf9335932	0x32130e0b	0xef4b3c96	0xacd903f2
+	0x5b362539	0xe7f85529	0xcb17c41f	0xe7e440d8
+	0xfaf7e925	0x969b76fb	0x5edab8c7	0xf00012e8
+	0x121c2971	0xe5b18959	0xadfd07c0	0x1f09c9d7
+	0x9781006a	0x39550073	0x6c438b6d	0x436f60bc
+	0x11000000	0x8514b971	0x40df7b4a	0x6a6b7285
+	0x7978ef59	0x319bddf5	0x04c68e5a	0xe1c28b10
+	0x172f63dc	0x306fb95d	0x31d881e8	0x69f8e08d
+	0x617a99e1	0x1ab6b574	0x2951fa5b	0xcc7e3e94
+	0xff379d19	0x5c035dec	0xe28ed726	0x22b8a5ac
+	0xd08b3ac5	0x45c03b9e	0xcea4083c	0xc26758aa
+	0xbe7cf81e	0x43d898f3	0x5c45a635	0xc9cac095
+	0xb89aea20	0x2c02b40e	0xe3a8b48d	0xeabfb60e
+	0x776ed2a9	0x080ae6d5	0x7f64b1df	0x00e40ee6
+	0x0f1c10f4	0x792e5423	0x787f5459	0x63a8b02c
+	0x3fd6a255	0x049cae26	0x0949f5ff	0x9aebb236
+	0xecc01775	0x91b57b84	0xe0e45ea3	0x5a8bf79e
+	0x356a843a	0x2406795f	0x8aaae5d8	0x6a8c877c
+	0xa8b2b8f4	0x04cf8f49	0x422d9e2c	0xf09f9896
+	0xe9b92215	0x9c98fb44	0x88556b7f	0x519d6f4c
+	0x9e8a016b	0xcb18d16c	0x419b4ee7	0x080b49c8
+	0xc51b875e	0x46aabc9c	0x262d27eb	0x93ea189d
+	0xdd0da69d	0x3e5b17e8	0xcc78509a	0x00b07e6e
+	0x363d5a70	0x64572070	0x8a84abc4	0x1cb03838
+	0x965fd76a	0x540aafc9	0x83a91654	0x1a722e67
+	0x4bf98ce1	0x2b3c2ff9	0x972cebd4	0xf3a68395
+	0x2613e422	0xf8d031d7	0xb1c79a0f	0xfd44f65b
+	0xa7012a9b	0xd9a15a60	0xc311fc0c	0x6f52f878
+	0x3d68381d	0xd2a035d7	0xb790c50e	0x9f1e5010
+	0x41877064	0xa9d1e4ae	0xfe9abbd5	0x60c2c748
+	0x8167e5ad	0x022dbfb3	0x75abe483	0x51c37170
+	0x09b8590d	0xc1bb323d	0x2c7336b1	0xd4d0d49b
+	0xc7f6152b	0x7919d596	0x1e1ff62e	0xc49604a0
+	0x33857369	0xeaa3f382	0x98b8cd86	0x176e1bf3
+	0x1a68867b	0x6af0a11c	0x69a82b25	0x48c72525
+	0xa00aae2d	0xb09f67f4	0x1a99f83d	0x7266cca3
+	0x8d03a7da	0x2e1d7c49	0x01ac68ae	0x93188770
+	0x0609e769	0x982ed28d	0xe40999e0	0x8932ebab
+	0x5637ad5a	0x2725e8ad	0x56d7caaf	0xc351faa2
+	0x09dbd737	0x0d2f3bf0	0x0623330d	0xdd547489
+	0xcca7e722	0xa9096d13	0x95b17818	0xc092cb81
+	0x72c6eefc	0x1811c37e	0x78161497	0x8be0c4c6
+	0xd63aeb19	0x91ab68df	0x8f2e5e4d	0xf4c74566
+	0x7677a553	0x19698ac3	0xedca0620	0x77f32470
+	0x031e011b	0x751f6696	0xb277d06e	0x3eae2742
+	0x133e621a	0x38fa3172	0x9398cc1c	0xf42a507b
+	0x4547d933	0x63a91eb0	0xf5bcf6a4	0x926ba056
+	0x0adf5bce	0x140f53e4	0x7ff6bb5c	0x87dd79ba
+	0xbba240ac	0x694f743d	0x709cdb20	0x5b4d4401
+	0xc9693610	0x55f9f268	0x1142bc3f	0xf8fe3689
+	0x04a93c4c	0x33dedc46	0xdc73c725	0x2f5ba264
+	0x5b7a6a69	0x024b64f5	0x6e8bfa12	0x62bf2aa7
+	0x520f5a07	0x3c7c4292	0xb7ad2613	0x1f78fc87
+	0xd5284e4e	0x2c730f33	0x8861e947	0x8bacef7d
+	0xbafa2608	0x14ed0b5b	0x3b9bfb02	0x24ced271
+	0x002b2941	0x22d4431c	0x855f4248	0x5ec46e29
+	0x6f1f42fb	0x5dd24fe0	0x290961f6	0xf392dbaf
+	0xa1a8d9c2	0x61e18f4e	0xfda59a70	0x5498daa5
+	0x5ae7ea6f	0xf058c635	0x6817ebee	0x8e30dc8b
+	0x7c8d79be	0x5fb15b9b	0xeed64741	0xe2642a94
+	0x680d7e6e	0x3cbad7aa	0x808c415f	0xe9323aa2
+	0xaadf5b25	0xf60abf13	0xd5c47967	0xc248d0b3
+	0x0f232cbd	0x84092449	0x5744384b	0x5e153ded
+	0x8bb19817	0x34430271	0x917d2315	0x1fc790c7
+	0xc21b5db6	0xec578b1f	0x903a286e	0xca0c59bc
+	0x03e95c7a	0x8c659e99	0x7b09da0a	0xd61e7517
+	0x90b1c519	0x8deac92c	0xf99c7bec	0xb6257d92
+	0x3d61c16e	0xebd58be0	0xb470e655	0xa44bbf4f
+	0xfebe5313	0x4662110a	0x5d42ccd9	0x140845ec
+	0xc80329a9	0x915ca966	0x71e33828	0xe46c870a
+	0x7da9a490	0x255544da	0xa20fb8df	0xf94062b3
+	0xb2df5870	0xebf31e88	0x6e723e2f	0xe6ba9cf1
+	0x7e7084c2	0x1782ac71	0x0a0b0127	0xe9234e38
+	0x881356d6	0xb27a54b6	0x5594730e	0x9a14bd8f
+	0x6dba7da9	0x1069e285	0x02a52798	0x61ea7d86
+	0x665b2572	0x29d41eb5	0x1d211169	0x1218b345
+	0xbfbd264c	0x5b8b0625	0xbbfdcf39	0x6768dfce
+	0x0b5f10cb	0xe159414c	0x74356ed6	0x70077f49
+	0x672107e8	0x11616856	0x824e6f2f	0x99614958
+	0x5857305d	0x416a193f	0x010d266c	0xe5194f03
+	0x152d6516	0xeb83872e	0x4923cc1f	0x1191d1ca
+	0x23feb738	0x6817c1d7	0xe49129ed	0x4a53132a
+	0xdb46b95b	0x3f970366	0x93f1a518	0xae8d72ae
+	0xb689d915	0x0bdfda17	0x2ac7238d	0x1c4291e7
+	0xc5b11085	0x3c51c1ba	0x9fd63edd	0xe464d740
+	0xc17f2789	0x0adef6b9	0xf9aaf83e	0xfb2a9798
+	0x7f16268b	0x4c8ca6c5	0x2b17be52	0x00c91157
+	0xb69eb5db	0xe55ed94a	0xdf13b5a5	0xbb52d1e3
+	0x651bb017	0xc7795724	0x0dfd4711	0x02d2d6e0
+	0xc835e771	0x8ab5dd50	0x7caca109	0xd5c18d6e
+	0xbef0e727	0xaff2dd07	0xf1062a32	0x26d14796
+	0x97f6e36c	0xf845278e	0x185eb5b3	0xcde4e201
+	0x13166ab7	0xcdcebcdc	0x143ef0c7	0x2349893f
+	0x9dfcb70e	0x7ef72725	0x141c5b71	0x7da0f5d3
+	0x76bebb67	0x28bc0a83	0xb67ecf0f	0xd60a1303
+	0x9391b279	0x6ad41154	0x317896b0	0x1237efa6
+	0x7b2a2e6c	0x3ad9a110	0xb44357d4	0xb32e39fe
+	0x2358d28e	0x76e847d9	0x3e85db01	0x6c74e466
+	0x9e4e6b32	0x13072a53	0x5972132e	0xd97cb04d
+	0x55ee6a0b	0xc1434b92	0x772f6a1d	0x0f81f7a6
+	0x072aa8f7	0x179da0e0	0x976bd78c	0x2e43c16b
+	0x4f4a6b51	0x92d9c61b	0xa9c15fe4	0x3f8a527a
+	0x3a232408	0x543d7957	0x21cbd682	0x896de3b0
+	0xba6b3df6	0x2ec86e51	0x2be889e3	0xae764ff0
+	0x3a2f0003	0x7a5f7949	0x577fb5ce	0xb5cbd1a6
+	0xc910ffe2	0x7fd76712	0xfc1e93ff	0xbee7b15c
+	0x5db2356d	0x9721a3fd	0x0d408aed	0x4df4c922
+	0x45d5be91	0x6c79b1fc	0xf0bf73bd	0x3f6a73b6
+	0xdcc1b51e	0x2049fe2d	0xf2b2ad4b	0xd0484d3a
+	0x1f097d3f	0xced1bf3d	0x10f4416b	0x73cb307c
+	0x4b4d94b4	0x2918ece0	0x0cfe69f3	0xb7e86cfb
+	0xa6c373b4	0x0d862b62	0x1735cd72	0xef23c127
+	0x09809c16	0x86cfb70b	0xe67c6903	0x743223a7
+	0x13c7d27f	0xb70a58cc	0x82c57566	0x2ead3c65
+	0xf9409863	0xf2b578ef	0x1622a34d	0x5ae8e861
+	0xf4384016	0x443ff5f4	0x088b8510	0xd738d1c5
+	0x577d624b	0x5adf3973	0x5f79add3	0xed7e7145
+	0x29008fc0	0xd5b278cf	0x5b4c08c2	0xb063af5c
+	0x67d41bd9	0x2d11424a	0x727924de	0x8903a86f
+	0xb122d314	0xd9675c8b	0xc2eb1382	0x4c4185da
+	0x257a0fe1	0xc3fd536b	0xadbfc223	0xc940dab4
+	0x2e83d4b0	0xf1135ad4	0xfeb1cc1a	0x9178ae04
+	0x996d72ba	0x07f6bf0f	0x6588f833	0x44f95205
+	0xee4e6897	0xa9006735	0xa5f5502c	0xeb61aca6
+	0xf2ceddb5	0x40ef9001	0xf862c3d7	0x73deaad3
+	0x7b1d8b1d	0x467bcbcf	0x7f76f969	0x6c8e7f8c
+	0xfb8e27c3	0x5075ce65	0x1c8628a8	0x7b6e3e32
+	0x4885fc9f	0xa9fa768c	0x15426120	0x1df9d006
+	0x31c52df4	0x1457f5c6	0xde5f2daa	0xfa250108
+	0xbcf7e460	0x565d4679	0x82c94142	0xae76342a
+	0x85aca7c7	0x8bc49e03	0x73f03da3	0x1e500b4c
+	0x250288a2	0x25a39951	0x66087700	0x6317754b
+	0x6ff62bdc	0xa519ad4f	0xa537b8ac	0xea6292ab
+	0xb5d66b68	0x15997d1f	0x0fdbf04a	0xaa2b1a25
+	0x74b72321	0xf8b1753a	0x33658d1e	0xb1cc5d96
+	0x5b0da6af	0x48f24997	0xb031146e	0xfe98e8d1
+	0x9bd75bf0	0x0ae088fe	0xb8fce721	0x964bc398
+	0xe82daef6	0x393884b5	0xa814f792	0xb3667bde
+	0x1d1cf32d	0xce862720	0x7b69e921	0xabd26f33
+	0x61fad35f	0xd7144eeb	0x74016bce	0x1d56277b
+	0x7f934eed	0xb1a3396a	0xd5090c7a	0x4ea94d12
+	0x1455ac10	0x7c37294c	0x06c60a9a	0xa735ab29
+	0xbffb880f	0x59e2cb48	0x54cca9d7	0xb569da05
+	0x595e72ec	0x7c82f204	0x7690420d	0xe02fbb37
+	0x4dbf4e68	0x221eda99	0x31868046	0xda435487
+	0xb4c0dcc4	0x37610096	0x35569b02	0xefcd4ecf
+	0x7b6917bf	0x45946a25	0x5d42a84a	0x8c3801b7
+	0x5ac838fa	0x7a7f252d	0xbccf3cb5	0x99a54c4c
+	0x39145831	0xfd5c1af3	0xcabb180c	0x8f0fe9dd
+	0xabd42357	0x3b6d9aa9	0x0e87ede1	0x65ea46ae
+	0xd89b618e	0x1e5cc772	0xfb43c9b4	0xdad3fdb2
+	0x96be6600	0x4887696e	0x82a4e73a	0xb2ca2cf0
+	0xc6840738	0x397d27a9	0xce971271	0x067e4de6
+	0xb593f079	0x6a77de2f	0xf9a92497	0xdc3e94aa
+	0x03239a80	0x7f38430a	0xf7f87908	0x682a8425
+	0x2d491962	0xb5737b4b	0xa26434e5	0x238ced20
+	0x1ed9fcbe	0x283a8f7b	0x18f33cf6	0x29f27cd5
+	0xd95018aa	0x883dbd25	0xfb216723	0xe939d42c
+	0xf4b1207d	0x54f5e102	0xbe2e46eb	0xb2ca8219
+	0xab181ad4	0x3a7dc3e6	0xf3713256	0x53f081ab
+	0xd630a7a3	0x07c40bc3	0x7a1fde0c	0xb368bab8
+	0xc0baaad3	0xf070baac	0xe4ab7a4f	0x82a8cf5e
+	0x9c3d7bb5	0xfe5f74a3	0x02548e86	0x2710ff5d
+	0x1b42a8c4	0x34d4f5d8	0x8dfde8f2	0xf2949298
+	0xe9d711bf	0x44d91e17	0x51ba8b32	0xbc3f60cc
+	0xa0d6c440	0xf71959b4	0x3b5f0603	0x02465794
+	0xff5d9b8a	0xd4a4abcf	0x8123626c	0x883ed4e4
+	0x9eaeaa09	0x91c38865	0xa0aaeebf	0xc48983ab
+	0x1df7a001	0x7519a65e	0x5ef3cd1d	0x8348225d
+	0x0f318b0b	0xbab1d51b	0x15ba9b84	0xef8c57bf
+	0x15d0a8c1	0x0b542fb4	0x1d51ccc8	0x6c297041
+	0xf3bee946	0x6a8c3d64	0x6e16361d	0xed50ca69
+	0x8c1f66ba	0xff7220e0	0x84a87cba	0x15d75922
+	0x77546d82	0x7bd456e3	0x10166195	0x55604f1f
+	0x894280d2	0x0ed406c4	0xc1b4058e	0x645252e5
+	0x670ea74e	0xd5b07337	0x9944e2cf	0xf2ac2579
+	0xd00c3ae8	0x2df3146d	0x4ee1c72a	0x3a3621cf
+	0x8c099145	0xf5f530e6	0x210da136	0x7908cec6
+	0xc6e47e22	0xe9bcbe4e	0x94cbcb12	0xb81f0792
+	0x1111f81e	0x4df4ac93	0x335c69be	0x9e3546b9
+	0x06c046b4	0x6f29a99c	0xbcd48ee7	0xeb011efe
+	0x41e80474	0xcee30bf4	0xad4e2ae0	0x6929a359
+	0xbdaa88e3	0x9e68a38e	0x16bbdac7	0x020d8d61
+	0x7bab6738	0x559cddbd	0xa6ae3d0c	0xe032c355
+	0xcb45a045	0x9f7680b2	0xc1cb73da	0x466052f7
+	0x488cb929	0xd93f0307	0xb2c9d81c	0xe25fdcd9
+	0xfe8b08c4	0xae6230bd	0x5238b335	0x3474b2a5
+	0x480ce0b7	0xd9a2942f	0xe830fa5b	0x3efa774f
+	0x84e53e93	0xf49e7d79	0x59897b26	0x75b1080f
+	0xc2212b0f	0xe5fe56bd	0x4556e908	0x1bd0bb17
+	0x2f159d20	0x866477e5	0x4e95a374	0xbdc9fd65
+	0x2ff87073	0x5d7dceea	0x69ada0c7	0x89f16ad0
+	0x97da55d8	0xe4457728	0x5ab7613e	0xf6bbe6ec
+	0x56b83617	0x9119b521	0x4fabf948	0x2e1ab994
+	0xd16363f0	0xaee14b3f	0x5461ea55	0x55d95d02
+	0xf72c902c	0x1ede6c56	0x697006d9	0x4d15007f
+	0x0c1cb5e5	0x55d3d5d5	0x1f18d76f	0x55c9f017
+	0x3e1d3b5b	0x8f775636	0x97e6bf8f	0x360a9fb5
+	0x1e080721	0xf9825356	0x30e900f3	0x55453bfe
+	0xbd8f1df0	0x35b43ba8	0x45db013f	0x20484d34
+	0x944ca654	0x79c2c151	0xd4e9b39b	0x1b2e79b6
+	0x554314d6	0xce4ee44d	0xd0394232	0x9da4db20
+	0xa70beed6	0x4ae4ed10	0x4c244770	0x4b91208c
+	0x39a01e0b	0x5eea0a55	0x4b36ffbe	0x6fd18df2
+	0x43fd13e3	0xa99302bc	0x63762b5d	0xd014d6b4
+	0xbf0e53d2	0x0f5b5aa5	0x3c23f5b7	0x16335036
+	0xe011bd10	0x66e596a3	0xf463e3ad	0x9670c0a3
+	0x4004e177	0xbd2b3260	0x01967017	0x1159a682
+	0x62931eb8	0xc581df9e	0x6710932f	0xfb2bb0b2
+	0xb8a0339c	0xc66f0fff	0x333f5ee3	0xc06f8586
+	0x7b9f47f1	0x9aaedaa3	0x6044562a	0x26c73565
+	0x82c6e5b2	0x39d4eed0	0x83b7432e	0x0c4f0e4a
+	0x4d9df788	0x989e7f41	0x61cacc3b	0xdc34efeb
+	0x240b22a8	0x70a508b0	0x7554f517	0x7269f02b
+	0xd27ffcf6	0x96a5879f	0x0650f7e4	0xdc1fc1ac
+	0x80781334	0x04ab3381	0x8bad17c1	0x18311833
+	0x65f06ee9	0xfaac30e1	0xe39b8b54	0x20b988ce
+	0xa6a818f3	0x75ac753b	0x66f815a4	0x224d7121
+	0x63dc6031	0xcfeed2c7	0x3ccd07d7	0x9df44157
+	0xb9dcca97	0xcf5178f1	0x10e8fb28	0xa1faa527
+	0x8851846e	0x01f56075	0x2dd4fff2	0x40786960
+	0x41aa9e6c	0xf7c85573	0x64a36432	0x4449e726
+	0x7aa7bb0d	0x08f596cc	0x248e1eb3	0x5c5567cb
+	0x62ffd012	0x2d79ce59	0xf9ed4239	0xe98e107a
+	0x4da25561	0xc6f83333	0x1ca0482d	0xcc3f3b69
+	0xa9f48711	0x99139510	0xc5777d2b	0x9c80814d
+	0xab47fbe4	0xf302d145	0x20aecccc	0x3be9e431
+	0x7dc34793	0x4d38171c	0xaa34e505	0xc32e492b
+	0x4f31bd0b	0xb7549889	0xdb3da9cf	0x084d0791
+	0xa4c63c9f	0x62e770e9	0x862fdb93	0x52c45b9e
+	0xf21019a5	0xdde6aa07	0xcb46386e	0x830693a8
+	0x651510c8	0xf3af66a4	0x78775e07	0xc9f22414
+	0x5769f089	0xac2ae873	0x044357d8	0x9fdc76f8
+	0xea16ade5	0x144e9211	0x181ade72	0xba50ce80
+	0x4573571a	0x5437c668	0x39c3b81d	0x013d766d
+	0xc1754b48	0xa611fa3b	0x725eae72	0x04b02ca9
+	0x186a2541	0xa2784e47	0x8b7601bb	0x7f9132e3
+	0x3295d5b5	0x4b470dee	0xaf5ec559	0xc4c442d6
+	0x5b07293d	0x9a68b079	0xc1408c0c	0xc2371025
+	0x4af99e8c	0x332c416a	0xec04321b	0xb8493ffb
+	0x51eab7de	0x26d7e9db	0x7880126e	0x439be5e3
+	0x7e8910f0	0xa8ba727b	0x88cb04df	0x70750495
+	0xc13413f6	0x684312db	0x0579d5b1	0x05fe44f7
+	0x627e04f3	0xe85b47da	0xbf646f0b	0x2ddf4932
+	0x1bcb6fc0	0x611de27d	0xb3ee1bed	0x247dad06
+	0xa7107d34	0xba434b88	0x6eb90466	0x45a65871
+	0xa9a67088	0x6af3b796	0xf5b73689	0xcab03ca4
+	0xca1f25e6	0xd4b7c32b	0x5908c88d	0xac6c1fa3
+	0x653184a5	0x062bc0bf	0x383de594	0x17064fc6
+	0x0650dbad	0xaec15153	0xab0572ff	0xab8c6f3c
+	0x37a93f91	0xbe51b8c5	0xabcd8573	0x05b3ad78
+	0xad6c9ecc	0xf302c7ab	0x4b3b88f7	0x805a0107
+	0xa5821ddd	0xc36f10ad	0x374b1056	0x79e69f8c
+	0x8368b6cf	0xf69458a7	0x9fad691d	0xb937724e
+	0xc542bfb1	0x37c0178d	0xc4707414	0xd6c7fa86
+	0xb3933710	0x227800f4	0x6dca3e39	0xd88bdb91
+	0x03755bda	0xa7f2d11d	0x4ab40803	0xf353e7ed
+	0xf2464ee4	0x8e58cea4	0xd05807fd	0xd8d8da5f
+	0x1a461333	0x5e84830d	0xb94ea4bc	0x5bf3506f
+	0x76461ba7	0xabe88c54	0x124c2e39	0xc3b01867
+	0xc6b0d4d1	0x9cc3c7be	0x8039ce38	0xfceb0e88
+	0xa965c5ce	0x9ff3811a	0x1af1c60e	0xae9c5f9b
+	0xee28bd50	0x202cbd2e	0x340a1312	0xa8f7115e
+	0xb000cf3a	0x21ff4052	0xa555f08f	0x1bead4d7
+	0xac14e135	0x449e208c	0x05ef8d94	0xb555a613
+	0x9d65a902	0x3ad8cc2a	0x55170533	0x75782927
+	0xefd4b5e5	0x6127ef1e	0x23fb5114	0x7ca3e1bc
+	0xc08957ba	0x44c4e2cd	0xc0b97ef9	0xea99db5a
+	0x53fdeb31	0x61721ee2	0xe41ef3c1	0x5f4788f5
+	0xa8543eca	0x3f36d642	0xda6eccef	0x0341c756
+	0xbfe7d2b9	0x66bb5cef	0xbfb43507	0xbd9c878e
+	0x94f307bc	0x7cd56198	0xf98596ba	0x21e9c50b
+	0xb9c9d725	0xf16211c2	0xe594b398	0x7e01aefc
+	0x745e5ddb	0x00bae556	0xc317ed35	0x4269b4c6
+	0x02f6b67d	0xccb4aa57	0x8a3fa0fa	0xcc660149
+	0x57cf5e87	0x4ed03819	0x77286134	0x631cc0a5
+	0x877fe8e0	0xa48856dc	0xe1c57e93	0xef04482a
+	0x40cd9ac8	0xc7f43528	0x473306c8	0x01eb339e
+	0x52612a88	0x65c3212f	0x7cc5f5e6	0xd3efbc2a
+	0xf2537dbc	0xa9428ffd	0x76ff40f9	0x0ad4a8e6
+	0x2020fbab	0xf8c5bbe4	0xb409e5a0	0x358d7b37
+	0x08220bd3	0xd3707d96	0x5e2f5edc	0x638feed5
+	0x045afa36	0x4f1604b4	0xd4dc85c7	0x37f97cef
+	0xe1c8f5a6	0xd16fdbbc	0x986137fd	0x25b3e84c
+	0x7f73be76	0xe25dbdcb	0x1f13d28a	0x7a31215b
+	0x241967d2	0x2c5b4063	0xe8339988	0x13689262
+	0x0b6d2b79	0x58773464	0xe822e560	0x77d6ba8e
+	0x6ae6c07f	0x105e1e88	0x0045bc6d	0x88ad198e
+	0xa350b9de	0xd5d0b3e6	0xc4e1cd14	0x47ca431a
+	0x2ee94476	0xa2aae1f9	0xfa2042a7	0x37b0cf82
+	0xb1aca28e	0x9a019883	0xbfb11afb	0x754ffff9
+	0xf065a9b5	0x916e14f2	0x93fba80f	0x1dd82da0
+	0xe41c950a	0x12b374bb	0x0f4d533f	0xbef539e2
+	0x1eb5c86a	0x577dd484	0x98900e2f	0xcaec8695
+	0x6a6ab336	0x135e9e68	0xc9b62a35	0xb8982b6c
+	0x5bcdb533	0x389b1517	0xbb106e40	0xd402a301
+	0x7446687b	0x35eda3ec	0xd44ceb2a	0xcfa4e441
+	0x29664690	0x598a273e	0xf2a144b1	0x68f81403
+	0xca53e666	0x064e69a4	0x87bb8ca8	0x58193c68
+	0x9b34b17a	0xde2bffc7	0xf72594dc	0x388d3f3f
+	0x638a1273	0x5ccf3567	0xcf1017a9	0xe616a6fd
+	0x64cab73c	0xd209b022	0x6f08cd26	0xc30f57b1
+	0xac2295b2	0x0c05b1c8	0xf7915ad8	0x9bcf836f
+	0x56d8b57a	0xc8b65a2c	0x11868dd3	0xea4764f8
+	0xa7bd30e8	0x8c895321	0xd276a894	0x86042daa
+	0xaf6cd261	0x18cc4ea4	0x2c2185f6	0x2bf3ae70
+	0xf3023c31	0x49f4b0e2	0x1e00afc3	0x2053b3c6
+	0xb188c9cc	0x7437a27a	0x1b29925e	0xbc488906
+	0x81cd9003	0x332fcf9b	0xeb20987a	0x831f912a
+	0x857387da	0xaf1edccb	0xfe01d809	0x05351b4a
+	0x31ec96ac	0x4f064e52	0x10ec8119	0x96c2d29f
+	0xc6e1f3fe	0x15b0d45f	0xdca23bc6	0x7b672563
+	0xa94fdc1b	0x7dd22f4f	0xd4d2260f	0xc9e055ff
+	0x89e066cc	0x98200d25	0xcba82cf7	0xffb8475b
+	0x26550a20	0xf5b4f84a	0x506cb84b	0x00d92997
+	0x7a5c5535	0xe11194eb	0x1ff21f4b	0x725d2be5
+	0xbe89242f	0x0b18afa7	0x6f5b1433	0x829bdaf9
+	0x42db07b9	0x479493cb	0xabd2ead3	0xea6afa58
+	0xf994c740	0x4cb77f7e	0xb946cbdc	0xfe558e82
+	0xa2ed5c20	0x7012b99c	0x72a41e08	0x2058815b
+	0x0528d06d	0xe6dbd7e1	0x3d1f6f9e	0xca78b63c
+	0x91fa57a2	0xb6d524a7	0x1a61863d	0x89c25c5f
+	0x16960596	0x6ebed63e	0xfcd617d1	0x0a927121
+	0x887fdc75	0xec27c8de	0x8c91a821	0xd6bb116d
+	0x51fe2c18	0x4af774d9	0x7aa13fdb	0xfc6ff59d
+	0x27dd287b	0xe7e3151c	0x835552ea	0xe628aa1c
+	0xe0edda2a	0x1957ade4	0x52336fae	0x9cecef28
+	0x2be84cbf	0xa5959450	0x65299682	0x8151d4f8
+	0x716a5209	0x0a8ca663	0x2187bc46	0x000767f5
+	0xe7295b8d	0xa8bc7a6c	0x2b4d2f10	0xf251372f
+	0x92ff27ff	0x9bfd83e8	0x8e2b593e	0x8915fd15
+	0x1e44eed0	0x4a3a4679	0xce135f45	0xf996ec1b
+	0xfd86c8ac	0x25b008fa	0x8973cf58	0x481512ae
+	0xf2bc46f1	0x8b3a92bf	0xbf2a7b24	0xb19e88be
+	0x1823f658	0xa8486c11	0x237771c0	0x6f5f0da2
+	0xb05a42e3	0xb562583c	0xa13d37f7	0xe8eede16
+	0xc5154af2	0xfdf7f9b9	0x0b907685	0x1f567e56
+	0x19987b40	0xc82974ab	0xf02ae429	0x9c356634
+	0xb85ba9e9	0xda2141b7	0xd44e331f	0x1dd722d3
+	0x68fd2f4e	0x4e7f88a2	0xab7314b3	0x3dd05c4e
+	0x1bb4093f	0xff73db9b	0xf917c6e0	0xae822501
+	0x05cab9fe	0x67c91c76	0x1ebd2575	0x1ae193fd
+	0x6f154ae6	0x13780ac7	0x6ff5bf0c	0x6b664594
+	0x494a71d1	0x9bc35a0f	0xb34f175b	0x0069468c
+	0x9b125042	0x7df22e49	0xf39cf8ed	0xbe020df1
+	0xe206848b	0x8c428e75	0xc76c05d4	0x0089e2c4
+	0x5bf9a75a	0x30677869	0x544797ed	0x68456dbd
+	0x45b8f0aa	0xac5c82d1	0x05aefb75	0x6d5c28bf
+	0x009ddb3b	0x551ff144	0xd19127ea	0xfc860071
+	0x30c93457	0xa4c4b56a	0x6928a07c	0x9f63e6a7
+	0x9fa2b174	0x7c1b2fa4	0x4a5a1f25	0x24acb022
+	0x0c3c11f4	0xc7d4cec8	0x4484a031	0x6d3cc1c7
+	0x2eb86733	0x8cd4f77d	0x7b551519	0x124b6805
+	0x57385eef	0x3efd3da9	0xea300d5d	0xe64fc82d
+	0x7d33386b	0x3933c4d3	0xe3cb61f8	0xc6fe8846
+	0xbe0df669	0x8646e4cf	0x194a444a	0x404c81af
+	0x9448791e	0x586f2132	0x3def508a	0xa3edebe5
+	0x2f3b0b5c	0xc974f91f	0x400ec25b	0xf1513ffb
+	0xc13b8859	0x32ac4d39	0xf8f334b2	0xab53ba5d
+	0x9e196996	0xf14d8046	0x22fcb441	0xf27ac4c8
+	0xbbdf5623	0x255df428	0xd95a2352	0x8d26f0dd
+	0x60a301d1	0x4a2e3e49	0x4654b081	0xf775e35f
+	0x592b5eba	0x6a3f9583	0x6ec3d395	0xc8ab02e8
+	0xf343f806	0x62745498	0xb499dbf3	0xd427334a
+	0xdf0b61e7	0xda67999e	0x14f9be12	0xf164898a
+	0xd6347aa7	0x079a537e	0x294542e1	0x687b7b6b
+	0x8478cffc	0xf335963f	0x6c1b9ac2	0x68ff2779
+	0xe3d3f8a8	0x5453c548	0xd968189b	0x13ad95b4
+	0xd71bee24	0x3939f36e	0xb19b3595	0x001961aa
+	0x5f2f001a	0x77137eea	0x477698a0	0x1c07c440
+	0x9606b6d3	0x6ce95229	0x25445629	0x5a935f13
+	0x3e2154aa	0x6876442c	0xd9175c78	0xc94d2535
+	0xf2070dd4	0xd4d1f50b	0xa04d18e5	0x3456cfa4
+	0xc7610f62	0xb705a1a8	0xb8766e3e	0x225642de
+	0x4be5b1b5	0x44d32453	0x80b8a9d4	0x7297d633
+	0x09e8aa04	0x540929ec	0xbcc58c41	0x6dcf7b61
+	0x6992928c	0xcd40ff22	0x13e4a724	0xd331d5f3
+	0xa512aeb5	0x1c1c4ae8	0x5f0fe5d2	0x3d539538
+	0x383c214c	0xd0a983e9	0x977e8682	0xf38a571d
+	0xdb92de78	0x04ba543f	0xb531e880	0xfea55473
+	0xd6d17b05	0xbdd676ed	0xfc7d4f68	0x8b5170ed
+	0xa738734f	0x8a25fff2	0xb1b0239f	0x60545acb
+	0xcfb00725	0x35f58585	0xcce4ed42	0x05da1c3f
+	0x29428b1b	0x099680c9	0xb4608916	0xa9f177b7
+	0x3b393c9d	0x92d19426	0x472dfe73	0x7b12de81
+	0x557ec0f2	0x166fa28f	0xfb6855da	0x592d3e69
+	0x373a1dba	0x9c76abae	0x13c7f717	0xbc53e796
+	0xb2d39602	0xf1efa3b2	0x00046c93	0x1faf82fa
+	0x55dec395	0x22a034c8	0x576bd5f2	0x97c36a45
+	0x08a1a923	0x9ac2f22c	0xb029e4bf	0x6c4ca958
+	0xed7276cb	0xa0924918	0x1894c9d8	0xdb993c42
+	0xc31c6e18	0xbadc738b	0x57f95d64	0x4d766a25
+	0xea41493b	0x60c19727	0xe7c63d8a	0xcbc52763
+	0x7882b244	0xe2da61e5	0xd19111df	0x526d01d2
+	0x4e7021db	0xa13fb9fb	0x23e082cd	0xb426b603
+	0x9cac0cdc	0x44a94870	0xd0adbbe2	0x9b77a80b
+	0xe1845f75	0xa1704da3	0x2d1c6207	0xba3ee883
+	0x0c3089d8	0x0cba7fdb	0xcb069fb0	0x38738df4
+	0x89971c2a	0xfbaeb7e6	0x459e1365	0x45fba877
+	0x02046ea3	0xd9d0bdb7	0x83c74383	0xc248e9d5
+	0xaae85a56	0x33092ec7	0x6bece02b	0x3b7af1d3
+	0xc92b6e83	0xba032588	0x70e61198	0xa5eb1239
+	0x4d9a6456	0x7d3fe964	0xdb3eb780	0x7e188648
+	0x511a6402	0x48c4ade9	0xba7e9153	0x09490df7
+	0x11b5ea7c	0x4e63145f	0x07ca7947	0xc337360a
+	0x2b399632	0x5d1fef78	0x9b1e439e	0x8daa70b7
+	0xf55a59bb	0xc3a8c84c	0x4d18eb22	0x74568737
+	0xf0419b6a	0xbab459a5	0x0cb07a0a	0xeeb8e086
+	0x0a9241a7	0x419c5ce5	0xec841275	0x3ec13615
+	0x49e42b6f	0x2dae6c7d	0x3fc35088	0x1b92ff9e
+	0x573b1cda	0x54381503	0x29a5b7b6	0x82994130
+	0xffb93c4c	0xc0a66aa1	0x68889181	0x0826e555
+	0xe81cdf31	0x740109a6	0xb8835558	0xaa5d9aac
+	0x0d97ea3b	0x89f744c6	0x2b702162	0x992fe0ea
+	0xab3a585a	0x3e7554db	0x9d97ebdc	0x9939bce8
+	0x486a5f50	0x804ccd06	0xff2e15cc	0x67bf77cb
+	0xf9beadd4	0x2da33477	0x18adbaf0	0xdb00dae4
+	0xe727033c	0xd10ce1ac	0x4f8c4a29	0x281bf150
+	0x764e1387	0x8c65a901	0x841521e3	0x31d9dfd7
+	0x1e7ba122	0xe8fd6d3b	0x4bfe880b	0xd2c1c20f
+	0x9a07169f	0xedbb94b8	0xe9cbcd9e	0x33cac378
+	0xa42fef1e	0xf0e5ff32	0xa86b9038	0x7dbec0cd
+	0x7ad1abe8	0x5e3e4e8f	0xc4dfe8cd	0x86630ba1
+	0x02003c6f	0xbcb50d9c	0x65d874b1	0x01a09ddd
+	0xc97d3d65	0x2d02bedf	0x6fc63309	0x214b421b
+	0x72e0a28d	0xd9c8a577	0x1c8665a1	0xd33b4583
+	0xfa004d9b	0x5c2470b7	0xc671fed3	0xe033617a
+	0x5a86c333	0x13388e4e	0x3bccdcda	0xc62fd60b
+	0xcae17379	0xf6d84d27	0xaaa52422	0x5771e380
+	0xeb1feaf3	0x3c28e7fe	0xa0fded4c	0x5f63a3c7
+	0x3b42ed09	0x1748d617	0xbc2d4fd6	0x3416fabc
+	0xc1e60e41	0x48ffe41d	0x4ea5532b	0xba7dba76
+	0x21378ac1	0x7425d0f3	0x426b3153	0xdc57d14a
+	0x54997f9a	0xeda2a56a	0xfcec5ef5	0x6fd7acb3
+	0xf2691009	0xc1a219e3	0x09a82589	0xc6e1792c
+	0xb4674578	0x0aaf55d2	0x23c7e9dc	0x7607d612
+	0x580fc695	0xd24b2629	0x0a8726a1	0x3544e0a2
+	0xc1de7011	0x30982b80	0x9cf4f328	0x02b22d26
+	0x78e33c10	0x2ce6bb5a	0x92280ed7	0x2ce5b007
+	0x64552836	0xda4a7b51	0xa6122870	0x00b28bb1
+	0xb98cda46	0x84cbe910	0xeccb62a8	0xe13c3645
+	0x2f4494e4	0xed0da7b1	0xb8aa8a1a	0x1adcbc0a
+	0xdab03e90	0x904d9041	0xaa8fe377	0x087cf59e
+	0xa123b5aa	0x633c29c0	0x36d915d6	0x8f5cacbb
+	0x8834d1b5	0xa2c12731	0xfab5176b	0xe1888d76
+	0x4875b9d7	0x5747b32c	0x73fc6d36	0x202ffb90
+	0x62900e06	0xa5f2a41f	0x497589c6	0x7ec701fd
+	0x45801f09	0x1833e8fd	0x734acfc5	0x2f65bdb8
+	0xe6add84d	0x4ad6dfaa	0xf59dd63b	0xb2150e00
+	0xed32ddd6	0x370ce8d7	0x5fec9315	0xb8e6ba73
+	0xccb15a6b	0x302a0084	0x9e49e2ce	0x7af3bc8b
+	0x488e6ee3	0xcdbf0b31	0x762ce0d4	0xc50a111c
+	0xd07d6e3e	0x18c391a2	0x1a7a559d	0x10b4b3bd
+	0xd0703a3d	0x4e431eb9	0xf78edbe3	0x896604ba
+	0xc0e8d4c9	0xd42f2292	0x5414ea6f	0x0ce7d429
+	0xbb659e0d	0x46fa830f	0xdad39c12	0x0f65fa5b
+	0xa002e598	0x5408cfcf	0xc1c3a5e0	0x28ca35fc
+	0x52b2b588	0xb76e1f54	0xb6c355c7	0x08e3ba79
+	0xfd89c1f8	0x6ebf03a9	0x51ebb756	0x729e1c5c
+	0x1ed0cce2	0x29733f1c	0x42b76fcc	0xd94022b4
+	0x3efc8ac9	0x3f23eae1	0xa0ccf230	0x9da59cf1
+	0x5f6db360	0x922686e1	0xc9138d5d	0xda43fd20
+	0xe0757988	0xa315c62f	0xe3642291	0xc45d9701
+	0x2c394ee3	0xab92e7bf	0xf6037b8e	0x1f523243
+	0xe91791d1	0x19961c4d	0x35d3b069	0x1596143c
+	0x203bca40	0xd26d72c1	0x94c059c2	0xae0df468
+	0x3b0909a4	0x34aa916f	0xe0c254e6	0xd0969c55
+	0xa9b0b923	0x80a9dd5c	0xe79b8d8a	0x3599f269
+	0x623c20dd	0x41e11b9c	0x40fcee5d	0x65dfa8f5
+	0xbffa7357	0xa5b8f59e	0x2bb8191f	0x226a1b43
+	0x910b6d4f	0x73837092	0xd666f5da	0x14fd4426
+	0xd41a8547	0x6f4e928d	0x8096c2f2	0x525ba180
+	0xc6a28d43	0x960b7cb0	0xb76dacbc	0x024de046
+	0xc8e3c937	0x0217493b	0x1516dc22	0xe19e70d0
+	0x655321c8	0xa46a9105	0x61ec2a61	0x1400405b
+	0xcd0a758d	0xdc792982	0xbd994932	0x6565c8b2
+	0x187be349	0x0afa44ad	0x714870fc	0xede1b8dc
+	0x2c4ac6b5	0x7d9793ea	0xe0bc3c0d	0xaa56f23a
+	0x7fd4e2ec	0x2131ad26	0x2cd34428	0x45e9dec0
+	0xc15b692a	0xae73e713	0x37c5c3d4	0x70ff213c
+	0x4d6322fe	0xa29a9b4a	0xca7d3c65	0x1024df74
+	0x308f4a3f	0x4f48c7d9	0x0c71a17b	0x540441ed
+	0xbc2f36a8	0x2592d7d4	0xbb643dd3	0xb8fb607b
+	0x6b2b339b	0x9a40ecc7	0x59226bdc	0x42a5c04c
+	0x6a1dc320	0x14e3c7c4	0x39cb912c	0xcf5eb477
+	0xa3a43975	0x79f92cc3	0xe9d4cdfd	0x02dc8fb3
+	0x240b6842	0xe9ff7bed	0x8f5269b3	0xc4f44baa
+	0x1f1c74b8	0xb5c39051	0x291cce82	0xfc129a8b
+	0x0fae02cf	0x31b4d4cc	0x1dfe9722	0x093cd430
+	0x96c2a838	0x19b3a068	0xa7ead8c3	0xa2b3b92c
+	0x2e1dc49f	0xe2f84217	0x670e73d3	0xd7c3710e
+	0x94e4a7c9	0x33e063ab	0x35176206	0x910504bf
+	0xb04b61d3	0xbed9c702	0x5d6c4cc3	0x63276a86
+	0x0bfe5143	0x7ed925a1	0xc455934b	0x402a8b04
+	0x01c03292	0x5de0933c	0xd932d260	0xb5b3b5ce
+	0xde53664e	0xeaec4fc0	0x506030ac	0x6fbd8304
+	0x0b0e4881	0x99c16b3a	0x6fc976ad	0xeae57df9
+	0xc53a953c	0xca681bc7	0x905e49e1	0x405d42c5
+	0xef39b878	0x57ded0df	0x56b98e32	0x392ce7d0
+	0xaa7fbfb5	0x6ff550e8	0xf346ae82	0x2b25a8dc
+	0x3ff980eb	0x302aff14	0x1a43c7ae	0x23f8ec16
+	0xf774024b	0x1c4e163d	0x6b6f9408	0x0646b4e5
+	0x2e55bfcb	0x14e3f7bf	0x86fec07a	0xda898470
+	0xd99a274a	0x8630e98f	0x8c843f0e	0xa840c028
+	0x950d7fb1	0xeca930fd	0xd281c9e3	0x29b3aed6
+	0xc419314d	0xa6147b28	0xb504311a	0x91c07531
+	0xe19ac720	0xfa8cfb5c	0xf8158bcd	0x42202a1d
+	0xfff43b87	0xdc6fa0d9	0x8a599eeb	0xac3a8df2
+	0x83ffa50f	0x346a8ff1	0x0947d1ca	0x318a8949
+	0xe409dd30	0xf73ac9cd	0x9504c972	0xa2392b4c
+	0x5594ac9f	0x7a45c3e8	0x181d42db	0x085e24a9
+	0x6cb3e60b	0x3568d771	0xfa96b628	0x945817e8
+	0xca9d28da	0xcd3a174b	0x7f84ca3d	0x90381d0e
+	0x09a6f9d7	0x11396376	0x4d158586	0xcc451745
+	0x9844225c	0xa45b8a9c	0x0c64efde	0x7429ee29
+	0x308c39b5	0xa3454fb6	0xf949f709	0x09391206
+	0x0168257e	0x94e10cb6	0x48e49996	0x92928443
+	0x4a826036	0x9a777b3f	0xf77adfdf	0xc111b354
+	0xa7ece533	0x050706ac	0x91ed3fd2	0xca15baf6
+	0xd1714105	0xb564c842	0x886800cc	0xd57309e1
+	0x38e4fa43	0xb74fe550	0x26f300bc	0x6349cbe6
+	0x4bc132ae	0x310c1d40	0x3353100c	0x0a308892
+	0xea6ab62d	0x0a438e7c	0xb000cf51	0xa21aadb3
+	0xd3628343	0xee7f1a6f	0x3ee28d91	0xa846f25a
+	0xc898e7c0	0x1198f67e	0x2401caf3	0x78d7acfc
+	0xbc592220	0x1efd847f	0x1e3e935d	0xdb9025f6
+	0x41ab6bb6	0x08a10f85	0x160dc5b4	0x4f0ed74e
+	0x8c3db59d	0x34034397	0xe26017c3	0x03fe3b41
+	0xc4480582	0x7c0c85de	0x4957c26d	0x9eb32143
+	0x28676ce2	0xe3627f34	0x71e3afb1	0x7e978fbe
+	0x3b3ee0f9	0xb5ae1bcf	0x474dc4cc	0x470e2114
+	0x2490e60c	0xbb534e7c	0x7a8ad252	0x7cc08810
+	0x9ea23718	0x04ecf4e1	0x732a9f10	0x62c69e22
+	0x5a94fb4e	0xc1da497b	0x3ab3f2b9	0x09ff7310
+	0xd7749df9	0x170471dd	0xaa551e91	0x2d605856
+	0x66a13f75	0x0be4b8a2	0xe64a0c3f	0x288e5671
+	0x5ee690c8	0x9e1c4b10	0x9f055568	0x8c6ff177
+	0xa7229231	0x19e678db	0xd90be83f	0x0cf70d67
+	0x47462463	0x327fdd91	0x51986170	0x3ad883b2
+	0xa32fa5f2	0x82167691	0x74b6c59e	0x3eae0a3a
+	0x569386dc	0x6d67fc33	0xa0943958	0x40b2939f
+	0x334acedf	0x91b6a866	0x5debd880	0xa6f3712d
+	0xbe8ca5c8	0x4b43fa68	0x72b677d7	0xa42b4d60
+	0xc719163c	0xa469fbb9	0xb484def6	0x508ddfd1
+	0x23bf14bd	0x857a13ad	0xf7a47090	0xe6816794
+	0xbf6d3db3	0xd19fe091	0xb9421e39	0x35b184c2
+	0xa5c94a6c	0x13b2b25c	0x5c7b45cf	0x648fdd47
+	0x8832d949	0x0e2380c2	0x2f8e4f88	0xc01022aa
+	0x4dec89bb	0x0a2c5bff	0xa97e58f8	0x304dddd1
+	0x468828ac	0x603da881	0x646ddc90	0x1afa151b
+	0x985bf8ad	0x6e3635d5	0x181268c6	0x420e1647
+	0x913af569	0x14075a17	0x803aba15	0x2a2562b7
+	0x2f0627db	0x52785b48	0x36ce7fc3	0x6057349e
+	0x4affb11c	0x84e82be9	0xa0f60f66	0x1d176256
+	0x9f1dba85	0x2852129f	0x4592540a	0xae083e7e
+	0x744edf82	0x75a1e1b7	0x518fbebc	0xf1828d15
+	0xfa1e31b7	0x88ebf51e	0x0a648385	0x956c002d
+	0xc8b660cd	0xa82eeb58	0x0754bcf9	0xc4873df1
+	0xf06c843b	0x7e5ac181	0x59661ea5	0xef2ae542
+	0x0fea9691	0x9493a352	0xb401f705	0x85573914
+	0x4e1eefc9	0x45e51c5f	0xd713688c	0x97efca3f
+	0x292d0e73	0x8db44fd8	0x9f4479e0	0xc049ff9a
+	0xfac5ddbb	0x4d610fdf	0xa9e01cdf	0x93b4dafd
+	0x925004b9	0xb0796ea4	0x7e166ac1	0xd030c4ea
+	0xa9f34c73	0x276cbadb	0xf3b9c282	0xa5bd6a69
+	0x53df3f11	0xded46173	0x70bff329	0x0ddd0e77
+	0x52e4a782	0xf01b024c	0xda90618a	0x34a2dd05
+	0xc144d1fe	0xbaca12a5	0xbbd28cf1	0xc54d84f5
+	0x0e7cb67b	0xe009e900	0x23657441	0x2214b4fe
+	0x37693ee7	0x62e093d0	0xf79ca670	0xf1bc6cec
+	0x1b91f787	0xc9d234c4	0x2a193a4c	0x8c2bfaf4
+	0x75f4514b	0x03501d9a	0x5554de35	0x5ff35a26
+	0x670ad976	0xbc8151eb	0x725fb971	0x5768e86f
+	0x7fdcf5ad	0xe814f3ce	0xe8b9510a	0x55bf074a
+	0x415fc288	0xa1a360c5	0xf5fef671	0x2d6253fd
+	0x7fa09b81	0x2bb2e018	0x7159e648	0x10d5d59d
+	0x462047cd	0x77583e64	0x47f1074c	0xc3c0e0d3
+	0x023a55b5	0x4ad55057	0xe6d4b9d2	0x9cdd844f
+	0x87eff8f4	0xd95c1e55	0x7499004e	0x2a43a598
+	0x0c1472b4	0x33c90a5c	0xc4703c62	0xf293e2d9
+	0xc3153c7e	0x6eeffef9	0x115e14ec	0x4ad27157
+	0x888d87c3	0x33edc70f	0x7c38ce66	0x61c10a52
+	0x5db41c48	0x8e309060	0x7b847b63	0x6b619cd1
+	0x12855e03	0x52c3281e	0x704f969e	0xf9ab7862
+	0xb143fc54	0x1ac23fd5	0x89dcd807	0x40a7ffc7
+	0xc84245b8	0x0248d94d	0x29aca158	0x92d7b241
+	0x751588ff	0xe8203587	0xc5bd7cdc	0x9de82608
+	0xb075493c	0x5d43c228	0xff6a5345	0xa64cae5c
+	0x4a1a9a26	0x08c60b16	0x9399ba46	0x3f535d1c
+	0x3b9a6ab1	0xa446115c	0xa77bd99c	0x2431dc72
+	0x729a637f	0x13f960d4	0x230d4e9f	0x0c608153
+	0x9b9670fc	0x72494838	0x14832ade	0x65aba892
+	0xd6434455	0x17697982	0x68b9bb34	0x1d700b3f
+	0x6d0dda39	0x30e0d15e	0x87de41fa	0x9fc55b16
+	0x0f5730d3	0xc3ea8127	0xeee64f5f	0xa02c5baf
+	0x64e18d74	0x31de5660	0x5cf8d724	0x6c07ceca
+	0x409e862a	0xd4ee7999	0x90c22c99	0x59cd395f
+	0x09c36563	0x1993b09f	0xb0c4e064	0x8d6870a5
+	0xe2e8e337	0xe8bef0cd	0x708d869e	0xdf808519
+	0x6fa61e32	0x27161ea8	0x063c783c	0x2aa55c1a
+	0xa6fcc8a3	0x918b284d	0xbb7870b9	0x788102c3
+	0x3e49edfa	0x6c5eae4e	0x1c9fc361	0x554ca60b
+	0xa08364d3	0xa7bd4442	0x204822a5	0x000b71a2
+	0xd4dff005	0x43265901	0xbdb99200	0xc438e254
+	0xa4982e58	0x02812101	0xfacbff1d	0xeec56aaa
+	0xa5525774	0x21ada574	0xffe2f703	0x15d30ea7
+	0x600696f9	0xc7ff3f59	0xdb57c175	0xa16f78df
+	0x54a15622	0xe3742dcf	0x06d32994	0xd48463a2
+	0x44c7c25a	0x41d6ded1	0x3b314de0	0x09992482
+	0xbeb183c5	0xa0a65c27	0x842075b7	0x9b97e3c6
+	0xd9545fc7	0x16d00629	0xd85640df	0xe79e694a
+	0xe818d277	0x1c3d4623	0x23a9a926	0x83ac1b3d
+	0x39e890c8	0xb3738b84	0x54b772ef	0x74518f0c
+	0x7190098e	0xe26aff75	0xf6237011	0xbd3400fe
+	0xda1b8fa6	0xdbf5566b	0x5155cef3	0xddbf1973
+	0x34e2cb2e	0x535fd6b8	0xbfd337aa	0x6dd1fb0e
+	0x52b04fbb	0xab5eca05	0xdb740dc1	0x104e6131
+	0xbf4dcb75	0xaeff3524	0x4257c6b9	0xbf1c8cbb
+	0x0a69ed82	0x90d991c7	0xea075cba	0x5e3c8330
+	0x823116f8	0xba8f8a2d	0xcb98a1e9	0x8b2655c6
+	0xd2f11133	0x3422f3ba	0x3e3a5742	0xdb9714fd
+	0x91701f60	0xeba19983	0x8bf9f157	0xec87cd03
+	0xb63260fa	0x207c345c	0x0c838d5a	0x736415ba
+	0x9638ab07	0xb32c72bc	0x304d191b	0x7775adc8
+	0x57ece662	0x0467bb66	0xb7cf80e8	0x4c635024
+	0x176946c3	0x29cba0ae	0xf214b3f2	0x6e727126
+	0x87b3747c	0x4c19b86b	0xfcc66fce	0x86681713
+	0x636387f1	0x589e78f3	0x2e8abf1c	0x22c828f7
+	0x99653c62	0x8e3bd31c	0x79187a73	0xc6d0e5e2
+	0x8005a045	0x78a38c60	0xe1e8ff4b	0x1102d320
+	0xaaf4ba7a	0x7223d041	0x45f73e81	0xaf7168af
+	0x218ab3ae	0x8b1956a7	0x4db00173	0x482c3bc2
+	0xd982b945	0x4bd7757d	0x0c5ef18e	0x74e66de3
+	0xcf421ae1	0xf2ddc098	0xcec27e0c	0xe79e711c
+	0x6f76e136	0xa8d72245	0x196390a6	0xbf56633d
+	0xd1156298	0x5712cd8b	0xaed801ae	0xa345fab5
+	0xfde1ba97	0x437a0b29	0xfc5628a4	0x93acf698
+	0x83ce0bff	0x212f15c3	0x723ef016	0xe793bd50
+	0x8bc51b39	0x42f17ad2	0x1df73878	0x19af3c24
+	0xf55b6f93	0x506138d0	0x164c542a	0x8d4e1a26
+	0x6c606f83	0x6fbebdf5	0x0e4ad76e	0xabd88e6b
+	0x0e0d74e6	0xd139e08d	0x8b6cf03b	0x04a527b1
+	0xe619c7a8	0xbf0d57f6	0xb38a5f5f	0x3f328013
+	0x374c0a9d	0xff36910c	0xe950a494	0xfc477720
+	0x37bd9390	0x4667497e	0x724eb66b	0x86bda8f7
+	0x52efc959	0x32d5c2bd	0xddbb49ca	0x9c1eef2c
+	0x508d8b81	0xc33d7001	0x360ae3c7	0x1197f6c2
+	0x25efc933	0x4ad234a5	0x9e9c8658	0xc16d4aff
+	0xbc428573	0x30e8b4c0	0x728c2c48	0xf34e1e70
+	0xd62187c5	0xca869f89	0x34685a33	0x85d9b877
+	0x9f77605f	0x93724d34	0x5fc8e8d1	0x70dd81a6
+	0x643e543b	0xe4ad6c73	0xd6b4e5cd	0x387519c3
+	0x719d8c6a	0xb2e0565f	0x02235c90	0x230c9b5e
+	0xe76841a3	0xc2833be0	0x4dab4a72	0x0ae6c0a9
+	0x0b5e12e2	0x4cda3610	0x954b6ff8	0x6d89a683
+	0x3583e633	0xdc540da7	0xe2955deb	0x0f290d9d
+	0xb01e57c4	0x977f4588	0x24b95f0c	0x45529128
+	0x4528b5ee	0x27511439	0xd088d9bc	0x7c471853
+	0xf03b8455	0xbda4a828	0xf49736df	0x50eb17c3
+	0x2affe0e6	0x6727858c	0x6500b8f0	0x0483aa89
+	0x0e1f6a41	0x72666733	0x85617ce8	0xa0c86838
+	0xbccd2eed	0x06e8462d	0xc947bf5c	0x4d2d0a53
+	0x02e70008	0x5039a596	0xb0118cc1	0x690ba325
+	0x057ca95e	0x032cc1ba	0x3dae2c88	0x4eaa740e
+	0xf07b09b5	0x6b2c2135	0xeca746b7	0x76019533
+	0x4cf477b7	0x31848299	0x6b5c7df9	0xc0db5ff1
+	0x7cd3e08d	0xe25fa562	0x260d66a4	0xda30cf2c
+	0x14ab6c70	0x029a8dd5	0x7cd5fe2d	0x98ea5852
+	0x555cf635	0x6c72ccbd	0x64120bef	0xd9e19613
+	0xf26ac6e8	0xafea03a4	0xc14a11d7	0xb2f8420e
+	0xe319634a	0x8a8fedd9	0x6ce0da89	0x74269f31
+	0xd7e0d776	0x86ae9513	0x48bdea80	0xb2e4c581
+	0xab25566e	0x9ccb71a5	0x7cedb09f	0xd2bdade6
+	0x39c96ad5	0xe8ebbeec	0xac8a2e2a	0x915be930
+	0x95e7c98b	0xd00e1d3b	0xdacd08ac	0xd9f515fd
+	0x45cd3946	0x828a2cc3	0xfbe1bd9a	0xc5e1ebcd
+	0xac69128c	0xcd6423ba	0xd8653b60	0x48f0614f
+	0x0c1ebbbe	0x7ab89792	0x9a4b0097	0x2bda854d
+	0xf17ab2c9	0xcde54eb9	0x4b53a030	0xe2399c4c
+	0x19454a2f	0x473fe390	0x3a42c16c	0xc4c106a9
+	0xf5d96e73	0x2ab4078c	0x5d20e7ba	0x47880aab
+	0xff5e0d78	0xa374bdc2	0xc17109ea	0x39fce648
+	0x00821cbe	0xc54a60ee	0xd753386e	0x7b28fc16
+	0xb6309bbe	0xaefd0548	0x41168500	0xee5989a3
+	0xe0177f09	0xc9fc9eb6	0x09a6e188	0x45776a0d
+	0xf19a4830	0xc6774893	0x814b2e43	0xf8be5e3c
+	0x22fa8237	0x75c98f46	0xb1c52edc	0x443d54f8
+	0x6a1a886e	0xc7f33598	0xaa794644	0x685e5ca2
+	0x97a735ba	0x3c1a391c	0x13f6f89a	0x660d7041
+	0x333c3eef	0x40541bb9	0x5c3724d5	0xc348023e
+	0x89791dd9	0xe72fba89	0x5af98b2c	0xb534fd29
+	0x64d0e6b1	0xa578e77f	0xf311215e	0x634cc8cb
+	0xbc534e51	0xdfce3ac7	0x90f88f51	0xb3f7dd48
+	0x20b3e0ae	0xf4456e85	0xacb3925b	0x2eb3ce78
+	0x37e61d82	0x724b9cbc	0x1462d9c1	0xd3f49dc4
+	0xc1ffcc00	0x7c3e3f86	0x6f283bf8	0xf43671ab
+	0x90cbfb35	0x55390829	0xc8fd0d31	0xc687c45d
+	0x724ee656	0xfc1eab3c	0x3c8c2f04	0x3caa3af4
+	0xbe220358	0x4d5b49a2	0x12cf4893	0x867173fb
+	0xccd4b513	0x7c94a1bb	0x86c42c18	0x2b2070f3
+	0xd2a70638	0x9d7c07e3	0xd02ed59e	0xd349488f
+	0x1e85754d	0x333db889	0x0d0defdf	0xef282e45
+	0xac3f6c29	0xd65a68d1	0x5d0914e4	0x395ec78a
+	0xb056aa6b	0x4d98d059	0x7ae08f88	0x25c923d2
+	0x79670f38	0xa881d62f	0x89cd5015	0xfb01da43
+	0x5861244c	0x05e201eb	0x41d71eda	0xb2babb53
+	0xc3845fb3	0x1f3b5c56	0xde6c10ac	0x73adb998
+	0x714aac3f	0x4ad9fc65	0x3acdd014	0xeb319d58
+	0x48842806	0x47ec1040	0xbfdf0052	0x3c478ec6
+	0x83b43a0f	0x9e727e69	0x9f4d5925	0x9f45c13e
+	0x30b8572b	0x26edf8cb	0x577e8b9d	0x9b98d7b3
+	0xa44a9bbb	0x903e39eb	0x51226dbc	0x933a52b7
+	0x14c6dc86	0xbc24db59	0x21054454	0x98fc5fa6
+	0x2c9d8606	0x19178173	0xeda24205	0x90dfaca4
+	0x21d562ad	0x7e3ad05e	0x2b3a40a4	0x46513f35
+	0x0d13a598	0x8bf71ca2	0x6a36c430	0xe66f5587
+	0xc9f13bd6	0xb6534a8b	0x8a3fbfd6	0x38cdfe6c
+	0x1a1c89f8	0x6d782709	0x7919c451	0x6ccc96fa
+	0x334029b2	0xa638356e	0x001e709f	0xb2132b06
+	0x483f1933	0x189ab8f9	0x4ba0ec13	0x490aee0a
+	0xda63f1fc	0x5679d38a	0xcf1e92f3	0xe7257fbe
+	0xfeb733d7	0x0704860a	0x34ce2032	0x663b948f
+	0x544cc928	0x8c23d5aa	0x67986469	0x93f9ac08
+	0x4fa9a13f	0x9eb311d4	0x41a64161	0x29d1050a
+	0xa5285c24	0xb53d03a6	0xc5de26f3	0x7876d1c5
+	0xbdcdcb4b	0x79d1196c	0xe9890732	0x3e58a8c0
+	0x874f03c7	0xfdfc9cac	0x5d57fa57	0xa3ef01df
+	0x47bcff48	0x8beb1aae	0xf4bb4f9b	0xa5c83b64
+	0xd69ab0ce	0x40f6691d	0x2eb8fb7d	0x22640f8d
+	0xac1ba157	0x3687d705	0x7fac8727	0x4ad75cd8
+	0x7016d2e9	0x25c36c08	0x7e4248ea	0x292bda19
+	0x2acf589d	0x0ef7726d	0x835f9e62	0x3f9a1973
+	0xbb6d2588	0x078ff6b4	0xaec22b5d	0xc740501e
+	0xa2ab115a	0xea993e64	0xa0cc3ed1	0x934e4e0e
+	0xd732b66d	0x5fd28c47	0xe4ccb898	0xc6a101c0
+	0x78274bae	0x625df6a1	0xaf774052	0x3b7c08d2
+	0x6180ac39	0x3e5aa769	0x6ec74578	0x6b5d27b9
+	0x98e58a17	0x119dd7d4	0x39429c5a	0xe3d5b391
+	0xbb8fddb8	0x5929801c	0x68cef71c	0xc36fa301
+	0xeace4850	0x29f4f97d	0xa58bad79	0x2823998f
+	0x0fe1352b	0x5960ded0	0x69308816	0x0d7e33c8
+	0x2fb13bfa	0xff6a326f	0x69cb631a	0x839ea2a1
+	0x528a8065	0x34cbebfa	0xd4432cc4	0xe13b550b
+	0xe046569f	0x87b41fb1	0x7751107c	0x0ef6e60b
+	0x856ffc50	0x11995683	0x77c2ebf1	0x4dec97f9
+	0x3a28ebc0	0xb7bfa04a	0x40cdceb0	0xd559dd06
+	0x61c2cd6a	0x8a906fa2	0xd55f43d6	0x7fb3ac35
+	0x8cea4e81	0x1d359c2e	0xec447c57	0x3414f7f1
+	0x18243b84	0xdf76849f	0xd753044a	0x7af2d51e
+	0xaee26ecc	0xae6946b2	0x7478c675	0x88b22f49
+	0x4de13fc9	0xd35c5956	0xeebb60b6	0xa15b1736
+	0xa6e78d78	0xfd5e30b3	0xb4fade2d	0x964eb418
+	0xe9035f51	0x22ab8242	0xfaa64053	0xdfe03834
+	0x47beb588	0xb82a0887	0x11182e85	0x2f2f9a67
+	0x4b612f11	0xae04077e	0x7f783c25	0x883a34e1
+	0x32d43beb	0x6f0536f7	0x85c1537e	0xfb26199a
+	0x45417e88	0x4af2c8cf	0x0a334486	0x2a3e6838
+	0x31b8725b	0x63d64541	0x7e516a0e	0x7e42e766
+	0x4cf30198	0x68abecff	0x7fb49c43	0x8f5b558b
+	0x32b99abe	0x67337248	0x224c3411	0x4e7c41b7
+	0xd3aee3a2	0xca19e704	0x2a430b7d	0xe9aee453
+	0xf4ce492d	0x48fab2a9	0x42ec2076	0x0182cea5
+	0x8a6373c7	0x18f41b5d	0xdd062fd5	0xb1db44a7
+	0x285ad917	0xeaaabbd1	0x359b1b23	0xcc123c8e
+	0x38b70cb9	0xb01ae722	0xa6e72010	0xb647530e
+	0xf9651d41	0x366d6d0f	0x4b656a6d	0xd36637f0
+	0x4b5ab8bf	0xc22fdb1e	0xc57c8250	0x799f4e60
+	0xb55bd50b	0xe8a3432b	0xe752e4e0	0xd0c86482
+	0x122991f1	0x5bec598e	0xbcb89abd	0x739f61d0
+	0xd230ae2a	0xd0b99c05	0x2a998a6d	0xab715831
+	0xb7dd1939	0x57db0ea7	0xed1f4952	0x49274caa
+	0x35e319b0	0xed2c9cb3	0x601caa20	0xfe782688
+	0x64b6d30b	0xcd5c325c	0x2c836157	0xa3552f79
+	0x188094db	0xa42dd7e8	0xc09c2dda	0x02d98d8d
+	0xed270d28	0xb0f38ada	0x5d7b4261	0xb41df8d8
+	0x7341b6ae	0x024ce90a	0x0727ae4c	0xa8dd3a0d
+	0x390f84d5	0x43f5bd12	0xd11fb61f	0x6fc330e1
+	0x7f2d7fa6	0xf758a4e0	0xceb1f3c3	0x2f341836
+	0x98fb470f	0x5bf68e58	0x1917a5b2	0x75f33be6
+	0x16e22316	0x8aa810a0	0x1fc6c9b2	0x22179249
+	0x3de701e9	0xec48d8b6	0xe85248c1	0x314ce9c1
+	0xddeb2f47	0x0187909e	0xaa755f62	0xb2019460
+	0xb2016a9c	0x91f789be	0xe5925997	0xe4864300
+	0x1fd13759	0x0ad97c1d	0x7cf08c01	0x7eac2dd6
+	0xcf61a7f3	0xaf9e108f	0x939a2fd9	0x0cb48e78
+	0xe6ea1a8b	0x0b968273	0xef1c9310	0xf60e82b7
+	0xe76e9bed	0xb8fa9668	0xf889765b	0x0e51eed6
+	0x6b6566ea	0xa8f7e2c5	0x9d8c283a	0x879afdcf
+	0x944873c5	0x58afcfa2	0x2e60600e	0x59666667
+	0xc812b833	0x5842d0be	0xdbdc0829	0x786bcff9
+	0x5857ba06	0x6968c729	0xf5447949	0xdb1ceeb0
+	0xaf04d1f5	0x30614f7f	0x3e80fdc9	0x8a6e1ce0
+	0xa267d7d5	0x8896143e	0x24e59072	0x68122e1d
+	0x3ce24add	0xda677bdc	0x8c3f74ef	0xfa60e825
+	0xf5c136cc	0x2cc5f249	0xa1c6b642	0x47a2305f
+	0x52cadbc8	0x4d0c32f6	0x07f4d344	0x1f496d59
+	0x5699b970	0xb8cbe564	0x707f7a2e	0x818bfd45
+	0x800a8be0	0xd3de4f1f	0x62de0a3a	0x6b342869
+	0x054daa7c	0xc72b945f	0x1612f126	0xdb4ad492
+	0xa28c467b	0x78542799	0x61607353	0x39f1c142
+	0xebf30ad6	0xabe076d0	0x5125cce4	0x5584149c
+	0x65fa33f4	0x878a918f	0x8c7e5c37	0x334c4284
+	0xbfd816e1	0x0f0f3460	0xd54519fd	0x03701ca9
+	0x64885229	0x00e841d0	0x756a9472	0x0c16c5f6
+	0x65560e81	0x129b6995	0x91c9dd1e	0xe9730dae
+	0xce47f2a2	0xead8a0ee	0xcd58078f	0x7ca2df31
+	0x0ebbf13d	0x3c74e061	0xb7f3980a	0x0d354b88
+	0xfd8db90c	0xec6726d0	0x6bfce0f5	0xea98b7a0
+	0xac5ddde2	0xb372a14c	0x47b09ed5	0x531bd5c3
+	0xcfaf5a0a	0x51d6394f	0xe9efdfa8	0x37c79445
+	0xb13ebf62	0x46715efb	0x31e6a0d7	0xfa48ab48
+	0xc6552f2c	0x3067b978	0x0afa4ab7	0xc2c17055
+	0x68dd427d	0xeac01e43	0xe90f12d8	0x6d97c3b1
+	0xe0d339b0	0x2f3c84cd	0xca3eb3b1	0xbc0d86e1
+	0x3566f657	0x083374b0	0x199c677f	0xa4a8a4d3
+	0x224dd5a8	0x8f304abf	0xe1019878	0x9b290d4c
+	0x5cef7341	0x59ff7e48	0xc91663ac	0xb0b1bede
+	0xe9d8a9a5	0x8f34cb70	0x588d00d6	0xb7fe69b6
+	0x29036caa	0xd21d7998	0x4edc3ee9	0xdbd94f37
+	0x99c63455	0xac94efda	0x545635dc	0xb787b5e1
+	0x8228666b	0xc7cd8170	0x4f1924a5	0x437884c1
+	0xfa9236fb	0x1f0f949c	0xd1dc0597	0x56082a24
+	0x04e51919	0x05dd926f	0x06d264ac	0xaa672d38
+	0x5a3e396b	0xab48a57c	0x53489bd1	0xb36b3ba2
+	0x55164db6	0x5b52c5f9	0x68aa8b7f	0x922ce829
+	0x09e6e5bd	0xbc488a86	0xc0fb6dab	0x98e7754b
+	0x4c9ad717	0xe3ae7045	0x0b498742	0x80a4384b
+	0x0dfe0b99	0x70eab3b9	0xbee30b9f	0x4237ca85
+	0xe67662b1	0xdae3dce5	0x47c84a45	0xf72febf2
+	0xa58dfdc8	0x77ae88d4	0x038c76b7	0xae699990
+	0xf5f10de7	0x65d4c59a	0x004a8b4b	0x67c788ec
+	0x71c918d7	0x0ec70171	0x7041de53	0x43591e1c
+	0x807242f8	0xa27fe146	0x0055fc7e	0x2f08467e
+	0x5e04a068	0x54dab094	0x4f6e8c7a	0x20ac2825
+	0x47949a42	0x9181486c	0x038e3132	0x7c1c51be
+	0x97544f38	0xe2d27588	0x64889c21	0xdad9a1a9
+	0xf1d328a4	0x7d47991f	0x2faa1b85	0x2430cab0
+	0x0e849f91	0x213686c1	0xa2635f37	0xee7983ae
+	0x87871273	0x6867d60f	0x04cb29ae	0x4e0ee4ee
+	0xfbd2666a	0xfd7fe017	0x870b26ee	0xc42e104b
+	0x78919117	0x19590e66	0x9e1a5039	0x9609471b
+	0x4057fde6	0xc1f27544	0x30af8a8b	0x2ea267a6
+	0xcfd886b6	0xe632b1f3	0x3f10bc50	0xf38a1bd8
+	0x7ae1e284	0xe3876d7a	0xb4ce64f8	0xf74b4100
+	0xa97686da	0x17ebacde	0x2ab068e8	0xcebd1076
+	0xee8f81d8	0x0d394301	0x6f32c277	0xa926dc1c
+	0xd5d2ea55	0xdc016b6b	0x6a96022f	0x0143e314
+	0x23836eed	0xa3e18369	0xd2a155bd	0x8022cef6
+	0x080b32a8	0x74ba38f0	0xd1ca2089	0x7c80219e
+	0xf536af16	0xd7a337e3	0xa33600a6	0x39c7754d
+	0x7d215312	0x1dd65026	0x8cb496c7	0x89dfd508
+	0x9f945a1c	0x45caec32	0x020a1edc	0x5917baa3
+	0x296b4b1a	0xcfaa2023	0x63e7a0e5	0xc48b19ae
+	0x78d98b1e	0xc5d6be01	0xfe4ef13d	0xea6c9915
+	0xb8190f09	0xf1793822	0x9acf1593	0xc7710fa0
+	0x6b9a9f3d	0x0220ee2a	0x5d63043d	0x7292a0d5
+	0xba9a1682	0x6f1e7c19	0xed7cc52e	0x6bb89645
+	0x4370269c	0x9cb2c1a1	0xa7135973	0xfd1f3bbb
+	0x50e6eb67	0xf2b9bd22	0xd891f6a7	0x4e0a7449
+	0xc3dc0005	0x878e3333	0x3b4b8686	0xb215c65c
+	0x5d8d24c0	0x8d203496	0xff20d243	0x0a6c1253
+	0x2385c79f	0x52e8d6dc	0xda4bb8b7	0xfab66d97
+	0x05a4a795	0x6876e856	0x9dabedc2	0x53550c20
+	0xb3bba16e	0x853bf1cf	0xb85b906d	0x3f374468
+	0x62e07c2c	0x6903a495	0xdb119586	0x07e91546
+	0xa8388945	0x5a4e1dda	0xf054cdad	0x4b052880
+	0xe9bbc9ec	0xe3555e11	0xd4d6479a	0xcad6a986
+	0x31d9c4ae	0x510ff951	0xcb2f3164	0xbe283401
+	0x0c390b9e	0x0c9cb487	0xe64e8ffe	0x611a63c0
+	0xa1d700a5	0x3f864335	0xd1fdf32d	0x7a3aeb09
+	0xabbc8c4d	0x4d703604	0x6532c8e7	0xccebc529
+	0xf3c0f514	0x1567f19d	0x591abf6c	0x6c7fc459
+	0x0858b061	0x092b2489	0x33c1a9cd	0xd6cc8e2e
+	0x7c1ffeb3	0x3f45cf40	0x1fbcbd39	0xc6f0e628
+	0xb88bab4d	0xc699de42	0xb62d850c	0xf71a6768
+	0x2866b891	0x13093fcc	0xc730c502	0x2deaeff4
+	0xb1bc8535	0x4303997b	0xb31ebd2f	0x82debe94
+	0x843fa02d	0xba29f80d	0x03cb58c1	0xef1d2017
+	0x0b5aadf0	0x6c5c3286	0xf084faeb	0x8b96a39b
+	0x67cb38f8	0xf686ee62	0xbfdc22a1	0xee3f779c
+	0x8ec73c8c	0xb448536d	0x67bb5d68	0x4369ea8d
+	0x4b5367cd	0x2dbbc0be	0x8f5986e7	0x798c8392
+	0xd3aac078	0x0081c0bd	0x94d9d70b	0x40bdeae8
+	0x6b528e89	0xb0713745	0x063e535f	0x7d696463
+	0x64f0666b	0x68a82e8c	0xc749dd19	0x875883cc
+	0x3d35728d	0x4c0e5d8d	0x135f11b3	0xb649b37f
+	0x8aead5cb	0xdfbd573e	0x563bf917	0xcdb75f08
+	0x024b93fb	0xc6477eea	0xd88ce51d	0x95f7d77f
+	0x0b561446	0x2fb6992c	0x4b48c8b1	0x940da60f
+	0xf1be60b9	0x66d8641b	0x17a0ce15	0x49d22f40
+	0xb8c494da	0x91930bb1	0xcd317991	0x4c5b4c23
+	0xafda60eb	0x212c9f04	0xe4732f4e	0xf731ae57
+	0x19165943	0x2d9288c3	0xc9c45dd3	0x2e05b148
+	0x225a256a	0xc0249ea2	0xe96733d1	0x56a6803f
+	0x20458549	0x28210fd6	0x13da740e	0xf0f0be41
+	0x029c1fa9	0xb1daf3f7	0x1bf0c9aa	0x6f0d5221
+	0x998b3616	0xa02212a3	0xe76b39b1	0xba0823e6
+	0x146da6a4	0x858a3e0e	0x58e75b32	0x732f75ed
+	0x8d88385e	0xe0e7ed55	0xc08ca86d	0x97e2ef67
+	0xbb048208	0xd384c40b	0x8595bc69	0x65581977
+	0x7b091c4c	0x60bfbbb5	0x23bcf38f	0x32e4621a
+	0x7f790d95	0x72c3267c	0x34dd0c12	0x27438915
+	0x5619893a	0x09d55159	0xdba7eef9	0x7413634f
+	0xf4883417	0x59a2f28e	0x491f5779	0x0c138f9c
+	0xc52a03de	0xcb1f92d0	0xb6cfcd21	0xbba95c83
+	0x5302f12d	0xfc4c030f	0x18722dde	0x131cd3b1
+	0xa19a1cdb	0x103d9216	0x403e45db	0x5cab72f3
+	0x17e18f5c	0xbad9d0d9	0xd0d2e010	0x798106fc
+	0x3abace6c	0x2c3131c6	0xf9529b61	0x27cfa158
+	0x8890951f	0x87ccf0f3	0xa112b1e8	0x3e0eb033
+	0xd7469e14	0xb6ccd2ca	0x3d238069	0xb32f057e
+	0x8d2c939b	0x18d8aa3d	0xdb3cdb2b	0x861ba258
+	0x46e7b170	0x4830d004	0xeea1b8b2	0x44e29b51
+	0x0cdd8591	0xf93ad973	0x9383c44d	0x24e323be
+	0xaaac87a1	0x84eb09d7	0x1f66b641	0x303f92b4
+	0x81a63a86	0x516321e4	0xe33dfe2e	0x371a4624
+	0x8f936425	0x596976ca	0x7b1947ef	0x83a9db29
+	0xc5f337b0	0xe4d51b73	0xb35b56ce	0xb9cac5ba
+	0x51705ecf	0x93e7d63f	0x5ee7d916	0x479f25b9
+	0xe90bb406	0xfcd6e78d	0xbd8ed9b7	0xbca7c8b7
+	0xdf95f4cb	0xc28baeba	0xb4534bbb	0x98b4f840
+	0xf2218357	0x726e4f81	0x7591ebc4	0xc0523d15
+	0x6bc82550	0xedfbcfa0	0x57280f50	0xbe7e420c
+	0xd1152012	0xbf3ee0a2	0x11825710	0x18e728d1
+	0xb8af00b5	0x2d1e940d	0x1c9ade8f	0x923ed269
+	0xfd8c2580	0xf6477ff7	0x476a486e	0xd09c18dd
+	0xaede7959	0x55fb68fc	0xe5692f7f	0x0bf4bd18
+	0xf5fede2b	0x07bb05e7	0x1bb8ec54	0xa46bba84
+	0x15051826	0x762ce6ae	0xa0246225	0x35c38cab
+	0xbbd00a24	0x8205d3f4	0x4cb33ba4	0x293013fd
+	0xd4f67965	0xe9c1951b	0xff108efa	0xb8e68197
+	0x36d51e4c	0x2959f7f9	0xf2e4206f	0xc9973e09
+	0xb61ce3fa	0x9543be90	0x63642668	0xcaaf02be
+	0x7346a8eb	0x4111f5b5	0xa453cc2b	0xdb524b49
+	0x4d528cfa	0x71e5fc4d	0x62cbbab2	0x8423f40b
+	0x1a4db908	0x560c41c2	0x03982d88	0xa49c553a
+	0x529f6acc	0x82dae294	0x6c5dbaa4	0xfb4ae1f2
+	0x36e31345	0xb5cba88e	0x3704c623	0xe35245ea
+	0xa412107c	0x35faf59c	0x08ceb649	0xbd67a6b9
+	0xe37ddfdf	0x21303abc	0xb7de5e8e	0x88d9366f
+	0x49bdd73c	0xeca0cd02	0xfe1e01eb	0x30a56c2d
+	0x0cae1f5b	0xe77521c7	0x5ca59eaf	0x1288aa13
+	0xc60bc96f	0xf7292504	0x2b037e4d	0xf34757b4
+	0xedcdc492	0x39044092	0x5d710fbb	0xb8658511
+	0xe23e4d57	0x595d4d3f	0xc0f80105	0xfe952879
+	0xe81e2cb6	0x4f5a8fed	0x3bd0d700	0x211887d3
+	0x6ea6e78a	0xe066640c	0x0d29c725	0xdabbeedd
+	0xd2aca4d4	0x65c4a06a	0x6645b62f	0xb1de0cd7
+	0x022e07ea	0xe9f9248b	0x0a2251da	0xdf34159c
+	0x7894bab3	0x72e465eb	0x37448fca	0xbfbc1911
+	0xa79e4938	0x48b83ec3	0xb9c6833f	0x19d24abb
+	0xa434e777	0x77947277	0x2309612e	0x546a6ebb
+	0x4c96447e	0xab918dce	0x5075ba1d	0x0aa55a7c
+	0xadcce25b	0x837819d4	0x90d62a9d	0xf116ede5
+	0xb056cc7f	0xb036353e	0xb7c1af8d	0x014c2cd1
+	0x356f1593	0x008c2634	0xf7cd0cb0	0x02b0576c
+	0x5364c954	0x5b40800b	0x60054bd7	0xef31bb60
+	0x1a85370a	0x458c4348	0x435b8da2	0xd8df0e06
+	0xde0cf1b8	0xd3c6171c	0x0bc14938	0xdc874128
+	0x694f96cc	0x7b6687e0	0x9ca59f25	0x617aea60
+	0x63ebcc8d	0x4bb44d00	0xce46d01c	0x4ab07a75
+	0x64757638	0xe5903811	0x3562895b	0x760627ce
+	0x8939cc7f	0x225db9b1	0x730062d9	0x7a5a7a15
+	0x49678fc3	0x8620cb95	0x9439dee1	0x501f2cae
+	0x3d08a33c	0x352de5c1	0xe7b24442	0x6ec76b79
+	0xc575a1e8	0xb7024b20	0xc9dbb9f0	0xfe2303c0
+	0xba3716ae	0x0cf37bdc	0x1c68a4a7	0x7ba0d609
+	0x43003a93	0x17dd96c3	0xb884aa37	0x15b2d65f
+	0xf6016133	0xd1fd7e04	0xc0a22822	0xf8c26247
+	0x818c35fa	0x4e2b3605	0x83923c44	0x4ddd4397
+	0x6faf6a11	0x50438703	0x67796dac	0x3443b780
+	0x484f5bb9	0x8ead98ea	0x472ae543	0x94b0b17b
+	0x1307833e	0xcb0e8286	0xb02e1ab1	0x36a89f9a
+	0x372e82f0	0x84741303	0x111ad8ae	0xb1eeacb7
+	0xd7d8ccd6	0x5f779f32	0x0d65184c	0x0a398467
+	0xc07c099f	0x0704ffdc	0xa10b2f17	0x4c926dc9
+	0xd80829ee	0x0821015a	0x512e6d0e	0x57b514dd
+	0x509cdfd6	0x7e08ef24	0xf536c381	0x65483797
+	0x439311fd	0xabed0f15	0x51a372c2	0xdd24c506
+	0x839cdd63	0x0c21c8dd	0x513d9eb4	0x43c6a95e
+	0x5d543848	0x64843a49	0x687bbf41	0x93d3bce3
+	0xcf85eea3	0x5f3a6fc4	0xe7b45979	0x4c5848ce
+	0x924188e3	0xbcbded12	0x0cc18c86	0xf3fd5723
+	0x148dddb6	0x77cb388f	0x30afd47c	0xa306c453
+	0x1da0b234	0x0f206f46	0xf25975bb	0x9c75d28f
+	0xc60ad2fe	0x0067c5b0	0x497a1617	0x81d330e6
+	0x2c5362ef	0x86a54b1e	0x80ad976e	0x0a86ed37
+	0x1183b84e	0x2e2ce6e5	0x10b02598	0xd56fb0b7
+	0xe3e0bca5	0x755d2333	0xe0be1b85	0x6c976f4a
+	0x555a1465	0x8ab38399	0x51d4a5c8	0xec3d86e1
+	0x2a85d0dd	0x0d31c16f	0x603f2d48	0x274d5d68
+	0x292e7df9	0xe444f292	0x329946f1	0x132c3230
+	0xb2c3ec05	0x88362f92	0x763dc2fa	0x7ee6f3ab
+	0x7ca649e8	0xafee8a8b	0xeef65517	0x4789c1e3
+	0x85bd4cb3	0xc87762d3	0xfa528ba7	0xa8e20dde
+	0xd369c227	0x97e7f300	0x8256f4ce	0xdd5d2901
+	0x1e37c55e	0xbb6e22fa	0xd9424392	0x8798d9a5
+	0xc118ddb2	0xc3c91c40	0xe68ead77	0x8cf3655b
+	0x4381e8fc	0xc94f312a	0x0b372483	0x70b620df
+	0x53820813	0xb50d6f0c	0x64a53e9e	0x6f7f19f3
+	0x6315f718	0x9aafff2e	0xf3b5a338	0xf1f3293c
+	0x750ac26c	0xefe3ddf9	0xdc7369eb	0x024dafe0
+	0xf56354fe	0xf0afaf86	0x7da1df00	0x7447ffa2
+	0x4afd091f	0x24f39c82	0x3b3c8aa3	0xd90fc65d
+	0x10d90b8a	0xf05d49fd	0x281320fe	0x75f62523
+	0x0537b558	0xf52ae61c	0x77961852	0xbd0db386
+	0xcb650cb6	0x7387ec69	0x320764c4	0xf5013b3f
+	0x4f4239c8	0x4983a307	0xf510f405	0x7e355790
+	0x4f8480d2	0x50dd84ca	0x66947bed	0x56efdfe0
+	0xa593407d	0xdac216de	0x642a5f74	0x92bb9c2f
+	0xf37abdd9	0xa24b1b64	0xca1f722c	0xaa5de969
+	0xb6cb128a	0x697f787b	0x5bd74fb3	0x6de74e39
+	0x2bc9a4aa	0x634455ab	0xa82aecc4	0x69647f0d
+	0x4be06592	0x0c220c92	0xb08adf1f	0xd4571d2a
+	0x0fadece6	0x297c124f	0x2830a499	0x3cc8363f
+	0x44e34d3a	0x27b4d820	0x98be7f08	0x43417964
+	0x8a3af8ac	0x89c42336	0xe55d19dd	0x00ee1f6e
+	0x47d48658	0x55986f58	0x11ccb046	0xf3b97a07
+	0x7ed364a3	0x106cfcd0	0xc1533857	0x3add2c15
+	0x143852c7	0x55b38512	0x49a85ce8	0xd61a285d
+	0x513bd0b9	0x21bde48e	0x4f231482	0x93aa6dde
+	0x88035659	0xa83e3d2b	0x542513f8	0xe6e74a1c
+	0x06092343	0xd37c8770	0x41553ead	0x09980a79
+	0xb0e45895	0x80db4662	0xa6ce0960	0x965cfa7e
+	0xfea96644	0x2a79157e	0xf020e115	0x61823e96
+	0xf14f63d7	0xd753d1bd	0xd24a060d	0xfd2691b9
+	0x18da9d0e	0x9f3c93c4	0x2730e0f2	0xb47e2afa
+	0x920fda38	0xb5d89646	0xfb4728e5	0x7e78c2cb
+	0xe46f812c	0xe51cc5c0	0x9d2957fc	0x548798a1
+	0x240c2103	0xd650ff70	0x15c49ff6	0x99587c0a
+	0x1bb4a5ca	0xd6db66e7	0xec2d3ac5	0x54164690
+	0xe61bd6f8	0xc7a45cf8	0xee25f4f4	0xd1eb3ae7
+	0x90085a1b	0x46a7a74b	0x829717f2	0x7f0769cd
+	0x3ef72792	0x0c8617a7	0xa86becad	0x9dfe5329
+	0x1a33c5a6	0x47d4c75b	0x2e10b45f	0xbd11762e
+	0x15b72a9b	0x015c7f84	0x379c6bd2	0x27525345
+	0xff3ac5a6	0xac916082	0xf5c24317	0xcc43fc64
+	0x7f092c8d	0x931d9a0c	0x5a07f13e	0x3e1aa46b
+	0x717a343f	0xd51221c4	0xc9422fcd	0x63f7af00
+	0xde81a497	0x0322d271	0x972a4065	0xd75df029
+	0x343a94a0	0x8c225f7d	0xb4abe87e	0x3cb8ba1b
+	0x0babab14	0xf29704e7	0xd7134233	0x391f1a35
+	0x33aca565	0xe6ae586b	0x0470a42c	0x570efddf
+	0xfea26a3b	0xcee8d934	0x99ece522	0xb8af1375
+	0xfe4dea4b	0xb96a32c2	0x3469ef9c	0x029fade7
+	0xc4e77d55	0xc0449b95	0x63336e95	0x8d46c2e0
+	0xd86d6e23	0xd365b781	0xe73ba0fe	0x10a354c5
+	0x2d4511a0	0x077206cf	0x1c0dbd55	0x03396771
+	0x8bce27af	0x70355b4b	0xc2275e58	0x3cfa4df5
+	0xc8b3b9b8	0xf3fd510f	0x6b055de5	0xb3fef295
+	0x42b95a20	0x5b5e75e7	0x0aaaa734	0x636d50ae
+	0x8329283e	0x446e76f3	0x6adc320d	0x69a3e9df
+	0x1da68939	0x6f071783	0x498dfee5	0xaece51ed
+	0x4f8a72a8	0x4f2f2f65	0xdac3ba47	0xcbab0287
+	0xf966cb4d	0xba27861f	0x54c79a21	0x44e2359a
+	0x6e6b0e7f	0xceae84fb	0xb1530a59	0xecb8cd96
+	0xff60633e	0xed748fe3	0xf1ab0d95	0x59997216
+	0x6894cf41	0x948fc7bc	0xfb162ae5	0xeb9951a1
+	0x99d0a7a3	0x9234587f	0xcd42615b	0x6f9ad0e8
+	0xeb936dbe	0xbe72b62c	0x44ab5e9f	0xed736b08
+	0xffaedca9	0x103b89bb	0x7896b40e	0x13a5a924
+	0x56786357	0x02ab80ec	0x72ef47fd	0x81bf0fd7
+	0x6661b300	0xaefadc79	0x9968433a	0x16f3718b
+	0xe997a663	0xbbb55a49	0xf9b9a710	0x5727271f
+	0x20e9bf55	0x358e3986	0xd1214e1f	0x4d42c46f
+	0xa6bf8194	0x0c14a853	0x7b51aeb0	0x2f3d4de4
+	0x3d6ffef6	0x4e94ba19	0x71a9c861	0xcade2398
+	0xe0b3eb18	0xc9f028b0	0x7d29d2d0	0x372ec60a
+	0x288a5bfd	0x4fc2bab3	0xc01dd045	0x8222e147
+	0xe06676de	0x750bbfea	0x586ffb3d	0x2addb655
+	0x767a6528	0x78abceec	0x1646cb38	0x21e26890
+	0xd2a7937b	0x2463457c	0x764103fb	0xd540867f
+	0x3566875f	0x007449ba	0xf9c0c523	0x2c51c86c
+	0x437e1196	0x69fc0059	0xe0103408	0x19f23997
+	0x23fdf335	0x7262eef4	0xcbe09390	0x583d0099
+	0xe862084d	0x19fffbab	0xd2958a5a	0xcb165416
+	0x32f3a97c	0xe502303a	0x16c4eda5	0xa1bcfd1d
+	0xc4f35053	0xfd037f66	0xdeac9fee	0xbfb167b1
+	0x39804db6	0x0bc2011d	0xf56bcd68	0x368cb345
+	0x52fcb352	0xc306c535	0xf6bff09c	0xa429cbf7
+	0x7e504be4	0xd2240214	0xf09ee41f	0xcbcf1fe4
+	0x70f96a85	0x8394bf28	0x3cc19a50	0x49581f96
+	0x58da5ae0	0x94708c48	0x63febeaa	0x4f656940
+	0xa7fd6879	0x65524f66	0x5f7ee0df	0x11d487f9
+	0xb494641e	0x7eb57255	0x5aa208c0	0x5666243a
+	0x7d5970b5	0x71ea69a1	0x67059c9d	0xd3bde5bc
+	0xe952b3fe	0x27bbf258	0x197504f4	0x5da6649d
+	0xecddf4de	0x2d040d3d	0xbc9d3ab6	0xd8cdfb81
+	0xb36ab627	0x7a548111	0xaaeefa4c	0x0e55b263
+	0x4f9da6e6	0x26a137dd	0xdea03395	0x23b87267
+	0x5b3cc98a	0x206de858	0x8d2e5cd2	0xb60f14e6
+	0xfc10356f	0xeecae1d5	0x39783cbe	0x1a1c9a70
+	0xb52c6f05	0x64adf10b	0xe12d9f3b	0xb3fb7cf1
+	0x9051fdea	0xc16ed3bc	0x697199b0	0x08f34342
+	0x2fb2bab6	0x729ed2b8	0x7691088b	0x82bc9cc1
+	0xafce7ac3	0xe167bbb9	0x362e5d43	0x945510ec
+	0xf32dce5e	0x4aec9a82	0xb80520d3	0xd8fcbe40
+	0xf4877350	0xcfdd487e	0x8c9ff8b5	0x84ce70df
+	0xffa6abd3	0xf9d2f273	0x342dbff8	0xa72580e3
+	0x6ffccdc3	0x0c7ccc0f	0x6b24afd4	0x82b71a25
+	0x1ba361f2	0x6ed8a67d	0x243ce000	0xd16b2e19
+	0x86d3c3e6	0xca209063	0xaff0b983	0xf411f71f
+	0x0f2ca724	0xa6fb0fb6	0xfa663640	0xe40fe20e
+	0xf8e2a5cc	0x1a0e8862	0x11de13a4	0xc811e4a7
+	0xfe6fa8e6	0xfefce644	0x8f7fcde9	0x94477c62
+	0xec9b942f	0xfda6b166	0x91330c4d	0xd059d679
+	0x96b0f7a1	0x22df13ce	0x3f36c3e9	0xc814e342
+	0x7b7dce7c	0x1000640a	0x8cbe7a56	0x622fa655
+	0x209d82d7	0x55668514	0x1534f8af	0xc2b7dc1f
+	0xd89da0dc	0x3ddfe751	0x0532dfe4	0xd39c360c
+	0x090f91d6	0x48587117	0x8ee383fe	0xf5ffdee4
+	0xd8bca448	0xd26d6d82	0xe8adcc12	0x8b14b8c1
+	0x7f872f36	0xb8cb0e16	0x76d60c06	0xf62ddbec
+	0x3ec7c151	0xe418a789	0x920a3bf8	0xc5b62e09
+	0x4974ea7e	0x0d8d7962	0x5bbb246a	0x37183d1c
+	0xf25c63dd	0xb15730a5	0x903e3400	0xdab426eb
+	0x0323289f	0x9bc16f49	0x2dfd02a1	0x3ab916a1
+	0xcb6f770a	0x342021b2	0xf9f5c9c0	0x9c8d53a5
+	0x3d53f39b	0x8e693c58	0xebecc732	0xbf30c538
+	0x96648d11	0x60f62751	0x29745559	0x8e365fb3
+	0x7d0b1179	0xea5abbb2	0xe45c4af0	0x53056b1d
+	0xac7b03dd	0x7015c355	0xf17f8dfd	0xe1ace271
+	0x9abacdc0	0x5ccedc75	0x478c717d	0xc01dfdad
+	0x26fb551f	0x73e61f00	0x8bc0b111	0xb6855743
+	0x28690dc2	0xf13b6766	0xc098861c	0x5c0ffa55
+	0x271e7d0c	0x66b47b80	0x9921a158	0xd9c560d0
+	0xb29b6ee7	0x50a9bc97	0xbec4d91e	0xdb2c1fcc
+	0xdf215786	0x1541e380	0x59cae516	0x2342b2ee
+	0x8088cd9b	0x7312579d	0xb17be14a	0xa1638c41
+	0x805c6b18	0xb8a56151	0x56f0a6da	0x96b114d2
+	0x0845ea7c	0x23e8f7eb	0x4e88e7ce	0x84640f2c
+	0xacf8eebe	0x4039725a	0x49bf9982	0xfbcfcbd9
+	0xfbbfb1c1	0x8041659b	0x5b8ee4f3	0x1b6d7a38
+	0xeb634fc4	0xbf818ab6	0x8076c921	0xc50be762
+	0x24c43f4b	0x3252acca	0xa7528630	0x9885b151
+	0x9154b37f	0xfd9d3ab1	0x4f93c117	0x578fba44
+	0xa56851fc	0x9d8083de	0x769f6fb4	0xd89fec27
+	0x747c8071	0xe6b2b747	0x8196e2a8	0x3ed6c699
+	0x8716f1df	0x65325e96	0xfbc715d5	0xb06f9171
+	0x7aa9cbdd	0x84bda56b	0xdeab06ee	0x80432d8b
+	0xd76f0a57	0xe0ed5f9a	0x70f991a2	0xf1a9e557
+	0xcbecbcdd	0xcf0d91fc	0x6751fd67	0x590f206a
+	0xa26d8130	0x1df02179	0x826303ce	0x6cd58190
+	0x1219d005	0x4bb2f3b2	0x0dbd8193	0xd8d8f582
+	0xa5867eed	0x2d6b8ec9	0x5f85ec18	0x7983775a
+	0x214ca0c1	0x9af3febb	0x213d6568	0x2f8e8c43
+	0x92add018	0x6e33e00f	0x6fa6834f	0xc3c2cbbc
+	0x1c65c8c5	0x1827f812	0x868d3a09	0xdac83ade
+	0x57623da5	0x5ff83257	0x0992e621	0x25cc9ca9
+	0x10580130	0xff2ae8fe	0x40a58253	0xffdc24d5
+	0x3e4dbe68	0x291b11f7	0xb3594b9a	0x570c7b6d
+	0x38d31bd4	0x7155ba24	0x84d56490	0xd98842d5
+	0xe037d2f6	0xdd2ba821	0xbeb861d5	0x0fda5758
+	0x5921c665	0x98c7676d	0x8eee487b	0xac0f2411
+	0xb332d321	0xa0816c65	0x76edde5c	0xab868b36
+	0x3f8da4fd	0x516af4e7	0xabf748a8	0xbe7820fc
+	0xbf763827	0xa03a3566	0x8a63e804	0xb4f8f901
+	0x5d262ee9	0xaf905cf5	0x896d0c94	0x5f992cab
+	0x81c2faf9	0xda3c686a	0xb01a06dc	0x45ef0c90
+	0xf2ca525f	0x0e74fe18	0x36ecdb11	0x494125d2
+	0x226b4aab	0x3e92ae29	0x5bb48774	0xc2c2ef90
+	0xa9e77d5a	0x409db546	0x7728f003	0x72229503
+	0x2e8febab	0x8322cfbc	0x5eaf74e9	0x621837f8
+	0xc70668d1	0xb25c1325	0xd741c010	0xf52e3166
+	0x71ef7a87	0x74cc93a4	0x7c25ecf4	0xb8b8e20f
+	0x3658c239	0xbc58fba7	0xf13ec858	0x9271b2a1
+	0x37084dd5	0x6fc92e82	0x44a6abe6	0x92b9238a
+	0x9ad3a57e	0xd75daf92	0x8ea573d6	0x69ce1fb6
+	0xe80df5f2	0xcc1c6ae7	0x6d565a77	0x6981ae63
+	0x18af1922	0x6e8a7af8	0x10716aa0	0xa7da9970
+	0x1abbc7cd	0x114f814a	0x4ebb0c07	0xc8fe6a69
+	0x93d7bc2e	0x0a16181c	0x0379c950	0x4b2e8c18
+	0x670b83f8	0x82a75eda	0x6eb772dd	0x42cfe197
+	0xd91ec29c	0x29fb4812	0xab693ead	0xb2f25a1c
+	0x0b9df6cf	0xb7a1aba2	0x1d7d90bf	0x7de14655
+	0x649965f6	0x11fbe065	0xa54ac5a3	0x418bd3df
+	0x4223c00f	0x7bfcf9ae	0xbd979739	0x6a2ee697
+	0x54e7d9c8	0x73803bdb	0x06654716	0x72225136
+	0xfaef3873	0x0b4b40dd	0xd3b98b57	0xc56cbab5
+	0x32174c47	0x4d4d8c32	0xd6f1bf93	0xeefb6950
+	0xb84ed0da	0x590723d4	0x2d006f09	0xc4bc139c
+	0x55434982	0x8734189f	0x0e314a50	0x94340d09
+	0x021c24a4	0x0b0f022d	0xa61f9025	0x71eb72b6
+	0x744ccea1	0x2030b859	0x78203d74	0x0b8a8389
+	0xd5211777	0x2609edfc	0x6134eede	0xec74584f
+	0x0bdb2d06	0xb1768f76	0x56221895	0xfc49bdae
+	0xbcc6e6ed	0xfeb19c0c	0x18652996	0xaa1a0164
+	0x3ffdcb94	0x2dc1b090	0xb68bf220	0xc33b967d
+	0xc907a1aa	0xa3968cb1	0xb3cc65e5	0x33e2b077
+	0x2bb22904	0xe0fe8fc2	0x4affcc46	0x6b0f0bbc
+	0x5d1bef41	0x2de11c7f	0xb0d864ee	0x6e96d8dd
+	0x59c1c108	0xb2544572	0xab3400af	0x604aefcd
+	0x81be22c3	0x6741e6ca	0x3a93dc1c	0x7b10e639
+	0x0add7a92	0x39fc1df3	0x884f150b	0xd666a96d
+	0x87da0c1a	0xf0f73c15	0xc0c00957	0x011ba61d
+	0xa77e9463	0x96020e4e	0x92416e99	0x881e89c4
+	0x46981327	0x3bc624f4	0x57f226f5	0xac340cd8
+	0x3ce239b2	0xec6b33bc	0xa9123e11	0x70640b6b
+	0xc30f59f0	0x411576fe	0x5ab12c3b	0x3cc20b85
+	0x924b3be2	0xd1fc7a28	0xa4b0cf7a	0x88098404
+	0xbbd331e3	0xff2b6047	0x2a1ab042	0xdf220849
+	0xaf774ae3	0x5a8da79d	0xf18450c8	0x8e6e235f
+	0x1dd3c039	0x1a867ae2	0xe4ccd1f4	0x50dd3f39
+	0x8be186ba	0xc7e30fe2	0x17552d4d	0xffac16e4
+	0x4094bbc4	0xc18a2513	0x650e707f	0x8ecdbba2
+	0xf53e8e7d	0x047dbce2	0x7fc2a89f	0x07628f94
+	0x2a8bfc67	0x0d738727	0x7b5c2fd4	0x2c89d27f
+	0x47f37a64	0xc63debc9	0x15d6c414	0x242c300a
+	0x645d95ab	0x29e1a49d	0xaf77fab1	0x643b4cd5
+	0x3e0f63db	0x4f7cc43a	0x33d6797b	0x497d4332
+	0x7160786f	0xe0c5b75d	0xfb08ecb2	0x26063065
+	0x9835bf7c	0xf5465591	0x63155d2d	0x14babba1
+	0x384a0879	0x460db3b1	0xcd37760b	0xad675a77
+	0xf1dceded	0x69df690a	0x44c6f456	0x87d6a7a4
+	0x4e0d6504	0xf967f55f	0xca9bb20d	0xd5eb41f6
+	0xa9aa9b2a	0xa907387b	0x965b6f23	0xdcd47eb5
+	0x43b5b1a0	0xec876728	0xee7339e8	0x10c5ee16
+	0x1bd8c0bb	0x7235ae07	0x063e3564	0x388d0bb5
+	0x80f9a9f6	0xaf96f714	0x6895c899	0x00ad21bd
+	0xee67961b	0x873781a9	0x22cf435a	0xee90cf3e
+	0xc9a4fadd	0x9bc1af4c	0x35c0e803	0x211ce71a
+	0xb9af86bb	0x97828ab5	0x9dbd002a	0x1cc981c7
+	0xefb36876	0xea739a75	0x5d5abcc1	0xd42260f2
+	0x95083e0a	0x31fb0b51	0xf243ab8f	0x628b1913
+	0xe74eb210	0x620b7d9f	0xc81666d2	0xc8fd1ce1
+	0xf054bd9e	0x78ba7618	0xe1df4e38	0x5e381b3a
+	0xcc68da1b	0xb3ce70ac	0x7ecda229	0xf8778140
+	0xae823fa1	0x12af1708	0xc9373879	0x1e687d29
+	0x96062069	0xf1bfde2b	0x999ff6c0	0x8cbeddf0
+	0xc825a2bb	0x78106bbb	0x87a964fc	0xb358ec2f
+	0x4d959300	0x0fe9706a	0xabb1d003	0x72b65294
+	0x43816b1f	0x6c83b958	0x5549567c	0xb474aa55
+	0x98851640	0x751a670f	0x25900026	0x2ab174e3
+	0x1952c3dd	0x38b47c29	0x32c0af52	0x460c8fad
+	0x85a1004e	0x8cbddcd7	0x66578310	0x4904dcfb
+	0x04b7a746	0x00c91fb7	0xb1ab2edb	0xd0178ae2
+	0xc4b8b57e	0x981d4753	0xfdd8939a	0xa8a05055
+	0x47c8c30e	0x0fab4f6b	0x6ea54079	0x23dc4151
+	0xc23e83aa	0x2ed2ce8a	0xff95b763	0x08df1d51
+	0xd16d104e	0x0fa3ee3b	0xdcfe8541	0xa0622490
+	0x085e5c0f	0xd9bc007b	0x24794e89	0xce341d16
+	0xf090a98c	0x317150a2	0xcc036257	0x3296722d
+	0x9c8d4f58	0x7ca5f53b	0xb0e4f9d4	0x1f178bbe
+	0xc0dcde7c	0x18551596	0x0507b8e2	0x3c40a8ca
+	0xc632f82b	0x5d1965f9	0x92a00465	0x13a8ca32
+	0xc0b6756f	0x669d706c	0x58056b22	0xaa25fd37
+	0x128b731c	0xb141ed31	0x0a8d3ddf	0x48b63bd1
+	0xd24c5c4e	0x0ccd96b8	0x4b1ff726	0x309be62b
+	0x26002e68	0x436f2bd0	0xacb62068	0xce098f50
+	0x330e6160	0x434da66d	0xce14054a	0x0a877e41
+	0x705eb2fb	0x8433fc7e	0xc1bd475b	0xb550de6d
+	0xf4faf808	0x9f9b6ebe	0x0ff98ef7	0xace2766f
+	0x01cc9606	0xd9654327	0x3544cf5b	0xbffbcd80
+	0xb4a5948f	0xcded4d04	0x69ef5a24	0xf5ae46de
+	0xe2139499	0x549f82bf	0x2cdfc6b7	0x5fdd2462
+	0x63c68a37	0x8bce0d04	0x9c66ae30	0x9fd94951
+	0x5774366d	0xd671675a	0x5582f253	0x436c5b6b
+	0xfc151e77	0x1974df45	0x5ea9eac2	0x30689b8a
+	0x9806681a	0xb74d3ec8	0x4f207181	0x668b4951
+	0xb06514b2	0xeccffed1	0x16188ff2	0x5914d385
+	0xed4b7023	0xfb0640e8	0x179adcda	0x6e806687
+	0xb4f0ac07	0x35813615	0x143e66b4	0x1b012a50
+	0x384f31c5	0x1500dbca	0x06e47afe	0xa8a17374
+	0x9d0f5c57	0x4574db82	0x91b3680e	0x794683a7
+	0x30c25d5d	0xf8748c08	0x2e601dfc	0x553152f7
+	0xec5d489a	0x4bd37616	0xdc04dc7b	0xf0a35ba2
+	0xb36975db	0xbfe6f98a	0x6d744996	0x5507380b
+	0x4191e01a	0x0092c384	0xcf3a4388	0x6b0e89c7
+	0xded7b820	0x1fbd6bba	0x3af210b1	0xfc4a608e
+	0xa920eb22	0x22db2d65	0x7d6f0447	0x090f3679
+	0xc4c759cd	0x9758aac6	0xa63251a9	0x47b7a974
+	0x65421071	0xdca8495e	0x96f879d7	0x1d22ea6f
+	0x46dd72ba	0xe0c59ccc	0x15737309	0x6d945f11
+	0xbcb15c8a	0xb11ef0b9	0xe2072633	0xccbd61dc
+	0xfcb51c44	0xd2315c65	0x3087a6f8	0x5609ee34
+	0x94c7f951	0x0a057b31	0x6e6f2733	0x179facec
+	0x36c005b9	0x60184919	0x50b3db1f	0x7a827d7f
+	0x88755ecc	0x3fb0d6c3	0x63b150d4	0xe2ec3004
+	0xe0ee30f1	0x118d7040	0x2f4689e7	0xa78be0be
+	0x3c9bb853	0x75c326cc	0x84097407	0xb0107b5e
+	0x83a56a91	0x14e60445	0x0fa72553	0x1385e6ce
+	0x9b8bbdcd	0xe6aa6a9b	0xc2072ccc	0xee916592
+	0xe44082e1	0x43dbf6d8	0x09f821fc	0xdc84b023
+	0x0e6a518b	0x945fb180	0x185d0841	0x9ece88f8
+	0x844558c2	0xed85f422	0xeceb983c	0x6db16826
+	0x7612b243	0xee3bf226	0xb8eebb7b	0x22e16615
+	0xc892bb7a	0xdc475a47	0xae390e93	0xe00baa1b
+	0x725fca23	0xbb868b3a	0x17c62a69	0xeccd3731
+	0xbe1a4223	0x05c8fd7e	0xa8354afa	0xbbb09f8c
+	0x31a77e83	0x01f17a68	0x5f37c847	0xa0fdd7db
+	0x9f8da870	0x98f02167	0x1e966884	0x00e19b81
+	0x50c91add	0x6aba2a55	0x60be9575	0x3da40b37
+	0xde13ff4d	0x5b7a79ec	0x4700ffd9	0xfee5ea61
+	0xaf4d1d1e	0xfccb6f04	0xcf5076d2	0x48c4c98a
+	0xd6a8915e	0xe4a58522	0x6bf3a6a9	0x4e7c2f15
+	0xcd7e8d2f	0x843b56b1	0xa35f1a5d	0x1ca226dc
+	0x917fb163	0x44751f0a	0xd96fa8aa	0x5028dccc
+	0x7792dd96	0x2a9d749d	0xe48385fb	0xde111e91
+	0x805e6581	0x3d9b9fad	0x5b750544	0x03785b71
+	0x9b583214	0x80022658	0xcf1f3730	0xa1be7be7
+	0x6c1e26f2	0x26de584b	0xb4fc8e35	0x072b520b
+	0x55db3ac9	0x81e9d490	0x4b5ea53e	0xd5628e00
+	0x71bfcac3	0x79956bbf	0x275fab80	0x2ad497ed
+	0x423854b2	0x686451ad	0xfd59d64e	0x9f2049d7
+	0xcb0f8f32	0x74d7545d	0x4f9c1df8	0x6fbf0afa
+	0x7ef06915	0xc5117549	0xf20088b4	0x731a5ccf
+	0xe78bbe74	0xdcb4996e	0x7062a6f1	0xa624b59a
+	0x7b2d5e41	0xc1065234	0xa7c32078	0x367e7134
+	0x86f55f58	0x3084ee83	0x0c599d1f	0x69380e2e
+	0xe59482b3	0x7096432e	0x81124388	0x5be8d01e
+	0xeb25ec24	0x8b47e9ad	0x432216fd	0xdc496dea
+	0xcb05fefe	0xe76eb9ab	0x8ed568d2	0xfa963d68
+	0x70ed6f4e	0xb2b88d58	0x15fc42bb	0xe992ec48
+	0x359856b3	0x4a0f7741	0x3f0b6eca	0x07c16950
+	0xcb9dae59	0x209570c2	0xf196555d	0xbf7c0a0f
+	0x4a814210	0xf8f206c7	0x8bbb0763	0x360fa596
+	0x13d46195	0x901170e8	0x6dc2e376	0xbfa00989
+	0xd12cab90	0xf4f4699d	0xbc88b362	0x4827dbd5
+	0x7cde5cf5	0xe45dff5e	0x2d661b05	0x8902d99e
+	0x6c9f3584	0x0db3f864	0x1132773f	0x3e944120
+	0x27058ae1	0xef978864	0xe58eff42	0x020ae503
+	0x77fe075b	0x9c577e08	0x210b42b9	0xcb8160c0
+	0x09f99f36	0x6a0b6bee	0x6f18b0ef	0x5452ee3f
+	0x6c8c4a4d	0x480cb803	0x892f3973	0x066dbb63
+	0xf7f845c8	0x7ceeee7e	0x7c26c5ce	0xec89119a
+	0xc64bdc20	0xf46e4324	0xff34c833	0x555b4b3c
+	0x23ff2701	0x52360759	0xf60acad8	0x241ccb7b
+	0x29e14901	0xcc068e2b	0xedd0ee02	0xc33a425d
+	0x7d889b28	0x88577f8d	0xaaf614b1	0x8e8c8eb5
+	0x81a363f8	0x29f5bcc6	0x08aeb8e9	0x6f9ee222
+	0x1c50045b	0x792c9434	0x62bc2601	0xc9289175
+	0x374fc38c	0xbae91a86	0x3268e89b	0x5b008f10
+	0x0ea6b759	0x9d43ce10	0x09b30dd2	0x643e2b94
+	0x5c19bafb	0x29515176	0x56a81f95	0x60a80534
+	0x22fa0a73	0x1259cf8d	0x323fa5b3	0x6322f1d0
+	0x30581c47	0x50458048	0xd711c1b6	0x4a34236e
+	0xb60a2e40	0x58df96c9	0x947b90d7	0xd327d664
+	0x5fe528db	0xf6d9c575	0xb0a251b9	0xed961301
+	0x2fee3cf9	0xb687e226	0x78fc46c2	0x29e9fef4
+	0x84bff086	0xd0482ed1	0x018996f1	0xb8b9cdf8
+	0x20885e68	0xa6f848e2	0xfddabc3e	0x5c9a7f67
+	0x7cbc3e40	0x5197ebe2	0x41a15775	0x8024fd2a
+	0x7864106f	0x7cfaf482	0x27798720	0x4956355f
+	0x30f7195e	0x6ea09dd6	0x6f2b5f3c	0xf38df38e
+	0xcae7e8cb	0xf8a80b0b	0xbeb227ba	0xbbfa2428
+	0xbbba3ab6	0xbf83edbc	0x2cdcaa9b	0x2b0841a7
+	0x79d52e5e	0x40260460	0xb27709be	0x07e3bf6a
+	0xbdccc2b9	0x369d0069	0x9d745e50	0xff251486
+	0x1e14957f	0xf7253467	0x9a31eeb9	0x4d77108a
+	0x44fefc47	0xd02d4082	0x232e3fc1	0xce39396b
+	0xd7a13714	0x2bd57e7e	0x00876803	0xee73377e
+	0x78bb6240	0x2ae63c46	0x11e009d2	0x922539cd
+	0xf3bef05a	0xf0c664c3	0x6e132a0b	0xb0c5bddd
+	0x40c66494	0xd7d0d02a	0xa73110d0	0x4b409d78
+	0x6f49bf88	0xcfc9d22e	0x4836da89	0xde5a80be
+	0xb9c8bdb3	0xe99b2e9d	0xf1b05e68	0x8ab599fc
+	0x22675035	0x3c8480c0	0xfa3cd457	0xba617098
+	0x422eca1c	0x0cdc0d01	0x4779b95e	0xccfa0bfa
+	0xd22674a4	0x76462be6	0x3015ab3b	0x7891688e
+	0x1c83bf8b	0xaa55839a	0x7a71a83f	0xad451c1b
+	0xf8b8bf06	0xc75a91be	0xcac50366	0x87e365ae
+	0x9013ac11	0xe9cec5a5	0xef4d88f5	0x15c27162
+	0x3dcaf8ae	0xe023891b	0x7b6f1706	0x2f1198e4
+	0x048e34ba	0xb647b5e8	0xa1826caa	0xed3bc134
+	0x43b14d28	0xf0c49b54	0x1a6362d4	0xc77fa378
+	0x3bb12e79	0xcba4cd2b	0x620f2476	0x7729add6
+	0x9876c439	0x5f7d8795	0x858f7ac8	0x68b94589
+	0x1321d70b	0x5353a2fc	0x912a5ea4	0x390cf0f5
+	0x37320473	0x51b3cacf	0xe45046d2	0x9188dcc5
+	0xb3713b54	0xc9b936e3	0xe9f24574	0x5977a68c
+	0xc23c56bd	0xcfc39ca9	0xc891b8d0	0x3683ef22
+	0xc1ce304a	0x3ebf1ce1	0x52cd1cc0	0x3777d973
+	0xde614072	0xf2efe226	0xbe1f9f9b	0x92a1896b
+	0x9ca62763	0xcf5703be	0xa6d9c56a	0x185260d6
+	0xd9e3b86f	0x5c47180b	0x71a7a219	0xe9974375
+	0xf22af4d3	0xfbc92962	0x968c3fe4	0xc584b60e
+	0xb9abee26	0x7e9737d8	0x5947da83	0x2f8ccad0
+	0x7b4ee942	0x51ad62dc	0xf517400c	0xe2bf9e37
+	0x63057e05	0xe1bfabf8	0xbf118805	0xc038de9c
+	0x7aa57b7b	0x05584eff	0xb15ea286	0x26c6a6c0
+	0x8e1392e8	0x7dbf22e1	0x3546f5bd	0x0f84ed9b
+	0x0b01da4d	0x6dc47417	0xadc6f687	0x4160c045
+	0xdc26765f	0x63b70c6e	0x8f177107	0x6a5f13cd
+	0xb56fce56	0x5d1f5ed1	0x62f6a18e	0xf7235691
+	0x222fa999	0xd48b1435	0xe597d406	0x8dacf828
+	0x694ecd8c	0xe5283c02	0x60bcdcd3	0xfb9eb384
+	0x9895492c	0xd38172dd	0xe7b6dff6	0x0ead5894
+	0x910e2675	0x97d9ee09	0x270b2d8a	0xd03e25e0
+	0x9e7bbb69	0x57ab1d31	0xf2e7a13d	0x9c8e5baf
+	0x65fa03f4	0xc66bcbfc	0xf2d8bfe1	0x23059412
+	0xa3ae7654	0x3a4734a3	0x32c0a8d3	0x4e007b8a
+	0x5ce30660	0xbd10c57c	0x5365f540	0xeaed3002
+	0xc377d84d	0x87097a59	0x929edec9	0x5878368b
+	0xbd450478	0xc3fab275	0x128fdced	0xb706fbb5
+	0x146f1d41	0x86782651	0xa530ca29	0xa3e1b6be
+	0x25390048	0x572b4a05	0x8c9b4c90	0xb05428cd
+	0x33fabab5	0xd16e513e	0x1d6cc812	0x4d80a6ed
+	0xd6a5a07e	0xc0ee4c19	0x544b75d1	0x3f887360
+	0xb2f46d1d	0x21609cbd	0xe340211d	0xe9202fb6
+	0x3023b005	0x3341ead9	0x76c99537	0xc9d76547
+	0xfb736c3f	0xf6385346	0x93fe2a05	0x92de6df5
+	0x7793acd1	0x68249b3e	0xc22cae3b	0x668988e0
+	0xdc1ea28c	0x7ef72b95	0x974098f9	0xb214701c
+	0xc2de7d98	0xeb1d443e	0x5975f0ec	0x21d67037
+	0x721e8e99	0x42105562	0x74b1e821	0x20193b2c
+	0x743a7bb3	0x24643c9c	0x240b331c	0xdf125e2e
+	0xcb4b0205	0x19edb174	0x505eb85c	0x1830bf22
+	0x6bf7a528	0x86a7281d	0xfee3488d	0x6c26f4ab
+	0xbff4ce7a	0xff7cfaf1	0x5df6fd66	0x523f0802
+	0xf8a87595	0x463b5c19	0x72c564fd	0x2e4797d6
+	0x1f04a1af	0x0be96baf	0x44552094	0x2a158f50
+	0x83dac587	0xad4c881d	0x3178e710	0xe938d1be
+	0xab715a65	0xc34b451e	0x1942832e	0x91557ecb
+	0xdaf0606d	0xa64623d9	0x84e11fbb	0xa9c9d11b
+	0x577a15b1	0xd49a2f23	0x6f204e0b	0x0a6e6a2f
+	0xdaf13637	0x6b4ef557	0xdcaac9a3	0xad97c404
+	0x8471691a	0x50ca3cf5	0xde57c446	0x70aa02f1
+	0x84baa6de	0x0232bc79	0xa06427af	0xd2ce56be
+	0x5da13949	0x254f5f4c	0x3fc3fd02	0x00b5f8eb
+	0x54a0d4b8	0x5e3ec3b1	0xc6718376	0x5acce6d8
+	0x614c56e0	0x89a6b00e	0x6cb4e087	0xa9822fe9
+	0xdea290c6	0xb294582f	0x36f9640e	0x30d0afc4
+	0xef7d75b9	0xfd9aae2d	0xd6729573	0xac442321
+	0x158224fc	0xfd6632df	0x10cebf98	0xc3864dd8
+	0x31577c58	0x49e71f9c	0xb96d876c	0xd867604e
+	0xba74c3f0	0xad69752f	0x716eb51a	0x469d9d03
+	0xda4b2e16	0x9e80a908	0x9bcb18e8	0x2f1c595a
+	0xe823ecfa	0xdfd5badc	0xe460e9e0	0xae418438
+	0x457811b4	0x29df713a	0xd90b0d29	0x415ba2de
+	0xa0af6489	0x4922a50e	0x2efa0b0b	0x9394e4cc
+	0x0ef8f59b	0x0f851711	0xa4670f3b	0xcc6bbfc6
+	0xae194dfe	0x78e51752	0x4c65a2d2	0x1b0741cd
+	0xc9f401c0	0x4a678062	0x290d2bc5	0x1a4279c4
+	0xb5f9160f	0x40ef7c77	0xa9bcfba9	0xaec75f21
+	0x53d6258e	0x8587eb74	0x0721d492	0x2c6a6e2d
+	0x8e6cb70e	0xa6bee309	0x6faf5706	0xf8eee239
+	0x52c85943	0x8c198893	0x3db37858	0x557fbf2e
+	0x92f1a0e5	0xbd279594	0x46d65132	0x90a2c32a
+	0xd11db660	0xc73b3922	0x9d1075ff	0xdb80a1cb
+	0x54158743	0x39694d0a	0x4a0ddc7c	0x721f9dc9
+	0x04b1b044	0x3bb40aed	0x6be7a88a	0x429a3b09
+	0xa6e9dfa8	0xba412f0c	0x354f08d2	0xa4569516
+	0x928cca34	0x398b1a99	0xb7e80291	0xe67d7b71
+	0xa6582bf0	0x556ebb23	0xdc6d9f6a	0x11b3b753
+	0xbdf31ae5	0xd3399560	0x6148cec8	0x5188689e
+	0xde18f46b	0x3da414ad	0x4c44ad29	0x68582541
+	0x75c8b1e6	0x7ba572de	0xd753ed20	0x4a9c4578
+	0xf1c9159d	0xcfd9da31	0x46799fbe	0x1aee4426
+	0xdcdf7b57	0x327db61b	0xa160ea1c	0x84a01fc2
+	0xbe0aa020	0x5963688b	0x24f32751	0x885b4177
+	0x26cde88c	0x39e6df90	0x1c7fee90	0x882a5c0c
+	0x56f1f2e0	0x10bb9f52	0x4f0502aa	0xeae6e5b9
+	0x65e7ee25	0x8ed230ac	0x38b5e02c	0x5f5311f7
+	0x929491c0	0xdd923e62	0x5bc6166e	0xa3c89f4e
+	0x5844fb12	0x0c40f02f	0xdda07582	0x8ca1b803
+	0x9398b0d0	0x4dba17f9	0xb9879c85	0x26956147
+	0x3c26a130	0x58cdc52b	0x21fa4801	0x9d965ce6
+	0xb9942dac	0xd83d1518	0x36e630dc	0x50bb2822
+	0xcd472a65	0x6feee2f4	0x4853b680	0x7f54945f
+	0xa522c561	0x28134f6a	0x89b46cb2	0x4fe0047e
+	0xad602b28	0x4942494f	0x1536ea37	0x40ea6278
+	0x5020bdb1	0xad3c9f7e	0x1356d0ce	0x411700c8
+	0x1ba61954	0x65dece8c	0xb788efb9	0x26efcd5e
+	0x9833fa21	0xea0052b8	0x119a994f	0xa71b168b
+	0x164a96e0	0x0bd1b4e9	0xaae1e562	0xb550f48c
+	0x3a3b55e1	0x4d921246	0xcb28af65	0xdd2388ff
+	0xa63988c3	0x7dfa5a8b	0xc7c44102	0xc75e9f3a
+	0x5e4305db	0xacb34d1c	0x9b50976b	0xad3f6379
+	0x6cd20ee3	0xba806f21	0xcd0fcf4a	0x18a55973
+	0xbafe5266	0x03ee9b8c	0xa35fbfde	0x7f2eb71b
+	0x23d9aa11	0x0e183c35	0xefb0ae3e	0xc6093786
+	0x5b380af5	0x64838229	0x3bd69926	0xe9758e1d
+	0xde439e4a	0x0cbc4bdd	0xda5858e8	0xbe8afc07
+	0x676379e1	0xccc4c628	0x763e3b38	0xb4823c67
+	0x9f4aa538	0xd8d33f50	0x41291e48	0xaed28ade
+	0x6c72eea8	0xa751f4e8	0x3a75dba2	0x5073e3bd
+	0xf10b4756	0xdf46ab98	0x9ad689f1	0xc2ba74a4
+	0xf2ce9419	0x4cf9732e	0x75cf58ca	0x249e3c52
+	0x95d10a93	0x51120008	0x7438d467	0x0a5e7f2d
+	0xb7a44e46	0xe31e5dee	0x26e2ed14	0x8f16a7d2
+	0xfcda431c	0xab32ada3	0x3a863c94	0x5fe91346
+	0x2a92c590	0xb8c17e6b	0xcaf753fe	0x50283647
+	0x533c8f3c	0x1233e1c1	0x7a5b2eb0	0x79b4ba22
+	0x3164670c	0x201c500d	0xafeac6bf	0x2fbb0884
+	0x915de3b0	0xbf733b7f	0xc45d1a42	0xa3b86d4a
+	0x333ef605	0x6348522a	0xd28d1d19	0xa2cad790
+	0xf8ad449c	0x05aacdcf	0x64500018	0xb1d8cb18
+	0x9e4a2ecc	0x091282c7	0xfd64bcf8	0xe1e7c24d
+	0xfcd0f386	0x0c9faa0e	0xa82f265c	0x83cafc3e
+	0xcad43563	0xc110837c	0x2a2da74f	0xbd98e00b
+	0x5c24553d	0x41c75caa	0xe75cb110	0xa004b946
+	0xd4daa77c	0x88d07273	0x0c75c7eb	0xaf05657a
+	0xbe1f8336	0x122a7acc	0xe0e5c29d	0xd5896217
+	0xfb2f909a	0xa74b6458	0xb33a1a38	0x815f7832
+	0x9584b271	0x9a3bb26e	0x39aa6d36	0x2fba41db
+	0x133797be	0x9993699e	0xdb50268d	0xccd54ff0
+	0xb7a33011	0x71db612b	0xef9a4429	0x7217f1d0
+	0x0ee420ba	0x1f7eb025	0x26572853	0x72712e17
+	0x5bd7be37	0x74b2288e	0x3ffd1f1f	0xed566562
+	0x744f4159	0xdbedb36b	0x69e25131	0x604ccb70
+	0x50d83542	0xe4704ddb	0xdc5144aa	0x33467434
+	0x1c7c4f2b	0xac774e8e	0xce9c4d1b	0xa0e3c7f7
+	0xffbecc1c	0xa1c25fb2	0x0e9f6039	0xbe9ed6d0
+	0xf958fb6a	0xaec3fba8	0x2944e767	0x77dc717e
+	0x06e9fe1d	0xaf3a4928	0x7d4f3f29	0xead3972b
+	0x65670bc4	0xd058cc70	0x9fb58c45	0xf5f08926
+	0x9aed1955	0xb1a5d161	0x14b5aa11	0x66e14cee
+	0x28d7aae3	0xae45fcec	0x92dc7dc3	0xe9eda97f
+	0xbee84f22	0xea6f71ac	0x6347c2b8	0xe919afff
+	0x2c409d7c	0xa9800c52	0xd8033a17	0xc3794565
+	0xb5311fe8	0x80d8a030	0xf9cf179a	0x508ea242
+	0x4464cd33	0x91da91a8	0x6c0806cd	0xb5473d09
+	0x0a0b99b3	0xdaf528eb	0xca1e99e7	0x064055ef
+	0xc2dce623	0x0b4c15ac	0x23c13327	0x3f9fc266
+	0x335d9c40	0xaca940c2	0xc18c0797	0xd5027a07
+	0xb0a4d322	0x2e601275	0x6cc88888	0x658eaf8d
+	0x509e2247	0xbae254d6	0xf097f138	0xa163751e
+	0x19558f7c	0xb66f0cd4	0x87b1d966	0x81dd2cad
+	0xf0c25e6d	0xb8e72dd1	0x00f15f42	0x6d2c1c68
+	0x43c7e436	0x68eedad4	0xc2686b38	0x6ff30211
+	0x197c7734	0x905b8602	0x6ab9d204	0x0d16385c
+	0xb1cb5e16	0x8249a5c4	0x29d1ce0e	0x779f7b63
+	0x63042725	0x12ce98e3	0x11282058	0xca3a9eb2
+	0xdb8294e7	0x423e41ac	0xc3ab2774	0xca658d6d
+	0x519f8896	0xaf6010f0	0xd57a94aa	0xcc17df91
+	0x7d25cf8b	0x041e6835	0xa056d9e0	0xf90f3964
+	0x7f99ae59	0xd80125d7	0x9961d6e5	0x41b3da06
+	0x65c254e4	0x787d2c61	0x16aafb02	0x157ab4a8
+	0xdee3674a	0x1ed1b601	0x2e36dae9	0xad57ad38
+	0xaaf25b15	0xd3c37a01	0x68ca9eba	0x2a1bc480
+	0xba157917	0xc00017c0	0x190bd74a	0xd6c6c1cd
+	0x4efd4f71	0x388ed702	0xc8812950	0xd0019ca4
+	0xd44cc835	0xd838fd6a	0x1432ce88	0xce98d932
+	0xaea21cf4	0x54a44cdf	0xdb4dc5ad	0x1d23a7ae
+	0x5ae126ad	0x100dcb50	0xa9727413	0xcf1c61cc
+	0x72f9d2f8	0x4d32d201	0xe27586a8	0x0a1cc932
+	0x21858469	0xf1cda3f2	0x59703f35	0xbd81f9f4
+	0xad6ac9cc	0x25665703	0x1212d5cc	0x98a243d3
+	0x8f47e113	0xd98feef4	0x3c93e832	0xfd67097a
+	0x0c73fea5	0x6132ec59	0x1dc9bdb7	0x791f79eb
+	0x84d83574	0xbd5817e6	0x7d5a0f8d	0x18482a08
+	0x53ac8e4f	0xadd3378f	0xd48540ac	0x4082f5d2
+	0x3ff5badc	0x24855b3d	0x7bb948f8	0x72637822
+	0x0687e93b	0x61290b4b	0xd9f20b3f	0xcc0e5beb
+	0x141ca01f	0xecd1337b	0x8576ec65	0xb6f825a2
+	0x8b84e8b6	0x5bac53f1	0xd4edd06a	0x76ae712b
+	0xdc00a887	0x798c2ee1	0xe74a5ab5	0x1539fa68
+	0xa30817da	0x06f7c53a	0x1930c59d	0xd4232359
+	0x0dfb1427	0x58d7180b	0x53bf57f9	0x5f001d08
+	0xd08128ed	0x3208b7be	0x5c2aba8c	0x0abbd0d0
+	0x424f2041	0x7982f731	0x010ec811	0xa3489c82
+	0x71ffdfa7	0xda0ed41f	0x8a9e806b	0xfa9bddcb
+	0x7a9e1a41	0x53c7603f	0x9e3df28d	0xd06dd100
+	0x2cc64f4a	0x0dfdccf2	0xb4eb9101	0xf56d506d
+	0xdaeed218	0x45523a16	0x4d6d68ba	0xff9a8f72
+	0x5358b2f1	0x2511a591	0x9ea2c2fb	0x08cafc7d
+	0x7ed34bb1	0x0cf2301e	0x62b6c05d	0xc05095ec
+	0x52128c55	0x030576af	0xef5f37a5	0xdf5ae47a
+	0x39e55496	0xb2c2129e	0xb2d67d77	0xc5adf049
+	0x15a1cb4f	0x981948e5	0x7d18acc0	0xec7abb43
+	0x23f7e366	0xa919a355	0x23872683	0xb7b6d84b
+	0x4767dab1	0xd133feb1	0x2e5536cd	0x587683d4
+	0xa181575c	0x4329e640	0x1244ae40	0x5be82f66
+	0x4b28dc4b	0x4106c9a9	0x517fad7e	0x9e334ca8
+	0x3c3ba741	0xe902a475	0x91d046a8	0x31361f96
+	0x911b83bc	0x6607fac7	0xdfbc6390	0x7213aab0
+	0x8ca8a47a	0x4f3d1f3a	0x3ee76c84	0x22bac3f0
+	0x475f3cab	0x05d05569	0x92b3f912	0xc632a733
+	0xd79b7448	0x595b82fa	0x6013b96e	0x6d03b5eb
+	0xe37045fb	0x6e4add26	0x11f116da	0x4ac8bd3b
+	0xacb5f8a9	0x8fb943d6	0xa9ac31c7	0xf1ba9752
+	0x43a6b29a	0xf123766f	0x536fcc32	0xcf8168ad
+	0xd8fb1e4d	0xb9562fa5	0xfe6d8dea	0xd31ab16c
+	0xf7dfc381	0xb70f11cb	0x371c6688	0xac3fccee
+	0xf130a51b	0xc5b8cad7	0x0cb13762	0x64ae00f2
+	0x45cfad12	0x753d6a4a	0xc6f69472	0x695fba60
+	0x49d1f754	0x9db947f2	0x2364ae20	0x197492e4
+	0xc5b9562e	0x34963cec	0xdc26402a	0xa1c88d01
+	0x58e27195	0x9d60f5c4	0x3e200a43	0x7e9827f2
+	0x0a4feee5	0xd401e139	0x17352152	0xd509564a
+	0x4b3142ed	0xef7567fd	0x9a619dbf	0x56ec2cb7
+	0xc64bb290	0x3d69fd89	0x897325a1	0x74e2cb7c
+	0xf270fdac	0x2beb6a4f	0x5b60de30	0x49df7517
+	0x294966cf	0x87f5f667	0x4a9e1f6a	0xabc332c3
+	0xfaf358aa	0x5baa6cfb	0x36b99bfa	0x40259687
+	0x584539e2	0x2710ce99	0xec1959aa	0x642c8413
+	0xfc005d36	0x2b2e6245	0x0012d041	0x09f6b626
+	0x70fe9e2b	0x3cf30c5c	0x69d0a3ed	0xfe621601
+	0xb6fa9267	0xe9b507dc	0x49f35866	0x4b97647a
+	0x9e721adb	0x89e6e8d6	0x407a2f49	0xd977cbaa
+	0xd9359f5d	0x7b69702d	0x22d6e818	0x57eaa5a3
+	0xdd5063b0	0x4d7d2312	0x7a865203	0xb7f0905f
+	0xdd2c2b87	0x7215803c	0x1abe5307	0x2926f38b
+	0xf6b0cacc	0x96f50647	0xb612feb7	0x6915bfcc
+	0x058b5cb0	0xc39e47d5	0x7513abdd	0x9e43972a
+	0x1e55f640	0x896db1c5	0xd9382d2c	0xa52c1f99
+	0x8afaf5cf	0x36500aa3	0x2e65fa1a	0xbb40d668
+	0x81188e3f	0x143fba69	0x3f61fc90	0x438d759c
+	0x893bb96a	0x069f349f	0xffdc43c7	0x6ebfa943
+	0x671b4751	0x629cec23	0xe717fb9c	0x53fadc0a
+	0xddc1e212	0xb99788ba	0x78378cf8	0x2ed91106
+	0xec1de376	0x98d86b3a	0x312a190f	0x0208a0da
+	0x6dcb469f	0xe6407c6b	0x1c7fea86	0x83841afa
+	0xa9caaffe	0x86e3fd0a	0x918af9b0	0x0fabdf39
+	0xdd9fc8f7	0xf9ddd98f	0x3dd0acce	0x2064360b
+	0x29006620	0x5d7733c2	0x682c4093	0xf038a8b4
+	0x3a688845	0xf9d0b9d2	0x27f51a57	0xb63b063c
+	0x533b082b	0x7f0d0dd1	0x7abdb018	0xea6f6176
+	0x13394ac6	0x825339bb	0x1835fd8d	0xaa46df84
+	0x0751fe4b	0xbc9fb7c7	0x233873ff	0xca200e1c
+	0x668fd5a5	0xda059135	0x2baf8828	0x7a2efc0e
+	0x7c63d98c	0xe71ea373	0x0f218e88	0xa031f88f
+	0xf32bccf3	0xf15eadad	0x6df44be6	0xb2536e4b
+	0x2903a9aa	0x42ef8689	0x444432f2	0xd27a6c4c
+	0x0992a32e	0xaf6e65d2	0xcbefdf23	0xe602151e
+	0x21beace6	0xd9b992b2	0xe43286cb	0xdb315c09
+	0x0de7672d	0x9d518ff0	0x75c4e9a0	0x64b2f70a
+	0x9deb697d	0x5bcf59b8	0x2e4b9a8a	0xd9294b49
+	0x3fee760e	0xfba8fec6	0x1c140305	0xe400487f
+	0xc4cd4a38	0x14e6f1c6	0xdf98e7f8	0xfa6c4992
+	0x62908c82	0x37393196	0xc02464b8	0x4b119742
+	0x83e5e79d	0x15ddd908	0xf75d1820	0x363025b9
+	0xd9e1a04b	0x9e110da7	0xd8caf954	0x30f62bc6
+	0x875fd2b7	0x8b67bc8e	0xd5c77d4c	0x1a8ce00a
+	0x7cfb14dd	0x3a39fd65	0xaecc2b5f	0xb017dbb5
+	0x6a57b4f3	0xa27b6509	0xcdb06076	0x000d6366
+	0x66e4f311	0xf22e25d7	0xf91d9bc5	0x5f9d3a05
+	0x3b37c96c	0xb0596f50	0x53c24ede	0xb620106a
+	0x5e675314	0xd98d5b02	0x75261f6e	0x5610c20f
+	0xedcbe43f	0xbe85b8c2	0x16f7ffb4	0x55eb91fc
+	0x2605ab1b	0x5ad3b426	0x3658d764	0x639c0560
+	0x987249ed	0xdc470fa2	0x0d112f6e	0xd8ab77f7
+	0xaed9455f	0xd9f6a341	0xb9b21249	0x3ff2b69f
+	0x37ad61d4	0xdd6a089f	0x609233f7	0x46a923f4
+	0xe5c23e8b	0x6aff8687	0x5e8ece1e	0xc65e1e4f
+	0xfb96cf51	0x9b697cce	0xb08e02e2	0xf874e0e9
+	0xbc983fa6	0x870375e3	0xc88bcd2b	0xc6bb19ae
+	0xaa0c99e3	0xb301ab7f	0x024ba529	0x4449828a
+	0xd226454a	0x0a610f3a	0xf302a0f4	0x021a3cc2
+	0xa9e4b6ea	0x0b690b92	0x3379c01c	0x36265ea4
+	0x29fbc8a3	0xe6279573	0x3cdb8a1e	0x005b5332
+	0xbab71a8e	0x9677db73	0xa8a6d6ea	0xf0afbd3d
+	0x576fbee6	0x49a54473	0xfa7c6e95	0xcb914daf
+	0x58266856	0xa6b53a63	0x7136515a	0x2a3da411
+	0xb1c994e0	0xbdaecd7b	0x5b436ff8	0x6334ec5f
+	0x0172b5d2	0x57acd652	0xca4efacd	0x87e7d313
+	0x78ac87c8	0xaf7602aa	0x3769ff6e	0x86d39747
+	0xd32a7aa7	0x840cb30c	0x3e7da9b1	0x3c905b44
+	0x90290dd7	0xebc85f3e	0x32693a53	0xc7140058
+	0x6ca5cf6c	0xdabfbc3b	0x3d559486	0xe5ce93b9
+	0x8d3c428a	0x9d18b8ee	0x404f58d3	0x151b4a78
+	0x2f393e9e	0x69c59344	0x7879e974	0xc32217f5
+	0xb946562f	0x1d1b8745	0x3666cd1a	0xc6a1e2ef
+	0xe22d2e5e	0x9e7ed504	0xe6c32118	0xb2919117
+	0xb2bad34c	0xe7177e87	0x47b68328	0xe579fe7b
+	0xd0d33f00	0x96923c90	0x5ff2bf45	0xff074961
+	0x4dce1092	0xe8a89464	0xc0b1ea51	0xd65f0f12
+	0x6b2389bb	0x48fa0960	0x82722b27	0x62625540
+	0xd4ff4985	0x768b7c26	0xb36a4ec6	0xf6a66375
+	0x1c89e246	0xb629fce9	0x6aa72399	0xd783733f
+	0x6478b123	0xa374412c	0x11b5cfc8	0x73cf2286
+	0x443f5601	0xd817fca7	0xb2ce2d63	0xf6c63479
+	0xd16b0550	0xf2a52ac4	0x7843803c	0x1ac3b58b
+	0x7f96b915	0x732403a1	0x64634349	0xd2ec0bf9
+	0x10410c08	0xe95d8dfa	0xaaeb33a5	0x57893eaa
+	0xb59afac2	0xe9fd6dd2	0x50d11a7f	0xde479c58
+	0x9dac27dc	0xebba7d8b	0x17fa1420	0x74a1678c
+	0x71ccdaa3	0x5e44b0bb	0x5927a75a	0x7b7580a8
+	0x33330c9a	0x40192652	0xba6308de	0xecc81fbe
+	0x41d48824	0x6ce4e0c7	0x145e9225	0xf8484bee
+	0xc8675611	0x750ec207	0xfa5f5b85	0x618b9f8a
+	0x007cdb05	0x67f98d4b	0x1035f305	0x8d700e9b
+	0x9857a0bf	0x4b774ad8	0x8960c81e	0x344a9462
+	0xee2680d0	0xebb5f6cf	0x7397c9f2	0xcafa01ec
+	0xaf69f3f4	0x0a1699cb	0x90ed82f8	0xc5c8ac04
+	0xe50bd06d	0xf75741c6	0xea52365c	0xd0c03f33
+	0xb5e4e95c	0xebf55379	0x0aae6e4a	0x29f8b91b
+	0xef8ad2b9	0x7bebf2ca	0xb194b728	0x7df7b083
+	0x0ea527c4	0x6d55939f	0xb9242c58	0xb3e1f570
+	0x4fba0507	0x82d7259b	0xb5be7b54	0x0aff6ff9
+	0x88391023	0xfe352956	0x4a6bfb30	0xa00c9644
+	0xc478d534	0x0cdb509d	0x9611713c	0xd7c442be
+	0x8d16889f	0x93abfefe	0x435fa757	0x40d95d3d
+	0x11b7bdce	0xd074874b	0xdce6add2	0x0b652a4e
+	0x595a88e6	0x307a223d	0xb624b9bd	0x855ba51f
+	0xad43c800	0x1fcf6afd	0x4bdd921a	0xd6777384
+	0x8da9f15f	0x5fb03ee2	0x5e6d04e2	0xb33751cf
+	0x55d9d38e	0x41589fad	0x6d311b4a	0x43046a7a
+	0x8d9c7304	0xe25f9788	0x8b459e1b	0xc9a3cfe2
+	0xe6ab721e	0x4de3c89c	0x5c2d2398	0x085d8d69
+	0x4e27ce73	0x1cc1f44e	0x05aeaebe	0x8cedb916
+	0x370b4d46	0x1bc29579	0x33d08b75	0x06b77cff
+	0x155693d7	0x125d3f0b	0xd8714e15	0x3b7427ba
+	0x13f6684d	0x834ee449	0xc5a45189	0xb2ad214c
+	0xa61be586	0x4e4727cd	0x563d1c31	0xd4ba1cc3
+	0xdb08cd16	0x4940a42c	0x43dfd0cc	0x9d43222c
+	0x638a0d11	0xc33d3992	0x98bf11f0	0x1aebf6b5
+	0x1e206582	0x5647f772	0x9255ad74	0x75915665
+	0x0fe7dd12	0x9def740a	0x9361bdf1	0xc1409fc0
+	0xd3bac631	0x7492ee87	0xe1e99dde	0x2fbaf552
+	0xfc24f52c	0xc080882a	0x0a2417c8	0xcea3da70
+	0x4fe34fad	0xb4e55427	0xd5d54d76	0xf36686ba
+	0xd6ab1798	0x1868e364	0xa380f948	0x0eaee02a
+	0xad5a44e8	0xb6d119f4	0x82a43444	0xafad0e68
+	0x595c3ab7	0x385746b3	0x32df6d2a	0x0b01b2de
+	0x51d3d6bc	0x107d8620	0x6d215143	0x29d0e901
+	0xbc57a3ec	0xd584ba34	0x8c244547	0x23d396fa
+	0xffb03cb4	0x8396c1a7	0x3f251905	0x8bc769b3
+	0x68f4696c	0xfc297895	0x9ec65e40	0x22deb20b
+	0x5d1def76	0xa7a095b1	0x3aa6a458	0x6ca11880
+	0xcde44ece	0x62b59f4c	0x067f272d	0x9a5aae97
+	0xc60a8d62	0xeb0f40c9	0x83ebae30	0x07dc9cb0
+	0x05dbdc76	0x0c108eb1	0x314f9247	0x7bfd6072
+	0xf648e1c0	0xae70bd5e	0x7c27b4d1	0xb0cff1c3
+	0x8c2dd93c	0x580a4b19	0xfaa1ee8b	0x4173a23f
+	0x838fa15b	0x2b0fe3c5	0x8059250d	0x659a445d
+	0x2a1c1968	0xbf13412b	0x1a9f915e	0xaf80263d
+	0x24508a66	0xe381d252	0x4e0f55a2	0x7ce1f4fb
+	0xc145da4d	0xbd4b29c3	0x27540ac2	0x23ad4b42
+	0x8e6bcda5	0x20061c20	0x1d3cb3fd	0x5c5498f3
+	0xc468681d	0x4c28ef55	0xf0165c1d	0x2dd6d032
+	0x7e347ccc	0xe04db59c	0x7caa883b	0x1f43df4f
+	0xc300031c	0x85f19e9b	0x22811fa7	0x2622940e
+	0x6299f57b	0x5c106568	0xd7da296e	0xccd36b39
+	0xe349afc0	0xd2c2463e	0xf7f55aef	0x0e0a7e3d
+	0x6b6fc6d1	0x8854098e	0xc87edace	0x8190c437
+	0x333b8ec6	0xe49b3a5b	0x4aecd4e3	0x14cc5f22
+	0xa11faf96	0x3d1cd023	0xae614c70	0x0ab662b4
+	0x908d8082	0x76316cd0	0x3068ec32	0x829b047d
+	0xf08d1b94	0x3b2b33f6	0x03df9ae8	0x40f632d0
+	0x3590085b	0xa33aad24	0x39597da2	0x99415f4e
+	0x7aed6e11	0x61a920ab	0xca851d8b	0x2606f821
+	0xeb7c0e8b	0x8bd6edb1	0x725b39f6	0x3afa6248
+	0x03540044	0xfb118ecf	0x8e18bd5a	0x2a85cc05
+	0x4ecac12f	0xf53a4d25	0x8e3fc6fe	0x32233799
+	0xc7ebb5e6	0x058fdcaa	0xe6db17ed	0x2751405c
+	0xa195a515	0x34410c51	0x4517154e	0xbbb5674f
+	0x28050e40	0x8fd71724	0xbe78711c	0xc1b18693
+	0xd202b9d2	0xdf4e0b62	0x460349da	0x71463aef
+	0xb2fb55d3	0x54a972dd	0x49379f09	0x7a7fdff3
+	0xbd82d4f8	0xd2894393	0xa82bca57	0xe61ca9b4
+	0x9e08e6a0	0x53dffe9d	0xe7ae1c5c	0x65bff365
+	0x7564aef8	0xd94abd3b	0x18d1ba52	0x64a759f0
+	0x65c5dd4f	0x6f9d433a	0x57cb5a25	0xc1862d25
+	0xcf50223f	0x90c2724d	0xf5527605	0xb085f18a
+	0x41e2b17d	0xfb1cabc4	0xd8ab04cc	0x761c2166
+	0x8365afd4	0xc3276657	0x14f64be6	0x5dd779b7
+	0x3b3f1faa	0x358d01e8	0x4c821ddd	0x7ada9f95
+	0x2970bad5	0x3b54a4bd	0x3ca7f039	0xcb67aabc
+	0x3b264655	0x96401a5e	0xa3990376	0x90834685
+	0x8ba56352	0xee98c564	0x4a0534ed	0x7d70fad6
+	0x5d73a1e7	0x23fd8de5	0x39c52296	0xefef1540
+	0x7bc934dc	0xeed157b4	0x898d8bfa	0x5761e88f
+	0x73af2674	0x2fb88d9e	0x28de1281	0x9aa76119
+	0xa3ac21ea	0x28ce635c	0x7596d79a	0xd3295e0b
+	0x7826630d	0xd815ef01	0x27cf2899	0xf3de6a01
+	0xcbb32e58	0x6c57be3c	0x292f819f	0xaa4623d6
+	0xb96ab772	0x90a6f778	0x44b9933b	0xa43e7543
+	0xb9f417b7	0x7a6537a5	0xf36a6da2	0x0a9bb3fb
+	0x177c1f28	0x0512c07f	0xdda55932	0x060dda31
+	0x14465771	0xf3f96780	0xb459e5e3	0x49aaefbd
+	0xb07db15d	0x2ac82807	0x8404060d	0x417d036b
+	0x70946fb1	0xe39e68f5	0x5f9b3035	0xf0335e7f
+	0x2ba457c6	0x2d97ba3a	0xc05156e7	0xbbc9afb2
+	0xd25981ea	0xe70d060b	0x805c231d	0xae471b34
+	0x31964d8d	0x3f34e35a	0x8355ee21	0x73822024
+	0x9ce5f2d6	0xdff19812	0xae55cbaa	0x55f5ecbd
+	0xfe558210	0x09b95751	0x41ee7cb8	0xd2b9fa15
+	0x342c07e5	0x7ee50e8e	0xb6154e01	0xdbf4df3a
+	0xd43e2c77	0xc3ff0498	0xd8106f33	0x9bdb25bd
+	0x40cb843e	0x106b08a9	0x3227ce7b	0x58bb7cb6
+	0xb84e3244	0x3f1d0e20	0x76dcbcfd	0xb750bce7
+	0xa8c11f3f	0x161a8610	0xdc1ef5bd	0x14270b6e
+	0x285e7898	0x68375db6	0x01d23b44	0x35a17fb0
+	0x7c9ad882	0x7bda2e0b	0xca67bfcf	0x6e2dd9ab
+	0x227a6aba	0x5d295397	0x5061f96e	0x47a20c68
+	0xf5427e3d	0x3a0a3165	0x2438fd9c	0x2dc91147
+	0xeabab62a	0xdc358e4d	0x7e1fcc9b	0xdc2a328e
+	0x6e6bf75c	0x68c45517	0x594fe5a7	0x2feac658
+	0x1f0a4d49	0x97575e83	0xcccbdab8	0xc13f3b64
+	0x8bfe659f	0xa4ebf545	0x2c3cf874	0x7d78ceba
+	0x46ac5d6e	0x09309533	0x78ffb6e3	0x7336541e
+	0x3d270f70	0xd71e72b4	0x9772402a	0x4ed185b7
+	0x213da698	0x78a54587	0x18054eb4	0x99179a25
+	0xf758337b	0x94629a30	0xec6bf4e0	0x255ac299
+	0xe56f52b1	0x1c2a6136	0xfb7cc1f6	0x87b53b53
+	0x079ca1f7	0x3a8c340f	0xeb70ef48	0xfd1caae4
+	0x564445e7	0xc1d5c663	0x658fb5fa	0x62d2debe
+	0xc0907042	0xb5402269	0x16965193	0xc038c21f
+	0x780f8b76	0x33ffeb3d	0x03ad9602	0x4a7b6432
+	0x93c2b2f5	0x40720fcd	0xf44c164f	0xcbd43d01
+	0xcf7098cd	0xc43242fa	0xc530a6b3	0xcc33c1f7
+	0xde3d648c	0xf1def13d	0x2a22f5d1	0x77704fc6
+	0x08ed5552	0x3e2295d0	0x00584764	0x6af8585e
+	0x43f845da	0xa92e38df	0xd98c12b4	0xb4fac901
+	0x0b05a079	0xa05f215a	0x27d635c6	0x9fc897e5
+	0x0eb91a30	0x43bdad4c	0x705df05f	0x6b7864b7
+	0x1b6380ba	0x4a64e8ec	0x517b7b68	0x67336d4b
+	0xc6d51eab	0xfac40c57	0xb977cbcd	0x0674e5dc
+	0x74ce2339	0x891cc5f5	0x3230ca78	0xa8a653a0
+	0xa8d4b370	0x496d2f7f	0x6ca677c5	0x54260ac2
+	0x630e1143	0xcbf6f819	0x546b2874	0x02267559
+	0xa2e23914	0x7c9a0393	0x1704bcb3	0x6d680415
+	0x91da300d	0xe2ce21d2	0xc38faf3e	0xcc8be7cb
+	0x14496036	0xc98e253a	0x05ca6582	0x8c566616
+	0xd26204dc	0x3335bd81	0xa94e5af0	0x76fbb455
+	0x23b27f08	0xc4db6f93	0x5cb5401c	0x7cb2ed29
+	0x7cbbad8b	0xfc1e8f5e	0x2bc79e28	0xf69228fe
+	0xbde16357	0xc9ac3b53	0xa6afbc74	0x984bb3f4
+	0x98a8b9d6	0xdd21c848	0x33e65c3a	0xc53c772c
+	0x633022f8	0xa324bd5a	0xd260a77a	0x668ca5d3
+	0x4b79a6b3	0xbfd19bbe	0xca2eb497	0x8e7eb5c9
+	0x169b2184	0x0503d4f6	0x24f35c00	0x0ac930ab
+	0xf694120f	0xcee12db4	0x9305757c	0x798a2db2
+	0xed27ebec	0x2f35829b	0x4294e805	0xa7994ad7
+	0x49fd229c	0x5d63fe52	0xb7cd7641	0x1a68af3b
+	0x6f952e97	0x1c02f4de	0xca3a1515	0xed5bf092
+	0x123c32ea	0x602030aa	0x7811cd1f	0x1b6c38dc
+	0xeb7712b4	0x4aa767e1	0x6b49d384	0x7ba4ee1a
+	0x87f02cd2	0xb8e6b0b1	0x090e9f89	0x95f8b90e
+	0x8d76892c	0x0be06870	0x9ec963c1	0x75d67c9d
+	0xdde23799	0xf9e3be20	0x549442fc	0x09cb0906
+	0x95ee6c4b	0x25a2d9b7	0x98154023	0xdda91829
+	0x0c46879b	0xfbf0e362	0xb7223786	0x7cfbc839
+	0x3b251e5c	0x8be187a6	0xa24f9da6	0xc3192693
+	0x7a8ac8b9	0xc493ca03	0xc736b974	0x369db725
+	0x85a6e92f	0x26dbef75	0xa61a71e9	0x38a08fb9
+	0x4a214ed6	0x57fc6f4b	0x9cf91617	0x322e13fe
+	0x5ac816a3	0x748a9728	0xdc777bd6	0x69fb5335
+	0x258439e8	0xf171a221	0xfa7a07af	0x26447b9f
+	0xadcf3734	0x5af34b97	0xf8b4b0dd	0x08c79517
+	0x28861618	0x64692555	0x19fe9897	0xe3bda02c
+	0x77df51ff	0x93dedf7a	0xc7cb57c4	0x02ee5928
+	0xd4aeb644	0x01d511e6	0x6512bd02	0x5d8f90f8
+	0xe77ccfe0	0xe6ee3ecd	0x5403139e	0x6f7075e5
+	0xb6484511	0x3bd42a35	0x5dcea90c	0x5bb1c6e1
+	0xb69b5847	0xfe106914	0x74442ce9	0x10997c57
+	0x1595af7f	0x9f04a8bb	0xa7d2870e	0x19e57681
+	0x54b276be	0x11c3e3f9	0xc5401783	0x9c413cda
+	0xa6aa9e8d	0x23ff8569	0xf1797ea7	0x86ce3e8e
+	0x9ef0a776	0x56a1c30d	0xf5e18916	0xb11464d1
+	0x7f313c1e	0x49c15cff	0xe2dcfb73	0x637819d8
+	0x2d6ce0e2	0x2170cd43	0xb750902d	0x5eb02cd2
+	0x6cadb7d4	0x89b96f3b	0x8d749ca2	0x8ac7abb7
+	0x31fbdb51	0x7a6df774	0xfb9139f0	0x56f3d9c3
+	0x0f104f2f	0xfaba3c49	0xe53aefff	0x932237d0
+	0x8ee10e80	0xadad6e20	0x19883a1a	0xf45a543b
+	0xd560ff0a	0x8c7b4e03	0xe35696d6	0x9e0ec159
+	0xfc2cbae5	0x6ce2cddc	0x14a72474	0x89757fe3
+	0x6b788e7b	0xc16fa200	0xad36bdf7	0x57bdc4d1
+	0x55146f2b	0xa57db4c5	0x313952e1	0x2c55d0d2
+	0x32ab0208	0x10f846bc	0xdcba1674	0x436485bb
+	0x932704de	0xcd7e2e1c	0x59f78879	0x7ca21395
+	0xbcc07be6	0x2b101e5b	0x38924c37	0xb90928f4
+	0x8f824214	0x55699b67	0x54cba493	0xe71c27a3
+	0xdde01c05	0x48d822fd	0x734ed8fe	0x29dbf298
+	0x9ef3a499	0xfb517934	0x19c8ce8b	0x38b8bf00
+	0x75da50eb	0x237f3b1d	0xa8940707	0xa98a4149
+	0x35ec2d39	0xee862d31	0x36659949	0x8f3dffc2
+	0x70afb227	0x94f443c1	0xb6f9308e	0x0e8ebd54
+	0x92b8960f	0x56d21560	0x8453d1ca	0x74c680c0
+	0x2d706dfc	0xd0b81c18	0xbac65445	0x40a34988
+	0x498145a9	0xf436ae10	0x9b72fec6	0xb4100aed
+	0xe305983c	0x349fe379	0xbf31cfa7	0xba624703
+	0x4a491754	0xf973a686	0xa2ba725c	0xd0a23615
+	0x31903086	0x4ae46e45	0x0f705e05	0x4ea6bbc8
+	0xbf299e43	0x0689709c	0x9fc93571	0x07cbc14f
+	0x542ef992	0x80ce91f1	0xf86014aa	0x17d533d1
+	0xb55e63e2	0xe02e0e4c	0x88a5ed22	0x6302126a
+	0x56b32e90	0x5fec4381	0xe2e98b3f	0x30693509
+	0x862e1d75	0x2da30e3c	0xad992d90	0xc62cae4b
+	0x379c77ba	0x467ea8f1	0x8a820048	0x74cc474e
+	0x6bca3803	0x18aaa3f3	0x1fafd26a	0x0865f360
+	0xe3479d10	0x6cefb2b9	0xf6612730	0x2e0f222a
+	0x749a89e0	0x75b1fa05	0xe2ea0874	0x5d422c20
+	0x24707d46	0x6d475835	0xed1e556e	0x6aa4543e
+	0x28b36c16	0x22d83c4a	0x8c3e6d51	0x42a94c9f
+	0x0c603d0e	0xa8c7f417	0x845997ff	0xdc79494e
+	0xa130d628	0xc2df082a	0xa3a2c27e	0x3f93b00f
+	0x1521a7e5	0xca15bae4	0x57e4e836	0xb915a471
+	0xd9147115	0xad52f80e	0x5fd2a2be	0x15972ed7
+	0xb69ec21c	0x502f2627	0xfb46a1ca	0xea685d34
+	0x9226f7f2	0x4b41927d	0x7965eaa0	0xb702e76f
+	0x79a54721	0x5b8e984a	0x37efcd59	0xfeabf30a
+	0xd4ad7db5	0xbb2282ab	0x8a5c840b	0x2ba370c5
+	0xdef5758d	0xa69a9aa1	0x46082250	0x6e8e8477
+	0xf6280c61	0xf99e4a14	0xcf3c5cbd	0xcce657f0
+	0xca635eae	0x0be182b5	0x58e8b43a	0x5c717ce5
+	0xaa7aaff7	0xc329c6b6	0xf1cc91ef	0x8d7cc520
+	0xda155783	0xd5e2e54c	0xf466f010	0xc5dfac4a
+	0x606ad5de	0xf4992f1a	0x1344c9ce	0x4aea9020
+	0xa30447c7	0x0a99ad18	0xd3caa96c	0xfe5b0b4e
+	0x7b50bbd1	0x33e50575	0xa22d1d06	0x73a1820d
+	0xce4c4c8c	0x2cde7764	0x511d1c26	0xad0cf826
+	0x086dc311	0x3060ef7d	0xe6fdc617	0x3050b179
+	0x1dbb5316	0x4145fcb7	0x2eb62505	0x2e1359e2
+	0x79cab612	0xaa9282c9	0x7eede562	0xb016f7ed
+	0x1445fefb	0x809b2e00	0xfafaa754	0x69ac113c
+	0x548a6e3a	0x6d444c14	0xb3d355d8	0xbbadcd2b
+	0x3032d634	0x7df39948	0x4c1f9098	0xa9d138ce
+	0x42823bbe	0x2ef39e3f	0xaaf9ef1d	0x63369afb
+	0x2bb76c9d	0xb7d38558	0x354160ce	0xc04c6378
+	0x6c71ab10	0x7914af1a	0x1c1a4694	0x2f9fce8a
+	0xe28f18d3	0x3acaa573	0x2503b236	0x90ca20e1
+	0xd2c77ccc	0xc3005311	0x836d9430	0xe91d8463
+	0xb53e4cb7	0x4e373c67	0xd06ef659	0x27e1a21c
+	0x285c0391	0x32046fa9	0x8b1b9c92	0x49a22f4e
+	0x81411430	0x050110e3	0x56144e6a	0x47fb824a
+	0xdb2e9a6a	0xb5fe97a9	0xabd37259	0x93da3055
+	0x19fb35e6	0x66661115	0xa27149a2	0xfb7d94b5
+	0xa315f9af	0xd7d97596	0x134d7d09	0xd5cde0e9
+	0xbc3f143a	0x1b2061ea	0xd7b15227	0xe8f506e3
+	0x0aa17e92	0xc8565276	0xc7d90586	0x22a26c8e
+	0x6d462029	0xe7b1ad73	0xd11fa609	0x67643f2c
+	0x64f1ef34	0xa0e7e0b6	0x9687611d	0x09c2d32b
+	0xb494937a	0xcc36510c	0x70555bfd	0xfa25e917
+	0x7d88b6da	0x30f3b531	0xd19b224a	0x999d0f7a
+	0x9fe0da18	0x45947b87	0x536dbf3b	0xa6f5182d
+	0xdf11f95d	0xa5abcdbf	0x7528110b	0xf54fe792
+	0x71a97619	0x680bd3ff	0x6981ea39	0x683ff854
+	0x302fbbe4	0x12129f84	0xf63cd448	0x69fe289b
+	0x568da933	0x2f1e1146	0xe7404e52	0xcd329394
+	0x02e41762	0x94456d4d	0xe9416a20	0x4e5920e7
+	0xe8db71fe	0x527a5313	0xe42c7d9e	0x58c8c1fb
+	0x28949bc1	0x312fdf97	0x3569f41f	0x3ed5f092
+	0x44baef39	0x5c11d5ad	0xb5d172cf	0xa9e4cfa3
+	0xbc5ed197	0x2f290ead	0x747f53ed	0xadf1b698
+	0x1b90440a	0x4cdfe154	0x9b24b832	0xeb97d794
+	0xc90fe91e	0x4fef1271	0x8bf96025	0xbdb49f79
+	0x63910640	0x26a05cce	0x3318e422	0xb2fc61de
+	0xf14cedd1	0x4bd7687a	0x8c4c91dc	0x48a857a2
+	0xb47aac94	0x787526e2	0x99349c7a	0x0bd6ba75
+	0xbfbc4b0b	0x040fbec9	0xd00de44b	0xc4c7f0f5
+	0x74a8653b	0xbd3cc036	0xa601a4f3	0xb82c0da0
+	0x2709b674	0x73065351	0xaf4cd23f	0x3481ea0f
+	0x6a1fa77c	0x26a9d280	0x95f4a170	0x393e7590
+	0x015b3d73	0x36d91e55	0x61a7f3f5	0xf6d39c21
+	0xd9ee4701	0xe57af451	0x5e141761	0xf6b6e472
+	0xa6efc965	0x9606aa1b	0xfb8ce005	0x831ab2d1
+	0xfe7a1af6	0x5e326881	0xa0ad32ae	0x15f86ecc
+	0xa1a634d2	0x3a40c4a9	0x88e10130	0x2e6c4556
+	0x8526aa32	0xa81b0d30	0x19c83936	0xdcaa556b
+	0x6dc8064e	0x5709ad31	0x1b6fba18	0x9ebe34b1
+	0x28abc3e6	0xd76c3908	0x4374657e	0x6f0fc085
+	0x4f19a108	0xb774421d	0x405228d5	0x123dbbab
+	0x18535471	0xfc6bde41	0xd4b2d82e	0x65b85772
+	0x64731e41	0x29e886f6	0x4c2c7eda	0x91586a5f
+	0x15b2407b	0x5fa08a72	0x56898e51	0x5424e976
+	0x19ce4a36	0x0ada4656	0xe634446a	0x478da533
+	0x36f1c763	0x01ec46c3	0x5e1d1040	0xf6da1918
+	0x831f8f94	0x43ddb630	0x80b5d4e5	0xfc403ba5
+	0x40dcdd4e	0xa19d0aa9	0x6c32fad7	0x7cdd6f3d
+	0x8e9c123a	0x42c4edd0	0xc8247030	0xf0e6cebb
+	0xf8d1425f	0xcfa8e403	0x67646391	0x9dee9f9b
+	0x5683c4f6	0xd958ae1c	0xc62eedfa	0xbd67ea10
+	0x253398d4	0x18b7f92a	0xf101a7de	0x60066732
+	0x4ca1e3dc	0x6e1eb0a0	0x115aa9e1	0x8370aae0
+	0xe46756d8	0xa02eb1aa	0x854dbb8a	0x6334873e
+	0x87613a81	0xb5bd56df	0x491371d1	0x02bbace8
+	0x2a2e45f9	0x91bdc460	0x2bcf90b6	0x81df2f07
+	0x34aa2dd5	0x5b54a117	0xb7a5bd42	0x713e2287
+	0x1ea184d6	0x176bdda0	0xa19c0d86	0x4180fd5c
+	0xd018a4cc	0x60120a37	0x8f6e094b	0xfebe1b15
+	0x42866bb7	0x4a9f772e	0x0bcf9cad	0xd936a924
+	0xec6cf0a1	0x1f9ccf16	0x81f8229f	0xdcef1733
+	0xb4a31fca	0xefbf0a0a	0x057e0b4b	0x59491c96
+	0x70ce99bb	0x908ce274	0x637ae09c	0x479fdd52
+	0x11ea6250	0x7778cdf6	0xd0ffe2ca	0x539b18dc
+	0xbcdab649	0x3066399b	0xd685edc0	0x79d8d588
+	0x32942aa1	0xd03531f7	0x5d024d56	0x4dc99729
+	0xd1efff53	0xdf3ce9a1	0x31462a0e	0xe5427113
+	0x395e2980	0xcf5c9d4e	0x91e11088	0x7e4d31e2
+	0x5ff91ae8	0x9340e815	0xfcb89789	0xcb1b2f58
+	0x655aa934	0x2eb022da	0x419104a9	0x6b648411
+	0x582048e2	0xa0db392a	0x1e1d6443	0xf3c7a401
+	0x1e737591	0x452af94c	0xfcb74331	0x2da70f75
+	0xa8b59eb9	0x736224c8	0x5ba81657	0xfb36eac0
+	0x4e0336b4	0x8925a32c	0xa4d60fde	0x8a95ff27
+	0x57a7e536	0x7e6a2f58	0xd9e9751e	0x817cc66a
+	0xca4bd134	0x627382fe	0x00e56736	0x74844fbc
+	0xab1f8265	0xa32955e3	0x41cd361a	0xb3ae6366
+	0x1f77ea37	0x2200c6ef	0x81854e76	0x49ed4e92
+	0xb57a7fbd	0x7b9de6d2	0x128feedf	0x57bb65fd
+	0x20ccd650	0xdcde5458	0xd5461b27	0x465147f4
+	0x70719068	0x2cb48f5d	0x6edc0d43	0x83dbda97
+	0xf077ea64	0xf61423e2	0x39a55177	0xb23ff07c
+	0xa02e4ca4	0x9e6250d3	0x77f1df9c	0x238c632e
+	0xce253a6a	0x096327c5	0x87f1db29	0xd75ac0de
+	0x456704b5	0x9ee7046e	0xd693dfe0	0xf995c6b9
+	0xa354d140	0xf16bf090	0xaf511cdd	0xdc56d21e
+	0xd7cc4d4c	0x5398cc1e	0xe5444b3b	0xe192f473
+	0xd09ae67d	0x8af2775e	0xc1af44a9	0x57bc4586
+	0xa6ff5419	0xdd4ba49d	0xec4864fa	0xda9d0357
+	0x84dfbe33	0xf41ba9c4	0x99e2bda8	0x9fba720b
+	0xa7dd9e92	0xa0d43386	0x3e0f9ef2	0x6e388282
+	0x8f47ea95	0xac920523	0xa98ae8a5	0xf6a6a4d4
+	0xc3fa2e55	0x74a21b36	0x9c0b14b2	0xc6b8a79a
+	0x367b7036	0x24b9f255	0x0b543b75	0xb630fa41
+	0x1b260452	0x7daf6714	0xdb8a13d9	0xede8f6bc
+	0x47a21d0c	0x01d9ca54	0x4a8e5cd4	0x257cd217
+	0x7504cecc	0x973bbf11	0x992b731e	0xaab55b65
+	0x77e2f058	0xf580b58e	0xb10419fe	0x679aa4df
+	0x296c1d64	0x751380f0	0x8f70f0de	0x3f78bdb8
+	0x1ee68ad6	0x7d5d50e4	0x823710a4	0x18b98d13
+	0x86bdf798	0x953b8131	0xb5da3d24	0x2eccd3b1
+	0x828a154c	0xed51b913	0x566e58ef	0xab8ff1b4
+	0xc744d227	0xe705bbc6	0x6032eb64	0x5495e4a5
+	0xe83add11	0x08429de8	0xa2e397dc	0x4f00c90b
+	0xcb7672e8	0xa1d55607	0x0741ca2a	0x323d64f2
+	0xa700ef1e	0x6ccb2967	0x07c29e41	0x018440a9
+	0xbb1880cc	0x35502720	0x8a13a96e	0xe2bfcd29
+	0xa76ad3aa	0xd95be915	0x6dd66033	0x41d655f3
+	0x02009028	0xb44ec634	0x82e61d87	0x216e624a
+	0x7fc79105	0xac0307cb	0xd22fa331	0x63746b2f
+	0xe51ab72d	0x9b550c82	0xb28dbc01	0xd569d017
+	0xd168d372	0x8d6bfe6b	0x5820751c	0x820a4e23
+	0x13cfd07a	0x678c8319	0xd1e65476	0x752967ee
+	0xafb28392	0x390d5488	0x53668098	0xa0c92673
+	0xaf0549c2	0x644f51c3	0xd59df083	0x7cb37a42
+	0x12261017	0x038c15b3	0xccc30b03	0x85ee24ce
+	0x1e029b23	0xb6bb2845	0xb62a305e	0x2d0cf4e9
+	0x182b887f	0xec423ce7	0x8c1c0b25	0xc83b4737
+	0x71fb9023	0x63d639f6	0x16c1ce44	0x66ac8331
+	0xd9aa0975	0xba3d445c	0x5d097729	0xb353a034
+	0x23811786	0xb81394b5	0x5323f1b3	0x7a3e1576
+	0x3f2867ad	0x0bc88c8e	0x74b60d63	0xd56335de
+	0x0d40f71c	0x55ec2524	0xea3a2c78	0x19e5e0ae
+	0x9bf3d033	0xf57bbc94	0x05b6ac55	0x4c368744
+	0xae8c68f2	0xf23aad06	0xcf94d185	0x2360ff3d
+	0x0e8a87f9	0xb97c8d33	0xa7122e6e	0x5ad4dc50
+	0x6145ff8e	0x617389df	0xe8a0e09b	0x4d40ce6f
+	0xee2b65fa	0x4104d368	0xf4bc9d85	0x0b67abbc
+	0x7bbad9ff	0x26b293a2	0x06055372	0xbbb05665
+	0x0560311d	0x421dc535	0x9c451ac7	0x38c83a74
+	0xc8921ff8	0x634d52c5	0x6e66dae7	0x1c86fae3
+	0x5a0645bd	0x6e5fddc9	0x86852d55	0x76207d9a
+	0x6a4b7990	0x661c00eb	0xb268e55b	0x17daec24
+	0xa2854da4	0x9b1f3f63	0xdd200bc5	0x0b50aecf
+	0x8242f913	0xc7ab6eea	0xaa977c22	0x748d0d1b
+	0x4490aae4	0xaa293e18	0x69aa0720	0x6115eb81
+	0xa5b187fe	0x828bfe34	0x5fb6d155	0xe764d755
+	0x08833186	0x8475cce3	0x718bfb48	0x063b287b
+	0x7ea71b59	0xbedbfd29	0x3736aa07	0xe2dfd533
+	0xf2ea49a3	0x96b0983a	0xc1f60b14	0x511bed9e
+	0xac976686	0x9c60ce3d	0xfffd0b07	0x59d7cf79
+	0x477942b4	0xff2f43cf	0xeb4b899b	0x37a47783
+	0x8e6602a7	0xb6bfc410	0x7685c6e4	0xb7ec103a
+	0xd54fdb01	0x3933d261	0x725982d1	0x86ada0a9
+	0x83788370	0xbafb1498	0x13972979	0x2157be41
+	0x5e976c80	0x05501107	0xb3b66da9	0xeebcb8fb
+	0x42ac1fee	0x1dba34a9	0x3f5a7582	0x362e7ed7
+	0xaa69be91	0x419f4d18	0xb09a9967	0x31aba127
+	0xaa247bff	0xb31f4958	0xe79562af	0xfb73878c
+	0x47dc697a	0x5d08fa9b	0x91dcd3c2	0x53e52d33
+	0xc84ddc84	0xdb5f8e17	0xe51889e2	0xb1aff523
+	0x4ffa0702	0x2c72b35a	0x9a4246fc	0x62420517
+	0xaad11acc	0x18190bf9	0x11e140de	0xacc99086
+	0x39347992	0x191a53d7	0xbe92c4ef	0x9a934b5d
+	0x64cf7353	0xe30a3e8d	0x0aa6db52	0xb0a7e26d
+	0xc8fe2f52	0x2e274a07	0x0c94b6ba	0xf80eaf3c
+	0x1ba3e94e	0x5853ffe3	0x11652833	0xce7b0839
+	0xd1893c23	0xd06d2078	0xa65f020e	0x281e6a7d
+	0xdf1da5a2	0xcdf69d20	0x74fa9b92	0xd98d6000
+	0xb732496c	0xbd12f87e	0x561dc55a	0x651d42ff
+	0x5736b74a	0x2c48a906	0xfdcbaf15	0xf76606e1
+	0x80dd0254	0x8105e60b	0x143200b2	0x0f02f524
+	0x1580d2c6	0x7281c6fc	0xc971cd31	0xd4a57180
+	0x5051e5ec	0x193c72eb	0x930332c4	0x488d7403
+	0xa93e425c	0x93e8ca97	0xa0a55070	0xafd8f8fc
+	0xc424f1bf	0x11050ed2	0x855d0923	0xa0fcef35
+	0x61f9e84a	0xc2196706	0x7221d5f7	0x96d036a5
+	0x137ca3fb	0xfd632623	0x30b10850	0xdda390eb
+	0x270fc9af	0xe6a8d748	0xf55bc288	0x8cc912d1
+	0xf2d9cd15	0x5ded2f07	0x2de9b076	0xf5088354
+	0x885becf4	0x959ef88a	0x0d9ea589	0x2ceb0a27
+	0x8925270e	0xca5ecd99	0x8ba9265c	0x209eb0b7
+	0x2e8b51d8	0xc598e096	0x23c17aa7	0xf600bcae
+	0x7b33f831	0x223e1501	0x361c9f12	0xe6aeea94
+	0xa5c6948f	0xd1daf8cc	0x0b0e0b54	0xb0cea6c7
+	0xa437fbc8	0xdb4139ab	0xcbbad47a	0x124e2117
+	0xfb80c5dd	0xef085f4a	0xd24c5fa8	0x2548a1db
+	0x5e6cdeb2	0x8e4f0290	0x78cd8245	0x1ebb5eb6
+	0xd9bf1208	0xf20eaf0a	0x544df94d	0xebc9c742
+	0xbc5b4bbe	0x33f6fcaf	0x32efb07a	0x55d91b59
+	0x2c0ed1bf	0x39985cb7	0x4cab882f	0x530cdaca
+	0xccc78cfd	0xdd834c48	0x7ce7898d	0xf7458891
+	0x933c2ae8	0xa06c5762	0x2eb03e35	0x8e938b71
+	0x3636f142	0x0026efb8	0x183d71c4	0x7e8ff92a
+	0x63265ea6	0x0f1352b8	0x73f8a8fa	0x6594e921
+	0x401f88db	0x64abd8e6	0x994140c7	0xb2258b0c
+	0x9bd6e6a1	0x92bab589	0x5919a943	0x29ab4d8e
+	0x33cbb8d4	0x57084d92	0x006c4d50	0x57c49e54
+	0xec1ecfe6	0xeaa8109a	0x269d94a5	0x4a664f84
+	0x2bda2944	0xdafb85c7	0x2a7b4b8c	0xd8f124d6
+	0xbbac0e70	0xeac5a129	0x308d7e39	0x99a023a9
+	0xf616fc22	0x76fcc40f	0x7f745409	0x83872303
+	0x0b067846	0xdf90a414	0xb6d9b6e1	0x8d0f93d8
+	0x6f76a627	0x02f89060	0x392cb9e0	0x6acf19a9
+	0x7cffe4d1	0x9928b4a0	0x87a031bf	0xecff42d5
+	0xa376e023	0x69d2e1e3	0x1fb67afd	0x5396049a
+	0x45538549	0xec0e6f60	0xf1ab27e5	0xc679e764
+	0xee430c38	0xa6b0c2dc	0x92824db1	0x65d5ffe7
+	0x448b17d7	0x9c67c8e0	0x14b36e2a	0x283de0a8
+	0xc59bb35d	0x8faf1ca7	0x4265db7f	0xb0e74749
+	0x0924d389	0xc22bf3fa	0x017c143d	0x93b4e0d4
+	0xf8aa8e07	0x07e0293d	0x5b40bba8	0x619c8946
+	0xc817ee7a	0x82fd526b	0x3e5b0f9a	0x5b352d98
+	0xc786d63a	0xcbec5c0d	0xd05e9640	0x7cab758e
+	0xaa9bd61d	0x205ff53f	0x2f093865	0x55ef390d
+	0x4b008d12	0x0344c52d	0x64820f87	0x8e9c5202
+	0xdd3f2276	0xf3b46630	0x80e85ea0	0x9aea428f
+	0xa205b11f	0xa8506b8f	0x2c89f419	0xb0b9694b
+	0x21029e6a	0x5e05869b	0x3baf3c6f	0xde680ae1
+	0xd65b5eb0	0x99a6937c	0x52a78fe0	0x6f577b06
+	0x8dea8d63	0x2417d49c	0x1a0ecb5d	0x91f22002
+	0xc540298f	0xea9f8f6d	0x01ccfdb5	0x287138c1
+	0xef206774	0x9d5deed8	0xba844833	0xf612317d
+	0xe0bd4bb4	0x595d0440	0x73643204	0x2c21370c
+	0xf9d5df6e	0x05614527	0x73c4edee	0x33f45ded
+	0xbc47170a	0x24b94b30	0xff304e54	0x4e0c3b53
+	0x658af390	0x402418bf	0x9db7318c	0x058721ed
+	0x896bdd56	0xa956c5cd	0x3f928400	0x94c93146
+	0x56600758	0xf46f4f66	0xa5bf66d5	0x0e8b5870
+	0x8ba7e755	0x4177fee6	0x32cc8824	0x90b677d8
+	0x307e9dd3	0x853a7e3b	0xa2f064a4	0xa42dbd46
+	0x243ed6a9	0x7164eb1f	0x9e97212a	0x9757d142
+	0xde296a05	0x8699a74a	0xeb02fa7d	0xf80b41fa
+	0xd9dd2198	0xd7ffbd00	0x21b15853	0x11b78093
+	0xbb329142	0x5260fb1f	0x22fb24fe	0x7a5e7e71
+	0x71434197	0xc5ddca32	0x930c8cb9	0x65192958
+	0xad1a41f1	0xc77442ca	0x72b64ff7	0xa90bcde5
+	0x184a19de	0x71df036e	0x1b69b0ed	0x023c391f
+	0xd9847da5	0xca57d383	0x0d21255d	0x2ea68d9b
+	0x0189eeb5	0x1ea62386	0x4c8d42f0	0xac20dd55
+	0xacceef1d	0x972f56e3	0x0bc40455	0x3853c5a7
+	0xcab0d1f5	0x0d2a990b	0x525be1ba	0x5cc6daf5
+	0x4d564f06	0x834d8f94	0xc0c055e1	0xef34557b
+	0x354537de	0x7207e6b8	0x659c9298	0xa88ac04e
+	0x80d8014a	0x7f4f6e7b	0x1136e621	0xb1b62f79
+	0x8d4613ec	0x673699ee	0xdd6d7741	0xdba1ffa9
+	0xe219e1b3	0x8bf64c21	0x14aadc3b	0xc4dc4e19
+	0x47ae1e52	0xc5409e4b	0xce8d29d8	0xe0b1cf25
+	0xcaf06411	0xd5450dcc	0xf14f29ee	0xf3611dd5
+	0x52bc02f3	0x886b68aa	0x3b2853ef	0x110aafb0
+	0x6b6d765a	0x87fbaa12	0xc79f134e	0x88b910fb
+	0xe04aa148	0x33feeccf	0x3be43d3b	0x067854eb
+	0xf22561e5	0x56c3abc3	0xcf0ff408	0x6291d940
+	0xe26819d9	0xcfd04da7	0x94ab2808	0x156dcd0a
+	0xb6d1c47b	0xdca4aa76	0x877f870d	0x4e06ec17
+	0xbb560b01	0xbe1b62e7	0xd98b51b2	0x7083e3d5
+	0x427ab621	0xe5fce36f	0x606dc14a	0xe4b70b49
+	0x982d2446	0xf2d2e82a	0x60836061	0x681317fe
+	0x1667e3c8	0xf6eef490	0x1ad768d2	0xbc86ae5c
+	0xfbb392de	0x868caaaf	0x8429b5ff	0x266b6d5b
+	0x372e8f2e	0x6e875cce	0x3a972f08	0xabddef20
+	0xc777c559	0xd8f924a4	0xad39137e	0x4c16a4f0
+	0x91d51877	0xae645599	0x4d09feb1	0x0cdededf
+	0x5749b5b8	0x513c9745	0xf4da62f7	0x6583b20d
+	0xb599bb89	0xaf6bea53	0x7275f6b3	0xdefc5092
+	0x01a3734f	0xd95f4c5f	0x37bce97c	0x63610b99
+	0x30555fe4	0x20af2f26	0xf84b2652	0x67ef6d87
+	0x2119805a	0xcc79747f	0xaa479405	0x63a02857
+	0x1953fc39	0x4f952879	0x886bfe97	0xf0067752
+	0xa08b5005	0xcd9a5ebb	0xb04486e6	0x560c79ae
+	0xe8faf52c	0x64a9a961	0xae9a5f1b	0x74cb5ef7
+	0xf8d0269d	0x2fb63c57	0xd78a9a90	0x99cc0a42
+	0x46bb0252	0xe56b026b	0xfb5ff703	0xdc8e0588
+	0xe5d9e280	0xa73ec2b3	0xe21bccb0	0xe22ee743
+	0xd1bb3217	0x5d4b3f92	0x0a627d8b	0xf2fd974a
+	0xad0a57c4	0x261ba12e	0x1670f842	0x996ab25d
+	0xf6f8043d	0xa6cbb362	0xcac3044e	0x6fe01268
+	0xa54ab676	0x54d7444a	0xf3be5437	0x6b2b737c
+	0xbe10300c	0xea505599	0xd60a15f6	0xd971ecc0
+	0x9c480c46	0x2233038d	0x66d38df9	0xcb566912
+	0x63cffade	0x75811ca6	0x8dbfa4cc	0xee5fc07b
+	0x23329e49	0x39ee07e5	0x5de33ff1	0x601f8348
+	0xb60a8bc3	0x832d3660	0xd1bee11b	0x1a38d12c
+	0xaf00744f	0x21c2639b	0x0fd34252	0xcd63a9f1
+	0x60f34993	0xf8728afe	0x75f8bb5c	0x74a250ca
+	0xb9f51490	0x6ac643a6	0x4011a0e5	0x77288317
+	0x57f772b9	0x92c0715c	0xd5d0e030	0xde335025
+	0x669f6b14	0x55c74853	0xf3ac7cd5	0x38284e8c
+	0xb0fda481	0xf9b7f045	0x839293cc	0xdf91a0a0
+	0x18d20454	0xf73214fc	0x09577b9d	0xb5febd00
+	0xd9b96c88	0xb454ea2c	0x6204a932	0x736edf8a
+	0x9724f56e	0x3092f58d	0xac17cced	0x5ae87e39
+	0x28dd2a0d	0x3806d96f	0x5e7c8c68	0x72df4471
+	0x0207de38	0xf026ecac	0x13258e9a	0x34a8e8ce
+	0xdd7d7286	0x8d7553af	0x11ebac36	0xfb9965ff
+	0x9beda82d	0x1cd898cf	0x1b791830	0xe96ca8f0
+	0xa0d274d6	0xdd6fea3a	0x7537177f	0xdd93627c
+	0x60b64e47	0x10f30724	0x12489cf7	0x4587e1ac
+	0xe7835522	0x61d48d9d	0x6afd081d	0xafbbcf2c
+	0xe31d79cd	0x49ae4218	0x7c2c4a33	0x4fdf949d
+	0x52ccd576	0xef2c3d62	0xfd5b75db	0xe6a5c2e9
+	0x04fc9c6e	0x47fde414	0x8a87ebfa	0x850904e4
+	0x2f49b552	0xb5f186fd	0x772a4ba3	0x48d0be3c
+	0x846c7d78	0xc1c2a1d7	0xb9375f9d	0x302ed828
+	0xf79208f1	0x8fdc4f71	0xc749ed51	0x1cd0c28c
+	0xee5a5f7e	0x7f02b7ca	0xdc3b531f	0x99c0119d
+	0x428e5474	0x10515459	0x8d804d27	0xb7c00220
+	0x264c2695	0x7aa6e5af	0xef807715	0xa444f446
+	0xe51c7755	0xcd825b6c	0x39afa440	0x88638e46
+	0x4ea4366d	0xddfc9854	0x99696f2d	0x210592ea
+	0xf4763dcf	0x7358acdb	0xedfc8523	0xe46031c8
+	0xc9762414	0xa71a348b	0x084b6c82	0x9162e0d7
+	0xda6a5b8a	0x68ca14d5	0x6385741f	0xb103d4c2
+	0x44299ef8	0x9aba89fa	0x2c87dcfd	0x476865df
+	0x1189dbb2	0xdcd9d19c	0xac2bbd51	0xa71526f5
+	0x745222d7	0x4813ca98	0xcfa5802c	0x5d2b3907
+	0x8a17d1b8	0xea56f907	0x3ea58d71	0x933fa242
+	0x021f46a7	0xab8d4e86	0xfa4eb33e	0xaecbd5c3
+	0xb3258e74	0xaac9f193	0x415a5518	0x28b13031
+	0xbae39e53	0x1072fd5a	0x4e0fbf55	0xb02c5d77
+	0x5949c780	0xbecf72df	0x15e52c72	0x3ffeb165
+	0xa8e73d50	0xa52fd918	0x2b3c4d7c	0xa1e9e021
+	0xd8e91949	0x63bf63ed	0x8f2e150a	0x9cbceca9
+	0x33b10a97	0x4d2c69f7	0xf26371bf	0x0b5214ec
+	0x10eb7fca	0x1958b429	0x25f190be	0xafcfb396
+	0x7aec0c45	0xf9a0f163	0x9c966818	0x28f83619
+	0xe35c61d4	0x1ad8a656	0x576dba63	0x7aa44804
+	0xf941b7b8	0xc5faf3cc	0xdf1fd628	0xc009417b
+	0x366ea78d	0xd3cb7030	0xf3f12e97	0x5298cc89
+	0xbb43c8ef	0xd0a8ef96	0x564bced6	0xbcbd865c
+	0x5c80b1d7	0x131ccb04	0x7502d06e	0x465f5cb0
+	0x93320c4c	0x9df42986	0xbdb1fe26	0x48ae8bdd
+	0xaf44e912	0x6aa468a5	0x67ecbb05	0x30b7c0a5
+	0x3ad75711	0xa2d5f63c	0x30150058	0x4d748121
+	0x70804875	0xf46b6ea6	0xa3fcbb7b	0x1af6b4c4
+	0x48496de1	0xdb1a2321	0x758eb79a	0xf35f697f
+	0xb4ff9dfa	0x38ab5b31	0xc918f6f1	0xb3a259fb
+	0x3610afe7	0xdfcaaa0b	0x00c747dc	0x96c40b4a
+	0x5c815168	0x29198fee	0xc94eeea9	0x70432b55
+	0x5de7bbd4	0x0995652d	0x4b3e846c	0x7e4c9ca1
+	0x7c0e91e6	0x401a820e	0x3ca3429a	0xd3812f44
+	0x9cb6a5eb	0xf03ce395	0xefca548b	0x8943bc10
+	0x472b2108	0x82d4a386	0x1d0ef931	0x94cd70ef
+	0x2d00d619	0x40d36f80	0x238ccc47	0xe0856568
+	0x9f06ad8b	0x95a4052f	0x287a57fb	0x9e9f9891
+	0x62bc3a31	0x24c3c1f8	0xbabdc3c4	0xfa40629d
+	0xd16f1f33	0xa9f7600d	0xbcbdb2d9	0x214f24be
+	0x623ea3b0	0x8d650418	0xe86635b7	0xb834745f
+	0x20771340	0x3c69a0b2	0x8b7c84cc	0x740e475c
+	0xe5a540eb	0x9e216852	0x1383201e	0xfbf1f572
+	0x9680d736	0x3d7f8d69	0x615ea313	0x87bc1297
+	0xe552725c	0x9bfee104	0xf2e87d90	0xde9188b4
+	0x028d268b	0x51c75c60	0xed93377f	0xc380d9d9
+	0xe858bf8c	0x5d0b4a40	0x05a3171f	0x76ae3ec0
+	0xf86e3fe6	0xc3d78254	0x7cd640c5	0x6835dacb
+	0x983bd9a8	0x05d1e564	0xc5d5e9b3	0xf81c6560
+	0x8ecba474	0x071daa33	0xf5010276	0x5432ba59
+	0x10f2dbc1	0xbe892680	0x7e92d3d7	0x8d2f0113
+	0x37fa8034	0xb13058f4	0x44684553	0x2bd0e36a
+	0x67ea83ef	0x815e7115	0x3cd123af	0xd9aec852
+	0x67c61c95	0x861d068a	0x60c7797e	0xd9733b31
+	0x9ed29f37	0x1ccc8e08	0x34bcfa7f	0x1c66914d
+	0xc64dc834	0xad884c08	0x2b22b8de	0x53d6fd78
+	0x0355dcc8	0xfd363485	0x62370358	0x0dcb046d
+	0x22fe7d2f	0x5fdd1117	0xccd6d8d1	0xe97925a4
+	0x309aca3d	0x56c31fb9	0xe6f81e08	0x24fc0560
+	0xa78d459b	0x4940b35b	0x9a4a2fdb	0x203eafb8
+	0x91e5fcab	0xfb9be08e	0x9cb903ac	0x31598d89
+	0x4f41986c	0x77206f4e	0x61811c9d	0xff51d95b
+	0x2d7b4c66	0x84ceb768	0xfb135597	0x58087b13
+	0xa1681cc2	0x14009e31	0x778c3fec	0xe3faf2fb
+	0x5092b2c9	0x8919c362	0x34e2b174	0x7bb04f44
+	0x63c39b5e	0x8ef696ff	0x2e4c612d	0x77d390e2
+	0x5dc958a1	0x528bb31a	0x1cb07e7a	0xe37c9c53
+	0x002856d7	0x6a10b962	0x423a7b39	0xc6da9227
+	0x207800e9	0xe200c119	0x0e5af6f3	0xfb580459
+	0x71dc40a0	0x70434cd9	0x13f7f455	0xdf3fd7ca
+	0x37cbc698	0xf5a5808d	0xa7bfdf32	0x8a0774c7
+	0x75b67d50	0x5a6908c9	0x23611a6d	0x8b50c483
+	0xfe1e2eba	0x7ee1c732	0x2191e47f	0x9e63eb3a
+	0x379cd875	0x4df7258d	0x166a8aa8	0x1c94586a
+	0x2456c4d3	0x000185fa	0x7a196b46	0x914e789c
+	0xf562c939	0xb3bad5db	0xc2c19b89	0x8a621ffd
+	0x0c807ce0	0x701a938f	0x69234cdd	0x36a00f09
+	0x964c43f7	0xcf71cd85	0x5f504e16	0x446c6388
+	0x25742397	0xf1a375c8	0x6bcf822c	0x1b175fd7
+	0x0fe78e56	0xfe7817d6	0x66da0366	0x904e8327
+	0x5a0749fa	0xef3ede57	0xd0fa2ac8	0x89791771
+	0xa5cd616f	0xe9ef2860	0x9b533bc3	0x1d746f03
+	0xf4bb82b5	0xacae0438	0x840b3e34	0x30371a0d
+	0x8590acf3	0xeb4ff7e4	0x40437052	0xba847bf6
+	0x24059538	0x44daca63	0x23b32e28	0x091386e0
+	0xc480e66a	0xe4a839f5	0x34929bcc	0xb9051207
+	0xd21252f9	0xc6524769	0x8c422851	0x36280aad
+	0xbf00b1a1	0x4e36c85d	0x7949e8ef	0xf76be57e
+	0x373a0ab9	0x1b7555a0	0x0c2caf56	0xc9241f75
+	0xbe5b0ee8	0x5a486f75	0xfb2c050d	0x6aeda464
+	0x3fa744ee	0xf6e055a1	0x0a7324ab	0xfab58776
+	0x09baaf66	0x459ce186	0xc6eb1894	0x56a4ce4a
+	0x58ce1069	0xf4debf5e	0x04a145b9	0x1a246583
+	0x9b07fe23	0xd4d37068	0x7321e0bf	0x2dfe17f3
+	0x426dd8a7	0xc561a2d5	0x7f515a47	0xe57d37fa
+	0xa85f0aa5	0xffb78cd7	0xf30c4551	0x3572c02b
+	0x6f4a4cbd	0x7322ecc7	0x170a7b9a	0xa1e80d28
+	0x5a366af2	0x4f24a3a7	0xfefd29ca	0x0d7b02dc
+	0x1adde2e1	0x5c426cc5	0xb1e53b76	0x5dba2c5c
+	0x1458b6ca	0x73cea912	0x39626c25	0x7547e76d
+	0xfcddbb97	0xf03d59ee	0x3cfdab3d	0x309db86e
+	0x3de8df47	0x4a570e6d	0x09c9579a	0x19ac033e
+	0x0a7a9a86	0x3662d261	0x048fa67f	0x4aa4009e
+	0xc7660654	0x524d81f1	0x3157ec52	0x857d1f10
+	0x3770162e	0x3d1ff919	0x732d2b13	0x84187da0
+	0x95722d45	0x362cada5	0x5d67637f	0xdaae8465
+	0x9f5c0699	0xab9aba98	0x6f97d3fa	0xf9cc4120
+	0x0ca1872c	0x1a832c9e	0x7b74d6ae	0x98dca967
+	0x03eb7699	0x5fd02b54	0x962c6224	0xde1ab807
+	0x800af435	0x2458a4ca	0x717de910	0x31648afc
+	0x871527de	0x3cb93892	0x45237e37	0x446b1315
+	0xecd807e8	0x70f38e30	0x140dc60e	0xaef7b7c1
+	0xadec312e	0x94d45820	0xb8960073	0xe8dd5bac
+	0x7616ab11	0x0c3cc190	0x516003e3	0x323cdb39
+	0xd679f9f4	0xd7c179d2	0xdfbc5e24	0xaa1226df
+	0x3cd41b0e	0x88f436f0	0xbd5b6cb1	0xb78c69aa
+	0x982e0ca0	0x91f852a3	0xb331636a	0x28df67ee
+	0x81b029a1	0x9e7375e3	0x56e874c0	0x8b93a735
+	0xa47eaa4e	0x772ad825	0xfb83ba8b	0xc08db79a
+	0xcb7a34be	0x14214d72	0x7d6fa82e	0xe75c7002
+	0xa6290902	0x716d04c1	0xc75f0a97	0xb68e0912
+	0x08b5ef1b	0x507ecac3	0x2d740b08	0x43b6c7bf
+	0x3965675a	0xf56dc4fd	0x1ba44239	0x36753f70
+	0x0b2452fc	0xe36bafe9	0xfc3134c3	0x2ac78286
+	0x69ba53b8	0x225b9bd9	0xaf426f79	0x99bd2d3e
+	0x0bcb8e18	0x28c87047	0x2045b3b9	0x730ec870
+	0xe6558839	0x9ca3de82	0x263a41e7	0x1c8ea255
+	0x334eb3ad	0xc36d6793	0x66add8ee	0x652c8548
+	0x79dca1a8	0xc2526972	0xd10f03e2	0xdbae6f42
+	0xe223bf69	0x10082495	0x74ba4cf9	0xeb71ef5f
+	0xafae5d4e	0x7b3663e9	0x9339468c	0x31edca72
+	0x65a07876	0xf336fc1a	0xaa505397	0x011d5253
+	0x99b88ade	0xa688f0fa	0xedac589d	0xab4d8f45
+	0x0ff866a1	0x61280e9b	0x65c5a63f	0x8b372073
+	0x7a4c88df	0xc74f7959	0x19597c51	0x97c8a27f
+	0x33eb652a	0xffd40c86	0x57a2ca0c	0xaabc6cc8
+	0x54fd2280	0xd5b59006	0x2e00f009	0x72bd86c4
+	0x24936e04	0x877188de	0x91b60401	0xb949b337
+	0xdab93e69	0xdffeab2e	0xb3aa7c79	0xb8612f31
+	0xf0c53b58	0x8896833f	0xda35944a	0x1867027a
+	0xef6bfce9	0x8213f320	0xac477eb2	0x92368362
+	0x606cfdc4	0x27c98907	0x50673ac5	0xec48f5f4
+	0x39e879f8	0x80d050c8	0x9febddbe	0x5d797725
+	0x06d8b755	0x0319d93d	0x7eae3ce5	0x8963ed64
+	0xc91772c9	0x4e031095	0x2fd03d3e	0xe774ea89
+	0x7dbc97ab	0xe8d8f361	0x6e167fa1	0xd1520c5a
+	0xb3278325	0x8acaf913	0x6ea81dd4	0x9e3b2a97
+	0x0a5b8a09	0x84000db1	0x59a30fa9	0xf0b6868d
+	0xfb62b0ed	0x8953057f	0xdbbca3c0	0xc103b876
+	0x47420e14	0x1eb22bed	0x58c8f65e	0x3a689da6
+	0x8ed1a99c	0x869ddc49	0x60015d09	0x2264c797
+	0xdc10c6ac	0x7275327e	0x8d47d2ab	0x87a75624
+	0x3dd8fcb6	0x40e67a31	0x98114b1f	0x7e3a5976
+	0x1d9e62a6	0x988c0398	0x0c7c0d8d	0x0aad4954
+	0x3c40a234	0x7b752b7b	0x79f94813	0xa0b86dec
+	0xe3f646ac	0xa993f76a	0x6f9d1f99	0xe883dabf
+	0xb8ab1b2d	0x6766ac8d	0x6b9a793a	0x02f55fa5
+	0x351a96ad	0xd190f768	0x35667fe0	0x6a85c938
+	0x72444e33	0x5140a848	0xd3062250	0xe4ce902a
+	0x44e7d9d3	0x7c8d48fe	0x4d26a61d	0xbd013c4b
+	0x540d32bb	0x9152cafd	0x09840a30	0xd7a8663a
+	0xd5a3ca17	0xfd5dbe65	0x655b226f	0x7cb9debc
+	0x59d300dd	0x13737132	0xdf0d004f	0xe98bbd9e
+	0x5626fb54	0xb6d66fbd	0x273087a8	0x032969ea
+	0xbd69c191	0x010cdfff	0xb2a9cea5	0xb8778e4c
+	0x8f0dd084	0xc75b4ce6	0x9c027c6f	0x36c58105
+	0xac424eb8	0xa15d2883	0x9e73b7b8	0x54e9aade
+	0xb9500a5a	0x97505e35	0x4c59b36c	0xb3ad1302
+	0x31e21ed1	0x78bcd74e	0x2d9fc122	0x49bae35e
+	0x5c8f01c0	0x8d29829c	0x0c672566	0x37938db5
+	0x4959e71f	0x0d2365bf	0xaab666b9	0x52b2cffc
+	0x200ee1f5	0x5dbb262b	0x9aae28df	0x3223780a
+	0xb65218cd	0x633b797d	0x93f42423	0x3268b3ae
+	0x141e506e	0xb1ed94b2	0x497b7973	0x9f2db9f6
+	0x5260bf9d	0xb30e4310	0x4a3539ec	0x275d2ae2
+	0xff43e500	0x645e30e5	0xf1527598	0xb76ec4cf
+	0x88fc44e9	0xde68932c	0xe61aff6b	0x19d042b6
+	0x11981ff8	0xb0d595d9	0x52764f82	0x7e0ca214
+	0x8cc51237	0x581f2a1a	0x482420b3	0xd47ff971
+	0xcff78344	0xc019eca7	0x3146ab02	0x107a3ee4
+	0x16dc120d	0x33a239ec	0x0ea84236	0xebc7a1f4
+	0xd1f2fa2a	0x9464c008	0x2b76a4fd	0x9b4acb99
+	0x00f6a92a	0xd68b8d15	0x25e1e58d	0xe1fe3cd1
+	0x6fbce2cd	0xf78be2dd	0x09b9c08d	0x6b32d210
+	0xd06e7c95	0xd62f47f4	0x92c717ca	0x44fe3d2d
+	0xaa13cc08	0x3d411f94	0xc2eba262	0x7521c9e4
+	0x77d6cdc7	0x22d76158	0xca2efacf	0x3e51004c
+	0xef9a82d6	0x1508d20c	0x923f18ff	0x3eaa88e6
+	0xf2f32bc7	0xe74b8483	0x82529884	0x58b38ad8
+	0xdd9f2a5f	0xdf54adc3	0xd4497667	0x789c000b
+	0x935d1743	0xa52d5f1a	0x4e27adf6	0x5c3334af
+	0x6cf71ba0	0x501f8353	0x031fd6cd	0x4831ec4f
+	0x08c847db	0x6a6e0657	0x0bd803d4	0xd7c48cfe
+	0x94b7e25f	0xc6516ebe	0x1001c08a	0x0e165da9
+	0x4e39605f	0xe3f3637a	0x013daae9	0x217168b0
+	0x6013ab5f	0xd5b7eb97	0x8ce6b6ef	0xc4259f29
+	0x470e90a9	0x7a254ff5	0x8dcbf841	0xa2541a7f
+	0x4880c5ea	0x28c750ea	0x043a0200	0xbeb9653c
+	0x46e354d1	0x64f7104e	0x05a64bf3	0x7db42752
+	0xbbd38c7b	0xca7da1d9	0x916c7ebf	0x1df5e3e1
+	0xef0897f5	0xd0456a5c	0x629b50a3	0x8caefdc3
+	0xddbf8b94	0xf6e6b341	0xd8ce3e02	0x27c96419
+	0xb2659ab5	0xe8d576df	0x9f136353	0x6f5230f5
+	0x68417adc	0x39b65378	0x4b742f21	0x96d071b1
+	0xeb046da9	0x245ecb46	0xc17eeec3	0xd7c56615
+	0x07df9b8c	0x647ee4f4	0xf15f7e7b	0x825b87eb
+	0xdc67dd20	0x43c38867	0x977868ca	0x3a299ef2
+	0xa75073f7	0x2dcd59e6	0xc6c78c75	0x63a00767
+	0x74dfba2d	0x7880c7da	0x83f72bc6	0xa9750166
+	0x716b3abe	0xc949a1ea	0x7e5fc036	0x574ee475
+	0x39c3cae9	0x8c1dacdb	0x640fcc41	0xc69437e8
+	0x5d33a950	0xa28e483a	0x4031cf9b	0x0007e3be
+	0x6e3f277f	0xe25d3025	0xdcbc4a0a	0x7451a537
+	0xb372169f	0x21ff0e91	0x1978aa74	0x6471624e
+	0x01a03f20	0xeb391a3c	0x70d18ad5	0x47c9ddcf
+	0xd9415b2f	0xd9ea29ce	0xffa0677e	0xeff7a04d
+	0x1d384ff4	0x66195704	0x22736810	0xad754f27
+	0x782ae9bb	0xffed05b6	0x5ae3f21d	0x5eb2c577
+	0x0101cf91	0xed0322ad	0x56ac50c8	0xc513b1c6
+	0x4f62ba8b	0xbaffd6b6	0x6649baa2	0x8702464e
+	0x78947007	0xd6e97d6e	0xde7c6abf	0x2bdee498
+	0xcee1db1a	0xb98149de	0x47f32f5c	0xc6c354fc
+	0x6e148fad	0xb343cf2f	0xeac6a9f0	0x33dd1560
+	0x923403bb	0x87d6e292	0x0b1cf653	0xe8b76402
+	0x5f21a955	0x236dec28	0x214663fd	0x1917539e
+	0x3f11ce80	0x1bb35a2c	0x38a358f1	0x15f67224
+	0xc65394f9	0x63cd4887	0xe8e73d2b	0x51b6204a
+	0x8eeae8f5	0x6e071c8f	0x55c23dca	0x4862eaee
+	0x0afa0037	0xc98446f3	0x09181a1c	0x41e46e02
+	0xcf13d6b9	0x85907776	0x30116b18	0x27b8c7b1
+	0xd153a5ce	0xc95c90b2	0x34392718	0x8103dbe4
+	0xe012a7be	0x6aeb8c6a	0x5bbaddbe	0x221eab21
+	0xaf769239	0x2621a689	0xe8c41061	0x5890f76b
+	0x2c4dadd4	0x2ad2e669	0x394209b5	0xb272b2ef
+	0x560031cb	0x4ab7be9c	0xcc5e92e4	0xc0de0667
+	0x7a39cf63	0x03482c6e	0xd653de11	0xe14466e1
+	0xf2dbaf25	0xc34d1c0c	0x03eeb3e3	0x8260874f
+	0xf6e2ef37	0x13626fba	0x15b7efe4	0x069cd153
+	0xbf631788	0x797668a9	0x724d831a	0x0ceeb589
+	0x9559cd31	0xb995d2d2	0x7564c4ef	0xfc45a3dc
+	0x1cd999e3	0xbe090229	0xab4f9383	0x879156a0
+	0x06e1d37b	0x3796487a	0xaf1e3884	0x1f9a59ef
+	0x6c2d8a7b	0x0a8a5ffc	0x4cd60f03	0xa60bfc63
+	0xf67c6872	0xf19b75cf	0x041cc864	0xc563566f
+	0x58ae88a0	0x3747b0c1	0x64cd86fa	0xed185c5a
+	0xb71533c9	0xf15672fa	0x2722d209	0xb71ec7d7
+	0x3143a8a5	0x61c18934	0x3a899ec5	0x4274f336
+	0xea7c52a9	0x9193cd11	0x44c471e7	0x57fff360
+	0x53923783	0x76d57ce6	0xbff32513	0x4dbe0d39
+	0xb9f80483	0x62ce4d25	0x5941e9fb	0x7dfedfe1
+	0xa33f9130	0x336e6539	0x1de31e79	0xb6855a41
+	0x4db2db67	0x02a9f1ed	0x019bcf20	0x53ad0ce3
+	0x4d049f95	0xa9de2c6f	0xa26f6997	0x28eafacb
+	0xa5220548	0xb4675e1b	0xe776ee88	0xc93e6c37
+	0x7868630d	0x1690625e	0x6eba0fd4	0x78f598ff
+	0x113fa1b7	0xcb025590	0x2ee34123	0x92241df5
+	0x6edbf0b2	0x3bc2e0a7	0x710ce59f	0x656f0eb7
+	0xa598424e	0xeca53268	0xb6a44542	0x5bf6674f
+	0xad483960	0x35290b93	0xfba74c81	0x78141ea2
+	0xd6baf9e7	0x8e5a08e6	0x4910c5b0	0x7b140d21
+	0x1958c79e	0x0dbed125	0xcfbe41dc	0x089fc4ab
+	0xbf014fa7	0xff961610	0x7a2ae6c3	0x560d3a9c
+	0x2cd77620	0x3a7c15cb	0x9464d8f1	0x249a93ff
+	0x96fe6c56	0x7231a31c	0x4bcdadd7	0x62edd9f4
+	0x8ad1916c	0x3a5fbc8d	0x2a2ccd7a	0x558980b1
+	0xb0137cfa	0x3cae6929	0x587c349c	0xbcfee701
+	0xbddd49df	0xa0da6dbe	0x4cb03dac	0x5f84ba2d
+	0x7fb3063c	0x66de2150	0xbf7dbcf2	0x1c0892aa
+	0x4be8b0ae	0x5d9845ab	0xa21455af	0xc42f2e68
+	0x9b6f438f	0x5eaf4941	0xabbf9079	0x94984a47
+	0x542bdea4	0x34cf3d67	0x854010a4	0xf39a9b19
+	0xd25ffb6a	0x04364e75	0x0af97ef8	0xe10e3620
+	0x2184d002	0x0c0ca683	0xc19963c6	0x4c428d15
+	0x47ae4151	0xd11ea57c	0x437a9ed6	0x50a6b8a2
+	0x141b16e9	0xeb4ae873	0xb51180fa	0xe3dc318d
+	0x7744a06f	0x64d297d2	0x845fac66	0x5854d172
+	0xc14dbe9d	0xccba053f	0x4620a715	0x405d728f
+	0x28b86cec	0xcba09cdc	0x92823f94	0xeae2664c
+	0x48eda6ae	0x4b60f5f6	0x1772f309	0x8af285bf
+	0x9c3ae474	0x13149ebf	0x2bc835c2	0xafcaa560
+	0xc11b6f91	0x94861d9a	0x089c0d82	0x1e04d66d
+	0xf0e497fb	0x6b2d8b6a	0x9d7f0cae	0x4a93ba71
+	0x1c006123	0xed4b5f75	0x76e7826d	0x4f884ba9
+	0xbba28011	0x1e275278	0xfa72461d	0x7e70e215
+	0x1427ba3c	0x467e4f3c	0x781c5f92	0x357b7951
+	0x9de2cce4	0x524a0de6	0x12e15f95	0x7b64fae0
+	0xf27e93cf	0xc6f48158	0x9b71dbd6	0x081dc1b3
+	0x47c9c2c8	0xf110add7	0x7881b556	0x0404bf1c
+	0x58e7d936	0x04442173	0xe1e7f0cc	0x128ce897
+	0x169c0a11	0xf30b5575	0xf2ac0bab	0x91515620
+	0xe8b809b0	0x2a73d5a0	0x9ed32dae	0xcf943a47
+	0xfc157bf9	0x1a53054d	0xf0657e2f	0xf39f6ea7
+	0x92a5834a	0xcdca0c13	0x40a7b40e	0xba0e0cdd
+	0x72f595c3	0x6b7eeaf3	0x4d0fd8ed	0x9a856082
+	0xd75402c8	0xe0f8d3b9	0xee57a2a5	0xe1ccf4a7
+	0xa4fc4fa6	0x9f2407c7	0x75f94c0e	0xbf2361de
+	0x2d3b4782	0x72c35e50	0xb97f7d4e	0xbc880223
+	0xb0b24073	0x08931201	0x40e0d18b	0x559db40c
+	0x6216a921	0x031a379c	0x29bff1ac	0x1c522c12
+	0x583bfe94	0x2519ba2a	0xd691d08e	0x905dc62f
+	0x43b421b0	0xd45caaa0	0x5f099da2	0x012fc4a5
+	0x509712b3	0x67e5d441	0xc843de50	0x7e1c756f
+	0x91368900	0xc6ec0dd4	0xa41e838f	0x58eabda5
+	0xd6ad78a9	0xa037b655	0x8af4e767	0xa9b95900
+	0xdcf1780e	0x64e28d82	0x215ad981	0x292dfcc3
+	0x708d8557	0x0a507562	0x486022ad	0x8165bc7e
+	0xabffce1d	0x78fbe480	0x77b916f6	0x88f8167d
+	0xae8b8edb	0x62698ab6	0xdbc6bbbd	0x001819a6
+	0x8c096fb3	0x40a121e9	0x7b96a718	0xf6d256ed
+	0xe5c0a484	0xa09bd764	0x6552b5a2	0x1847ae3f
+	0x0669a650	0xccabc209	0x85246d20	0x61158f3c
+	0x379d8086	0x02135988	0x1eccc6db	0xf8f38c67
+	0x8e1b0f3d	0x0f6e87e5	0x936bbb84	0xe04839eb
+	0xe26b3e5c	0x3f35ffda	0x4920e752	0x014c876a
+	0x25189061	0xbe2bc4ec	0xbb2ca0f2	0xe2c1c9b0
+	0x747df643	0x26da8dbd	0xdacc3c8a	0x7d93b22a
+	0x922d9a0a	0xf82d65b6	0xd56e5f35	0x7aea7534
+	0xf1808648	0xdfa7ec9a	0xff00f8c6	0x69091da7
+	0xbb478c83	0x64e24ae6	0xf2371faf	0xcff5732a
+	0x4da88e73	0x9c8494df	0x4c0da767	0x3e22bd67
+	0x059298eb	0x9d7611ce	0x74b4a198	0xbcbe440c
+	0xe2bb1a9f	0x0ba3e5f7	0x65a5cf9c	0x8b24b6f4
+	0x7784ca5c	0x24ffc234	0xece71bbd	0x36f8e876
+	0x1b55d68b	0x2b9163a5	0xaf8be424	0x958eeaef
+	0x5d711c41	0x66d11cbe	0xfce42868	0x4a3c819c
+	0xf66d295c	0x629402f7	0x64b2ee3d	0xc0b74538
+	0xe93a735d	0x3b9e807f	0xd1d0d7c8	0x69588f34
+	0xae92b6fe	0xf5508d03	0x45b6ccd6	0xf85a18c6
+	0xe1a28a53	0x438f9a35	0xf4fe84dd	0xe3f95791
+	0x16860340	0xefe72aee	0xb13575c6	0x3d730481
+	0x3cf2a43e	0xa6ed239e	0xd7529176	0x8ad63f3f
+	0x5efe8f4d	0xe9cad7df	0x44fefef4	0xc7198f50
+	0x85aabf5c	0x15c175c2	0x26f7a0cf	0xf06782f0
+	0x4dfadfa7	0xbc57a087	0x21406f0b	0x692a8f18
+	0xd17a358b	0x19d1b2a6	0x6c35022e	0x87d8c987
+	0xe7f2d06c	0x91c4daa6	0x4a132822	0x1e864671
+	0x5cbf0c4d	0x6a34f073	0x1c87a8e5	0xb38f1717
+	0x1cac430b	0xf733ee6e	0xdf73201f	0x71026328
+	0xee976531	0x661c9d28	0xdeefcd7f	0xdefb4607
+	0xfca9ef3a	0x3e1b9b38	0xd204c892	0x6b059f5f
+	0xd5b8665f	0x4eec24fd	0x09b21b40	0x364c708c
+	0xebe0d543	0xc3d64eed	0x8facb895	0x8f415f31
+	0x3dd25b0b	0x95f4072e	0x85e6f4c1	0x3345e2a5
+	0xa56e8dcf	0x3ed8df67	0xa8194a81	0xafe613c7
+	0x384b25b9	0xe7661836	0x5ad6476d	0xeb0ae982
+	0x19afdf2f	0x4efb8658	0xff07e358	0x96c469d2
+	0xf3030add	0xf5bf5b51	0xba03b24c	0xcb77143f
+	0x134fba20	0xa126558a	0x193cd220	0x48f43727
+	0x156f2b18	0x4e599917	0xc3ac4eac	0xcc460648
+	0x67974a2a	0xe2917a7a	0x02998a74	0x470c60d1
+	0xbacbc868	0xfef38d84	0x3e4597a9	0xa1723ab7
+	0x8ffed7b2	0xe489b151	0x34b982fa	0xf67bf8ce
+	0x043cbb33	0xe3927c98	0x3c8fb221	0xbff0644a
+	0x886d333c	0x1f4cd6b7	0xe9b744f0	0x443ef364
+	0x04847d65	0xf3c2ba04	0x60a8e656	0xab4dca06
+	0x620dbf22	0x5b0221e5	0x877973ab	0x128b5a6a
+	0x4696b5d7	0x8f034e85	0x18796215	0x8579ec7c
+	0xf8917eae	0xa98bffce	0xfc67e9de	0xa897445e
+	0x2f115777	0x990bfb90	0x1de53f71	0xfa2e5c1f
+	0x24a5b882	0x0f871a5b	0xe7fc33a0	0x6927a106
+	0xb210bc90	0x2ef851de	0x09629147	0x2553882d
+	0x77393353	0xeacf977e	0x470198f7	0xb7564a05
+	0x4d575fb4	0x1d980371	0x0feeebba	0x26ba3c12
+	0x17b21567	0xfb664d1d	0xcee1a603	0xa8881580
+	0x8a47e853	0x6511027f	0x734f6fd7	0x2977b345
+	0x7465e47c	0x0e3c4c8c	0x3185ac04	0x2450ea5d
+	0xa6e97dba	0xf52b2f4b	0x328ac24f	0x5a507ad2
+	0xac05d4f7	0xca332e1e	0x44b6cdd5	0xe22b049b
+	0x55b885d1	0x71144ba1	0xf57284d9	0x76cb0900
+	0x8266cfae	0x82bb0271	0xfe547080	0x53e4dac9
+	0x0546dcb9	0xa09a8de0	0xd55d15a9	0x7a3a96ad
+	0xd23c33ed	0x7a8fa769	0xa0542b10	0xdaf92f2c
+	0xd6433b0e	0xad7cf7b9	0x72c54814	0x38ff5c07
+	0xddee72d7	0x6c29582d	0xa1574da8	0x418272ea
+	0x0a9e21f3	0xa34bb5ea	0x1e78630b	0x9238d5d2
+	0x7cfa682f	0x6e8e841b	0xa4b3d17d	0x70b6d075
+	0x704db3f8	0x76aa7d19	0x1cd3e85b	0x2ae7fa63
+	0x5ff0dad0	0xdd92c129	0xce7d884a	0xa7ba03ab
+	0x3b366560	0xfeaf75c5	0xd08856c3	0x01ffbced
+	0x089aa8a3	0x2e4b36f1	0x03955648	0x882468ba
+	0x534abc87	0x28c08402	0xa7512f6a	0x1fab044e
+	0x6595e159	0x92fdef27	0xa0b6093a	0x5fdb5f3e
+	0xd0facb7d	0x512a8b83	0xd7f31adc	0x82166318
+	0xf9ad7f02	0x9120b349	0xab744947	0x2787d6bf
+	0x489e3546	0x02a7ce3b	0xd3812409	0x819a092d
+	0x94a48db8	0x49d8dff3	0xdd4e9b5f	0x330d32d0
+	0x203cad0d	0xace20075	0xfd019f42	0x1cc56871
+	0xe53e452b	0x51e7c9e6	0x1d6732c7	0x03694ca7
+	0x900ecdb4	0x3251d119	0x2c4a0669	0x3243bb5e
+	0xb434326f	0xd6eb26b8	0x8ceb7328	0xff30d7e3
+	0x861fa43d	0x15386557	0x3fa11d24	0x86590299
+	0xc3cbd319	0x8d1031a5	0x80db9f63	0x9d957321
+	0xdec927f4	0x1468a2a1	0xff1b8842	0x4c403eed
+	0x62140459	0x912ddd25	0x36252404	0x49052d26
+	0x22205558	0x53773ca0	0x3428d400	0x51002834
+	0x6b5baa18	0x838bcf14	0x30d09ce0	0xf1c456bd
+	0xb1fc90c1	0x525dbb0f	0x64a9105e	0xe0a5cc89
+	0x293f2441	0x335b1c7d	0x55842eff	0x6c7f60dc
+	0x903fd793	0x868589ef	0x50a596a6	0x337c6988
+	0xb7a670a9	0xa46b1a8d	0xdf8c013c	0x3dcdfd02
+	0x01075847	0x06c3a7e6	0xc8f22594	0xfcd94f04
+	0x8b6ddbbb	0x5a138f6a	0xf43d2cca	0xcf4df232
+	0x088cddf4	0x9adce26d	0xee803f2c	0xedf042d5
+	0x7d738c39	0x8f02cc34	0x3f964043	0xbfae17d7
+	0x5f2dd670	0x177a9f36	0xf0e1dc28	0x07082ed9
+	0x90534419	0xf03db66a	0xb8ccbbbf	0x739d2ae4
+	0x3509b32d	0xf0105125	0x2d603572	0xbd1a6b64
+	0x50959fe9	0x26100668	0x758e250c	0x9b372d1b
+	0x0f1e1bde	0xd53edd46	0x0187d6e6	0xd0158da6
+	0x05dd0922	0x3fc0a182	0xd7f70ebd	0xeeda22e1
+	0x1c7f99ad	0x9b39bee9	0xf101d67c	0x1ffea21d
+	0x5494b799	0x787a77ca	0xe8908c34	0xdd00d1db
+	0x25e21bcc	0x30bf0b70	0xd8cd0350	0x96f2d414
+	0xa9a4cb6d	0xa3f3c207	0x2db5c7bf	0x88e8837b
+	0xb157189a	0xb9fb869e	0x48c2a7b3	0xf5e0c692
+	0xf9103c12	0x6c590e9a	0x7e0aac34	0x97392b87
+	0x8e6c201b	0xc6d68ddb	0xb5fbaf0a	0x1f8e411f
+	0x6355e9d9	0x05fcca55	0x9b0250dc	0xec9c5d7d
+	0x668075bd	0xb93078f1	0xcefa1755	0x216c5e0c
+	0xa83ae6b5	0x748bff79	0xfee9e797	0xc6acb230
+	0x1243bc06	0xfee350e0	0x3ee5f8e0	0x0508fb60
+	0x87d9d24d	0x0b54ac94	0xfc37c8fc	0xe9958f2f
+	0x3a927f73	0x04933b6a	0xa195a6dd	0xda96dca3
+	0x9c1799c4	0xd055fc63	0x05deebbd	0x2b5400fb
+	0xf157f110	0x80b1e79a	0xd7f1e4b7	0x5a1fab0d
+	0xbaaa81c3	0xa42489e8	0x594a791a	0x29f18382
+	0xe86f0358	0x5aa5f4b0	0xa682993b	0xedbfc5b7
+	0xf1eac55d	0x9b1716bc	0x907d9d1e	0xb2205254
+	0x4fbba0f3	0xacea63a4	0xc518d83b	0x8449fef8
+	0x80b4f69b	0x95dc7429	0x16c22c9b	0x6e116239
+	0x4c4bfd11	0x56f159fa	0x60cbb0a5	0xa2f4721f
+	0xa829cf9b	0x5ddbb3af	0x2db824cf	0xe82f3fd1
+	0xe5dcb2db	0x185fe7af	0x0775003d	0x38669aba
+	0x7b540eea	0x94ce3d10	0xba77f357	0x63507853
+	0xb50ebb0c	0xb614739b	0xea3a3c47	0xf2b6176a
+	0xf805b28d	0xdd0819b7	0x9f4b2799	0x18bdadb8
+	0x7d58d588	0xc4f0994a	0xef834870	0xef2d6ce4
+	0x97a36a52	0xb6e581e6	0xddd9aa9b	0x6437d4e8
+	0x43f74dc5	0x8cbbd744	0xf394a2a0	0x4a1e7f75
+	0x395bd36f	0x27a8f9e9	0xed62f4a5	0x7c2f0484
+	0xf394f837	0x5f69d50e	0x86ef57af	0x7af052f0
+	0x85dee180	0x125f56fa	0x87291494	0x141931ac
+	0xabca9ae0	0xbc1e4e4d	0x541e2edf	0xa3551bb4
+	0xed2766fd	0xf6e778c2	0x3a82644f	0x67c47659
+	0xb81b826c	0xb11603ee	0xba6cc507	0x691fdb74
+	0x06507f6e	0x64ef2a0f	0xebd9b51d	0xee620487
+	0x82991d7c	0x1493fed5	0x08af819e	0x7066de45
+	0xdeee1600	0xde12b903	0xe572ced5	0x81b897be
+	0x458d0db8	0xc9970232	0x7402dd05	0x44e1c70c
+	0x1619441f	0x9ea0c392	0x1d13c3dc	0x34737cbb
+	0xe1d726e1	0xbe7d749d	0x304892a5	0x71c7bb33
+	0x608bb696	0xd334cfd7	0x862e360e	0x868757ad
+	0xb7d8aa70	0x81031f5e	0xdb64b80c	0x954ff4c1
+	0x5c66d432	0x08c77a67	0xd5e298af	0xb6074be1
+	0xd687a163	0xac2fd525	0x14e6ab5a	0x6ca4232d
+	0x8a921092	0x0a19e936	0xd4464ee4	0x0da28777
+	0x6b6d4131	0x975111bc	0x3f26afae	0x5a6faf38
+	0x867d7956	0x554aa8be	0xf9898211	0x3afcde65
+	0x493dac6c	0x61d901b2	0xbaf3e9fe	0x2a3758fa
+	0xc2ad3ee4	0x97d13dad	0xe84b02f9	0xaaf5ca63
+	0x41a94864	0x6d7b71be	0xd843e866	0x83c3193b
+	0x972d4bbf	0x55c3a234	0x0d03b540	0x53396a64
+	0x98b5c0f3	0x36708484	0x38363c7a	0x0076dbf8
+	0x5edbd01a	0xf6e835d6	0xccb95e4f	0x2bd2907e
+	0x210f9312	0xf4ec9221	0x343697d6	0x3913cd41
+	0xb02ced20	0xba991ee5	0x09c7893c	0x749da3c0
+	0x46e5ad3b	0x871b685d	0x02358659	0xca76706d
+	0xe61524a2	0xf46ac4a9	0x4f6c9e19	0x68a86d0c
+	0x9d16bc4f	0xa9157a1f	0x830993b8	0x3738896c
+	0x7c821db5	0x02de8542	0xb17e3767	0x455a0b40
+	0x19b707eb	0xed81e63d	0x568e1e36	0xbf5cee00
+	0xaa12957f	0x67f65ecd	0xb940789c	0x0ab3bab8
+	0xd7e3a789	0x777b64ba	0x4e00d3be	0x46887a34
+	0x08f0127f	0xf5027e8f	0x9cdb4671	0xb7a7eac4
+	0x9be5cfb5	0xb1f57dbd	0xbce97b11	0x41525f56
+	0x5e847d16	0xf71585b3	0x1ce5047b	0x1bc2fa00
+	0x860aa4ca	0xf97ee77d	0xe7843ee6	0xf07bd865
+	0xfa059452	0x58a59ce9	0x24f03b1b	0xd18a52c2
+	0x180426ab	0x2ced0003	0x399234cd	0xe43f91e9
+	0xa0516a92	0x8088d598	0xc3a41365	0xd1f044ef
+	0xfb3808f9	0x1770e594	0xf96c4185	0xc6b67b9f
+	0x5c01c703	0x65c6ef8d	0xd49310f3	0x0f962bd1
+	0xfb3c96f1	0x4d501516	0xa09beeb5	0xce9df639
+	0xf792c71f	0x392b420d	0xc03c9099	0xcab5dc42
+	0xbdfea308	0x84c80c32	0xcd66ec3f	0x68932191
+	0x62b69b08	0xcacb4a8b	0x0415feff	0x84673edf
+	0xe61b5ff3	0x6107a18e	0x6a7a206b	0xed64aa34
+	0x1bbaef36	0x22a3f0fa	0xb0945c72	0xd1a7f7f8
+	0x65fd1b29	0xa34d99a9	0xb6f2ea53	0x055ab055
+	0x433c3eb2	0xe591d68b	0xcabb8a71	0xfb055c2e
+	0x37e1efec	0x558fd45e	0xa5358766	0xe0c450f3
+	0x78ed3061	0x8713e084	0x4b0d2ec4	0x24feb10e
+	0x6689fc4e	0x0c83f1c9	0x7490df57	0x00d618bc
+	0x2c510caa	0xc5e2838a	0xcfae6669	0xdc2fa4b0
+	0xa4569e3e	0xcee095c4	0xcb5f42ee	0xdc11393f
+	0x69f1c5aa	0xa495fae6	0x64c53ea4	0x4477aeb8
+	0x2ff43cef	0x660aa186	0x5dec9e67	0xa59f6aab
+	0x51504061	0x28279b5a	0x4e245278	0xdbf53c73
+	0x01a77ff9	0x7d771730	0xa8d19fc6	0xce3697dd
+	0xecc405d8	0x22f1872a	0x683afa3f	0x725f7e03
+	0x14c7acb2	0x845efb20	0xf3e03095	0x8c9a7d04
+	0xa9f115d3	0xb93fa8ef	0xd2e78a32	0x91e3cc61
+	0x805d48de	0xc9fcc672	0x225d36f0	0xb32e7627
+	0x11b7a585	0xa7321798	0x9b40640f	0x0c3a6b7f
+	0x3337c762	0xbbe54bb3	0xc8316a84	0x0d487a67
+	0xa6d6b86b	0xd1fb2b92	0x15805dfe	0x5cd49b21
+	0x9855f2c2	0x74e2a195	0xbdc0729f	0x29f680a9
+	0x092f47ad	0x0e7091d1	0x6e7d2020	0x0a7b5d47
+	0xc9c4065b	0xc4cacd97	0xcd7b4071	0x7986cc7a
+	0xb1c29ef5	0x47ced57d	0xc08a8b40	0x12102685
+	0x685caae1	0x1ebf3635	0xdfe6af15	0x8a0496f4
+	0xb9c07f19	0x1f62a68f	0x0133de0a	0x993017d9
+	0xd0553b5c	0x0c8f1311	0x7d979028	0x6001db26
+	0x1caf7ffd	0x76ced0cf	0xc33d3f23	0x9fc27423
+	0x235fc137	0xf85a079b	0x78174474	0x1d15b725
+	0x20162abf	0x62e0712d	0xa03f9cf0	0x0f4ff140
+	0xaa389d0d	0xd58e1171	0x8f5d21f4	0x3ad5b3c4
+	0x03003b51	0x49b29d4f	0xa3d82796	0x9c7f3391
+	0xe34de3a8	0xab75e6f4	0x3f06b52d	0xb8092f83
+	0x01f14341	0x929a3b8a	0xa630aa03	0x4b7e055e
+	0x90b06e58	0xeaf2ad79	0xe8c5b756	0xf46f44e3
+	0x6693ff09	0x499d2790	0xd0d81c69	0x72d7a2bd
+	0x794d242b	0x9be19084	0xddd51a72	0xf4f60698
+	0xd1747d6a	0x24dc87dd	0x78ba7af6	0x548b43d0
+	0xa2b03ee8	0x100ef53b	0xe836488a	0xf4b9a443
+	0x41d61bdc	0xee4bedb1	0x8f0ec0b0	0xc0125983
+	0xaa919a7f	0x6677db37	0x78e7d366	0xc7bef834
+	0x967a54e7	0x5f78951a	0xc0fddf1f	0xbd5cf29a
+	0x3fa13be8	0xca67a695	0xc13e8c23	0xaff54342
+	0x94f4bc22	0x85512c06	0x1439cd71	0x7d13b7b5
+	0x76f8bd59	0xffe02871	0xbd88ccb1	0x2597d721
+	0x80a52e2e	0x1f696120	0x689e73aa	0x7d085fa0
+	0x0e183650	0xe041d3fb	0x5a340dd0	0x26a6c10c
+	0xe6fef6d0	0xdb18b3b8	0x2fc6df63	0xfa695c57
+	0xfb3e6a3a	0x64fb412f	0xc1cf1e32	0x6edd945f
+	0xcee44d66	0xdfb2ec8c	0x5eb84515	0x177f031b
+	0x56a9db8a	0x0e247577	0x99004862	0xa5805854
+	0x04b1afc9	0x9c649998	0x908a1424	0xb595099b
+	0xb91fb0ce	0x8c4bdd8a	0x78de806e	0x65ff3cba
+	0xb66aeda0	0xe22d3592	0x7c0cdebf	0xc15c0853
+	0x80f31d27	0x84dfc7ed	0xc96a5992	0x939b3d6c
+	0xf0ffac53	0xe4be269e	0x4d56d528	0xb0477318
+	0x40a4b528	0xd938f1bb	0x2b25a6c2	0xc93b3c9f
+	0x179c9571	0x999c2e91	0xe7280616	0xee6e0481
+	0xc30eae2a	0x7d6f0458	0x0b7a52ff	0xd44e0a23
+	0x81d661ee	0x9d0f857b	0xe7fa9d18	0xd499cb85
+	0x4e27e30a	0xd51d1f9a	0x14195d32	0xccca7d6e
+	0xc1703a6e	0x15664170	0x7f51c821	0xf1363619
+	0x37dc27f5	0x6aea6223	0xd574e44c	0x4b683223
+	0x4135ad1a	0x7694390a	0x0bf4bddf	0x9522f11b
+	0xc20797be	0x45fb151e	0x96f2a952	0xedfd5f2c
+	0xdfbcac7f	0x58f5dba6	0x68204d0d	0x52eeb34a
+	0x8313fd8b	0xda2f1243	0x195a1479	0x19bb2970
+	0x1c2131e5	0x6841c28c	0x1ec33cfd	0xd3e489de
+	0xd9b70b18	0x81503d32	0x9642a53e	0x02470015
+	0xb8d1087f	0x4b629e77	0xd7ec9ee0	0x795ffd91
+	0xcfa71aeb	0x4bae649a	0x7f768123	0x69f501d5
+	0x56c19a0c	0x4bfaac57	0x90ea664a	0x4d428e1a
+	0xaee71c90	0x198fc316	0x549f5572	0x07a22e58
+	0xe8f444e3	0xedc7fc23	0xe96c1595	0xc4bdad06
+	0x751a3df5	0x3bc4fba4	0x58cd19b3	0x3665000a
+	0xe4371d96	0x6c50d4e6	0x5d1d6a57	0xf130eabf
+	0x48fd82ad	0x42a8bee8	0x71f89c32	0x95fba6dc
+	0x9150b601	0x72c361b0	0x71a3c317	0x149614f9
+	0x224e67fa	0xf6a3fea9	0x5461cefa	0x367bc566
+	0x2226ee83	0xaa13e83f	0x8d7dc705	0x417c7afd
+	0x8a0f2e17	0xbb4003df	0xd1c27124	0xaaaede8d
+	0xd4ed5bcd	0xd0102aa8	0x3b519bfa	0xb82d6932
+	0x50b8f966	0xec685a1d	0xffb18b64	0x538955b2
+	0xac4b6cf1	0x0a86d32f	0x34e4cc05	0x02adcf17
+	0x7c80379f	0xcfb5bcb5	0x842190e7	0x8348cd1f
+	0xabf77742	0x3332866f	0xa56fb2e6	0x6c1fec47
+	0xf2fbb22c	0x7230d805	0xed17d8f5	0x3426e157
+	0x1d045cb2	0x6c1e349f	0x3a6116ca	0x4baf0bdb
+	0xab68daad	0xc4867466	0x7bb15fd9	0x707a6a1a
+	0x83157678	0x277cffd1	0x8d48e5d2	0xf829bd6d
+	0x1fd2750e	0xb6bb8854	0x66d0a20a	0x38f47b92
+	0xa3568b90	0x0d091e16	0x65a8245b	0x238e4299
+	0xd0bc6bbe	0x8ef67730	0xf976b632	0x326d9d24
+	0x96833335	0x1d475e95	0x1f8f41b6	0x65c9dabe
+	0x2133b931	0x43be592d	0xb887160c	0xf21fbfce
+	0xd83ca306	0xa0fb3fe7	0x7da09bf9	0x3f464aa6
+	0x37a7e40a	0xbb0c85bc	0xb172ff01	0xee62de6f
+	0x59d2d646	0x4262e938	0xcd96f5e3	0x0c1862cc
+	0x438388c7	0x9f45d4b2	0xc65ab0b0	0xd24a381c
+	0x1d6c6767	0xedaa1ae2	0xa93eaec0	0x662d776b
+	0x192a88c9	0x6c9d860d	0x61106181	0x30027db0
+	0xa5ae7b76	0x73fc43da	0xd77472b0	0xf4ceba3d
+	0x7cd642c6	0x903dd266	0xe33f58e9	0xbd088621
+	0x8e4c2c12	0xd8c4288e	0x24fdbb22	0xf72ee1f9
+	0xf291bd7e	0x94e68382	0xbbdd9240	0xb59602de
+	0x1b59afd0	0xe5417cf5	0x20bbb538	0xe28fdee3
+	0x0bb16920	0x77d6712a	0x1a0ae5f6	0x0156c43e
+	0x976b53c4	0xef856d7b	0x5a974cfe	0xec53404b
+	0xc627c557	0x3318542a	0x8fd883e6	0x508562b3
+	0xe0ab7501	0x9ae57262	0x95611b5e	0x50c699fd
+	0x984bb8ab	0x5983ed68	0x9947a7c5	0xc0d2374a
+	0xe0845ab6	0x9ffec0fe	0x41873bf5	0xc85c1a4c
+	0x7ef2b12d	0x9e1a3857	0x444da53d	0xb8947919
+	0x84c8588c	0x268f34e3	0x1974cf3d	0xfa67e03f
+	0xc4478570	0xc1896f5c	0xf86de14a	0x9d27ddb7
+	0x5da1c695	0x73c74ab7	0x9123a47b	0x1c9d9563
+	0x7b96bb9f	0x98d20464	0x1f46fd8d	0x4bc35857
+	0xc221a75f	0x04b24c86	0xbe1c7271	0x21a7b19a
+	0x9e050b54	0x8d93d0fb	0x98d7b55b	0xe5fe9502
+	0x9471bff8	0xb3825934	0x5f22d5b2	0x47f4ae9c
+	0x62d7623f	0xfdeef9b6	0x38c64ff3	0x9268fd7b
+	0xa7cfd22e	0x80eeed4c	0xf80a4a3e	0xc9a7e4f4
+	0x6f334b52	0x48e932a5	0xef8720eb	0xb9e86512
+	0xc4183682	0x08142405	0x0a32902d	0x34503fb5
+	0x4c7f132b	0x8db9be38	0x82c20236	0x80a79fa5
+	0x9a31e682	0xca61dd2c	0x2e354b63	0x8d5a4750
+	0x7a838960	0x24dffeb5	0xc7d19837	0xebfbc508
+	0x82e8dbdb	0xe732eaf4	0x109470c1	0xb012af6e
+	0xe2ce17be	0x79db33be	0x281184f3	0xc813df9d
+	0x9e6a771f	0x4a81882c	0xda5baf2c	0xfecbbb6b
+	0x4621a151	0xf4cece92	0xfc230416	0x8d4e758e
+	0xf69c296c	0x9fa2490a	0xeaa56785	0x3075ed95
+	0x4c2ffe06	0x817caf32	0x5a72f33a	0xc6d99da3
+	0x2bbc3dde	0xade463f7	0xb74af1a3	0x738d809d
+	0xd244aeaa	0x7302a2db	0xcb6e9b1d	0xe297c027
+	0x15dbaff6	0xce99c273	0x2810eb0e	0xafbe1f09
+	0xd316d8ba	0x27b8af19	0xb66bdf45	0x3e3b5fbe
+	0x318a4f05	0x2ea7807b	0xed6d40a0	0x58ba8267
+	0x1d1c9d15	0x29af51cd	0x04a46683	0x4b759694
+	0x20ce21e6	0x19ef8036	0x141a8064	0xca36f583
+	0x6d47da5f	0x3a8f6b9a	0x70a99a79	0x03677150
+	0x0feb8c70	0xf3509842	0xf33b5dde	0xbef320a3
+	0x932f9512	0x87497bf0	0xf521a0c8	0xa813483b
+	0xcd6fae43	0xbb7e4dce	0xc7d039b3	0x2d1e6f8b
+	0x1b19cb9e	0x8341c193	0xeffde49d	0x4c40621b
+	0x19d60210	0x8846c540	0xea735ec0	0x0c995dbd
+	0x9aefe2f3	0xbd46f954	0x9b315f98	0x2819307e
+	0xebe2c1f5	0x05919533	0xa52921ee	0xa0bd6746
+	0xd754f5d1	0x39eb2ce6	0x8442d51e	0xb1f75159
+	0x1b617cd1	0x046fc90a	0x6452daca	0xe8d3e3e1
+	0x77406387	0xe3ffbfca	0x89387e91	0x7e348a53
+	0xa5bd3b60	0xc113e95f	0x2ad5a7c4	0x45c1f445
+	0x2a683930	0x3428246c	0x4b89cf6b	0x05e66b1a
+	0x571737eb	0x6e55a8e1	0xbc96ce28	0x24d501f3
+	0x242c8191	0xde8c9472	0xbff946e4	0x551b5759
+	0x411e3420	0x0f0b9299	0x44aaaf70	0xacf2f3df
+	0xe9c44a27	0x781ffdce	0xa39651a5	0xdb7b44a5
+	0xed0ec4d9	0xec17fca2	0xd3ccb15f	0x2b9bd010
+	0x0446a9ef	0x18df586c	0xe227ae08	0xbbaff527
+	0x7958fb15	0x03bfc823	0xc09b7b6b	0xce07b0b3
+	0x0161a359	0x8e21f733	0x8f8168bf	0xc1e2207e
+	0xf9f65e93	0x831b4ba8	0x4b3677f9	0xf8342d03
+	0x03c10268	0xd07233c1	0x0df67d97	0x72434732
+	0x059c7679	0x96526a88	0xb54f9440	0x19e7327f
+	0x6f7f52c1	0xb4b8d069	0xcc4681eb	0x26ea581b
+	0xc26fe16e	0x4073cc56	0x6d252a42	0x689fd0fd
+	0x5d93f1b3	0x070ad283	0xa07cb95b	0x6effe0d1
+	0xe303ed01	0xb8e9b3f4	0x0721647a	0x31f877c6
+	0x134518e5	0x08694d5a	0xb0e6ef3b	0xc7fdc67e
+	0x6111276e	0x45185e0a	0xe13cb5c7	0x7c6ec9e9
+	0xfdee9721	0xc1fb8bcc	0xe25a2bc1	0x075f717e
+	0xd37b7698	0xa9cbfeae	0x6b7d0a28	0x1f1c8bdf
+	0x35d0e6b2	0x8b988b79	0x54f02ea3	0x3426ae01
+	0x5e402b08	0x840d3b8e	0x221527ff	0x906a86f8
+	0x411ce6dc	0xe4b3056e	0x26c9ed04	0xf3d8bc97
+	0x3b02cf67	0x11309c45	0x06ea08bd	0x1c698922
+	0x04e1e492	0x06e0c39d	0xed2937ab	0x83f1911b
+	0x25a94599	0x75d365f0	0x98f191e9	0x845f5e0f
+	0x49547aa4	0x42a0ae2e	0xb7e77fb7	0xe132bfb9
+	0x1cc087a2	0xb0435a85	0x4818ee36	0x4cd90b16
+	0xf56d5e22	0xdc49137b	0xb5f16e70	0x8f8ac784
+	0x84b020c7	0x83c26ace	0x090b3489	0xde14f529
+	0x6ee716ba	0x9deabba1	0x2c230ded	0xd6a68037
+	0xe626043f	0x33431885	0xd26423e7	0xcf259f47
+	0x335dfa6d	0xf052f836	0xcadf2fa5	0x6f2125d9
+	0xafbb23bf	0x19ec69ba	0x84d10bad	0x8cd3ebd5
+	0x36f0fbb1	0xbc1cbfbe	0x96c56812	0x0b05c939
+	0xbd79989d	0xffe74b98	0x6f99405a	0x9f10b14c
+	0x9d8efef4	0x299d21b5	0x9dd2df5a	0xc7ea511b
+	0xbdde106f	0xe5dc7d17	0xee136bc7	0xc4521b6b
+	0x823d31d0	0xcc3c32eb	0xb35ffb33	0x84dd8acd
+	0xe8ddf3d6	0x4611888c	0xfe469f52	0xf8e18215
+	0x768747f0	0x86379e46	0xd3cf9eb7	0x86f1e47d
+	0x30e68652	0x740203fe	0x1031b14e	0x96ce6827
+	0x45f57455	0xe41b7656	0xaa8496d3	0xb99701d0
+	0x485f88ed	0x1d064ef7	0xc7e3348e	0x110d938f
+	0x0c3c9604	0x786b0b35	0x2b2aa6ad	0xdcc45e0b
+	0xe9b29146	0xdbb00ed2	0x0527d574	0xc8029ff1
+	0x5699dfd0	0xd627ff70	0x285fb3d8	0xcf2e6b75
+	0xefad87da	0x4fa21893	0xa391388c	0x5760b28e
+	0x41a95b55	0x82001638	0x6f0e2d45	0xd30f70aa
+	0x5eca612f	0x946317f4	0x24c44ef7	0x470d26f2
+	0xf7e65ef4	0x3a831857	0x53c5699e	0x1af6ff3f
+	0x675b46c3	0x1bd5cfbb	0x03ab61be	0xa67a2b7b
+	0xbae16286	0xe1522d53	0x076d8ec2	0x3a603daa
+	0x0dbacfd9	0xd32acae8	0xe8a23399	0xdf3330bf
+	0xe990c05d	0xfe56bcc3	0x165f868a	0xdf42a220
+	0x6587e194	0x0a31eb94	0xa72a98fb	0x5512801d
+	0xc5fd9c69	0xf7210367	0xcc80f30c	0xc08755bc
+	0x3afe8202	0xc47d603e	0xd17d2990	0xa4addd73
+	0xce89fcc5	0x55726cbd	0xeeb77a64	0x628b3d1c
+	0x2297e332	0x6ecab8e4	0x9739c0d1	0xd53d619c
+	0xbf1a3371	0xe29ea297	0x140436d5	0xfa4802f8
+	0x1b277664	0x4f101407	0xde441685	0x1d36bbf4
+	0x057d9f25	0x7949dbc2	0x57686ffc	0x12984cb7
+	0x0721d76b	0x81ac7aac	0xeb40577c	0x43aaa8d4
+	0xb4e06e63	0x7054a526	0x18bced57	0xa37d26a0
+	0xac039a34	0x156e6d9f	0x07ae4487	0x0e59f4db
+	0x28aeb416	0xc1c4dafd	0xe0357fef	0x683adca7
+	0x93f2d62b	0x8f1f6ec6	0xd42fcbd8	0xfc4e3fad
+	0x082e4bbe	0x578bdbee	0x42dcda04	0x7684e947
+	0x20853da1	0x207dd044	0x56e372bb	0x5ef4c033
+	0x83353865	0xb3b42465	0xb80c9c79	0xffedbed0
+	0x09e45d5b	0x794fe5c7	0x498d4fbd	0xb1cd7a48
+	0xfc89b057	0xc1d19df8	0x9654d056	0xc94cd085
+	0xd7cb03b5	0x13a52c5b	0x52471fd3	0x990aaebe
+	0xe8bed6a7	0xa6960d01	0x68011da1	0x021bf151
+	0xaaa196f2	0x9e3b6188	0xbb28f2c5	0x559d3dd2
+	0xc38861b2	0xfd7242b1	0x716c29e2	0x270236a9
+	0xaaf33479	0x610a7d76	0xc0d564fc	0xf0bb1bd8
+	0x31fb232b	0xf19ebb3f	0xd62acd99	0x5e45578e
+	0x467c587f	0x0ac00140	0x9c7c1705	0x61a8a1ea
+	0x4c5e4e5d	0x0e0d846c	0xd199939c	0xb4c615ae
+	0x4cfe60cd	0x6b4e5cf4	0xe97ad9ec	0xf325a456
+	0x6ca45a64	0xb88b4506	0x9f751f49	0x1d66e330
+	0x59b40444	0x00f530b0	0x9242124d	0xac6de2f9
+	0x7b7e7a67	0x64962ed3	0xfd0825bc	0xbdbcc113
+	0x38d8d589	0x3cedb53e	0x17d95495	0x020b8ac2
+	0xe9aa9bdf	0x0a5a2820	0x64670635	0x91a2a89e
+	0x91bec6be	0xe9b4f902	0x1ef88ee7	0xec6e1208
+	0x149e39ca	0xb140ce3b	0x3210a2a7	0x8e489c45
+	0x59d3ebad	0x30275658	0xc20708d2	0xffdc3e00
+	0x96c700b8	0x3d03aea6	0xf0ce7ad3	0x232a5585
+	0xb0dc6620	0x1c1357b3	0xfb4c6d29	0xe5c5b7b7
+	0xc4bfe2aa	0x37f7ce13	0x433eb884	0x3dde220f
+	0xc1c34602	0xea700f6f	0x37b79490	0xad5761a3
+	0xfc5917b1	0x22f7e1be	0xa90566d8	0x89e9db15
+	0xf91bfa1f	0xdad2260c	0x93eba86f	0x2d94c130
+	0x777290f1	0x2e656559	0x9be4a490	0x377a6ea0
+	0x1b4523e4	0xdca0c8a5	0xb00eed31	0x6baeb803
+	0x9601ee69	0x13d53e86	0xba8d6d8f	0xed6203ce
+	0xc844f9c7	0x91e8a556	0x39974676	0x3b81329b
+	0xdd7f10e1	0xbccb6558	0xb20de25c	0x448c44ee
+	0x8932398a	0x76717b57	0xb20a667a	0x14e2df4a
+	0xa57107f6	0x701b6c36	0x4b83a1ac	0xb39a1c9e
+	0x2cc7e9fe	0xf5ae4a62	0x620687b6	0x2d6aef9d
+	0x6672612c	0x168cdc7e	0x8b09abea	0x522692da
+	0x6461676d	0x34ab3a9c	0x0d61a2ba	0x0590fef1
+	0xe9b4b475	0x2dfb6081	0xbcdafb25	0xdae642aa
+	0x9a9230fd	0xfd67f346	0xdb9d66e1	0x5b307b61
+	0x9d4f1869	0x21133d6f	0x5157502f	0xcc8ccbc5
+	0xb6631100	0xa33f48db	0xc0172774	0x5cb276ac
+	0xe6e5c560	0x07e126dd	0x42bcf23a	0x8064fd70
+	0x567ece78	0xbbc2fe32	0x9d5ee1bb	0x175b24be
+	0xf0feac7a	0x57322618	0xfe9e893f	0xa9b2d67b
+	0x36d03f5a	0xdf178831	0x4da346c5	0x843b1b10
+	0x0d688dca	0x41a475c6	0x4b7adf33	0x145a00dc
+	0xcd226a4d	0x4c40cf2c	0xd4972929	0xbad5ea65
+	0xa96987fa	0xbe247d1c	0x49f2ce89	0xe09bbe72
+	0xee48486e	0x34b41435	0xb41dbb86	0xe58866c9
+	0xe848e228	0x18880947	0xd03cd275	0xca285915
+	0x53dd0097	0xff9069f9	0xaff6a8cd	0xbfe16ac5
+	0x5e88e076	0xac629a26	0x5a99bee9	0xea892a43
+	0x8d1d5ce8	0x806a38e3	0xc4d99fcd	0x331a4a01
+	0x0e586310	0xdd2dfabb	0xe7e6ad37	0x31d67fb1
+	0xbb985560	0xc969ce24	0x3a424634	0x20a2080e
+	0xeb1b587c	0x5cf7da4b	0xdaec0133	0xc99abb17
+	0x63ab9c8f	0xef7e4042	0xca513c8a	0x4e15f5d9
+	0x7cf8fc96	0x464cea5a	0x2363577d	0xd21bb7db
+	0x1d977a0f	0xb02f4878	0x4fd1a03b	0x435b9149
+	0xdfba062e	0xa2f7fc23	0x5ebde93c	0x28e9ed7a
+	0x4023b147	0x9cac0cf9	0x7c5d5ca1	0xb7453148
+	0xa52197d9	0xb85dd94b	0x72ee7e51	0xb81f4f5c
+	0x97a4b485	0x13d8858a	0xa0aabd28	0x9d381125
+	0x4960d2a7	0xa62787b2	0x865231c2	0xd637cc90
+	0x6d58f3b7	0xe2759f6e	0xa28af8da	0x5a005f20
+	0xc11c495b	0x85ecc413	0x657e7b91	0x10b39f7e
+	0x3fcc394a	0x94b3fc3a	0xb359d60e	0x2e6c1555
+	0x67d6d21d	0xb0457bc4	0x004f329a	0x2e131d8b
+	0xfbfbff2a	0x2c1bcbef	0x181f26b6	0x32ebda60
+	0xa0839e5a	0x241097df	0xb3f070a7	0xefbbd9f0
+	0x7c3669c7	0x265f2dbc	0x0bd00e42	0x80d6c4c2
+	0x44874336	0x0b6e7e0a	0xec590889	0xef865c09
+	0x1a02ac8a	0xfbf78784	0xaaf89d75	0xa86c9caa
+	0xc626528d	0xfbcec50f	0x2955f18e	0xb5e9a833
+	0xae60f6bb	0xb3f4c51e	0x21bd6a6e	0x092a6861
+	0x162d73dd	0xacfa4f0e	0x4efed2bd	0x88980089
+	0xa2cee6d9	0xdf0953b8	0x6bf5208d	0x4364ed53
+	0x1a5f19ad	0x2ec7711e	0x7d18832b	0x0f1b28a6
+	0x0e127845	0x278a6a61	0x9e236436	0xf4646e82
+	0x07fff0f3	0x34ae92f9	0xec3e71af	0xf7ec7c67
+	0xdb9ddd62	0xe664e712	0xbb48a158	0x30a14ae6
+	0x0d93b021	0x83082cc8	0x68952311	0x001b0003
+	0xf0688e25	0x6c3b5161	0xfff18a53	0xbd1fb0c9
+	0xe3cc9013	0x1d1e553e	0xa85cdfb0	0x358afc14
+	0x61749007	0x6fad59bd	0xe85f4500	0x26a5ffa1
+	0xedd69e21	0x4c1db8ce	0xaf3be18f	0xcd75c259
+	0xd05f62ee	0x2f0ff1b7	0x717d9bd3	0x62e13392
+	0x159ce5ce	0xcd9e9bff	0x8964600e	0x57d85abb
+	0x3f5ead09	0x2d5d4a55	0x87da8369	0xc7944933
+	0xcde9a717	0x55fa318d	0x112e1607	0x2ca832cb
+	0xb1181bd5	0x7541a7d4	0xac1a1e20	0x6ad024c8
+	0x119378ec	0x60b6cbfb	0x068e2f24	0x83acecb1
+	0x87fd0df3	0x94c9552f	0x08c3d8dc	0x56f1b514
+	0x717d50e9	0x9680fc39	0xa1bdb28a	0x3dfa1c7c
+	0x8fc84774	0xb72e06d7	0x42b7ad1e	0x93646393
+	0xd3632e4a	0x368d78f2	0x36a5ac5b	0x6576a4d8
+	0x8bc6856c	0xd447936a	0xbec6fb22	0xab285e59
+	0x3db2c781	0x72eda32a	0x9d654f18	0xdbd78e99
+	0xbba310ad	0x938ecfc6	0x72d5079a	0x49e2fad4
+	0x4b44dc75	0x81e82165	0xbe269c9c	0x2558ae80
+	0xa3bb693e	0x107d10fd	0x8e4fd977	0x22926b4f
+	0x68c9a7f8	0x6b7439e0	0x5c71c127	0xff5d88b3
+	0x9d8cce8e	0x02982a71	0xf8fe1ceb	0x3ed3996b
+	0x1e4f9957	0x63aca642	0xcc9db51b	0xbcb5af80
+	0x7b2bf393	0x2915079f	0x87f531c5	0xfb06b13a
+	0x550b261c	0xf01fa342	0xcdf4dd86	0x76718f50
+	0x717c6bde	0xf460ef23	0x7f912022	0x54fe5b9b
+	0xc7a5261b	0x073ea6e7	0x71504d55	0x91dd9b8e
+	0x6d259452	0x2dc96e43	0x289959ca	0x128176a5
+	0x8d004371	0x835c494e	0x0efa1879	0xddc02e95
+	0xf0f4618e	0xc67656e2	0xd2bde6b1	0xccaa5e84
+	0xc6592f19	0x91d01db8	0x2b697d22	0x8adfa55f
+	0x5a49e4e7	0x897d5c43	0xd326d94f	0xf5ff0c5b
+	0x57976ca6	0xeff0db4e	0x6d49d466	0x7c054970
+	0xd3eb0f9f	0x0cbdce79	0x1beaf714	0xfe2df967
+	0x6a50895e	0x013167bf	0x6139e59c	0x0662ecee
+	0x9a8d6b53	0xfffb8649	0xce0e685f	0xea5b2a7a
+	0x8819a629	0x5f96afb4	0x8891acfe	0x545f1097
+	0x9f314e1b	0x248a5272	0xa40b8424	0xe42af07a
+	0xa180f331	0x904f3c05	0x98455bc5	0x46198ed7
+	0x03e208e5	0xcf670099	0x7a85b08c	0xba921ae2
+	0x1e6947d0	0xddffa6ec	0xea6330d3	0xcda6957e
+	0x19525cd3	0x311fb407	0x796c1ff4	0x3a2760fb
+	0xde4bdd71	0xdb289b69	0x9811773c	0xa72cd839
+	0x03da90de	0xd42912e8	0x8da1fb0a	0x985d4132
+	0x5890ae40	0x1f7724d0	0xa336824f	0xca19df32
+	0xf8ac73d1	0x61c370a9	0xe152b073	0xdafc6461
+	0x23672042	0x9e6982b6	0x1256c6b4	0xe6bf2c9c
+	0x9dae123e	0x30896b8f	0x99acf3a3	0xaa05d384
+	0xea3b7bb7	0xe711d473	0xa9053351	0x71a85cb4
+	0x3a0f5d25	0x2db3cb48	0x86314a6e	0xf7a2265b
+	0xf7dc1cc3	0x548f56cf	0x4028a1ee	0x7d2e25d5
+	0x68c87e37	0xbced6b8c	0x536cc252	0x68bab5ca
+	0x1158c6c5	0xae0e9509	0x66fa6885	0x22bf2b9a
+	0xa7a60a97	0x18f4f609	0x348623eb	0x773e705f
+	0xb3d6622f	0x8f348186	0x81cb9856	0x64bf21ba
+	0x47e1f96d	0xc95a5843	0xeff6cfce	0x08cb092c
+	0xf214e48d	0xce272fec	0x57bf90df	0x3c425ea8
+	0x856e1f5e	0x5c21d1b6	0x105488a3	0x553971eb
+	0xde614ee5	0xdfa3ac81	0xc5eca5b1	0x69d02d23
+	0x2a0fefb7	0xf9a01854	0xdd99f277	0x75014d7d
+	0x3830e3dd	0x7dd8f1e7	0xdac5ac92	0xbf57c03a
+	0xa5e6a6c7	0xb7c1b7a9	0xc8c8405e	0xfd1977da
+	0x1e6a7ca4	0x299e1025	0x651a0e55	0x53d624a7
+	0xccc9e861	0x901bce45	0x1de5a1ab	0x6140dcef
+	0x3e09eafb	0x20c63cd0	0xff642faa	0xbc91a0a7
+	0xe373e111	0x857236e7	0xe3e61037	0x0b6cc497
+	0xca1da7e6	0x60e53803	0xb68663db	0x42e9956a
+	0xbf4a1650	0xb43f25ec	0xc1232a3a	0x283c2ff3
+	0xcd233183	0x17ccdfc0	0x03ac3e6d	0xa68ced48
+	0xe38217d5	0x03c6472d	0x6a623afc	0xfce0d117
+	0x448ee829	0x0909efd4	0x843a3b4a	0x9ad07683
+	0x2250af2a	0x01ecc053	0x29684919	0x4ee0c62e
+	0xa326a904	0x3ec83943	0xc42b0663	0x966379b2
+	0xc672ece4	0x39391ad3	0x689a10f9	0xd3e9cbd6
+	0x4bfa8446	0xd1ef6375	0xfe01b6a9	0xbda7d01a
+	0x1e6879bf	0x05bdf46e	0x14ccab04	0xb02ae668
+	0x58b51752	0x5eb8e83c	0x753d99de	0x87e4235b
+	0x80b2afe7	0x127439fe	0x127a98a4	0xe5934c92
+	0x86044bc0	0xa9664abb	0x91365b53	0x35b14bda
+	0x67755842	0x7239651a	0x49e0b2e6	0xbb1d25fe
+	0x51ca7213	0xaff2fd82	0xc1223aba	0x02941bcf
+	0xb6ec2cfe	0xaa817dc0	0xe0475250	0x78098112
+	0x750ae102	0x0b3135fa	0x23b648d4	0xbc9d78bd
+	0xc5d7e046	0xe90ef47c	0x7f21eb75	0xdb304b0b
+	0xa2c12ee2	0xb45e62ed	0x9f50feb6	0xe036ff55
+	0x422f410b	0x2385de45	0xb37df6a5	0x4c2abf10
+	0x6a2c7370	0xf35197ac	0x381face9	0x694761c6
+	0xb2275097	0x208824c7	0x945300a0	0x4ad3f83d
+	0x38a7aa12	0x00daaf41	0xcd4b2c19	0x25b2e8f7
+	0x60d3e39b	0xb3dd8220	0x152f86ab	0xd1ec4233
+	0x1c3df78a	0x5aeac74e	0xdeea2fe3	0xcfcf9b2e
+	0x6efc8b2a	0x12a8c5c3	0xb56384e4	0x1b1fe549
+	0xc55acb4d	0x78e7306a	0x733b0f70	0xf4afe6be
+	0x6d904b03	0x7ddd7862	0x4da02602	0xfce1e904
+	0x78773a4b	0x9083e908	0xda8a7593	0xafd8776e
+	0x9e5ae37a	0xd6e7c557	0xad27adaa	0xd0f1a995
+	0x1c84e046	0x3319b21a	0xd24c0d03	0x1789df77
+	0x0f02b9ff	0xdb911f76	0xb2df7654	0x2e75a7bd
+	0x8acc6fd3	0x3c16ec0b	0xe0d7ac22	0x3ddd1ce1
+	0xfa9ec67a	0x48f2c409	0xf8099606	0xd73a459d
+	0x9b2b3fa5	0x8e3c3e9c	0x8b99286a	0x006c0e07
+	0xc299ded3	0x8a2bd400	0x74508dd4	0x609b4afc
+	0x1a532838	0xb352a629	0xd390d8af	0x440a5798
+	0xd31f6ad5	0x161aa48e	0x24a4359f	0xf39f49f7
+	0xff160d2a	0x27a24637	0x84c46d40	0x988d026a
+	0x5697a68f	0xeae970a0	0x42689e3d	0xc84ee62f
+	0x764aabd5	0xb6d74ba5	0x8efc05a6	0xf2d0eccb
+	0x2b4fa41c	0xad24799f	0xf73b8353	0x76bcd448
+	0x08172d5e	0x5c6be301	0x926ffdd6	0xfa31009f
+	0x8339c5f9	0x9dde2840	0x00c2d730	0x6402335f
+	0xf6f84eda	0x5b0e628a	0x140dbafb	0x0533ee67
+	0xa7523e60	0x20ca14b3	0x1145d280	0xb0c0ba41
+	0x81f174d1	0xb80fc64e	0xe8321cfe	0x5762e501
+	0x9e266b75	0x2695a738	0xe3104779	0x1d1ea19e
+	0x15fd1d53	0xf0fbd4ee	0xc82f4552	0x4ea98e23
+	0xec892d69	0x66ccadeb	0x2fdf99b4	0xafffec15
+	0x2de5ee13	0x5e6ead7f	0x20b111cd	0x752254d1
+	0xc0126f43	0xe2695fd8	0x38651d40	0x15b708ce
+	0xf2c2ffdc	0xec24c68c	0x04351ddc	0xceac029b
+	0x0525fc89	0x90e28526	0x0a23a4c2	0xbb33a5c4
+	0x13f1fc38	0x66d79cd9	0x0acabe80	0x8d4ef5d8
+	0x4091808e	0x02f7150b	0xf550597e	0x52703c3f
+	0xfc954b68	0xe9ebaccb	0xd4f35b2a	0x93793446
+	0xc40799e6	0xa963fc0c	0x92c8d8f1	0xbc8218dc
+	0x9ec5c30a	0x8a6a2217	0x63d13dfe	0xea664e1e
+	0x487192a7	0x1c8f8610	0x88e20f93	0xc54a6de3
+	0x0111ae79	0x1335f02e	0xa2e2d37d	0xc2563697
+	0x5fffcdec	0x233919ab	0x3bab1329	0x61943e99
+	0xea7940f7	0x3cc62cf4	0xaedc5bc4	0x41b63f2c
+	0x6dbf285f	0xb4793534	0x0e1013f2	0xc54d8c2d
+	0x23c587f7	0x75df0092	0xc055254a	0x55db2c71
+	0x518eaa5b	0x55c810d6	0x9c44ca37	0x034287ea
+	0xe06a0567	0x221a0d8c	0x037a9164	0x36693ef9
+	0xb7d270a6	0xa8d84a63	0xe8862970	0x484077b7
+	0xab426cb7	0x37db7c9e	0xb34e1752	0x35444958
+	0x00d48e90	0x8142602d	0x8ca28e2c	0x714598c9
+	0xb1cce1be	0xbb98db74	0x400e1029	0x330cb2b6
+	0x1fd3f8ce	0x2abf7516	0xc2d07e5c	0x2b1d2b80
+	0xf06bd895	0x2fa7bc09	0xbdbdf893	0xd8466f85
+	0x61e551b0	0x5b99bfb8	0x86ea5ee7	0xfd82ff9a
+	0xd7c6344a	0x1fa144d8	0x650f0f02	0x71bd73cf
+	0x2825177d	0x56c76399	0x2e0b873e	0xc3bf939d
+	0xf8bc3c1b	0x468482e7	0x33cb98a7	0xa679eaf4
+	0x32ba9b49	0xde86d50c	0x9eeeeee5	0x94a306e5
+	0x432e1c9c	0x37997d0c	0xa84d981f	0xbe07b56d
+	0x4ab6d465	0xa3cd92c4	0x5dea82ab	0xf771249d
+	0x78f87ba5	0x8105df1c	0x3d74e1c1	0xf48cd4c1
+	0x8ad010e1	0x9e9a2758	0x509c8953	0xeaaed79a
+	0x97a4ecb7	0x23ffceb0	0xb3e42e61	0x5f41b4eb
+	0x14d2804c	0x2d635ad3	0xe1314781	0x3921ec18
+	0x3dbebec3	0x94e0df22	0xb0b4724e	0x0e7f986b
+	0x83dd7694	0x7041a22e	0x3c942757	0xd6ff5cbb
+	0x048b0426	0xa5d6c4cb	0x1f4e3bbd	0x78d5924e
+	0x6a857d77	0x1d115ecc	0x73c6a888	0xefb934ee
+	0xa7d1702b	0x6794a668	0x03715b90	0xfbab19f9
+	0xd5a433df	0x12f4d421	0x40519650	0x636a093e
+	0x1601be15	0xe0fbef6f	0x79d775bc	0x789c3a30
+	0x4d9fa618	0xedf8fa70	0xb0fa402d	0x692ee91b
+	0x5a593e5c	0x0fa3667f	0x3f51a636	0x935e28c7
+	0x230b725a	0x4929bc83	0x76de40ad	0x2d9a5f7f
+	0x8799e033	0xbf2700b0	0x5220159d	0x1ed71ca5
+	0xcc66f114	0x15fd868d	0x4236645a	0xded2558e
+	0xa561cc0d	0x02822e5b	0xd0177f80	0xf09badd9
+	0xd5380ae3	0xcfc11a46	0x36713416	0x7f3d60cc
+	0x4018797e	0xc6b23941	0xcb5a4861	0x614ce6df
+	0xabfc0629	0xa519bcfc	0x911f04f0	0xe509b546
+	0xbb411eb9	0x9e6b921c	0xbf0b1c70	0x80c2901c
+	0x85786713	0xad2aafec	0x62711ba7	0x6edb4971
+	0x214eb137	0x45b1b313	0x6742d5e9	0x7daf37a6
+	0x21d6a27a	0x059424f7	0x2c8c3dfb	0xe7a06c77
+	0x10815625	0xb4dc69e8	0x52767f66	0x44d48738
+	0x84d26c93	0x09008893	0xfc21394a	0x82155a72
+	0xc4fd7512	0x6d43cd2f	0xcae99e08	0x453175ae
+	0xc6ee93a3	0x2fed0eac	0xe48fb73d	0x0afe2d2a
+	0x5966735e	0xdc7e5fb6	0xed1ef13d	0x7e08a106
+	0xd3ca0e6b	0x4ce5ca02	0xa0beebed	0xe982c609
+	0x1ee9e5a2	0x24ae26cb	0xfd4c08d4	0x5e85e850
+	0x11b54b3b	0x87209692	0x4a5b0c35	0xcd25dd6f
+	0xd9570253	0xaad0b9fe	0xaf984fee	0x6cf7ae2d
+	0x45d9926c	0x07a66ac6	0x8e7aacdc	0xaf587d66
+	0x53972a4e	0x8da4a6c9	0x2bc311e5	0x36938ae8
+	0x179b965d	0x515743f7	0xb5bbbdcd	0xd8602715
+	0x9e43049f	0x4e78a080	0xba3f1750	0x68635cf0
+	0x85823047	0xbb03b5fd	0xb0d747c8	0x58d214af
+	0x94b1ba85	0x6d2cf8ac	0x2bc1faeb	0x6bd7c1e3
+	0x127658e9	0x8b499020	0xab8f0f62	0xee665a6a
+	0x89240e4d	0x8a95342b	0x00b38ccc	0xe6b14d9d
+	0x32a2af71	0x4c9ecb69	0xc8de2685	0xd7385184
+	0x8e943872	0x809b2c79	0x108511da	0x08b4f54d
+	0x95f52442	0x26fe296f	0xf7e037c0	0xa1aecdd3
+	0x89774a91	0xde67c55f	0x1f9816dc	0x1469a4c2
+	0x28240be2	0x5fd0ad14	0x0949db3a	0x451b94d3
+	0x637e6d49	0x8a4771c8	0xf65104b7	0xc3058c40
+	0x592fe4d0	0xe26129f0	0xe66e6ce9	0x26ab39b8
+	0x308da532	0x205afe77	0x6dc78664	0x84d4890f
+	0x9d49fcb0	0xcac8f2ed	0xe713d798	0xfed7c75b
+	0xe441a0d4	0xdf60df37	0xc2eed2f5	0x2d68b20e
+	0x7827c89a	0x9d4cb9f2	0xb8912cce	0x07516335
+	0x976ffbb6	0x5cd0de48	0xed716f54	0x6f3c9f7f
+	0x34cf42d1	0xc1027cbb	0xde67c065	0xe0a229af
+	0xfc8bd2e8	0xd62ca176	0x8bfb76b2	0x54a1388f
+	0xe0650bb6	0x6d60682b	0xe16cf130	0xbd7c3ca2
+	0xea642814	0xa25f4d44	0x27013786	0x7316aa38
+	0x571511c8	0xf1b6b789	0xb7bfe72b	0x8fd2652c
+	0xbfc7771a	0x51a2e551	0x3bd738c2	0x2698b495
+	0xec69a196	0xd5ecb5c4	0x9bd3224c	0x6d9ab4cf
+	0x326c9942	0x4d711191	0xde9be50a	0xa980ca0b
+	0xe8e59dd0	0x4439e4ae	0x35de914d	0xee499a84
+	0xd1ca0c9d	0xfe6ee96d	0x5b1f4fd0	0xabf0621a
+	0x0c8220c7	0xcb6dbb1e	0xa5116036	0xe858d3c3
+	0x728e3a56	0x3b33e818	0xbe2643c1	0x497bbcc7
+	0xeb369828	0x9a4a01be	0x8c7e72a6	0xaf052f25
+	0x8d3ca85b	0x4703e55e	0x45647d4c	0x86d1e3e8
+	0x40ab59f9	0x3259b195	0xf979a147	0xb8961870
+	0x88b024f9	0x366e26bc	0xd6811525	0x252910c2
+	0x4223a20e	0x7fc971a3	0x4a639bf3	0xb6550c3b
+	0xfe05e552	0xbdc98897	0x509923ff	0xf51a5abc
+	0xc6cc0891	0x61cdac05	0x03a68664	0x1b80cc76
+	0xe18d8ee1	0x798bb4d2	0xd7769bf9	0x9ab4c02d
+	0x7484774b	0xa9ee2c8b	0x87d34c85	0x15697682
+	0x9f6a4a55	0x9d7a731c	0x10014d6a	0xb9798070
+	0xd42f79cb	0x89db59b3	0xd5b0a0b6	0xf60864a5
+	0x2d6fb084	0x1cb607b2	0x48232701	0x9310cbc6
+	0x5bc81c98	0x6b25016c	0x2014b99d	0x0836e60b
+	0x0addbc4c	0x3b8bac7c	0x8d95ac77	0x1d56c3c7
+	0x58333104	0x3d6eb719	0x676eb951	0xd5c2d1a3
+	0x239dae86	0x92181ab8	0xbdde9741	0x7995d452
+	0xe0020661	0x2f80c8b7	0xeedcd4fc	0xe4bde175
+	0xb98fdf78	0x84b9228f	0x78ecb4f3	0xe99e5d46
+	0xa33b9b96	0xe2cbc71c	0xc19e2146	0xdc0ee758
+	0x2d8f8767	0x2036685b	0x149df155	0x2e7ab376
+	0xb13b4266	0xf5c8a3b0	0x02ca1e19	0x1badd81b
+	0xb9c1832a	0x73b31f75	0x69979b55	0x567070a2
+	0x2edeb3dc	0x26b55921	0x461df49f	0xc1aba883
+	0x25d6faec	0x5260e9bf	0xa8ccdd4c	0x04291961
+	0xfaf7a1b8	0xbc2d36e3	0xd6c86385	0x2757fbb9
+	0x62c7107c	0x87dac461	0x0c006454	0x0e971e49
+	0x4749afca	0x7f1fb389	0xdc0b69d3	0xc69fab09
+	0x12c372c9	0x78480a51	0x8ab03a94	0xb37022ca
+	0x1d00e893	0x0989de45	0x8c819503	0x8e0e1c06
+	0x11cfef86	0x3c2386a6	0x66c0e6c8	0x1befa478
+	0xd2e7a4a7	0x9a8b5917	0x2cfa1816	0xaf7e6c7a
+	0xd6c9f0ff	0x1aada3e0	0xbe36a471	0x5a91f3c7
+	0x6c61ea95	0x5246ef7c	0x20bc86c4	0xcfd87abd
+	0xdc61f595	0x8310a684	0x0477e35c	0xe59e776f
+	0xfa403863	0xdaf7bcb1	0xd6084825	0xb90bb047
+	0xeb9ff684	0x7223fbca	0x6b4af987	0x6b2553f8
+	0xdaabc6d2	0x82e2ebc3	0xa7c1c054	0x667eb0a7
+	0x53a0c7d4	0x3fcba743	0x38170187	0x2a2e5830
+	0xee134608	0xcd6e0112	0xac0831f9	0x9537d532
+	0x1e176b9c	0xe3fcb69f	0x17a2eee9	0xa9e6467f
+	0xbf6b0246	0x6a08c0fb	0x7fb943b6	0xb8f67c0e
+	0x2b3b4ffc	0xb155d20c	0x4eb5de53	0xf078715b
+	>;
diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
new file mode 100644
index 0000000..8f34369
--- /dev/null
+++ b/arch/x86/dts/minnowmax.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
+
+/ {
+	model = "Intel Minnowboard Max";
+	compatible = "intel,minnowmax", "intel,baytrail";
+
+	aliases {
+		serial0 = &serial;
+	};
+
+	config {
+		silent_console = <0>;
+	};
+
+	chosen {
+		stdout-path = "/serial";
+	};
+
+	spi {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "intel,ich";
+		spi-flash@0 {
+			reg = <0>;
+			compatible = "sst,25vf016b", "spi-flash";
+			memory-map = <0xff800000 0x00800000>;
+		};
+	};
+
+	microcode {
+		update@0 {
+#include "microcode/m0130673322.dtsi"
+		};
+	};
+
+};
diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi
index 9b097f4..6865eed 100644
--- a/arch/x86/dts/serial.dtsi
+++ b/arch/x86/dts/serial.dtsi
@@ -1,5 +1,5 @@
 / {
-	serial {
+	serial: serial {
 		compatible = "x86-uart";
 		reg = <0x3f8 8>;
 		reg-shift = <0>;
diff --git a/arch/x86/include/asm/arch-baytrail/fsp/azalia.h b/arch/x86/include/asm/arch-baytrail/fsp/azalia.h
new file mode 100644
index 0000000..d96a20f
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/fsp/azalia.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef _FSP_AZALIA_H_
+#define _FSP_AZALIA_H_
+
+struct __packed pch_azalia_verb_table_header {
+	uint32_t vendor_device_id;
+	uint16_t sub_system_id;
+	uint8_t revision_id;		/* 0xff applies to all steppings */
+	uint8_t front_panel_support;
+	uint16_t number_of_rear_jacks;
+	uint16_t number_of_front_jacks;
+};
+
+struct __packed pch_azalia_verb_table {
+	struct pch_azalia_verb_table_header verb_table_header;
+	const uint32_t *verb_table_data;
+};
+
+struct __packed pch_azalia_config {
+	uint8_t pme_enable:1;
+	uint8_t docking_supported:1;
+	uint8_t docking_attached:1;
+	uint8_t hdmi_codec_enable:1;
+	uint8_t azalia_v_ci_enable:1;
+	uint8_t rsvdbits:3;
+	/* number of verb tables provided by platform */
+	uint8_t azalia_verb_table_num;
+	const struct pch_azalia_verb_table *azalia_verb_table;
+	/* delay timer after azalia reset */
+	uint16_t reset_wait_timer_us;
+};
+
+#endif
diff --git a/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h
new file mode 100644
index 0000000..82862f6
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/fsp/fsp_vpd.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef __FSP_VPD_H
+#define __FSP_VPD_H
+
+struct memory_down_data {
+	uint8_t enable_memory_down;
+	uint8_t dram_speed;
+	uint8_t dram_type;
+	uint8_t dimm_0_enable;
+	uint8_t dimm_1_enable;
+	uint8_t dimm_width;
+	uint8_t dimm_density;
+	uint8_t dimm_bus_width;
+	uint8_t dimm_sides;			/* Ranks Per dimm_ */
+	uint8_t dimm_tcl;			/* tCL */
+	/* tRP and tRCD in DRAM clk - 5:12.5ns, 6:15ns, etc. */
+	uint8_t dimm_trpt_rcd;
+	uint8_t dimm_twr;			/* tWR in DRAM clk  */
+	uint8_t dimm_twtr;			/* tWTR in DRAM clk */
+	uint8_t dimm_trrd;			/* tRRD in DRAM clk */
+	uint8_t dimm_trtp;			/* tRTP in DRAM clk */
+	uint8_t dimm_tfaw;			/* tFAW in DRAM clk */
+};
+
+struct __packed upd_region {
+	uint64_t signature;			/* Offset 0x0000 */
+	uint8_t reserved0[24];			/* Offset 0x0008 */
+	uint16_t mrc_init_tseg_size;		/* Offset 0x0020 */
+	uint16_t mrc_init_mmio_size;		/* Offset 0x0022 */
+	uint8_t mrc_init_spd_addr1;		/* Offset 0x0024 */
+	uint8_t mrc_init_spd_addr2;		/* Offset 0x0025 */
+	uint8_t emmc_boot_mode;			/* Offset 0x0026 */
+	uint8_t enable_sdio;			/* Offset 0x0027 */
+	uint8_t enable_sdcard;			/* Offset 0x0028 */
+	uint8_t enable_hsuart0;			/* Offset 0x0029 */
+	uint8_t enable_hsuart1;			/* Offset 0x002a */
+	uint8_t enable_spi;			/* Offset 0x002b */
+	uint8_t reserved1;			/* Offset 0x002c */
+	uint8_t enable_sata;			/* Offset 0x002d */
+	uint8_t sata_mode;			/* Offset 0x002e */
+	uint8_t enable_azalia;			/* Offset 0x002f */
+	uint32_t azalia_config_ptr;		/* Offset 0x0030 */
+	uint8_t enable_xhci;			/* Offset 0x0034 */
+	uint8_t enable_lpe;			/* Offset 0x0035 */
+	uint8_t lpss_sio_enable_pci_mode;	/* Offset 0x0036 */
+	uint8_t enable_dma0;			/* Offset 0x0037 */
+	uint8_t enable_dma1;			/* Offset 0x0038 */
+	uint8_t enable_i2_c0;			/* Offset 0x0039 */
+	uint8_t enable_i2_c1;			/* Offset 0x003a */
+	uint8_t enable_i2_c2;			/* Offset 0x003b */
+	uint8_t enable_i2_c3;			/* Offset 0x003c */
+	uint8_t enable_i2_c4;			/* Offset 0x003d */
+	uint8_t enable_i2_c5;			/* Offset 0x003e */
+	uint8_t enable_i2_c6;			/* Offset 0x003f */
+	uint8_t enable_pwm0;			/* Offset 0x0040 */
+	uint8_t enable_pwm1;			/* Offset 0x0041 */
+	uint8_t enable_hsi;			/* Offset 0x0042 */
+	uint8_t igd_dvmt50_pre_alloc;		/* Offset 0x0043 */
+	uint8_t aperture_size;			/* Offset 0x0044 */
+	uint8_t gtt_size;			/* Offset 0x0045 */
+	uint32_t serial_debug_port_address;	/* Offset 0x0046 */
+	uint8_t serial_debug_port_type;		/* Offset 0x004a */
+	uint8_t mrc_debug_msg;			/* Offset 0x004b */
+	uint8_t isp_enable;			/* Offset 0x004c */
+	uint8_t scc_enable_pci_mode;		/* Offset 0x004d */
+	uint8_t igd_render_standby;		/* Offset 0x004e */
+	uint8_t txe_uma_enable;			/* Offset 0x004f */
+	uint8_t os_selection;			/* Offset 0x0050 */
+	uint8_t emmc45_ddr50_enabled;		/* Offset 0x0051 */
+	uint8_t emmc45_hs200_enabled;		/* Offset 0x0052 */
+	uint8_t emmc45_retune_timer_value;	/* Offset 0x0053 */
+	uint8_t unused_upd_space1[156];		/* Offset 0x0054 */
+	struct memory_down_data memory_params;	/* Offset 0x00f0 */
+	uint16_t terminator;			/* Offset 0x0100 */
+};
+
+#define VPD_IMAGE_ID		0x3157454956594C56	/* 'VLYVIEW1' */
+#define VPD_IMAGE_REV		0x00000303
+
+struct __packed vpd_region {
+	uint64_t sign;				/* Offset 0x0000 */
+	uint32_t img_rev;			/* Offset 0x0008 */
+	uint32_t upd_offset;			/* Offset 0x000c */
+	uint8_t unused[16];			/* Offset 0x0010 */
+	uint32_t fsp_res_memlen;		/* Offset 0x0020 */
+	uint8_t platform_type;			/* Offset 0x0024 */
+	uint8_t enable_secure_boot;		/* Offset 0x0025 */
+};
+#endif
diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
new file mode 100644
index 0000000..ab4e059
--- /dev/null
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x44
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
index cf7457f..c960525 100644
--- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -43,7 +43,7 @@
 #define DEFAULT_EPBAR		0xfed19000	/* 4 KB */
 #define DEFAULT_RCBABASE	0xfed1c000
 /* 4 KB per PCIe device */
-#define DEFAULT_PCIEXBAR	CONFIG_MMCONF_BASE_ADDRESS
+#define DEFAULT_PCIEXBAR	CONFIG_PCIE_ECAM_BASE
 
 /* Device 0:0.0 PCI configuration space (Host Bridge) */
 #define EPBAR		0x40
diff --git a/arch/x86/include/asm/arch-quark/device.h b/arch/x86/include/asm/arch-quark/device.h
new file mode 100644
index 0000000..4af3ded
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/device.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _QUARK_DEVICE_H_
+#define _QUARK_DEVICE_H_
+
+#include <pci.h>
+
+#define QUARK_HOST_BRIDGE	PCI_BDF(0, 0, 0)
+#define QUARK_MMC_SDIO		PCI_BDF(0, 20, 0)
+#define QUARK_UART0		PCI_BDF(0, 20, 1)
+#define QUARK_USB_DEVICE	PCI_BDF(0, 20, 2)
+#define QUARK_USB_EHCI		PCI_BDF(0, 20, 3)
+#define QUARK_USB_OHCI		PCI_BDF(0, 20, 4)
+#define QUARK_UART1		PCI_BDF(0, 20, 5)
+#define QUARK_EMAC0		PCI_BDF(0, 20, 6)
+#define QUARK_EMAC1		PCI_BDF(0, 20, 7)
+#define QUARK_SPI0		PCI_BDF(0, 21, 0)
+#define QUARK_SPI1		PCI_BDF(0, 21, 1)
+#define QUARK_I2C_GPIO		PCI_BDF(0, 21, 2)
+#define QUARK_PCIE0		PCI_BDF(0, 23, 0)
+#define QUARK_PCIE1		PCI_BDF(0, 23, 1)
+#define QUARK_LEGACY_BRIDGE	PCI_BDF(0, 31, 0)
+
+#endif /* _QUARK_DEVICE_H_ */
diff --git a/arch/x86/include/asm/arch-quark/gpio.h b/arch/x86/include/asm/arch-quark/gpio.h
new file mode 100644
index 0000000..ca8cba4
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/gpio.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x44
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-quark/mrc.h b/arch/x86/include/asm/arch-quark/mrc.h
new file mode 100644
index 0000000..150fbea
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/mrc.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Ported from Intel released Quark UEFI BIOS
+ * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
+ *
+ * SPDX-License-Identifier:	Intel
+ */
+
+#ifndef _MRC_H_
+#define _MRC_H_
+
+#define MRC_VERSION	0x0111
+
+/* architectural definitions */
+#define NUM_CHANNELS	1	/* number of channels */
+#define NUM_RANKS	2	/* number of ranks per channel */
+#define NUM_BYTE_LANES	4	/* number of byte lanes per channel */
+
+/* software limitations */
+#define MAX_CHANNELS	1
+#define MAX_RANKS	2
+#define MAX_BYTE_LANES	4
+
+#define MAX_SOCKETS	1
+#define MAX_SIDES	1
+#define MAX_ROWS	(MAX_SIDES * MAX_SOCKETS)
+
+/* Specify DRAM and channel width */
+enum {
+	X8,	/* DRAM width */
+	X16,	/* DRAM width & Channel Width */
+	X32	/* Channel Width */
+};
+
+/* Specify DRAM speed */
+enum {
+	DDRFREQ_800,
+	DDRFREQ_1066
+};
+
+/* Specify DRAM type */
+enum {
+	DDR3,
+	DDR3L
+};
+
+/*
+ * density: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
+ * cl: DRAM CAS Latency in clocks
+ * ras: ACT to PRE command period
+ * wtr: Delay from start of internal write transaction to internal read command
+ * rrd: ACT to ACT command period (JESD79 specific to page size 1K/2K)
+ * faw: Four activate window (JESD79 specific to page size 1K/2K)
+ *
+ * ras/wtr/rrd/faw timings are in picoseconds
+ *
+ * Refer to JEDEC spec (or DRAM datasheet) when changing these values.
+ */
+struct dram_params {
+	uint8_t density;
+	uint8_t cl;
+	uint32_t ras;
+	uint32_t wtr;
+	uint32_t rrd;
+	uint32_t faw;
+};
+
+/*
+ * Delay configuration for individual signals
+ * Vref setting
+ * Scrambler seed
+ */
+struct mrc_timings {
+	uint32_t rcvn[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	uint32_t rdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	uint32_t wdqs[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	uint32_t wdq[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
+	uint32_t vref[NUM_CHANNELS][NUM_BYTE_LANES];
+	uint32_t wctl[NUM_CHANNELS][NUM_RANKS];
+	uint32_t wcmd[NUM_CHANNELS];
+	uint32_t scrambler_seed;
+	/* need to save for the case of frequency change */
+	uint8_t ddr_speed;
+};
+
+/* Boot mode defined as bit mask (1<<n) */
+enum {
+	BM_UNKNOWN,
+	BM_COLD = 1,	/* full training */
+	BM_FAST = 2,	/* restore timing parameters */
+	BM_S3   = 4,	/* resume from S3 */
+	BM_WARM = 8
+};
+
+/* MRC execution status */
+#define MRC_SUCCESS	0	/* initialization ok */
+#define MRC_E_MEMTEST	1	/* memtest failed */
+
+/*
+ * Memory Reference Code parameters
+ *
+ * It includes 3 parts:
+ * - input parameters like boot mode and DRAM parameters
+ * - context parameters for MRC internal state
+ * - output parameters like initialization result and memory size
+ */
+struct mrc_params {
+	/* Input parameters */
+	uint32_t boot_mode;		/* BM_COLD, BM_FAST, BM_WARM, BM_S3 */
+	/* DRAM parameters */
+	uint8_t dram_width;		/* x8, x16 */
+	uint8_t ddr_speed;		/* DDRFREQ_800, DDRFREQ_1066 */
+	uint8_t ddr_type;		/* DDR3, DDR3L */
+	uint8_t ecc_enables;		/* 0, 1 (memory size reduced to 7/8) */
+	uint8_t scrambling_enables;	/* 0, 1 */
+	/* 1, 3 (1'st rank has to be populated if 2'nd rank present) */
+	uint32_t rank_enables;
+	uint32_t channel_enables;	/* 1 only */
+	uint32_t channel_width;		/* x16 only */
+	/* 0, 1, 2 (mode 2 forced if ecc enabled) */
+	uint32_t address_mode;
+	/* REFRESH_RATE: 1=1.95us, 2=3.9us, 3=7.8us, others=RESERVED */
+	uint8_t refresh_rate;
+	/* SR_TEMP_RANGE: 0=normal, 1=extended, others=RESERVED */
+	uint8_t sr_temp_range;
+	/*
+	 * RON_VALUE: 0=34ohm, 1=40ohm, others=RESERVED
+	 * (select MRS1.DIC driver impedance control)
+	 */
+	uint8_t ron_value;
+	/* RTT_NOM_VALUE: 0=40ohm, 1=60ohm, 2=120ohm, others=RESERVED */
+	uint8_t rtt_nom_value;
+	/* RD_ODT_VALUE: 0=off, 1=60ohm, 2=120ohm, 3=180ohm, others=RESERVED */
+	uint8_t rd_odt_value;
+	struct dram_params params;
+	/* Internally used context parameters */
+	uint32_t board_id;	/* board layout (use x8 or x16 memory) */
+	uint32_t hte_setup;	/* when set hte reconfiguration requested */
+	uint32_t menu_after_mrc;
+	uint32_t power_down_disable;
+	uint32_t tune_rcvn;
+	uint32_t channel_size[NUM_CHANNELS];
+	uint32_t column_bits[NUM_CHANNELS];
+	uint32_t row_bits[NUM_CHANNELS];
+	uint32_t mrs1;		/* register content saved during training */
+	uint8_t first_run;
+	/* Output parameters */
+	/* initialization result (non zero specifies error code) */
+	uint32_t status;
+	/* total memory size in bytes (excludes ECC banks) */
+	uint32_t mem_size;
+	/* training results (also used on input) */
+	struct mrc_timings timings;
+};
+
+/*
+ * MRC memory initialization structure
+ *
+ * post_code: a 16-bit post code of a specific initialization routine
+ * boot_path: bitwise or of BM_COLD, BM_FAST, BM_WARM and BM_S3
+ * init_fn: real memory initialization routine
+ */
+struct mem_init {
+	uint16_t post_code;
+	uint16_t boot_path;
+	void (*init_fn)(struct mrc_params *mrc_params);
+};
+
+/* MRC platform data flags */
+#define MRC_FLAG_ECC_EN		0x00000001
+#define MRC_FLAG_SCRAMBLE_EN	0x00000002
+#define MRC_FLAG_MEMTEST_EN	0x00000004
+/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
+#define MRC_FLAG_TOP_TREE_EN	0x00000008
+/* If set ODR signal is asserted to DRAM devices on writes */
+#define MRC_FLAG_WR_ODT_EN	0x00000010
+
+/**
+ * mrc_init - Memory Reference Code initialization entry routine
+ *
+ * @mrc_params: parameters for MRC
+ */
+void mrc_init(struct mrc_params *mrc_params);
+
+#endif /* _MRC_H_ */
diff --git a/arch/x86/include/asm/arch-quark/msg_port.h b/arch/x86/include/asm/arch-quark/msg_port.h
new file mode 100644
index 0000000..2e78a66
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/msg_port.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _QUARK_MSG_PORT_H_
+#define _QUARK_MSG_PORT_H_
+
+/*
+ * In the Quark SoC, some chipset commands are accomplished by utilizing
+ * the internal message network within the host bridge (D0:F0). Accesses
+ * to this network are accomplished by populating the message control
+ * register (MCR), Message Control Register eXtension (MCRX) and the
+ * message data register (MDR).
+ */
+#define MSG_CTRL_REG		0xd0	/* Message Control Register */
+#define MSG_DATA_REG		0xd4	/* Message Data Register */
+#define MSG_CTRL_EXT_REG	0xd8	/* Message Control Register EXT */
+
+/* Normal Read/Write OpCodes */
+#define MSG_OP_READ		0x10
+#define MSG_OP_WRITE		0x11
+
+/* Alternative Read/Write OpCodes */
+#define MSG_OP_ALT_READ		0x06
+#define MSG_OP_ALT_WRITE	0x07
+
+/* IO Read/Write OpCodes */
+#define MSG_OP_IO_READ		0x02
+#define MSG_OP_IO_WRITE		0x03
+
+/* All byte enables */
+#define MSG_BYTE_ENABLE		0xf0
+
+#ifndef __ASSEMBLY__
+
+/**
+ * msg_port_setup - set up the message port control register
+ *
+ * @op:     message bus access opcode
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ */
+void msg_port_setup(int op, int port, int reg);
+
+/**
+ * msg_port_read - read a message port register using normal opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_read(u8 port, u32 reg);
+
+/**
+ * msg_port_write - write a message port register using normal opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ * @value:  register value to write
+ */
+void msg_port_write(u8 port, u32 reg, u32 value);
+
+/**
+ * msg_port_alt_read - read a message port register using alternative opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_alt_read(u8 port, u32 reg);
+
+/**
+ * msg_port_alt_write - write a message port register using alternative opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ * @value:  register value to write
+ */
+void msg_port_alt_write(u8 port, u32 reg, u32 value);
+
+/**
+ * msg_port_io_read - read a message port register using I/O opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ *
+ * @return: message port register value
+ */
+u32 msg_port_io_read(u8 port, u32 reg);
+
+/**
+ * msg_port_io_write - write a message port register using I/O opcode
+ *
+ * @port:   port number on the message bus
+ * @reg:    register number within a port
+ * @value:  register value to write
+ */
+void msg_port_io_write(u8 port, u32 reg, u32 value);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _QUARK_MSG_PORT_H_ */
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h
new file mode 100644
index 0000000..ceb583e
--- /dev/null
+++ b/arch/x86/include/asm/arch-quark/quark.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _QUARK_H_
+#define _QUARK_H_
+
+/* Message Bus Ports */
+#define MSG_PORT_MEM_ARBITER	0x00
+#define MSG_PORT_HOST_BRIDGE	0x03
+#define MSG_PORT_RMU		0x04
+#define MSG_PORT_MEM_MGR	0x05
+#define MSG_PORT_SOC_UNIT	0x31
+
+/* Port 0x00: Memory Arbiter Message Port Registers */
+
+/* Enhanced Configuration Space */
+#define AEC_CTRL		0x00
+
+/* Port 0x03: Host Bridge Message Port Registers */
+
+/* Host Memory I/O Boundary */
+#define HM_BOUND		0x08
+
+/* Extended Configuration Space */
+#define HEC_REG			0x09
+
+/* Port 0x04: Remote Management Unit Message Port Registers */
+
+/* ACPI PBLK Base Address Register */
+#define PBLK_BA			0x70
+
+/* SPI DMA Base Address Register */
+#define SPI_DMA_BA		0x7a
+
+/* Port 0x05: Memory Manager Message Port Registers */
+
+/* eSRAM Block Page Control */
+#define ESRAM_BLK_CTRL		0x82
+#define ESRAM_BLOCK_MODE	0x10000000
+
+/* DRAM */
+#define DRAM_BASE		0x00000000
+#define DRAM_MAX_SIZE		0x80000000
+
+/* eSRAM */
+#define ESRAM_SIZE		0x80000
+
+/* Memory BAR Enable */
+#define MEM_BAR_EN		0x00000001
+
+/* I/O BAR Enable */
+#define IO_BAR_EN		0x80000000
+
+/* 64KiB of RMU binary in flash */
+#define RMU_BINARY_SIZE		0x10000
+
+/* Legacy Bridge PCI Configuration Registers */
+#define LB_GBA			0x44
+#define LB_PM1BLK		0x48
+#define LB_GPE0BLK		0x4c
+#define LB_ACTL			0x58
+#define LB_PABCDRC		0x60
+#define LB_PEFGHRC		0x64
+#define LB_WDTBA		0x84
+#define LB_BCE			0xd4
+#define LB_BC			0xd8
+#define LB_RCBA			0xf0
+
+#endif /* _QUARK_H_ */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
index bce58b1..3c57558 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h
@@ -10,8 +10,6 @@
 #ifndef __VPDHEADER_H__
 #define __VPDHEADER_H__
 
-#define UPD_TERMINATOR	0x55AA
-
 struct __packed upd_region {
 	u64	sign;			/* Offset 0x0000 */
 	u64	reserved;		/* Offset 0x0008 */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h b/arch/x86/include/asm/fsp/fsp_api.h
similarity index 87%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h
rename to arch/x86/include/asm/fsp/fsp_api.h
index a9d7156..2d34d13 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h
+++ b/arch/x86/include/asm/fsp/fsp_api.h
@@ -8,6 +8,8 @@
 #ifndef __FSP_API_H__
 #define __FSP_API_H__
 
+#include <linux/linkage.h>
+
 /*
  * FspInit continuation function prototype.
  * Control will be returned to this callback function after FspInit API call.
@@ -47,9 +49,9 @@
 };
 
 /* FspInit API function prototype */
-typedef u32 (*fsp_init_f)(struct fsp_init_params *params);
+typedef asmlinkage u32 (*fsp_init_f)(struct fsp_init_params *params);
 
 /* FspNotify API function prototype */
-typedef u32 (*fsp_notify_f)(struct fsp_notify_params *params);
+typedef asmlinkage u32 (*fsp_notify_f)(struct fsp_notify_params *params);
 
 #endif
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h b/arch/x86/include/asm/fsp/fsp_bootmode.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h
rename to arch/x86/include/asm/fsp/fsp_bootmode.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp/fsp_ffs.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h
rename to arch/x86/include/asm/fsp/fsp_ffs.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h
rename to arch/x86/include/asm/fsp/fsp_fv.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
rename to arch/x86/include/asm/fsp/fsp_hob.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h
rename to arch/x86/include/asm/fsp/fsp_infoheader.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h b/arch/x86/include/asm/fsp/fsp_platform.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h
rename to arch/x86/include/asm/fsp/fsp_platform.h
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
similarity index 97%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
rename to arch/x86/include/asm/fsp/fsp_support.h
index ebdbd03..c6c7dc0 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -16,7 +16,7 @@
 #include "fsp_platform.h"
 #include "fsp_infoheader.h"
 #include "fsp_bootmode.h"
-#include "fsp_vpd.h"
+#include <asm/arch/fsp/fsp_vpd.h>
 
 struct shared_data {
 	struct fsp_header	*fsp_hdr;
@@ -26,6 +26,8 @@
 
 #define FSP_LOWMEM_BASE		0x100000UL
 #define FSP_HIGHMEM_BASE	0x100000000ULL
+#define UPD_TERMINATOR		0x55AA
+
 
 /**
  * FSP Continuation assembly helper routine
@@ -61,7 +63,7 @@
  *
  * @retval: the offset of FSP header. If signature is invalid, returns 0.
  */
-u32 find_fsp_header(void);
+struct fsp_header *find_fsp_header(void);
 
 /**
  * FSP initialization wrapper function.
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h
similarity index 100%
rename from arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h
rename to arch/x86/include/asm/fsp/fsp_types.h
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index c30dd4c..a153dd1 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -1,4 +1,3 @@
-
 /*
  * (C) Copyright 2002
  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
@@ -9,6 +8,14 @@
 #ifndef _PCI_I386_H_
 #define _PCI_I386_H_
 
+/* bus mapping constants (used for PCI core initialization) */
+#define PCI_REG_ADDR	0xcf8
+#define PCI_REG_DATA	0xcfc
+
+#define PCI_CFG_EN	0x80000000
+
+#ifndef __ASSEMBLY__
+
 #define DEFINE_PCI_DEVICE_TABLE(_table) \
 	const struct pci_device_id _table[]
 
@@ -49,4 +56,6 @@
 void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value);
 void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value);
 
-#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PCI_I386_H_ */
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index b98afa8..c743efd 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -26,15 +26,9 @@
 void timer_set_base(uint64_t base);
 int pcat_timer_init(void);
 
-/* Architecture specific DRAM init */
-int dram_init(void);
-
 /* cpu/.../interrupts.c */
 int cpu_init_interrupts(void);
 
-/* board/.../... */
-int dram_init(void);
-
 int cleanup_before_linux(void);
 int x86_cleanup_before_linux(void);
 void x86_enable_caches(void);
@@ -45,6 +39,9 @@
 void dram_init_banksize(void);
 int default_print_cpuinfo(void);
 
+/* Set up a UART which can be used with printch(), printhex8(), etc. */
+int setup_early_uart(void);
+
 void setup_pcat_compatibility(void);
 
 void isa_unmap_rom(u32 addr);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 32d7b98..c17f7f0 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_SYS_X86_TSC_TIMER)	+= tsc_timer.o
 obj-$(CONFIG_VIDEO_VGA)	+= video.o
 obj-$(CONFIG_CMD_ZBOOT)	+= zimage.o
+obj-$(CONFIG_HAVE_FSP) += fsp/
 
 extra-$(CONFIG_USE_PRIVATE_LIBGCC) := lib.a
 
diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c
index a0ef037..915746a 100644
--- a/arch/x86/lib/cmd_hob.c
+++ b/arch/x86/lib/cmd_hob.c
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <command.h>
 #include <linux/compiler.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile
new file mode 100644
index 0000000..5b12c12
--- /dev/null
+++ b/arch/x86/lib/fsp/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2015 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += fsp_car.o
+obj-y += fsp_common.o
+obj-y += fsp_dram.o
+obj-y += fsp_support.o
diff --git a/arch/x86/cpu/queensbay/tnc_car.S b/arch/x86/lib/fsp/fsp_car.S
similarity index 100%
rename from arch/x86/cpu/queensbay/tnc_car.S
rename to arch/x86/lib/fsp/fsp_car.S
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
new file mode 100644
index 0000000..f668259
--- /dev/null
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/fsp/fsp_support.h>
+
+int print_cpuinfo(void)
+{
+	post_code(POST_CPU_INFO);
+	return default_print_cpuinfo();
+}
+
+void reset_cpu(ulong addr)
+{
+	/* cold reset */
+	outb(0x06, PORT_RESET);
+}
+
+
+int board_pci_post_scan(struct pci_controller *hose)
+{
+	u32 status;
+
+	/* call into FspNotify */
+	debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
+	status = fsp_notify(NULL, INIT_PHASE_PCI);
+	if (status != FSP_SUCCESS)
+		debug("fail, error code %x\n", status);
+	else
+		debug("OK\n");
+
+	return 0;
+}
+
+void board_final_cleanup(void)
+{
+	u32 status;
+
+	/* call into FspNotify */
+	debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
+	status = fsp_notify(NULL, INIT_PHASE_BOOT);
+	if (status != FSP_SUCCESS)
+		debug("fail, error code %x\n", status);
+	else
+		debug("OK\n");
+
+	return;
+}
diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/lib/fsp/fsp_dram.c
similarity index 97%
rename from arch/x86/cpu/queensbay/tnc_dram.c
rename to arch/x86/lib/fsp/fsp_dram.c
index df79a39..4c0a7c8 100644
--- a/arch/x86/cpu/queensbay/tnc_dram.c
+++ b/arch/x86/lib/fsp/fsp_dram.c
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 #include <asm/e820.h>
 #include <asm/post.h>
 
diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
similarity index 96%
rename from arch/x86/cpu/queensbay/fsp_support.c
rename to arch/x86/lib/fsp/fsp_support.c
index aed3e2b..5f96da1 100644
--- a/arch/x86/cpu/queensbay/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -6,7 +6,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/fsp/fsp_support.h>
+#include <asm/fsp/fsp_support.h>
 #include <asm/post.h>
 
 /**
@@ -30,7 +30,7 @@
 		return false;
 }
 
-u32 __attribute__((optimize("O0"))) find_fsp_header(void)
+struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
 {
 	/*
 	 * This function may be called before the a stack is established,
@@ -84,7 +84,7 @@
 		fsp = 0;
 	}
 
-	return (u32)fsp;
+	return (struct fsp_header *)fsp;
 }
 
 void fsp_continue(struct shared_data *shared_data, u32 status, void *hob_list)
@@ -124,25 +124,29 @@
 	struct fsp_init_params *params_ptr;
 	struct upd_region *fsp_upd;
 
-	fsp_hdr = (struct fsp_header *)find_fsp_header();
+#ifdef CONFIG_DEBUG_UART
+	setup_early_uart();
+#endif
+
+	fsp_hdr = find_fsp_header();
 	if (fsp_hdr == NULL) {
 		/* No valid FSP info header was found */
 		panic("Invalid FSP header");
 	}
 
-	fsp_upd = (struct upd_region *)&shared_data.fsp_upd;
+	fsp_upd = &shared_data.fsp_upd;
 	memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
 
 	/* Reserve a gap in stack top */
 	rt_buf.common.stack_top = (u32 *)stack_top - 32;
 	rt_buf.common.boot_mode = boot_mode;
-	rt_buf.common.upd_data = (struct upd_region *)fsp_upd;
+	rt_buf.common.upd_data = fsp_upd;
 
 	/* Get VPD region start */
 	fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
 			fsp_hdr->cfg_region_off);
 
-	/* Verifify the VPD data region is valid */
+	/* Verify the VPD data region is valid */
 	assert((fsp_vpd->img_rev == VPD_IMAGE_REV) &&
 	       (fsp_vpd->sign == VPD_IMAGE_ID));
 
@@ -150,7 +154,7 @@
 	memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
 	       sizeof(struct upd_region));
 
-	/* Verifify the UPD data region is valid */
+	/* Verify the UPD data region is valid */
 	assert(fsp_upd->terminator == UPD_TERMINATOR);
 
 	/* Override any UPD setting if required */
diff --git a/arch/x86/lib/pci_type1.c b/arch/x86/lib/pci_type1.c
index 13942a3..a251adc 100644
--- a/arch/x86/lib/pci_type1.c
+++ b/arch/x86/lib/pci_type1.c
@@ -12,6 +12,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <pci.h>
+#include <asm/pci.h>
 
 #define cfg_read(val, addr, op)		(*val = op((int)(addr)))
 #define cfg_write(val, addr, op)	op((val), (int)(addr))
@@ -21,7 +22,7 @@
 type1_##rw##_config_##size(struct pci_controller *hose,			\
 			      pci_dev_t dev, int offset, type val)	\
 {									\
-	outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr);	\
+	outl(dev | (offset & 0xfc) | PCI_CFG_EN, (int)hose->cfg_addr);	\
 	cfg_##rw(val, hose->cfg_data + (offset & mask), op);		\
 	return 0;							\
 }
@@ -34,10 +35,6 @@
 TYPE1_PCI_OP(write, word, u16, outw, 2)
 TYPE1_PCI_OP(write, dword, u32, outl, 0)
 
-/* bus mapping constants (used for PCI core initialization) */
-#define PCI_REG_ADDR		0x00000cf8
-#define PCI_REG_DATA		0x00000cfc
-
 void pci_setup_type1(struct pci_controller *hose)
 {
 	pci_set_ops(hose,
diff --git a/board/BuS/eb_cpux9k2/Kconfig b/board/BuS/eb_cpux9k2/Kconfig
index 230e64d..e2a787a 100644
--- a/board/BuS/eb_cpux9k2/Kconfig
+++ b/board/BuS/eb_cpux9k2/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "BuS"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "eb_cpux9k2"
 
diff --git a/board/BuS/eb_cpux9k2/cpux9k2.c b/board/BuS/eb_cpux9k2/cpux9k2.c
index 5e4778e..76ad7c4 100644
--- a/board/BuS/eb_cpux9k2/cpux9k2.c
+++ b/board/BuS/eb_cpux9k2/cpux9k2.c
@@ -98,7 +98,7 @@
 				puts("Error: invalid MAC at EEPROM\n");
 		}
 	}
-	gd->jt[XF_do_reset] = (void *) do_reset;
+	gd->jt->do_reset = do_reset;
 
 #ifdef CONFIG_STATUS_LED
 	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
diff --git a/board/BuS/vl_ma2sc/Kconfig b/board/BuS/vl_ma2sc/Kconfig
index 2f43519..848177f 100644
--- a/board/BuS/vl_ma2sc/Kconfig
+++ b/board/BuS/vl_ma2sc/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "BuS"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "vl_ma2sc"
 
diff --git a/board/Marvell/db-mv784mp-gp/binary.0 b/board/Marvell/db-mv784mp-gp/binary.0
deleted file mode 100644
index 17bfad9..0000000
--- a/board/Marvell/db-mv784mp-gp/binary.0
+++ /dev/null
@@ -1,17 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
-
diff --git a/board/Marvell/db-mv784mp-gp/kwbimage.cfg b/board/Marvell/db-mv784mp-gp/kwbimage.cfg
index d7ef407..cc05792 100644
--- a/board/Marvell/db-mv784mp-gp/kwbimage.cfg
+++ b/board/Marvell/db-mv784mp-gp/kwbimage.cfg
@@ -9,4 +9,4 @@
 BOOT_FROM	spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY board/Marvell/db-mv784mp-gp/binary.0 0000005b 00000068
+BINARY spl/u-boot-spl.bin 0000005b 00000068
diff --git a/board/afeb9260/Kconfig b/board/afeb9260/Kconfig
index 6a5a931..fb64c9c 100644
--- a/board/afeb9260/Kconfig
+++ b/board/afeb9260/Kconfig
@@ -3,9 +3,6 @@
 config SYS_BOARD
 	default "afeb9260"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "afeb9260"
 
diff --git a/board/amcc/canyonlands/Kconfig b/board/amcc/canyonlands/Kconfig
index 530a6ef..848e08f 100644
--- a/board/amcc/canyonlands/Kconfig
+++ b/board/amcc/canyonlands/Kconfig
@@ -9,4 +9,42 @@
 config SYS_CONFIG_NAME
 	default "canyonlands"
 
+choice BOARD_TYPE
+	prompt "Select which board to build for"
+
+config CANYONLANDS
+	bool "Glacier"
+	help
+	  Select this to build for the Canyonlands 460EX board.
+
+config GLACIER
+	bool "Glacier"
+	help
+	  Select this to build for the Glacier 460GT board.
+
+config ARCHES
+	bool "Arches"
+	help
+	  Select this to build for the Arches dual 460GT board.
+
+endchoice
+
+config DISPLAY_BOARDINFO
+	bool
+	default y
+
+config DM
+	default y
+
+config DM_SERIAL
+	default y
+
+config SYS_MALLOC_F
+	bool
+	default y
+
+config SYS_MALLOC_F_LEN
+	hex
+	default 0x400
+
 endif
diff --git a/board/amcc/canyonlands/MAINTAINERS b/board/amcc/canyonlands/MAINTAINERS
index 52bf004..8be8a52 100644
--- a/board/amcc/canyonlands/MAINTAINERS
+++ b/board/amcc/canyonlands/MAINTAINERS
@@ -6,3 +6,4 @@
 F:	configs/arches_defconfig
 F:	configs/canyonlands_defconfig
 F:	configs/glacier_defconfig
+F:	configs/glacier_ramboot_defconfig
diff --git a/board/amcc/canyonlands/config.mk b/board/amcc/canyonlands/config.mk
index 63b8973..5cc90d2 100644
--- a/board/amcc/canyonlands/config.mk
+++ b/board/amcc/canyonlands/config.mk
@@ -8,8 +8,6 @@
 # AMCC 460EX/460GT Evaluation Board (Canyonlands) board
 #
 
-PLATFORM_CPPFLAGS += -DCONFIG_440=1
-
 ifeq ($(debug),1)
 PLATFORM_CPPFLAGS += -DDEBUG
 endif
diff --git a/board/amcc/canyonlands/u-boot-ram.lds b/board/amcc/canyonlands/u-boot-ram.lds
new file mode 100644
index 0000000..1750c74
--- /dev/null
+++ b/board/amcc/canyonlands/u-boot-ram.lds
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .text      :
+  {
+    _image_copy_start = .;
+    arch/powerpc/cpu/ppc4xx/start.o	(.text*)
+    board/amcc/canyonlands/init.o	(.text*)
+
+    *(.text*)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    KEEP(*(.got))
+    _GOT2_TABLE_ = .;
+    KEEP(*(.got2))
+    _FIXUP_TABLE_ = .;
+    KEEP(*(.fixup))
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data*)
+    *(.sdata*)
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+
+  .u_boot_list : {
+	KEEP(*(SORT(.u_boot_list*)));
+  }
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : {
+	*(.data.init)
+	. = ALIGN(256);
+	LONG(0) LONG(0)		/* Extend u-boot.bin to here */
+  }
+  __init_end = .;
+  _end = .;
+  _image_binary_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   *(.bss*)
+   *(.sbss*)
+   *(COMMON)
+   . = ALIGN(4);
+  }
+
+  __bss_end = . ;
+  PROVIDE (end = .);
+}
diff --git a/board/aristainetos/aristainetos.c b/board/aristainetos/aristainetos.c
index 67ac260..8330bb6 100644
--- a/board/aristainetos/aristainetos.c
+++ b/board/aristainetos/aristainetos.c
@@ -321,8 +321,8 @@
 	/* enable backlight PWM 3 */
 	if (pwm_init(2, 0, 0))
 		goto error;
-	/* duty cycle 200ns, period: 3000ns */
-	if (pwm_config(2, 200, 3000))
+	/* duty cycle 500ns, period: 3000ns */
+	if (pwm_config(2, 500, 3000))
 		goto error;
 	if (pwm_enable(2))
 		goto error;
@@ -350,8 +350,8 @@
 			.right_margin   = 88,
 			.upper_margin   = 10,
 			.lower_margin   = 10,
-			.hsync_len      = 25,
-			.vsync_len      = 1,
+			.hsync_len      = 80,
+			.vsync_len      = 25,
 			.sync           = 0,
 			.vmode          = FB_VMODE_NONINTERLACED
 		}
diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig
index 7ebea63..7d5e7be 100644
--- a/board/armltd/vexpress64/Kconfig
+++ b/board/armltd/vexpress64/Kconfig
@@ -1,4 +1,30 @@
-if TARGET_VEXPRESS_AEMV8A
+if TARGET_VEXPRESS64_AEMV8A
+
+config SYS_BOARD
+	default "vexpress64"
+
+config SYS_VENDOR
+	default "armltd"
+
+config SYS_CONFIG_NAME
+	default "vexpress_aemv8a"
+
+endif
+
+if TARGET_VEXPRESS64_BASE_FVP
+
+config SYS_BOARD
+	default "vexpress64"
+
+config SYS_VENDOR
+	default "armltd"
+
+config SYS_CONFIG_NAME
+	default "vexpress_aemv8a"
+
+endif
+
+if TARGET_VEXPRESS64_JUNO
 
 config SYS_BOARD
 	default "vexpress64"
diff --git a/board/armltd/vexpress64/MAINTAINERS b/board/armltd/vexpress64/MAINTAINERS
index 66c8dff..0ba044d 100644
--- a/board/armltd/vexpress64/MAINTAINERS
+++ b/board/armltd/vexpress64/MAINTAINERS
@@ -9,3 +9,8 @@
 M:	Linus Walleij <linus.walleij@linaro.org>
 S:	Maintained
 F:	configs/vexpress_aemv8a_semi_defconfig
+
+JUNO DEVELOPMENT PLATFORM BOARD
+M:	Linus Walleij <linus.walleij@linaro.org>
+S:	Maintained
+F:	configs/vexpress_aemv8a_juno_defconfig
diff --git a/board/atmel/at91rm9200ek/Kconfig b/board/atmel/at91rm9200ek/Kconfig
index bad4a37..952351d 100644
--- a/board/atmel/at91rm9200ek/Kconfig
+++ b/board/atmel/at91rm9200ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91rm9200ek"
 
diff --git a/board/atmel/at91sam9260ek/Kconfig b/board/atmel/at91sam9260ek/Kconfig
index fe00ed5..3844f08 100644
--- a/board/atmel/at91sam9260ek/Kconfig
+++ b/board/atmel/at91sam9260ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9260ek"
 
diff --git a/board/atmel/at91sam9261ek/Kconfig b/board/atmel/at91sam9261ek/Kconfig
index d839c1a..2971b3c 100644
--- a/board/atmel/at91sam9261ek/Kconfig
+++ b/board/atmel/at91sam9261ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9261ek"
 
diff --git a/board/atmel/at91sam9263ek/Kconfig b/board/atmel/at91sam9263ek/Kconfig
index 311c504..3f0873f 100644
--- a/board/atmel/at91sam9263ek/Kconfig
+++ b/board/atmel/at91sam9263ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9263ek"
 
diff --git a/board/atmel/at91sam9m10g45ek/Kconfig b/board/atmel/at91sam9m10g45ek/Kconfig
index 1bc086a..211c411 100644
--- a/board/atmel/at91sam9m10g45ek/Kconfig
+++ b/board/atmel/at91sam9m10g45ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9m10g45ek"
 
diff --git a/board/atmel/at91sam9n12ek/Kconfig b/board/atmel/at91sam9n12ek/Kconfig
index cf1d1a3..816003a 100644
--- a/board/atmel/at91sam9n12ek/Kconfig
+++ b/board/atmel/at91sam9n12ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9n12ek"
 
diff --git a/board/atmel/at91sam9rlek/Kconfig b/board/atmel/at91sam9rlek/Kconfig
index 438d300..81a839a 100644
--- a/board/atmel/at91sam9rlek/Kconfig
+++ b/board/atmel/at91sam9rlek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9rlek"
 
diff --git a/board/atmel/at91sam9x5ek/Kconfig b/board/atmel/at91sam9x5ek/Kconfig
index 5c5ec61..3f92754 100644
--- a/board/atmel/at91sam9x5ek/Kconfig
+++ b/board/atmel/at91sam9x5ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "at91sam9x5ek"
 
diff --git a/board/atmel/atngw100/atngw100.c b/board/atmel/atngw100/atngw100.c
index 03d767a..dacd427 100644
--- a/board/atmel/atngw100/atngw100.c
+++ b/board/atmel/atngw100/atngw100.c
@@ -18,14 +18,14 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -52,6 +52,8 @@
 	hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
 
 	portmux_enable_ebi(16, 23, 0, PORTMUX_DRIVE_HIGH);
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
 
 #if defined(CONFIG_MACB)
@@ -68,24 +70,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x01;
diff --git a/board/atmel/atngw100mkii/atngw100mkii.c b/board/atmel/atngw100mkii/atngw100mkii.c
index 72d19e4..8e215d5 100644
--- a/board/atmel/atngw100mkii/atngw100mkii.c
+++ b/board/atmel/atngw100mkii/atngw100mkii.c
@@ -23,21 +23,21 @@
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
 		/* Atmel AT49BV640D 8 MiB x16 NOR flash on NCS0 */
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
 		/* Micron MT29F2G16AAD 256 MiB x16 NAND flash on NCS3 */
-		.virt_pgno	= EBI_SRAM_CS3_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SRAM_CS3_SIZE >> PAGE_SHIFT,
-		.phys		= (EBI_SRAM_CS3_BASE >> PAGE_SHIFT)
+		.virt_pgno	= EBI_SRAM_CS3_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SRAM_CS3_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (EBI_SRAM_CS3_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
 		/* 2x16-bit ISSI IS42S16320B 64 MiB SDRAM (128 MiB total) */
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -69,6 +69,9 @@
 	portmux_select_gpio(PORTMUX_PORT_E, 1 << 23,
 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH
 			| PORTMUX_DRIVE_MIN);
+
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
 
 #if defined(CONFIG_MACB)
@@ -85,24 +88,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x01;
diff --git a/board/atmel/atstk1000/atstk1000.c b/board/atmel/atstk1000/atstk1000.c
index 4b6b90f..fd4363b 100644
--- a/board/atmel/atstk1000/atstk1000.c
+++ b/board/atmel/atstk1000/atstk1000.c
@@ -17,14 +17,14 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -78,7 +78,10 @@
 	hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
 
 	portmux_enable_ebi(sdram_config.data_bits, 23, 0, PORTMUX_DRIVE_HIGH);
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
+
 #if defined(CONFIG_MACB)
 	portmux_enable_macb0(PORTMUX_MACB_MII, PORTMUX_DRIVE_LOW);
 	portmux_enable_macb1(PORTMUX_MACB_MII, PORTMUX_DRIVE_LOW);
@@ -90,24 +93,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x10;
diff --git a/board/atmel/sama5d3_xplained/Kconfig b/board/atmel/sama5d3_xplained/Kconfig
index 0ba8a7b..2df751a 100644
--- a/board/atmel/sama5d3_xplained/Kconfig
+++ b/board/atmel/sama5d3_xplained/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "sama5d3_xplained"
 
diff --git a/board/atmel/sama5d3xek/Kconfig b/board/atmel/sama5d3xek/Kconfig
index 2a9ed23..abd1ad8 100644
--- a/board/atmel/sama5d3xek/Kconfig
+++ b/board/atmel/sama5d3xek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "sama5d3xek"
 
diff --git a/board/atmel/sama5d4_xplained/Kconfig b/board/atmel/sama5d4_xplained/Kconfig
index f320a68..2cb03cb 100644
--- a/board/atmel/sama5d4_xplained/Kconfig
+++ b/board/atmel/sama5d4_xplained/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "sama5d4_xplained"
 
diff --git a/board/atmel/sama5d4_xplained/sama5d4_xplained.c b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
index 1c5b92c..bc2aa38 100644
--- a/board/atmel/sama5d4_xplained/sama5d4_xplained.c
+++ b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
@@ -10,6 +10,7 @@
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_rstc.h>
+#include <asm/arch/atmel_mpddrc.h>
 #include <asm/arch/atmel_usba_udc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
@@ -326,3 +327,87 @@
 
 	return rc;
 }
+
+/* SPL */
+#ifdef CONFIG_SPL_BUILD
+void spl_board_init(void)
+{
+#ifdef CONFIG_SYS_USE_MMC
+	sama5d4_xplained_mci1_hw_init();
+#elif CONFIG_SYS_USE_NANDFLASH
+	sama5d4_xplained_nand_hw_init();
+#elif CONFIG_SYS_USE_SERIALFLASH
+	sama5d4_xplained_spi0_hw_init();
+#endif
+}
+
+static void ddr2_conf(struct atmel_mpddr *ddr2)
+{
+	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
+
+	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+		    ATMEL_MPDDRC_CR_NR_ROW_14 |
+		    ATMEL_MPDDRC_CR_CAS_DDR_CAS3 |
+		    ATMEL_MPDDRC_CR_NB_8BANKS |
+		    ATMEL_MPDDRC_CR_NDQS_DISABLED |
+		    ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+		    ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
+
+	ddr2->rtr = 0x2b0;
+
+	ddr2->tpr0 = (8 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
+		      10 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
+
+	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET |
+		      200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+		      25 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+		      23 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
+
+	ddr2->tpr2 = (7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+		      8 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	struct atmel_mpddr ddr2;
+
+	ddr2_conf(&ddr2);
+
+	/* enable MPDDR clock */
+	at91_periph_clk_enable(ATMEL_ID_MPDDRC);
+	writel(0x4, &pmc->scer);
+
+	/* DDRAM2 Controller initialize */
+	ddr2_init(ATMEL_BASE_DDRCS, &ddr2);
+}
+
+void at91_pmc_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = AT91_PMC_PLLAR_29 |
+	      AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
+	      AT91_PMC_PLLXR_MUL(87) |
+	      AT91_PMC_PLLXR_DIV(1);
+	at91_plla_init(tmp);
+
+	writel(0x0 << 8, &pmc->pllicpr);
+
+	tmp = AT91_PMC_MCKR_H32MXDIV |
+	      AT91_PMC_MCKR_PLLADIV_2 |
+	      AT91_PMC_MCKR_MDIV_3 |
+	      AT91_PMC_MCKR_CSS_PLLA;
+	at91_mck_init(tmp);
+}
+#endif
diff --git a/board/atmel/sama5d4ek/Kconfig b/board/atmel/sama5d4ek/Kconfig
index 7dc569c..1a63403 100644
--- a/board/atmel/sama5d4ek/Kconfig
+++ b/board/atmel/sama5d4ek/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "atmel"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "sama5d4ek"
 
diff --git a/board/atmel/sama5d4ek/sama5d4ek.c b/board/atmel/sama5d4ek/sama5d4ek.c
index d8ff648..46e5041 100644
--- a/board/atmel/sama5d4ek/sama5d4ek.c
+++ b/board/atmel/sama5d4ek/sama5d4ek.c
@@ -10,6 +10,7 @@
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_rstc.h>
+#include <asm/arch/atmel_mpddrc.h>
 #include <asm/arch/atmel_usba_udc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
@@ -325,3 +326,87 @@
 
 	return rc;
 }
+
+/* SPL */
+#ifdef CONFIG_SPL_BUILD
+void spl_board_init(void)
+{
+#ifdef CONFIG_SYS_USE_MMC
+	sama5d4ek_mci1_hw_init();
+#elif CONFIG_SYS_USE_NANDFLASH
+	sama5d4ek_nand_hw_init();
+#elif CONFIG_SYS_USE_SERIALFLASH
+	sama5d4ek_spi0_hw_init();
+#endif
+}
+
+static void ddr2_conf(struct atmel_mpddr *ddr2)
+{
+	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
+
+	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+		    ATMEL_MPDDRC_CR_NR_ROW_14 |
+		    ATMEL_MPDDRC_CR_CAS_DDR_CAS3 |
+		    ATMEL_MPDDRC_CR_NB_8BANKS |
+		    ATMEL_MPDDRC_CR_NDQS_DISABLED |
+		    ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+		    ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
+
+	ddr2->rtr = 0x2b0;
+
+	ddr2->tpr0 = (8 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
+		      10 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
+
+	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET |
+		      200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+		      25 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+		      23 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
+
+	ddr2->tpr2 = (7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+		      2 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+		      8 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	struct atmel_mpddr ddr2;
+
+	ddr2_conf(&ddr2);
+
+	/* enable MPDDR clock */
+	at91_periph_clk_enable(ATMEL_ID_MPDDRC);
+	writel(0x4, &pmc->scer);
+
+	/* DDRAM2 Controller initialize */
+	ddr2_init(ATMEL_BASE_DDRCS, &ddr2);
+}
+
+void at91_pmc_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = AT91_PMC_PLLAR_29 |
+	      AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
+	      AT91_PMC_PLLXR_MUL(87) |
+	      AT91_PMC_PLLXR_DIV(1);
+	at91_plla_init(tmp);
+
+	writel(0x0 << 8, &pmc->pllicpr);
+
+	tmp = AT91_PMC_MCKR_H32MXDIV |
+	      AT91_PMC_MCKR_PLLADIV_2 |
+	      AT91_PMC_MCKR_MDIV_3 |
+	      AT91_PMC_MCKR_CSS_PLLA;
+	at91_mck_init(tmp);
+}
+#endif
diff --git a/board/avionic-design/common/tamonten-ng.c b/board/avionic-design/common/tamonten-ng.c
index 86a0844..1704627 100644
--- a/board/avionic-design/common/tamonten-ng.c
+++ b/board/avionic-design/common/tamonten-ng.c
@@ -55,12 +55,12 @@
 	struct udevice *dev;
 	int ret;
 
-	ret = i2c_get_chip_for_busnum(4, PMU_I2C_ADDRESS, &dev);
+	ret = i2c_get_chip_for_busnum(4, PMU_I2C_ADDRESS, 1, &dev);
 	if (ret) {
 		debug("%s: Cannot find PMIC I2C chip\n", __func__);
 		return;
 	}
-	i2c_write(dev, reg, &data, 1);
+	dm_i2c_write(dev, reg, &data, 1);
 }
 
 /*
diff --git a/board/bachmann/ot1200/Makefile b/board/bachmann/ot1200/Makefile
index 1bd42e8..9e50bfe 100644
--- a/board/bachmann/ot1200/Makefile
+++ b/board/bachmann/ot1200/Makefile
@@ -6,4 +6,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifdef CONFIG_SPL_BUILD
+obj-y  := ot1200.o ot1200_spl.o
+else
 obj-y  := ot1200.o
+endif
diff --git a/board/bachmann/ot1200/mx6q_4x_mt41j128.cfg b/board/bachmann/ot1200/mx6q_4x_mt41j128.cfg
index bb6c60b..c25f99d 100644
--- a/board/bachmann/ot1200/mx6q_4x_mt41j128.cfg
+++ b/board/bachmann/ot1200/mx6q_4x_mt41j128.cfg
@@ -142,20 +142,6 @@
 DATA 4 0x021b001c 0x00000000
 DATA 4 0x021b0404 0x00011006
 
-/* set the default clock gate to save power */
-DATA 4 0x020c4068 0x00C03F3F
-DATA 4 0x020c406c 0x0030FC03
-DATA 4 0x020c4070 0x0FFFC000
-DATA 4 0x020c4074 0x3FF00000
-DATA 4 0x020c4078 0x00FFF300
-DATA 4 0x020c407c 0x0F0000C3
-DATA 4 0x020c4080 0x000003FF
-
-/* enable AXI cache for VDOA/VPU/IPU */
-DATA 4 0x020e0010 0xF00000CF
-/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
-DATA 4 0x020e0018 0x007F007F
-DATA 4 0x020e001c 0x007F007F
 
 /*
  * Setup CCM_CCOSR register as follows:
diff --git a/board/bachmann/ot1200/ot1200.c b/board/bachmann/ot1200/ot1200.c
index 93f3d65..e434ed9 100644
--- a/board/bachmann/ot1200/ot1200.c
+++ b/board/bachmann/ot1200/ot1200.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/iomux.h>
@@ -16,6 +17,7 @@
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/boot_mode.h>
 #include <asm/arch/crm_regs.h>
+#include <asm/arch/sys_proto.h>
 #include <mmc.h>
 #include <fsl_esdhc.h>
 #include <netdev.h>
@@ -46,7 +48,7 @@
 
 int dram_init(void)
 {
-	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+	gd->ram_size = imx_ddr_size();
 
 	return 0;
 }
@@ -118,8 +120,35 @@
 		ARRAY_SIZE(feature_pads));
 }
 
+static void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	writel(0x00C03F3F, &ccm->CCGR0);
+	writel(0x0030FC33, &ccm->CCGR1);
+	writel(0x0FFFC000, &ccm->CCGR2);
+	writel(0x3FF00000, &ccm->CCGR3);
+	writel(0x00FFF300, &ccm->CCGR4);
+	writel(0x0F0000C3, &ccm->CCGR5);
+	writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void gpr_init(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* enable AXI cache for VDOA/VPU/IPU */
+	writel(0xF00000CF, &iomux->gpr[4]);
+	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+	writel(0x007F007F, &iomux->gpr[6]);
+	writel(0x007F007F, &iomux->gpr[7]);
+}
+
 int board_early_init_f(void)
 {
+	ccgr_init();
+	gpr_init();
+
 	setup_iomux_uart();
 	setup_iomux_spi();
 	setup_iomux_features();
@@ -290,9 +319,6 @@
 
 	leds_on();
 
-	/* enable ecspi3 clocks */
-	enable_cspi_clock(1, 2);
-
 #ifdef CONFIG_CMD_SATA
 	setup_sata();
 #endif
diff --git a/board/bachmann/ot1200/ot1200_spl.c b/board/bachmann/ot1200/ot1200_spl.c
new file mode 100644
index 0000000..9c77fd3
--- /dev/null
+++ b/board/bachmann/ot1200/ot1200_spl.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015, Bachmann electronic GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/arch/mx6-ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+static struct mx6dq_iomux_ddr_regs ot1200_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 48ohm */
+	.dram_sdclk_0   = 0x00000028,
+	.dram_sdclk_1   = 0x00000028,
+	.dram_cas       = 0x00000028,
+	.dram_ras       = 0x00000028,
+	.dram_reset     = 0x00000028,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0    = 0x00003000,
+	.dram_sdcke1    = 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2	    = 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 48 ohm */
+	.dram_sdodt0    = 0x00000028,
+	.dram_sdodt1    = 0x00000028,
+	/* SDQS[0:7]: Differential input, 48 ohm */
+	.dram_sdqs0     = 0x00000028,
+	.dram_sdqs1     = 0x00000028,
+	.dram_sdqs2     = 0x00000028,
+	.dram_sdqs3     = 0x00000028,
+	.dram_sdqs4     = 0x00000028,
+	.dram_sdqs5     = 0x00000028,
+	.dram_sdqs6     = 0x00000028,
+	.dram_sdqs7     = 0x00000028,
+	/* DQM[0:7]: Differential input, 48 ohm */
+	.dram_dqm0      = 0x00000028,
+	.dram_dqm1      = 0x00000028,
+	.dram_dqm2      = 0x00000028,
+	.dram_dqm3      = 0x00000028,
+	.dram_dqm4      = 0x00000028,
+	.dram_dqm5      = 0x00000028,
+	.dram_dqm6      = 0x00000028,
+	.dram_dqm7      = 0x00000028,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+static struct mx6dq_iomux_grp_regs ot1200_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type    = 0x000c0000,
+	.grp_ddrmode_ctl = 0x00020000,
+	/* Disable DDR pullups */
+	.grp_ddrpke      = 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 48 ohm */
+	.grp_addds       = 0x00000028,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 48 ohm */
+	.grp_ctlds       = 0x00000028,
+	/* DATA[00:63]: Differential input, 48 ohm */
+	.grp_ddrmode     = 0x00020000,
+	.grp_b0ds        = 0x00000028,
+	.grp_b1ds        = 0x00000028,
+	.grp_b2ds        = 0x00000028,
+	.grp_b3ds        = 0x00000028,
+	.grp_b4ds        = 0x00000028,
+	.grp_b5ds        = 0x00000028,
+	.grp_b6ds        = 0x00000028,
+	.grp_b7ds        = 0x00000028,
+};
+
+static struct mx6_ddr_sysinfo ot1200_ddr_sysinfo = {
+	/* Width of data bus: 0=16, 1=32, 2=64 */
+	.dsize      = 2,
+	/* config for full 4GB range so that get_mem_size() works */
+	.cs_density = 32, /* 32Gb per CS */
+	/* Single chip select */
+	.ncs        = 1,
+	.cs1_mirror = 0,	/* war 0 */
+	.rtt_wr     = 1,	/* DDR3_RTT_60_OHM - RTT_Wr = RZQ/4 */
+	.rtt_nom    = 1,	/* DDR3_RTT_60_OHM - RTT_Nom = RZQ/4 */
+	.walat      = 1,	/* Write additional latency */
+	.ralat      = 5,	/* Read additional latency */
+	.mif3_mode  = 3,	/* Command prediction working mode */
+	.bi_on      = 1,	/* Bank interleaving enabled */	/* war 1 */
+	.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+	.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+};
+
+/* MT41K128M16JT-125 */
+static struct mx6_ddr3_cfg micron_2gib_1600 = {
+	.mem_speed = 1600,
+	.density   = 2,
+	.width     = 16,
+	.banks     = 8,
+	.rowaddr   = 14,
+	.coladdr   = 10,
+	.pagesz    = 2,
+	.trcd      = 1375,
+	.trcmin    = 4875,
+	.trasmin   = 3500,
+	.SRT       = 1,
+};
+
+static struct mx6_mmdc_calibration micron_2gib_1600_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x00260025,
+	.p0_mpwldectrl1 = 0x00270021,
+	.p1_mpwldectrl0 = 0x00180034,
+	.p1_mpwldectrl1 = 0x00180024,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0   = 0x04380344,
+	.p0_mpdgctrl1   = 0x0330032C,
+	.p1_mpdgctrl0   = 0x0338033C,
+	.p1_mpdgctrl1   = 0x032C0300,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl   = 0x3C2E3238,
+	.p1_mprddlctl   = 0x3A2E303C,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl   = 0x36384036,
+	.p1_mpwrdlctl   = 0x442E4438,
+};
+
+static void ot1200_spl_dram_init(void)
+{
+	mx6dq_dram_iocfg(64, &ot1200_ddr_ioregs, &ot1200_grp_ioregs);
+	mx6_dram_cfg(&ot1200_ddr_sysinfo, &micron_2gib_1600_mmdc_calib,
+		     &micron_2gib_1600);
+}
+
+/*
+ * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+	/* setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	/* iomux and setup of i2c */
+	board_early_init_f();
+
+	/* setup GP timer */
+	timer_init();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* configure MMDC for SDRAM width/size and per-model calibration */
+	ot1200_spl_dram_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
diff --git a/board/barco/platinum/Kconfig b/board/barco/platinum/Kconfig
new file mode 100644
index 0000000..8bbad24
--- /dev/null
+++ b/board/barco/platinum/Kconfig
@@ -0,0 +1,37 @@
+if TARGET_PLATINUM_PICON
+
+config SYS_CPU
+	default "armv7"
+
+config SYS_VENDOR
+	default "barco"
+
+config SYS_SOC
+	default "mx6"
+
+config SYS_BOARD
+	default "platinum"
+
+config SYS_CONFIG_NAME
+	default "platinum_picon"
+
+endif
+
+if TARGET_PLATINUM_TITANIUM
+
+config SYS_CPU
+	default "armv7"
+
+config SYS_VENDOR
+	default "barco"
+
+config SYS_SOC
+	default "mx6"
+
+config SYS_BOARD
+	default "platinum"
+
+config SYS_CONFIG_NAME
+	default "platinum_titanium"
+
+endif
diff --git a/board/barco/platinum/MAINTAINERS b/board/barco/platinum/MAINTAINERS
new file mode 100644
index 0000000..a22584b
--- /dev/null
+++ b/board/barco/platinum/MAINTAINERS
@@ -0,0 +1,7 @@
+PLATINUM BOARD
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+F:	board/barco/platinum/
+F:	include/configs/platinum.h
+F:	configs/platinum_picon_defconfig
+F:	configs/platinum_titanium_defconfig
diff --git a/board/barco/platinum/Makefile b/board/barco/platinum/Makefile
new file mode 100644
index 0000000..abc9419
--- /dev/null
+++ b/board/barco/platinum/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2014, Barco (www.barco.com)
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y := platinum.o
+obj-$(CONFIG_TARGET_PLATINUM_PICON)     += platinum_picon.o
+obj-$(CONFIG_TARGET_PLATINUM_TITANIUM)  += platinum_titanium.o
+
+ifneq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_TARGET_PLATINUM_PICON) += spl_picon.o
+obj-$(CONFIG_TARGET_PLATINUM_TITANIUM) += spl_titanium.o
+endif
diff --git a/board/barco/platinum/platinum.c b/board/barco/platinum/platinum.c
new file mode 100644
index 0000000..1485a48
--- /dev/null
+++ b/board/barco/platinum/platinum.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/boot_mode.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+iomux_v3_cfg_t const usdhc3_pads[] = {
+	MX6_PAD_SD3_CLK__SD3_CLK	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_CMD__SD3_CMD	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT0__SD3_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT1__SD3_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT2__SD3_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT3__SD3_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	MX6_PAD_SD3_DAT5__GPIO7_IO00	| MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+iomux_v3_cfg_t nfc_pads[] = {
+	MX6_PAD_NANDF_CLE__NAND_CLE		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_ALE__NAND_ALE		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_WP_B__NAND_WP_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_RB0__NAND_READY_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_CS0__NAND_CE0_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_CS1__NAND_CE1_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_CS2__NAND_CE2_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_CS3__NAND_CE3_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD4_CMD__NAND_RE_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD4_CLK__NAND_WE_B		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D0__NAND_DATA00		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D1__NAND_DATA01		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D2__NAND_DATA02		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D3__NAND_DATA03		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D4__NAND_DATA04		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D5__NAND_DATA05		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D6__NAND_DATA06		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_NANDF_D7__NAND_DATA07		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD4_DAT0__NAND_DQS		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+struct fsl_esdhc_cfg usdhc_cfg[] = {
+	{ USDHC3_BASE_ADDR },
+};
+
+void setup_gpmi_nand(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	/* config gpmi nand iomux */
+	imx_iomux_v3_setup_multiple_pads(nfc_pads, ARRAY_SIZE(nfc_pads));
+
+	/* config gpmi and bch clock to 100 MHz */
+	clrsetbits_le32(&mxc_ccm->cs2cdr,
+			MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+			MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+			MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+			MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+			MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
+			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
+
+	/* enable gpmi and bch clock gating */
+	setbits_le32(&mxc_ccm->CCGR4,
+		     MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+		     MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+
+	/* enable apbh clock gating */
+	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
+}
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+	return 0;
+}
+
+int board_ehci_hcd_init(int port)
+{
+	return 0;
+}
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+
+	if (cfg->esdhc_base == usdhc_cfg[0].esdhc_base) {
+		unsigned sd3_cd = IMX_GPIO_NR(7, 0);
+		gpio_direction_input(sd3_cd);
+		return !gpio_get_value(sd3_cd);
+	}
+
+	return 0;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+
+	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+}
+
+void board_init_gpio(void)
+{
+	platinum_init_gpio();
+}
+
+void board_init_gpmi_nand(void)
+{
+	setup_gpmi_nand();
+}
+
+void board_init_i2c(void)
+{
+	platinum_setup_i2c();
+}
+
+void board_init_spi(void)
+{
+	platinum_setup_spi();
+}
+
+void board_init_uart(void)
+{
+	platinum_setup_uart();
+}
+
+void board_init_usb(void)
+{
+	platinum_init_usb();
+}
+
+void board_init_finished(void)
+{
+	platinum_init_finished();
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	return platinum_phy_config(phydev);
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return cpu_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+	board_init_uart();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+	board_init_spi();
+
+	board_init_i2c();
+
+	board_init_gpmi_nand();
+
+	board_init_gpio();
+
+	board_init_usb();
+
+	board_init_finished();
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: " CONFIG_PLATINUM_BOARD "\n");
+	return 0;
+}
+
+static const struct boot_mode board_boot_modes[] = {
+	/* NAND */
+	{ "nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00) },
+	/* 4 bit bus width */
+	{ "mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00) },
+	{ "mmc1", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00) },
+	{ NULL, 0 },
+};
+
+int misc_init_r(void)
+{
+	add_board_boot_modes(board_boot_modes);
+
+	return 0;
+}
diff --git a/board/barco/platinum/platinum.h b/board/barco/platinum/platinum.h
new file mode 100644
index 0000000..d3ea8bd
--- /dev/null
+++ b/board/barco/platinum/platinum.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _PLATINUM_H_
+#define _PLATINUM_H_
+
+#include <miiphy.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+
+/* Defines */
+
+#define ECSPI1_PAD_CLK		(PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_DOWN | \
+				 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_40ohm | \
+				 PAD_CTL_HYS)
+#define ECSPI2_PAD_CLK		(PAD_CTL_SRE_FAST | PAD_CTL_PUS_100K_DOWN | \
+				 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+				 PAD_CTL_HYS)
+#define ECSPI_PAD_MOSI		(PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_DOWN | \
+				 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_120ohm | \
+				 PAD_CTL_HYS)
+#define ECSPI_PAD_MISO		(PAD_CTL_SRE_FAST | PAD_CTL_PUS_100K_DOWN | \
+				 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_40ohm | \
+				 PAD_CTL_HYS)
+#define ECSPI_PAD_SS		(PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_UP | \
+				 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_120ohm | \
+				 PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL		(PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+				 PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define I2C_PAD_CTRL		(PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+				 PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
+				 PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define I2C_PAD_CTRL_SCL	(PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
+				 PAD_CTL_DSE_80ohm | PAD_CTL_HYS | \
+				 PAD_CTL_ODE | PAD_CTL_SRE_SLOW)
+
+#define UART_PAD_CTRL		(PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+				 PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | \
+				 PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL		(PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW | \
+				PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | \
+				PAD_CTL_HYS)
+
+
+#define PC			MUX_PAD_CTRL(I2C_PAD_CTRL)
+#define PC_SCL			MUX_PAD_CTRL(I2C_PAD_CTRL_SCL)
+
+/* Prototypes */
+
+int platinum_setup_enet(void);
+int platinum_setup_i2c(void);
+int platinum_setup_spi(void);
+int platinum_setup_uart(void);
+int platinum_phy_config(struct phy_device *phydev);
+int platinum_init_gpio(void);
+int platinum_init_usb(void);
+int platinum_init_finished(void);
+
+static inline void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	writel(0x00C03F3F, &ccm->CCGR0);
+	writel(0x0030FC03, &ccm->CCGR1);
+	writel(0x0FFFC000, &ccm->CCGR2);
+	writel(0x3FF00000, &ccm->CCGR3);
+	writel(0xFFFFF300, &ccm->CCGR4);	/* enable NAND/GPMI/BCH clks */
+	writel(0x0F0000C3, &ccm->CCGR5);
+	writel(0x000003FF, &ccm->CCGR6);
+}
+
+static inline void gpr_init(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* enable AXI cache for VDOA/VPU/IPU */
+	writel(0xF00000CF, &iomux->gpr[4]);
+	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+	writel(0x007F007F, &iomux->gpr[6]);
+	writel(0x007F007F, &iomux->gpr[7]);
+}
+
+#endif /* _PLATINUM_H_ */
diff --git a/board/barco/platinum/platinum_picon.c b/board/barco/platinum/platinum_picon.c
new file mode 100644
index 0000000..b2eab76
--- /dev/null
+++ b/board/barco/platinum/platinum_picon.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <i2c.h>
+#include <miiphy.h>
+
+#include "platinum.h"
+
+#define GPIO_IP_NCONFIG		IMX_GPIO_NR(5, 18)
+#define GPIO_HK_NCONFIG		IMX_GPIO_NR(7, 13)
+#define GPIO_LS_NCONFIG		IMX_GPIO_NR(5, 19)
+
+#define GPIO_I2C0_SEL0		IMX_GPIO_NR(5,  2)
+#define GPIO_I2C0_SEL1		IMX_GPIO_NR(1, 11)
+#define GPIO_I2C0_ENBN		IMX_GPIO_NR(1, 13)
+
+#define GPIO_I2C2_SEL0		IMX_GPIO_NR(1, 17)
+#define GPIO_I2C2_SEL1		IMX_GPIO_NR(1, 20)
+#define GPIO_I2C2_ENBN		IMX_GPIO_NR(1, 14)
+
+#define GPIO_USB_RESET		IMX_GPIO_NR(1,  5)
+
+iomux_v3_cfg_t const ecspi1_pads[] = {
+	MX6_PAD_EIM_D16__ECSPI1_SCLK		| MUX_PAD_CTRL(ECSPI1_PAD_CLK),
+	MX6_PAD_EIM_D17__ECSPI1_MISO		| MUX_PAD_CTRL(ECSPI_PAD_MISO),
+	MX6_PAD_EIM_D18__ECSPI1_MOSI		| MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+	MX6_PAD_CSI0_DAT7__ECSPI1_SS0		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+	MX6_PAD_EIM_D24__ECSPI1_SS2		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+	MX6_PAD_EIM_D25__ECSPI1_SS3		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const ecspi2_pads[] = {
+	MX6_PAD_EIM_CS0__ECSPI2_SCLK		| MUX_PAD_CTRL(ECSPI2_PAD_CLK),
+	MX6_PAD_EIM_OE__ECSPI2_MISO		| MUX_PAD_CTRL(ECSPI_PAD_MISO),
+	MX6_PAD_EIM_CS1__ECSPI2_MOSI		| MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+	MX6_PAD_EIM_RW__ECSPI2_SS0		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+	MX6_PAD_EIM_LBA__ECSPI2_SS1		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const enet_pads[] = {
+	MX6_PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_CRS_DV__ENET_RX_EN		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_GPIO_16__ENET_REF_CLK		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RX_ER__ENET_RX_ER		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RXD0__ENET_RX_DATA0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_RXD1__ENET_RX_DATA1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_TX_EN__ENET_TX_EN		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_TXD0__ENET_TX_DATA0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_TXD1__ENET_TX_DATA1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+
+/* PHY nRESET */
+iomux_v3_cfg_t const phy_reset_pad = {
+	MX6_PAD_SD1_DAT2__GPIO1_IO19		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart1_pads[] = {
+	MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart4_pads[] = {
+	MX6_PAD_CSI0_DAT12__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT13__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT16__UART4_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT17__UART4_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart5_pads[] = {
+	MX6_PAD_CSI0_DAT14__UART5_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT15__UART5_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT18__UART5_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT19__UART5_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const i2c0_mux_pads[] = {
+	MX6_PAD_EIM_A25__GPIO5_IO02		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD2_CMD__GPIO1_IO11		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD2_DAT2__GPIO1_IO13		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const i2c2_mux_pads[] = {
+	MX6_PAD_SD1_DAT1__GPIO1_IO17		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD1_CLK__GPIO1_IO20		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_SD2_DAT1__GPIO1_IO14		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+struct i2c_pads_info i2c_pad_info0 = {
+	.scl = {
+		.i2c_mode  = MX6_PAD_CSI0_DAT9__I2C1_SCL	| PC_SCL,
+		.gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27	| PC_SCL,
+		.gp = IMX_GPIO_NR(5, 27)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA		| PC,
+		.gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26	| PC,
+		.gp = IMX_GPIO_NR(5, 26)
+	 }
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL		| PC_SCL,
+		.gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03		| PC_SCL,
+		.gp = IMX_GPIO_NR(1, 3)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA		| PC,
+		.gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06		| PC,
+		.gp = IMX_GPIO_NR(1, 6)
+	 }
+};
+
+/*
+ * This enet related pin-muxing and GPIO handling is done
+ * in SPL U-Boot. For early initialization. And to give the
+ * PHY some time to come out of reset before the U-Boot
+ * ethernet driver tries to access its registers via MDIO.
+ */
+int platinum_setup_enet(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+	unsigned phy_reset = IMX_GPIO_NR(1, 19);
+
+	/* First configure PHY reset GPIO pin */
+	imx_iomux_v3_setup_pad(phy_reset_pad);
+
+	/* Reconfigure enet muxing while PHY is in reset */
+	gpio_direction_output(phy_reset, 0);
+	imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+	mdelay(10);
+	gpio_set_value(phy_reset, 1);
+	udelay(100);
+
+	/* set GPIO_16 as ENET_REF_CLK_OUT */
+	setbits_le32(&iomux->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
+
+	return enable_fec_anatop_clock(ENET_50MHZ);
+}
+
+int platinum_setup_i2c(void)
+{
+	imx_iomux_v3_setup_multiple_pads(i2c0_mux_pads,
+					 ARRAY_SIZE(i2c0_mux_pads));
+	imx_iomux_v3_setup_multiple_pads(i2c2_mux_pads,
+					 ARRAY_SIZE(i2c2_mux_pads));
+
+	mdelay(10);
+
+	/* Disable i2c mux 0 */
+	gpio_direction_output(GPIO_I2C0_SEL0, 0);
+	gpio_direction_output(GPIO_I2C0_SEL1, 0);
+	gpio_direction_output(GPIO_I2C0_ENBN, 1);
+
+	/* Disable i2c mux 1 */
+	gpio_direction_output(GPIO_I2C2_SEL0, 0);
+	gpio_direction_output(GPIO_I2C2_SEL1, 0);
+	gpio_direction_output(GPIO_I2C2_ENBN, 1);
+
+	udelay(10);
+
+	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+	/* Disable all leds */
+	i2c_set_bus_num(0);
+	i2c_reg_write(0x60, 0x05, 0x55);
+
+	return 0;
+}
+
+int platinum_setup_spi(void)
+{
+	imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+	imx_iomux_v3_setup_multiple_pads(ecspi2_pads, ARRAY_SIZE(ecspi2_pads));
+
+	return 0;
+}
+
+int platinum_setup_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
+	imx_iomux_v3_setup_multiple_pads(uart5_pads, ARRAY_SIZE(uart5_pads));
+
+	return 0;
+}
+
+int platinum_phy_config(struct phy_device *phydev)
+{
+	/* Use generic infrastructure, no specific setup */
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
+int platinum_init_gpio(void)
+{
+	/* Reset FPGA's */
+	gpio_direction_output(GPIO_IP_NCONFIG, 0);
+	gpio_direction_output(GPIO_HK_NCONFIG, 0);
+	gpio_direction_output(GPIO_LS_NCONFIG, 0);
+	udelay(3);
+	gpio_set_value(GPIO_IP_NCONFIG, 1);
+	gpio_set_value(GPIO_HK_NCONFIG, 1);
+	gpio_set_value(GPIO_LS_NCONFIG, 1);
+
+	/* no dmd configuration yet */
+
+	return 0;
+}
+
+int platinum_init_usb(void)
+{
+	/* Reset usb hub */
+	gpio_direction_output(GPIO_USB_RESET, 0);
+	udelay(100);
+	gpio_set_value(GPIO_USB_RESET, 1);
+
+	return 0;
+}
+
+int platinum_init_finished(void)
+{
+	/* Enable led 0 */
+	i2c_set_bus_num(0);
+	i2c_reg_write(0x60, 0x05, 0x54);
+
+	return 0;
+}
diff --git a/board/barco/platinum/platinum_titanium.c b/board/barco/platinum/platinum_titanium.c
new file mode 100644
index 0000000..73a955f
--- /dev/null
+++ b/board/barco/platinum/platinum_titanium.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <miiphy.h>
+#include <micrel.h>
+
+#include "platinum.h"
+
+iomux_v3_cfg_t const ecspi1_pads[] = {
+	MX6_PAD_EIM_D16__ECSPI1_SCLK		| MUX_PAD_CTRL(ECSPI1_PAD_CLK),
+	MX6_PAD_EIM_D17__ECSPI1_MISO		| MUX_PAD_CTRL(ECSPI_PAD_MISO),
+	MX6_PAD_EIM_D18__ECSPI1_MOSI		| MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+	MX6_PAD_CSI0_DAT7__ECSPI1_SS0		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+	/* non mounted spi nor flash for booting */
+	MX6_PAD_EIM_D19__ECSPI1_SS1		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	MX6_PAD_EIM_D24__ECSPI1_SS2		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+	MX6_PAD_EIM_D25__ECSPI1_SS3		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const ecspi2_pads[] = {
+	MX6_PAD_EIM_CS0__ECSPI2_SCLK		| MUX_PAD_CTRL(ECSPI2_PAD_CLK),
+	MX6_PAD_EIM_OE__ECSPI2_MISO		| MUX_PAD_CTRL(ECSPI_PAD_MISO),
+	MX6_PAD_EIM_CS1__ECSPI2_MOSI		| MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+	MX6_PAD_EIM_RW__ECSPI2_SS0		| MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const enet_pads1[] = {
+	MX6_PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TXC__RGMII_TXC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD0__RGMII_TD0		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD1__RGMII_TD1		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD2__RGMII_TD2		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TD3__RGMII_TD3		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	/* pin 35 - 1 (PHY_AD2) on reset */
+	MX6_PAD_RGMII_RXC__GPIO6_IO30		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 32 - 1 - (MODE0) all */
+	MX6_PAD_RGMII_RD0__GPIO6_IO25		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 31 - 1 - (MODE1) all */
+	MX6_PAD_RGMII_RD1__GPIO6_IO27		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 28 - 1 - (MODE2) all */
+	MX6_PAD_RGMII_RD2__GPIO6_IO28		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 27 - 1 - (MODE3) all */
+	MX6_PAD_RGMII_RD3__GPIO6_IO29		| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
+	MX6_PAD_RGMII_RX_CTL__GPIO6_IO24	| MUX_PAD_CTRL(NO_PAD_CTRL),
+	/* pin 42 PHY nRST */
+	MX6_PAD_EIM_D23__GPIO3_IO23		| MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const enet_pads2[] = {
+	MX6_PAD_RGMII_RXC__RGMII_RXC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD0__RGMII_RD0		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD1__RGMII_RD1		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD2__RGMII_RD2		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RD3__RGMII_RD3		| MUX_PAD_CTRL(ENET_PAD_CTRL),
+	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart1_pads[] = {
+	MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart2_pads[] = {
+	MX6_PAD_EIM_D26__UART2_TX_DATA   | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D27__UART2_RX_DATA   | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D28__UART2_DTE_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_EIM_D29__UART2_RTS_B     | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart4_pads[] = {
+	MX6_PAD_CSI0_DAT12__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT13__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT16__UART4_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+	MX6_PAD_CSI0_DAT17__UART4_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+struct i2c_pads_info i2c_pad_info0 = {
+	.scl = {
+		.i2c_mode  = MX6_PAD_CSI0_DAT9__I2C1_SCL	| PC_SCL,
+		.gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27	| PC_SCL,
+		.gp = IMX_GPIO_NR(5, 27)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA		| PC,
+		.gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26	| PC,
+		.gp = IMX_GPIO_NR(5, 26)
+	 }
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL		| PC_SCL,
+		.gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03		| PC_SCL,
+		.gp = IMX_GPIO_NR(1, 3)
+	},
+	.sda = {
+		.i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA		| PC,
+		.gpio_mode = MX6_PAD_GPIO_16__GPIO7_IO11	| PC,
+		.gp = IMX_GPIO_NR(7, 11)
+	 }
+};
+
+/*
+ * This enet related pin-muxing and GPIO handling is done
+ * in SPL U-Boot. For early initialization. And to give the
+ * PHY some time to come out of reset before the U-Boot
+ * ethernet driver tries to access its registers via MDIO.
+ */
+int platinum_setup_enet(void)
+{
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+	gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
+	imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
+	gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
+
+	/* Need delay 10ms according to KSZ9021 spec */
+	mdelay(10);
+	gpio_set_value(IMX_GPIO_NR(3, 23), 1);
+	udelay(100);
+
+	imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
+
+	return 0;
+}
+
+int platinum_setup_i2c(void)
+{
+	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+	return 0;
+}
+
+int platinum_setup_spi(void)
+{
+	imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+	imx_iomux_v3_setup_multiple_pads(ecspi2_pads, ARRAY_SIZE(ecspi2_pads));
+
+	return 0;
+}
+
+int platinum_setup_uart(void)
+{
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
+
+	return 0;
+}
+
+int platinum_phy_config(struct phy_device *phydev)
+{
+	/* min rx data delay */
+	ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW,
+				   0x0);
+	/* min tx data delay */
+	ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW,
+				   0x0);
+	/* max rx/tx clock delay, min rx/tx control */
+	ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_CLOCK_SKEW,
+				   0xf0f0);
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
+int platinum_init_gpio(void)
+{
+	/* Default GPIO's */
+	/* Toggle CONFIG_n to reset fpga on every boot */
+	gpio_direction_output(IMX_GPIO_NR(5, 18), 0);
+	/* Need delay >=2uS */
+	udelay(3);
+	gpio_set_value(IMX_GPIO_NR(5, 18), 1);
+
+	/* Default pin 1,15 high - DLP_FLASH_WPZ */
+	gpio_direction_output(IMX_GPIO_NR(1, 15), 1);
+
+	return 0;
+}
+
+int platinum_init_usb(void)
+{
+	return 0;
+}
+
+int platinum_init_finished(void)
+{
+	return 0;
+}
diff --git a/board/barco/platinum/spl_picon.c b/board/barco/platinum/spl_picon.c
new file mode 100644
index 0000000..f421c21
--- /dev/null
+++ b/board/barco/platinum/spl_picon.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * Based on: gw_ventana_spl.c which is:
+ * Copyright (C) 2014 Gateworks Corporation
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <spl.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef RTT_NOM_120OHM	/* use 120ohm Rtt_nom vs 60ohm (lower power) */
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+	.dram_sdclk_0 = 0x00020030,
+	.dram_sdclk_1 = 0x00020030,
+	.dram_cas = 0x00020030,
+	.dram_ras = 0x00020030,
+	.dram_reset = 0x00020030,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2 = 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 40 ohm */
+	.dram_sdodt0 = 0x00003030,
+	.dram_sdodt1 = 0x00003030,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.dram_sdqs0 = 0x00000030,
+	.dram_sdqs1 = 0x00000030,
+	.dram_sdqs2 = 0x00000030,
+	.dram_sdqs3 = 0x00000030,
+	.dram_sdqs4 = 0x00000030,
+	.dram_sdqs5 = 0x00000030,
+	.dram_sdqs6 = 0x00000030,
+	.dram_sdqs7 = 0x00000030,
+	/* DQM[0:7]: Differential input, 40 ohm */
+	.dram_dqm0 = 0x00020030,
+	.dram_dqm1 = 0x00020030,
+	.dram_dqm2 = 0x00020030,
+	.dram_dqm3 = 0x00020030,
+	.dram_dqm4 = 0x00020030,
+	.dram_dqm5 = 0x00020030,
+	.dram_dqm6 = 0x00020030,
+	.dram_dqm7 = 0x00020030,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type = 0x000c0000,
+	.grp_ddrmode_ctl = 0x00020000,
+	/* disable DDR pullups */
+	.grp_ddrpke = 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
+	.grp_addds = 0x00000030,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+	.grp_ctlds = 0x00000030,
+	/* DATA[00:63]: Differential input, 40 ohm */
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = 0x00000030,
+	.grp_b1ds = 0x00000030,
+	.grp_b2ds = 0x00000030,
+	.grp_b3ds = 0x00000030,
+	.grp_b4ds = 0x00000030,
+	.grp_b5ds = 0x00000030,
+	.grp_b6ds = 0x00000030,
+	.grp_b7ds = 0x00000030,
+};
+
+/* MT41K256M16HA-125 */
+static struct mx6_ddr3_cfg mt41k256m16ha_125 = {
+	.mem_speed = 1600,
+	.density = 4,		/* 4Gbit */
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 15,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+/*
+ * Values from running the Freescale DDR stress tool via USB
+ */
+static struct mx6_mmdc_calibration mx6dq_mmdc_calib = {
+	/* write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x0044004E,
+	.p0_mpwldectrl1 = 0x001F0023,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x02480248,
+	.p0_mpdgctrl1 = 0x0210021C,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x42444444,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x36322C32,
+};
+
+static void spl_dram_init(int width)
+{
+	struct mx6_ddr3_cfg *mem = &mt41k256m16ha_125;
+	struct mx6_ddr_sysinfo sysinfo = {
+		/* width of data bus:0=16,1=32,2=64 */
+		.dsize = width / 32,
+		/* config for full 4GB range so that get_mem_size() works */
+		.cs_density = 32, /* 32Gb per CS */
+		/* single chip select */
+		.ncs = 1,
+		.cs1_mirror = 1,
+		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+		.rtt_nom = 2 /*DDR3_RTT_120_OHM*/,	/* RTT_Nom = RZQ/2 */
+#else
+		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
+#endif
+		.walat = 0,	/* Write additional latency */
+		.ralat = 5,	/* Read additional latency */
+		.mif3_mode = 3,	/* Command prediction working mode */
+		.bi_on = 1,	/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+	};
+
+	mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, &mx6dq_mmdc_calib, mem);
+}
+
+/*
+ * Called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+	/* Setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	ccgr_init();
+	gpr_init();
+
+	/* UART iomux */
+	board_early_init_f();
+
+	/* Setup GP timer */
+	timer_init();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* Init DDR with 32bit width */
+	spl_dram_init(32);
+
+	/* Clear the BSS */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/*
+	 * Setup enet related MUXing early to give the PHY
+	 * some time to wake-up from reset
+	 */
+	platinum_setup_enet();
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
diff --git a/board/barco/platinum/spl_titanium.c b/board/barco/platinum/spl_titanium.c
new file mode 100644
index 0000000..26fe26b
--- /dev/null
+++ b/board/barco/platinum/spl_titanium.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * Based on: gw_ventana_spl.c which is:
+ * Copyright (C) 2014 Gateworks Corporation
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <spl.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef RTT_NOM_120OHM	/* use 120ohm Rtt_nom vs 60ohm (lower power) */
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
+	/* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+	.dram_sdclk_0 = 0x00020030,
+	.dram_sdclk_1 = 0x00020030,
+	.dram_cas = 0x00020030,
+	.dram_ras = 0x00020030,
+	.dram_reset = 0x00020030,
+	/* SDCKE[0:1]: 100k pull-up */
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	/* SDBA2: pull-up disabled */
+	.dram_sdba2 = 0x00000000,
+	/* SDODT[0:1]: 100k pull-up, 40 ohm */
+	.dram_sdodt0 = 0x00003030,
+	.dram_sdodt1 = 0x00003030,
+	/* SDQS[0:7]: Differential input, 40 ohm */
+	.dram_sdqs0 = 0x00000030,
+	.dram_sdqs1 = 0x00000030,
+	.dram_sdqs2 = 0x00000030,
+	.dram_sdqs3 = 0x00000030,
+	.dram_sdqs4 = 0x00000030,
+	.dram_sdqs5 = 0x00000030,
+	.dram_sdqs6 = 0x00000030,
+	.dram_sdqs7 = 0x00000030,
+	/* DQM[0:7]: Differential input, 40 ohm */
+	.dram_dqm0 = 0x00020030,
+	.dram_dqm1 = 0x00020030,
+	.dram_dqm2 = 0x00020030,
+	.dram_dqm3 = 0x00020030,
+	.dram_dqm4 = 0x00020030,
+	.dram_dqm5 = 0x00020030,
+	.dram_dqm6 = 0x00020030,
+	.dram_dqm7 = 0x00020030,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type = 0x000c0000,
+	.grp_ddrmode_ctl = 0x00020000,
+	/* disable DDR pullups */
+	.grp_ddrpke = 0x00000000,
+	/* ADDR[00:16], SDBA[0:1]: 40 ohm */
+	.grp_addds = 0x00000030,
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+	.grp_ctlds = 0x00000030,
+	/* DATA[00:63]: Differential input, 40 ohm */
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = 0x00000030,
+	.grp_b1ds = 0x00000030,
+	.grp_b2ds = 0x00000030,
+	.grp_b3ds = 0x00000030,
+	.grp_b4ds = 0x00000030,
+	.grp_b5ds = 0x00000030,
+	.grp_b6ds = 0x00000030,
+	.grp_b7ds = 0x00000030,
+};
+
+/* MT41J128M16JT-125 */
+static struct mx6_ddr3_cfg mt41j128m16jt_125 = {
+	.mem_speed = 1600,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+static struct mx6_mmdc_calibration mx6dq_mmdc_calib = {
+	/* Write leveling calibration determine */
+	.p0_mpwldectrl0 = 0x001f001f,
+	.p0_mpwldectrl1 = 0x001f001f,
+	.p1_mpwldectrl0 = 0x00440044,
+	.p1_mpwldectrl1 = 0x00440044,
+	/* Read DQS Gating calibration */
+	.p0_mpdgctrl0 = 0x434b0350,
+	.p0_mpdgctrl1 = 0x034c0359,
+	.p1_mpdgctrl0 = 0x434b0350,
+	.p1_mpdgctrl1 = 0x03650348,
+	/* Read Calibration: DQS delay relative to DQ read access */
+	.p0_mprddlctl = 0x4436383b,
+	.p1_mprddlctl = 0x39393341,
+	/* Write Calibration: DQ/DM delay relative to DQS write access */
+	.p0_mpwrdlctl = 0x35373933,
+	.p1_mpwrdlctl = 0x48254a36,
+};
+
+static void spl_dram_init(int width)
+{
+	struct mx6_ddr3_cfg *mem = &mt41j128m16jt_125;
+	struct mx6_ddr_sysinfo sysinfo = {
+		/* width of data bus:0=16,1=32,2=64 */
+		.dsize = width / 32,
+		/* config for full 4GB range so that get_mem_size() works */
+		.cs_density = 32, /* 32Gb per CS */
+		/* single chip select */
+		.ncs = 1,
+		.cs1_mirror = 1,
+		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+		.rtt_nom = 2 /*DDR3_RTT_120_OHM*/,	/* RTT_Nom = RZQ/2 */
+#else
+		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
+#endif
+		.walat = 0,	/* Write additional latency */
+		.ralat = 5,	/* Read additional latency */
+		.mif3_mode = 3,	/* Command prediction working mode */
+		.bi_on = 1,	/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+	};
+
+	mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, &mx6dq_mmdc_calib, mem);
+}
+
+/*
+ * Called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+	/* Setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	ccgr_init();
+	gpr_init();
+
+	/* UART iomux */
+	board_early_init_f();
+
+	/* Setup GP timer */
+	timer_init();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* Init DDR with 32bit width */
+	spl_dram_init(32);
+
+	/* Clear the BSS */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/*
+	 * Setup enet related MUXing early to give the PHY
+	 * some time to wake-up from reset
+	 */
+	platinum_setup_enet();
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
diff --git a/board/bluewater/snapper9260/Kconfig b/board/bluewater/snapper9260/Kconfig
index c896c46..b8e9cbc 100644
--- a/board/bluewater/snapper9260/Kconfig
+++ b/board/bluewater/snapper9260/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "bluewater"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "snapper9260"
 
diff --git a/board/buffalo/lsxl/README b/board/buffalo/lsxl/README
new file mode 100644
index 0000000..ef5ed42
--- /dev/null
+++ b/board/buffalo/lsxl/README
@@ -0,0 +1,139 @@
+Intro
+-----
+The Buffalo Linkstation Pro/Live, codename LS-XHL and LS-CHLv2, is a single
+disk NAS server. The PCBs of the LS-XHL and LS-CHLv2 are almost the same.
+The LS-XHL has a faster CPU and more RAM with a wider data bus, therefore
+the LS-XHL PCB has two SDRAM chips. Both have a Kirkwood CPU (Marvell
+88F6281). The only on-board storage is a 4 Mbit SPI flash which stores the
+bootloader and its environment. The linux kernel and the initial ramdisk
+are loaded from the hard disk.
+
+
+Rescue Mode
+-----------
+These linkstations don't have a populated serial port. There is no way to
+access an (unmodified) board other than using the netconsole. If you want
+to recover from a bad environment setting or an empty environment, you can
+do this only with a working network connection.
+
+Therefore, on entering the resuce mode, a random ethernet address is
+generated if no valid address could be loaded from the environment variable
+'ethaddr' and a DHCP request is sent. After a successful DHCP response is
+received, the network settings are configured and the ncip is unset. Thus
+all netconsole packets are broadcasted and you can use the netconsole to
+access board from any host within the network segment. To determine the IP
+address assigned to the board, you either have to sniff the traffic or
+check the logs/leases of your DHCP server.
+
+The resuce mode is selected by holding the push button for at least one
+second, while powering-on the device. The status LED turns solid amber if
+the resuce mode is enabled, thus providing a visual feedback.
+
+Pressing the same button for at least 10 seconds on power-up will erase the
+environment and reset the board. In this case the visual indication will
+be:
+- blinking blue, for about one second
+- solid amber, for about nine seconds
+- blinking amber, until you release the button
+
+This ensures, that you still can recover a device with a broken
+environment by first erasing the environment and then entering the rescue
+mode.
+
+Once the rescue mode is started, use the ncb binary from the tools/
+directory to access your board. There is a helper script named
+'restore_env' to save your changes. It unsets all the network variables
+which were set by the rescue mode, saves your changes and then resets the
+board.
+
+The common use case for this is setting a MAC address. Let us assume you
+have an empty environment, the board comes up with the amber LED blinking.
+Then you enter the rescue mode, connect to the board with the ncb tool and
+use the following commands to set your MAC address:
+
+  setenv ethaddr 00:00:00:00:00:00
+  run restore_env
+
+Of course you need to replace the 00:00:00:00:00:00 with your valid MAC
+address, which can be found on a sticker on the bottom of your box.
+
+
+Status LED
+----------
+blinking blue
+  Bootloader is running normally.
+
+blinking amber
+  No ethaddr set. Use the `Rescue Mode` to set one.
+
+blinking red
+  Something bad happend during loading the operating system.
+
+The default behavior of the linux kernel is to turn on the blue LED. So if
+the blinking blue LED changes to solid blue the kernel was loaded
+successfully.
+
+
+Power-on Switch
+---------------
+The power-on switch is a software switch. If it is not in ON position when
+the bootloader starts, the bootloader will disable the HDD and USB power
+and stop the fan. Then it loops until the switch is in ON position again,
+enables the power and fan again and continue booting.
+
+
+Boot sources
+------------
+The environment defines several different boot sources:
+
+legacy
+  This is the default boot source. It loads the kernel and ramdisk from the
+  attached HDD using the original filenames. The load addresses were
+  modified to support loading larger kernels. But it should behave the same
+  as the original bootloader.
+
+hdd
+  Use this for new-style booting. Loads three files /vmlinuz, /initrd.img
+  and /dtb from the boot partition. This should work out of the box if you
+  have debian and the flash-kernel package installed.
+
+usb
+  Same as hdd expect, that the files are loaded from an attached USB mass
+  storage device and the filename for the device tree is kirkwood-lsxhl.dtb
+  (or kirkwood-lschlv2.dtb).
+
+net
+  Same as usb expect, that the file are loaded from the network.
+
+rescue
+  Automatically activated if the push button is pressed for at least one
+  second on power-up. Does a DHCP request and enables the network console.
+  See `Rescue Mode` for more information.
+
+You can change the boot source by setting the 'bootsource' variable to the
+corresponding value. Please note, that the restore_env script will the the
+bootsource back to 'legacy'.
+
+
+Flash map
+---------
+00000 - 5ffff   u-boot
+60000 - 6ffff   reserved, may be used to store dtb
+70000 - 7ffff   u-boot environment
+
+
+Compiling
+---------
+make lsxhl_config (or lschlv2_config)
+make u-boot.kwb
+
+
+Update your board
+-----------------
+Just flash the resulting u-boot.kwb to the beginning of the SPI flash. If
+you already have a bootloader CLI, you can use the following commands:
+
+ sf probe 0
+ bootp ${loadaddr} u-boot.kwb
+ sf erase 0 +${filelen}
+ sf write 0 ${fileaddr} ${filesize}
diff --git a/board/calao/sbc35_a9g20/Kconfig b/board/calao/sbc35_a9g20/Kconfig
index fb5a1a3..37ecfb5 100644
--- a/board/calao/sbc35_a9g20/Kconfig
+++ b/board/calao/sbc35_a9g20/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "calao"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "sbc35_a9g20"
 
diff --git a/board/calao/tny_a9260/Kconfig b/board/calao/tny_a9260/Kconfig
index b1de8f8..2b66329 100644
--- a/board/calao/tny_a9260/Kconfig
+++ b/board/calao/tny_a9260/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "calao"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "tny_a9260"
 
diff --git a/board/calao/usb_a9263/Kconfig b/board/calao/usb_a9263/Kconfig
index 7a159dc..19e446d 100644
--- a/board/calao/usb_a9263/Kconfig
+++ b/board/calao/usb_a9263/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "calao"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "usb_a9263"
 
diff --git a/board/compulab/cm_fx6/cm_fx6.c b/board/compulab/cm_fx6/cm_fx6.c
index 84e3643..ae6945b 100644
--- a/board/compulab/cm_fx6/cm_fx6.c
+++ b/board/compulab/cm_fx6/cm_fx6.c
@@ -15,19 +15,86 @@
 #include <netdev.h>
 #include <fdt_support.h>
 #include <sata.h>
+#include <splash.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/iomux.h>
+#include <asm/arch/mxc_hdmi.h>
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/sata.h>
+#include <asm/imx-common/video.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/platform_data/serial_mxc.h>
 #include "common.h"
 #include "../common/eeprom.h"
+#include "../common/common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_SPLASH_SCREEN
+static struct splash_location cm_fx6_splash_locations[] = {
+	{
+		.name = "sf",
+		.storage = SPLASH_STORAGE_SF,
+		.offset = 0x100000,
+	},
+};
+
+int splash_screen_prepare(void)
+{
+	return splash_source_load(cm_fx6_splash_locations,
+				  ARRAY_SIZE(cm_fx6_splash_locations));
+}
+#endif
+
+#ifdef CONFIG_IMX_HDMI
+static void cm_fx6_enable_hdmi(struct display_info_t const *dev)
+{
+	imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+	{
+		.bus	= -1,
+		.addr	= 0,
+		.pixfmt	= IPU_PIX_FMT_RGB24,
+		.detect	= detect_hdmi,
+		.enable	= cm_fx6_enable_hdmi,
+		.mode	= {
+			.name           = "HDMI",
+			.refresh        = 60,
+			.xres           = 1024,
+			.yres           = 768,
+			.pixclock       = 40385,
+			.left_margin    = 220,
+			.right_margin   = 40,
+			.upper_margin   = 21,
+			.lower_margin   = 7,
+			.hsync_len      = 60,
+			.vsync_len      = 10,
+			.sync           = FB_SYNC_EXT,
+			.vmode          = FB_VMODE_NONINTERLACED,
+		}
+	},
+};
+size_t display_count = ARRAY_SIZE(displays);
+
+static void cm_fx6_setup_display(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	int reg;
+
+	enable_ipu_clock();
+	imx_setup_hdmi();
+	reg = __raw_readl(&mxc_ccm->CCGR3);
+	reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK;
+	writel(reg, &mxc_ccm->CCGR3);
+}
+#else
+static inline void cm_fx6_setup_display(void) {}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
 #ifdef CONFIG_DWC_AHSATA
 static int cm_fx6_issd_gpios[] = {
 	/* The order of the GPIOs in the array is important! */
@@ -345,32 +412,36 @@
 						MUX_PAD_CTRL(ENET_PAD_CTRL)),
 };
 
-static int handle_mac_address(void)
+static int handle_mac_address(char *env_var, uint eeprom_bus)
 {
 	unsigned char enetaddr[6];
 	int rc;
 
-	rc = eth_getenv_enetaddr("ethaddr", enetaddr);
+	rc = eth_getenv_enetaddr(env_var, enetaddr);
 	if (rc)
 		return 0;
 
-	rc = cl_eeprom_read_mac_addr(enetaddr);
+	rc = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus);
 	if (rc)
 		return rc;
 
 	if (!is_valid_ether_addr(enetaddr))
 		return -1;
 
-	return eth_setenv_enetaddr("ethaddr", enetaddr);
+	return eth_setenv_enetaddr(env_var, enetaddr);
 }
 
+#define SB_FX6_I2C_EEPROM_BUS	0
+#define NO_MAC_ADDR		"No MAC address found for %s\n"
 int board_eth_init(bd_t *bis)
 {
 	int err;
 
-	err = handle_mac_address();
-	if (err)
-		puts("No MAC address found\n");
+	if (handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS))
+		printf(NO_MAC_ADDR, "primary NIC");
+
+	if (handle_mac_address("eth1addr", SB_FX6_I2C_EEPROM_BUS))
+		printf(NO_MAC_ADDR, "secondary NIC");
 
 	SETUP_IOMUX_PADS(enet_pads);
 	/* phy reset */
@@ -464,7 +535,13 @@
 
 	/* MAC addr */
 	if (eth_getenv_enetaddr("ethaddr", enetaddr)) {
-		fdt_find_and_setprop(blob, "/fec", "local-mac-address",
+		fdt_find_and_setprop(blob,
+				     "/soc/aips-bus@02100000/ethernet@02188000",
+				     "local-mac-address", enetaddr, 6, 1);
+	}
+
+	if (eth_getenv_enetaddr("eth1addr", enetaddr)) {
+		fdt_find_and_setprop(blob, "/eth@pcie", "local-mac-address",
 				     enetaddr, 6, 1);
 	}
 
@@ -506,6 +583,8 @@
 	if (ret)
 		printf("Warning: I2C setup failed: %d\n", ret);
 
+	cm_fx6_setup_display();
+
 	return 0;
 }
 
diff --git a/board/compulab/cm_t335/Kconfig b/board/compulab/cm_t335/Kconfig
index 683efde..aadbfbc 100644
--- a/board/compulab/cm_t335/Kconfig
+++ b/board/compulab/cm_t335/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "cm_t335"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/compulab/cm_t335/cm_t335.c b/board/compulab/cm_t335/cm_t335.c
index 9583149..592ef3d 100644
--- a/board/compulab/cm_t335/cm_t335.c
+++ b/board/compulab/cm_t335/cm_t335.c
@@ -110,7 +110,7 @@
 	if (rv)
 		return 0;
 
-	rv = cl_eeprom_read_mac_addr(enetaddr);
+	rv = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
 	if (rv)
 		get_efuse_mac_addr(enetaddr);
 
diff --git a/board/compulab/cm_t35/cm_t35.c b/board/compulab/cm_t35/cm_t35.c
index 43463d5..c4ea8ea 100644
--- a/board/compulab/cm_t35/cm_t35.c
+++ b/board/compulab/cm_t35/cm_t35.c
@@ -19,6 +19,7 @@
 #include <i2c.h>
 #include <usb.h>
 #include <mmc.h>
+#include <splash.h>
 #include <twl4030.h>
 #include <linux/compiler.h>
 
@@ -59,11 +60,18 @@
 }
 #endif
 
-#define CM_T35_SPLASH_NAND_OFFSET 0x100000
+struct splash_location splash_locations[] = {
+	{
+		.name = "nand",
+		.storage = SPLASH_STORAGE_NAND,
+		.offset = 0x100000,
+	},
+};
 
 int splash_screen_prepare(void)
 {
-	return cl_splash_screen_prepare(CM_T35_SPLASH_NAND_OFFSET);
+	return splash_source_load(splash_locations,
+				  ARRAY_SIZE(splash_locations));
 }
 
 /*
@@ -429,7 +437,7 @@
 	if (rc)
 		return 0;
 
-	rc = cl_eeprom_read_mac_addr(enetaddr);
+	rc = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
 	if (rc)
 		return rc;
 
diff --git a/board/compulab/cm_t3517/cm_t3517.c b/board/compulab/cm_t3517/cm_t3517.c
index cac1ad9..624cf4c 100644
--- a/board/compulab/cm_t3517/cm_t3517.c
+++ b/board/compulab/cm_t3517/cm_t3517.c
@@ -163,7 +163,7 @@
 	if (ret)
 		return 0;
 
-	ret = cl_eeprom_read_mac_addr(enetaddr);
+	ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
 	if (ret) {
 		ret = am3517_get_efuse_enetaddr(enetaddr);
 		if (ret)
diff --git a/board/compulab/cm_t54/cm_t54.c b/board/compulab/cm_t54/cm_t54.c
index 2c2530a..fdea909 100644
--- a/board/compulab/cm_t54/cm_t54.c
+++ b/board/compulab/cm_t54/cm_t54.c
@@ -165,7 +165,7 @@
 	if (ret)
 		return 0;
 
-	ret = cl_eeprom_read_mac_addr(enetaddr);
+	ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
 	if (ret || !is_valid_ether_addr(enetaddr))
 		generate_mac_addr(enetaddr);
 
diff --git a/board/compulab/common/Makefile b/board/compulab/common/Makefile
index dbf0009..286f327 100644
--- a/board/compulab/common/Makefile
+++ b/board/compulab/common/Makefile
@@ -9,5 +9,4 @@
 obj-y				+= common.o
 obj-$(CONFIG_SYS_I2C)		+= eeprom.o
 obj-$(CONFIG_LCD)		+= omap3_display.o
-obj-$(CONFIG_SPLASH_SCREEN)	+= splash.o
 obj-$(CONFIG_SMC911X)		+= omap3_smc911x.o
diff --git a/board/compulab/common/common.h b/board/compulab/common/common.h
index 68ffb11..8f38b79 100644
--- a/board/compulab/common/common.h
+++ b/board/compulab/common/common.h
@@ -24,15 +24,6 @@
 static inline void cl_usb_hub_deinit(int gpio) {}
 #endif /* CONFIG_CMD_USB */
 
-#ifdef CONFIG_SPLASH_SCREEN
-int cl_splash_screen_prepare(int nand_offset);
-#else /* !CONFIG_SPLASH_SCREEN */
-static inline int cl_splash_screen_prepare(int nand_offset)
-{
-	return -ENOSYS;
-}
-#endif /* CONFIG_SPLASH_SCREEN */
-
 #ifdef CONFIG_SMC911X
 int cl_omap3_smc911x_init(int id, int cs, u32 base_addr,
 			  int (*reset)(int), int rst_gpio);
diff --git a/board/compulab/common/eeprom.c b/board/compulab/common/eeprom.c
index a45e7be..77bcea4 100644
--- a/board/compulab/common/eeprom.c
+++ b/board/compulab/common/eeprom.c
@@ -31,6 +31,7 @@
 #define LAYOUT_INVALID	0
 #define LAYOUT_LEGACY	0xff
 
+static int cl_eeprom_bus;
 static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */
 
 static int cl_eeprom_read(uint offset, uchar *buf, int len)
@@ -38,7 +39,7 @@
 	int res;
 	unsigned int current_i2c_bus = i2c_get_bus_num();
 
-	res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
+	res = i2c_set_bus_num(cl_eeprom_bus);
 	if (res < 0)
 		return res;
 
@@ -50,13 +51,18 @@
 	return res;
 }
 
-static int cl_eeprom_setup_layout(void)
+static int cl_eeprom_setup(uint eeprom_bus)
 {
 	int res;
 
-	if (cl_eeprom_layout != LAYOUT_INVALID)
+	/*
+	 * We know the setup was already done when the layout is set to a valid
+	 * value and we're using the same bus as before.
+	 */
+	if (cl_eeprom_layout != LAYOUT_INVALID && eeprom_bus == cl_eeprom_bus)
 		return 0;
 
+	cl_eeprom_bus = eeprom_bus;
 	res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET,
 			     (uchar *)&cl_eeprom_layout, 1);
 	if (res) {
@@ -77,7 +83,7 @@
 
 	memset(serialnr, 0, sizeof(*serialnr));
 
-	if (cl_eeprom_setup_layout())
+	if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
 		return;
 
 	offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
@@ -96,11 +102,11 @@
  * Routine: cl_eeprom_read_mac_addr
  * Description: read mac address and store it in buf.
  */
-int cl_eeprom_read_mac_addr(uchar *buf)
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
 {
 	uint offset;
 
-	if (cl_eeprom_setup_layout())
+	if (cl_eeprom_setup(eeprom_bus))
 		return 0;
 
 	offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
@@ -123,7 +129,7 @@
 	if (board_rev)
 		return board_rev;
 
-	if (cl_eeprom_setup_layout())
+	if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
 		return 0;
 
 	if (cl_eeprom_layout != LAYOUT_LEGACY)
diff --git a/board/compulab/common/eeprom.h b/board/compulab/common/eeprom.h
index 85d5bf0..50c6b02 100644
--- a/board/compulab/common/eeprom.h
+++ b/board/compulab/common/eeprom.h
@@ -11,10 +11,10 @@
 #define _EEPROM_
 
 #ifdef CONFIG_SYS_I2C
-int cl_eeprom_read_mac_addr(uchar *buf);
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus);
 u32 cl_eeprom_get_board_rev(void);
 #else
-static inline int cl_eeprom_read_mac_addr(uchar *buf)
+static inline int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
 {
 	return 1;
 }
diff --git a/board/compulab/common/splash.c b/board/compulab/common/splash.c
deleted file mode 100644
index 49ed49b..0000000
--- a/board/compulab/common/splash.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
- *
- * Authors: Igor Grinberg <grinberg@compulab.co.il>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <bmp_layout.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifdef CONFIG_CMD_NAND
-static int splash_load_from_nand(u32 bmp_load_addr, int nand_offset)
-{
-	struct bmp_header *bmp_hdr;
-	int res;
-	size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
-
-	if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
-		goto splash_address_too_high;
-
-	res = nand_read_skip_bad(&nand_info[nand_curr_device],
-			nand_offset, &bmp_header_size,
-			NULL, nand_info[nand_curr_device].size,
-			(u_char *)bmp_load_addr);
-	if (res < 0)
-		return res;
-
-	bmp_hdr = (struct bmp_header *)bmp_load_addr;
-	bmp_size = le32_to_cpu(bmp_hdr->file_size);
-
-	if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
-		goto splash_address_too_high;
-
-	return nand_read_skip_bad(&nand_info[nand_curr_device],
-			nand_offset, &bmp_size,
-			NULL, nand_info[nand_curr_device].size,
-			(u_char *)bmp_load_addr);
-
-splash_address_too_high:
-	printf("Error: splashimage address too high. Data overwrites U-Boot "
-		"and/or placed beyond DRAM boundaries.\n");
-
-	return -1;
-}
-#else
-static inline int splash_load_from_nand(u32 bmp_load_addr, int nand_offset)
-{
-	return -1;
-}
-#endif /* CONFIG_CMD_NAND */
-
-int cl_splash_screen_prepare(int nand_offset)
-{
-	char *env_splashimage_value;
-	u32 bmp_load_addr;
-
-	env_splashimage_value = getenv("splashimage");
-	if (env_splashimage_value == NULL)
-		return -1;
-
-	bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
-	if (bmp_load_addr == 0) {
-		printf("Error: bad splashimage address specified\n");
-		return -1;
-	}
-
-	return splash_load_from_nand(bmp_load_addr, nand_offset);
-}
diff --git a/board/earthlcd/favr-32-ezkit/favr-32-ezkit.c b/board/earthlcd/favr-32-ezkit/favr-32-ezkit.c
index a74547b..f9ac330 100644
--- a/board/earthlcd/favr-32-ezkit/favr-32-ezkit.c
+++ b/board/earthlcd/favr-32-ezkit/favr-32-ezkit.c
@@ -17,14 +17,14 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -52,6 +52,9 @@
 	hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
 
 	portmux_enable_ebi(32, 23, 0, PORTMUX_DRIVE_HIGH);
+
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart3(PORTMUX_DRIVE_MIN);
 #if defined(CONFIG_MACB)
 	portmux_enable_macb0(PORTMUX_MACB_MII, PORTMUX_DRIVE_HIGH);
@@ -63,24 +66,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x01;
diff --git a/board/egnite/ethernut5/Kconfig b/board/egnite/ethernut5/Kconfig
index c42c734..5a6c1c5 100644
--- a/board/egnite/ethernut5/Kconfig
+++ b/board/egnite/ethernut5/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "egnite"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "ethernut5"
 
diff --git a/board/esd/meesc/Kconfig b/board/esd/meesc/Kconfig
index 5041041..150348a 100644
--- a/board/esd/meesc/Kconfig
+++ b/board/esd/meesc/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "esd"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "meesc"
 
diff --git a/board/esd/otc570/Kconfig b/board/esd/otc570/Kconfig
index 55a2f70..4966f5f 100644
--- a/board/esd/otc570/Kconfig
+++ b/board/esd/otc570/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "esd"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "otc570"
 
diff --git a/board/eukrea/cpu9260/Kconfig b/board/eukrea/cpu9260/Kconfig
index 9bd077b..90d2124 100644
--- a/board/eukrea/cpu9260/Kconfig
+++ b/board/eukrea/cpu9260/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "eukrea"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "cpu9260"
 
diff --git a/board/eukrea/cpuat91/Kconfig b/board/eukrea/cpuat91/Kconfig
index b69e4c3..27b005c 100644
--- a/board/eukrea/cpuat91/Kconfig
+++ b/board/eukrea/cpuat91/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "eukrea"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "cpuat91"
 
diff --git a/board/freescale/mx53loco/imximage.cfg b/board/freescale/mx53loco/imximage.cfg
index d1c1931..a5f1d98 100644
--- a/board/freescale/mx53loco/imximage.cfg
+++ b/board/freescale/mx53loco/imximage.cfg
@@ -59,7 +59,7 @@
 DATA 4 0x63fd907c 0x01370138
 DATA 4 0x63fd9080 0x013b013c
 DATA 4 0x63fd9018 0x00011740
-DATA 4 0x63fd9000 0xc3190000
+DATA 4 0x63fd9000 0x83190000
 DATA 4 0x63fd900c 0x9f5152e3
 DATA 4 0x63fd9010 0xb68e8a63
 DATA 4 0x63fd9014 0x01ff00db
@@ -72,6 +72,7 @@
 DATA 4 0x63fd901c 0x00028031
 DATA 4 0x63fd901c 0x052080b0
 DATA 4 0x63fd901c 0x04008040
+DATA 4 0x63fd9000 0xc3190000
 DATA 4 0x63fd901c 0x0000803a
 DATA 4 0x63fd901c 0x0000803b
 DATA 4 0x63fd901c 0x00028039
diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c
index 59387ff..a90360f 100644
--- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c
+++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c
@@ -311,30 +311,9 @@
 	/* config gpmi nand iomux */
 	imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
 
-	/* gate ENFC_CLK_ROOT clock first,before clk source switch */
-	clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
-	clrbits_le32(&mxc_ccm->CCGR4,
-		MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
-
-	/* config gpmi and bch clock to 100 MHz */
-	clrsetbits_le32(&mxc_ccm->cs2cdr,
-			MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
-			MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
-			MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
-			MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+	setup_gpmi_io_clk((MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
 			MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
-			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
-
-	/* enable ENFC_CLK_ROOT clock */
-	setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
-
-	/* enable gpmi and bch clock gating */
-	setbits_le32(&mxc_ccm->CCGR4,
-		     MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
-		     MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
-		     MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)));
 
 	/* enable apbh clock gating */
 	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
diff --git a/board/freescale/mx6sxsabresd/MAINTAINERS b/board/freescale/mx6sxsabresd/MAINTAINERS
index f52f300..c0f5d9c 100644
--- a/board/freescale/mx6sxsabresd/MAINTAINERS
+++ b/board/freescale/mx6sxsabresd/MAINTAINERS
@@ -4,3 +4,4 @@
 F:	board/freescale/mx6sxsabresd/
 F:	include/configs/mx6sxsabresd.h
 F:	configs/mx6sxsabresd_defconfig
+F:	configs/mx6sxsabresd_spl_defconfig
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c
index 5cc58ac..a2c9aae 100644
--- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c
+++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c
@@ -326,6 +326,7 @@
 
 int board_mmc_init(bd_t *bis)
 {
+#ifndef CONFIG_SPL_BUILD
 	int i, ret;
 
 	/*
@@ -369,6 +370,47 @@
 	}
 
 	return 0;
+#else
+	struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+	u32 val;
+	u32 port;
+
+	val = readl(&src_regs->sbmr1);
+
+	if ((val & 0xc0) != 0x40) {
+		printf("Not boot from USDHC!\n");
+		return -EINVAL;
+	}
+
+	port = (val >> 11) & 0x3;
+	printf("port %d\n", port);
+	switch (port) {
+	case 1:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+		usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
+		break;
+	case 2:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+		gpio_direction_input(USDHC3_CD_GPIO);
+		gpio_direction_output(USDHC3_PWR_GPIO, 1);
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+		usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
+		break;
+	case 3:
+		imx_iomux_v3_setup_multiple_pads(
+			usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+		gpio_direction_input(USDHC4_CD_GPIO);
+		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+		usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
+		break;
+	}
+
+	gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+#endif
 }
 
 #ifdef CONFIG_FSL_QSPI
@@ -423,14 +465,135 @@
 	return 0;
 }
 
-int board_late_init(void)
-{
-	return 0;
-}
-
 int checkboard(void)
 {
 	puts("Board: MX6SX SABRE SDB\n");
 
 	return 0;
 }
+
+#ifdef CONFIG_SPL_BUILD
+#include <libfdt.h>
+#include <spl.h>
+#include <asm/arch/mx6-ddr.h>
+
+const struct mx6sx_iomux_ddr_regs mx6_ddr_ioregs = {
+	.dram_dqm0 = 0x00000028,
+	.dram_dqm1 = 0x00000028,
+	.dram_dqm2 = 0x00000028,
+	.dram_dqm3 = 0x00000028,
+	.dram_ras = 0x00000020,
+	.dram_cas = 0x00000020,
+	.dram_odt0 = 0x00000020,
+	.dram_odt1 = 0x00000020,
+	.dram_sdba2 = 0x00000000,
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	.dram_sdclk_0 = 0x00000030,
+	.dram_sdqs0 = 0x00000028,
+	.dram_sdqs1 = 0x00000028,
+	.dram_sdqs2 = 0x00000028,
+	.dram_sdqs3 = 0x00000028,
+	.dram_reset = 0x00000020,
+};
+
+const struct mx6sx_iomux_grp_regs mx6_grp_ioregs = {
+	.grp_addds = 0x00000020,
+	.grp_ddrmode_ctl = 0x00020000,
+	.grp_ddrpke = 0x00000000,
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = 0x00000028,
+	.grp_b1ds = 0x00000028,
+	.grp_ctlds = 0x00000020,
+	.grp_ddr_type = 0x000c0000,
+	.grp_b2ds = 0x00000028,
+	.grp_b3ds = 0x00000028,
+};
+
+const struct mx6_mmdc_calibration mx6_mmcd_calib = {
+	.p0_mpwldectrl0 = 0x00290025,
+	.p0_mpwldectrl1 = 0x00220022,
+	.p0_mpdgctrl0 = 0x41480144,
+	.p0_mpdgctrl1 = 0x01340130,
+	.p0_mprddlctl = 0x3C3E4244,
+	.p0_mpwrdlctl = 0x34363638,
+};
+
+static struct mx6_ddr3_cfg mem_ddr = {
+	.mem_speed = 1600,
+	.density = 4,
+	.width = 32,
+	.banks = 8,
+	.rowaddr = 15,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+static void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	writel(0xFFFFFFFF, &ccm->CCGR0);
+	writel(0xFFFFFFFF, &ccm->CCGR1);
+	writel(0xFFFFFFFF, &ccm->CCGR2);
+	writel(0xFFFFFFFF, &ccm->CCGR3);
+	writel(0xFFFFFFFF, &ccm->CCGR4);
+	writel(0xFFFFFFFF, &ccm->CCGR5);
+	writel(0xFFFFFFFF, &ccm->CCGR6);
+	writel(0xFFFFFFFF, &ccm->CCGR7);
+}
+
+static void spl_dram_init(void)
+{
+	struct mx6_ddr_sysinfo sysinfo = {
+		.dsize = mem_ddr.width/32,
+		.cs_density = 24,
+		.ncs = 1,
+		.cs1_mirror = 0,
+		.rtt_wr = 2,
+		.rtt_nom = 2,		/* RTT_Nom = RZQ/2 */
+		.walat = 1,		/* Write additional latency */
+		.ralat = 5,		/* Read additional latency */
+		.mif3_mode = 3,		/* Command prediction working mode */
+		.bi_on = 1,		/* Bank interleaving enabled */
+		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
+		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+	};
+
+	mx6sx_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+	mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
+}
+
+void board_init_f(ulong dummy)
+{
+	/* setup AIPS and disable watchdog */
+	arch_cpu_init();
+
+	ccgr_init();
+
+	/* iomux and setup of i2c */
+	board_early_init_f();
+
+	/* setup GP timer */
+	timer_init();
+
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+
+	/* DDR initialization */
+	spl_dram_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* load/boot image from boot device */
+	board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
+#endif
diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig
index 33a31f3..ea45472 100644
--- a/board/google/chromebook_link/Kconfig
+++ b/board/google/chromebook_link/Kconfig
@@ -22,8 +22,7 @@
 	select MARK_GRAPHICS_MEM_WRCOMB
 	select BOARD_ROMSIZE_KB_8192
 
-config MMCONF_BASE_ADDRESS
-	hex
+config PCIE_ECAM_BASE
 	default 0xf0000000
 
 config EARLY_POST_CROS_EC
diff --git a/board/gumstix/pepper/Kconfig b/board/gumstix/pepper/Kconfig
index 6f94612..3099a9e 100644
--- a/board/gumstix/pepper/Kconfig
+++ b/board/gumstix/pepper/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "pepper"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/imgtec/malta/malta.c b/board/imgtec/malta/malta.c
index 78c4bd4..79562f7 100644
--- a/board/imgtec/malta/malta.c
+++ b/board/imgtec/malta/malta.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <ide.h>
 #include <netdev.h>
 #include <pci.h>
 #include <pci_gt64120.h>
@@ -123,6 +124,7 @@
 
 	reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE);
 	__raw_writel(GORESET, reset_base);
+	mdelay(1000);
 }
 
 int board_early_init_f(void)
@@ -217,4 +219,22 @@
 	pci_read_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, &val8);
 	val8 |= PCI_CFG_PIIX4_SERIRQC_EN | PCI_CFG_PIIX4_SERIRQC_CONT;
 	pci_write_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, val8);
+
+	bdf = pci_find_device(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82371AB, 0);
+	if (bdf == -1)
+		panic("Failed to find PIIX4 IDE controller\n");
+
+	/* enable bus master & IO access */
+	val32 |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
+	pci_write_config_dword(bdf, PCI_COMMAND, val32);
+
+	/* set latency */
+	pci_write_config_byte(bdf, PCI_LATENCY_TIMER, 0x40);
+
+	/* enable IDE/ATA */
+	pci_write_config_dword(bdf, PCI_CFG_PIIX4_IDETIM_PRI,
+			       PCI_CFG_PIIX4_IDETIM_IDE);
+	pci_write_config_dword(bdf, PCI_CFG_PIIX4_IDETIM_SEC,
+			       PCI_CFG_PIIX4_IDETIM_IDE);
 }
diff --git a/board/in-circuit/grasshopper/grasshopper.c b/board/in-circuit/grasshopper/grasshopper.c
index 340b713..91b4116 100644
--- a/board/in-circuit/grasshopper/grasshopper.c
+++ b/board/in-circuit/grasshopper/grasshopper.c
@@ -18,14 +18,14 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 				| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 				| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -53,6 +53,8 @@
 	hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
 
 	portmux_enable_ebi(SDRAM_DATA_32BIT, 23, 0, PORTMUX_DRIVE_HIGH);
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart0(PORTMUX_DRIVE_MIN);
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
 #if defined(CONFIG_MACB)
@@ -69,24 +71,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x00;
diff --git a/board/intel/galileo/Kconfig b/board/intel/galileo/Kconfig
new file mode 100644
index 0000000..85afbbc
--- /dev/null
+++ b/board/intel/galileo/Kconfig
@@ -0,0 +1,21 @@
+if TARGET_GALILEO
+
+config SYS_BOARD
+	default "galileo"
+
+config SYS_VENDOR
+	default "intel"
+
+config SYS_SOC
+	default "quark"
+
+config SYS_CONFIG_NAME
+	default "galileo"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select X86_RESET_VECTOR
+	select INTEL_QUARK
+	select BOARD_ROMSIZE_KB_1024
+
+endif
diff --git a/board/intel/galileo/MAINTAINERS b/board/intel/galileo/MAINTAINERS
new file mode 100644
index 0000000..dbbc82e
--- /dev/null
+++ b/board/intel/galileo/MAINTAINERS
@@ -0,0 +1,6 @@
+INTEL GALILEO BOARD
+M:	Bin Meng <bmeng.cn@gmail.com>
+S:	Maintained
+F:	board/intel/galileo/
+F:	include/configs/galileo.h
+F:	configs/galileo_defconfig
diff --git a/board/intel/galileo/Makefile b/board/intel/galileo/Makefile
new file mode 100644
index 0000000..8356df1
--- /dev/null
+++ b/board/intel/galileo/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= galileo.o start.o
diff --git a/board/intel/galileo/galileo.c b/board/intel/galileo/galileo.c
new file mode 100644
index 0000000..f2e7468
--- /dev/null
+++ b/board/intel/galileo/galileo.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
+{
+	return;
+}
diff --git a/board/intel/galileo/start.S b/board/intel/galileo/start.S
new file mode 100644
index 0000000..a71db69
--- /dev/null
+++ b/board/intel/galileo/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/board/intel/minnowmax/Kconfig b/board/intel/minnowmax/Kconfig
new file mode 100644
index 0000000..43c50a5
--- /dev/null
+++ b/board/intel/minnowmax/Kconfig
@@ -0,0 +1,24 @@
+if TARGET_MINNOWMAX
+
+config SYS_BOARD
+	default "minnowmax"
+
+config SYS_VENDOR
+	default "intel"
+
+config SYS_SOC
+	default "baytrail"
+
+config SYS_CONFIG_NAME
+	default "minnowmax"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select X86_RESET_VECTOR
+	select INTEL_BAYTRAIL
+	select BOARD_ROMSIZE_KB_8192
+
+config PCIE_ECAM_BASE
+	default 0xe0000000
+
+endif
diff --git a/board/intel/minnowmax/MAINTAINERS b/board/intel/minnowmax/MAINTAINERS
new file mode 100644
index 0000000..d655761
--- /dev/null
+++ b/board/intel/minnowmax/MAINTAINERS
@@ -0,0 +1,6 @@
+CircuitCo Minnowboard Max
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/intel/minnowmax
+F:	include/configs/minnowmax.h
+F:	configs/minnowmax_defconfig
diff --git a/board/intel/minnowmax/Makefile b/board/intel/minnowmax/Makefile
new file mode 100644
index 0000000..1a61432
--- /dev/null
+++ b/board/intel/minnowmax/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015, Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= minnowmax.o start.o
diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
new file mode 100644
index 0000000..6e82b16
--- /dev/null
+++ b/board/intel/minnowmax/minnowmax.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/ibmpc.h>
+#include <asm/pnp_def.h>
+#include <netdev.h>
+#include <smsc_lpc47m.h>
+
+#define SERIAL_DEV PNP_DEV(0x2e, 4)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
+
+	return 0;
+}
+
+void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
+{
+	return;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
diff --git a/board/intel/minnowmax/start.S b/board/intel/minnowmax/start.S
new file mode 100644
index 0000000..2c941a4
--- /dev/null
+++ b/board/intel/minnowmax/start.S
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/board/isee/igep0033/Kconfig b/board/isee/igep0033/Kconfig
index e989e4b..2fe2ef1 100644
--- a/board/isee/igep0033/Kconfig
+++ b/board/isee/igep0033/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "am335x_igep0033"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/isee/igep00x0/igep00x0.c b/board/isee/igep00x0/igep00x0.c
index 47522f8..693fce7 100644
--- a/board/isee/igep00x0/igep00x0.c
+++ b/board/isee/igep00x0/igep00x0.c
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <status_led.h>
 #include <dm.h>
 #include <ns16550.h>
 #include <twl4030.h>
@@ -53,22 +54,13 @@
 	/* boot param addr */
 	gd->bd->bi_boot_params = (OMAP34XX_SDRC_CS0 + 0x100);
 
+#if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
+	status_led_set(STATUS_LED_BOOT, STATUS_LED_ON);
+#endif
+
 	return 0;
 }
 
-#if defined(CONFIG_SHOW_BOOT_PROGRESS) && !defined(CONFIG_SPL_BUILD)
-void show_boot_progress(int val)
-{
-	if (val < 0) {
-		/* something went wrong */
-		return;
-	}
-
-	if (!gpio_request(IGEP00X0_GPIO_LED, ""))
-		gpio_direction_output(IGEP00X0_GPIO_LED, 1);
-}
-#endif
-
 #ifdef CONFIG_SPL_BUILD
 /*
  * Routine: omap_rev_string
diff --git a/board/isee/igep00x0/igep00x0.h b/board/isee/igep00x0/igep00x0.h
index 181f81f..3c7ff9b 100644
--- a/board/isee/igep00x0/igep00x0.h
+++ b/board/isee/igep00x0/igep00x0.h
@@ -7,14 +7,6 @@
 #ifndef _IGEP00X0_H_
 #define _IGEP00X0_H_
 
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020)
-#define IGEP00X0_GPIO_LED 27
-#endif
-
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0030)
-#define IGEP00X0_GPIO_LED 16
-#endif
-
 const omap3_sysinfo sysinfo = {
 	DDR_STACKED,
 #if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020)
diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index e075f46..dcfefc4 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -126,7 +126,8 @@
 #endif
 
 int ethernet_present(void);
-int ivm_read_eeprom(void);
+int ivm_read_eeprom(unsigned char *buf, int len);
+int ivm_analyze_eeprom(unsigned char *buf, int len);
 
 int trigger_fpga_config(void);
 int wait_for_fpga_config(void);
diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c
index b6b19cc..42db542 100644
--- a/board/keymile/common/ivm.c
+++ b/board/keymile/common/ivm.c
@@ -10,6 +10,8 @@
 #include <i2c.h>
 #include "common.h"
 
+#define MAC_STR_SZ	20
+
 static int ivm_calc_crc(unsigned char *buf, int len)
 {
 	const unsigned short crc_tab[16] = {
@@ -185,45 +187,37 @@
 	return 0;
 }
 
-static int calculate_mac_offset(unsigned char *valbuf, unsigned char *buf,
+/* take care of the possible MAC address offset and the IVM content offset */
+static int process_mac(unsigned char *valbuf, unsigned char *buf,
 				int offset)
 {
+	unsigned char mac[6];
 	unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6];
 
-	if (offset == 0)
-		return 0;
+	/* use an intermediate buffer, to not change IVM content
+	 * MAC address is at offset 1
+	 */
+	memcpy(mac, buf+1, 6);
 
-	val += offset;
-	buf[4] = (val >> 16) & 0xff;
-	buf[5] = (val >> 8) & 0xff;
-	buf[6] = val & 0xff;
-	sprintf((char *)valbuf, "%pM", buf + 1);
+	if (offset) {
+		val += offset;
+		mac[3] = (val >> 16) & 0xff;
+		mac[4] = (val >> 8) & 0xff;
+		mac[5] = val & 0xff;
+	}
+
+	sprintf((char *)valbuf, "%pM", mac);
 	return 0;
 }
 
 static int ivm_analyze_block2(unsigned char *buf, int len)
 {
-	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
+	unsigned char	valbuf[MAC_STR_SZ];
 	unsigned long	count;
 
 	/* IVM_MAC Adress begins at offset 1 */
 	sprintf((char *)valbuf, "%pM", buf + 1);
 	ivm_set_value("IVM_MacAddress", (char *)valbuf);
-	/* if an offset is defined, add it */
-	calculate_mac_offset(buf, valbuf, CONFIG_PIGGY_MAC_ADRESS_OFFSET);
-#ifdef MACH_TYPE_KM_KIRKWOOD
-	setenv((char *)"ethaddr", (char *)valbuf);
-#else
-	if (getenv("ethaddr") == NULL)
-		setenv((char *)"ethaddr", (char *)valbuf);
-#endif
-#ifdef CONFIG_KMVECT1
-/* KMVECT1 has two ethernet interfaces */
-	if (getenv("eth1addr") == NULL) {
-		calculate_mac_offset(buf, valbuf, 1);
-		setenv((char *)"eth1addr", (char *)valbuf);
-	}
-#endif
 	/* IVM_MacCount */
 	count = (buf[10] << 24) +
 		   (buf[11] << 16) +
@@ -236,7 +230,7 @@
 	return 0;
 }
 
-static int ivm_analyze_eeprom(unsigned char *buf, int len)
+int ivm_analyze_eeprom(unsigned char *buf, int len)
 {
 	unsigned short	val;
 	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
@@ -296,21 +290,44 @@
 	return 0;
 }
 
-int ivm_read_eeprom(void)
+static int ivm_populate_env(unsigned char *buf, int len)
 {
-	uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+	unsigned char	*page2;
+	unsigned char	valbuf[MAC_STR_SZ];
+
+	/* do we have the page 2 filled ? if not return */
+	if (ivm_check_crc(buf, 2))
+		return 0;
+	page2 = &buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN*2];
+
+	/* if an offset is defined, add it */
+	process_mac(valbuf, page2, CONFIG_PIGGY_MAC_ADRESS_OFFSET);
+	if (getenv("ethaddr") == NULL)
+		setenv((char *)"ethaddr", (char *)valbuf);
+#ifdef CONFIG_KMVECT1
+/* KMVECT1 has two ethernet interfaces */
+	if (getenv("eth1addr") == NULL) {
+		process_mac(valbuf, page2, 1);
+		setenv((char *)"eth1addr", (char *)valbuf);
+	}
+#endif
+
+	return 0;
+}
+
+int ivm_read_eeprom(unsigned char *buf, int len)
+{
 	int ret;
 
 	i2c_set_bus_num(CONFIG_KM_IVM_BUS);
 	/* add deblocking here */
 	i2c_make_abort();
 
-	ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, i2c_buffer,
-		CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, buf, len);
 	if (ret != 0) {
 		printf("Error reading EEprom\n");
 		return -2;
 	}
 
-	return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	return ivm_populate_env(buf, len);
 }
diff --git a/board/keymile/km82xx/km82xx.c b/board/keymile/km82xx/km82xx.c
index bf84676..c599b40 100644
--- a/board/keymile/km82xx/km82xx.c
+++ b/board/keymile/km82xx/km82xx.c
@@ -18,6 +18,8 @@
 #include <i2c.h>
 #include "../common/common.h"
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 /*
  * I/O Port configuration table
  *
@@ -393,9 +395,15 @@
 	return 0;
 }
 
+int misc_init_r(void)
+{
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	return 0;
+}
+
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
diff --git a/board/keymile/km83xx/km83xx.c b/board/keymile/km83xx/km83xx.c
index 1da0dcb..89e9e1e 100644
--- a/board/keymile/km83xx/km83xx.c
+++ b/board/keymile/km83xx/km83xx.c
@@ -28,6 +28,8 @@
 
 #include "../common/common.h"
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 const qe_iop_conf_t qe_iop_conf_tab[] = {
 	/* port pin dir open_drain assign */
 #if defined(CONFIG_MPC8360)
@@ -190,6 +192,7 @@
 
 int misc_init_r(void)
 {
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
@@ -370,7 +373,7 @@
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index 1c7c108..2938861 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -102,6 +102,8 @@
 	0
 };
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 #if defined(CONFIG_KM_MGCOGE3UN)
 /*
  * Wait for startup OK from mgcoge3ne
@@ -210,6 +212,8 @@
 	}
 #endif
 
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+
 	initialize_unit_leds();
 	set_km_env();
 	set_bootcount_addr();
@@ -419,7 +423,7 @@
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c
index a74f75b..eebb47f 100644
--- a/board/keymile/kmp204x/kmp204x.c
+++ b/board/keymile/kmp204x/kmp204x.c
@@ -26,6 +26,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 int checkboard(void)
 {
 	printf("Board: Keymile %s\n", CONFIG_KM_BOARD_NAME);
@@ -195,13 +197,14 @@
 		}
 	}
 
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/maxbcm/binary.0 b/board/maxbcm/binary.0
deleted file mode 100644
index 17bfad9..0000000
--- a/board/maxbcm/binary.0
+++ /dev/null
@@ -1,17 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
-
diff --git a/board/maxbcm/kwbimage.cfg b/board/maxbcm/kwbimage.cfg
index 5a3bc67..cc05792 100644
--- a/board/maxbcm/kwbimage.cfg
+++ b/board/maxbcm/kwbimage.cfg
@@ -9,4 +9,4 @@
 BOOT_FROM	spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY board/maxbcm/binary.0 0000005b 00000068
+BINARY spl/u-boot-spl.bin 0000005b 00000068
diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c
index 7fc83ee..46b16ac 100644
--- a/board/maxbcm/maxbcm.c
+++ b/board/maxbcm/maxbcm.c
@@ -11,6 +11,9 @@
 #include <asm/arch/soc.h>
 #include <linux/mbus.h>
 
+#include "../drivers/ddr/mvebu/ddr3_hw_training.h"
+#include "../arch/arm/mvebu-common/serdes/high_speed_env_spec.h"
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Base addresses for the external device chip selects */
@@ -19,8 +22,84 @@
 #define DEV_CS2_BASE		0xe2000000
 #define DEV_CS3_BASE		0xe3000000
 
-/* Needed for dynamic (board-specific) mbus configuration */
-extern struct mvebu_mbus_state mbus_state;
+/* DDR3 static configuration */
+MV_DRAM_MC_INIT ddr3_b0_maxbcm[MV_MAX_DDR3_STATIC_SIZE] = {
+	{0x00001400, 0x7301CC30},	/* DDR SDRAM Configuration Register */
+	{0x00001404, 0x30000820},	/* Dunit Control Low Register */
+	{0x00001408, 0x5515BAAB},	/* DDR SDRAM Timing (Low) Register */
+	{0x0000140C, 0x38DA3F97},	/* DDR SDRAM Timing (High) Register */
+	{0x00001410, 0x20100005},	/* DDR SDRAM Address Control Register */
+	{0x00001414, 0x0000F3FF},	/* DDR SDRAM Open Pages Control Reg */
+	{0x00001418, 0x00000e00},	/* DDR SDRAM Operation Register */
+	{0x0000141C, 0x00000672},	/* DDR SDRAM Mode Register */
+	{0x00001420, 0x00000004},	/* DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0000F3FF},	/* Dunit Control High Register */
+	{0x00001428, 0x0011A940},	/* Dunit Control High Register */
+	{0x0000142C, 0x014C5134},	/* Dunit Control High Register */
+	{0x0000147C, 0x0000D771},
+
+	{0x00001494, 0x00010000},	/* DDR SDRAM ODT Control (Low) Reg */
+	{0x0000149C, 0x00000001},	/* DDR Dunit ODT Control Register */
+	{0x000014A0, 0x00000001},
+	{0x000014A8, 0x00000101},
+
+	/* Recommended Settings from Marvell for 4 x 16 bit devices: */
+	{0x000014C0, 0x192424C9},	/* DRAM addr and Ctrl Driving Strenght*/
+	{0x000014C4, 0xAAA24C9},	/* DRAM Data and DQS Driving Strenght */
+
+	/*
+	 * DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the
+	 * training sequence
+	 */
+	{0x000200e8, 0x3FFF0E01},
+	{0x00020184, 0x3FFFFFE0},	/* Close fast path Window to - 2G */
+
+	{0x0001504, 0x3FFFFFE1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	{0x0020220, 0x00000007},	/* Reserved */
+
+	{0x00001538, 0x0000000B},	/* Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000B},	/* Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000670},	/* MR0 */
+	{0x000015D4, 0x00000044},	/* MR1 */
+	{0x000015D8, 0x00000018},	/* MR2 */
+	{0x000015DC, 0x00000000},	/* MR3 */
+	{0x000015E0, 0x00000001},
+	{0x000015E4, 0x00203c18},	/* ZQDS Configuration Register */
+	{0x000015EC, 0xF800A225},	/* DDR PHY */
+
+	{0x0, 0x0}
+};
+
+MV_DRAM_MODES maxbcm_ddr_modes[MV_DDR3_MODES_NUMBER] = {
+	{"maxbcm_1600-800", 0xB, 0x5, 0x0, A0, ddr3_b0_maxbcm,  NULL},
+};
+
+extern MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[];
+
+/* MAXBCM: SERDES 0-4 PCIE, Serdes 7 = SGMII 0, all others =  unconnected */
+MV_BIN_SERDES_CFG maxbcm_serdes_cfg[] = {
+	{ MV_PEX_ROOT_COMPLEX, 0x20011111, 0x00000000,
+	  { PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_DISABLED,
+	    PEX_BUS_DISABLED },
+	  0x1f, serdes_change_m_phy
+	}
+};
+
+MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
+{
+	/* Only one mode supported for this board */
+	return &maxbcm_ddr_modes[0];
+}
+
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+{
+	return &maxbcm_serdes_cfg[0];
+}
 
 int board_early_init_f(void)
 {
@@ -63,9 +142,7 @@
 /* Configure and enable MV88E6185 switch */
 void reset_phy(void)
 {
-	u16 devadr = CONFIG_PHY_BASE_ADDR;
 	char *name = "neta0";
-	u16 reg;
 
 	if (miiphy_set_current_dev(name))
 		return;
diff --git a/board/mimc/mimc200/mimc200.c b/board/mimc/mimc200/mimc200.c
index 2ad53ec..f078295 100644
--- a/board/mimc/mimc200/mimc200.c
+++ b/board/mimc/mimc200/mimc200.c
@@ -20,19 +20,19 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= EBI_SRAM_CS2_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SRAM_CS2_SIZE >> PAGE_SHIFT,
-		.phys		= (EBI_SRAM_CS2_BASE >> PAGE_SHIFT)
+		.virt_pgno	= EBI_SRAM_CS2_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SRAM_CS2_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (EBI_SRAM_CS2_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -91,6 +91,8 @@
 
 	/* Enable 26 address bits and NCS2 */
 	portmux_enable_ebi(16, 26, PORTMUX_EBI_CS(2), PORTMUX_DRIVE_HIGH);
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
 
 	/* de-assert "force sys reset" pin */
@@ -151,24 +153,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-				actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x01;
diff --git a/board/miromico/hammerhead/hammerhead.c b/board/miromico/hammerhead/hammerhead.c
index d82fee7..a0c7d3b 100644
--- a/board/miromico/hammerhead/hammerhead.c
+++ b/board/miromico/hammerhead/hammerhead.c
@@ -21,14 +21,14 @@
 
 struct mmu_vm_range mmu_vmr_table[CONFIG_SYS_NR_VM_REGIONS] = {
 	{
-		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT,
-		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_FLASH_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= CONFIG_SYS_FLASH_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_FLASH_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_NONE,
 	}, {
-		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT,
-		.nr_pages	= EBI_SDRAM_SIZE >> PAGE_SHIFT,
-		.phys		= (CONFIG_SYS_SDRAM_BASE >> PAGE_SHIFT)
+		.virt_pgno	= CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT,
+		.nr_pages	= EBI_SDRAM_SIZE >> MMU_PAGE_SHIFT,
+		.phys		= (CONFIG_SYS_SDRAM_BASE >> MMU_PAGE_SHIFT)
 					| MMU_VMR_CACHE_WRBACK,
 	},
 };
@@ -63,6 +63,8 @@
 	hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
 
 	portmux_enable_ebi(32, 23, 0, PORTMUX_DRIVE_HIGH);
+	sdram_init(uncached(EBI_SDRAM_BASE), &sdram_config);
+
 	portmux_enable_usart1(PORTMUX_DRIVE_MIN);
 
 #if defined(CONFIG_MACB)
@@ -74,24 +76,6 @@
 	return 0;
 }
 
-phys_size_t initdram(int board_type)
-{
-	unsigned long expected_size;
-	unsigned long actual_size;
-	void *sdram_base;
-
-	sdram_base = uncached(EBI_SDRAM_BASE);
-
-	expected_size = sdram_init(sdram_base, &sdram_config);
-	actual_size = get_ram_size(sdram_base, expected_size);
-
-	if (expected_size != actual_size)
-		printf("Warning: Only %lu of %lu MiB SDRAM is working\n",
-		       actual_size >> 20, expected_size >> 20);
-
-	return actual_size;
-}
-
 int board_early_init_r(void)
 {
 	gd->bd->bi_phy_id[0] = 0x01;
diff --git a/board/nokia/rx51/lowlevel_init.S b/board/nokia/rx51/lowlevel_init.S
index e252909..9d4ea1b 100644
--- a/board/nokia/rx51/lowlevel_init.S
+++ b/board/nokia/rx51/lowlevel_init.S
@@ -37,7 +37,8 @@
 
 .global save_boot_params
 save_boot_params:
-
+	/* Get return address */
+	ldr	lr, =save_boot_params_ret
 
 /* Copy valid attached kernel to address KERNEL_ADDRESS */
 
diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index 95c4ff2..1540526 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -46,7 +46,7 @@
 	int ret;
 	int i;
 
-	ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+	ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev);
 	if (ret) {
 		debug("%s: Cannot find PMIC I2C chip\n", __func__);
 		return;
@@ -57,7 +57,7 @@
 	reg = 0x32;
 
 	for (i = 0; i < MAX_I2C_RETRY; ++i) {
-		if (i2c_write(dev, reg, data_buffer, 1))
+		if (dm_i2c_write(dev, reg, data_buffer, 1))
 			udelay(100);
 	}
 
@@ -66,7 +66,7 @@
 	reg = 0x67;
 
 	for (i = 0; i < MAX_I2C_RETRY; ++i) {
-		if (i2c_write(dev, reg, data_buffer, 1))
+		if (dm_i2c_write(dev, reg, data_buffer, 1))
 			udelay(100);
 	}
 }
@@ -94,7 +94,7 @@
 	u8 addr, data[1];
 	int err;
 
-	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev);
 	if (err) {
 		debug("failed to find PMU bus\n");
 		return err;
@@ -104,7 +104,7 @@
 	data[0] = 0x15;
 	addr = 0x30;
 
-	err = i2c_write(dev, addr, data, 1);
+	err = dm_i2c_write(dev, addr, data, 1);
 	if (err) {
 		debug("failed to set VDD supply\n");
 		return err;
@@ -121,7 +121,7 @@
 	data[0] = 0x15;
 	addr = 0x31;
 
-	err = i2c_write(dev, addr, data, 1);
+	err = dm_i2c_write(dev, addr, data, 1);
 	if (err) {
 		debug("failed to set AVDD supply\n");
 		return err;
diff --git a/board/nvidia/dalmore/dalmore.c b/board/nvidia/dalmore/dalmore.c
index 2a73746..d7c1a69 100644
--- a/board/nvidia/dalmore/dalmore.c
+++ b/board/nvidia/dalmore/dalmore.c
@@ -55,7 +55,7 @@
 	uchar reg, data_buffer[1];
 	int ret;
 
-	ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+	ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev);
 	if (ret) {
 		debug("%s: Cannot find PMIC I2C chip\n", __func__);
 		return;
@@ -65,7 +65,7 @@
 	data_buffer[0] = 0x31;
 	reg = 0x61;
 
-	ret = i2c_write(dev, reg, data_buffer, 1);
+	ret = dm_i2c_write(dev, reg, data_buffer, 1);
 	if (ret)
 		printf("%s: PMU i2c_write %02X<-%02X returned %d\n",
 			__func__, reg, data_buffer[0], ret);
@@ -74,7 +74,7 @@
 	data_buffer[0] = 0x01;
 	reg = 0x60;
 
-	ret = i2c_write(dev, reg, data_buffer, 1);
+	ret = dm_i2c_write(dev, reg, data_buffer, 1);
 	if (ret)
 		printf("%s: PMU i2c_write %02X<-%02X returned %d\n",
 			__func__, reg, data_buffer[0], ret);
@@ -83,12 +83,12 @@
 	data_buffer[0] = 0x03;
 	reg = 0x14;
 
-	ret = i2c_get_chip_for_busnum(0, BAT_I2C_ADDRESS, &dev);
+	ret = i2c_get_chip_for_busnum(0, BAT_I2C_ADDRESS, 1, &dev);
 	if (ret) {
 		debug("%s: Cannot find charger I2C chip\n", __func__);
 		return;
 	}
-	ret = i2c_write(dev, reg, data_buffer, 1);
+	ret = dm_i2c_write(dev, reg, data_buffer, 1);
 	if (ret)
 		printf("%s: BAT i2c_write %02X<-%02X returned %d\n",
 			__func__, reg, data_buffer[0], ret);
diff --git a/board/nvidia/whistler/whistler.c b/board/nvidia/whistler/whistler.c
index 3114b20..3476f11 100644
--- a/board/nvidia/whistler/whistler.c
+++ b/board/nvidia/whistler/whistler.c
@@ -27,21 +27,21 @@
 	int ret;
 
 	/* Turn on MAX8907B LDO12 to 2.8V for J40 power */
-	ret = i2c_get_chip_for_busnum(0, 0x3c, &dev);
+	ret = i2c_get_chip_for_busnum(0, 0x3c, 1, &dev);
 	if (ret) {
 		printf("%s: Cannot find MAX8907B I2C chip\n", __func__);
 		return;
 	}
 	val = 0x29;
-	ret = i2c_write(dev, 0x46, &val, 1);
+	ret = dm_i2c_write(dev, 0x46, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x3c 0x46 failed: %d\n", ret);
 	val = 0x00;
-	ret = i2c_write(dev, 0x45, &val, 1);
+	ret = dm_i2c_write(dev, 0x45, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x3c 0x45 failed: %d\n", ret);
 	val = 0x1f;
-	ret = i2c_write(dev, 0x44, &val, 1);
+	ret = dm_i2c_write(dev, 0x44, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x3c 0x44 failed: %d\n", ret);
 
@@ -64,17 +64,17 @@
 	 */
 
 	/* Turn on TAC6416's GPIO 0+1 for USB1/3's VBUS */
-	ret = i2c_get_chip_for_busnum(0, 0x20, &dev);
+	ret = i2c_get_chip_for_busnum(0, 0x20, 1, &dev);
 	if (ret) {
 		printf("%s: Cannot find TAC6416 I2C chip\n", __func__);
 		return;
 	}
 	val = 0x03;
-	ret = i2c_write(dev, 2, &val, 1);
+	ret = dm_i2c_write(dev, 2, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x20 2 failed: %d\n", ret);
 	val = 0xfc;
-	ret = i2c_write(dev, 6, &val, 1);
+	ret = dm_i2c_write(dev, 6, &val, 1);
 	if (ret)
 		printf("i2c_write 0 0x20 6 failed: %d\n", ret);
 }
diff --git a/board/phytec/pcm051/Kconfig b/board/phytec/pcm051/Kconfig
index 2cc0d88..65094cf 100644
--- a/board/phytec/pcm051/Kconfig
+++ b/board/phytec/pcm051/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "pcm051"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile
index c53c92b..4ce2c98 100644
--- a/board/raspberrypi/rpi/Makefile
+++ b/board/raspberrypi/rpi/Makefile
@@ -1,15 +1,7 @@
 #
-# See file CREDITS for list of people who contributed to this
-# project.
+# (C) Copyright 2012 Stephen Warren
 #
-# 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.
+# SPDX-License-Identifier:	GPL-2.0
 #
 
 obj-y	:= rpi.o
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index c18271f..50a699b 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -1,23 +1,14 @@
 /*
- * (C) Copyright 2012-2013 Stephen Warren
+ * (C) Copyright 2012-2013,2015 Stephen Warren
  *
- * 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
- * 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.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #include <common.h>
 #include <config.h>
 #include <dm.h>
 #include <fdt_support.h>
+#include <fdt_simplefb.h>
 #include <lcd.h>
 #include <mmc.h>
 #include <asm/gpio.h>
@@ -38,7 +29,11 @@
 };
 
 static const struct pl01x_serial_platdata serial_platdata = {
+#ifdef CONFIG_BCM2836
+	.base = 0x3f201000,
+#else
 	.base = 0x20201000,
+#endif
 	.type = TYPE_PL011,
 	.clock = 3000000,
 };
@@ -86,9 +81,20 @@
 } models[] = {
 	[0] = {
 		"Unknown model",
+#ifdef CONFIG_BCM2836
+		"bcm2836-rpi-other.dtb",
+#else
 		"bcm2835-rpi-other.dtb",
+#endif
 		false,
 	},
+#ifdef CONFIG_BCM2836
+	[BCM2836_BOARD_REV_2_B] = {
+		"2 Model B",
+		"bcm2836-rpi-2-b.dtb",
+		true,
+	},
+#else
 	[BCM2835_BOARD_REV_B_I2C0_2] = {
 		"Model B (no P5)",
 		"bcm2835-rpi-b-i2c0.dtb",
@@ -159,6 +165,7 @@
 		"bcm2835-rpi-a-plus.dtb",
 		false,
 	},
+#endif
 };
 
 u32 rpi_board_rev = 0;
@@ -266,7 +273,15 @@
 		return;
 	}
 
+	/*
+	 * For details of old-vs-new scheme, see:
+	 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py
+	 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282
+	 * (a few posts down)
+	 */
 	rpi_board_rev = msg->get_board_rev.body.resp.rev;
+	if (rpi_board_rev & 0x800000)
+		rpi_board_rev = (rpi_board_rev >> 4) & 0xff;
 	if (rpi_board_rev >= ARRAY_SIZE(models)) {
 		printf("RPI: Board rev %u outside known range\n",
 		       rpi_board_rev);
@@ -278,7 +293,7 @@
 	}
 
 	name = models[rpi_board_rev].name;
-	printf("RPI model: %s\n", name);
+	printf("RPI %s\n", name);
 }
 
 int board_init(void)
diff --git a/board/raspberrypi/rpi_2/Kconfig b/board/raspberrypi/rpi_2/Kconfig
new file mode 100644
index 0000000..032184d
--- /dev/null
+++ b/board/raspberrypi/rpi_2/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_RPI_2
+
+config SYS_BOARD
+	default "rpi_2"
+
+config SYS_VENDOR
+	default "raspberrypi"
+
+config SYS_SOC
+	default "bcm2835"
+
+config SYS_CONFIG_NAME
+	default "rpi_2"
+
+endif
diff --git a/board/raspberrypi/rpi_2/MAINTAINERS b/board/raspberrypi/rpi_2/MAINTAINERS
new file mode 100644
index 0000000..85a480c
--- /dev/null
+++ b/board/raspberrypi/rpi_2/MAINTAINERS
@@ -0,0 +1,6 @@
+RPI_2 BOARD
+M:	Stephen Warren <swarren@wwwdotorg.org>
+S:	Maintained
+F:	board/raspberrypi/rpi_2/
+F:	include/configs/rpi_2.h
+F:	configs/rpi_2_defconfig
diff --git a/board/raspberrypi/rpi_2/Makefile b/board/raspberrypi/rpi_2/Makefile
new file mode 100644
index 0000000..d82cd21
--- /dev/null
+++ b/board/raspberrypi/rpi_2/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2012,2015 Stephen Warren
+#
+# SPDX-License-Identifier:	GPL-2.0
+#
+
+obj-y	:= ../rpi/rpi.o
diff --git a/board/renesas/silk/Kconfig b/board/renesas/silk/Kconfig
new file mode 100644
index 0000000..07aee0e
--- /dev/null
+++ b/board/renesas/silk/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_SILK
+
+config SYS_BOARD
+	default "silk"
+
+config SYS_VENDOR
+	default "renesas"
+
+config SYS_CONFIG_NAME
+	default "silk"
+
+endif
diff --git a/board/renesas/silk/MAINTAINERS b/board/renesas/silk/MAINTAINERS
new file mode 100644
index 0000000..b566ccf
--- /dev/null
+++ b/board/renesas/silk/MAINTAINERS
@@ -0,0 +1,6 @@
+SILK BOARD
+M:	Cogent Embedded, Inc. <source@cogentembedded.com>
+S:	Maintained
+F:	board/renesas/silk/
+F:	include/configs/silk.h
+F:	configs/silk_defconfig
diff --git a/board/renesas/silk/Makefile b/board/renesas/silk/Makefile
new file mode 100644
index 0000000..e6eea61
--- /dev/null
+++ b/board/renesas/silk/Makefile
@@ -0,0 +1,10 @@
+#
+# board/renesas/silk/Makefile
+#
+# Copyright (C) 2015 Renesas Electronics Corporation
+# Copyright (C) 2015 Cogent Embedded, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0
+#
+
+obj-y	:= silk.o qos.o ../rcar-gen2-common/common.o
diff --git a/board/renesas/silk/qos.c b/board/renesas/silk/qos.c
new file mode 100644
index 0000000..4f6e46c
--- /dev/null
+++ b/board/renesas/silk/qos.c
@@ -0,0 +1,951 @@
+/*
+ * board/renesas/silk/qos.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/arch/rmobile.h>
+
+#if defined(CONFIG_RMOBILE_EXTRAM_BOOT)
+/* QoS version 0.11 */
+
+enum {
+	DBSC3_00, DBSC3_01, DBSC3_02, DBSC3_03, DBSC3_04,
+	DBSC3_05, DBSC3_06, DBSC3_07, DBSC3_08, DBSC3_09,
+	DBSC3_10, DBSC3_11, DBSC3_12, DBSC3_13, DBSC3_14,
+	DBSC3_15,
+	DBSC3_NR,
+};
+
+static u32 dbsc3_0_r_qos_addr[DBSC3_NR] = {
+	[DBSC3_00] = DBSC3_0_QOS_R0_BASE,
+	[DBSC3_01] = DBSC3_0_QOS_R1_BASE,
+	[DBSC3_02] = DBSC3_0_QOS_R2_BASE,
+	[DBSC3_03] = DBSC3_0_QOS_R3_BASE,
+	[DBSC3_04] = DBSC3_0_QOS_R4_BASE,
+	[DBSC3_05] = DBSC3_0_QOS_R5_BASE,
+	[DBSC3_06] = DBSC3_0_QOS_R6_BASE,
+	[DBSC3_07] = DBSC3_0_QOS_R7_BASE,
+	[DBSC3_08] = DBSC3_0_QOS_R8_BASE,
+	[DBSC3_09] = DBSC3_0_QOS_R9_BASE,
+	[DBSC3_10] = DBSC3_0_QOS_R10_BASE,
+	[DBSC3_11] = DBSC3_0_QOS_R11_BASE,
+	[DBSC3_12] = DBSC3_0_QOS_R12_BASE,
+	[DBSC3_13] = DBSC3_0_QOS_R13_BASE,
+	[DBSC3_14] = DBSC3_0_QOS_R14_BASE,
+	[DBSC3_15] = DBSC3_0_QOS_R15_BASE,
+};
+
+static u32 dbsc3_0_w_qos_addr[DBSC3_NR] = {
+	[DBSC3_00] = DBSC3_0_QOS_W0_BASE,
+	[DBSC3_01] = DBSC3_0_QOS_W1_BASE,
+	[DBSC3_02] = DBSC3_0_QOS_W2_BASE,
+	[DBSC3_03] = DBSC3_0_QOS_W3_BASE,
+	[DBSC3_04] = DBSC3_0_QOS_W4_BASE,
+	[DBSC3_05] = DBSC3_0_QOS_W5_BASE,
+	[DBSC3_06] = DBSC3_0_QOS_W6_BASE,
+	[DBSC3_07] = DBSC3_0_QOS_W7_BASE,
+	[DBSC3_08] = DBSC3_0_QOS_W8_BASE,
+	[DBSC3_09] = DBSC3_0_QOS_W9_BASE,
+	[DBSC3_10] = DBSC3_0_QOS_W10_BASE,
+	[DBSC3_11] = DBSC3_0_QOS_W11_BASE,
+	[DBSC3_12] = DBSC3_0_QOS_W12_BASE,
+	[DBSC3_13] = DBSC3_0_QOS_W13_BASE,
+	[DBSC3_14] = DBSC3_0_QOS_W14_BASE,
+	[DBSC3_15] = DBSC3_0_QOS_W15_BASE,
+};
+
+void qos_init(void)
+{
+	int i;
+	struct rcar_s3c *s3c;
+	struct rcar_s3c_qos *s3c_qos;
+	struct rcar_dbsc3_qos *qos_addr;
+	struct rcar_mxi *mxi;
+	struct rcar_mxi_qos *mxi_qos;
+	struct rcar_axi_qos *axi_qos;
+
+	/* DBSC DBADJ2 */
+	writel(0x20042004, DBSC3_0_DBADJ2);
+
+	/* S3C -QoS */
+	s3c = (struct rcar_s3c *)S3C_BASE;
+	writel(0x1F0D0B0A, &s3c->s3crorr);
+	writel(0x1F0D0B09, &s3c->s3cworr);
+
+	/* QoS Control Registers */
+	s3c_qos = (struct rcar_s3c_qos *)S3C_QOS_CCI0_BASE;
+	writel(0x00890089, &s3c_qos->s3cqos0);
+	writel(0x20960010, &s3c_qos->s3cqos1);
+	writel(0x20302030, &s3c_qos->s3cqos2);
+	writel(0x20AA2200, &s3c_qos->s3cqos3);
+	writel(0x00002032, &s3c_qos->s3cqos4);
+	writel(0x20960010, &s3c_qos->s3cqos5);
+	writel(0x20302030, &s3c_qos->s3cqos6);
+	writel(0x20AA2200, &s3c_qos->s3cqos7);
+	writel(0x00002032, &s3c_qos->s3cqos8);
+
+	s3c_qos = (struct rcar_s3c_qos *)S3C_QOS_CCI1_BASE;
+	writel(0x00890089, &s3c_qos->s3cqos0);
+	writel(0x20960010, &s3c_qos->s3cqos1);
+	writel(0x20302030, &s3c_qos->s3cqos2);
+	writel(0x20AA2200, &s3c_qos->s3cqos3);
+	writel(0x00002032, &s3c_qos->s3cqos4);
+	writel(0x20960010, &s3c_qos->s3cqos5);
+	writel(0x20302030, &s3c_qos->s3cqos6);
+	writel(0x20AA2200, &s3c_qos->s3cqos7);
+	writel(0x00002032, &s3c_qos->s3cqos8);
+
+	s3c_qos = (struct rcar_s3c_qos *)S3C_QOS_MXI_BASE;
+	writel(0x80928092, &s3c_qos->s3cqos0);
+	writel(0x20960020, &s3c_qos->s3cqos1);
+	writel(0x20302030, &s3c_qos->s3cqos2);
+	writel(0x20AA20DC, &s3c_qos->s3cqos3);
+	writel(0x00002032, &s3c_qos->s3cqos4);
+	writel(0x20960020, &s3c_qos->s3cqos5);
+	writel(0x20302030, &s3c_qos->s3cqos6);
+	writel(0x20AA20DC, &s3c_qos->s3cqos7);
+	writel(0x00002032, &s3c_qos->s3cqos8);
+
+	s3c_qos = (struct rcar_s3c_qos *)S3C_QOS_AXI_BASE;
+	writel(0x00820082, &s3c_qos->s3cqos0);
+	writel(0x20960020, &s3c_qos->s3cqos1);
+	writel(0x20302030, &s3c_qos->s3cqos2);
+	writel(0x20AA20FA, &s3c_qos->s3cqos3);
+	writel(0x00002032, &s3c_qos->s3cqos4);
+	writel(0x20960020, &s3c_qos->s3cqos5);
+	writel(0x20302030, &s3c_qos->s3cqos6);
+	writel(0x20AA20FA, &s3c_qos->s3cqos7);
+	writel(0x00002032, &s3c_qos->s3cqos8);
+
+	/* DBSC -QoS */
+	/* DBSC0 - Read */
+	for (i = DBSC3_00; i < DBSC3_NR; i++) {
+		qos_addr = (struct rcar_dbsc3_qos *)dbsc3_0_r_qos_addr[i];
+		writel(0x00000002, &qos_addr->dblgcnt);
+		writel(0x0000207D, &qos_addr->dbtmval0);
+		writel(0x00002053, &qos_addr->dbtmval1);
+		writel(0x0000202A, &qos_addr->dbtmval2);
+		writel(0x00001FBD, &qos_addr->dbtmval3);
+		writel(0x00000001, &qos_addr->dbrqctr);
+		writel(0x00002064, &qos_addr->dbthres0);
+		writel(0x0000203E, &qos_addr->dbthres1);
+		writel(0x00002019, &qos_addr->dbthres2);
+		writel(0x00000001, &qos_addr->dblgqon);
+	}
+
+	/* DBSC0 - Write */
+	for (i = DBSC3_00; i < DBSC3_NR; i++) {
+		qos_addr = (struct rcar_dbsc3_qos *)dbsc3_0_w_qos_addr[i];
+		writel(0x00000002, &qos_addr->dblgcnt);
+		writel(0x0000207D, &qos_addr->dbtmval0);
+		writel(0x00002053, &qos_addr->dbtmval1);
+		writel(0x00002043, &qos_addr->dbtmval2);
+		writel(0x00002030, &qos_addr->dbtmval3);
+		writel(0x00000001, &qos_addr->dbrqctr);
+		writel(0x00002064, &qos_addr->dbthres0);
+		writel(0x0000203E, &qos_addr->dbthres1);
+		writel(0x00002031, &qos_addr->dbthres2);
+		writel(0x00000001, &qos_addr->dblgqon);
+	}
+
+	/* CCI-400 -QoS */
+	writel(0x20000800, CCI_400_MAXOT_1);
+	writel(0x20000800, CCI_400_MAXOT_2);
+	writel(0x0000000C, CCI_400_QOSCNTL_1);
+	writel(0x0000000C, CCI_400_QOSCNTL_2);
+
+	/* MXI -QoS */
+	/* Transaction Control (MXI) */
+	mxi = (struct rcar_mxi *)MXI_BASE;
+	writel(0x00000013, &mxi->mxrtcr);
+	writel(0x00000013, &mxi->mxwtcr);
+	writel(0x00780080, &mxi->mxsaar0);
+	writel(0x02000800, &mxi->mxsaar1);
+
+	/* QoS Control (MXI) */
+	mxi_qos = (struct rcar_mxi_qos *)MXI_QOS_BASE;
+	writel(0x0000000C, &mxi_qos->vspdu0);
+	writel(0x0000000E, &mxi_qos->du0);
+
+	/* AXI -QoS */
+	/* Transaction Control (MXI) */
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_SYX64TO128_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_AVB_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x000020A6, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_IMUX0_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_IMUX1_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_IMUX2_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_LBS_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x0000214C, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_MMUDS_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_MMUM_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_MMUS0_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_MMUS1_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_RTX_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_SDS0_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x000020A6, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_SDS1_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x000020A6, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_USB20_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_USB22_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_AX2M_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_CC50_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002029, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_CCI_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_CS_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_DDM_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x000020A6, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_ETH_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_MPXM_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_SDM0_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x0000214C, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_SDM1_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x0000214C, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_TRAB_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x000020A6, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_UDM0_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI_UDM1_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	/* QoS Register (RT-AXI) */
+	axi_qos = (struct rcar_axi_qos *)RT_AXI_SHX_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)RT_AXI_DBG_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)RT_AXI_RTX64TO128_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)RT_AXI_SY2RT_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	/* QoS Register (MP-AXI) */
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_ADSP_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002037, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_ASDS0_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002014, &axi_qos->qosctset0);
+	writel(0x00000040, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_ASDS1_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002014, &axi_qos->qosctset0);
+	writel(0x00000040, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_MLP_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00001FF0, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00002001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_MMUMP_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_SPU_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x00002053, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MP_AXI_SPUC_BASE;
+	writel(0x00000000, &axi_qos->qosconf);
+	writel(0x0000206E, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	/* QoS Register (SYS-AXI256) */
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI256_AXI128TO256_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020EB, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI256_SYX_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020EB, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI256_MPX_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020EB, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)SYS_AXI256_MXI_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020EB, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	/* QoS Register (CCI-AXI) */
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUS0_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_SYX2_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUDS_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUM_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MXI_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x00002245, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUS1_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)CCI_AXI_MMUMP_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002004, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000000, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	/* QoS Register (Media-AXI) */
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_MXR_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020DC, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x000020AA, &axi_qos->qosthres0);
+	writel(0x00002032, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_MXW_BASE;
+	writel(0x00000002, &axi_qos->qosconf);
+	writel(0x000020DC, &axi_qos->qosctset0);
+	writel(0x00002096, &axi_qos->qosctset1);
+	writel(0x00002030, &axi_qos->qosctset2);
+	writel(0x00002030, &axi_qos->qosctset3);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x000020AA, &axi_qos->qosthres0);
+	writel(0x00002032, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_TDMR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_TDMW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSP1CR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSP1CW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSPDU0CR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSPDU0CW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002190, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VIN0W_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00001FF0, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00002001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_FDP0R_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_FDP0W_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_IMSR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_IMSW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSP1R_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSP1W_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_IMRR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_IMRW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSPD0R_BASE;
+	writel(0x00000003, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VSPD0W_BASE;
+	writel(0x00000003, &axi_qos->qosconf);
+	writel(0x000020C8, &axi_qos->qosctset0);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_DU0R_BASE;
+	writel(0x00000003, &axi_qos->qosconf);
+	writel(0x00002063, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_DU0W_BASE;
+	writel(0x00000003, &axi_qos->qosconf);
+	writel(0x00002063, &axi_qos->qosctset0);
+	writel(0x00000001, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VCP0CR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002073, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VCP0CW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002073, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VCP0VR_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002073, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VCP0VW_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002073, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00000001, &axi_qos->qosthres0);
+	writel(0x00000001, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+
+	axi_qos = (struct rcar_axi_qos *)MEDIA_AXI_VPC0R_BASE;
+	writel(0x00000001, &axi_qos->qosconf);
+	writel(0x00002073, &axi_qos->qosctset0);
+	writel(0x00000020, &axi_qos->qosreqctr);
+	writel(0x00002064, &axi_qos->qosthres0);
+	writel(0x00002004, &axi_qos->qosthres1);
+	writel(0x00000001, &axi_qos->qosthres2);
+	writel(0x00000001, &axi_qos->qosqon);
+}
+#else /* CONFIG_RMOBILE_EXTRAM_BOOT */
+void qos_init(void)
+{
+}
+#endif /* CONFIG_RMOBILE_EXTRAM_BOOT */
diff --git a/board/renesas/silk/qos.h b/board/renesas/silk/qos.h
new file mode 100644
index 0000000..75a20bb
--- /dev/null
+++ b/board/renesas/silk/qos.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __QOS_H__
+#define __QOS_H__
+
+void qos_init(void);
+
+#endif
diff --git a/board/renesas/silk/silk.c b/board/renesas/silk/silk.c
new file mode 100644
index 0000000..dfd9a9d
--- /dev/null
+++ b/board/renesas/silk/silk.c
@@ -0,0 +1,163 @@
+/*
+ * board/renesas/silk/silk.c
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/processor.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/arch/rmobile.h>
+#include <asm/arch/rcar-mstp.h>
+#include <asm/arch/mmc.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include <i2c.h>
+#include <div64.h>
+#include "qos.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CLK2MHZ(clk)	(clk / 1000 / 1000)
+void s_init(void)
+{
+	struct rcar_rwdt *rwdt = (struct rcar_rwdt *)RWDT_BASE;
+	struct rcar_swdt *swdt = (struct rcar_swdt *)SWDT_BASE;
+
+	/* Watchdog init */
+	writel(0xA5A5A500, &rwdt->rwtcsra);
+	writel(0xA5A5A500, &swdt->swtcsra);
+
+	/* QoS */
+	qos_init();
+}
+
+#define TMU0_MSTP125	(1 << 25)
+#define SCIF2_MSTP719	(1 << 19)
+#define ETHER_MSTP813	(1 << 13)
+#define IIC1_MSTP323	(1 << 23)
+#define MMC0_MSTP315	(1 << 15)
+
+int board_early_init_f(void)
+{
+	/* TMU */
+	mstp_clrbits_le32(MSTPSR1, SMSTPCR1, TMU0_MSTP125);
+
+	/* SCIF2 */
+	mstp_clrbits_le32(MSTPSR7, SMSTPCR7, SCIF2_MSTP719);
+
+	/* ETHER */
+	mstp_clrbits_le32(MSTPSR8, SMSTPCR8, ETHER_MSTP813);
+
+	/* IIC1 / sh-i2c ch1 */
+	mstp_clrbits_le32(MSTPSR3, SMSTPCR3, IIC1_MSTP323);
+
+#ifdef CONFIG_SH_MMCIF
+	/* MMC */
+	mstp_clrbits_le32(MSTPSR3, SMSTPCR3, MMC0_MSTP315);
+#endif
+	return 0;
+}
+
+int board_init(void)
+{
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	/* Init PFC controller */
+	r8a7794_pinmux_init();
+
+	/* Ether Enable */
+	gpio_request(GPIO_FN_ETH_CRS_DV, NULL);
+	gpio_request(GPIO_FN_ETH_RX_ER, NULL);
+	gpio_request(GPIO_FN_ETH_RXD0, NULL);
+	gpio_request(GPIO_FN_ETH_RXD1, NULL);
+	gpio_request(GPIO_FN_ETH_LINK, NULL);
+	gpio_request(GPIO_FN_ETH_REFCLK, NULL);
+	gpio_request(GPIO_FN_ETH_MDIO, NULL);
+	gpio_request(GPIO_FN_ETH_TXD1, NULL);
+	gpio_request(GPIO_FN_ETH_TX_EN, NULL);
+	gpio_request(GPIO_FN_ETH_MAGIC, NULL);
+	gpio_request(GPIO_FN_ETH_TXD0, NULL);
+	gpio_request(GPIO_FN_ETH_MDC, NULL);
+	gpio_request(GPIO_FN_IRQ8, NULL);
+
+	/* PHY reset */
+	gpio_request(GPIO_GP_1_24, NULL);
+	gpio_direction_output(GPIO_GP_1_24, 0);
+	mdelay(20);
+	gpio_set_value(GPIO_GP_1_24, 1);
+	udelay(1);
+
+	return 0;
+}
+
+#define CXR24 0xEE7003C0 /* MAC address high register */
+#define CXR25 0xEE7003C8 /* MAC address low register */
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_SH_ETHER
+	int ret = -ENODEV;
+	u32 val;
+	unsigned char enetaddr[6];
+
+	ret = sh_eth_initialize(bis);
+	if (!eth_getenv_enetaddr("ethaddr", enetaddr))
+		return ret;
+
+	/* Set Mac address */
+	val = enetaddr[0] << 24 | enetaddr[1] << 16 |
+		enetaddr[2] << 8 | enetaddr[3];
+	writel(val, CXR24);
+
+	val = enetaddr[4] << 8 | enetaddr[5];
+	writel(val, CXR25);
+
+	return ret;
+#else
+	return 0;
+#endif
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	int ret = 0;
+
+#ifdef CONFIG_SH_MMCIF
+	/* MMC0 */
+	gpio_request(GPIO_GP_4_31, NULL);
+	gpio_set_value(GPIO_GP_4_31, 1);
+
+	ret = mmcif_mmc_init();
+#endif
+	return ret;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+const struct rmobile_sysinfo sysinfo = {
+	CONFIG_RMOBILE_BOARD_STRING
+};
+
+void reset_cpu(ulong addr)
+{
+	u8 val;
+
+	i2c_set_bus_num(1); /* PowerIC connected to ch1 */
+	i2c_read(CONFIG_SYS_I2C_POWERIC_ADDR, 0x13, 1, &val, 1);
+	val |= 0x02;
+	i2c_write(CONFIG_SYS_I2C_POWERIC_ADDR, 0x13, 1, &val, 1);
+}
diff --git a/board/ronetix/pm9261/Kconfig b/board/ronetix/pm9261/Kconfig
index a4934c5..8c54198 100644
--- a/board/ronetix/pm9261/Kconfig
+++ b/board/ronetix/pm9261/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "ronetix"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "pm9261"
 
diff --git a/board/ronetix/pm9263/Kconfig b/board/ronetix/pm9263/Kconfig
index 339a6ea..5b47d34 100644
--- a/board/ronetix/pm9263/Kconfig
+++ b/board/ronetix/pm9263/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "ronetix"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "pm9263"
 
diff --git a/board/ronetix/pm9g45/Kconfig b/board/ronetix/pm9g45/Kconfig
index 65fc5c4..ad5309f 100644
--- a/board/ronetix/pm9g45/Kconfig
+++ b/board/ronetix/pm9g45/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "ronetix"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "pm9g45"
 
diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c
index 8b4c8e9..da2245f 100644
--- a/board/samsung/common/board.c
+++ b/board/samsung/common/board.c
@@ -355,3 +355,31 @@
 	return 0;
 }
 #endif
+
+void reset_misc(void)
+{
+	struct gpio_desc gpio = {};
+	int node;
+
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
+			"samsung,emmc-reset");
+	if (node < 0)
+		return;
+
+	gpio_request_by_name_nodev(gd->fdt_blob, node, "reset-gpio", 0, &gpio,
+				   GPIOD_IS_OUT);
+
+	if (dm_gpio_is_valid(&gpio)) {
+		/*
+		 * Reset eMMC
+		 *
+		 * FIXME: Need to optimize delay time. Minimum 1usec pulse is
+		 *	  required by 'JEDEC Standard No.84-A441' (eMMC)
+		 *	  document but real delay time is expected to greater
+		 *	  than 1usec.
+		 */
+		dm_gpio_set_value(&gpio, 0);
+		mdelay(10);
+		dm_gpio_set_value(&gpio, 1);
+	}
+}
diff --git a/board/samsung/goni/Kconfig b/board/samsung/goni/Kconfig
index cbbf5a9..2c5d3fc 100644
--- a/board/samsung/goni/Kconfig
+++ b/board/samsung/goni/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "s5p_goni"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
index b7d2381..bff6ac9 100644
--- a/board/samsung/odroid/odroid.c
+++ b/board/samsung/odroid/odroid.c
@@ -248,12 +248,12 @@
 	 * MOUTc2c = 800 Mhz
 	 * MOUTpwi = 108 MHz
 	 *
-	 * sclk_g2d_acp = MOUTg2d / (ratio + 1) = 400 (1)
+	 * sclk_g2d_acp = MOUTg2d / (ratio + 1) = 200 (3)
 	 * sclk_c2c = MOUTc2c / (ratio + 1) = 400 (1)
 	 * aclk_c2c = sclk_c2c / (ratio + 1) = 200 (1)
 	 * sclk_pwi = MOUTpwi / (ratio + 1) = 18 (5)
 	 */
-	set = G2D_ACP_RATIO(1) | C2C_RATIO(1) | PWI_RATIO(5) |
+	set = G2D_ACP_RATIO(3) | C2C_RATIO(1) | PWI_RATIO(5) |
 	      C2C_ACLK_RATIO(1) | DVSEM_RATIO(1) | DPM_RATIO(1);
 
 	clrsetbits_le32(&clk->div_dmc1, clr, set);
@@ -415,15 +415,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_I2C_INIT_BOARD
-static void board_init_i2c(void)
-{
-	/* I2C_0 */
-	if (exynos_pinmux_config(PERIPH_ID_I2C0, PINMUX_FLAG_NONE))
-		debug("I2C%d not configured\n", (I2C_0));
-}
-#endif
-
 int exynos_early_init_f(void)
 {
 	board_clock_init();
@@ -444,10 +435,7 @@
 
 int exynos_power_init(void)
 {
-#ifdef CONFIG_SYS_I2C_INIT_BOARD
-	board_init_i2c();
-#endif
-	pmic_init(I2C_0);
+	pmic_init(0);
 	pmic_init_max77686();
 
 	return 0;
@@ -515,11 +503,3 @@
 	return s3c_udc_probe(&s5pc210_otg_data);
 }
 #endif
-
-void reset_misc(void)
-{
-	/* Reset eMMC*/
-	gpio_set_value(EXYNOS4X12_GPIO_K12, 0);
-	mdelay(10);
-	gpio_set_value(EXYNOS4X12_GPIO_K12, 1);
-}
diff --git a/board/samsung/smdk5420/Kconfig b/board/samsung/smdk5420/Kconfig
index a9d62ff..576abae 100644
--- a/board/samsung/smdk5420/Kconfig
+++ b/board/samsung/smdk5420/Kconfig
@@ -22,6 +22,9 @@
 config SYS_CONFIG_NAME
 	default "peach-pi"
 
+config DM_CROS_EC
+	default y
+
 endif
 
 if TARGET_PEACH_PIT
@@ -35,6 +38,9 @@
 config SYS_CONFIG_NAME
 	default "peach-pit"
 
+config DM_CROS_EC
+	default y
+
 endif
 
 if TARGET_SMDK5420
diff --git a/board/samsung/smdkc100/Kconfig b/board/samsung/smdkc100/Kconfig
index d2157b4..996fe3c 100644
--- a/board/samsung/smdkc100/Kconfig
+++ b/board/samsung/smdkc100/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "smdkc100"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index 5f879f5..3c0df17 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -18,8 +18,8 @@
 
 CONFIG_SANDBOX is defined when building a native board.
 
-The chosen vendor and board names are also 'sandbox', so there is a single
-board in board/sandbox.
+The board name is 'sandbox' but the vendor name is unset, so there is a
+single board in board/sandbox.
 
 CONFIG_SANDBOX_BIG_ENDIAN should be defined when running on big-endian
 machines.
diff --git a/board/siemens/corvus/Kconfig b/board/siemens/corvus/Kconfig
index 7b505aa..69fe0f0 100644
--- a/board/siemens/corvus/Kconfig
+++ b/board/siemens/corvus/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "siemens"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "corvus"
 
diff --git a/board/siemens/taurus/Kconfig b/board/siemens/taurus/Kconfig
index c07d244..cf71e4c 100644
--- a/board/siemens/taurus/Kconfig
+++ b/board/siemens/taurus/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "siemens"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "taurus"
 
diff --git a/board/silica/pengwyn/Kconfig b/board/silica/pengwyn/Kconfig
index f2e1098..6ecda80 100644
--- a/board/silica/pengwyn/Kconfig
+++ b/board/silica/pengwyn/Kconfig
@@ -12,4 +12,13 @@
 config SYS_CONFIG_NAME
 	default "pengwyn"
 
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if !SPL_BUILD
+
+config DM_SERIAL
+	default y if !SPL_BUILD
+
 endif
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 738b55e..9cf54e5 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -39,16 +39,23 @@
 	default 360 if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 	---help---
 	Set the dram clock speed, valid range 240 - 480, must be a multiple
-	of 24. Note on sun4i / sun5i / sun7i this is only used by boards
-	which use dram autoconfig.
+	of 24.
+
+if MACH_SUN5I || MACH_SUN7I
+config DRAM_MBUS_CLK
+	int "sunxi mbus clock speed"
+	default 300
+	---help---
+	Set the mbus clock speed. The maximum on sun5i hardware is 300MHz.
+
+endif
 
 config DRAM_ZQ
 	int "sunxi dram zq value"
 	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I
 	default 127 if MACH_SUN7I
 	---help---
-	Set the dram zq value. Note on sun4i / sun5i / sun7i this is only
-	used by boards which use dram autoconfig.
+	Set the dram zq value.
 
 if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 config DRAM_EMR1
@@ -56,8 +63,73 @@
 	default 0 if MACH_SUN4I
 	default 4 if MACH_SUN5I || MACH_SUN7I
 	---help---
-	Set the dram controller emr1 value. Note this is only used by boards
-	which use dram autoconfig.
+	Set the dram controller emr1 value.
+
+config DRAM_ODT_EN
+	int "sunxi dram odt_en value"
+	default 0
+	---help---
+	Set the dram controller odt_en parameter. This can be used to
+	enable/disable the ODT feature.
+
+config DRAM_TPR3
+	hex "sunxi dram tpr3 value"
+	default 0
+	---help---
+	Set the dram controller tpr3 parameter. This parameter configures
+	the delay on the command lane and also phase shifts, which are
+	applied for sampling incoming read data. The default value 0
+	means that no phase/delay adjustments are necessary. Properly
+	configuring this parameter increases reliability at high DRAM
+	clock speeds.
+
+config DRAM_DQS_GATING_DELAY
+	hex "sunxi dram dqs_gating_delay value"
+	default 0
+	---help---
+	Set the dram controller dqs_gating_delay parmeter. Each byte
+	encodes the DQS gating delay for each byte lane. The delay
+	granularity is 1/4 cycle. For example, the value 0x05060606
+	means that the delay is 5 quarter-cycles for one lane (1.25
+	cycles) and 6 quarter-cycles (1.5 cycles) for 3 other lanes.
+	The default value 0 means autodetection. The results of hardware
+	autodetection are not very reliable and depend on the chip
+	temperature (sometimes producing different results on cold start
+	and warm reboot). But the accuracy of hardware autodetection
+	is usually good enough, unless running at really high DRAM
+	clocks speeds (up to 600MHz). If unsure, keep as 0.
+
+choice
+	prompt "sunxi dram timings"
+	default DRAM_TIMINGS_VENDOR_MAGIC
+	---help---
+	Select the timings of the DDR3 chips.
+
+config DRAM_TIMINGS_VENDOR_MAGIC
+	bool "Magic vendor timings from Android"
+	---help---
+	The same DRAM timings as in the Allwinner boot0 bootloader.
+
+config DRAM_TIMINGS_DDR3_1066F_1333H
+	bool "JEDEC DDR3-1333H with down binning to DDR3-1066F"
+	---help---
+	Use the timings of the standard JEDEC DDR3-1066F speed bin for
+	DRAM_CLK <= 533MHz and the timings of the DDR3-1333H speed bin
+	for DRAM_CLK > 533MHz. This covers the majority of DDR3 chips
+	used in Allwinner A10/A13/A20 devices. In the case of DDR3-1333
+	or DDR3-1600 chips, be sure to check the DRAM datasheet to confirm
+	that down binning to DDR3-1066F is supported (because DDR3-1066F
+	uses a bit faster timings than DDR3-1333H).
+
+config DRAM_TIMINGS_DDR3_800E_1066G_1333J
+	bool "JEDEC DDR3-800E / DDR3-1066G / DDR3-1333J"
+	---help---
+	Use the timings of the slowest possible JEDEC speed bin for the
+	selected DRAM_CLK. Depending on the DRAM_CLK value, it may be
+	DDR3-800E, DDR3-1066G or DDR3-1333J.
+
+endchoice
+
 endif
 
 config SYS_CONFIG_NAME
@@ -67,88 +139,6 @@
 	default "sun7i" if MACH_SUN7I
 	default "sun8i" if MACH_SUN8I
 
-choice
-	prompt "Board"
-
-config TARGET_A10S_OLINUXINO_M
-	bool "A10S_OLINUXINO_M"
-	depends on MACH_SUN5I
-
-config TARGET_A13_OLINUXINOM
-	bool "A13_OLINUXINOM"
-	depends on MACH_SUN5I
-
-config TARGET_A13_OLINUXINO
-	bool "A13_OLINUXINO"
-	depends on MACH_SUN5I
-
-config TARGET_A20_OLINUXINO_L2
-	bool "A20_OLINUXINO_L2"
-	depends on MACH_SUN7I
-
-config TARGET_A20_OLINUXINO_L
-	bool "A20_OLINUXINO_L"
-	depends on MACH_SUN7I
-
-config TARGET_A20_OLINUXINO_M
-	bool "A20_OLINUXINO_M"
-	depends on MACH_SUN7I
-
-config TARGET_AUXTEK_T004
-	bool "AUXTEK_T004"
-	depends on MACH_SUN5I
-
-config TARGET_BANANAPI
-	bool "BANANAPI"
-	depends on MACH_SUN7I
-
-config TARGET_BANANAPRO
-	bool "BANANAPRO"
-	depends on MACH_SUN7I
-
-config TARGET_CUBIEBOARD2
-	bool "CUBIEBOARD2"
-	depends on MACH_SUN7I
-
-config TARGET_CUBIETRUCK
-	bool "CUBIETRUCK"
-	depends on MACH_SUN7I
-
-config TARGET_PCDUINO3
-	bool "PCDUINO3"
-	depends on MACH_SUN7I
-
-config TARGET_MELE_M3
-	bool "MELE_M3"
-	depends on MACH_SUN7I
-
-config TARGET_MK802_A10S
-	bool "MK802_A10S"
-	depends on MACH_SUN5I
-
-config TARGET_MSI_PRIMO73
-	bool "MSI Primo73 (7\" tablet)"
-	depends on MACH_SUN7I
-	---help---
-	The MSI Primo73 is an A20 based tablet, with 1G RAM, 16G NAND,
-	1024x600 TN LCD display, mono speaker, 0.3 MP front camera, 2.0 MP
-	rear camera, 3000 mAh battery, gt911 touchscreen, mma8452 accelerometer
-	and rtl8188etv usb wifi. Has "power", "volume+" and "volume-" buttons
-	(both volume buttons are also connected to the UBOOT_SEL pin). The
-	external connectors are represented by MicroSD slot, MiniHDMI, MicroUSB
-	OTG and 3.5mm headphone jack. More details are available at
-	    http://linux-sunxi.org/MSI_Primo73
-
-config TARGET_I12_TVBOX
-	bool "I12_TVBOX"
-	depends on MACH_SUN7I
-
-config TARGET_R7DONGLE
-	bool "R7DONGLE"
-	depends on MACH_SUN5I
-
-endchoice
-
 config SYS_BOARD
 	default "sunxi"
 
@@ -159,6 +149,16 @@
 	bool "SPL/FEL mode support"
 	depends on SPL
 	default n
+	help
+	  This enables support for Fast Early Loader (FEL) mode. This
+	  allows U-Boot to be loaded to the board over USB by the on-chip
+	  boot rom. U-Boot should be sent in two parts: SPL first, with
+	  'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000' then U-Boot with
+	  'fel write 0x4a000000 u-boot.bin; fel exe 0x4a000000'. This option
+	  shrinks the amount of SRAM available to SPL, so only enable it if
+	  you need FEL. Note that enabling this option only allows FEL to be
+	  used; it is still possible to boot U-Boot from boot media. U-Boot
+	  SPL detects when it is being loaded using FEL.
 
 config UART0_PORT_F
 	bool "UART0 on MicroSD breakout board"
@@ -223,6 +223,14 @@
 	Set the Vbus enable pin for usb0 (otg). This takes a string in the
 	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
 
+config USB0_VBUS_DET
+	string "Vbus detect pin for usb0 (otg)"
+	depends on USB_MUSB_SUNXI
+	default ""
+	---help---
+	Set the Vbus detect pin for usb0 (otg). This takes a string in the
+	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+
 config USB1_VBUS_PIN
 	string "Vbus enable pin for usb1 (ehci0)"
 	default "PH6" if MACH_SUN4I || MACH_SUN7I
@@ -270,6 +278,16 @@
 	LCD interface driving a VGA connector, such as found on the
 	Olimex A13 boards.
 
+config VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
+	boolean "Force sync active high for VGA via LCD controller support"
+	depends on VIDEO_VGA_VIA_LCD
+	default n
+	---help---
+	Say Y here if you've a board which uses opendrain drivers for the vga
+	hsync and vsync signals. Opendrain drivers cannot generate steep enough
+	positive edges for a stable video output, so on boards with opendrain
+	drivers the sync signals must always be active high.
+
 config VIDEO_VGA_EXTERNAL_DAC_EN
 	string "LCD panel power enable pin"
 	depends on VIDEO_VGA_VIA_LCD
@@ -302,6 +320,14 @@
 	Set the power enable pin for the LCD panel. This takes a string in the
 	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
 
+config VIDEO_LCD_RESET
+	string "LCD panel reset pin"
+	depends on VIDEO
+	default ""
+	---help---
+	Set the reset pin for the LCD panel. This takes a string in the format
+	understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+
 config VIDEO_LCD_BL_EN
 	string "LCD panel backlight enable pin"
 	depends on VIDEO
@@ -326,6 +352,30 @@
 	---help---
 	Set this if the backlight pwm output is active low.
 
+config VIDEO_LCD_PANEL_I2C
+	bool "LCD panel needs to be configured via i2c"
+	depends on VIDEO
+	default m
+	---help---
+	Say y here if the LCD panel needs to be configured via i2c. This
+	will add a bitbang i2c controller using gpios to talk to the LCD.
+
+config VIDEO_LCD_PANEL_I2C_SDA
+	string "LCD panel i2c interface SDA pin"
+	depends on VIDEO_LCD_PANEL_I2C
+	default "PG12"
+	---help---
+	Set the SDA pin for the LCD i2c interface. This takes a string in the
+	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+
+config VIDEO_LCD_PANEL_I2C_SCL
+	string "LCD panel i2c interface SCL pin"
+	depends on VIDEO_LCD_PANEL_I2C
+	default "PG10"
+	---help---
+	Set the SCL pin for the LCD i2c interface. This takes a string in the
+	format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+
 
 # Note only one of these may be selected at a time! But hidden choices are
 # not supported by Kconfig
@@ -364,6 +414,14 @@
 	---help---
 	7.85" 1024x768 Hitachi tx18d42vm LCD panel support
 
+config VIDEO_LCD_TL059WV5C0
+	bool "tl059wv5c0 LCD panel"
+	select VIDEO_LCD_PANEL_I2C
+	select VIDEO_LCD_IF_PARALLEL
+	---help---
+	6" 480x800 tl059wv5c0 panel support, as used on the Utoo P66 and
+	Aigo M60/M608/M606 tablets.
+
 endchoice
 
 
@@ -383,4 +441,10 @@
 	Say Y here to add support for using a USB keyboard (typically used
 	in combination with a graphical console).
 
+config GMAC_TX_DELAY
+	int "GMAC Transmit Clock Delay Chain"
+	default 0
+	---help---
+	Set the GMAC Transmit Clock Delay Chain value.
+
 endif
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 743e7f5..9a287d3 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -34,16 +34,6 @@
 F:	include/configs/sun8i.h
 F:	configs/Ippo_q8h_v1_2_defconfig
 
-CUBIEBOARD2 BOARD
-M:	Ian Campbell <ijc@hellion.org.uk>
-M:	Hans de Goede <hdegoede@redhat.com>
-S:	Maintained
-F:	include/configs/sun7i.h
-F:	configs/Cubieboard2_defconfig
-F:	configs/Cubieboard2_FEL_defconfig
-F:	configs/Cubietruck_defconfig
-F:	configs/Cubietruck_FEL_defconfig
-
 A20-OLINUXINO-LIME BOARD
 M:	FUKAUMI Naoki <naobsd@gmail.com>
 S:	Maintained
@@ -56,26 +46,65 @@
 F:	board/sunxi/dram_a20_olinuxino_l2.c
 F:	configs/A20-OLinuXino-Lime2_defconfig
 
+AMPE A76 BOARD
+M:	Paul Kocialkowski <contact@paulk.fr>
+S:	Maintained
+F:	configs/Ampe_A76_defconfig
+
 COLOMBUS BOARD
 M:	Maxime Ripard <maxime.ripard@free-electrons.com>
 S:	Maintained
 F:	configs/Colombus_defconfig
 
-GEMEI-G9 TABLET
-M: Priit Laes <plaes@plaes.org>
-S: Maintained
-F: configs/sunxi_Gemei_G9_defconfig
+CUBIEBOARD2 BOARD
+M:	Ian Campbell <ijc@hellion.org.uk>
+M:	Hans de Goede <hdegoede@redhat.com>
+S:	Maintained
+F:	include/configs/sun7i.h
+F:	configs/Cubieboard2_defconfig
+F:	configs/Cubietruck_defconfig
 
-HUMMINIGBIRD-A31 BOARD
+GEMEI-G9 TABLET
+M:	Priit Laes <plaes@plaes.org>
+S:	Maintained
+F:	configs/sunxi_Gemei_G9_defconfig
+
+HUMMINGBIRD-A31 BOARD
 M:	Chen-Yu Tsai <wens@csie.org>
 S:	Maintained
 F:	configs/Hummingbird_A31_defconfig
 
+INET-86VS BOARD
+M:	Michal Suchanek <hramrach@gmail.com>
+S:	Maintained
+F:	board/sunxi/dram_inet_86vs.c
+F:	configs/Inet_86VS_defconfig
+
 IPPO-Q8H-V5 BOARD
 M:	Chen-Yu Tsai <wens@csie.org>
 S:	Maintained
 F:	configs/Ippo_q8h_v5_defconfig
 
+LINKSPRITE-PCDUINO BOARD
+M:	Zoltan Herpai <wigyori@uid0.hu>
+S:	Maintained
+F:	configs/Linksprite_pcDuino_defconfig
+
+LINKSPRITE-PCDUINO3-NANO BOARD
+M:	Adam Sampson <ats@offog.org>
+S:	Maintained
+F:	configs/Linksprite_pcDuino3_Nano_defconfig
+
+MARSBOARD-A10 BOARD
+M:	Aleksei Mamlin <mamlinav@gmail.com>
+S:	Maintained
+F:	configs/Marsboard_A10_defconfig
+
+MELE M5 BOARD
+M:	Ian Campbell <ijc@hellion.org.uk>
+S:	Maintained
+F:	configs/Mele_M5_defconfig
+
 MSI-PRIMO73 BOARD
 M:	Siarhei Siamashka <siarhei.siamashka@gmail.com>
 S:	Maintained
@@ -86,17 +115,7 @@
 S:	Maintained
 F:	configs/MSI_Primo81_defconfig
 
-LINKSPRITE-PCDUINO BOARD
-M:	Zoltan Herpai <wigyori@uid0.hu>
+TZX-Q8-713B7 BOARD
+M:	Paul Kocialkowski <contact@paulk.fr>
 S:	Maintained
-F:	configs/Linksprite_pcDuino_defconfig
-
-MARSBOARD-A10 BOARD
-M:	Aleksei Mamlin <mamlinav@gmail.com>
-S:	Maintained
-F:	configs/Marsboard_A10_defconfig
-
-MELE M5 BOARD
-M:	Ian Campbell <ijc@hellion.org.uk>
-S:	Maintained
-F:	configs/Mele_M5_defconfig
+F:	configs/TZX-Q8-713B7_defconfig
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
index 71edb83..43766e0 100644
--- a/board/sunxi/Makefile
+++ b/board/sunxi/Makefile
@@ -12,11 +12,5 @@
 obj-$(CONFIG_SUNXI_GMAC)	+= gmac.o
 obj-$(CONFIG_SUNXI_AHCI)	+= ahci.o
 obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i_auto.o
+obj-$(CONFIG_MACH_SUN5I)	+= dram_sun5i_auto.o
 obj-$(CONFIG_MACH_SUN7I)	+= dram_sun5i_auto.o
-obj-$(CONFIG_TARGET_A10S_OLINUXINO_M)	+= dram_a10s_olinuxino_m.o
-obj-$(CONFIG_TARGET_A13_OLINUXINO)	+= dram_a13_olinuxino.o
-obj-$(CONFIG_TARGET_A13_OLINUXINOM)	+= dram_a13_oli_micro.o
-# This is not a typo, uses the same mem settings as the a10s-olinuxino-m
-obj-$(CONFIG_TARGET_AUXTEK_T004)	+= dram_a10s_olinuxino_m.o
-obj-$(CONFIG_TARGET_MK802_A10S)		+= dram_sun5i_auto.o
-obj-$(CONFIG_TARGET_R7DONGLE)		+= dram_r7dongle.o
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index b70e00c..e1891d1 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -33,6 +33,12 @@
 #include <linux/usb/musb.h>
 #include <net.h>
 
+#if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
+/* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */
+int soft_i2c_gpio_sda;
+int soft_i2c_gpio_scl;
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* add board specific code here */
@@ -152,6 +158,10 @@
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUNXI_GPB0_TWI0);
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUNXI_GPB0_TWI0);
 	clock_twi_onoff(0, 1);
+#if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
+	soft_i2c_gpio_sda = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SDA);
+	soft_i2c_gpio_scl = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SCL);
+#endif
 }
 
 #ifdef CONFIG_SPL_BUILD
diff --git a/board/sunxi/dram_a10s_olinuxino_m.c b/board/sunxi/dram_a10s_olinuxino_m.c
deleted file mode 100644
index 8900539..0000000
--- a/board/sunxi/dram_a10s_olinuxino_m.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* this file is generated, don't edit it yourself */
-
-#include <common.h>
-#include <asm/arch/dram.h>
-
-static struct dram_para dram_para = {
-	.clock = 432,
-	.type = 3,
-	.rank_num = 1,
-	.density = 4096,
-	.io_width = 16,
-	.bus_width = 16,
-	.cas = 9,
-	.zq = 123,
-	.odt_en = 0,
-	.size = 512,
-	.tpr0 = 0x42d899b7,
-	.tpr1 = 0xa090,
-	.tpr2 = 0x22a00,
-	.tpr3 = 0,
-	.tpr4 = 0,
-	.tpr5 = 0,
-	.emr1 = 0x4,
-	.emr2 = 0x10,
-	.emr3 = 0,
-};
-
-unsigned long sunxi_dram_init(void)
-{
-	return dramc_init(&dram_para);
-}
diff --git a/board/sunxi/dram_a13_oli_micro.c b/board/sunxi/dram_a13_oli_micro.c
deleted file mode 100644
index 8154ea2..0000000
--- a/board/sunxi/dram_a13_oli_micro.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* this file is generated, don't edit it yourself */
-
-#include <common.h>
-#include <asm/arch/dram.h>
-
-static struct dram_para dram_para = {
-	.clock = 408,
-	.type = 3,
-	.rank_num = 1,
-	.density = 2048,
-	.io_width = 16,
-	.bus_width = 16,
-	.cas = 9,
-	.zq = 123,
-	.odt_en = 0,
-	.size = 256,
-	.tpr0 = 0x42d899b7,
-	.tpr1 = 0xa090,
-	.tpr2 = 0x22a00,
-	.tpr3 = 0,
-	.tpr4 = 0,
-	.tpr5 = 0,
-	.emr1 = 0,
-	.emr2 = 0x10,
-	.emr3 = 0,
-
-};
-
-unsigned long sunxi_dram_init(void)
-{
-	return dramc_init(&dram_para);
-}
diff --git a/board/sunxi/dram_a13_olinuxino.c b/board/sunxi/dram_a13_olinuxino.c
deleted file mode 100644
index ca96260..0000000
--- a/board/sunxi/dram_a13_olinuxino.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* this file is generated, don't edit it yourself */
-
-#include <common.h>
-#include <asm/arch/dram.h>
-
-static struct dram_para dram_para = {
-	.clock = 408,
-	.type = 3,
-	.rank_num = 1,
-	.density = 2048,
-	.io_width = 8,
-	.bus_width = 16,
-	.cas = 9,
-	.zq = 123,
-	.odt_en = 0,
-	.size = 512,
-	.tpr0 = 0x42d899b7,
-	.tpr1 = 0xa090,
-	.tpr2 = 0x22a00,
-	.tpr3 = 0,
-	.tpr4 = 0,
-	.tpr5 = 0,
-	.emr1 = 0,
-	.emr2 = 0x10,
-	.emr3 = 0,
-};
-
-unsigned long sunxi_dram_init(void)
-{
-	return dramc_init(&dram_para);
-}
diff --git a/board/sunxi/dram_bananapi.c b/board/sunxi/dram_bananapi.c
deleted file mode 100644
index 0ed7943..0000000
--- a/board/sunxi/dram_bananapi.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* this file is generated, don't edit it yourself */
-
-#include <common.h>
-#include <asm/arch/dram.h>
-
-static struct dram_para dram_para = {
-	.clock = 432,
-	.type = 3,
-	.rank_num = 1,
-	.density = 4096,
-	.io_width = 16,
-	.bus_width = 32,
-	.cas = 9,
-	.zq = 0x7f,
-	.odt_en = 0,
-	.size = 1024,
-	.tpr0 = 0x42d899b7,
-	.tpr1 = 0xa090,
-	.tpr2 = 0x22a00,
-	.tpr3 = 0x0,
-	.tpr4 = 0x1,
-	.tpr5 = 0x0,
-	.emr1 = 0x4,
-	.emr2 = 0x10,
-	.emr3 = 0x0,
-};
-
-unsigned long sunxi_dram_init(void)
-{
-	return dramc_init(&dram_para);
-}
diff --git a/board/sunxi/dram_r7dongle.c b/board/sunxi/dram_r7dongle.c
deleted file mode 100644
index 59343cb..0000000
--- a/board/sunxi/dram_r7dongle.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* this file is generated, don't edit it yourself */
-
-#include <common.h>
-#include <asm/arch/dram.h>
-
-static struct dram_para dram_para = {
-	.clock = 384,
-	.type = 3,
-	.rank_num = 1,
-	.density = 2048,
-	.io_width = 8,
-	.bus_width = 32,
-	.cas = 9,
-	.zq = 123,
-	.odt_en = 0,
-	.size = 1024,
-	.tpr0 = 0x42d899b7,
-	.tpr1 = 0xa090,
-	.tpr2 = 0x22a00,
-	.tpr3 = 0,
-	.tpr4 = 0,
-	.tpr5 = 0,
-	.emr1 = 0x04,
-	.emr2 = 0x10,
-	.emr3 = 0,
-};
-
-unsigned long sunxi_dram_init(void)
-{
-	return dramc_init(&dram_para);
-}
diff --git a/board/sunxi/dram_sun4i_auto.c b/board/sunxi/dram_sun4i_auto.c
index 826bacf..09e0c9a 100644
--- a/board/sunxi/dram_sun4i_auto.c
+++ b/board/sunxi/dram_sun4i_auto.c
@@ -8,19 +8,25 @@
 	.density = 0,
 	.io_width = 0,
 	.bus_width = 0,
-	.cas = 6,
 	.zq = CONFIG_DRAM_ZQ,
-	.odt_en = 0,
+	.odt_en = CONFIG_DRAM_ODT_EN,
 	.size = 0,
+#ifdef CONFIG_DRAM_TIMINGS_VENDOR_MAGIC
+	.cas = 6,
 	.tpr0 = 0x30926692,
 	.tpr1 = 0x1090,
 	.tpr2 = 0x1a0c8,
-	.tpr3 = 0,
+	.emr2 = 0,
+#else
+#	include "dram_timings_sun4i.h"
+	.active_windowing = 1,
+#endif
+	.tpr3 = CONFIG_DRAM_TPR3,
 	.tpr4 = 0,
 	.tpr5 = 0,
 	.emr1 = CONFIG_DRAM_EMR1,
-	.emr2 = 0,
 	.emr3 = 0,
+	.dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY,
 };
 
 unsigned long sunxi_dram_init(void)
diff --git a/board/sunxi/dram_sun5i_auto.c b/board/sunxi/dram_sun5i_auto.c
index e86b08e..e52d54c 100644
--- a/board/sunxi/dram_sun5i_auto.c
+++ b/board/sunxi/dram_sun5i_auto.c
@@ -5,24 +5,31 @@
 
 static struct dram_para dram_para = {
 	.clock = CONFIG_DRAM_CLK,
+	.mbus_clock = CONFIG_DRAM_MBUS_CLK,
 	.type = 3,
 	.rank_num = 1,
 	.density = 0,
 	.io_width = 0,
 	.bus_width = 0,
-	.cas = 9,
 	.zq = CONFIG_DRAM_ZQ,
-	.odt_en = 0,
+	.odt_en = CONFIG_DRAM_ODT_EN,
 	.size = 0,
+#ifdef CONFIG_DRAM_TIMINGS_VENDOR_MAGIC
+	.cas = 9,
 	.tpr0 = 0x42d899b7,
 	.tpr1 = 0xa090,
 	.tpr2 = 0x22a00,
+	.emr2 = 0x10,
+#else
+#	include "dram_timings_sun4i.h"
+	.active_windowing = 1,
+#endif
 	.tpr3 = 0,
 	.tpr4 = 0,
 	.tpr5 = 0,
 	.emr1 = CONFIG_DRAM_EMR1,
-	.emr2 = 0x10,
 	.emr3 = 0,
+	.dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY,
 };
 
 unsigned long sunxi_dram_init(void)
diff --git a/board/sunxi/dram_timings_sun4i.h b/board/sunxi/dram_timings_sun4i.h
new file mode 100644
index 0000000..29b934d
--- /dev/null
+++ b/board/sunxi/dram_timings_sun4i.h
@@ -0,0 +1,205 @@
+/* This file is automatically generated, do not edit */
+
+#if defined(CONFIG_DRAM_TIMINGS_DDR3_1066F_1333H)
+# if CONFIG_DRAM_CLK <= 360 /* DDR3-1066F @360MHz, timings: 6-5-5-14 */
+	.cas  = 6,
+	.tpr0 = 0x268e5590,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 384 /* DDR3-1066F @384MHz, timings: 6-6-6-15 */
+	.cas  = 6,
+	.tpr0 = 0x288f6690,
+	.tpr1 = 0xa0a0,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 396 /* DDR3-1066F @396MHz, timings: 6-6-6-15 */
+	.cas  = 6,
+	.tpr0 = 0x2a8f6690,
+	.tpr1 = 0xa0a0,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 408 /* DDR3-1066F @408MHz, timings: 7-6-6-16 */
+	.cas  = 7,
+	.tpr0 = 0x2ab06690,
+	.tpr1 = 0xa0a8,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 432 /* DDR3-1066F @432MHz, timings: 7-6-6-17 */
+	.cas  = 7,
+	.tpr0 = 0x2cb16690,
+	.tpr1 = 0xa0b0,
+	.tpr2 = 0x22e00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 456 /* DDR3-1066F @456MHz, timings: 7-6-6-18 */
+	.cas  = 7,
+	.tpr0 = 0x30b26690,
+	.tpr1 = 0xa0b8,
+	.tpr2 = 0x22e00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 468 /* DDR3-1066F @468MHz, timings: 7-7-7-18 */
+	.cas  = 7,
+	.tpr0 = 0x30b27790,
+	.tpr1 = 0xa0c0,
+	.tpr2 = 0x23200,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 480 /* DDR3-1066F @480MHz, timings: 7-7-7-18 */
+	.cas  = 7,
+	.tpr0 = 0x32b27790,
+	.tpr1 = 0xa0c0,
+	.tpr2 = 0x23200,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 504 /* DDR3-1066F @504MHz, timings: 7-7-7-19 */
+	.cas  = 7,
+	.tpr0 = 0x34d37790,
+	.tpr1 = 0xa0d0,
+	.tpr2 = 0x23600,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 528 /* DDR3-1066F @528MHz, timings: 7-7-7-20 */
+	.cas  = 7,
+	.tpr0 = 0x36d47790,
+	.tpr1 = 0xa0d8,
+	.tpr2 = 0x23600,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 540 /* DDR3-1333H @540MHz, timings: 9-8-8-20 */
+	.cas  = 9,
+	.tpr0 = 0x36b488b4,
+	.tpr1 = 0xa0c8,
+	.tpr2 = 0x2b600,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 552 /* DDR3-1333H @552MHz, timings: 9-8-8-20 */
+	.cas  = 9,
+	.tpr0 = 0x38b488b4,
+	.tpr1 = 0xa0c8,
+	.tpr2 = 0x2ba00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 576 /* DDR3-1333H @576MHz, timings: 9-8-8-21 */
+	.cas  = 9,
+	.tpr0 = 0x3ab588b4,
+	.tpr1 = 0xa0d0,
+	.tpr2 = 0x2ba00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 600 /* DDR3-1333H @600MHz, timings: 9-9-9-22 */
+	.cas  = 9,
+	.tpr0 = 0x3cb699b4,
+	.tpr1 = 0xa0d8,
+	.tpr2 = 0x2be00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 624 /* DDR3-1333H @624MHz, timings: 9-9-9-23 */
+	.cas  = 9,
+	.tpr0 = 0x3eb799b4,
+	.tpr1 = 0xa0e8,
+	.tpr2 = 0x2be00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 648 /* DDR3-1333H @648MHz, timings: 9-9-9-24 */
+	.cas  = 9,
+	.tpr0 = 0x42b899b4,
+	.tpr1 = 0xa0f0,
+	.tpr2 = 0x2c200,
+	.emr2 = 0x10,
+# else
+#   error CONFIG_DRAM_CLK is set too high
+# endif
+#elif defined(CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J)
+# if CONFIG_DRAM_CLK <= 360 /* DDR3-800E @360MHz, timings: 6-6-6-14 */
+	.cas  = 6,
+	.tpr0 = 0x268e6690,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 384 /* DDR3-800E @384MHz, timings: 6-6-6-15 */
+	.cas  = 6,
+	.tpr0 = 0x2a8f6690,
+	.tpr1 = 0xa0a0,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 396 /* DDR3-800E @396MHz, timings: 6-6-6-15 */
+	.cas  = 6,
+	.tpr0 = 0x2a8f6690,
+	.tpr1 = 0xa0a0,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x0,
+# elif CONFIG_DRAM_CLK <= 408 /* DDR3-1066G @408MHz, timings: 8-7-7-16 */
+	.cas  = 8,
+	.tpr0 = 0x2cb07790,
+	.tpr1 = 0xa0a8,
+	.tpr2 = 0x22a00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 432 /* DDR3-1066G @432MHz, timings: 8-7-7-17 */
+	.cas  = 8,
+	.tpr0 = 0x2eb17790,
+	.tpr1 = 0xa0b0,
+	.tpr2 = 0x22e00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 456 /* DDR3-1066G @456MHz, timings: 8-7-7-18 */
+	.cas  = 8,
+	.tpr0 = 0x30b27790,
+	.tpr1 = 0xa0b8,
+	.tpr2 = 0x22e00,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 468 /* DDR3-1066G @468MHz, timings: 8-8-8-18 */
+	.cas  = 8,
+	.tpr0 = 0x32b28890,
+	.tpr1 = 0xa0c0,
+	.tpr2 = 0x23200,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 480 /* DDR3-1066G @480MHz, timings: 8-8-8-18 */
+	.cas  = 8,
+	.tpr0 = 0x34b28890,
+	.tpr1 = 0xa0c0,
+	.tpr2 = 0x23200,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 504 /* DDR3-1066G @504MHz, timings: 8-8-8-19 */
+	.cas  = 8,
+	.tpr0 = 0x36d38890,
+	.tpr1 = 0xa0d0,
+	.tpr2 = 0x23600,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 528 /* DDR3-1066G @528MHz, timings: 8-8-8-20 */
+	.cas  = 8,
+	.tpr0 = 0x38d48890,
+	.tpr1 = 0xa0d8,
+	.tpr2 = 0x23600,
+	.emr2 = 0x8,
+# elif CONFIG_DRAM_CLK <= 540 /* DDR3-1333J @540MHz, timings: 10-9-9-20 */
+	.cas  = 10,
+	.tpr0 = 0x38b499b4,
+	.tpr1 = 0xa0c8,
+	.tpr2 = 0x2b600,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 552 /* DDR3-1333J @552MHz, timings: 10-9-9-20 */
+	.cas  = 10,
+	.tpr0 = 0x3ab499b4,
+	.tpr1 = 0xa0c8,
+	.tpr2 = 0x2ba00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 576 /* DDR3-1333J @576MHz, timings: 10-9-9-21 */
+	.cas  = 10,
+	.tpr0 = 0x3cb599b4,
+	.tpr1 = 0xa0d0,
+	.tpr2 = 0x2ba00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 600 /* DDR3-1333J @600MHz, timings: 10-9-9-22 */
+	.cas  = 10,
+	.tpr0 = 0x3eb699b4,
+	.tpr1 = 0xa0d8,
+	.tpr2 = 0x2be00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 624 /* DDR3-1333J @624MHz, timings: 10-10-10-23 */
+	.cas  = 10,
+	.tpr0 = 0x40b7aab4,
+	.tpr1 = 0xa0e8,
+	.tpr2 = 0x2be00,
+	.emr2 = 0x10,
+# elif CONFIG_DRAM_CLK <= 648 /* DDR3-1333J @648MHz, timings: 10-10-10-24 */
+	.cas  = 10,
+	.tpr0 = 0x44b8aab4,
+	.tpr1 = 0xa0f0,
+	.tpr2 = 0x2c200,
+	.emr2 = 0x10,
+# else
+#   error CONFIG_DRAM_CLK is set too high
+# endif
+#else
+# error CONFIG_DRAM_TIMINGS_* is not defined
+#endif
diff --git a/board/sunxi/gmac.c b/board/sunxi/gmac.c
index 4e4615e..8849132 100644
--- a/board/sunxi/gmac.c
+++ b/board/sunxi/gmac.c
@@ -24,20 +24,13 @@
 #ifdef CONFIG_RGMII
 	setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII |
 		CCM_GMAC_CTRL_GPIT_RGMII);
+	setbits_le32(&ccm->gmac_clk_cfg,
+		     CCM_GMAC_CTRL_TX_CLK_DELAY(CONFIG_GMAC_TX_DELAY));
 #else
 	setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_MII |
 		CCM_GMAC_CTRL_GPIT_MII);
 #endif
 
-	/*
-	 * In order for the gmac nic to work reliable on the Bananapi, we
-	 * need to set bits 10-12 GTXDC "GMAC Transmit Clock Delay Chain"
-	 * of the GMAC clk register to 3.
-	 */
-#if defined CONFIG_TARGET_BANANAPI || defined CONFIG_TARGET_BANANAPRO
-	setbits_le32(&ccm->gmac_clk_cfg, 0x3 << 10);
-#endif
-
 #ifndef CONFIG_MACH_SUN6I
 	/* Configure pin mux settings for GMAC */
 	for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) {
diff --git a/board/synopsys/Kconfig b/board/synopsys/Kconfig
index f614f88..8ab48cd 100644
--- a/board/synopsys/Kconfig
+++ b/board/synopsys/Kconfig
@@ -7,13 +7,3 @@
 	default "arcangel4"
 
 endif
-
-if TARGET_ARCANGEL4_BE
-
-config SYS_VENDOR
-	default "synopsys"
-
-config SYS_CONFIG_NAME
-	default "arcangel4-be"
-
-endif
diff --git a/board/synopsys/MAINTAINERS b/board/synopsys/MAINTAINERS
index 720edd8..43114ce 100644
--- a/board/synopsys/MAINTAINERS
+++ b/board/synopsys/MAINTAINERS
@@ -3,5 +3,4 @@
 S:	Maintained
 F:	include/configs/arcangel4.h
 F:	configs/arcangel4_defconfig
-F:	include/configs/arcangel4-be.h
 F:	configs/arcangel4-be_defconfig
diff --git a/board/taskit/stamp9g20/Kconfig b/board/taskit/stamp9g20/Kconfig
index 3139f9a..1121dac 100644
--- a/board/taskit/stamp9g20/Kconfig
+++ b/board/taskit/stamp9g20/Kconfig
@@ -6,9 +6,6 @@
 config SYS_VENDOR
 	default "taskit"
 
-config SYS_SOC
-	default "at91"
-
 config SYS_CONFIG_NAME
 	default "stamp9g20"
 
diff --git a/board/ti/am335x/Kconfig b/board/ti/am335x/Kconfig
index 1ddbb2c..a20e0c1 100644
--- a/board/ti/am335x/Kconfig
+++ b/board/ti/am335x/Kconfig
@@ -37,4 +37,20 @@
 	  booted via NOR.  In this case we will enable certain pinmux early
 	  as the ROM only partially sets up pinmux.  We also default to using
 	  NOR for environment.
+
+config DM
+	default y if !SPL_BUILD
+
+config DM_GPIO
+	default y if DM && !SPL_BUILD
+
+config DM_SERIAL
+	default y if DM && !SPL_BUILD
+
+config SYS_MALLOC_F
+	default y if DM && !SPL_BUILD
+
+config SYS_MALLOC_F_LEN
+	default 0x400 if DM && !SPL_BUILD
+
 endif
diff --git a/board/ti/beagle_x15/board.c b/board/ti/beagle_x15/board.c
index db96e34..3a7e04d 100644
--- a/board/ti/beagle_x15/board.c
+++ b/board/ti/beagle_x15/board.c
@@ -47,7 +47,8 @@
 	.sdram_config_init	= 0x61851b32,
 	.sdram_config		= 0x61851b32,
 	.sdram_config2		= 0x00000000,
-	.ref_ctrl		= 0x00001035,
+	.ref_ctrl		= 0x000040F1,
+	.ref_ctrl_final		= 0x00001035,
 	.sdram_tim1		= 0xceef266b,
 	.sdram_tim2		= 0x328f7fda,
 	.sdram_tim3		= 0x027f88a8,
@@ -103,7 +104,8 @@
 	.sdram_config_init	= 0x61851b32,
 	.sdram_config		= 0x61851b32,
 	.sdram_config2		= 0x00000000,
-	.ref_ctrl		= 0x00001035,
+	.ref_ctrl		= 0x000040F1,
+	.ref_ctrl_final		= 0x00001035,
 	.sdram_tim1		= 0xceef266b,
 	.sdram_tim2		= 0x328f7fda,
 	.sdram_tim3		= 0x027f88a8,
diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c
index 04ec675..8892a28 100644
--- a/board/ti/ks2_evm/board.c
+++ b/board/ti/ks2_evm/board.c
@@ -35,12 +35,14 @@
 
 int dram_init(void)
 {
-	ddr3_init();
+	u32 ddr3_size;
+
+	ddr3_size = ddr3_init();
 
 	gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
 				    CONFIG_MAX_RAM_BANK_SIZE);
 	aemif_init(ARRAY_SIZE(aemif_configs), aemif_configs);
-	ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE);
+	ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE, ddr3_size);
 	return 0;
 }
 
diff --git a/board/ti/ks2_evm/ddr3_k2e.c b/board/ti/ks2_evm/ddr3_k2e.c
index 40fd966..35ffb42 100644
--- a/board/ti/ks2_evm/ddr3_k2e.c
+++ b/board/ti/ks2_evm/ddr3_k2e.c
@@ -11,11 +11,11 @@
 #include "ddr3_cfg.h"
 #include <asm/arch/ddr3.h>
 
-static int ddr3_size;
 static struct pll_init_data ddr3_400 = DDR3_PLL_400;
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
+	u32 ddr3_size;
 	char dimm_name[32];
 
 	if (~(readl(KS2_PLL_CNTRL_BASE + KS2_RSTCTRL_RSTYPE) & 0x1))
@@ -43,13 +43,11 @@
 		printf("DRAM: 4 GiB\n");
 		ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_4g);
 		ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_4g);
+	} else {
+		printf("Unknown SO-DIMM. Cannot configure DDR3\n");
+		while (1)
+			;
 	}
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
 	return ddr3_size;
 }
diff --git a/board/ti/ks2_evm/ddr3_k2hk.c b/board/ti/ks2_evm/ddr3_k2hk.c
index a1c3d05..b36eb27 100644
--- a/board/ti/ks2_evm/ddr3_k2hk.c
+++ b/board/ti/ks2_evm/ddr3_k2hk.c
@@ -12,14 +12,13 @@
 #include <asm/arch/ddr3.h>
 #include <asm/arch/hardware.h>
 
-static int ddr3_size;
-
 struct pll_init_data ddr3a_333 = DDR3_PLL_333(A);
 struct pll_init_data ddr3a_400 = DDR3_PLL_400(A);
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
 	char dimm_name[32];
+	u32 ddr3_size;
 
 	ddr3_get_dimm_params(dimm_name);
 
@@ -93,12 +92,6 @@
 	/* Apply the workaround for PG 1.0 and 1.1 Silicons */
 	if (cpu_revision() <= 1)
 		ddr3_err_reset_workaround();
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
 	return ddr3_size;
 }
diff --git a/board/ti/ks2_evm/ddr3_k2l.c b/board/ti/ks2_evm/ddr3_k2l.c
index 15a14f2..00fc194 100644
--- a/board/ti/ks2_evm/ddr3_k2l.c
+++ b/board/ti/ks2_evm/ddr3_k2l.c
@@ -11,28 +11,20 @@
 #include "ddr3_cfg.h"
 #include <asm/arch/ddr3.h>
 
-static int ddr3_size;
 static struct pll_init_data ddr3_400 = DDR3_PLL_400;
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
 	init_pll(&ddr3_400);
 
 	/* No SO-DIMM, 2GB discreet DDR */
 	printf("DRAM: 2 GiB\n");
-	ddr3_size = 2;
 
 	/* Reset DDR3 PHY after PLL enabled */
 	ddr3_reset_ddrphy();
 
 	ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_2g);
 	ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_2g);
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
-	return ddr3_size;
+	return 2;
 }
diff --git a/board/toradex/apalis_t30/apalis_t30.c b/board/toradex/apalis_t30/apalis_t30.c
index 5d2c024..6244214 100644
--- a/board/toradex/apalis_t30/apalis_t30.c
+++ b/board/toradex/apalis_t30/apalis_t30.c
@@ -42,7 +42,7 @@
 	u8 addr, data[1];
 	int err;
 
-	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev);
 	if (err) {
 		debug("%s: Cannot find PMIC I2C chip\n", __func__);
 		return err;
@@ -51,7 +51,7 @@
 	data[0] = 0x27;
 	addr = 0x25;
 
-	err = i2c_write(dev, addr, data, 1);
+	err = dm_i2c_write(dev, addr, data, 1);
 	if (err) {
 		debug("failed to set VDD supply\n");
 		return err;
@@ -61,7 +61,7 @@
 	data[0] = 0x0D;
 	addr = 0x24;
 
-	err = i2c_write(dev, addr, data, 1);
+	err = dm_i2c_write(dev, addr, data, 1);
 	if (err) {
 		debug("failed to enable VDD supply\n");
 		return err;
@@ -71,7 +71,7 @@
 	data[0] = 0x0D;
 	addr = 0x35;
 
-	err = i2c_write(dev, addr, data, 1);
+	err = dm_i2c_write(dev, addr, data, 1);
 	if (err) {
 		debug("failed to set AVDD supply\n");
 		return err;
diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c
index 42a8d0c..3110405 100644
--- a/board/xilinx/microblaze-generic/microblaze-generic.c
+++ b/board/xilinx/microblaze-generic/microblaze-generic.c
@@ -11,16 +11,62 @@
 
 #include <common.h>
 #include <config.h>
+#include <fdtdec.h>
 #include <netdev.h>
 #include <asm/processor.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 #include <asm/gpio.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifdef CONFIG_XILINX_GPIO
 static int reset_pin = -1;
 #endif
 
+#ifdef CONFIG_OF_CONTROL
+ulong ram_base;
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = ram_base;
+	gd->bd->bi_dram[0].size = get_effective_memsize();
+}
+
+int dram_init(void)
+{
+	int node;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	const void *blob = gd->fdt_blob;
+
+	node = fdt_node_offset_by_prop_value(blob, -1, "device_type",
+					     "memory", 7);
+	if (node == -FDT_ERR_NOTFOUND) {
+		debug("DRAM: Can't get memory node\n");
+		return 1;
+	}
+	addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+	if (addr == FDT_ADDR_T_NONE || size == 0) {
+		debug("DRAM: Can't get base address or size\n");
+		return 1;
+	}
+	ram_base = addr;
+
+	gd->ram_top = addr; /* In setup_dest_addr() is done +ram_size */
+	gd->ram_size = size;
+
+	return 0;
+};
+#else
+int dram_init(void)
+{
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+#endif
+
 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 #ifdef CONFIG_XILINX_GPIO
diff --git a/common/Kconfig b/common/Kconfig
index fd84fa0..2ca002d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -153,6 +153,29 @@
 
 menu "Device access commands"
 
+config CMD_DM
+	bool "dm - Access to driver model information"
+	depends on DM
+	default y
+	help
+	  Provides access to driver model data structures and information,
+	  such as a list of devices, list of uclasses and the state of each
+	  device (e.g. activated). This is not required for operation, but
+	  can be useful to see the state of driver model for debugging or
+	  interest.
+
+config CMD_DEMO
+	bool "demo - Demonstration commands for driver model"
+	depends on DM
+	help
+	  Provides a 'demo' command which can be used to play around with
+	  driver model. To use this properly you will need to enable one or
+	  both of the demo devices (DM_DEMO_SHAPE and DM_DEMO_SIMPLE).
+	  Otherwise you will always get an empty list of devices. The demo
+	  devices are defined in the sandbox device tree, so the easiest
+	  option is to use sandbox and pass the -d point to sandbox's
+	  u-boot.dtb file.
+
 config CMD_LOADB
 	bool "loadb"
 	help
diff --git a/common/Makefile b/common/Makefile
index 94554f2..7216a13 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -27,6 +27,8 @@
 # boards
 obj-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o
 obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o
+obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+obj-$(CONFIG_DISPLAY_BOARDINFO_LATE) += board_info.o
 
 # core command
 obj-y += cmd_boot.o
@@ -196,7 +198,9 @@
 obj-$(CONFIG_I2C_EDID) += edid.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-y += splash.o
+obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o
 obj-$(CONFIG_LCD) += lcd.o lcd_console.o
+obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
 obj-$(CONFIG_MENU) += menu.o
 obj-$(CONFIG_MODEM_SUPPORT) += modem.o
diff --git a/common/board_f.c b/common/board_f.c
index 215108b..4d8b8a6 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -111,7 +111,7 @@
 {
 # if defined(CONFIG_HW_WATCHDOG) && (defined(CONFIG_BLACKFIN) || \
 	defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
-	defined(CONFIG_SH))
+	defined(CONFIG_SH) || defined(CONFIG_AT91SAM9_WATCHDOG))
 	hw_watchdog_init();
 # endif
 	puts("       Watchdog enabled\n");
@@ -262,7 +262,7 @@
 
 static int setup_mon_len(void)
 {
-#ifdef __ARM__
+#if defined(__ARM__) || defined(__MICROBLAZE__)
 	gd->mon_len = (ulong)&__bss_end - (ulong)_start;
 #elif defined(CONFIG_SANDBOX)
 	gd->mon_len = (ulong)&_end - (ulong)_init;
@@ -573,48 +573,22 @@
 	return 0;
 }
 
+int arch_reserve_stacks(void)
+{
+	return 0;
+}
+
 static int reserve_stacks(void)
 {
-#ifdef CONFIG_SPL_BUILD
-# ifdef CONFIG_ARM
-	gd->start_addr_sp -= 128;	/* leave 32 words for abort-stack */
-	gd->irq_sp = gd->start_addr_sp;
-# endif
-#else
-# ifdef CONFIG_PPC
-	ulong *s;
-# endif
-
-	/* setup stack pointer for exceptions */
+	/* make stack pointer 16-byte aligned */
 	gd->start_addr_sp -= 16;
 	gd->start_addr_sp &= ~0xf;
-	gd->irq_sp = gd->start_addr_sp;
 
 	/*
-	 * Handle architecture-specific things here
-	 * TODO(sjg@chromium.org): Perhaps create arch_reserve_stack()
-	 * to handle this and put in arch/xxx/lib/stack.c
+	 * let the architecture specific code tailor gd->start_addr_sp and
+	 * gd->irq_sp
 	 */
-# if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
-#  ifdef CONFIG_USE_IRQ
-	gd->start_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ);
-	debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
-		CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ, gd->start_addr_sp);
-
-	/* 8-byte alignment for ARM ABI compliance */
-	gd->start_addr_sp &= ~0x07;
-#  endif
-	/* leave 3 words for abort-stack, plus 1 for alignment */
-	gd->start_addr_sp -= 16;
-# elif defined(CONFIG_PPC)
-	/* Clear initial stack frame */
-	s = (ulong *) gd->start_addr_sp;
-	*s = 0; /* Terminate back chain */
-	*++s = 0; /* NULL return address */
-# endif /* Architecture specific code */
-
-	return 0;
-#endif
+	return arch_reserve_stacks();
 }
 
 static int display_new_sp(void)
@@ -894,7 +868,7 @@
 	prt_mpc5xxx_clks,
 #endif /* CONFIG_MPC5xxx */
 #if defined(CONFIG_DISPLAY_BOARDINFO)
-	checkboard,		/* display board info */
+	show_board_info,
 #endif
 	INIT_FUNC_WATCHDOG_INIT
 #if defined(CONFIG_MISC_INIT_F)
@@ -909,7 +883,7 @@
 #endif
 	announce_dram_init,
 	/* TODO: unify all these dram functions? */
-#if defined(CONFIG_ARM) || defined(CONFIG_X86)
+#if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32)
 	dram_init,		/* configure available RAM banks */
 #endif
 #if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
@@ -1075,4 +1049,22 @@
 	/* NOTREACHED - board_init_r() does not return */
 	hang();
 }
+#else
+ulong board_init_f_mem(ulong top)
+{
+	/* Leave space for the stack we are running with now */
+	top -= 0x40;
+
+	top -= sizeof(struct global_data);
+	top = ALIGN(top, 16);
+	gd = (struct global_data *)top;
+	memset((void *)gd, '\0', sizeof(*gd));
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	top -= CONFIG_SYS_MALLOC_F_LEN;
+	gd->malloc_base = top;
+#endif
+
+	return top;
+}
 #endif /* CONFIG_X86 */
diff --git a/common/board_info.c b/common/board_info.c
new file mode 100644
index 0000000..42d0641
--- /dev/null
+++ b/common/board_info.c
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <linux/compiler.h>
+
+int __weak checkboard(void)
+{
+	printf("Board: Unknown\n");
+	return 0;
+}
+
+/*
+ * If the root node of the DTB has a "model" property, show it.
+ * If CONFIG_OF_CONTROL is disabled or the "model" property is missing,
+ * fall back to checkboard().
+ */
+int show_board_info(void)
+{
+#ifdef CONFIG_OF_CONTROL
+	DECLARE_GLOBAL_DATA_PTR;
+	const char *model;
+
+	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+
+	if (model) {
+		printf("Model: %s\n", model);
+		return 0;
+	}
+#endif
+
+	return checkboard();
+}
diff --git a/common/board_r.c b/common/board_r.c
index a301cc2..4fcd4f6 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -55,6 +55,9 @@
 #include <dm/root.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
+#ifdef CONFIG_AVR32
+#include <asm/arch/mmu.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -294,6 +297,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+static int initr_manual_reloc_cmdtable(void)
+{
+	fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
+		       ll_entry_count(cmd_tbl_t, cmd));
+	return 0;
+}
+#endif
+
 #if !defined(CONFIG_SYS_NO_FLASH)
 static int initr_flash(void)
 {
@@ -450,6 +462,18 @@
 	return 0;
 }
 
+#ifdef CONFIG_SYS_BOOTPARAMS_LEN
+static int initr_malloc_bootparams(void)
+{
+	gd->bd->bi_boot_params = (ulong)malloc(CONFIG_SYS_BOOTPARAMS_LEN);
+	if (!gd->bd->bi_boot_params) {
+		puts("WARNING: Cannot allocate space for boot parameters\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SC3
 /* TODO: with new initcalls, move this into the driver */
 extern void sc3_read_eeprom(void);
@@ -476,24 +500,8 @@
 }
 #endif
 
-#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
-static int show_model_r(void)
-{
-	/* Put this here so it appears on the LCD, now it is ready */
-# ifdef CONFIG_OF_CONTROL
-	const char *model;
-
-	model = (char *)fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-	printf("Model: %s\n", model ? model : "<unknown>");
-# else
-	checkboard();
-# endif
-	return 0;
-}
-#endif
-
 /* enable exceptions */
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM) || defined(CONFIG_AVR32)
 static int initr_enable_interrupts(void)
 {
 	enable_interrupts();
@@ -718,6 +726,9 @@
 	initr_serial,
 	initr_announce,
 	INIT_FUNC_WATCHDOG_RESET
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+	initr_manual_reloc_cmdtable,
+#endif
 #ifdef CONFIG_PPC
 	initr_trap,
 #endif
@@ -779,6 +790,9 @@
 	initr_dataflash,
 #endif
 	initr_env,
+#ifdef CONFIG_SYS_BOOTPARAMS_LEN
+	initr_malloc_bootparams,
+#endif
 	INIT_FUNC_WATCHDOG_RESET
 	initr_secondary_cpu,
 #ifdef CONFIG_SC3
@@ -801,7 +815,7 @@
 #endif
 	console_init_r,		/* fully init console as a device */
 #ifdef CONFIG_DISPLAY_BOARDINFO_LATE
-	show_model_r,
+	show_board_info,
 #endif
 #ifdef CONFIG_ARCH_MISC_INIT
 	arch_misc_init,		/* miscellaneous arch-dependent init */
@@ -814,10 +828,10 @@
 	initr_kgdb,
 #endif
 	interrupt_init,
-#if defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) || defined(CONFIG_AVR32)
 	initr_enable_interrupts,
 #endif
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32)
 	timer_init,		/* initialize timer */
 #endif
 #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
@@ -882,6 +896,10 @@
 	int i;
 #endif
 
+#ifdef CONFIG_AVR32
+	mmu_init_r(dest_addr);
+#endif
+
 #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
 	gd = new_gd;
 #endif
diff --git a/common/bootm.c b/common/bootm.c
index e2dc164..34f60bb 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -233,7 +233,7 @@
 		return 1;
 	}
 
-	set_working_fdt_addr(images.ft_addr);
+	set_working_fdt_addr((ulong)images.ft_addr);
 
 	return 0;
 }
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index e6d8a7a..aa81da2 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -183,8 +183,14 @@
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	bd_t *bd = gd->bd;
-	print_num("mem start      ",	(ulong)bd->bi_memstart);
-	print_lnum("mem size       ",	(u64)bd->bi_memsize);
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+		print_num("DRAM bank",	i);
+		print_num("-> start",	bd->bi_dram[i].start);
+		print_num("-> size",	bd->bi_dram[i].size);
+	}
+
 	print_num("flash start    ",	(ulong)bd->bi_flashstart);
 	print_num("flash size     ",	(ulong)bd->bi_flashsize);
 	print_num("flash offset   ",	(ulong)bd->bi_flashoffset);
@@ -196,6 +202,12 @@
 	print_eths();
 #endif
 	printf("baudrate    = %u bps\n", gd->baudrate);
+	print_num("relocaddr", gd->relocaddr);
+	print_num("reloc off", gd->reloc_off);
+	print_num("fdt_blob", (ulong)gd->fdt_blob);
+	print_num("new_fdt", (ulong)gd->new_fdt);
+	print_num("fdt_size", (ulong)gd->fdt_size);
+
 	return 0;
 }
 
@@ -333,8 +345,8 @@
 	bd_t *bd = gd->bd;
 
 	print_num("boot_params",	(ulong)bd->bi_boot_params);
-	print_num("memstart",		(ulong)bd->bi_memstart);
-	print_lnum("memsize",		(u64)bd->bi_memsize);
+	print_num("memstart",		(ulong)bd->bi_dram[0].start);
+	print_lnum("memsize",		(u64)bd->bi_dram[0].size);
 	print_num("flashstart",		(ulong)bd->bi_flashstart);
 	print_num("flashsize",		(ulong)bd->bi_flashsize);
 	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 6723360..48199bf 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -185,6 +185,9 @@
 	"\tcmdline - OS specific command line processing/setup\n"
 	"\tbdt     - OS specific bd_t processing\n"
 	"\tprep    - OS specific prep before relocation or go\n"
+#if defined(CONFIG_TRACE)
+	"\tfake    - OS specific fake start without go\n"
+#endif
 	"\tgo      - start OS";
 #endif
 
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
index 652c61c..8a10bdf 100644
--- a/common/cmd_demo.c
+++ b/common/cmd_demo.c
@@ -39,6 +39,26 @@
 	return 0;
 }
 
+static int do_demo_light(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	int light;
+	int ret;
+
+	if (argc) {
+		light = simple_strtoul(argv[0], NULL, 16);
+		ret = demo_set_light(demo_dev, light);
+	} else {
+		ret = demo_get_light(demo_dev);
+		if (ret >= 0) {
+			printf("Light: %x\n", ret);
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
 int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	struct udevice *dev;
@@ -61,6 +81,7 @@
 static cmd_tbl_t demo_commands[] = {
 	U_BOOT_CMD_MKENT(list, 0, 1, do_demo_list, "", ""),
 	U_BOOT_CMD_MKENT(hello, 2, 1, do_demo_hello, "", ""),
+	U_BOOT_CMD_MKENT(light, 2, 1, do_demo_light, "", ""),
 	U_BOOT_CMD_MKENT(status, 1, 1, do_demo_status, "", ""),
 };
 
@@ -76,7 +97,9 @@
 				ARRAY_SIZE(demo_commands));
 	argc -= 2;
 	argv += 2;
-	if (!demo_cmd || argc > demo_cmd->maxargs)
+
+	if ((!demo_cmd || argc > demo_cmd->maxargs) ||
+	    ((demo_cmd->name[0] != 'l') && (argc < 1)))
 		return CMD_RET_USAGE;
 
 	if (argc) {
@@ -86,6 +109,10 @@
 			return cmd_process_error(cmdtp, ret);
 		argc--;
 		argv++;
+	} else {
+		demo_dev = NULL;
+		if (demo_cmd->cmd != do_demo_list)
+			return CMD_RET_USAGE;
 	}
 
 	ret = demo_cmd->cmd(demo_cmd, flag, argc, argv);
@@ -98,5 +125,7 @@
 	"Driver model (dm) demo operations",
 	"list                     List available demo devices\n"
 	"demo hello <num> [<char>]     Say hello\n"
-	"demo status <num>             Get demo device status"
+	"demo light [<num>]            Set or get the lights\n"
+	"demo status <num>             Get demo device status\n"
+	"demo list                     List available demo devices"
 );
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index dc59fab..48b3e70 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -38,13 +38,13 @@
  */
 struct fdt_header *working_fdt;
 
-void set_working_fdt_addr(void *addr)
+void set_working_fdt_addr(ulong addr)
 {
 	void *buf;
 
-	buf = map_sysmem((ulong)addr, 0);
+	buf = map_sysmem(addr, 0);
 	working_fdt = buf;
-	setenv_addr("fdtaddr", addr);
+	setenv_ulong("fdtaddr", addr);
 }
 
 /*
@@ -111,7 +111,7 @@
 			if (!blob || !fdt_valid(&blob))
 				return 1;
 			printf("The address of the fdt is %#08lx\n",
-			       control ? (ulong)blob :
+			       control ? (ulong)map_to_sysmem(blob) :
 					getenv_hex("fdtaddr", 0));
 			return 0;
 		}
@@ -123,7 +123,7 @@
 		if (control)
 			gd->fdt_blob = blob;
 		else
-			set_working_fdt_addr((void *)blob);
+			set_working_fdt_addr(addr);
 
 		if (argc >= 2) {
 			int  len;
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 484a6c6..7f99aab 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -346,7 +346,7 @@
 	   "loadable FPGA image support",
 	   "[operation type] [device number] [image address] [image size]\n"
 	   "fpga operations:\n"
-	   "  dump\t[dev]\t\t\tLoad device to memory buffer\n"
+	   "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
 	   "  info\t[dev]\t\t\tlist known device information\n"
 	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
 #if defined(CONFIG_CMD_FPGA_LOADP)
diff --git a/common/cmd_fs.c b/common/cmd_fs.c
index 0d9da11..e146254 100644
--- a/common/cmd_fs.c
+++ b/common/cmd_fs.c
@@ -81,3 +81,18 @@
 	"    - List files in directory 'directory' of partition 'part' on\n"
 	"      device type 'interface' instance 'dev'."
 )
+
+static int do_fstype_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
+				char * const argv[])
+{
+	return do_fs_type(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+	fstype, 4, 1, do_fstype_wrapper,
+	"Look up a filesystem type",
+	"<interface> <dev>:<part>\n"
+	"- print filesystem type\n"
+	"fstype <interface> <dev>:<part> <varname>\n"
+	"- set environment variable to filesystem type\n"
+);
diff --git a/common/cmd_gettime.c b/common/cmd_gettime.c
index 320ff70..c48baad 100644
--- a/common/cmd_gettime.c
+++ b/common/cmd_gettime.c
@@ -35,6 +35,6 @@
 
 U_BOOT_CMD(
 	gettime,	1,	1,	do_gettime,
-	"get timer val elapsed,\n",
-	"get time elapsed from uboot start\n"
+	"get timer val elapsed",
+	"get time elapsed from uboot start"
 );
diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c
index 22db1bb..ad38cbf 100644
--- a/common/cmd_i2c.c
+++ b/common/cmd_i2c.c
@@ -83,12 +83,12 @@
 /* Display values from last command.
  * Memory modify remembered values are different from display memory.
  */
-static uchar	i2c_dp_last_chip;
+static uint	i2c_dp_last_chip;
 static uint	i2c_dp_last_addr;
 static uint	i2c_dp_last_alen;
 static uint	i2c_dp_last_length = 0x10;
 
-static uchar	i2c_mm_last_chip;
+static uint	i2c_mm_last_chip;
 static uint	i2c_mm_last_addr;
 static uint	i2c_mm_last_alen;
 
@@ -133,7 +133,7 @@
 #ifdef CONFIG_DM_I2C
 static struct udevice *i2c_cur_bus;
 
-static int i2c_set_bus_num(unsigned int busnum)
+static int cmd_i2c_set_bus_num(unsigned int busnum)
 {
 	struct udevice *bus;
 	int ret;
@@ -168,7 +168,7 @@
 	if (ret)
 		return ret;
 
-	return i2c_get_chip(bus, chip_addr, devp);
+	return i2c_get_chip(bus, chip_addr, 1, devp);
 }
 
 #endif
@@ -282,7 +282,7 @@
  */
 static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	u_char	chip;
+	uint	chip;
 	uint	devaddr, length;
 	int alen;
 	u_char  *memaddr;
@@ -323,7 +323,7 @@
 	if (!ret && alen != -1)
 		ret = i2c_set_chip_offset_len(dev, alen);
 	if (!ret)
-		ret = i2c_read(dev, devaddr, memaddr, length);
+		ret = dm_i2c_read(dev, devaddr, memaddr, length);
 #else
 	ret = i2c_read(chip, devaddr, alen, memaddr, length);
 #endif
@@ -335,16 +335,17 @@
 
 static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	u_char	chip;
+	uint	chip;
 	uint	devaddr, length;
 	int alen;
 	u_char  *memaddr;
 	int ret;
 #ifdef CONFIG_DM_I2C
 	struct udevice *dev;
+	struct dm_i2c_chip *i2c_chip;
 #endif
 
-	if (argc != 5)
+	if ((argc < 5) || (argc > 6))
 		return cmd_usage(cmdtp);
 
 	/*
@@ -367,7 +368,7 @@
 		return cmd_usage(cmdtp);
 
 	/*
-	 * Length is the number of objects, not number of bytes.
+	 * Length is the number of bytes.
 	 */
 	length = simple_strtoul(argv[4], NULL, 16);
 
@@ -377,22 +378,47 @@
 		ret = i2c_set_chip_offset_len(dev, alen);
 	if (ret)
 		return i2c_report_err(ret, I2C_ERR_WRITE);
+	i2c_chip = dev_get_parent_platdata(dev);
+	if (!i2c_chip)
+		return i2c_report_err(ret, I2C_ERR_WRITE);
 #endif
 
-	while (length-- > 0) {
+	if (argc == 6 && !strcmp(argv[5], "-s")) {
+		/*
+		 * Write all bytes in a single I2C transaction. If the target
+		 * device is an EEPROM, it is your responsibility to not cross
+		 * a page boundary. No write delay upon completion, take this
+		 * into account if linking commands.
+		 */
 #ifdef CONFIG_DM_I2C
-		ret = i2c_write(dev, devaddr++, memaddr++, 1);
+		i2c_chip->flags &= ~DM_I2C_CHIP_WR_ADDRESS;
+		ret = dm_i2c_write(dev, devaddr, memaddr, length);
 #else
-		ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
+		ret = i2c_write(chip, devaddr, alen, memaddr, length);
 #endif
 		if (ret)
 			return i2c_report_err(ret, I2C_ERR_WRITE);
+	} else {
+		/*
+		 * Repeated addressing - perform <length> separate
+		 * write transactions of one byte each
+		 */
+		while (length-- > 0) {
+#ifdef CONFIG_DM_I2C
+			i2c_chip->flags |= DM_I2C_CHIP_WR_ADDRESS;
+			ret = dm_i2c_write(dev, devaddr++, memaddr++, 1);
+#else
+			ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
+#endif
+			if (ret)
+				return i2c_report_err(ret, I2C_ERR_WRITE);
 /*
  * No write delay with FRAM devices.
  */
 #if !defined(CONFIG_SYS_I2C_FRAM)
-		udelay(11000);
+			udelay(11000);
 #endif
+		}
 	}
 	return 0;
 }
@@ -444,7 +470,7 @@
  */
 static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	u_char	chip;
+	uint	chip;
 	uint	addr, length;
 	int alen;
 	int	j, nbytes, linebytes;
@@ -513,12 +539,12 @@
 		linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
 
 #ifdef CONFIG_DM_I2C
-		ret = i2c_read(dev, addr, linebuf, linebytes);
+		ret = dm_i2c_read(dev, addr, linebuf, linebytes);
 #else
 		ret = i2c_read(chip, addr, alen, linebuf, linebytes);
 #endif
 		if (ret)
-			i2c_report_err(ret, I2C_ERR_READ);
+			return i2c_report_err(ret, I2C_ERR_READ);
 		else {
 			printf("%04x:", addr);
 			cp = linebuf;
@@ -563,7 +589,7 @@
  */
 static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	uchar	chip;
+	uint	chip;
 	ulong	addr;
 	int	alen;
 	uchar	byte;
@@ -611,12 +637,12 @@
 
 	while (count-- > 0) {
 #ifdef CONFIG_DM_I2C
-		ret = i2c_write(dev, addr++, &byte, 1);
+		ret = dm_i2c_write(dev, addr++, &byte, 1);
 #else
 		ret = i2c_write(chip, addr++, alen, &byte, 1);
 #endif
 		if (ret)
-			i2c_report_err(ret, I2C_ERR_WRITE);
+			return i2c_report_err(ret, I2C_ERR_WRITE);
 		/*
 		 * Wait for the write to complete.  The write can take
 		 * up to 10mSec (we allow a little more time).
@@ -649,7 +675,7 @@
  */
 static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	uchar	chip;
+	uint	chip;
 	ulong	addr;
 	int	alen;
 	int	count;
@@ -698,7 +724,7 @@
 	err = 0;
 	while (count-- > 0) {
 #ifdef CONFIG_DM_I2C
-		ret = i2c_read(dev, addr, &byte, 1);
+		ret = dm_i2c_read(dev, addr, &byte, 1);
 #else
 		ret = i2c_read(chip, addr, alen, &byte, 1);
 #endif
@@ -734,7 +760,7 @@
 static int
 mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 {
-	uchar	chip;
+	uint	chip;
 	ulong	addr;
 	int	alen;
 	ulong	data;
@@ -793,21 +819,20 @@
 	do {
 		printf("%08lx:", addr);
 #ifdef CONFIG_DM_I2C
-		ret = i2c_read(dev, addr, (uchar *)&data, size);
+		ret = dm_i2c_read(dev, addr, (uchar *)&data, size);
 #else
 		ret = i2c_read(chip, addr, alen, (uchar *)&data, size);
 #endif
 		if (ret)
-			i2c_report_err(ret, I2C_ERR_READ);
-		else {
-			data = cpu_to_be32(data);
-			if (size == 1)
-				printf(" %02lx", (data >> 24) & 0x000000FF);
-			else if (size == 2)
-				printf(" %04lx", (data >> 16) & 0x0000FFFF);
-			else
-				printf(" %08lx", data);
-		}
+			return i2c_report_err(ret, I2C_ERR_READ);
+
+		data = cpu_to_be32(data);
+		if (size == 1)
+			printf(" %02lx", (data >> 24) & 0x000000FF);
+		else if (size == 2)
+			printf(" %04lx", (data >> 16) & 0x0000FFFF);
+		else
+			printf(" %08lx", data);
 
 		nbytes = cli_readline(" ? ");
 		if (nbytes == 0) {
@@ -841,14 +866,15 @@
 				 */
 				bootretry_reset_cmd_timeout();
 #ifdef CONFIG_DM_I2C
-				ret = i2c_write(dev, addr, (uchar *)&data,
-						size);
+				ret = dm_i2c_write(dev, addr, (uchar *)&data,
+						   size);
 #else
 				ret = i2c_write(chip, addr, alen,
 						(uchar *)&data, size);
 #endif
 				if (ret)
-					i2c_report_err(ret, I2C_ERR_WRITE);
+					return i2c_report_err(ret,
+							      I2C_ERR_WRITE);
 #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
 				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
@@ -917,7 +943,7 @@
 			continue;
 #endif
 #ifdef CONFIG_DM_I2C
-		ret = i2c_probe(bus, j, 0, &dev);
+		ret = dm_i2c_probe(bus, j, 0, &dev);
 #else
 		ret = i2c_probe(j);
 #endif
@@ -957,7 +983,7 @@
  */
 static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	u_char	chip;
+	uint	chip;
 	int alen;
 	uint	addr;
 	uint	length;
@@ -1010,7 +1036,7 @@
 	 */
 	while (1) {
 #ifdef CONFIG_DM_I2C
-		ret = i2c_read(dev, addr, bytes, length);
+		ret = dm_i2c_read(dev, addr, bytes, length);
 #else
 		ret = i2c_read(chip, addr, alen, bytes, length);
 #endif
@@ -1085,7 +1111,7 @@
 {
 	enum { unknown, EDO, SDRAM, DDR2 } type;
 
-	u_char	chip;
+	uint	chip;
 	u_char	data[128];
 	u_char	cksum;
 	int	j;
@@ -1563,7 +1589,7 @@
 #if defined(CONFIG_I2C_EDID)
 int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
-	u_char chip;
+	uint chip;
 	struct edid1_info edid;
 	int ret;
 #ifdef CONFIG_DM_I2C
@@ -1579,7 +1605,7 @@
 #ifdef CONFIG_DM_I2C
 	ret = i2c_get_cur_bus_chip(chip, &dev);
 	if (!ret)
-		ret = i2c_read(dev, 0, (uchar *)&edid, sizeof(edid));
+		ret = dm_i2c_read(dev, 0, (uchar *)&edid, sizeof(edid));
 #else
 	ret = i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid));
 #endif
@@ -1696,7 +1722,11 @@
 		}
 #endif
 		printf("Setting bus to %d\n", bus_no);
+#ifdef CONFIG_DM_I2C
+		ret = cmd_i2c_set_bus_num(bus_no);
+#else
 		ret = i2c_set_bus_num(bus_no);
+#endif
 		if (ret)
 			printf("Failure changing bus number (%d)\n", ret);
 	}
@@ -1726,7 +1756,7 @@
 #endif
 	if (argc == 1) {
 #ifdef CONFIG_DM_I2C
-		speed = i2c_get_bus_speed(bus);
+		speed = dm_i2c_get_bus_speed(bus);
 #else
 		speed = i2c_get_bus_speed();
 #endif
@@ -1736,7 +1766,7 @@
 		speed = simple_strtoul(argv[1], NULL, 10);
 		printf("Setting bus speed to %d Hz\n", speed);
 #ifdef CONFIG_DM_I2C
-		ret = i2c_set_bus_speed(bus, speed);
+		ret = dm_i2c_set_bus_speed(bus, speed);
 #else
 		ret = i2c_set_bus_speed(speed);
 #endif
@@ -1823,7 +1853,7 @@
 	U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""),
 	U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
 	U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
-	U_BOOT_CMD_MKENT(write, 5, 0, do_i2c_write, "", ""),
+	U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""),
 #ifdef CONFIG_DM_I2C
 	U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
 #endif
@@ -1890,7 +1920,8 @@
 	"i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
 	"i2c probe [address] - test for and show device(s) on the I2C bus\n"
 	"i2c read chip address[.0, .1, .2] length memaddress - read to memory\n"
-	"i2c write memaddress chip address[.0, .1, .2] length - write memory to i2c\n"
+	"i2c write memaddress chip address[.0, .1, .2] length [-s] - write memory\n"
+	"          to I2C; the -s option selects bulk write in a single transaction\n"
 #ifdef CONFIG_DM_I2C
 	"i2c flags chip [flags] - set or get chip flags\n"
 #endif
@@ -1902,7 +1933,7 @@
 #endif
 
 U_BOOT_CMD(
-	i2c, 6, 1, do_i2c,
+	i2c, 7, 1, do_i2c,
 	"I2C sub-system",
 	i2c_help_text
 );
diff --git a/common/cmd_load.c b/common/cmd_load.c
index f6e522c..d043e6d 100644
--- a/common/cmd_load.c
+++ b/common/cmd_load.c
@@ -222,7 +222,7 @@
 		}
 
 	    /* Check for the console hangup (if any different from serial) */
-	    if (gd->jt[XF_getc] != getc) {
+	    if (gd->jt->getc != getc) {
 		if (ctrlc()) {
 		    return (-1);
 		}
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 4e28c9d..1335e3d 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -85,8 +85,12 @@
 	printf("Tran Speed: %d\n", mmc->tran_speed);
 	printf("Rd Block Len: %d\n", mmc->read_bl_len);
 
-	printf("%s version %d.%d\n", IS_SD(mmc) ? "SD" : "MMC",
-			(mmc->version >> 8) & 0xf, mmc->version & 0xff);
+	printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
+			EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
+			EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
+	if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0)
+		printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version));
+	printf("\n");
 
 	printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
 	puts("Capacity: ");
diff --git a/common/cmd_part.c b/common/cmd_part.c
index 39e8666..c99f527 100644
--- a/common/cmd_part.c
+++ b/common/cmd_part.c
@@ -54,13 +54,31 @@
 	int ret;
 	block_dev_desc_t *desc;
 
-	if (argc != 2)
+	if (argc < 2 || argc > 3)
 		return CMD_RET_USAGE;
 
 	ret = get_device(argv[0], argv[1], &desc);
 	if (ret < 0)
 		return 1;
 
+	if (argc == 3) {
+		int p;
+		char str[512] = { 0, };
+	  disk_partition_t info;
+
+		for (p = 1; p < 128; p++) {
+			int r = get_partition_info(desc, p, &info);
+
+			if (r == 0) {
+				char t[5];
+				sprintf(t, "%s%d", str[0] ? " " : "", p);
+				strcat(str, t);
+			}
+		}
+		setenv(argv[2], str);
+		return 0;
+	}
+
 	print_part(desc);
 
 	return 0;
@@ -87,5 +105,7 @@
 	"part uuid <interface> <dev>:<part> <varname>\n"
 	"    - set environment variable to partition UUID\n"
 	"part list <interface> <dev>\n"
-	"    - print a device's partition table"
+	"    - print a device's partition table\n"
+	"part list <interface> <dev> <varname>\n"
+	"    - set environment variable to the list of partitions"
 );
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c
index cbc107e..a0a62eb 100644
--- a/common/cmd_scsi.c
+++ b/common/cmd_scsi.c
@@ -217,8 +217,10 @@
 		       (busdevfunc >> 8) & 0x7);
 	}
 #endif
+	bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci");
 	scsi_low_level_init(busdevfunc);
 	scsi_scan(1);
+	bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI);
 }
 #endif
 
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index ae2714d..64b9186 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -247,6 +247,8 @@
 		puts("OK\n");
 	}
 
+	flush_cache(dest, len);
+
 	setenv_hex("fileaddr", data);
 	setenv_hex("filesize", len);
 
diff --git a/common/console.c b/common/console.c
index fc1963b..3f25e76 100644
--- a/common/console.c
+++ b/common/console.c
@@ -125,13 +125,13 @@
 		 */
 		switch (file) {
 		case stdin:
-			gd->jt[XF_getc] = getc;
-			gd->jt[XF_tstc] = tstc;
+			gd->jt->getc = getc;
+			gd->jt->tstc = tstc;
 			break;
 		case stdout:
-			gd->jt[XF_putc] = putc;
-			gd->jt[XF_puts] = puts;
-			gd->jt[XF_printf] = printf;
+			gd->jt->putc  = putc;
+			gd->jt->puts  = puts;
+			gd->jt->printf = printf;
 			break;
 		}
 		break;
@@ -758,11 +758,11 @@
 #endif
 
 	/* set default handlers at first */
-	gd->jt[XF_getc] = serial_getc;
-	gd->jt[XF_tstc] = serial_tstc;
-	gd->jt[XF_putc] = serial_putc;
-	gd->jt[XF_puts] = serial_puts;
-	gd->jt[XF_printf] = serial_printf;
+	gd->jt->getc  = serial_getc;
+	gd->jt->tstc  = serial_tstc;
+	gd->jt->putc  = serial_putc;
+	gd->jt->puts  = serial_puts;
+	gd->jt->printf = serial_printf;
 
 	/* stdin stdout and stderr are in environment */
 	/* scan for it */
diff --git a/common/exports.c b/common/exports.c
index 88fcfc8..333107c 100644
--- a/common/exports.c
+++ b/common/exports.c
@@ -1,6 +1,7 @@
 #include <common.h>
 #include <exports.h>
 #include <spi.h>
+#include <i2c.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -13,33 +14,10 @@
 	return XF_VERSION;
 }
 
-/* Reuse _exports.h with a little trickery to avoid bitrot */
-#define EXPORT_FUNC(sym) gd->jt[XF_##sym] = (void *)sym;
-
-#if !defined(CONFIG_X86) && !defined(CONFIG_PPC)
-# define install_hdlr      dummy
-# define free_hdlr         dummy
-#else /* kludge for non-standard function naming */
-# define install_hdlr      irq_install_handler
-# define free_hdlr         irq_free_handler
-#endif
-#ifndef CONFIG_CMD_I2C
-# define i2c_write         dummy
-# define i2c_read          dummy
-#endif
-#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
-# define spi_init          dummy
-# define spi_setup_slave   dummy
-# define spi_free_slave    dummy
-#endif
-#ifndef CONFIG_CMD_SPI
-# define spi_claim_bus     dummy
-# define spi_release_bus   dummy
-# define spi_xfer          dummy
-#endif
+#define EXPORT_FUNC(f, a, x, ...)  gd->jt->x = f;
 
 void jumptable_init(void)
 {
-	gd->jt = malloc(XF_MAX * sizeof(void *));
+	gd->jt = malloc(sizeof(struct jt_funcs));
 #include <_exports.h>
 }
diff --git a/common/hash.c b/common/hash.c
index aceabc5..d154d02 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -10,17 +10,26 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#ifndef USE_HOSTCC
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
 #include <hw_sha.h>
-#include <hash.h>
-#include <u-boot/sha1.h>
-#include <u-boot/sha256.h>
 #include <asm/io.h>
 #include <asm/errno.h>
+#else
+#include "mkimage.h"
+#include <time.h>
+#include <image.h>
+#endif /* !USE_HOSTCC*/
 
-#ifdef CONFIG_CMD_SHA1SUM
+#include <hash.h>
+#include <u-boot/crc.h>
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
+#include <u-boot/md5.h>
+
+#ifdef CONFIG_SHA1
 static int hash_init_sha1(struct hash_algo *algo, void **ctxp)
 {
 	sha1_context *ctx = malloc(sizeof(sha1_context));
@@ -125,12 +134,7 @@
 		CHUNKSZ_SHA256,
 	},
 #endif
-	/*
-	 * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise
-	 * it bloats the code for boards which use SHA1 but not the 'hash'
-	 * or 'sha1sum' commands.
-	 */
-#ifdef CONFIG_CMD_SHA1SUM
+#ifdef CONFIG_SHA1
 	{
 		"sha1",
 		SHA1_SUM_LEN,
@@ -140,7 +144,6 @@
 		hash_update_sha1,
 		hash_finish_sha1,
 	},
-#define MULTI_HASH
 #endif
 #ifdef CONFIG_SHA256
 	{
@@ -152,7 +155,6 @@
 		hash_update_sha256,
 		hash_finish_sha256,
 	},
-#define MULTI_HASH
 #endif
 	{
 		"crc32",
@@ -165,6 +167,10 @@
 	},
 };
 
+#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM)
+#define MULTI_HASH
+#endif
+
 #if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH)
 #define MULTI_HASH
 #endif
@@ -176,6 +182,40 @@
 #define multi_hash()	0
 #endif
 
+int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
+		if (!strcmp(algo_name, hash_algo[i].name)) {
+			*algop = &hash_algo[i];
+			return 0;
+		}
+	}
+
+	debug("Unknown hash algorithm '%s'\n", algo_name);
+	return -EPROTONOSUPPORT;
+}
+
+int hash_progressive_lookup_algo(const char *algo_name,
+				 struct hash_algo **algop)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
+		if (!strcmp(algo_name, hash_algo[i].name)) {
+			if (hash_algo[i].hash_init) {
+				*algop = &hash_algo[i];
+				return 0;
+			}
+		}
+	}
+
+	debug("Unknown hash algorithm '%s'\n", algo_name);
+	return -EPROTONOSUPPORT;
+}
+
+#ifndef USE_HOSTCC
 /**
  * store_result: Store the resulting sum to an address or variable
  *
@@ -296,21 +336,6 @@
 	return 0;
 }
 
-int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
-		if (!strcmp(algo_name, hash_algo[i].name)) {
-			*algop = &hash_algo[i];
-			return 0;
-		}
-	}
-
-	debug("Unknown hash algorithm '%s'\n", algo_name);
-	return -EPROTONOSUPPORT;
-}
-
 void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output)
 {
 	int i;
@@ -424,3 +449,4 @@
 
 	return 0;
 }
+#endif
diff --git a/common/image-fdt.c b/common/image-fdt.c
index e3f06cd..d9e4728 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -190,7 +190,7 @@
 	*of_flat_tree = of_start;
 	*of_size = of_len;
 
-	set_working_fdt_addr(*of_flat_tree);
+	set_working_fdt_addr((ulong)*of_flat_tree);
 	return 0;
 
 error:
diff --git a/common/image-fit.c b/common/image-fit.c
index 1589ee3..778d2a1 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -112,6 +112,33 @@
 	      fdt_strerror(err));
 }
 
+/**
+ * fit_get_subimage_count - get component (sub-image) count
+ * @fit: pointer to the FIT format image header
+ * @images_noffset: offset of images node
+ *
+ * returns:
+ *     number of image components
+ */
+int fit_get_subimage_count(const void *fit, int images_noffset)
+{
+	int noffset;
+	int ndepth;
+	int count = 0;
+
+	/* Process its subnodes, print out component images details */
+	for (ndepth = 0, count = 0,
+		noffset = fdt_next_node(fit, images_noffset, &ndepth);
+	     (noffset >= 0) && (ndepth > 0);
+	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
+		if (ndepth == 1) {
+			count++;
+		}
+	}
+
+	return count;
+}
+
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
 /**
  * fit_print_contents - prints out the contents of the FIT format image
@@ -423,7 +450,8 @@
 		}
 	}
 }
-#endif
+
+#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) */
 
 /**
  * fit_get_desc - get node description property
@@ -982,9 +1010,7 @@
 	}
 
 	/* 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)) {
+	fdt_for_each_subnode(fit, noffset, image_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		/*
diff --git a/common/image-sig.c b/common/image-sig.c
index 8601eda..eda5e13 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -38,7 +38,7 @@
 #if IMAGE_ENABLE_SIGN
 		EVP_sha1,
 #endif
-		sha1_calculate,
+		hash_calculate,
 		padding_sha1_rsa2048,
 	},
 	{
@@ -48,7 +48,7 @@
 #if IMAGE_ENABLE_SIGN
 		EVP_sha256,
 #endif
-		sha256_calculate,
+		hash_calculate,
 		padding_sha256_rsa2048,
 	},
 	{
@@ -58,7 +58,7 @@
 #if IMAGE_ENABLE_SIGN
 		EVP_sha256,
 #endif
-		sha256_calculate,
+		hash_calculate,
 		padding_sha256_rsa4096,
 	}
 
@@ -212,9 +212,7 @@
 	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)) {
+	fdt_for_each_subnode(fit, noffset, image_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		if (!strncmp(name, FIT_SIG_NODENAME,
@@ -262,9 +260,7 @@
 		return 0;
 	}
 
-	for (noffset = fdt_first_subnode(sig_blob, sig_node);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+	fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 		const char *required;
 		int ret;
 
@@ -397,9 +393,7 @@
 	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)) {
+	fdt_for_each_subnode(fit, noffset, conf_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		if (!strncmp(name, FIT_SIG_NODENAME,
@@ -444,9 +438,7 @@
 		return 0;
 	}
 
-	for (noffset = fdt_first_subnode(sig_blob, sig_node);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+	fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 		const char *required;
 		int ret;
 
diff --git a/common/image.c b/common/image.c
index ad7a46d..a911aa9 100644
--- a/common/image.c
+++ b/common/image.c
@@ -756,7 +756,7 @@
  * genimg_get_image - get image from special storage (if necessary)
  * @img_addr: image start address
  *
- * genimg_get_image() checks if provided image start adddress is located
+ * genimg_get_image() checks if provided image start address is located
  * in a dataflash storage. If so, image is moved to a system RAM memory.
  *
  * returns:
diff --git a/common/lcd.c b/common/lcd.c
index 1195a54..f33942c 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -1,5 +1,5 @@
 /*
- * Common LCD routines for supported CPUs
+ * Common LCD routines
  *
  * (C) Copyright 2001-2002
  * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
@@ -7,62 +7,27 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-/************************************************************************/
-/* ** HEADER FILES							*/
-/************************************************************************/
-
 /* #define DEBUG */
-
 #include <config.h>
 #include <common.h>
 #include <command.h>
-#include <stdarg.h>
-#include <search.h>
 #include <env_callback.h>
 #include <linux/types.h>
 #include <stdio_dev.h>
-#if defined(CONFIG_POST)
-#include <post.h>
-#endif
 #include <lcd.h>
 #include <watchdog.h>
 #include <asm/unaligned.h>
 #include <splash.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
-#include <fdt_support.h>
+#include <video_font.h>
 
-#if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
-	defined(CONFIG_CPU_MONAHANS)
-#include <asm/byteorder.h>
-#endif
-
-#if defined(CONFIG_MPC823)
-#include <lcdvideo.h>
-#endif
-
-#if defined(CONFIG_ATMEL_LCD)
-#include <atmel_lcdc.h>
-#endif
-
-#if defined(CONFIG_LCD_DT_SIMPLEFB)
-#include <libfdt.h>
-#endif
-
-/************************************************************************/
-/* ** FONT DATA								*/
-/************************************************************************/
-#include <video_font.h>		/* Get font data, width and height	*/
-
-/************************************************************************/
-/* ** LOGO DATA								*/
-/************************************************************************/
 #ifdef CONFIG_LCD_LOGO
-# include <bmp_logo.h>		/* Get logo data, width and height	*/
-# include <bmp_logo_data.h>
-# if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16)
-#  error Default Color Map overlaps with Logo Color Map
-# endif
+#include <bmp_logo.h>
+#include <bmp_logo_data.h>
+#if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16)
+#error Default Color Map overlaps with Logo Color Map
+#endif
 #endif
 
 #ifdef CONFIG_SANDBOX
@@ -75,30 +40,23 @@
 
 #if (LCD_BPP != LCD_COLOR8) && (LCD_BPP != LCD_COLOR16) && \
 	(LCD_BPP != LCD_COLOR32)
-# error Unsupported LCD BPP.
+#error Unsupported LCD BPP.
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
 static int lcd_init(void *lcdbase);
-
-static void *lcd_logo(void);
-
+static void lcd_logo(void);
 static void lcd_setfgcolor(int color);
 static void lcd_setbgcolor(int color);
 
 static int lcd_color_fg;
 static int lcd_color_bg;
 int lcd_line_length;
-
 char lcd_is_enabled = 0;
-
 static void *lcd_base;			/* Start of framebuffer memory	*/
-
 static char lcd_flush_dcache;	/* 1 to flush dcache after each lcd update */
 
-/************************************************************************/
-
 /* Flush LCD activity to the caches */
 void lcd_sync(void)
 {
@@ -128,8 +86,6 @@
 	lcd_flush_dcache = (flush != 0);
 }
 
-/*----------------------------------------------------------------------*/
-
 static void lcd_stub_putc(struct stdio_dev *dev, const char c)
 {
 	lcd_putc(c);
@@ -140,9 +96,7 @@
 	lcd_puts(s);
 }
 
-/************************************************************************/
-/**  Small utility to check that you got the colours right		*/
-/************************************************************************/
+/* Small utility to check that you got the colours right */
 #ifdef LCD_TEST_PATTERN
 
 #define	N_BLK_VERT	2
@@ -176,10 +130,6 @@
 }
 #endif /* LCD_TEST_PATTERN */
 
-
-/************************************************************************/
-/* ** GENERIC Initialization Routines					*/
-/************************************************************************/
 /*
  * With most lcd drivers the line length is set up
  * by calculating it from panel_info parameters. Some
@@ -199,7 +149,7 @@
 
 	lcd_base = map_sysmem(gd->fb_base, 0);
 
-	lcd_init(lcd_base);		/* LCD initialization */
+	lcd_init(lcd_base);
 
 	/* Device initialization */
 	memset(&lcddev, 0, sizeof(lcddev));
@@ -215,11 +165,13 @@
 	return (rc == 0) ? 1 : rc;
 }
 
-/*----------------------------------------------------------------------*/
 void lcd_clear(void)
 {
 	short console_rows, console_cols;
 	int bg_color;
+	char *s;
+	ulong addr;
+	static int do_splash = 1;
 #if LCD_BPP == LCD_COLOR8
 	/* Setting the palette */
 	lcd_setcolreg(CONSOLE_COLOR_BLACK, 0, 0, 0);
@@ -269,7 +221,23 @@
 #endif
 	console_cols = panel_info.vl_col / VIDEO_FONT_WIDTH;
 	lcd_init_console(lcd_base, console_rows, console_cols);
-	lcd_init_console(lcd_logo(), console_rows, console_cols);
+	if (do_splash) {
+		s = getenv("splashimage");
+		if (s) {
+			do_splash = 0;
+			addr = simple_strtoul(s, NULL, 16);
+			if (lcd_splash(addr) == 0) {
+				lcd_sync();
+				return;
+			}
+		}
+	}
+
+	lcd_logo();
+#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
+	addr = (ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length;
+	lcd_init_console((void *)addr, console_rows, console_cols);
+#endif
 	lcd_sync();
 }
 
@@ -279,20 +247,11 @@
 	lcd_clear();
 	return 0;
 }
-
-U_BOOT_CMD(
-	cls,	1,	1,	do_lcd_clear,
-	"clear screen",
-	""
-);
-
-/*----------------------------------------------------------------------*/
+U_BOOT_CMD(cls,	1, 1, do_lcd_clear, "clear screen", "");
 
 static int lcd_init(void *lcdbase)
 {
-	/* Initialize the lcd controller */
 	debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
-
 	lcd_ctrl_init(lcdbase);
 
 	/*
@@ -322,10 +281,6 @@
 	return 0;
 }
 
-
-/************************************************************************/
-/* ** ROM capable initialization part - needed to reserve FB memory	*/
-/************************************************************************/
 /*
  * This is called early in the system initialization to grab memory
  * for the LCD controller.
@@ -356,8 +311,6 @@
 	return addr;
 }
 
-/*----------------------------------------------------------------------*/
-
 static void lcd_setfgcolor(int color)
 {
 	lcd_color_fg = color;
@@ -368,8 +321,6 @@
 	return lcd_color_fg;
 }
 
-/*----------------------------------------------------------------------*/
-
 static void lcd_setbgcolor(int color)
 {
 	lcd_color_bg = color;
@@ -380,91 +331,30 @@
 	return lcd_color_bg;
 }
 
-/************************************************************************/
-/* ** Chipset depending Bitmap / Logo stuff...                          */
-/************************************************************************/
-static inline ushort *configuration_get_cmap(void)
+#ifdef CONFIG_LCD_LOGO
+__weak void lcd_logo_set_cmap(void)
 {
-#if defined CONFIG_CPU_PXA
-	struct pxafb_info *fbi = &panel_info.pxa;
-	return (ushort *)fbi->palette;
-#elif defined(CONFIG_MPC823)
-	immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
-	cpm8xx_t *cp = &(immr->im_cpm);
-	return (ushort *)&(cp->lcd_cmap[255 * sizeof(ushort)]);
-#elif defined(CONFIG_ATMEL_LCD)
-	return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));
-#elif !defined(CONFIG_ATMEL_HLCD) && !defined(CONFIG_EXYNOS_FB)
-	return panel_info.cmap;
-#elif defined(CONFIG_LCD_LOGO)
-	return bmp_logo_palette;
-#else
-	return NULL;
-#endif
+	int i;
+	ushort *cmap = configuration_get_cmap();
+
+	for (i = 0; i < ARRAY_SIZE(bmp_logo_palette); ++i)
+		*cmap++ = bmp_logo_palette[i];
 }
 
-#ifdef CONFIG_LCD_LOGO
-void bitmap_plot(int x, int y)
+void lcd_logo_plot(int x, int y)
 {
-#ifdef CONFIG_ATMEL_LCD
-	uint *cmap = (uint *)bmp_logo_palette;
-#else
-	ushort *cmap = (ushort *)bmp_logo_palette;
-#endif
 	ushort i, j;
-	uchar *bmap;
-	uchar *fb;
-	ushort *fb16;
-#if defined(CONFIG_MPC823)
-	immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
-	cpm8xx_t *cp = &(immr->im_cpm);
-#endif
+	uchar *bmap = &bmp_logo_bitmap[0];
 	unsigned bpix = NBITS(panel_info.vl_bpix);
+	uchar *fb = (uchar *)(lcd_base + y * lcd_line_length + x * bpix / 8);
+	ushort *fb16;
 
-	debug("Logo: width %d  height %d  colors %d  cmap %d\n",
-		BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
-		ARRAY_SIZE(bmp_logo_palette));
-
-	bmap = &bmp_logo_bitmap[0];
-	fb   = (uchar *)(lcd_base + y * lcd_line_length + x * bpix / 8);
+	debug("Logo: width %d  height %d  colors %d\n",
+	      BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS);
 
 	if (bpix < 12) {
-		/* Leave room for default color map
-		 * default case: generic system with no cmap (most likely 16bpp)
-		 * cmap was set to the source palette, so no change is done.
-		 * This avoids even more ifdefs in the next stanza
-		 */
-#if defined(CONFIG_MPC823)
-		cmap = (ushort *) &(cp->lcd_cmap[BMP_LOGO_OFFSET * sizeof(ushort)]);
-#elif defined(CONFIG_ATMEL_LCD)
-		cmap = (uint *)configuration_get_cmap();
-#else
-		cmap = configuration_get_cmap();
-#endif
-
 		WATCHDOG_RESET();
-
-		/* Set color map */
-		for (i = 0; i < ARRAY_SIZE(bmp_logo_palette); ++i) {
-			ushort colreg = bmp_logo_palette[i];
-#ifdef CONFIG_ATMEL_LCD
-			uint lut_entry;
-#ifdef CONFIG_ATMEL_LCD_BGR555
-			lut_entry = ((colreg & 0x000F) << 11) |
-					((colreg & 0x00F0) <<  2) |
-					((colreg & 0x0F00) >>  7);
-#else /* CONFIG_ATMEL_LCD_RGB565 */
-			lut_entry = ((colreg & 0x000F) << 1) |
-					((colreg & 0x00F0) << 3) |
-					((colreg & 0x0F00) << 4);
-#endif
-			*(cmap + BMP_LOGO_OFFSET) = lut_entry;
-			cmap++;
-#else /* !CONFIG_ATMEL_LCD */
-			*cmap++ = colreg;
-#endif /* CONFIG_ATMEL_LCD */
-		}
-
+		lcd_logo_set_cmap();
 		WATCHDOG_RESET();
 
 		for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
@@ -493,16 +383,10 @@
 	lcd_sync();
 }
 #else
-static inline void bitmap_plot(int x, int y) {}
+static inline void lcd_logo_plot(int x, int y) {}
 #endif /* CONFIG_LCD_LOGO */
 
-/*----------------------------------------------------------------------*/
 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
-/*
- * Display the BMP file located at address bmp_image.
- * Only uncompressed.
- */
-
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
 #define BMP_ALIGN_CENTER	0x7FFF
 
@@ -523,9 +407,7 @@
 }
 #endif
 
-
 #ifdef CONFIG_LCD_BMP_RLE8
-
 #define BMP_RLE8_ESCAPE		0
 #define BMP_RLE8_EOL		0
 #define BMP_RLE8_EOBMP		1
@@ -654,32 +536,40 @@
 }
 #endif
 
-#if defined(CONFIG_MPC823)
-#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
-#else
-#define FB_PUT_BYTE(fb, from) *(fb)++ = *(from)++
-#endif
+__weak void fb_put_byte(uchar **fb, uchar **from)
+{
+	*(*fb)++ = *(*from)++;
+}
 
 #if defined(CONFIG_BMP_16BPP)
-#if defined(CONFIG_ATMEL_LCD_BGR555)
-static inline void fb_put_word(uchar **fb, uchar **from)
-{
-	*(*fb)++ = (((*from)[0] & 0x1f) << 2) | ((*from)[1] & 0x03);
-	*(*fb)++ = ((*from)[0] & 0xe0) | (((*from)[1] & 0x7c) >> 2);
-	*from += 2;
-}
-#else
-static inline void fb_put_word(uchar **fb, uchar **from)
+__weak void fb_put_word(uchar **fb, uchar **from)
 {
 	*(*fb)++ = *(*from)++;
 	*(*fb)++ = *(*from)++;
 }
-#endif
 #endif /* CONFIG_BMP_16BPP */
 
+__weak void lcd_set_cmap(bmp_image_t *bmp, unsigned colors)
+{
+	int i;
+	bmp_color_table_entry_t cte;
+	ushort *cmap = configuration_get_cmap();
+
+	for (i = 0; i < colors; ++i) {
+		cte = bmp->color_table[i];
+		*cmap = (((cte.red)   << 8) & 0xf800) |
+			(((cte.green) << 3) & 0x07e0) |
+			(((cte.blue)  >> 3) & 0x001f);
+#if defined(CONFIG_MPC823)
+		cmap--;
+#else
+		cmap++;
+#endif
+	}
+}
+
 int lcd_display_bitmap(ulong bmp_image, int x, int y)
 {
-	ushort *cmap = NULL;
 	ushort *cmap_base = NULL;
 	ushort i, j;
 	uchar *fb;
@@ -727,29 +617,8 @@
 	debug("Display-bmp: %d x %d  with %d colors\n",
 		(int)width, (int)height, (int)colors);
 
-	if (bmp_bpix == 8) {
-		cmap = configuration_get_cmap();
-		cmap_base = cmap;
-
-		/* Set color map */
-		for (i = 0; i < colors; ++i) {
-			bmp_color_table_entry_t cte = bmp->color_table[i];
-#if !defined(CONFIG_ATMEL_LCD)
-			ushort colreg =
-				( ((cte.red)   << 8) & 0xf800) |
-				( ((cte.green) << 3) & 0x07e0) |
-				( ((cte.blue)  >> 3) & 0x001f) ;
-			*cmap = colreg;
-#if defined(CONFIG_MPC823)
-			cmap--;
-#else
-			cmap++;
-#endif
-#else /* CONFIG_ATMEL_LCD */
-			lcd_setcolreg(i, cte.red, cte.green, cte.blue);
-#endif
-		}
-	}
+	if (bmp_bpix == 8)
+		lcd_set_cmap(bmp, colors);
 
 	padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);
 
@@ -768,8 +637,9 @@
 		(y + height - 1) * lcd_line_length + x * bpix / 8);
 
 	switch (bmp_bpix) {
-	case 1: /* pass through */
+	case 1:
 	case 8: {
+		cmap_base = configuration_get_cmap();
 #ifdef CONFIG_LCD_BMP_RLE8
 		u32 compression = get_unaligned_le32(&bmp->header.compression);
 		if (compression == BMP_BI_RLE8) {
@@ -792,7 +662,7 @@
 			WATCHDOG_RESET();
 			for (j = 0; j < width; j++) {
 				if (bpix != 16) {
-					FB_PUT_BYTE(fb, bmap);
+					fb_put_byte(&fb, &bmap);
 				} else {
 					*(uint16_t *)fb = cmap_base[*(bmap++)];
 					fb += sizeof(uint16_t) / sizeof(*fb);
@@ -850,42 +720,15 @@
 }
 #endif
 
-static void *lcd_logo(void)
+static void lcd_logo(void)
 {
-#ifdef CONFIG_SPLASH_SCREEN
-	char *s;
-	ulong addr;
-	static int do_splash = 1;
-
-	if (do_splash && (s = getenv("splashimage")) != NULL) {
-		int x = 0, y = 0;
-		do_splash = 0;
-
-		if (splash_screen_prepare())
-			return (void *)lcd_base;
-
-		addr = simple_strtoul (s, NULL, 16);
-
-		splash_get_pos(&x, &y);
-
-		if (bmp_display(addr, x, y) == 0)
-			return (void *)lcd_base;
-	}
-#endif /* CONFIG_SPLASH_SCREEN */
-
-	bitmap_plot(0, 0);
+	lcd_logo_plot(0, 0);
 
 #ifdef CONFIG_LCD_INFO
 	lcd_set_col(LCD_INFO_X / VIDEO_FONT_WIDTH);
 	lcd_set_row(LCD_INFO_Y / VIDEO_FONT_HEIGHT);
 	lcd_show_board_info();
 #endif /* CONFIG_LCD_INFO */
-
-#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
-	return (void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length);
-#else
-	return (void *)lcd_base;
-#endif /* CONFIG_LCD_LOGO && !defined(CONFIG_LCD_INFO_BELOW_LOGO) */
 }
 
 #ifdef CONFIG_SPLASHIMAGE_GUARD
@@ -921,48 +764,3 @@
 {
 	return panel_info.vl_row;
 }
-
-#if defined(CONFIG_LCD_DT_SIMPLEFB)
-static int lcd_dt_simplefb_configure_node(void *blob, int off)
-{
-#if LCD_BPP == LCD_COLOR16
-	return fdt_setup_simplefb_node(blob, off, gd->fb_base,
-				       panel_info.vl_col, panel_info.vl_row,
-				       panel_info.vl_col * 2, "r5g6b5");
-#else
-	return -1;
-#endif
-}
-
-int lcd_dt_simplefb_add_node(void *blob)
-{
-	static const char compat[] = "simple-framebuffer";
-	static const char disabled[] = "disabled";
-	int off, ret;
-
-	off = fdt_add_subnode(blob, 0, "framebuffer");
-	if (off < 0)
-		return -1;
-
-	ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled));
-	if (ret < 0)
-		return -1;
-
-	ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat));
-	if (ret < 0)
-		return -1;
-
-	return lcd_dt_simplefb_configure_node(blob, off);
-}
-
-int lcd_dt_simplefb_enable_existing_node(void *blob)
-{
-	int off;
-
-	off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer");
-	if (off < 0)
-		return -1;
-
-	return lcd_dt_simplefb_configure_node(blob, off);
-}
-#endif
diff --git a/common/lcd_simplefb.c b/common/lcd_simplefb.c
new file mode 100644
index 0000000..8db2add
--- /dev/null
+++ b/common/lcd_simplefb.c
@@ -0,0 +1,59 @@
+/*
+ * Simplefb device tree support
+ *
+ * (C) Copyright 2015
+ * Stephen Warren <swarren@wwwdotorg.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <lcd.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int lcd_dt_simplefb_configure_node(void *blob, int off)
+{
+#if LCD_BPP == LCD_COLOR16
+	int vl_col = lcd_get_pixel_width();
+	int vl_row = lcd_get_pixel_height();
+	return fdt_setup_simplefb_node(blob, off, gd->fb_base, vl_col, vl_row,
+				       vl_col * 2, "r5g6b5");
+#else
+	return -1;
+#endif
+}
+
+int lcd_dt_simplefb_add_node(void *blob)
+{
+	static const char compat[] = "simple-framebuffer";
+	static const char disabled[] = "disabled";
+	int off, ret;
+
+	off = fdt_add_subnode(blob, 0, "framebuffer");
+	if (off < 0)
+		return -1;
+
+	ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled));
+	if (ret < 0)
+		return -1;
+
+	ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat));
+	if (ret < 0)
+		return -1;
+
+	return lcd_dt_simplefb_configure_node(blob, off);
+}
+
+int lcd_dt_simplefb_enable_existing_node(void *blob)
+{
+	int off;
+
+	off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer");
+	if (off < 0)
+		return -1;
+
+	return lcd_dt_simplefb_configure_node(blob, off);
+}
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index afdacff..64ae036 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -19,7 +19,7 @@
 
 	new_ptr = gd->malloc_ptr + bytes;
 	if (new_ptr > gd->malloc_limit)
-		panic("Out of pre-reloc memory");
+		return NULL;
 	ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
 	gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
 	return ptr;
diff --git a/common/spl/spl.c b/common/spl/spl.c
index daaeb50..ded0f30 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -229,6 +229,11 @@
 		spl_sata_load_image();
 		break;
 #endif
+#ifdef CONFIG_SPL_BOARD_LOAD_IMAGE
+	case BOOT_DEVICE_BOARD:
+		spl_board_load_image();
+		break;
+#endif
 	default:
 #if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		puts("SPL: Unsupported Boot Device!\n");
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c
index 2c0e8e0..c2fee01 100644
--- a/common/spl/spl_nor.c
+++ b/common/spl/spl_nor.c
@@ -17,7 +17,7 @@
 
 #ifdef CONFIG_SPL_OS_BOOT
 	if (!spl_start_uboot()) {
-		struct image_header *header;
+		const struct image_header *header;
 
 		/*
 		 * Load Linux from its location in NOR flash to its defined
diff --git a/common/splash.c b/common/splash.c
index 144fb10..561d35b 100644
--- a/common/splash.c
+++ b/common/splash.c
@@ -22,6 +22,7 @@
 
 #include <common.h>
 #include <splash.h>
+#include <lcd.h>
 
 __weak int splash_screen_prepare(void)
 {
@@ -50,3 +51,18 @@
 	}
 }
 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
+
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
+int lcd_splash(ulong addr)
+{
+	int x = 0, y = 0, ret;
+
+	ret = splash_screen_prepare();
+	if (ret)
+		return ret;
+
+	splash_get_pos(&x, &y);
+
+	return bmp_display(addr, x, y);
+}
+#endif
diff --git a/common/splash_source.c b/common/splash_source.c
new file mode 100644
index 0000000..d1bb5a4
--- /dev/null
+++ b/common/splash_source.c
@@ -0,0 +1,176 @@
+/*
+ * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <errno.h>
+#include <splash.h>
+#include <spi_flash.h>
+#include <spi.h>
+#include <bmp_layout.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SPI_FLASH
+static struct spi_flash *sf;
+static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+	if (!sf) {
+		sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+				     CONFIG_SF_DEFAULT_CS,
+				     CONFIG_SF_DEFAULT_SPEED,
+				     CONFIG_SF_DEFAULT_MODE);
+		if (!sf)
+			return -ENODEV;
+	}
+
+	return spi_flash_read(sf, offset, read_size, (void *)bmp_load_addr);
+}
+#else
+static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+	debug("%s: sf support not available\n", __func__);
+	return -ENOSYS;
+}
+#endif
+
+#ifdef CONFIG_CMD_NAND
+static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+	return nand_read_skip_bad(&nand_info[nand_curr_device], offset,
+				  &read_size, NULL,
+				  nand_info[nand_curr_device].size,
+				  (u_char *)bmp_load_addr);
+}
+#else
+static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+	debug("%s: nand support not available\n", __func__);
+	return -ENOSYS;
+}
+#endif
+
+static int splash_storage_read(struct splash_location *location,
+			       u32 bmp_load_addr, size_t read_size)
+{
+	u32 offset;
+
+	if (!location)
+		return -EINVAL;
+
+	offset = location->offset;
+	switch (location->storage) {
+	case SPLASH_STORAGE_NAND:
+		return splash_nand_read(bmp_load_addr, offset, read_size);
+	case SPLASH_STORAGE_SF:
+		return splash_sf_read(bmp_load_addr, offset, read_size);
+	default:
+		printf("Unknown splash location\n");
+	}
+
+	return -EINVAL;
+}
+
+static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr)
+{
+	struct bmp_header *bmp_hdr;
+	int res;
+	size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
+
+	if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
+		goto splash_address_too_high;
+
+	res = splash_storage_read(location, bmp_load_addr, bmp_header_size);
+	if (res < 0)
+		return res;
+
+	bmp_hdr = (struct bmp_header *)bmp_load_addr;
+	bmp_size = le32_to_cpu(bmp_hdr->file_size);
+
+	if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
+		goto splash_address_too_high;
+
+	return splash_storage_read(location, bmp_load_addr, bmp_size);
+
+splash_address_too_high:
+	printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
+
+	return -EFAULT;
+}
+
+/**
+ * select_splash_location - return the splash location based on board support
+ *			    and env variable "splashsource".
+ *
+ * @locations:		An array of supported splash locations.
+ * @size:		Size of splash_locations array.
+ *
+ * @return: If a null set of splash locations is given, or
+ *	    splashsource env variable is set to unsupported value
+ *			return NULL.
+ *	    If splashsource env variable is not defined
+ *			return the first entry in splash_locations as default.
+ *	    If splashsource env variable contains a supported value
+ *			return the location selected by splashsource.
+ */
+static struct splash_location *select_splash_location(
+			    struct splash_location *locations, uint size)
+{
+	int i;
+	char *env_splashsource;
+
+	if (!locations || size == 0)
+		return NULL;
+
+	env_splashsource = getenv("splashsource");
+	if (env_splashsource == NULL)
+		return &locations[0];
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(locations[i].name, env_splashsource))
+			return &locations[i];
+	}
+
+	printf("splashsource env variable set to unsupported value\n");
+	return NULL;
+}
+
+/**
+ * splash_source_load - load splash image from a supported location.
+ *
+ * Select a splash image location based on the value of splashsource environment
+ * variable and the board supported splash source locations, and load a
+ * splashimage to the address pointed to by splashimage environment variable.
+ *
+ * @locations:		An array of supported splash locations.
+ * @size:		Size of splash_locations array.
+ *
+ * @return: 0 on success, negative value on failure.
+ */
+int splash_source_load(struct splash_location *locations, uint size)
+{
+	struct splash_location *splash_location;
+	char *env_splashimage_value;
+	u32 bmp_load_addr;
+
+	env_splashimage_value = getenv("splashimage");
+	if (env_splashimage_value == NULL)
+		return -ENOENT;
+
+	bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
+	if (bmp_load_addr == 0) {
+		printf("Error: bad splashimage address specified\n");
+		return -EFAULT;
+	}
+
+	splash_location = select_splash_location(locations, size);
+	if (!splash_location)
+		return -EINVAL;
+
+	return splash_load_raw(splash_location, bmp_load_addr);
+}
diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig
index 94fafa6..b5f0a0f 100644
--- a/configs/A10s-OLinuXino-M_defconfig
+++ b/configs/A10s-OLinuXino-M_defconfig
@@ -8,4 +8,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_A10S_OLINUXINO_M=y
++S:CONFIG_DRAM_CLK=432
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig
index 1a99418..a04f2b3 100644
--- a/configs/A13-OLinuXinoM_defconfig
+++ b/configs/A13-OLinuXinoM_defconfig
@@ -4,6 +4,7 @@
 CONFIG_USB1_VBUS_PIN="PG11"
 CONFIG_VIDEO_HDMI=n
 CONFIG_VIDEO_VGA_VIA_LCD=y
+CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH=y
 # For use with the Olimex 7" LCD module, adjust timings for other displays
 # Set video-mode=sunxi:800x600-24@60,monitor=lcd in the env. to enable
 CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0"
@@ -12,4 +13,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_A13_OLINUXINOM=y
++S:CONFIG_DRAM_CLK=408
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=0
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index 7df6951..806d5b7 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -4,6 +4,7 @@
 CONFIG_USB1_VBUS_PIN="PG11"
 CONFIG_VIDEO_HDMI=n
 CONFIG_VIDEO_VGA_VIA_LCD=y
+CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH=y
 # For use with the Olimex 7" LCD module, adjust timings for other displays
 # Set video-mode=sunxi:800x600-24@60,monitor=lcd in the env. to enable
 CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0"
@@ -12,4 +13,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_A13_OLINUXINO=y
++S:CONFIG_DRAM_CLK=408
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=0
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 17fd19d..ff94e77 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -4,7 +4,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_A20_OLINUXINO_L2=y
 +S:CONFIG_DRAM_CLK=480
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index c8243a4..5442f64 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -4,7 +4,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_A20_OLINUXINO_L=y
 +S:CONFIG_DRAM_CLK=480
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index ac94c79..97a21ee 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -8,7 +8,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_A20_OLINUXINO_M=y
 +S:CONFIG_DRAM_CLK=384
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Ampe_A76_defconfig b/configs/Ampe_A76_defconfig
new file mode 100644
index 0000000..f8ceb6c
--- /dev/null
+++ b/configs/Ampe_A76_defconfig
@@ -0,0 +1,16 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,AXP209_POWER"
+CONFIG_FDTFILE="sun5i-a13-ampe-a76.dtb"
+CONFIG_USB_MUSB_SUNXI=y
+CONFIG_USB0_VBUS_PIN="PG12"
+CONFIG_USB0_VBUS_DET="PG01"
+CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:45,ri:82,up:22,lo:22,hs:1,vs:1,sync:3,vmode:0"
+CONFIG_VIDEO_LCD_POWER="AXP0-0"
+CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
+CONFIG_VIDEO_LCD_BL_PWM="PB2"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN5I=y
++S:CONFIG_DRAM_CLK=432
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Auxtek-T004_defconfig b/configs/Auxtek-T004_defconfig
index 7fe9059..03ec3db 100644
--- a/configs/Auxtek-T004_defconfig
+++ b/configs/Auxtek-T004_defconfig
@@ -5,4 +5,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_AUXTEK_T004=y
++S:CONFIG_DRAM_CLK=432
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index d94e08e..5aba938 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -1,10 +1,10 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,RGMII,MACPWR=SUNXI_GPH(23),AHCI,USB_EHCI"
 CONFIG_FDTFILE="sun7i-a20-bananapi.dtb"
+CONFIG_GMAC_TX_DELAY=3
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_BANANAPI=y
 +S:CONFIG_DRAM_CLK=432
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 02e4f3e..e501b5c 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -3,10 +3,10 @@
 CONFIG_FDTFILE="sun7i-a20-bananapro.dtb"
 CONFIG_USB1_VBUS_PIN="PH0"
 CONFIG_USB2_VBUS_PIN="PH1"
+CONFIG_GMAC_TX_DELAY=3
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_BANANAPRO=y
 +S:CONFIG_DRAM_CLK=432
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Chuwi_V7_CW0825_defconfig b/configs/Chuwi_V7_CW0825_defconfig
index 680b631..1ef23e4 100644
--- a/configs/Chuwi_V7_CW0825_defconfig
+++ b/configs/Chuwi_V7_CW0825_defconfig
@@ -3,6 +3,7 @@
 CONFIG_FDTFILE="sun4i-a10-chuwi-v7-cw0825.dtb"
 CONFIG_USB_MUSB_SUNXI=y
 CONFIG_USB0_VBUS_PIN="PB9"
+CONFIG_USB0_VBUS_DET="PH5"
 CONFIG_VIDEO_LCD_MODE="x:1024,y:768,depth:24,pclk_khz:51000,le:19,ri:300,up:6,lo:31,hs:1,vs:1,sync:3,vmode:0"
 CONFIG_VIDEO_LCD_POWER="PH8"
 CONFIG_VIDEO_LCD_BL_EN="PH7"
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index ef5b43a..7704a0e 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -4,7 +4,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_CUBIEBOARD2=y
 +S:CONFIG_DRAM_CLK=480
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index f51c491..b64f84f 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -5,7 +5,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_CUBIETRUCK=y
 +S:CONFIG_DRAM_CLK=432
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Hyundai_A7HD_defconfig b/configs/Hyundai_A7HD_defconfig
index 60eb03e..6b784e2 100644
--- a/configs/Hyundai_A7HD_defconfig
+++ b/configs/Hyundai_A7HD_defconfig
@@ -6,7 +6,9 @@
 CONFIG_FDTFILE="sun4i-a10-hyundai-a7hd.dtb"
 CONFIG_USB_MUSB_SUNXI=y
 CONFIG_USB0_VBUS_PIN="PB09"
-CONFIG_USB2_VBUS_PIN=""
+CONFIG_USB0_VBUS_DET="PH5"
+CONFIG_USB1_VBUS_PIN=""
+CONFIG_USB2_VBUS_PIN="PH6"
 CONFIG_VIDEO_LCD_MODE="x:1024,y:600,depth:18,pclk_khz:51000,le:45,ri:274,up:22,lo:12,hs:1,vs:1,sync:3,vmode:0"
 CONFIG_VIDEO_LCD_DCLK_PHASE=1
 CONFIG_VIDEO_LCD_POWER="PH2"
diff --git a/configs/Inet_86VS_defconfig b/configs/Inet_86VS_defconfig
new file mode 100644
index 0000000..50c073a
--- /dev/null
+++ b/configs/Inet_86VS_defconfig
@@ -0,0 +1,16 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER"
+CONFIG_FDTFILE="sun5i-a13-inet-86vs.dtb"
+CONFIG_USB_MUSB_SUNXI=y
+CONFIG_USB0_VBUS_PIN="PG12"
+CONFIG_USB0_VBUS_DET="PG1"
+CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:45,ri:209,up:22,lo:22,hs:1,vs:1,sync:3,vmode:0"
+CONFIG_VIDEO_LCD_POWER="AXP0-0"
+CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
+CONFIG_VIDEO_LCD_BL_PWM="PB2"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN5I=y
++S:CONFIG_DRAM_CLK=408
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
index c894948..4786202 100644
--- a/configs/Ippo_q8h_v5_defconfig
+++ b/configs/Ippo_q8h_v5_defconfig
@@ -11,7 +11,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN8I=y
-+S:CONFIG_TARGET_IPPO_Q8H_V5=y
 +S:CONFIG_DRAM_CLK=480
 # zq = 0xf777
 +S:CONFIG_DRAM_ZQ=63351
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
new file mode 100644
index 0000000..4baba14
--- /dev/null
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -0,0 +1,11 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(2),USB_EHCI"
+CONFIG_FDTFILE="sun7i-a20-pcduino3-nano.dtb"
+CONFIG_GMAC_TX_DELAY=3
+CONFIG_USB1_VBUS_PIN="PH11"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN7I=y
++S:CONFIG_DRAM_CLK=408
++S:CONFIG_DRAM_ZQ=122
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 64e01c8..45d88f3 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -4,7 +4,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_PCDUINO3=y
 +S:CONFIG_DRAM_CLK=480
 +S:CONFIG_DRAM_ZQ=122
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Linksprite_pcDuino3_fdt_defconfig b/configs/Linksprite_pcDuino3_fdt_defconfig
index 49718c7..1e749cd 100644
--- a/configs/Linksprite_pcDuino3_fdt_defconfig
+++ b/configs/Linksprite_pcDuino3_fdt_defconfig
@@ -2,13 +2,16 @@
 CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPH(2),USB_EHCI"
 CONFIG_FDTFILE="sun7i-a20-pcduino3.dtb"
 CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
 CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-pcduino3"
 CONFIG_OF_CONTROL=y
 CONFIG_OF_SEPARATE=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_PCDUINO3=y
 +S:CONFIG_DRAM_CLK=480
 +S:CONFIG_DRAM_ZQ=122
 +S:CONFIG_DRAM_EMR1=4
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/MSI_Primo73_defconfig b/configs/MSI_Primo73_defconfig
index 6628184..c6fb7e6 100644
--- a/configs/MSI_Primo73_defconfig
+++ b/configs/MSI_Primo73_defconfig
@@ -1,3 +1,11 @@
+# The MSI Primo73 is an A20 based tablet, with 1G RAM, 16G NAND,
+# 1024x600 TN LCD display, mono speaker, 0.3 MP front camera, 2.0 MP
+# rear camera, 3000 mAh battery, gt911 touchscreen, mma8452 accelerometer
+# and rtl8188etv usb wifi. Has "power", "volume+" and "volume-" buttons
+# (both volume buttons are also connected to the UBOOT_SEL pin). The
+# external connectors are represented by MicroSD slot, MiniHDMI, MicroUSB
+# OTG and 3.5mm headphone jack. More details are available at
+#    http://linux-sunxi.org/MSI_Primo73
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER"
 CONFIG_FDTFILE="sun7i-a20-primo73.dtb"
@@ -10,7 +18,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_MSI_PRIMO73=y
 +S:CONFIG_DRAM_CLK=384
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig
index 7f1710a..723a72a 100644
--- a/configs/Mele_M3_defconfig
+++ b/configs/Mele_M3_defconfig
@@ -7,7 +7,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_MELE_M3=y
 +S:CONFIG_DRAM_CLK=384
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/TZX-Q8-713B7_defconfig b/configs/TZX-Q8-713B7_defconfig
new file mode 100644
index 0000000..c22286a
--- /dev/null
+++ b/configs/TZX-Q8-713B7_defconfig
@@ -0,0 +1,16 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,AXP209_POWER"
+CONFIG_FDTFILE="sun5i-a13-tzx-q8-713b7.dtb"
+CONFIG_USB_MUSB_SUNXI=y
+CONFIG_USB0_VBUS_PIN="PG12"
+CONFIG_USB0_VBUS_DET="PG1"
+CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:40,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0"
+CONFIG_VIDEO_LCD_POWER="AXP0-0"
+CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
+CONFIG_VIDEO_LCD_BL_PWM="PB2"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN5I=y
++S:CONFIG_DRAM_CLK=408
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/UTOO_P66_defconfig b/configs/UTOO_P66_defconfig
new file mode 100644
index 0000000..919a467
--- /dev/null
+++ b/configs/UTOO_P66_defconfig
@@ -0,0 +1,21 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER"
+CONFIG_FDTFILE="sun5i-a13-utoo-p66.dtb"
+CONFIG_USB_MUSB_SUNXI=y
+CONFIG_USB0_VBUS_PIN="PB04"
+CONFIG_USB0_VBUS_DET="PG01"
+CONFIG_VIDEO_LCD_MODE="x:480,y:800,depth:18,pclk_khz:25000,le:2,ri:93,up:2,lo:93,hs:1,vs:1,sync:3,vmode:0"
+CONFIG_VIDEO_LCD_DCLK_PHASE=0
+CONFIG_VIDEO_LCD_POWER="PG4"
+CONFIG_VIDEO_LCD_RESET="PG11"
+CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
+CONFIG_VIDEO_LCD_BL_PWM="PB2"
+CONFIG_VIDEO_LCD_TL059WV5C0=y
++S:CONFIG_MMC_SUNXI_SLOT_EXTRA=2
++S:CONFIG_MMC0_CD_PIN="PG0"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN5I=y
++S:CONFIG_DRAM_CLK=432
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=0
diff --git a/configs/afeb9260_defconfig b/configs/afeb9260_defconfig
index 2616d2d..694d24d 100644
--- a/configs/afeb9260_defconfig
+++ b/configs/afeb9260_defconfig
@@ -1,2 +1,3 @@
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AFEB9260=y
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index 5837a0a..51bf370 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -4,3 +4,7 @@
 +S:CONFIG_TARGET_AM335X_EVM=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="am335x-boneblack"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/am335x_igep0033_defconfig b/configs/am335x_igep0033_defconfig
index 23f0a32..f3544b5 100644
--- a/configs/am335x_igep0033_defconfig
+++ b/configs/am335x_igep0033_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_AM335X_IGEP0033=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/am3517_crane_defconfig b/configs/am3517_crane_defconfig
index cf9d8c7..33b63c7 100644
--- a/configs/am3517_crane_defconfig
+++ b/configs/am3517_crane_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_AM3517_CRANE=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/am3517_evm_defconfig b/configs/am3517_evm_defconfig
index 2336f1e..7558b89 100644
--- a/configs/am3517_evm_defconfig
+++ b/configs/am3517_evm_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_AM3517_EVM=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/arcangel4-be_defconfig b/configs/arcangel4-be_defconfig
index 0c3ab4e..979f26e 100644
--- a/configs/arcangel4-be_defconfig
+++ b/configs/arcangel4-be_defconfig
@@ -1,3 +1,5 @@
 CONFIG_ARC=y
-CONFIG_TARGET_ARCANGEL4_BE=y
+CONFIG_TARGET_ARCANGEL4=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_SYS_TEXT_BASE=0x81000000
diff --git a/configs/arcangel4_defconfig b/configs/arcangel4_defconfig
index a63ef21..797595f 100644
--- a/configs/arcangel4_defconfig
+++ b/configs/arcangel4_defconfig
@@ -1,3 +1,4 @@
 CONFIG_ARC=y
 CONFIG_TARGET_ARCANGEL4=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_SYS_TEXT_BASE=0x81000000
diff --git a/configs/arches_defconfig b/configs/arches_defconfig
index 18d0a14..30c6932 100644
--- a/configs/arches_defconfig
+++ b/configs/arches_defconfig
@@ -1,4 +1,7 @@
-CONFIG_SYS_EXTRA_OPTIONS="ARCHES"
 CONFIG_PPC=y
 CONFIG_4xx=y
 CONFIG_TARGET_CANYONLANDS=y
+CONFIG_ARCHES=y
+CONFIG_DEFAULT_DEVICE_TREE="arches"
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
diff --git a/configs/at91rm9200ek_defconfig b/configs/at91rm9200ek_defconfig
index 95b5c27..e1fd2ec 100644
--- a/configs/at91rm9200ek_defconfig
+++ b/configs/at91rm9200ek_defconfig
@@ -1,2 +1,3 @@
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91RM9200EK=y
diff --git a/configs/at91rm9200ek_ram_defconfig b/configs/at91rm9200ek_ram_defconfig
index 5039ebc..64f5e54 100644
--- a/configs/at91rm9200ek_ram_defconfig
+++ b/configs/at91rm9200ek_ram_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91RM9200EK=y
diff --git a/configs/at91sam9260ek_dataflash_cs0_defconfig b/configs/at91sam9260ek_dataflash_cs0_defconfig
index 7f929c8..46ce31b 100644
--- a/configs/at91sam9260ek_dataflash_cs0_defconfig
+++ b/configs/at91sam9260ek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260,SYS_USE_DATAFLASH_CS0"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9260ek_dataflash_cs1_defconfig b/configs/at91sam9260ek_dataflash_cs1_defconfig
index e2c32bf..9fd40df 100644
--- a/configs/at91sam9260ek_dataflash_cs1_defconfig
+++ b/configs/at91sam9260ek_dataflash_cs1_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260,SYS_USE_DATAFLASH_CS1"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9260ek_nandflash_defconfig b/configs/at91sam9260ek_nandflash_defconfig
index 1168cac..98adab2 100644
--- a/configs/at91sam9260ek_nandflash_defconfig
+++ b/configs/at91sam9260ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9261ek_dataflash_cs0_defconfig b/configs/at91sam9261ek_dataflash_cs0_defconfig
index 486eeb2..9c311a3 100644
--- a/configs/at91sam9261ek_dataflash_cs0_defconfig
+++ b/configs/at91sam9261ek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9261,SYS_USE_DATAFLASH_CS0"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9261ek_dataflash_cs3_defconfig b/configs/at91sam9261ek_dataflash_cs3_defconfig
index 5f42a90..3711fe4 100644
--- a/configs/at91sam9261ek_dataflash_cs3_defconfig
+++ b/configs/at91sam9261ek_dataflash_cs3_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9261,SYS_USE_DATAFLASH_CS3"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9261ek_nandflash_defconfig b/configs/at91sam9261ek_nandflash_defconfig
index 4d7aa90..503f760 100644
--- a/configs/at91sam9261ek_nandflash_defconfig
+++ b/configs/at91sam9261ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9261,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9263ek_dataflash_cs0_defconfig b/configs/at91sam9263ek_dataflash_cs0_defconfig
index 4dce54e..15925b6 100644
--- a/configs/at91sam9263ek_dataflash_cs0_defconfig
+++ b/configs/at91sam9263ek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9263EK=y
diff --git a/configs/at91sam9263ek_dataflash_defconfig b/configs/at91sam9263ek_dataflash_defconfig
index 4dce54e..15925b6 100644
--- a/configs/at91sam9263ek_dataflash_defconfig
+++ b/configs/at91sam9263ek_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9263EK=y
diff --git a/configs/at91sam9263ek_nandflash_defconfig b/configs/at91sam9263ek_nandflash_defconfig
index 6f60daa..457fb1a 100644
--- a/configs/at91sam9263ek_nandflash_defconfig
+++ b/configs/at91sam9263ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9263EK=y
diff --git a/configs/at91sam9263ek_norflash_boot_defconfig b/configs/at91sam9263ek_norflash_boot_defconfig
index 944c14d..e49b177 100644
--- a/configs/at91sam9263ek_norflash_boot_defconfig
+++ b/configs/at91sam9263ek_norflash_boot_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_BOOT_NORFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9263EK=y
diff --git a/configs/at91sam9263ek_norflash_defconfig b/configs/at91sam9263ek_norflash_defconfig
index b54ef7f..fcd1764 100644
--- a/configs/at91sam9263ek_norflash_defconfig
+++ b/configs/at91sam9263ek_norflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_NORFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9263EK=y
diff --git a/configs/at91sam9g10ek_dataflash_cs0_defconfig b/configs/at91sam9g10ek_dataflash_cs0_defconfig
index 132102d..8334122 100644
--- a/configs/at91sam9g10ek_dataflash_cs0_defconfig
+++ b/configs/at91sam9g10ek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G10,SYS_USE_DATAFLASH_CS0"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9g10ek_dataflash_cs3_defconfig b/configs/at91sam9g10ek_dataflash_cs3_defconfig
index 3dd3f9a..25626ce 100644
--- a/configs/at91sam9g10ek_dataflash_cs3_defconfig
+++ b/configs/at91sam9g10ek_dataflash_cs3_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G10,SYS_USE_DATAFLASH_CS3"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9g10ek_nandflash_defconfig b/configs/at91sam9g10ek_nandflash_defconfig
index a2bd6df..7ae0794 100644
--- a/configs/at91sam9g10ek_nandflash_defconfig
+++ b/configs/at91sam9g10ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G10,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9261EK=y
diff --git a/configs/at91sam9g20ek_2mmc_defconfig b/configs/at91sam9g20ek_2mmc_defconfig
new file mode 100644
index 0000000..e277557
--- /dev/null
+++ b/configs/at91sam9g20ek_2mmc_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,AT91SAM9G20EK_2MMC,SYS_USE_MMC"
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9g20ek_2mmc_nandflash_defconfig b/configs/at91sam9g20ek_2mmc_nandflash_defconfig
index 1a4c505..29219fb 100644
--- a/configs/at91sam9g20ek_2mmc_nandflash_defconfig
+++ b/configs/at91sam9g20ek_2mmc_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,AT91SAM9G20EK_2MMC,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9g20ek_dataflash_cs0_defconfig b/configs/at91sam9g20ek_dataflash_cs0_defconfig
index cf35782..4587f49 100644
--- a/configs/at91sam9g20ek_dataflash_cs0_defconfig
+++ b/configs/at91sam9g20ek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_DATAFLASH_CS0"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9g20ek_dataflash_cs1_defconfig b/configs/at91sam9g20ek_dataflash_cs1_defconfig
index 1377ad9..c9fcc6e 100644
--- a/configs/at91sam9g20ek_dataflash_cs1_defconfig
+++ b/configs/at91sam9g20ek_dataflash_cs1_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_DATAFLASH_CS1"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9g20ek_mmc_defconfig b/configs/at91sam9g20ek_mmc_defconfig
deleted file mode 100644
index 8cca2e5..0000000
--- a/configs/at91sam9g20ek_mmc_defconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_MMC"
-CONFIG_ARM=y
-CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9g20ek_nandflash_defconfig b/configs/at91sam9g20ek_nandflash_defconfig
index cfe9127..1d60e0a 100644
--- a/configs/at91sam9g20ek_nandflash_defconfig
+++ b/configs/at91sam9g20ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9m10g45ek_mmc_defconfig b/configs/at91sam9m10g45ek_mmc_defconfig
index 1681bc8..6949d3a 100644
--- a/configs/at91sam9m10g45ek_mmc_defconfig
+++ b/configs/at91sam9m10g45ek_mmc_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_MMC"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9M10G45EK=y
diff --git a/configs/at91sam9m10g45ek_nandflash_defconfig b/configs/at91sam9m10g45ek_nandflash_defconfig
index 61ae56e..30967e3 100644
--- a/configs/at91sam9m10g45ek_nandflash_defconfig
+++ b/configs/at91sam9m10g45ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9M10G45EK=y
diff --git a/configs/at91sam9n12ek_mmc_defconfig b/configs/at91sam9n12ek_mmc_defconfig
index 71d1658..4fc417a 100644
--- a/configs/at91sam9n12ek_mmc_defconfig
+++ b/configs/at91sam9n12ek_mmc_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9N12,SYS_USE_MMC"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9N12EK=y
diff --git a/configs/at91sam9n12ek_nandflash_defconfig b/configs/at91sam9n12ek_nandflash_defconfig
index 6f677b1..f908246 100644
--- a/configs/at91sam9n12ek_nandflash_defconfig
+++ b/configs/at91sam9n12ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9N12,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9N12EK=y
diff --git a/configs/at91sam9n12ek_spiflash_defconfig b/configs/at91sam9n12ek_spiflash_defconfig
index 7e898f0..d106b5a 100644
--- a/configs/at91sam9n12ek_spiflash_defconfig
+++ b/configs/at91sam9n12ek_spiflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9N12,SYS_USE_SPIFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9N12EK=y
diff --git a/configs/at91sam9rlek_dataflash_defconfig b/configs/at91sam9rlek_dataflash_defconfig
index 90516e0..ee632d1 100644
--- a/configs/at91sam9rlek_dataflash_defconfig
+++ b/configs/at91sam9rlek_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9RL,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9RLEK=y
diff --git a/configs/at91sam9rlek_nandflash_defconfig b/configs/at91sam9rlek_nandflash_defconfig
index 0e2edfd..6465f57 100644
--- a/configs/at91sam9rlek_nandflash_defconfig
+++ b/configs/at91sam9rlek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9RL,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9RLEK=y
diff --git a/configs/at91sam9x5ek_dataflash_defconfig b/configs/at91sam9x5ek_dataflash_defconfig
index d00eed5..15b5fa9 100644
--- a/configs/at91sam9x5ek_dataflash_defconfig
+++ b/configs/at91sam9x5ek_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9X5,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9X5EK=y
diff --git a/configs/at91sam9x5ek_mmc_defconfig b/configs/at91sam9x5ek_mmc_defconfig
index 64f7af9..c8096c2 100644
--- a/configs/at91sam9x5ek_mmc_defconfig
+++ b/configs/at91sam9x5ek_mmc_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9X5,SYS_USE_MMC"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9X5EK=y
diff --git a/configs/at91sam9x5ek_nandflash_defconfig b/configs/at91sam9x5ek_nandflash_defconfig
index 47cd1e0..c2ebb00 100644
--- a/configs/at91sam9x5ek_nandflash_defconfig
+++ b/configs/at91sam9x5ek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9X5,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9X5EK=y
diff --git a/configs/at91sam9x5ek_spiflash_defconfig b/configs/at91sam9x5ek_spiflash_defconfig
index 1b7391e..76f68a6 100644
--- a/configs/at91sam9x5ek_spiflash_defconfig
+++ b/configs/at91sam9x5ek_spiflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9X5,SYS_USE_SPIFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9X5EK=y
diff --git a/configs/at91sam9xeek_dataflash_cs0_defconfig b/configs/at91sam9xeek_dataflash_cs0_defconfig
index ccbccd4..1449791 100644
--- a/configs/at91sam9xeek_dataflash_cs0_defconfig
+++ b/configs/at91sam9xeek_dataflash_cs0_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9XE,SYS_USE_DATAFLASH_CS0"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9xeek_dataflash_cs1_defconfig b/configs/at91sam9xeek_dataflash_cs1_defconfig
index e8f4cc3..b465064 100644
--- a/configs/at91sam9xeek_dataflash_cs1_defconfig
+++ b/configs/at91sam9xeek_dataflash_cs1_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9XE,SYS_USE_DATAFLASH_CS1"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/at91sam9xeek_nandflash_defconfig b/configs/at91sam9xeek_nandflash_defconfig
index 49c5d78..7e73d48 100644
--- a/configs/at91sam9xeek_nandflash_defconfig
+++ b/configs/at91sam9xeek_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9XE,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_AT91SAM9260EK=y
diff --git a/configs/axm_defconfig b/configs/axm_defconfig
index 076ad0f..abb64b6 100644
--- a/configs/axm_defconfig
+++ b/configs/axm_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,MACH_TYPE=2068,BOARD_AXM"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_TAURUS=y
diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig
index 5c0ca11..34ed963 100644
--- a/configs/axs101_defconfig
+++ b/configs/axs101_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARC=y
 CONFIG_TARGET_AXS101=y
-CONFIG_SYS_CLK_FREQ=750000000
\ No newline at end of file
+CONFIG_SYS_CLK_FREQ=750000000
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_SYS_TEXT_BASE=0x81000000
\ No newline at end of file
diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig
new file mode 100644
index 0000000..c63dd4a
--- /dev/null
+++ b/configs/axs103_defconfig
@@ -0,0 +1,5 @@
+CONFIG_SYS_TEXT_BASE=0x81000000
+CONFIG_SYS_CLK_FREQ=50000000
+CONFIG_ARC=y
+CONFIG_ISA_ARCV2=y
+CONFIG_TARGET_AXS101=y
diff --git a/configs/canyonlands_defconfig b/configs/canyonlands_defconfig
index 09b9ab9..44d4fbd 100644
--- a/configs/canyonlands_defconfig
+++ b/configs/canyonlands_defconfig
@@ -1,4 +1,7 @@
-CONFIG_SYS_EXTRA_OPTIONS="CANYONLANDS"
 CONFIG_PPC=y
 CONFIG_4xx=y
 CONFIG_TARGET_CANYONLANDS=y
+CONFIG_CANYONLANDS=y
+CONFIG_DEFAULT_DEVICE_TREE="canyonlands"
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
diff --git a/configs/cm_fx6_defconfig b/configs/cm_fx6_defconfig
index 3c0d64f..631698c 100644
--- a/configs/cm_fx6_defconfig
+++ b/configs/cm_fx6_defconfig
@@ -2,3 +2,8 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6QDL,SPL"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_CM_FX6=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/cm_t335_defconfig b/configs/cm_t335_defconfig
index 5ff4f9c..5c1d3cf 100644
--- a/configs/cm_t335_defconfig
+++ b/configs/cm_t335_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_CM_T335=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/cm_t3517_defconfig b/configs/cm_t3517_defconfig
index 4000d2c..6eb37c0 100644
--- a/configs/cm_t3517_defconfig
+++ b/configs/cm_t3517_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_CM_T3517=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/cm_t35_defconfig b/configs/cm_t35_defconfig
index 2bb616f..84a6fb0 100644
--- a/configs/cm_t35_defconfig
+++ b/configs/cm_t35_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_CM_T35=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/corvus_defconfig b/configs/corvus_defconfig
index 5d60847..82be323 100644
--- a/configs/corvus_defconfig
+++ b/configs/corvus_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9M10G45,SYS_USE_NANDFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_CORVUS=y
diff --git a/configs/cpu9260_128M_defconfig b/configs/cpu9260_128M_defconfig
index 86fc6bd..6fe59dd 100644
--- a/configs/cpu9260_128M_defconfig
+++ b/configs/cpu9260_128M_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9260,CPU9260_128M"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9260_defconfig b/configs/cpu9260_defconfig
index 10299e3..63e7c73 100644
--- a/configs/cpu9260_defconfig
+++ b/configs/cpu9260_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9260"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9260_nand_128M_defconfig b/configs/cpu9260_nand_128M_defconfig
index e582a15..11c5bce 100644
--- a/configs/cpu9260_nand_128M_defconfig
+++ b/configs/cpu9260_nand_128M_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9260,CPU9260_128M,NANDBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9260_nand_defconfig b/configs/cpu9260_nand_defconfig
index 40988cd..d4d6ec9 100644
--- a/configs/cpu9260_nand_defconfig
+++ b/configs/cpu9260_nand_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9260,NANDBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9G20_128M_defconfig b/configs/cpu9G20_128M_defconfig
index 4c28d25..8d33f08 100644
--- a/configs/cpu9G20_128M_defconfig
+++ b/configs/cpu9G20_128M_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9G20,CPU9G20_128M"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9G20_defconfig b/configs/cpu9G20_defconfig
index 468b2c8..fcfebb8 100644
--- a/configs/cpu9G20_defconfig
+++ b/configs/cpu9G20_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9G20"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9G20_nand_128M_defconfig b/configs/cpu9G20_nand_128M_defconfig
index a74df9d..315042d 100644
--- a/configs/cpu9G20_nand_128M_defconfig
+++ b/configs/cpu9G20_nand_128M_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9G20,CPU9G20_128M,NANDBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpu9G20_nand_defconfig b/configs/cpu9G20_nand_defconfig
index 11cc276..c405c50 100644
--- a/configs/cpu9G20_nand_defconfig
+++ b/configs/cpu9G20_nand_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="CPU9G20,NANDBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPU9260=y
diff --git a/configs/cpuat91_defconfig b/configs/cpuat91_defconfig
index d25bd3a..5a1ef3a 100644
--- a/configs/cpuat91_defconfig
+++ b/configs/cpuat91_defconfig
@@ -1,2 +1,3 @@
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPUAT91=y
diff --git a/configs/cpuat91_ram_defconfig b/configs/cpuat91_ram_defconfig
index f5b722d..2759192 100644
--- a/configs/cpuat91_ram_defconfig
+++ b/configs/cpuat91_ram_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_CPUAT91=y
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig
index 7aa216c..a7f13e2 100644
--- a/configs/db-mv784mp-gp_defconfig
+++ b/configs/db-mv784mp-gp_defconfig
@@ -1,2 +1,3 @@
-CONFIG_ARM=y
-CONFIG_TARGET_DB_MV784MP_GP=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_DB_MV784MP_GP=y
diff --git a/configs/devkit8000_defconfig b/configs/devkit8000_defconfig
index 578ae74..05a8700 100644
--- a/configs/devkit8000_defconfig
+++ b/configs/devkit8000_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_DEVKIT8000=y
+CONFIG_DM=y
+CONFIG_DM_SERIAL=y
+CONFIG_DM_GPIO=y
diff --git a/configs/dig297_defconfig b/configs/dig297_defconfig
index 95bc353..0d18290 100644
--- a/configs/dig297_defconfig
+++ b/configs/dig297_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_DIG297=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/eb_cpux9k2_defconfig b/configs/eb_cpux9k2_defconfig
index 5f0ab44..257fee5 100644
--- a/configs/eb_cpux9k2_defconfig
+++ b/configs/eb_cpux9k2_defconfig
@@ -1,2 +1,3 @@
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_EB_CPUX9K2=y
diff --git a/configs/eb_cpux9k2_ram_defconfig b/configs/eb_cpux9k2_ram_defconfig
index c6e8b71..4393ccc 100644
--- a/configs/eb_cpux9k2_ram_defconfig
+++ b/configs/eb_cpux9k2_ram_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="RAMBOOT"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_EB_CPUX9K2=y
diff --git a/configs/eco5pk_defconfig b/configs/eco5pk_defconfig
index e45bdad..e07df8b 100644
--- a/configs/eco5pk_defconfig
+++ b/configs/eco5pk_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_ECO5PK=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/ethernut5_defconfig b/configs/ethernut5_defconfig
index 5be495c..9a3d40a 100644
--- a/configs/ethernut5_defconfig
+++ b/configs/ethernut5_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9XE"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_ETHERNUT5=y
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig
new file mode 100644
index 0000000..f208651
--- /dev/null
+++ b/configs/galileo_defconfig
@@ -0,0 +1,6 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff10000"
+CONFIG_X86=y
+CONFIG_TARGET_GALILEO=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="galileo"
diff --git a/configs/glacier_defconfig b/configs/glacier_defconfig
index 2a66bfb..d318f82 100644
--- a/configs/glacier_defconfig
+++ b/configs/glacier_defconfig
@@ -1,4 +1,7 @@
-CONFIG_SYS_EXTRA_OPTIONS="GLACIER"
 CONFIG_PPC=y
 CONFIG_4xx=y
 CONFIG_TARGET_CANYONLANDS=y
+CONFIG_GLACIER=y
+CONFIG_DEFAULT_DEVICE_TREE="glacier"
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
diff --git a/configs/glacier_ramboot_defconfig b/configs/glacier_ramboot_defconfig
new file mode 100644
index 0000000..f8363b2
--- /dev/null
+++ b/configs/glacier_ramboot_defconfig
@@ -0,0 +1,8 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_RAMBOOT,SYS_TEXT_BASE=0x01000000,SYS_LDSCRIPT=board/amcc/canyonlands/u-boot-ram.lds"
+CONFIG_PPC=y
+CONFIG_4xx=y
+CONFIG_TARGET_CANYONLANDS=y
+CONFIG_GLACIER=y
+CONFIG_DEFAULT_DEVICE_TREE="glacier"
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
diff --git a/configs/gwventana_defconfig b/configs/gwventana_defconfig
index 4cddbdd..5b1a4c4 100644
--- a/configs/gwventana_defconfig
+++ b/configs/gwventana_defconfig
@@ -2,3 +2,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6QDL"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_GW_VENTANA=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 65791b7..41192fc 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -4,7 +4,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN7I=y
-+S:CONFIG_TARGET_I12_TVBOX=y
 +S:CONFIG_DRAM_CLK=384
 +S:CONFIG_DRAM_ZQ=127
 +S:CONFIG_DRAM_EMR1=4
diff --git a/configs/ids8313_defconfig b/configs/ids8313_defconfig
index 1c665aa..0950ec8 100644
--- a/configs/ids8313_defconfig
+++ b/configs/ids8313_defconfig
@@ -1,4 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xFFF00000"
 CONFIG_PPC=y
 CONFIG_MPC83xx=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
 CONFIG_TARGET_IDS8313=y
+CONFIG_DM=y
diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig
index 4bcffd8..219586a 100644
--- a/configs/maxbcm_defconfig
+++ b/configs/maxbcm_defconfig
@@ -1,2 +1,3 @@
-CONFIG_ARM=y
-CONFIG_TARGET_MAXBCM=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_MAXBCM=y
diff --git a/configs/mcx_defconfig b/configs/mcx_defconfig
index c2031f8..6566d40 100644
--- a/configs/mcx_defconfig
+++ b/configs/mcx_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_MCX=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/meesc_dataflash_defconfig b/configs/meesc_dataflash_defconfig
index fa737ef..0430d58 100644
--- a/configs/meesc_dataflash_defconfig
+++ b/configs/meesc_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_MEESC=y
diff --git a/configs/meesc_defconfig b/configs/meesc_defconfig
index f58efbb..b8a48f8 100644
--- a/configs/meesc_defconfig
+++ b/configs/meesc_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_MEESC=y
diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig
new file mode 100644
index 0000000..d124289
--- /dev/null
+++ b/configs/minnowmax_defconfig
@@ -0,0 +1,11 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff00000"
+CONFIG_X86=y
+CONFIG_TARGET_MINNOWMAX=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
+CONFIG_VIDEO_X86=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
+CONFIG_MMCONF_BASE_ADDRESS=0xe0000000
+CONFIG_HAVE_INTEL_ME=y
diff --git a/configs/mk802_a10s_defconfig b/configs/mk802_a10s_defconfig
index 086e1e4..cafcbaa 100644
--- a/configs/mk802_a10s_defconfig
+++ b/configs/mk802_a10s_defconfig
@@ -5,7 +5,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_MK802_A10S=y
 +S:CONFIG_DRAM_CLK=432
 +S:CONFIG_DRAM_ZQ=123
 +S:CONFIG_DRAM_EMR1=0
diff --git a/configs/mt_ventoux_defconfig b/configs/mt_ventoux_defconfig
index a0678bb..a4747c6 100644
--- a/configs/mt_ventoux_defconfig
+++ b/configs/mt_ventoux_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_MT_VENTOUX=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/mx6dlsabreauto_defconfig b/configs/mx6dlsabreauto_defconfig
index b649935..47f3f87 100644
--- a/configs/mx6dlsabreauto_defconfig
+++ b/configs/mx6dlsabreauto_defconfig
@@ -1,3 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6qsabreauto/mx6dl.cfg,MX6DL"
 CONFIG_ARM=y
 CONFIG_TARGET_MX6QSABREAUTO=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6dlsabresd_defconfig b/configs/mx6dlsabresd_defconfig
index 7f6cdff..6adfd55 100644
--- a/configs/mx6dlsabresd_defconfig
+++ b/configs/mx6dlsabresd_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6sabresd/mx6dlsabresd.cfg,MX6DL"
 CONFIG_ARM=y
 CONFIG_TARGET_MX6SABRESD=y
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6qsabreauto_defconfig b/configs/mx6qsabreauto_defconfig
index 7d86700..ab72942 100644
--- a/configs/mx6qsabreauto_defconfig
+++ b/configs/mx6qsabreauto_defconfig
@@ -1,3 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6qsabreauto/imximage.cfg,MX6Q"
 CONFIG_ARM=y
 CONFIG_TARGET_MX6QSABREAUTO=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6qsabrelite_defconfig b/configs/mx6qsabrelite_defconfig
index dfa9c2e..50b75ae 100644
--- a/configs/mx6qsabrelite_defconfig
+++ b/configs/mx6qsabrelite_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q.cfg,MX6Q,DDR_MB=1024,SABRELITE"
 CONFIG_ARM=y
 CONFIG_TARGET_NITROGEN6X=y
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6qsabresd_defconfig b/configs/mx6qsabresd_defconfig
index 67c1b77..112918b 100644
--- a/configs/mx6qsabresd_defconfig
+++ b/configs/mx6qsabresd_defconfig
@@ -1,3 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6sabresd/mx6q_4x_mt41j128.cfg,MX6Q"
 CONFIG_ARM=y
 CONFIG_TARGET_MX6SABRESD=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6sabresd_spl_defconfig b/configs/mx6sabresd_spl_defconfig
index 12e7844..67079ba 100644
--- a/configs/mx6sabresd_spl_defconfig
+++ b/configs/mx6sabresd_spl_defconfig
@@ -2,4 +2,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6Q"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_MX6SABRESD=y
-
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6sxsabresd_defconfig b/configs/mx6sxsabresd_defconfig
index f23d48f..cc82322 100644
--- a/configs/mx6sxsabresd_defconfig
+++ b/configs/mx6sxsabresd_defconfig
@@ -1,3 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6sxsabresd/imximage.cfg,MX6SX"
 CONFIG_ARM=y
 CONFIG_TARGET_MX6SXSABRESD=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/mx6sxsabresd_spl_defconfig b/configs/mx6sxsabresd_spl_defconfig
new file mode 100644
index 0000000..901b01b
--- /dev/null
+++ b/configs/mx6sxsabresd_spl_defconfig
@@ -0,0 +1,6 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6SX"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_MX6SXSABRESD=y
+CONFIG_DM=y
+CONFIG_DM_THERMAL=y
diff --git a/configs/nokia_rx51_defconfig b/configs/nokia_rx51_defconfig
index e03f586..1bb7664 100644
--- a/configs/nokia_rx51_defconfig
+++ b/configs/nokia_rx51_defconfig
@@ -1,3 +1,8 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_NOKIA_RX51=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/odroid_defconfig b/configs/odroid_defconfig
index a842837..816a3fa 100644
--- a/configs/odroid_defconfig
+++ b/configs/odroid_defconfig
@@ -3,3 +3,5 @@
 CONFIG_TARGET_ODROID=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="exynos4412-odroid"
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
diff --git a/configs/omap3_beagle_defconfig b/configs/omap3_beagle_defconfig
index a3e4c2c..5a2d20b 100644
--- a/configs/omap3_beagle_defconfig
+++ b/configs/omap3_beagle_defconfig
@@ -3,3 +3,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_OMAP3_BEAGLE=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
diff --git a/configs/omap3_evm_defconfig b/configs/omap3_evm_defconfig
index c749aa7..3bb1911 100644
--- a/configs/omap3_evm_defconfig
+++ b/configs/omap3_evm_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_OMAP3_EVM=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_evm_quick_mmc_defconfig b/configs/omap3_evm_quick_mmc_defconfig
index e89bb82..4e1471b 100644
--- a/configs/omap3_evm_quick_mmc_defconfig
+++ b/configs/omap3_evm_quick_mmc_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_OMAP3_EVM_QUICK_MMC=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_evm_quick_nand_defconfig b/configs/omap3_evm_quick_nand_defconfig
index e70fddd..f98672f 100644
--- a/configs/omap3_evm_quick_nand_defconfig
+++ b/configs/omap3_evm_quick_nand_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_OMAP3_EVM_QUICK_NAND=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_ha_defconfig b/configs/omap3_ha_defconfig
index 50bffa9..1a8b1b4 100644
--- a/configs/omap3_ha_defconfig
+++ b/configs/omap3_ha_defconfig
@@ -3,3 +3,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_TAO3530=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig
index 5f2c063..790ccba 100644
--- a/configs/omap3_logic_defconfig
+++ b/configs/omap3_logic_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_OMAP3_LOGIC=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_mvblx_defconfig b/configs/omap3_mvblx_defconfig
index fb6edc2..b75f513 100644
--- a/configs/omap3_mvblx_defconfig
+++ b/configs/omap3_mvblx_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_OMAP3_MVBLX=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_pandora_defconfig b/configs/omap3_pandora_defconfig
index bf28537..dd0f17c 100644
--- a/configs/omap3_pandora_defconfig
+++ b/configs/omap3_pandora_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_OMAP3_PANDORA=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/omap3_sdp3430_defconfig b/configs/omap3_sdp3430_defconfig
index 1172c2a..b3a8745 100644
--- a/configs/omap3_sdp3430_defconfig
+++ b/configs/omap3_sdp3430_defconfig
@@ -1,3 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP34XX=y
 CONFIG_TARGET_OMAP3_SDP3430=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/ot1200_spl_defconfig b/configs/ot1200_spl_defconfig
new file mode 100644
index 0000000..ad57f88
--- /dev/null
+++ b/configs/ot1200_spl_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_OT1200=y
diff --git a/configs/otc570_dataflash_defconfig b/configs/otc570_dataflash_defconfig
index 992d6b6..7aac6d8 100644
--- a/configs/otc570_dataflash_defconfig
+++ b/configs/otc570_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_OTC570=y
diff --git a/configs/otc570_defconfig b/configs/otc570_defconfig
index 65295cb..5204245 100644
--- a/configs/otc570_defconfig
+++ b/configs/otc570_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_OTC570=y
diff --git a/configs/pcm051_rev1_defconfig b/configs/pcm051_rev1_defconfig
index 8b27682..baa2b23 100644
--- a/configs/pcm051_rev1_defconfig
+++ b/configs/pcm051_rev1_defconfig
@@ -2,3 +2,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="REV1"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_PCM051=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/pcm051_rev3_defconfig b/configs/pcm051_rev3_defconfig
index 27ad6ff..b5c62a6 100644
--- a/configs/pcm051_rev3_defconfig
+++ b/configs/pcm051_rev3_defconfig
@@ -2,3 +2,5 @@
 CONFIG_SYS_EXTRA_OPTIONS="REV3"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_PCM051=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig
index 8ada0db..333e335 100644
--- a/configs/peach-pi_defconfig
+++ b/configs/peach-pi_defconfig
@@ -3,3 +3,7 @@
 +S:CONFIG_ARCH_EXYNOS=y
 +S:CONFIG_TARGET_PEACH_PI=y
 CONFIG_DEFAULT_DEVICE_TREE="exynos5800-peach-pi"
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_CMD_CROS_EC=y
diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig
index b944b3b..cf84444 100644
--- a/configs/peach-pit_defconfig
+++ b/configs/peach-pit_defconfig
@@ -3,3 +3,7 @@
 +S:CONFIG_ARCH_EXYNOS=y
 +S:CONFIG_TARGET_PEACH_PIT=y
 CONFIG_DEFAULT_DEVICE_TREE="exynos5420-peach-pit"
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_CMD_CROS_EC=y
diff --git a/configs/pengwyn_defconfig b/configs/pengwyn_defconfig
index 1b9aa68..cbdd404 100644
--- a/configs/pengwyn_defconfig
+++ b/configs/pengwyn_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_PENGWYN=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/pepper_defconfig b/configs/pepper_defconfig
index 22c7bb4..14266ef 100644
--- a/configs/pepper_defconfig
+++ b/configs/pepper_defconfig
@@ -1,3 +1,5 @@
 CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_PEPPER=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/ph1_ld4_defconfig b/configs/ph1_ld4_defconfig
index 2e9dd00..86b4b15 100644
--- a/configs/ph1_ld4_defconfig
+++ b/configs/ph1_ld4_defconfig
@@ -18,6 +18,7 @@
 CONFIG_CMD_LOADS=y
 CONFIG_CMD_FLASH=y
 CONFIG_CMD_NAND=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_ECHO=y
 CONFIG_CMD_ITEST=y
@@ -34,6 +35,7 @@
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
 CONFIG_DM_SERIAL=y
 CONFIG_UNIPHIER_SERIAL=y
+CONFIG_DM_I2C=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/ph1_pro4_defconfig b/configs/ph1_pro4_defconfig
index 5dca64b..242bcf9 100644
--- a/configs/ph1_pro4_defconfig
+++ b/configs/ph1_pro4_defconfig
@@ -18,6 +18,7 @@
 CONFIG_CMD_LOADS=y
 CONFIG_CMD_FLASH=y
 CONFIG_CMD_NAND=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_ECHO=y
 CONFIG_CMD_ITEST=y
@@ -34,6 +35,7 @@
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
 CONFIG_DM_SERIAL=y
 CONFIG_UNIPHIER_SERIAL=y
+CONFIG_DM_I2C=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/ph1_sld8_defconfig b/configs/ph1_sld8_defconfig
index 2a6e334..8e95f17 100644
--- a/configs/ph1_sld8_defconfig
+++ b/configs/ph1_sld8_defconfig
@@ -18,6 +18,7 @@
 CONFIG_CMD_LOADS=y
 CONFIG_CMD_FLASH=y
 CONFIG_CMD_NAND=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_ECHO=y
 CONFIG_CMD_ITEST=y
@@ -34,6 +35,7 @@
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
 CONFIG_DM_SERIAL=y
 CONFIG_UNIPHIER_SERIAL=y
+CONFIG_DM_I2C=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/platinum_picon_defconfig b/configs/platinum_picon_defconfig
new file mode 100644
index 0000000..c3ca040
--- /dev/null
+++ b/configs/platinum_picon_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6DL"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_PLATINUM_PICON=y
diff --git a/configs/platinum_titanium_defconfig b/configs/platinum_titanium_defconfig
new file mode 100644
index 0000000..db8cef9
--- /dev/null
+++ b/configs/platinum_titanium_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_PLATINUM_TITANIUM=y
diff --git a/configs/pm9261_defconfig b/configs/pm9261_defconfig
index b8a0248..0c7efc7 100644
--- a/configs/pm9261_defconfig
+++ b/configs/pm9261_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9261"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_PM9261=y
diff --git a/configs/pm9263_defconfig b/configs/pm9263_defconfig
index 3a5029a..6e88046 100644
--- a/configs/pm9263_defconfig
+++ b/configs/pm9263_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_PM9263=y
diff --git a/configs/pm9g45_defconfig b/configs/pm9g45_defconfig
index 89297e0..112ad5f 100644
--- a/configs/pm9g45_defconfig
+++ b/configs/pm9g45_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G45"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_PM9G45=y
diff --git a/configs/portuxg20_defconfig b/configs/portuxg20_defconfig
index b1634e9..9f3a8e1 100644
--- a/configs/portuxg20_defconfig
+++ b/configs/portuxg20_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,PORTUXG20"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_STAMP9G20=y
diff --git a/configs/r7-tv-dongle_defconfig b/configs/r7-tv-dongle_defconfig
index b9fd59c..e99e57d 100644
--- a/configs/r7-tv-dongle_defconfig
+++ b/configs/r7-tv-dongle_defconfig
@@ -5,4 +5,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
-+S:CONFIG_TARGET_R7DONGLE=y
++S:CONFIG_DRAM_CLK=384
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig
new file mode 100644
index 0000000..b539d4a
--- /dev/null
+++ b/configs/rpi_2_defconfig
@@ -0,0 +1,4 @@
+CONFIG_ARM=y
+CONFIG_TARGET_RPI_2=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig
index 9379cf0..98d3199 100644
--- a/configs/rpi_defconfig
+++ b/configs/rpi_defconfig
@@ -1,2 +1,4 @@
 CONFIG_ARM=y
 CONFIG_TARGET_RPI=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/s5p_goni_defconfig b/configs/s5p_goni_defconfig
index 618e590..33e6fb8 100644
--- a/configs/s5p_goni_defconfig
+++ b/configs/s5p_goni_defconfig
@@ -2,3 +2,5 @@
 CONFIG_ARCH_S5PC1XX=y
 CONFIG_TARGET_S5P_GONI=y
 CONFIG_DEFAULT_DEVICE_TREE="s5pc1xx-goni"
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/sama5d3_xplained_mmc_defconfig b/configs/sama5d3_xplained_mmc_defconfig
index a7d791f..1d95487 100644
--- a/configs/sama5d3_xplained_mmc_defconfig
+++ b/configs/sama5d3_xplained_mmc_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_MMC"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D3_XPLAINED=y
diff --git a/configs/sama5d3_xplained_nandflash_defconfig b/configs/sama5d3_xplained_nandflash_defconfig
index b972860..91dd104 100644
--- a/configs/sama5d3_xplained_nandflash_defconfig
+++ b/configs/sama5d3_xplained_nandflash_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_NANDFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D3_XPLAINED=y
diff --git a/configs/sama5d3xek_mmc_defconfig b/configs/sama5d3xek_mmc_defconfig
index 3f8d997..c03106c 100644
--- a/configs/sama5d3xek_mmc_defconfig
+++ b/configs/sama5d3xek_mmc_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_MMC"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D3XEK=y
diff --git a/configs/sama5d3xek_nandflash_defconfig b/configs/sama5d3xek_nandflash_defconfig
index 7a92417..54bf79c 100644
--- a/configs/sama5d3xek_nandflash_defconfig
+++ b/configs/sama5d3xek_nandflash_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_NANDFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D3XEK=y
diff --git a/configs/sama5d3xek_spiflash_defconfig b/configs/sama5d3xek_spiflash_defconfig
index c83a7ab..07bff18 100644
--- a/configs/sama5d3xek_spiflash_defconfig
+++ b/configs/sama5d3xek_spiflash_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_SERIALFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D3XEK=y
diff --git a/configs/sama5d4_xplained_mmc_defconfig b/configs/sama5d4_xplained_mmc_defconfig
index 3720f3c..da5f811 100644
--- a/configs/sama5d4_xplained_mmc_defconfig
+++ b/configs/sama5d4_xplained_mmc_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_MMC"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4_XPLAINED=y
diff --git a/configs/sama5d4_xplained_nandflash_defconfig b/configs/sama5d4_xplained_nandflash_defconfig
index 5e13da7..ea06200 100644
--- a/configs/sama5d4_xplained_nandflash_defconfig
+++ b/configs/sama5d4_xplained_nandflash_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_NANDFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4_XPLAINED=y
diff --git a/configs/sama5d4_xplained_spiflash_defconfig b/configs/sama5d4_xplained_spiflash_defconfig
index 3a4607c..0408fa4 100644
--- a/configs/sama5d4_xplained_spiflash_defconfig
+++ b/configs/sama5d4_xplained_spiflash_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_SERIALFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4_XPLAINED=y
diff --git a/configs/sama5d4ek_mmc_defconfig b/configs/sama5d4ek_mmc_defconfig
index 16a5ed7..1f66d37 100644
--- a/configs/sama5d4ek_mmc_defconfig
+++ b/configs/sama5d4ek_mmc_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_MMC"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4EK=y
diff --git a/configs/sama5d4ek_nandflash_defconfig b/configs/sama5d4ek_nandflash_defconfig
index 8b7fbc3..c623d9b 100644
--- a/configs/sama5d4ek_nandflash_defconfig
+++ b/configs/sama5d4ek_nandflash_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_NANDFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4EK=y
diff --git a/configs/sama5d4ek_spiflash_defconfig b/configs/sama5d4ek_spiflash_defconfig
index 63e9b6c..3b4e124 100644
--- a/configs/sama5d4ek_spiflash_defconfig
+++ b/configs/sama5d4ek_spiflash_defconfig
@@ -1,3 +1,5 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D4,SYS_USE_SERIALFLASH"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_SAMA5D4EK=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 47d8400..70f5b86 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,3 +1,14 @@
 CONFIG_OF_CONTROL=y
 CONFIG_OF_HOSTFILE=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
 CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_CROS_EC=y
+CONFIG_DM_CROS_EC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_CMD_CROS_EC=y
diff --git a/configs/sbc35_a9g20_eeprom_defconfig b/configs/sbc35_a9g20_eeprom_defconfig
index aa9cd3e..cd0909c 100644
--- a/configs/sbc35_a9g20_eeprom_defconfig
+++ b/configs/sbc35_a9g20_eeprom_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_EEPROM"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SBC35_A9G20=y
diff --git a/configs/sbc35_a9g20_nandflash_defconfig b/configs/sbc35_a9g20_nandflash_defconfig
index fba9f31..017346f 100644
--- a/configs/sbc35_a9g20_nandflash_defconfig
+++ b/configs/sbc35_a9g20_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SBC35_A9G20=y
diff --git a/configs/silk_defconfig b/configs/silk_defconfig
new file mode 100644
index 0000000..515ee33
--- /dev/null
+++ b/configs/silk_defconfig
@@ -0,0 +1,3 @@
+CONFIG_ARM=y
+CONFIG_RMOBILE=y
+CONFIG_TARGET_SILK=y
diff --git a/configs/smdkc100_defconfig b/configs/smdkc100_defconfig
index 041030f..e933a32 100644
--- a/configs/smdkc100_defconfig
+++ b/configs/smdkc100_defconfig
@@ -2,3 +2,5 @@
 CONFIG_TARGET_SMDKC100=y
 CONFIG_ARCH_S5PC1XX=y
 CONFIG_DEFAULT_DEVICE_TREE="s5pc1xx-smdkc100"
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/snapper9260_defconfig b/configs/snapper9260_defconfig
index 7055e2a..3a47505 100644
--- a/configs/snapper9260_defconfig
+++ b/configs/snapper9260_defconfig
@@ -1,3 +1,9 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SNAPPER9260=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/snapper9g20_defconfig b/configs/snapper9g20_defconfig
index 2faae15..1f0244b 100644
--- a/configs/snapper9g20_defconfig
+++ b/configs/snapper9g20_defconfig
@@ -1,3 +1,9 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SNAPPER9260=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x400
diff --git a/configs/snow_defconfig b/configs/snow_defconfig
index 14ed793..353ddb0 100644
--- a/configs/snow_defconfig
+++ b/configs/snow_defconfig
@@ -3,3 +3,8 @@
 +S:CONFIG_ARCH_EXYNOS=y
 +S:CONFIG_TARGET_SNOW=y
 CONFIG_DEFAULT_DEVICE_TREE="exynos5250-snow"
+CONFIG_CROS_EC=y
+CONFIG_DM_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_CMD_CROS_EC=y
diff --git a/configs/socfpga_socrates_defconfig b/configs/socfpga_socrates_defconfig
index 0f3896d..888bbb6 100644
--- a/configs/socfpga_socrates_defconfig
+++ b/configs/socfpga_socrates_defconfig
@@ -3,3 +3,6 @@
 +S:CONFIG_TARGET_SOCFPGA_CYCLONE5=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="socfpga_cyclone5_socrates"
+CONFIG_DM=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
diff --git a/configs/stamp9g20_defconfig b/configs/stamp9g20_defconfig
index 8c0f874..03bf492 100644
--- a/configs/stamp9g20_defconfig
+++ b/configs/stamp9g20_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_STAMP9G20=y
diff --git a/configs/stv0991_defconfig b/configs/stv0991_defconfig
index a05e991..1c9ba88 100644
--- a/configs/stv0991_defconfig
+++ b/configs/stv0991_defconfig
@@ -1,3 +1,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="stv0991"
 CONFIG_ARM=y
 CONFIG_TARGET_STV0991=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DM=y
+CONFIG_DM_SERIAL=y
diff --git a/configs/tao3530_defconfig b/configs/tao3530_defconfig
index a511389..39ed872 100644
--- a/configs/tao3530_defconfig
+++ b/configs/tao3530_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_TAO3530=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/taurus_defconfig b/configs/taurus_defconfig
index 438e25d..fac3316 100644
--- a/configs/taurus_defconfig
+++ b/configs/taurus_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,MACH_TYPE=2067,BOARD_TAURUS"
 +S:CONFIG_ARM=y
++S:CONFIG_ARCH_AT91=y
 +S:CONFIG_TARGET_TAURUS=y
diff --git a/configs/tb100_defconfig b/configs/tb100_defconfig
index d2de03b..b0e8c9f 100644
--- a/configs/tb100_defconfig
+++ b/configs/tb100_defconfig
@@ -1,3 +1,5 @@
 CONFIG_ARC=y
 CONFIG_TARGET_TB100=y
-CONFIG_SYS_CLK_FREQ=500000000
\ No newline at end of file
+CONFIG_SYS_CLK_FREQ=500000000
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/tny_a9260_eeprom_defconfig b/configs/tny_a9260_eeprom_defconfig
index a662669..28a1d5e 100644
--- a/configs/tny_a9260_eeprom_defconfig
+++ b/configs/tny_a9260_eeprom_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260,SYS_USE_EEPROM"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_TNY_A9260=y
diff --git a/configs/tny_a9260_nandflash_defconfig b/configs/tny_a9260_nandflash_defconfig
index 41fd9c1..14710c0 100644
--- a/configs/tny_a9260_nandflash_defconfig
+++ b/configs/tny_a9260_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9260,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_TNY_A9260=y
diff --git a/configs/tny_a9g20_eeprom_defconfig b/configs/tny_a9g20_eeprom_defconfig
index a2eb60e..f4023cc 100644
--- a/configs/tny_a9g20_eeprom_defconfig
+++ b/configs/tny_a9g20_eeprom_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_EEPROM"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_TNY_A9260=y
diff --git a/configs/tny_a9g20_nandflash_defconfig b/configs/tny_a9g20_nandflash_defconfig
index 60ebfa2..2452e1e 100644
--- a/configs/tny_a9g20_nandflash_defconfig
+++ b/configs/tny_a9g20_nandflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G20,SYS_USE_NANDFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_TNY_A9260=y
diff --git a/configs/tricorder_defconfig b/configs/tricorder_defconfig
index 7ea5e02..3efe829 100644
--- a/configs/tricorder_defconfig
+++ b/configs/tricorder_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_TRICORDER=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/tricorder_flash_defconfig b/configs/tricorder_flash_defconfig
index f6e1c46..8f999ff 100644
--- a/configs/tricorder_flash_defconfig
+++ b/configs/tricorder_flash_defconfig
@@ -3,3 +3,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_TRICORDER=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/twister_defconfig b/configs/twister_defconfig
index 9023736..d21a551 100644
--- a/configs/twister_defconfig
+++ b/configs/twister_defconfig
@@ -2,3 +2,6 @@
 +S:CONFIG_ARM=y
 +S:CONFIG_OMAP34XX=y
 +S:CONFIG_TARGET_TWISTER=y
+CONFIG_DM=n
+CONFIG_DM_SERIAL=n
+CONFIG_DM_GPIO=n
diff --git a/configs/usb_a9263_dataflash_defconfig b/configs/usb_a9263_dataflash_defconfig
index 8c0ac11..ae2b9a1 100644
--- a/configs/usb_a9263_dataflash_defconfig
+++ b/configs/usb_a9263_dataflash_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9263,SYS_USE_DATAFLASH"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_USB_A9263=y
diff --git a/configs/vexpress_aemv8a_defconfig b/configs/vexpress_aemv8a_defconfig
index b463a33..9f4b876 100644
--- a/configs/vexpress_aemv8a_defconfig
+++ b/configs/vexpress_aemv8a_defconfig
@@ -1,3 +1,3 @@
 CONFIG_ARM=y
-CONFIG_TARGET_VEXPRESS_AEMV8A=y
+CONFIG_TARGET_VEXPRESS64_AEMV8A=y
 CONFIG_DEFAULT_DEVICE_TREE="vexpress64"
diff --git a/configs/vexpress_aemv8a_juno_defconfig b/configs/vexpress_aemv8a_juno_defconfig
new file mode 100644
index 0000000..d28a428
--- /dev/null
+++ b/configs/vexpress_aemv8a_juno_defconfig
@@ -0,0 +1,5 @@
+# ARM Ltd. Juno Board Reference Design
+CONFIG_ARM=y
+CONFIG_TARGET_VEXPRESS64_JUNO=y
+CONFIG_DEFAULT_DEVICE_TREE="vexpress64"
+CONFIG_SHOW_BOOT_PROGRESS=y
diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig
index 0035ccd..26cf7db4 100644
--- a/configs/vexpress_aemv8a_semi_defconfig
+++ b/configs/vexpress_aemv8a_semi_defconfig
@@ -1,4 +1,4 @@
-CONFIG_SYS_EXTRA_OPTIONS="SEMIHOSTING,BASE_FVP"
+# Semihosted FVP fast model
 CONFIG_ARM=y
-CONFIG_TARGET_VEXPRESS_AEMV8A=y
+CONFIG_TARGET_VEXPRESS64_BASE_FVP=y
 CONFIG_DEFAULT_DEVICE_TREE="vexpress64"
diff --git a/configs/vl_ma2sc_defconfig b/configs/vl_ma2sc_defconfig
index 39cd725..e6478a7 100644
--- a/configs/vl_ma2sc_defconfig
+++ b/configs/vl_ma2sc_defconfig
@@ -1,2 +1,3 @@
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_VL_MA2SC=y
diff --git a/configs/vl_ma2sc_ram_defconfig b/configs/vl_ma2sc_ram_defconfig
index 70a07ab..fdb262d 100644
--- a/configs/vl_ma2sc_ram_defconfig
+++ b/configs/vl_ma2sc_ram_defconfig
@@ -1,3 +1,4 @@
 CONFIG_SYS_EXTRA_OPTIONS="RAMLOAD"
 CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
 CONFIG_TARGET_VL_MA2SC=y
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index 9588849..8b985fe 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -3,4 +3,8 @@
 +S:CONFIG_ZYNQ=y
 +S:CONFIG_TARGET_ZYNQ_MICROZED=y
 CONFIG_OF_CONTROL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed"
diff --git a/configs/zynq_zc70x_defconfig b/configs/zynq_zc70x_defconfig
index cf50730..cceb321 100644
--- a/configs/zynq_zc70x_defconfig
+++ b/configs/zynq_zc70x_defconfig
@@ -4,3 +4,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZC70X=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig
index 8bb405d..2935c0d 100644
--- a/configs/zynq_zc770_xm010_defconfig
+++ b/configs/zynq_zc770_xm010_defconfig
@@ -5,3 +5,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig
index 0ba5da5..0401739 100644
--- a/configs/zynq_zc770_xm012_defconfig
+++ b/configs/zynq_zc770_xm012_defconfig
@@ -5,3 +5,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig
index 13f8112..a95970a 100644
--- a/configs/zynq_zc770_xm013_defconfig
+++ b/configs/zynq_zc770_xm013_defconfig
@@ -5,3 +5,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index eb057fa..0fbc41a 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -4,3 +4,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZED=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zed"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index 12311cd..4e66760 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -4,3 +4,7 @@
 +S:CONFIG_TARGET_ZYNQ_ZYBO=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_DM=y
diff --git a/doc/README.distro b/doc/README.distro
new file mode 100644
index 0000000..dd0f1c7
--- /dev/null
+++ b/doc/README.distro
@@ -0,0 +1,341 @@
+/*
+ * (C) Copyright 2014 Red Hat Inc.
+ * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+Generic Distro Configuration Concept
+====================================
+
+Linux distributions are faced with supporting a variety of boot mechanisms,
+environments or bootloaders (PC BIOS, EFI, U-Boot, Barebox, ...). This makes
+life complicated. Worse, bootloaders such as U-Boot have a configurable set
+of features, and each board chooses to enable a different set of features.
+Hence, distros typically need to have board-specific knowledge in order to
+set up a bootable system.
+
+This document defines a common set of U-Boot features that are required for
+a distro to support the board in a generic fashion. Any board wishing to
+allow distros to install and boot in an out-of-the-box fashion should enable
+all these features. Linux distros can then create a single set of boot
+support/install logic that targets these features. This will allow distros
+to install on many boards without the need for board-specific logic.
+
+In fact, some of these features can be implemented by any bootloader, thus
+decoupling distro install/boot logic from any knowledge of the bootloader.
+
+This model assumes that boards will load boot configuration files from a
+regular storage mechanism (eMMC, SD card, USB Disk, SATA disk, etc.) with
+a standard partitioning scheme (MBR, GPT). Boards that cannnot support this
+storage model are outside the scope of this document, and may still need
+board-specific installer/boot-configuration support in a distro.
+
+To some extent, this model assumes that a board has a separate boot flash
+that contains U-Boot, and that the user has somehow installed U-Boot to this
+flash before running the distro installer. Even on boards that do not conform
+to this aspect of the model, the extent of the board-specific support in the
+distro installer logic would be to install a board-specific U-Boot package to
+the boot partition partition during installation. This distro-supplied U-Boot
+can still implement the same features as on any other board, and hence the
+distro's boot configuration file generation logic can still be board-agnostic.
+
+Locating Bootable Disks
+-----------------------
+
+Typical desktop/server PCs search all (or a user-defined subset of) attached
+storage devices for a bootable partition, then load the bootloader or boot
+configuration files from there. A U-Boot board port that enables the features
+mentioned in this document will search for boot configuration files in the
+same way.
+
+Thus, distros do not need to manipulate any kind of bootloader-specific
+configuration data to indicate which storage device the system should boot
+from.
+
+Distros simply need to install the boot configuration files (see next
+section) in an ext2/3/4 or FAT partition, mark the partition bootable (via
+the MBR bootable flag, or GPT legacy_bios_bootable attribute), and U-Boot (or
+any other bootloader) will find those boot files and execute them. This is
+conceptually identical to creating a grub2 configuration file on a desktop
+PC.
+
+Note that in the absense of any partition that is explicitly marked bootable,
+U-Boot falls back to searching the first valid partition of a disk for boot
+configuration files. Other bootloaders are recommended to do the same, since
+I believe that partition table bootable flags aren't so commonly used outside
+the realm of x86 PCs.
+
+U-Boot can also search for boot configuration files from a TFTP server.
+
+Boot Configuration Files
+------------------------
+
+The standard format for boot configuration files is that of extlinux.conf, as
+handled by U-Boot's "syslinux" (disk) or "pxe boot" (network). This is roughly
+as specified at:
+
+http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
+
+... with the exceptions that the BootLoaderSpec document:
+
+* Prescribes a separate configuration per boot menu option, whereas U-Boot
+  lumps all options into a single extlinux.conf file. Hence, U-Boot searches
+  for /extlinux/extlinux.conf then /boot/extlinux/extlinux.conf on disk, or
+  pxelinux.cfg/default over the network.
+
+* Does not document the fdtdir option, which automatically selects the DTB to
+  pass to the kernel.
+
+One example extlinux.conf generated by the Fedora installer is:
+
+------------------------------------------------------------
+# extlinux.conf generated by anaconda
+
+ui menu.c32
+
+menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options.
+menu title Fedora Boot Options.
+menu hidden
+
+timeout 50
+#totaltimeout 9000
+
+default Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
+
+label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl) 22 (Rawhide)
+	kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl
+	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
+	fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl
+	initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl.img
+
+label Fedora (3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae) 22 (Rawhide)
+	kernel /boot/vmlinuz-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
+	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8 LANG=en_US.UTF-8 drm.debug=0xf
+	fdtdir /boot/dtb-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae
+	initrd /boot/initramfs-3.17.0-0.rc4.git2.1.fc22.armv7hl+lpae.img
+
+label Fedora-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc (0-rescue-8f6ba7b039524e0eb957d2c9203f04bc)
+	kernel /boot/vmlinuz-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc
+	initrd /boot/initramfs-0-rescue-8f6ba7b039524e0eb957d2c9203f04bc.img
+	append ro root=UUID=8eac677f-8ea8-4270-8479-d5ddbb797450 console=ttyS0,115200n8
+	fdtdir /boot/dtb-3.16.0-0.rc6.git1.1.fc22.armv7hl+lpae
+------------------------------------------------------------
+
+Another hand-crafted network boot configuration file is:
+
+------------------------------------------------------------
+TIMEOUT 100
+
+MENU TITLE TFTP boot options
+
+LABEL jetson-tk1-emmc
+        MENU LABEL ../zImage root on Jetson TK1 eMMC
+        LINUX ../zImage
+        FDTDIR ../
+        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=80a5a8e9-c744-491a-93c1-4f4194fd690b
+
+LABEL venice2-emmc
+        MENU LABEL ../zImage root on Venice2 eMMC
+        LINUX ../zImage
+        FDTDIR ../
+        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=5f71e06f-be08-48ed-b1ef-ee4800cc860f
+
+LABEL sdcard
+        MENU LABEL ../zImage, root on 2GB sdcard
+        LINUX ../zImage
+        FDTDIR ../
+        APPEND console=ttyS0,115200n8 console=tty1 loglevel=8 rootwait rw earlyprintk root=PARTUUID=b2f82cda-2535-4779-b467-094a210fbae7
+
+LABEL fedora-installer-fk
+        MENU LABEL Fedora installer w/ Fedora kernel
+        LINUX fedora-installer/vmlinuz
+        INITRD fedora-installer/initrd.img.orig
+        FDTDIR fedora-installer/dtb
+        APPEND loglevel=8 ip=dhcp inst.repo=http://10.0.0.2/mirrors/fedora/linux/development/rawhide/armhfp/os/ rd.shell cma=64M
+------------------------------------------------------------
+
+U-Boot Implementation
+=====================
+
+Enabling the distro options
+---------------------------
+
+In your board configuration file, include the following:
+
+------------------------------------------------------------
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+#include <config_distro_bootcmd.h>
+#endif
+------------------------------------------------------------
+
+The first of those headers primarily enables a core set of U-Boot features,
+such as support for MBR and GPT partitions, ext* and FAT filesystems, booting
+raw zImage and initrd (rather than FIT- or uImage-wrapped files), etc. Network
+boot support is also enabled here, which is useful in order to boot distro
+installers given that distros do not commonly distribute bootable install
+media for non-PC targets at present.
+
+Finally, a few options that are mostly relevant only when using U-Boot-
+specific boot.scr scripts are enabled. This enables distros to generate a
+U-Boot-specific boot.scr script rather than extlinux.conf as the boot
+configuration file. While doing so is fully supported, and
+<config_distro_defaults.h> exposes enough parameterization to boot.scr to
+allow for board-agnostic boot.scr content, this document recommends that
+distros generate extlinux.conf rather than boot.scr. extlinux.conf is intended
+to work across multiple bootloaders, whereas boot.scr will only work with
+U-Boot. TODO: document the contract between U-Boot and boot.scr re: which
+environment variables a generic boot.scr may rely upon.
+
+The second of those headers sets up the default environment so that $bootcmd
+is defined in a way that searches attached disks for boot configuration files,
+and executes them if found.
+
+Required Environment Variables
+------------------------------
+
+The U-Boot "syslinux" and "pxe boot" commands require a number of environment
+variables be set. Default values for these variables are often hard-coded into
+CONFIG_EXTRA_ENV_SETTINGS in the board's U-Boot configuration file, so that
+the user doesn't have to configure them.
+
+fdt_addr:
+
+  Mandatory for any system that provides the DTB in HW (e.g. ROM) and wishes
+  to pass that DTB to Linux, rather than loading a DTB from the boot
+  filesystem. Prohibited for any other system.
+
+  If specified a DTB to boot the system must be available at the given
+  address.
+
+fdt_addr_r:
+
+  Mandatory. The location in RAM where the DTB will be loaded or copied to when
+  processing the fdtdir/devicetreedir or fdt/devicetree options in
+  extlinux.conf.
+
+  This is mandatory even when fdt_addr is provided, since extlinux.conf must
+  always be able to provide a DTB which overrides any copy provided by the HW.
+
+  A size of 1MB for the FDT/DTB seems reasonable.
+
+ramdisk_addr_r:
+
+  Mandatory. The location in RAM where the initial ramdisk will be loaded to
+  when processing the initrd option in extlinux.conf.
+
+  It is recommended that this location be highest in RAM out of fdt_addr_,
+  kernel_addr_r, and ramdisk_addr_r, so that the RAM disk can vary in size
+  and use any available RAM.
+
+kernel_addr_r:
+
+  Mandatory. The location in RAM where the kernel will be loaded to when
+  processing the kernel option in the extlinux.conf.
+
+  The kernel should be located within the first 128M of RAM in order for the
+  kernel CONFIG_AUTO_ZRELADDR option to work, which is likely enabled on any
+  distro kernel. Since the kernel will decompress itself to 0x8000 after the
+  start of RAM, kernel_addr_rshould not overlap that area, or the kernel will
+  have to copy itself somewhere else first before decompression.
+
+  A size of 16MB for the kernel is likely adequate.
+
+pxe_addr_r:
+
+  Mandatory. The location in RAM where extlinux.conf will be loaded to prior
+  to processing.
+
+  A size of 1MB for extlinux.conf is more than adequate.
+
+scriptaddr:
+
+  Mandatory, if the boot script is boot.scr rather than extlinux.conf. The
+  location in RAM where boot.scr will be loaded to prior to execution.
+
+  A size of 1MB for extlinux.conf is more than adequate.
+
+For suggestions on memory locations for ARM systems, you must follow the
+guidelines specified in Documentation/arm/Booting in the Linux kernel tree.
+
+For a commented example of setting these values, please see the definition of
+MEM_LAYOUT_ENV_SETTINGS in include/configs/tegra124-common.h.
+
+Boot Target Configuration
+-------------------------
+
+<config_distro_bootcmd.h> defines $bootcmd and many helper command variables
+that automatically search attached disks for boot configuration files and
+execute them. Boards must provide configure <config_distro_bootcmd.h> so that
+it supports the correct set of possible boot device types. To provide this
+configuration, simply define macro BOOT_TARGET_DEVICES prior to including
+<config_distro_bootcmd.h>. For example:
+
+------------------------------------------------------------
+#ifndef CONFIG_SPL_BUILD
+#define BOOT_TARGET_DEVICES(func) \
+        func(MMC, mmc, 1) \
+        func(MMC, mmc, 0) \
+        func(USB, usb, 0) \
+        func(PXE, pxe, na) \
+        func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
+#endif
+------------------------------------------------------------
+
+Each entry in the macro defines a single boot device (e.g. a specific eMMC
+device or SD card) or type of boot device (e.g. USB disk). The parameters to
+the func macro (passed in by the internal implementation of the header) are:
+
+- Upper-case disk type (MMC, SATA, SCSI, IDE, USB, DHCP, PXE).
+- Lower-case disk type (same options as above).
+- ID of the specific disk (MMC only) or ignored for other types.
+
+User Configuration
+==================
+
+Once the user has installed U-Boot, it is expected that the environment will
+be reset to the default values in order to enable $bootcmd and friends, as set
+up by <config_distro_bootcmd.h>. After this, various environment variables may
+be altered to influence the boot process:
+
+boot_targets:
+
+  The list of boot locations searched.
+
+  Example: mmc0, mmc1, usb, pxe
+
+  Entries may be removed or re-ordered in this list to affect the boot order.
+
+boot_prefixes:
+
+  For disk-based booting, the list of directories within a partition that are
+  searched for boot configuration files (extlinux.conf, boot.scr).
+
+  Example: / /boot/
+
+  Entries may be removed or re-ordered in this list to affect the set of
+  directories which are searched.
+
+boot_scripts:
+
+  The name of U-Boot style boot.scr files that $bootcmd searches for.
+
+  Example: boot.scr.uimg boot.scr
+
+  (Typically we expect extlinux.conf to be used, but execution of boot.scr is
+  maintained for backwards-compatibility.)
+
+  Entries may be removed or re-ordered in this list to affect the set of
+  filenames which are supported.
+
+scan_dev_for_extlinux:
+
+  If you want to disable extlinux.conf on all disks, set the value to something
+  innocuous, e.g. setenv scan_dev_for_extlinux true.
+
+scan_dev_for_scripts:
+
+  If you want to disable boot.scr on all disks, set the value to something
+  innocuous, e.g. setenv scan_dev_for_scripts true.
diff --git a/doc/README.splashprepare b/doc/README.splashprepare
index 61b4ec5..a0f0f3c 100644
--- a/doc/README.splashprepare
+++ b/doc/README.splashprepare
@@ -6,3 +6,16 @@
 sequence. It gives the board an opportunity to prepare the splash
 image data before it is processed and sent to the frame buffer by
 U-Boot.  Define your own version to use this feature.
+
+CONFIG_SPLASH_SOURCE
+
+Use the splash_source.c library. This library provides facilities to declare
+board specific splash image locations, routines for loading splash image from
+supported locations, and a way of controlling the selected splash location
+using the "splashsource" environment variable.
+
+splashsource works as follows:
+- If splashsource is set to a supported location name as defined by board code,
+  use that splash location.
+- If splashsource is undefined, use the first splash location as default.
+- If splashsource is set to an unsupported value, do not load a splash screen.
diff --git a/doc/README.standalone b/doc/README.standalone
index e3000ef..659a12f 100644
--- a/doc/README.standalone
+++ b/doc/README.standalone
@@ -5,18 +5,18 @@
    table is allocated and initialized in the jumptable_init() routine
    (common/exports.c). Other routines may also modify the jump table,
    however. The jump table can be accessed as the 'jt' field of the
-   'global_data' structure. The slot numbers for the jump table are
+   'global_data' structure. The struct members for the jump table are
    defined in the <include/exports.h> header. E.g., to substitute the
    malloc() and free() functions that will be available to standalone
    applications, one should do the following:
 
 	DECLARE_GLOBAL_DATA_PTR;
 
-	gd->jt[XF_malloc]	= my_malloc;
-	gd->jt[XF_free]		= my_free;
+	gd->jt->malloc	= my_malloc;
+	gd->jt->free = my_free;
 
-   Note that the pointers to the functions all have 'void *' type and
-   thus the compiler cannot perform type checks on these assignments.
+   Note that the pointers to the functions are real function pointers
+   so the compiler can perform type checks on these assignments.
 
 2. The pointer to the jump table is passed to the application in a
    machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II
@@ -65,27 +65,46 @@
    => tftp 0x40000 hello_world.bin
    => go 0x40004
 
-5. To export some additional function foobar(), the following steps
+5. To export some additional function long foobar(int i,char c), the following steps
    should be undertaken:
 
    - Append the following line at the end of the include/_exports.h
      file:
 
-	EXPORT_FUNC(foobar)
+	EXPORT_FUNC(foobar, long, foobar, int, char)
+
+	Parameters to EXPORT_FUNC:
+	 - the first parameter is the function that is exported (default implementation)
+	 - the second parameter is the return value type
+	 - the third  parameter is the name of the member in struct jt_funcs
+	   this is also the name that the standalone application will used.
+	   the rest of the parameters are the function arguments
 
    - Add the prototype for this function to the include/exports.h
      file:
 
-	void foobar(void);
+	long foobar(int i, char c);
 
-   - Add the initialization of the jump table slot wherever
-     appropriate (most likely, to the jumptable_init() function):
+	Initialization with the default implementation is done in jumptable_init()
 
-	gd->jt[XF_foobar] = foobar;
+	You can override the default implementation using:
+
+	gd->jt->foobar = another_foobar;
+
+	The signature of another_foobar must then match the declaration of foobar.
 
    - Increase the XF_VERSION value by one in the include/exports.h
      file
 
+   - If you want to export a function which depends on a CONFIG_XXX
+	use 2 lines like this:
+	#ifdef CONFIG_FOOBAR
+		EXPORT_FUNC(foobar, long, foobar, int, char)
+	#else
+		EXPORT_FUNC(dummy, void, foobar, void)
+	#endif
+
+
 6. The code for exporting the U-Boot functions to applications is
    mostly machine-independent. The only places written in assembly
    language are stub functions that perform the jump through the jump
diff --git a/doc/README.uniphier b/doc/README.uniphier
new file mode 100644
index 0000000..aaeb50c
--- /dev/null
+++ b/doc/README.uniphier
@@ -0,0 +1,85 @@
+U-Boot for UniPhier SoC family
+==============================
+
+
+Tested toolchains
+-----------------
+
+ (a) Ubuntu packages  (CROSS_COMPILE=arm-linux-gnueabi-)
+
+  If you are building U-Boot on Ubuntu, its standard package is recommended.
+  You can install it as follows:
+
+    $ sudo apt-get install gcc-arm-linux-gnueabi-
+
+ (b) Linaro compilers  (CROSS_COMPILE=arm-linux-gnueabihf-)
+
+  You can download pre-built toolchains from:
+
+    http://www.linaro.org/downloads/
+
+ (c) kernel.org compilers  (CROSS_COMPILE=arm-unknown-linux-gnueabi-)
+
+  You can download pre-built toolchains from:
+
+    ftp://www.kernel.org/pub/tools/crosstool/files/bin/
+
+
+Compile the source
+------------------
+
+PH1-Pro4:
+    $ make ph1_pro4_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+PH1-LD4:
+    $ make ph1_ld4_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+PH1-sLD8:
+    $ make ph1_sld8_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+You may wish to change the "CROSS_COMPILE=arm-linux-gnueabi-"
+to use your favorite compiler.
+
+
+Burn U-Boot images to NAND
+--------------------------
+
+Write two files to the NAND device as follows:
+ - spl/u-boot-spl.bin at the offset address 0x00000000
+ - u-boot-dtb.img     at the offset address 0x00010000
+
+If a TFTP server is available, the images can be easily updated.
+Just copy the u-boot-spl.bin and u-boot-dtb.img to the TFTP public directory,
+and then run the following command at the U-Boot command line:
+
+  => run nandupdate
+
+
+UniPhier specific commands
+--------------------------
+
+ - pinmon (enabled by CONFIG_CMD_PINMON)
+     shows the boot mode pins that has been latched at the power-on reset
+
+ - ddrphy (enabled by CONFIG_CMD_DDRPHY_DUMP)
+     shows the DDR PHY parameters set by the PHY training
+
+
+Supported devices
+-----------------
+
+ - UART (on-chip)
+ - NAND
+ - USB (2.0)
+ - LAN (on-board SMSC9118)
+ - I2C
+ - EEPROM (connected to the on-board I2C bus)
+ - Support card (SRAM, NOR flash, some peripherals)
+
+
+--
+Masahiro Yamada <yamada.m@jp.panasonic.com>
+Feb. 2015
diff --git a/doc/README.x86 b/doc/README.x86
index 7df8cc5..fb87682 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -18,11 +18,11 @@
 on other x86 boards since coreboot deals with most of the low-level details.
 
 U-Boot also supports booting directly from x86 reset vector without coreboot,
-aka raw support or bare support. Currently Link and Intel Crown Bay board
-support running U-Boot 'bare metal'.
+aka raw support or bare support. Currently Link, Intel Crown Bay, Intel
+Minnowboard Max and Intel Galileo support running U-Boot 'bare metal'.
 
-As for loading OS, U-Boot supports directly booting a 32-bit or 64-bit Linux
-kernel as part of a FIT image. It also supports a compressed zImage.
+As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit
+Linux kernel as part of a FIT image. It also supports a compressed zImage.
 
 Build Instructions
 ------------------
@@ -47,13 +47,15 @@
 to point to a new board. You can also change the Cache-As-RAM (CAR) related
 settings here if the default values do not fit your new board.
 
-Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
+Building a ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
 little bit tricky, as generally it requires several binary blobs which are not
 shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is
 not turned on by default in the U-Boot source tree. Firstly, you need turn it
-on by uncommenting the following line in the main U-Boot Makefile:
+on by enabling the ROM build:
 
-# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+$ export BUILD_ROM=y
+
+This tells the Makefile to build u-boot.rom as a target.
 
 Link-specific instructions:
 
@@ -108,6 +110,50 @@
 $ make crownbay_defconfig
 $ make all
 
+Intel Minnowboard Max instructions:
+
+This uses as FSP as with Crown Bay, except it is for the Atom E3800 series.
+Download this and get the .fd file (BAYTRAIL_FSP_GOLD_003_16-SEP-2014.fd at
+the time of writing). Put it in the board directory:
+board/intel/minnowmax/fsp.bin
+
+Obtain the VGA RAM (Vga.dat at the time of writing) and put it into the same
+directory: board/intel/minnowmax/vga.bin
+
+You still need two more binary blobs. These come from the sample SPI image
+provided in the FSP (SPI.bin at the time of writing).
+
+Use ifdtool in the U-Boot tools directory to extract the images from that
+file, for example:
+
+   $ ./tools/ifdtool -x BayleyBay/SPI.bin
+   $ cp flashregion_2_intel_me.bin board/intel/minnowmax/me.bin
+   $ cp flashregion_0_flashdescriptor.bin board/intel/minnowmax/descriptor.bin
+
+Now you can build U-Boot and obtain u-boot.rom
+
+$ make minnowmax_defconfig
+$ make all
+
+Intel Galileo instructions:
+
+Only one binary blob is needed for Remote Management Unit (RMU) within Intel
+Quark SoC. Not like FSP, U-Boot does not call into the binary. The binary is
+needed by the Quark SoC itself.
+
+You can get the binary blob from Quark Board Support Package from Intel website:
+
+* ./QuarkSocPkg/QuarkNorthCluster/Binary/QuarkMicrocode/RMU.bin
+
+Rename the file and put it to the board directory by:
+
+   $ cp RMU.bin board/intel/galileo/rmu.bin
+
+Now you can build U-Boot and obtain u-boot.rom
+
+$ make galileo_defconfig
+$ make all
+
 Test with coreboot
 ------------------
 For testing U-Boot as the coreboot payload, there are things that need be paid
@@ -126,11 +172,21 @@
 symbol address of _start (in arch/x86/cpu/start.S).
 
 If you want to use ELF as the coreboot payload, change U-Boot configuration to
-use CONFIG_OF_EMBED.
+use CONFIG_OF_EMBED instead of CONFIG_OF_SEPARATE.
+
+To enable video you must enable these options in coreboot:
+
+   - Set framebuffer graphics resolution (1280x1024 32k-color (1:5:5))
+   - Keep VESA framebuffer
+
+At present it seems that for Minnowboard Max, coreboot does not pass through
+the video information correctly (it always says the resolution is 0x0). This
+works correctly for link though.
+
 
 CPU Microcode
 -------------
-Modern CPU usually requires a special bit stream called microcode [5] to be
+Modern CPUs usually require a special bit stream called microcode [5] to be
 loaded on the processor after power up in order to function properly. U-Boot
 has already integrated these as hex dumps in the source tree.
 
@@ -162,6 +218,69 @@
 	 mode to use. U-Boot sets up some reasonable values but you can
 	 adjust then with this command.
 
+Development Flow
+----------------
+These notes are for those who want to port U-Boot to a new x86 platform.
+
+Since x86 CPUs boot from SPI flash, a SPI flash emulator is a good investment.
+The Dediprog em100 can be used on Linux. The em100 tool is available here:
+
+   http://review.coreboot.org/p/em100.git
+
+On Minnowboard Max the following command line can be used:
+
+   sudo em100 -s -p LOW -d u-boot.rom -c W25Q64DW -r
+
+A suitable clip for connecting over the SPI flash chip is here:
+
+   http://www.dediprog.com/pd/programmer-accessories/EM-TC-8
+
+This allows you to override the SPI flash contents for development purposes.
+Typically you can write to the em100 in around 1200ms, considerably faster
+than programming the real flash device each time. The only important
+limitation of the em100 is that it only supports SPI bus speeds up to 20MHz.
+This means that images must be set to boot with that speed. This is an
+Intel-specific feature - e.g. tools/ifttool has an option to set the SPI
+speed in the SPI descriptor region.
+
+If your chip/board uses an Intel Firmware Support Package (FSP) it is fairly
+easy to fit it in. You can follow the Minnowboard Max implementation, for
+example. Hopefully you will just need to create new files similar to those
+in arch/x86/cpu/baytrail which provide Bay Trail support.
+
+If you are not using an FSP you have more freedom and more responsibility.
+The ivybridge support works this way, although it still uses a ROM for
+graphics and still has binary blobs containing Intel code. You should aim to
+support all important peripherals on your platform including video and storage.
+Use the device tree for configuration where possible.
+
+For the microcode you can create a suitable device tree file using the
+microcode tool:
+
+  ./tools/microcode-tool -d microcode.dat create <model>
+
+or if you only have header files and not the full Intel microcode.dat database:
+
+  ./tools/microcode-tool -H BAY_TRAIL_FSP_KIT/Microcode/M0130673322.h \
+	-H BAY_TRAIL_FSP_KIT/Microcode/M0130679901.h \
+	create all
+
+These are written to arch/x86/dts/microcode/ by default.
+
+Note that it is possible to just add the micrcode for your CPU if you know its
+model. U-Boot prints this information when it starts
+
+   CPU: x86_64, vendor Intel, device 30673h
+
+so here we can use the M0130673322 file.
+
+If you platform can display POST codes on two little 7-segment displays on
+the board, then you can use post_code() calls from C or assembler to monitor
+boot progress. This can be good for debugging.
+
+If not, you can try to get serial working as early as possible. The early
+debug serial port may be useful here. See setup_early_uart() for an example.
+
 TODO List
 ---------
 - Audio
diff --git a/doc/device-tree-bindings/exynos/emmc-reset.txt b/doc/device-tree-bindings/exynos/emmc-reset.txt
new file mode 100644
index 0000000..5e7ba26
--- /dev/null
+++ b/doc/device-tree-bindings/exynos/emmc-reset.txt
@@ -0,0 +1,15 @@
+* Samsung eMMC reset
+
+Some exynos boards require special handling of nRESET_OUT line for eMMC memory
+to perform complete reboot.
+
+Required properties:
+- compatible: should be "samsung,emmc-reset"
+- reset-gpio: gpio chip for eMMC reset.
+
+Example:
+
+emmc-reset {
+        compatible = "samsung,emmc-reset";
+        reset-gpio = <&gpk1 2 0>;
+};
diff --git a/doc/device-tree-bindings/gpio/gpio-samsung.txt b/doc/device-tree-bindings/gpio/gpio-samsung.txt
new file mode 100644
index 0000000..5375625
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/gpio-samsung.txt
@@ -0,0 +1,41 @@
+Samsung Exynos4 GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "samsung,exynos4-gpio>".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- #gpio-cells: Should be 4. The syntax of the gpio specifier used by client nodes
+  should be the following with values derived from the SoC user manual.
+     <[phandle of the gpio controller node]
+      [pin number within the gpio controller]
+      [mux function]
+      [flags and pull up/down]
+      [drive strength]>
+
+  Values for gpio specifier:
+  - Pin number: is a value between 0 to 7.
+  - Flags and Pull Up/Down: 0 - Pull Up/Down Disabled.
+                            1 - Pull Down Enabled.
+                            3 - Pull Up Enabled.
+          Bit 16 (0x00010000) - Input is active low.
+  - Drive Strength: 0 - 1x,
+                    1 - 3x,
+                    2 - 2x,
+                    3 - 4x
+
+- gpio-controller: Specifies that the node is a gpio controller.
+- #address-cells: should be 1.
+- #size-cells: should be 1.
+
+Example:
+
+	gpa0: gpio-controller@11400000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "samsung,exynos4-gpio";
+		reg = <0x11400000 0x20>;
+		#gpio-cells = <4>;
+		gpio-controller;
+	};
diff --git a/doc/device-tree-bindings/gpio/gpio.txt b/doc/device-tree-bindings/gpio/gpio.txt
new file mode 100644
index 0000000..f7a158d
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/gpio.txt
@@ -0,0 +1,212 @@
+Specifying GPIO information for devices
+============================================
+
+1) gpios property
+-----------------
+
+Nodes that makes use of GPIOs should specify them using one or more
+properties, each containing a 'gpio-list':
+
+	gpio-list ::= <single-gpio> [gpio-list]
+	single-gpio ::= <gpio-phandle> <gpio-specifier>
+	gpio-phandle : phandle to gpio controller node
+	gpio-specifier : Array of #gpio-cells specifying specific gpio
+			 (controller specific)
+
+GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
+of this GPIO for the device. While a non-existent <name> is considered valid
+for compatibility reasons (resolving to the "gpios" property), it is not allowed
+for new bindings.
+
+GPIO properties can contain one or more GPIO phandles, but only in exceptional
+cases should they contain more than one. If your device uses several GPIOs with
+distinct functions, reference each of them under its own property, giving it a
+meaningful name. The only case where an array of GPIOs is accepted is when
+several GPIOs serve the same function (e.g. a parallel data line).
+
+The exact purpose of each gpios property must be documented in the device tree
+binding of the device.
+
+The following example could be used to describe GPIO pins used as device enable
+and bit-banged data signals:
+
+	gpio1: gpio1 {
+		gpio-controller
+		 #gpio-cells = <2>;
+	};
+	gpio2: gpio2 {
+		gpio-controller
+		 #gpio-cells = <1>;
+	};
+	[...]
+
+	enable-gpios = <&gpio2 2>;
+	data-gpios = <&gpio1 12 0>,
+		     <&gpio1 13 0>,
+		     <&gpio1 14 0>,
+		     <&gpio1 15 0>;
+
+Note that gpio-specifier length is controller dependent.  In the
+above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
+only uses one.
+
+gpio-specifier may encode: bank, pin position inside the bank,
+whether pin is open-drain and whether pin is logically inverted.
+Exact meaning of each specifier cell is controller specific, and must
+be documented in the device tree binding for the device. Use the macros
+defined in include/dt-bindings/gpio/gpio.h whenever possible:
+
+Example of a node using GPIOs:
+
+	node {
+		enable-gpios = <&qe_pio_e 18 GPIO_ACTIVE_HIGH>;
+	};
+
+GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
+GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
+
+1.1) GPIO specifier best practices
+----------------------------------
+
+A gpio-specifier should contain a flag indicating the GPIO polarity; active-
+high or active-low. If it does, the following best practices should be
+followed:
+
+The gpio-specifier's polarity flag should represent the physical level at the
+GPIO controller that achieves (or represents, for inputs) a logically asserted
+value at the device. The exact definition of logically asserted should be
+defined by the binding for the device. If the board inverts the signal between
+the GPIO controller and the device, then the gpio-specifier will represent the
+opposite physical level than the signal at the device's pin.
+
+When the device's signal polarity is configurable, the binding for the
+device must either:
+
+a) Define a single static polarity for the signal, with the expectation that
+any software using that binding would statically program the device to use
+that signal polarity.
+
+The static choice of polarity may be either:
+
+a1) (Preferred) Dictated by a binding-specific DT property.
+
+or:
+
+a2) Defined statically by the DT binding itself.
+
+In particular, the polarity cannot be derived from the gpio-specifier, since
+that would prevent the DT from separately representing the two orthogonal
+concepts of configurable signal polarity in the device, and possible board-
+level signal inversion.
+
+or:
+
+b) Pick a single option for device signal polarity, and document this choice
+in the binding. The gpio-specifier should represent the polarity of the signal
+(at the GPIO controller) assuming that the device is configured for this
+particular signal polarity choice. If software chooses to program the device
+to generate or receive a signal of the opposite polarity, software will be
+responsible for correctly interpreting (inverting) the GPIO signal at the GPIO
+controller.
+
+2) gpio-controller nodes
+------------------------
+
+Every GPIO controller node must contain both an empty "gpio-controller"
+property, and a #gpio-cells integer property, which indicates the number of
+cells in a gpio-specifier.
+
+Example of two SOC GPIO banks defined as gpio-controller nodes:
+
+	qe_pio_a: gpio-controller@1400 {
+		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	qe_pio_e: gpio-controller@1460 {
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+2.1) gpio- and pin-controller interaction
+-----------------------------------------
+
+Some or all of the GPIOs provided by a GPIO controller may be routed to pins
+on the package via a pin controller. This allows muxing those pins between
+GPIO and other functions.
+
+It is useful to represent which GPIOs correspond to which pins on which pin
+controllers. The gpio-ranges property described below represents this, and
+contains information structures as follows:
+
+	gpio-range-list ::= <single-gpio-range> [gpio-range-list]
+	single-gpio-range ::= <numeric-gpio-range> | <named-gpio-range>
+	numeric-gpio-range ::=
+			<pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
+	named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>'
+	pinctrl-phandle : phandle to pin controller node
+	gpio-base : Base GPIO ID in the GPIO controller
+	pinctrl-base : Base pinctrl pin ID in the pin controller
+	count : The number of GPIOs/pins in this range
+
+The "pin controller node" mentioned above must conform to the bindings
+described in ../pinctrl/pinctrl-bindings.txt.
+
+In case named gpio ranges are used (ranges with both <pinctrl-base> and
+<count> set to 0), the property gpio-ranges-group-names contains one string
+for every single-gpio-range in gpio-ranges:
+	gpiorange-names-list ::= <gpiorange-name> [gpiorange-names-list]
+	gpiorange-name : Name of the pingroup associated to the GPIO range in
+			the respective pin controller.
+
+Elements of gpiorange-names-list corresponding to numeric ranges contain
+the empty string. Elements of gpiorange-names-list corresponding to named
+ranges contain the name of a pin group defined in the respective pin
+controller. The number of pins/GPIOs in the range is the number of pins in
+that pin group.
+
+Previous versions of this binding required all pin controller nodes that
+were referenced by any gpio-ranges property to contain a property named
+#gpio-range-cells with value <3>. This requirement is now deprecated.
+However, that property may still exist in older device trees for
+compatibility reasons, and would still be required even in new device
+trees that need to be compatible with older software.
+
+Example 1:
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+		gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
+	};
+
+Here, a single GPIO controller has GPIOs 0..9 routed to pin controller
+pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's
+pins 50..59.
+
+Example 2:
+
+	gpio_pio_i: gpio-controller@14B0 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1480 0x18>;
+		gpio-controller;
+		gpio-ranges =			<&pinctrl1 0 20 10>,
+						<&pinctrl2 10 0 0>,
+						<&pinctrl1 15 0 10>,
+						<&pinctrl2 25 0 0>;
+		gpio-ranges-group-names =	"",
+						"foo",
+						"",
+						"bar";
+	};
+
+Here, three GPIO ranges are defined wrt. two pin controllers. pinctrl1 GPIO
+ranges are defined using pin numbers whereas the GPIO ranges wrt. pinctrl2
+are named "foo" and "bar".
diff --git a/doc/device-tree-bindings/gpio/nvidia,tegra20-gpio.txt b/doc/device-tree-bindings/gpio/nvidia,tegra20-gpio.txt
new file mode 100644
index 0000000..023c952
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/nvidia,tegra20-gpio.txt
@@ -0,0 +1,40 @@
+NVIDIA Tegra GPIO controller
+
+Required properties:
+- compatible : "nvidia,tegra<chip>-gpio"
+- reg : Physical base address and length of the controller's registers.
+- interrupts : The interrupt outputs from the controller. For Tegra20,
+  there should be 7 interrupts specified, and for Tegra30, there should
+  be 8 interrupts specified.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+      Valid combinations are 1, 2, 3, 4, 8.
+- interrupt-controller : Marks the device node as an interrupt controller.
+
+Example:
+
+gpio: gpio@6000d000 {
+	compatible = "nvidia,tegra20-gpio";
+	reg = < 0x6000d000 0x1000 >;
+	interrupts = < 0 32 0x04
+		       0 33 0x04
+		       0 34 0x04
+		       0 35 0x04
+		       0 55 0x04
+		       0 87 0x04
+		       0 89 0x04 >;
+	#gpio-cells = <2>;
+	gpio-controller;
+	#interrupt-cells = <2>;
+	interrupt-controller;
+};
diff --git a/doc/device-tree-bindings/i2c/i2c.txt b/doc/device-tree-bindings/i2c/i2c.txt
new file mode 100644
index 0000000..ea918dd
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/i2c.txt
@@ -0,0 +1,28 @@
+U-Boot I2C
+----------
+
+U-Boot's I2C model has the concept of an offset within a chip (I2C target
+device). The offset can be up to 4 bytes long, but is normally 1 byte,
+meaning that offsets from 0 to 255 are supported by the chip. This often
+corresponds to register numbers.
+
+Apart from the controller-specific I2C bindings, U-Boot supports a special
+property which allows the chip offset length to be selected.
+
+Optional properties:
+- u-boot,i2c-offset-len - length of chip offset in bytes. If omitted the
+    default value of 1 is used.
+
+
+Example
+-------
+
+i2c4: i2c@12ca0000 {
+	cros-ec@1e {
+		reg = <0x1e>;
+		compatible = "google,cros-ec";
+		i2c-max-frequency = <100000>;
+		u-boot,i2c-offset-len = <0>;
+		ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
+	};
+};
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index eafa825..f83264d 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -363,6 +363,10 @@
 in your ofdata_to_platdata (or probe) method to allocate the required memory,
 and you should free it in the remove method.
 
+The driver model tree is intended to mirror that of the device tree. The
+root driver is at device tree offset 0 (the root node, '/'), and its
+children are the children of the root node.
+
 
 Declaring Uclasses
 ------------------
@@ -384,12 +388,12 @@
 U-Boot numbers devices from 0 in many situations, such as in the command
 line for I2C and SPI buses, and the device names for serial ports (serial0,
 serial1, ...). Driver model supports this numbering and permits devices
-to be locating by their 'sequence'. This numbering unique identifies a
+to be locating by their 'sequence'. This numbering uniquely identifies a
 device in its uclass, so no two devices within a particular uclass can have
 the same sequence number.
 
 Sequence numbers start from 0 but gaps are permitted. For example, a board
-may have I2C buses 0, 1, 4, 5 but no 2 or 3. The choice of how devices are
+may have I2C buses 1, 4, 5 but no 0, 2 or 3. The choice of how devices are
 numbered is up to a particular board, and may be set by the SoC in some
 cases. While it might be tempting to automatically renumber the devices
 where there are gaps in the sequence, this can lead to confusion and is
@@ -399,7 +403,7 @@
 device will be automatically allocated the next available sequence number.
 
 To specify the sequence number in the device tree an alias is typically
-used.
+used. Make sure that the uclass has the DM_UC_FLAG_SEQ_ALIAS flag set.
 
 aliases {
 	serial2 = "/serial@22230000";
@@ -409,43 +413,18 @@
 ("/serial@22230000") will be given sequence number 2. Any command or driver
 which requests serial device 2 will obtain this device.
 
-Some devices represent buses where the devices on the bus are numbered or
-addressed. For example, SPI typically numbers its slaves from 0, and I2C
-uses a 7-bit address. In these cases the 'reg' property of the subnode is
-used, for example:
+More commonly you can use node references, which expand to the full path:
 
-{
-	aliases {
-		spi2 = "/spi@22300000";
-	};
+aliases {
+	serial2 = &serial_2;
+};
+...
+serial_2: serial@22230000 {
+...
+};
 
-	spi@22300000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		spi-flash@0 {
-			reg = <0>;
-			...
-		}
-		eeprom@1 {
-			reg = <1>;
-		};
-	};
-
-In this case we have a SPI bus with two slaves at 0 and 1. The SPI bus
-itself is numbered 2. So we might access the SPI flash with:
-
-	sf probe 2:0
-
-and the eeprom with
-
-	sspi 2:1 32 ef
-
-These commands simply need to look up the 2nd device in the SPI uclass to
-find the right SPI bus. Then, they look at the children of that bus for the
-right sequence number (0 or 1 in this case).
-
-Typically the alias method is used for top-level nodes and the 'reg' method
-is used only for buses.
+The alias resolves to the same string in this case, but this version is
+easier to read.
 
 Device sequence numbers are resolved when a device is probed. Before then
 the sequence number is only a request which may or may not be honoured,
@@ -462,11 +441,18 @@
 the bus provides some sort of transport or translation that makes it
 possible to talk to the devices on the bus.
 
-Driver model provides a few useful features to help with implementing
-buses. Firstly, a bus can request that its children store some 'parent
-data' which can be used to keep track of child state. Secondly, the bus can
-define methods which are called when a child is probed or removed. This is
-similar to the methods the uclass driver provides.
+Driver model provides some useful features to help with implementing buses.
+Firstly, a bus can request that its children store some 'parent data' which
+can be used to keep track of child state. Secondly, the bus can define
+methods which are called when a child is probed or removed. This is similar
+to the methods the uclass driver provides. Thirdly, per-child platform data
+can be provided to specify things like the child's address on the bus. This
+persists across child probe()/remove() cycles.
+
+For consistency and ease of implementation, the bus uclass can specify the
+per-child platform data, so that it can be the same for all children of buses
+in that uclass. There are also uclass methods which can be called when
+children are bound and probed.
 
 Here an explanation of how a bus fits with a uclass may be useful. Consider
 a USB bus with several devices attached to it, each from a different (made
@@ -481,15 +467,23 @@
 The bus device wants to store this address and some other information such
 as the bus speed for each device.
 
-To achieve this, the bus device can use dev->parent_priv in each of its
-three children. This can be auto-allocated if the bus driver has a non-zero
-value for per_child_auto_alloc_size. If not, then the bus device can
-allocate the space itself before the child device is probed.
+To achieve this, the bus device can use dev->parent_platdata in each of its
+three children. This can be auto-allocated if the bus driver (or bus uclass)
+has a non-zero value for per_child_platdata_auto_alloc_size. If not, then
+the bus device or uclass can allocate the space itself before the child
+device is probed.
 
 Also the bus driver can define the child_pre_probe() and child_post_remove()
 methods to allow it to do some processing before the child is activated or
 after it is deactivated.
 
+Similarly the bus uclass can define the child_post_bind() method to obtain
+the per-child platform data from the device tree and set it up for the child.
+The bus uclass can also provide a child_pre_probe() method. Very often it is
+the bus uclass that controls these features, since it avoids each driver
+having to do the same processing. Of course the driver can still tweak and
+override these activities.
+
 Note that the information that controls this behaviour is in the bus's
 driver, not the child's. In fact it is possible that child has no knowledge
 that it is connected to a bus. The same child device may even be used on two
@@ -516,7 +510,8 @@
 The uclass for the device can also contain data private to that uclass.
 But note that each device on the bus may be a memeber of a different
 uclass, and this data has nothing to do with the child data for each child
-on the bus.
+on the bus. It is the bus' uclass that controls the child with respect to
+the bus.
 
 
 Driver Lifecycle
diff --git a/doc/driver-model/spi-howto.txt b/doc/driver-model/spi-howto.txt
index 719dbd5..ee4abf4 100644
--- a/doc/driver-model/spi-howto.txt
+++ b/doc/driver-model/spi-howto.txt
@@ -3,7 +3,8 @@
 
 Here is a rough step-by-step guide. It is based around converting the
 exynos SPI driver to driver model (DM) and the example code is based
-around U-Boot v2014.10-rc2 (commit be9f643).
+around U-Boot v2014.10-rc2 (commit be9f643). This has been updated for
+v2015.04.
 
 It is quite long since it includes actual code examples.
 
@@ -39,8 +40,8 @@
 
 Add these to your board config:
 
-#define CONFIG_DM_SPI
-#define CONFIG_DM_SPI_FLASH
+CONFIG_DM_SPI
+CONFIG_DM_SPI_FLASH
 
 
 2. Add the skeleton
@@ -262,8 +263,8 @@
 	.platdata = &platdata_spi0,
 };
 
-You will unfortunately need to put the struct into a header file in this
-case so that your board file can use it.
+You will unfortunately need to put the struct definition into a header file
+in this case so that your board file can use it.
 
 
 9. Add the device private data
@@ -592,3 +593,36 @@
 
 You can use 'tools/patman/patman' to prepare, check and send patches for
 your work. See the README for details.
+
+20. A little note about SPI uclass features:
+
+The SPI uclass keeps some information about each device 'dev' on the bus:
+
+   struct dm_spi_slave_platdata - this is device_get_parent_platdata(dev)
+		This is where the chip select number is stored, along with
+		the default bus speed and mode. It is automatically read
+		from the device tree in spi_child_post_bind(). It must not
+		be changed at run-time after being set up because platform
+		data is supposed to be immutable at run-time.
+   struct spi_slave - this is device_get_parentdata(dev)
+		Already mentioned above. It holds run-time information about
+		the device.
+
+There are also some SPI uclass methods that get called behind the scenes:
+
+   spi_post_bind() - called when a new bus is bound
+		This scans the device tree for devices on the bus, and binds
+		each one. This in turn causes spi_child_post_bind() to be
+		called for each, which reads the device tree information
+		into the parent (per-child) platform data.
+   spi_child_post_bind() - called when a new child is bound
+		As mentioned above this reads the device tree information
+		into the per-child platform data
+   spi_child_pre_probe() - called before a new child is probed
+		This sets up the mode and speed in struct spi_slave by
+		copying it from the parent's platform data for this child.
+		It also sets the 'dev' pointer, needed to permit passing
+		'struct spi_slave' around the place without needing a
+		separate 'struct udevice' pointer.
+
+The above housekeeping makes it easier to write your SPI driver.
diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt
index b47ce73..427ea49 100644
--- a/doc/uImage.FIT/source_file_format.txt
+++ b/doc/uImage.FIT/source_file_format.txt
@@ -159,17 +159,17 @@
   - description : Textual description of the component sub-image
   - type : Name of component sub-image type, supported types are:
     "standalone", "kernel", "ramdisk", "firmware", "script", "filesystem",
-    "flat_dt" and others (see uimage_type in common/images.c).
+    "flat_dt" and others (see uimage_type in common/image.c).
   - data : Path to the external file which contains this node's binary data.
   - compression : Compression used by included data. Supported compressions
     are "gzip" and "bzip2". If no compression is used compression property
     should be set to "none".
 
   Conditionally mandatory property:
-  - os : OS name, mandatory for type="kernel", valid OS names are: "openbsd",
-    "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix", "solaris", "irix",
-    "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx", "u_boot",
-    "rtems", "unity", "integrity".
+  - os : OS name, mandatory for types "kernel" and "ramdisk". Valid OS names
+    are: "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix",
+    "solaris", "irix", "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx",
+    "u_boot", "rtems", "unity", "integrity".
   - arch : Architecture name, mandatory for types: "standalone", "kernel",
     "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha",
     "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc",
diff --git a/doc/uImage.FIT/verified-boot.txt b/doc/uImage.FIT/verified-boot.txt
index 3c83fbc..e639e7a 100644
--- a/doc/uImage.FIT/verified-boot.txt
+++ b/doc/uImage.FIT/verified-boot.txt
@@ -64,7 +64,7 @@
 
 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
+crypto provided by some modern SOCs. If the public key can be changed, then
 the verification is worthless.
 
 
@@ -87,7 +87,7 @@
 
 Flattened Image Tree (FIT)
 --------------------------
-The FIT format is alreay widely used in U-Boot. It is a flattened device
+The FIT format is already 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.
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 128736d..dcce532 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -2,6 +2,8 @@
 
 source "drivers/core/Kconfig"
 
+source "drivers/demo/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
@@ -48,4 +50,6 @@
 
 source "drivers/crypto/Kconfig"
 
+source "drivers/thermal/Kconfig"
+
 endmenu
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index d2799dc..f0d6110 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -2,5 +2,51 @@
 	bool "Enable Driver Model"
 	depends on !SPL_BUILD
 	help
-	  This config option enables Driver Model.
-	  To use legacy drivers, say N.
+	  This config option enables Driver Model. This brings in the core
+	  support, including scanning of platform data on start-up. If
+	  CONFIG_OF_CONTROL is enabled, the device tree will be scanned also
+	  when available.
+
+config SPL_DM
+	bool "Enable Driver Model for SPL"
+	depends on DM && SPL
+	help
+	  Enable driver model in SPL. You will need to provide a
+	  suitable malloc() implementation. If you are not using the
+	  full malloc() enabled by CONFIG_SYS_SPL_MALLOC_START,
+	  consider using CONFIG_SYS_MALLOC_SIMPLE. In that case you
+	  must provide CONFIG_SYS_MALLOC_F_LEN to set the size.
+	  In most cases driver model will only allocate a few uclasses
+	  and devices in SPL, so 1KB should be enable. See
+	  CONFIG_SYS_MALLOC_F_LEN for more details on how to enable it.
+
+config DM_WARN
+	bool "Enable warnings in driver model"
+	help
+	  The dm_warn() function can use up quite a bit of space for its
+	  strings. By default this is disabled for SPL builds to save space.
+	  This will cause dm_warn() to be compiled out - it will do nothing
+	  when called.
+	depends on DM
+	default y if !SPL_BUILD
+	default n if SPL_BUILD
+
+config DM_DEVICE_REMOVE
+	bool "Support device removal"
+	help
+	  We can save some code space by dropping support for removing a
+	  device. This is not normally required in SPL, so by default this
+	  option is disabled for SPL.
+	depends on DM
+	default y if !SPL_BUILD
+	default n if SPL_BUILD
+
+config DM_STDIO
+	bool "Support stdio registration"
+	help
+	  Normally serial drivers register with stdio so that they can be used
+	  as normal output devices. In SPL we don't normally use stdio, so
+	  we can omit this feature.
+	depends on DM
+	default y if !SPL_BUILD
+	default n if SPL_BUILD
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 8fc6b71..3a5f48d 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -88,6 +88,14 @@
 	if (ret)
 		return ret;
 
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
+	if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+		free(dev->parent_platdata);
+		dev->parent_platdata = NULL;
+	}
 	ret = uclass_unbind_device(dev);
 	if (ret)
 		return ret;
@@ -111,10 +119,6 @@
 		free(dev->priv);
 		dev->priv = NULL;
 	}
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		free(dev->platdata);
-		dev->platdata = NULL;
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		free(dev->uclass_priv);
@@ -122,6 +126,10 @@
 	}
 	if (dev->parent) {
 		size = dev->parent->driver->per_child_auto_alloc_size;
+		if (!size) {
+			size = dev->parent->uclass->uc_drv->
+					per_child_auto_alloc_size;
+		}
 		if (size) {
 			free(dev->parent_priv);
 			dev->parent_priv = NULL;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 963b16f..73c3e07 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -53,27 +53,47 @@
 	dev->driver = drv;
 	dev->uclass = uc;
 
-	/*
-	 * For some devices, such as a SPI or I2C bus, the 'reg' property
-	 * is a reasonable indicator of the sequence number. But if there is
-	 * an alias, we use that in preference. In any case, this is just
-	 * a 'requested' sequence, and will be resolved (and ->seq updated)
-	 * when the device is probed.
-	 */
 	dev->seq = -1;
-#ifdef CONFIG_OF_CONTROL
-	dev->req_seq = fdtdec_get_int(gd->fdt_blob, of_offset, "reg", -1);
-	if (!IS_ERR_VALUE(dev->req_seq))
-		dev->req_seq &= INT_MAX;
-	if (uc->uc_drv->name && of_offset != -1) {
-		fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name, of_offset,
-				     &dev->req_seq);
-	}
-#else
 	dev->req_seq = -1;
+#ifdef CONFIG_OF_CONTROL
+	/*
+	 * Some devices, such as a SPI bus, I2C bus and serial ports are
+	 * numbered using aliases.
+	 *
+	 * This is just a 'requested' sequence, and will be
+	 * resolved (and ->seq updated) when the device is probed.
+	 */
+	if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
+		if (uc->uc_drv->name && of_offset != -1) {
+			fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name,
+					     of_offset, &dev->req_seq);
+		}
+	}
 #endif
-	if (!dev->platdata && drv->platdata_auto_alloc_size)
+	if (!dev->platdata && drv->platdata_auto_alloc_size) {
 		dev->flags |= DM_FLAG_ALLOC_PDATA;
+		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
+		if (!dev->platdata) {
+			ret = -ENOMEM;
+			goto fail_alloc1;
+		}
+	}
+	if (parent) {
+		int size = parent->driver->per_child_platdata_auto_alloc_size;
+
+		if (!size) {
+			size = parent->uclass->uc_drv->
+					per_child_platdata_auto_alloc_size;
+		}
+		if (size) {
+			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
+			dev->parent_platdata = calloc(1, size);
+			if (!dev->parent_platdata) {
+				ret = -ENOMEM;
+				goto fail_alloc2;
+			}
+		}
+	}
 
 	/* put dev into parent's successor list */
 	if (parent)
@@ -81,28 +101,51 @@
 
 	ret = uclass_bind_device(dev);
 	if (ret)
-		goto fail_bind;
+		goto fail_uclass_bind;
 
 	/* if we fail to bind we remove device from successors and free it */
 	if (drv->bind) {
 		ret = drv->bind(dev);
-		if (ret) {
-			if (uclass_unbind_device(dev)) {
-				dm_warn("Failed to unbind dev '%s' on error path\n",
-					dev->name);
-			}
+		if (ret)
 			goto fail_bind;
-		}
 	}
+	if (parent && parent->driver->child_post_bind) {
+		ret = parent->driver->child_post_bind(dev);
+		if (ret)
+			goto fail_child_post_bind;
+	}
+
 	if (parent)
 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
 	*devp = dev;
 
 	return 0;
 
+fail_child_post_bind:
+	if (drv->unbind && drv->unbind(dev)) {
+		dm_warn("unbind() method failed on dev '%s' on error path\n",
+			dev->name);
+	}
+
 fail_bind:
+	if (uclass_unbind_device(dev)) {
+		dm_warn("Failed to unbind dev '%s' on error path\n",
+			dev->name);
+	}
+fail_uclass_bind:
 	list_del(&dev->sibling_node);
+	if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
+		free(dev->parent_platdata);
+		dev->parent_platdata = NULL;
+	}
+fail_alloc2:
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
+fail_alloc1:
 	free(dev);
+
 	return ret;
 }
 
@@ -137,7 +180,7 @@
 	drv = dev->driver;
 	assert(drv);
 
-	/* Allocate private data and platdata if requested */
+	/* Allocate private data if requested */
 	if (drv->priv_auto_alloc_size) {
 		dev->priv = calloc(1, drv->priv_auto_alloc_size);
 		if (!dev->priv) {
@@ -146,13 +189,6 @@
 		}
 	}
 	/* Allocate private data if requested */
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
-		if (!dev->platdata) {
-			ret = -ENOMEM;
-			goto fail;
-		}
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		dev->uclass_priv = calloc(1, size);
@@ -165,6 +201,10 @@
 	/* Ensure all parents are probed */
 	if (dev->parent) {
 		size = dev->parent->driver->per_child_auto_alloc_size;
+		if (!size) {
+			size = dev->parent->uclass->uc_drv->
+					per_child_auto_alloc_size;
+		}
 		if (size) {
 			dev->parent_priv = calloc(1, size);
 			if (!dev->parent_priv) {
@@ -187,6 +227,10 @@
 	}
 	dev->seq = seq;
 
+	ret = uclass_pre_probe_child(dev);
+	if (ret)
+		goto fail;
+
 	if (dev->parent && dev->parent->driver->child_pre_probe) {
 		ret = dev->parent->driver->child_pre_probe(dev);
 		if (ret)
@@ -241,6 +285,16 @@
 	return dev->platdata;
 }
 
+void *dev_get_parent_platdata(struct udevice *dev)
+{
+	if (!dev) {
+		dm_warn("%s: null device", __func__);
+		return NULL;
+	}
+
+	return dev->parent_platdata;
+}
+
 void *dev_get_priv(struct udevice *dev)
 {
 	if (!dev) {
@@ -390,3 +444,20 @@
 {
 	return dev->of_id->data;
 }
+
+enum uclass_id device_get_uclass_id(struct udevice *dev)
+{
+	return dev->uclass->uc_drv->id;
+}
+
+#ifdef CONFIG_OF_CONTROL
+fdt_addr_t dev_get_addr(struct udevice *dev)
+{
+	return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+}
+#else
+fdt_addr_t dev_get_addr(struct udevice *dev)
+{
+	return FDT_ADDR_T_NONE;
+}
+#endif
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 47b3acf..9b5c6bb 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <errno.h>
+#include <fdtdec.h>
 #include <malloc.h>
 #include <libfdt.h>
 #include <dm/device.h>
@@ -36,6 +37,65 @@
 	return gd->dm_root;
 }
 
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+void fix_drivers(void)
+{
+	struct driver *drv =
+		ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct driver *entry;
+
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		if (entry->of_match)
+			entry->of_match = (const struct udevice_id *)
+				((u32)entry->of_match + gd->reloc_off);
+		if (entry->bind)
+			entry->bind += gd->reloc_off;
+		if (entry->probe)
+			entry->probe += gd->reloc_off;
+		if (entry->remove)
+			entry->remove += gd->reloc_off;
+		if (entry->unbind)
+			entry->unbind += gd->reloc_off;
+		if (entry->ofdata_to_platdata)
+			entry->ofdata_to_platdata += gd->reloc_off;
+		if (entry->child_pre_probe)
+			entry->child_pre_probe += gd->reloc_off;
+		if (entry->child_post_remove)
+			entry->child_post_remove += gd->reloc_off;
+		/* OPS are fixed in every uclass post_probe function */
+		if (entry->ops)
+			entry->ops += gd->reloc_off;
+	}
+}
+
+void fix_uclass(void)
+{
+	struct uclass_driver *uclass =
+		ll_entry_start(struct uclass_driver, uclass);
+	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
+	struct uclass_driver *entry;
+
+	for (entry = uclass; entry != uclass + n_ents; entry++) {
+		if (entry->post_bind)
+			entry->post_bind += gd->reloc_off;
+		if (entry->pre_unbind)
+			entry->pre_unbind += gd->reloc_off;
+		if (entry->post_probe)
+			entry->post_probe += gd->reloc_off;
+		if (entry->pre_remove)
+			entry->pre_remove += gd->reloc_off;
+		if (entry->init)
+			entry->init += gd->reloc_off;
+		if (entry->destroy)
+			entry->destroy += gd->reloc_off;
+		/* FIXME maybe also need to fix these ops */
+		if (entry->ops)
+			entry->ops += gd->reloc_off;
+	}
+}
+#endif
+
 int dm_init(void)
 {
 	int ret;
@@ -46,9 +106,17 @@
 	}
 	INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
 
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+	fix_drivers();
+	fix_uclass();
+#endif
+
 	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
 	if (ret)
 		return ret;
+#ifdef CONFIG_OF_CONTROL
+	DM_ROOT_NON_CONST->of_offset = 0;
+#endif
 	ret = device_probe(DM_ROOT_NON_CONST);
 	if (ret)
 		return ret;
@@ -89,6 +157,10 @@
 		if (pre_reloc_only &&
 		    !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
 			continue;
+		if (!fdtdec_get_is_enabled(blob, offset)) {
+			dm_dbg("   - ignoring disabled device\n");
+			continue;
+		}
 		err = lists_bind_fdt(parent, blob, offset, NULL);
 		if (err && !ret)
 			ret = err;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 901b06e..289a5d2 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -319,18 +319,29 @@
 	int ret;
 
 	uc = dev->uclass;
-
 	list_add_tail(&dev->uclass_node, &uc->dev_head);
 
+	if (dev->parent) {
+		struct uclass_driver *uc_drv = dev->parent->uclass->uc_drv;
+
+		if (uc_drv->child_post_bind) {
+			ret = uc_drv->child_post_bind(dev);
+			if (ret)
+				goto err;
+		}
+	}
 	if (uc->uc_drv->post_bind) {
 		ret = uc->uc_drv->post_bind(dev);
-		if (ret) {
-			list_del(&dev->uclass_node);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	return 0;
+err:
+	/* There is no need to undo the parent's post_bind call */
+	list_del(&dev->uclass_node);
+
+	return ret;
 }
 
 int uclass_unbind_device(struct udevice *dev)
@@ -380,6 +391,19 @@
 	return seq;
 }
 
+int uclass_pre_probe_child(struct udevice *dev)
+{
+	struct uclass_driver *uc_drv;
+
+	if (!dev->parent)
+		return 0;
+	uc_drv = dev->parent->uclass->uc_drv;
+	if (uc_drv->child_pre_probe)
+		return uc_drv->child_pre_probe(dev);
+
+	return 0;
+}
+
 int uclass_post_probe_device(struct udevice *dev)
 {
 	struct uclass_driver *uc_drv = dev->uclass->uc_drv;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e69de29..bd26a2b 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -0,0 +1 @@
+source drivers/crypto/fsl/Kconfig
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 7b79237..fb8c10b 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -6,4 +6,5 @@
 #
 
 obj-$(CONFIG_EXYNOS_ACE_SHA)	+= ace_sha.o
+obj-y += rsa_mod_exp/
 obj-y += fsl/
diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
new file mode 100644
index 0000000..86b2f2f
--- /dev/null
+++ b/drivers/crypto/fsl/Kconfig
@@ -0,0 +1,6 @@
+config FSL_CAAM
+	bool "Freescale Crypto Driver Support"
+	help
+	  Enables the Freescale's Cryptographic Accelerator and Assurance
+	  Module (CAAM), also known as the SEC version 4 (SEC4). The driver uses
+	  Job Ring as interface to communicate with CAAM.
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index 067d0a9..c0cf642 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -9,3 +9,4 @@
 obj-y += sec.o
 obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
 obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
+obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
diff --git a/drivers/crypto/fsl/fsl_rsa.c b/drivers/crypto/fsl/fsl_rsa.c
new file mode 100644
index 0000000..cf1c4c1
--- /dev/null
+++ b/drivers/crypto/fsl/fsl_rsa.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc.
+ * Author: Ruchika Gupta <ruchika.gupta@freescale.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <dm.h>
+#include <asm/types.h>
+#include <malloc.h>
+#include "jobdesc.h"
+#include "desc.h"
+#include "jr.h"
+#include "rsa_caam.h"
+#include <u-boot/rsa-mod-exp.h>
+
+int fsl_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *prop, uint8_t *out)
+{
+	uint32_t keylen;
+	struct pk_in_params pkin;
+	uint32_t desc[MAX_CAAM_DESCSIZE];
+	int ret;
+
+	/* Length in bytes */
+	keylen = prop->num_bits / 8;
+
+	pkin.a = sig;
+	pkin.a_siz = sig_len;
+	pkin.n = prop->modulus;
+	pkin.n_siz = keylen;
+	pkin.e = prop->public_exponent;
+	pkin.e_siz = prop->exp_len;
+
+	inline_cnstr_jobdesc_pkha_rsaexp(desc, &pkin, out, sig_len);
+
+	ret = run_descriptor_jr(desc);
+	if (ret) {
+		debug("%s: RSA failed to verify: %d\n", __func__, ret);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static const struct mod_exp_ops fsl_mod_exp_ops = {
+	.mod_exp	= fsl_mod_exp,
+};
+
+U_BOOT_DRIVER(fsl_rsa_mod_exp) = {
+	.name	= "fsl_rsa_mod_exp",
+	.id	= UCLASS_MOD_EXP,
+	.ops	= &fsl_mod_exp_ops,
+};
+
+U_BOOT_DEVICE(fsl_rsa) = {
+	.name = "fsl_rsa_mod_exp",
+};
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index 1386bae..cc0dced 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -11,6 +11,7 @@
 #include <common.h>
 #include "desc_constr.h"
 #include "jobdesc.h"
+#include "rsa_caam.h"
 
 #define KEY_BLOB_SIZE			32
 #define MAC_SIZE			16
@@ -123,3 +124,30 @@
 	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
 			 OP_ALG_RNG4_SK);
 }
+
+/* Change key size to bytes form bits in calling function*/
+void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+				      struct pk_in_params *pkin, uint8_t *out,
+				      uint32_t out_siz)
+{
+	dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
+
+	dma_addr_e = virt_to_phys((void *)pkin->e);
+	dma_addr_a = virt_to_phys((void *)pkin->a);
+	dma_addr_n = virt_to_phys((void *)pkin->n);
+	dma_addr_out = virt_to_phys((void *)out);
+
+	init_job_desc(desc, 0);
+	append_key(desc, dma_addr_e, pkin->e_siz, KEY_DEST_PKHA_E | CLASS_1);
+
+	append_fifo_load(desc, dma_addr_a,
+			 pkin->a_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_A);
+
+	append_fifo_load(desc, dma_addr_n,
+			 pkin->n_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_N);
+
+	append_operation(desc, OP_TYPE_PK | OP_ALG_PK | OP_ALG_PKMODE_MOD_EXPO);
+
+	append_fifo_store(desc, dma_addr_out, out_siz,
+			  LDST_CLASS_1_CCB | FIFOST_TYPE_PKHA_B);
+}
diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
index 3cf7226..84b3edd 100644
--- a/drivers/crypto/fsl/jobdesc.h
+++ b/drivers/crypto/fsl/jobdesc.h
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <asm/io.h>
+#include "rsa_caam.h"
 
 #define KEY_IDNFR_SZ_BYTES		16
 
@@ -26,4 +27,8 @@
 				     uint32_t out_sz);
 
 void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc);
+
+void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+				      struct pk_in_params *pkin, uint8_t *out,
+				      uint32_t out_siz);
 #endif
diff --git a/drivers/crypto/fsl/rsa_caam.h b/drivers/crypto/fsl/rsa_caam.h
new file mode 100644
index 0000000..4ff87ef
--- /dev/null
+++ b/drivers/crypto/fsl/rsa_caam.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __RSA_CAAM_H
+#define __RSA_CAAM_H
+
+#include <common.h>
+
+/**
+ * struct pk_in_params - holder for input to PKHA block in CAAM
+ * These parameters are required to perform Modular Exponentiation
+ * using PKHA Block in CAAM
+ */
+struct pk_in_params {
+	const uint8_t *e;	/* public exponent as byte array */
+	uint32_t e_siz;		/* size of e[] in number of bytes */
+	const uint8_t *n;	/* modulus as byte array */
+	uint32_t n_siz;		/* size of n[] in number of bytes */
+	const uint8_t *a;		/* Signature as byte array */
+	uint32_t a_siz;		/* size of a[] in number of bytes */
+	uint8_t *b;		/* Result exp. modulus in number of bytes */
+	uint32_t b_siz;		/* size of b[] in number of bytes */
+};
+
+#endif
diff --git a/drivers/crypto/rsa_mod_exp/Kconfig b/drivers/crypto/rsa_mod_exp/Kconfig
new file mode 100644
index 0000000..6dcb39a
--- /dev/null
+++ b/drivers/crypto/rsa_mod_exp/Kconfig
@@ -0,0 +1,5 @@
+config DM_MOD_EXP
+	bool "Enable Driver Model for RSA Modular Exponentiation"
+	depends on DM
+	help
+	  If you want to use driver model for RSA Modular Exponentiation, say Y.
diff --git a/drivers/crypto/rsa_mod_exp/Makefile b/drivers/crypto/rsa_mod_exp/Makefile
new file mode 100644
index 0000000..915b751
--- /dev/null
+++ b/drivers/crypto/rsa_mod_exp/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2014 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_RSA) += mod_exp_uclass.o mod_exp_sw.o
diff --git a/drivers/crypto/rsa_mod_exp/mod_exp_sw.c b/drivers/crypto/rsa_mod_exp/mod_exp_sw.c
new file mode 100644
index 0000000..dc6c064
--- /dev/null
+++ b/drivers/crypto/rsa_mod_exp/mod_exp_sw.c
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc.
+ * Author: Ruchika Gupta <ruchika.gupta@freescale.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <dm.h>
+#include <u-boot/rsa-mod-exp.h>
+
+int mod_exp_sw(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *prop, uint8_t *out)
+{
+	int ret = 0;
+
+	ret = rsa_mod_exp_sw(sig, sig_len, prop, out);
+	if (ret) {
+		debug("%s: RSA failed to verify: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct mod_exp_ops mod_exp_ops_sw = {
+	.mod_exp	= mod_exp_sw,
+};
+
+U_BOOT_DRIVER(mod_exp_sw) = {
+	.name	= "mod_exp_sw",
+	.id	= UCLASS_MOD_EXP,
+	.ops	= &mod_exp_ops_sw,
+};
+
+U_BOOT_DEVICE(mod_exp_sw) = {
+	.name = "mod_exp_sw",
+};
diff --git a/drivers/crypto/rsa_mod_exp/mod_exp_uclass.c b/drivers/crypto/rsa_mod_exp/mod_exp_uclass.c
new file mode 100644
index 0000000..266f094
--- /dev/null
+++ b/drivers/crypto/rsa_mod_exp/mod_exp_uclass.c
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2014 Freescale Semiconductor, Inc
+ * Author: Ruchika Gupta <ruchika.gupta@freescale.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <u-boot/rsa-mod-exp.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <linux/list.h>
+
+int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *node, uint8_t *out)
+{
+	const struct mod_exp_ops *ops = device_get_ops(dev);
+
+	if (!ops->mod_exp)
+		return -ENOSYS;
+
+	return ops->mod_exp(dev, sig, sig_len, node, out);
+}
+
+UCLASS_DRIVER(mod_exp) = {
+	.id		= UCLASS_MOD_EXP,
+	.name		= "rsa_mod_exp",
+};
diff --git a/drivers/ddr/mvebu/Makefile b/drivers/ddr/mvebu/Makefile
new file mode 100644
index 0000000..50a69ea
--- /dev/null
+++ b/drivers/ddr/mvebu/Makefile
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_SPL_BUILD) += ddr3_dfs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_dqs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_hw_training.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_init.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_pbs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_read_leveling.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_sdram.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_spd.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_write_leveling.o
+obj-$(CONFIG_SPL_BUILD) += xor.o
diff --git a/drivers/ddr/mvebu/ddr3_axp.h b/drivers/ddr/mvebu/ddr3_axp.h
new file mode 100644
index 0000000..bf65f6b
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_axp.h
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DDR3_AXP_H
+#define __DDR3_AXP_H
+
+#define MV_78XX0_Z1_REV			0x0
+#define MV_78XX0_A0_REV			0x1
+#define MV_78XX0_B0_REV			0x2
+
+#define SAR_DDR3_FREQ_MASK		0xFE00000
+#define SAR_CPU_FAB_GET(cpu, fab)	(((cpu & 0x7) << 21) | ((fab & 0xF) << 24))
+
+#define MAX_CS				4
+
+#define MIN_DIMM_ADDR			0x50
+#define FAR_END_DIMM_ADDR		0x50
+#define MAX_DIMM_ADDR			0x60
+
+#ifndef CONFIG_DDR_FIXED_SIZE
+#define SDRAM_CS_SIZE			0xFFFFFFF
+#else
+#define SDRAM_CS_SIZE			(CONFIG_DDR_FIXED_SIZE - 1)
+#endif
+#define SDRAM_CS_BASE			0x0
+#define SDRAM_DIMM_SIZE			0x80000000
+
+#define CPU_CONFIGURATION_REG(id)	(0x21800 + (id * 0x100))
+#define CPU_MRVL_ID_OFFSET		0x10
+#define SAR1_CPU_CORE_MASK		0x00000018
+#define SAR1_CPU_CORE_OFFSET		3
+
+#define ECC_SUPPORT
+#define NEW_FABRIC_TWSI_ADDR		0x4E
+#ifdef DB_784MP_GP
+#define BUS_WIDTH_ECC_TWSI_ADDR		0x4E
+#else
+#define BUS_WIDTH_ECC_TWSI_ADDR		0x4F
+#endif
+#define MV_MAX_DDR3_STATIC_SIZE		50
+#define MV_DDR3_MODES_NUMBER		30
+
+#define RESUME_RL_PATTERNS_ADDR		(0xFE0000)
+#define RESUME_RL_PATTERNS_SIZE		(0x100)
+#define RESUME_TRAINING_VALUES_ADDR	(RESUME_RL_PATTERNS_ADDR + RESUME_RL_PATTERNS_SIZE)
+#define RESUME_TRAINING_VALUES_MAX	(0xCD0)
+#define BOOT_INFO_ADDR			(RESUME_RL_PATTERNS_ADDR + 0x1000)
+#define CHECKSUM_RESULT_ADDR		(BOOT_INFO_ADDR + 0x1000)
+#define NUM_OF_REGISTER_ADDR		(CHECKSUM_RESULT_ADDR + 4)
+#define SUSPEND_MAGIC_WORD		(0xDEADB002)
+#define REGISTER_LIST_END		(0xFFFFFFFF)
+
+/*
+ * Registers offset
+ */
+
+#define REG_SAMPLE_RESET_LOW_ADDR		0x18230
+#define REG_SAMPLE_RESET_HIGH_ADDR		0x18234
+#define	REG_SAMPLE_RESET_CPU_FREQ_OFFS		21
+#define	REG_SAMPLE_RESET_CPU_FREQ_MASK		0x00E00000
+#define	REG_SAMPLE_RESET_FAB_OFFS		24
+#define	REG_SAMPLE_RESET_FAB_MASK		0xF000000
+#define	REG_SAMPLE_RESET_TCLK_OFFS		28
+#define	REG_SAMPLE_RESET_CPU_ARCH_OFFS		31
+#define	REG_SAMPLE_RESET_HIGH_CPU_FREQ_OFFS	20
+
+/* MISC */
+/*
+ * In mainline U-Boot we're re-configuring the mvebu base address
+ * register to 0xf1000000. So need to use this value for the DDR
+ * training code as well.
+ */
+#define INTER_REGS_BASE				SOC_REGS_PHY_BASE
+
+/* DDR */
+#define REG_SDRAM_CONFIG_ADDR			0x1400
+#define REG_SDRAM_CONFIG_MASK			0x9FFFFFFF
+#define REG_SDRAM_CONFIG_RFRS_MASK		0x3FFF
+#define REG_SDRAM_CONFIG_WIDTH_OFFS		15
+#define REG_SDRAM_CONFIG_REGDIMM_OFFS		17
+#define REG_SDRAM_CONFIG_ECC_OFFS		18
+#define REG_SDRAM_CONFIG_IERR_OFFS		19
+#define REG_SDRAM_CONFIG_PUPRSTDIV_OFFS		28
+#define REG_SDRAM_CONFIG_RSTRD_OFFS		30
+
+#define REG_DUNIT_CTRL_LOW_ADDR			0x1404
+#define REG_DUNIT_CTRL_LOW_2T_OFFS		3
+#define REG_DUNIT_CTRL_LOW_2T_MASK		0x3
+#define REG_DUNIT_CTRL_LOW_DPDE_OFFS		14
+
+#define REG_SDRAM_TIMING_LOW_ADDR		0x1408
+
+#define REG_SDRAM_TIMING_HIGH_ADDR		0x140C
+#define REG_SDRAM_TIMING_H_R2R_OFFS		7
+#define REG_SDRAM_TIMING_H_R2R_MASK		0x3
+#define REG_SDRAM_TIMING_H_R2W_W2R_OFFS		9
+#define REG_SDRAM_TIMING_H_R2W_W2R_MASK		0x3
+#define REG_SDRAM_TIMING_H_W2W_OFFS		11
+#define REG_SDRAM_TIMING_H_W2W_MASK		0x1F
+#define REG_SDRAM_TIMING_H_R2R_H_OFFS		19
+#define REG_SDRAM_TIMING_H_R2R_H_MASK		0x7
+#define REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS	22
+#define REG_SDRAM_TIMING_H_R2W_W2R_H_MASK	0x7
+
+#define REG_SDRAM_ADDRESS_CTRL_ADDR		0x1410
+#define REG_SDRAM_ADDRESS_SIZE_OFFS		2
+#define REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS	18
+#define REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS	4
+
+#define REG_SDRAM_OPEN_PAGES_ADDR		0x1414
+#define REG_SDRAM_OPERATION_CS_OFFS		8
+
+#define REG_SDRAM_OPERATION_ADDR		0x1418
+#define REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS	24
+#define REG_SDRAM_OPERATION_CWA_DATA_OFFS	20
+#define REG_SDRAM_OPERATION_CWA_DATA_MASK	0xF
+#define REG_SDRAM_OPERATION_CWA_RC_OFFS		16
+#define REG_SDRAM_OPERATION_CWA_RC_MASK		0xF
+#define REG_SDRAM_OPERATION_CMD_MR0		0xF03
+#define REG_SDRAM_OPERATION_CMD_MR1		0xF04
+#define REG_SDRAM_OPERATION_CMD_MR2		0xF08
+#define REG_SDRAM_OPERATION_CMD_MR3		0xF09
+#define REG_SDRAM_OPERATION_CMD_RFRS		0xF02
+#define REG_SDRAM_OPERATION_CMD_CWA		0xF0E
+#define REG_SDRAM_OPERATION_CMD_RFRS_DONE	0xF
+#define REG_SDRAM_OPERATION_CMD_MASK		0xF
+#define REG_SDRAM_OPERATION_CS_OFFS		8
+
+#define REG_OUDDR3_TIMING_ADDR			0x142C
+
+#define REG_SDRAM_MODE_ADDR			0x141C
+
+#define REG_SDRAM_EXT_MODE_ADDR			0x1420
+
+#define REG_DDR_CONT_HIGH_ADDR			0x1424
+
+#define REG_ODT_TIME_LOW_ADDR			0x1428
+#define REG_ODT_ON_CTL_RD_OFFS                  12
+#define REG_ODT_OFF_CTL_RD_OFFS                 16
+#define REG_SDRAM_ERROR_ADDR			0x1454
+#define REG_SDRAM_AUTO_PWR_SAVE_ADDR		0x1474
+#define REG_ODT_TIME_HIGH_ADDR			0x147C
+
+#define REG_SDRAM_INIT_CTRL_ADDR		0x1480
+#define REG_SDRAM_INIT_CTRL_OFFS		0
+#define REG_SDRAM_INIT_CKE_ASSERT_OFFS		2
+#define REG_SDRAM_INIT_RESET_DEASSERT_OFFS	3
+
+#define REG_SDRAM_ODT_CTRL_LOW_ADDR		0x1494
+
+#define REG_SDRAM_ODT_CTRL_HIGH_ADDR		0x1498
+/*#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK	0xFFFFFF55 */
+#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK	0x0
+#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA	0x3
+
+#define REG_DUNIT_ODT_CTRL_ADDR			0x149C
+#define REG_DUNIT_ODT_CTRL_OVRD_OFFS            8
+#define REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS        9
+
+#define REG_DRAM_FIFO_CTRL_ADDR			0x14A0
+
+#define REG_DRAM_AXI_CTRL_ADDR			0x14A8
+#define REG_DRAM_AXI_CTRL_AXIDATABUSWIDTH_OFFS	0
+
+#define REG_METAL_MASK_ADDR			0x14B0
+#define REG_METAL_MASK_MASK			0xDFFFFFFF
+#define REG_METAL_MASK_RETRY_OFFS		0
+
+#define REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR	0x14C0
+
+#define REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR	0x14C4
+#define REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR	0x14c8
+#define REG_DRAM_MAIN_PADS_CAL_ADDR		0x14CC
+
+#define REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR	0x17c8
+
+#define REG_CS_SIZE_SCRATCH_ADDR		0x1504
+#define REG_DYNAMIC_POWER_SAVE_ADDR		0x1520
+#define REG_DDR_IO_ADDR				0x1524
+#define REG_DDR_IO_CLK_RATIO_OFFS		15
+
+#define REG_DFS_ADDR				0x1528
+#define REG_DFS_DLLNEXTSTATE_OFFS		0
+#define REG_DFS_BLOCK_OFFS			1
+#define REG_DFS_SR_OFFS				2
+#define REG_DFS_ATSR_OFFS			3
+#define REG_DFS_RECONF_OFFS			4
+#define REG_DFS_CL_NEXT_STATE_OFFS		8
+#define REG_DFS_CL_NEXT_STATE_MASK		0xF
+#define REG_DFS_CWL_NEXT_STATE_OFFS		12
+#define REG_DFS_CWL_NEXT_STATE_MASK		0x7
+
+#define REG_READ_DATA_SAMPLE_DELAYS_ADDR	0x1538
+#define REG_READ_DATA_SAMPLE_DELAYS_MASK	0x1F
+#define REG_READ_DATA_SAMPLE_DELAYS_OFFS	8
+
+#define REG_READ_DATA_READY_DELAYS_ADDR		0x153C
+#define REG_READ_DATA_READY_DELAYS_MASK		0x1F
+#define REG_READ_DATA_READY_DELAYS_OFFS		8
+
+#define START_BURST_IN_ADDR			1
+
+#define REG_DRAM_TRAINING_SHADOW_ADDR		0x18488
+#define REG_DRAM_TRAINING_ADDR			0x15B0
+#define REG_DRAM_TRAINING_LOW_FREQ_OFFS		0
+#define REG_DRAM_TRAINING_PATTERNS_OFFS		4
+#define REG_DRAM_TRAINING_MED_FREQ_OFFS		2
+#define REG_DRAM_TRAINING_WL_OFFS		3
+#define REG_DRAM_TRAINING_RL_OFFS		6
+#define REG_DRAM_TRAINING_DQS_RX_OFFS		15
+#define REG_DRAM_TRAINING_DQS_TX_OFFS		16
+#define REG_DRAM_TRAINING_CS_OFFS		20
+#define REG_DRAM_TRAINING_RETEST_OFFS		24
+#define REG_DRAM_TRAINING_DFS_FREQ_OFFS		27
+#define REG_DRAM_TRAINING_DFS_REQ_OFFS		29
+#define REG_DRAM_TRAINING_ERROR_OFFS		30
+#define REG_DRAM_TRAINING_AUTO_OFFS		31
+#define REG_DRAM_TRAINING_RETEST_PAR		0x3
+#define REG_DRAM_TRAINING_RETEST_MASK		0xF8FFFFFF
+#define REG_DRAM_TRAINING_CS_MASK		0xFF0FFFFF
+#define REG_DRAM_TRAINING_PATTERNS_MASK		0xFF0F0000
+
+#define REG_DRAM_TRAINING_1_ADDR		0x15B4
+#define REG_DRAM_TRAINING_1_TRNBPOINT_OFFS	16
+
+#define REG_DRAM_TRAINING_2_ADDR		0x15B8
+#define REG_DRAM_TRAINING_2_OVERRUN_OFFS	17
+#define REG_DRAM_TRAINING_2_FIFO_RST_OFFS	4
+#define REG_DRAM_TRAINING_2_RL_MODE_OFFS	3
+#define REG_DRAM_TRAINING_2_WL_MODE_OFFS	2
+#define REG_DRAM_TRAINING_2_ECC_MUX_OFFS	1
+#define REG_DRAM_TRAINING_2_SW_OVRD_OFFS	0
+
+#define REG_DRAM_TRAINING_PATTERN_BASE_ADDR	0x15BC
+#define REG_DRAM_TRAINING_PATTERN_BASE_OFFS	3
+
+#define REG_TRAINING_DEBUG_2_ADDR		0x15C4
+#define REG_TRAINING_DEBUG_2_OFFS		16
+#define REG_TRAINING_DEBUG_2_MASK		0x3
+
+#define REG_TRAINING_DEBUG_3_ADDR		0x15C8
+#define REG_TRAINING_DEBUG_3_OFFS		3
+#define REG_TRAINING_DEBUG_3_MASK		0x7
+
+#define	MR_CS_ADDR_OFFS				4
+
+#define	REG_DDR3_MR0_ADDR			0x15D0
+#define	REG_DDR3_MR0_CS_ADDR			0x1870
+#define REG_DDR3_MR0_CL_MASK			0x74
+#define	REG_DDR3_MR0_CL_OFFS			2
+#define	REG_DDR3_MR0_CL_HIGH_OFFS		3
+#define	CL_MASK					0xF
+
+#define	REG_DDR3_MR1_ADDR			0x15D4
+#define	REG_DDR3_MR1_CS_ADDR			0x1874
+#define REG_DDR3_MR1_RTT_MASK			0xFFFFFDBB
+#define REG_DDR3_MR1_DLL_ENA_OFFS		0
+#define REG_DDR3_MR1_RTT_DISABLED		0x0
+#define REG_DDR3_MR1_RTT_RZQ2			0x40
+#define REG_DDR3_MR1_RTT_RZQ4			0x2
+#define REG_DDR3_MR1_RTT_RZQ6			0x42
+#define REG_DDR3_MR1_RTT_RZQ8			0x202
+#define REG_DDR3_MR1_RTT_RZQ12			0x4
+#define REG_DDR3_MR1_OUTBUF_WL_MASK		0xFFFFEF7F	/* WL-disabled,OB-enabled */
+#define REG_DDR3_MR1_OUTBUF_DIS_OFFS		12	/* Output Buffer Disabled */
+#define REG_DDR3_MR1_WL_ENA_OFFS		7
+#define REG_DDR3_MR1_WL_ENA			0x80	/* WL Enabled */
+#define REG_DDR3_MR1_ODT_MASK			0xFFFFFDBB
+
+#define	REG_DDR3_MR2_ADDR			0x15D8
+#define	REG_DDR3_MR2_CS_ADDR			0x1878
+#define	REG_DDR3_MR2_CWL_OFFS			3
+#define	REG_DDR3_MR2_CWL_MASK			0x7
+#define REG_DDR3_MR2_ODT_MASK			0xFFFFF9FF
+#define	REG_DDR3_MR3_ADDR			0x15DC
+#define	REG_DDR3_MR3_CS_ADDR			0x187C
+
+#define REG_DDR3_RANK_CTRL_ADDR			0x15E0
+#define REG_DDR3_RANK_CTRL_CS_ENA_MASK		0xF
+#define REG_DDR3_RANK_CTRL_MIRROR_OFFS		4
+
+#define REG_ZQC_CONF_ADDR			0x15E4
+
+#define REG_DRAM_PHY_CONFIG_ADDR		0x15EC
+#define REG_DRAM_PHY_CONFIG_MASK		0x3FFFFFFF
+
+#define REG_ODPG_CNTRL_ADDR			0x1600
+#define REG_ODPG_CNTRL_OFFS			21
+
+#define REG_PHY_LOCK_MASK_ADDR			0x1670
+#define REG_PHY_LOCK_MASK_MASK			0xFFFFF000
+
+#define REG_PHY_LOCK_STATUS_ADDR		0x1674
+#define REG_PHY_LOCK_STATUS_LOCK_OFFS		9
+#define REG_PHY_LOCK_STATUS_LOCK_MASK		0xFFF
+#define REG_PHY_LOCK_APLL_ADLL_STATUS_MASK	0x7FF
+
+#define REG_PHY_REGISTRY_FILE_ACCESS_ADDR	0x16A0
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_WR	0xC0000000
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_RD	0x80000000
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE	0x80000000
+#define REG_PHY_BC_OFFS				27
+#define REG_PHY_CNTRL_OFFS			26
+#define REG_PHY_CS_OFFS				16
+#define REG_PHY_DQS_REF_DLY_OFFS		10
+#define REG_PHY_PHASE_OFFS			8
+#define REG_PHY_PUP_OFFS			22
+
+#define REG_TRAINING_WL_ADDR			0x16AC
+#define REG_TRAINING_WL_CS_MASK			0xFFFFFFFC
+#define REG_TRAINING_WL_UPD_OFFS		2
+#define REG_TRAINING_WL_CS_DONE_OFFS		3
+#define REG_TRAINING_WL_RATIO_MASK		0xFFFFFF0F
+#define REG_TRAINING_WL_1TO1			0x50
+#define REG_TRAINING_WL_2TO1			0x10
+#define REG_TRAINING_WL_DELAYEXP_MASK		0x20000000
+#define REG_TRAINING_WL_RESULTS_MASK		0x000001FF
+#define REG_TRAINING_WL_RESULTS_OFFS		20
+
+#define REG_REGISTERED_DRAM_CTRL_ADDR		0x16D0
+#define REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS	15
+#define REG_REGISTERED_DRAM_CTRL_PARITY_MASK	0x3F
+/* DLB*/
+#define REG_STATIC_DRAM_DLB_CONTROL		0x1700
+#define DLB_BUS_OPTIMIZATION_WEIGHTS_REG	0x1704
+#define DLB_AGING_REGISTER			0x1708
+#define DLB_EVICTION_CONTROL_REG		0x170c
+#define DLB_EVICTION_TIMERS_REGISTER_REG	0x1710
+
+#define DLB_ENABLE				0x1
+#define DLB_WRITE_COALESING			(0x1 << 2)
+#define DLB_AXI_PREFETCH_EN			(0x1 << 3)
+#define DLB_MBUS_PREFETCH_EN			(0x1 << 4)
+#define PREFETCH_NLNSZTR			(0x1 << 6)
+
+/* CPU    */
+#define REG_BOOTROM_ROUTINE_ADDR		0x182D0
+#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS	12
+
+#define REG_DRAM_INIT_CTRL_STATUS_ADDR		0x18488
+#define REG_DRAM_INIT_CTRL_TRN_CLK_OFFS		16
+#define REG_CPU_DIV_CLK_CTRL_0_NEW_RATIO	0x000200FF
+#define REG_DRAM_INIT_CTRL_STATUS_2_ADDR	0x1488
+
+#define REG_CPU_DIV_CLK_CTRL_0_ADDR		0x18700
+
+#define REG_CPU_DIV_CLK_CTRL_1_ADDR		0x18704
+#define REG_CPU_DIV_CLK_CTRL_2_ADDR		0x18708
+
+#define REG_CPU_DIV_CLK_CTRL_3_ADDR		0x1870C
+#define REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK	0xFFFFC0FF
+#define REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS	8
+
+#define REG_CPU_DIV_CLK_CTRL_4_ADDR		0x18710
+
+#define REG_CPU_DIV_CLK_STATUS_0_ADDR		0x18718
+#define REG_CPU_DIV_CLK_ALL_STABLE_OFFS		8
+
+#define REG_CPU_PLL_CTRL_0_ADDR			0x1871C
+#define REG_CPU_PLL_STATUS_0_ADDR		0x18724
+#define REG_CORE_DIV_CLK_CTRL_ADDR		0x18740
+#define REG_CORE_DIV_CLK_STATUS_ADDR		0x18744
+#define REG_DDRPHY_APLL_CTRL_ADDR		0x18780
+
+#define REG_DDRPHY_APLL_CTRL_2_ADDR		0x18784
+
+#define REG_SFABRIC_CLK_CTRL_ADDR		0x20858
+#define REG_SFABRIC_CLK_CTRL_SMPL_OFFS		8
+
+/* DRAM Windows */
+#define REG_XBAR_WIN_19_CTRL_ADDR		0x200e8
+#define REG_XBAR_WIN_4_CTRL_ADDR		0x20040
+#define REG_XBAR_WIN_4_BASE_ADDR		0x20044
+#define REG_XBAR_WIN_4_REMAP_ADDR		0x20048
+#define REG_FASTPATH_WIN_0_CTRL_ADDR		0x20184
+#define REG_XBAR_WIN_7_REMAP_ADDR		0x20078
+
+/* SRAM */
+#define REG_CDI_CONFIG_ADDR			0x20220
+#define REG_SRAM_WINDOW_0_ADDR			0x20240
+#define REG_SRAM_WINDOW_0_ENA_OFFS		0
+#define REG_SRAM_WINDOW_1_ADDR			0x20244
+#define REG_SRAM_L2_ENA_ADDR			0x8500
+#define REG_SRAM_CLEAN_BY_WAY_ADDR		0x87BC
+
+/* PMU */
+#define REG_PMU_I_F_CTRL_ADDR			0x1C090
+#define REG_PMU_DUNIT_BLK_OFFS			16
+#define REG_PMU_DUNIT_RFRS_OFFS			20
+#define REG_PMU_DUNIT_ACK_OFFS			24
+
+/* MBUS*/
+#define MBUS_UNITS_PRIORITY_CONTROL_REG		(MV_MBUS_REGS_OFFSET + 0x420)
+#define FABRIC_UNITS_PRIORITY_CONTROL_REG	(MV_MBUS_REGS_OFFSET + 0x424)
+#define MBUS_UNITS_PREFETCH_CONTROL_REG		(MV_MBUS_REGS_OFFSET + 0x428)
+#define FABRIC_UNITS_PREFETCH_CONTROL_REG	(MV_MBUS_REGS_OFFSET + 0x42c)
+
+#define REG_PM_STAT_MASK_ADDR			0x2210C
+#define REG_PM_STAT_MASK_CPU0_IDLE_MASK_OFFS	16
+
+#define REG_PM_EVENT_STAT_MASK_ADDR		0x22120
+#define REG_PM_EVENT_STAT_MASK_DFS_DONE_OFFS	17
+
+#define REG_PM_CTRL_CONFIG_ADDR			0x22104
+#define REG_PM_CTRL_CONFIG_DFS_REQ_OFFS		18
+
+#define REG_FABRIC_LOCAL_IRQ_MASK_ADDR		0x218C4
+#define REG_FABRIC_LOCAL_IRQ_PMU_MASK_OFFS	18
+
+/* Controller revision info */
+#define PCI_CLASS_CODE_AND_REVISION_ID		0x008
+#define PCCRIR_REVID_OFFS			0	/* Revision ID */
+#define PCCRIR_REVID_MASK			(0xff << PCCRIR_REVID_OFFS)
+
+/*  Power Management Clock Gating Control Register	*/
+#define MV_PEX_IF_REGS_OFFSET(if) \
+	(if < 8 ? (0x40000 + ((if) / 4) * 0x40000 + ((if) % 4) * 0x4000) \
+	 : (0x42000 + ((if) % 8) * 0x40000))
+#define MV_PEX_IF_REGS_BASE(unit)		(MV_PEX_IF_REGS_OFFSET(unit))
+#define POWER_MNG_CTRL_REG			0x18220
+#define PEX_DEVICE_AND_VENDOR_ID		0x000
+#define PEX_CFG_DIRECT_ACCESS(if, reg)		(MV_PEX_IF_REGS_BASE(if) + (reg))
+#define PMC_PEXSTOPCLOCK_OFFS(port)		((port) < 8 ? (5 + (port)) : (18 + (port)))
+#define PMC_PEXSTOPCLOCK_MASK(port)		(1 << PMC_PEXSTOPCLOCK_OFFS(port))
+#define PMC_PEXSTOPCLOCK_EN(port)		(1 << PMC_PEXSTOPCLOCK_OFFS(port))
+#define PMC_PEXSTOPCLOCK_STOP(port)		(0 << PMC_PEXSTOPCLOCK_OFFS(port))
+
+/* TWSI */
+#define TWSI_DATA_ADDR_MASK			0x7
+#define TWSI_DATA_ADDR_OFFS			1
+
+/* General */
+#define MAX_CS					4
+
+/* Frequencies */
+#define FAB_OPT					21
+#define CLK_CPU					12
+#define CLK_VCO					(2 * CLK_CPU)
+#define CLK_DDR					12
+
+/* Cpu Frequencies: */
+#define CLK_CPU_1000				0
+#define CLK_CPU_1066				1
+#define CLK_CPU_1200				2
+#define CLK_CPU_1333				3
+#define CLK_CPU_1500				4
+#define CLK_CPU_1666				5
+#define CLK_CPU_1800				6
+#define CLK_CPU_2000				7
+#define CLK_CPU_600				8
+#define CLK_CPU_667				9
+#define CLK_CPU_800				0xa
+
+/* Extra Cpu Frequencies: */
+#define CLK_CPU_1600				11
+#define CLK_CPU_2133				12
+#define CLK_CPU_2200				13
+#define CLK_CPU_2400				14
+
+/* DDR3 Frequencies: */
+#define DDR_100					0
+#define DDR_300					1
+#define DDR_333					1
+#define DDR_360					2
+#define DDR_400					3
+#define DDR_444					4
+#define DDR_500					5
+#define DDR_533					6
+#define DDR_600					7
+#define DDR_640					8
+#define DDR_666					8
+#define DDR_720					9
+#define DDR_750					9
+#define DDR_800					10
+#define DDR_833					11
+#define DDR_HCLK				20
+#define DDR_S					12
+#define DDR_S_1TO1				13
+#define MARGIN_FREQ				DDR_400
+#define DFS_MARGIN				DDR_100
+
+#define ODT_OPT					16
+#define ODT20					0x200
+#define ODT30					0x204
+#define ODT40					0x44
+#define ODT120					0x40
+#define ODT120D					0x400
+
+#define MRS_DELAY				100
+
+#define SDRAM_WL_SW_OFFS			0x100
+#define SDRAM_RL_OFFS				0x0
+#define SDRAM_PBS_I_OFFS			0x140
+#define SDRAM_PBS_II_OFFS			0x180
+#define SDRAM_PBS_NEXT_OFFS			(SDRAM_PBS_II_OFFS - SDRAM_PBS_I_OFFS)
+#define SDRAM_PBS_TX_OFFS			0x180
+#define SDRAM_PBS_TX_DM_OFFS			576
+#define SDRAM_DQS_RX_OFFS			1024
+#define SDRAM_DQS_TX_OFFS			2048
+#define SDRAM_DQS_RX_SPECIAL_OFFS		5120
+
+#define LEN_STD_PATTERN				16
+#define LEN_KILLER_PATTERN			128
+#define LEN_SPECIAL_PATTERN			128
+#define LEN_PBS_PATTERN				16
+
+#endif /* __DDR3_AXP_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_config.h b/drivers/ddr/mvebu/ddr3_axp_config.h
new file mode 100644
index 0000000..800d2d1
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_axp_config.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DDR3_AXP_CONFIG_H
+#define __DDR3_AXP_CONFIG_H
+
+/*
+ * DDR3_LOG_LEVEL Information
+ *
+ * Level 0: Provides an error code in a case of failure, RL, WL errors
+ *          and other algorithm failure
+ * Level 1: Provides the D-Unit setup (SPD/Static configuration)
+ * Level 2: Provides the windows margin as a results of DQS centeralization
+ * Level 3: Provides the windows margin of each DQ as a results of DQS
+ *          centeralization
+ */
+#ifdef CONFIG_DDR_LOG_LEVEL
+#define	DDR3_LOG_LEVEL	CONFIG_DDR_LOG_LEVEL
+#else
+#define	DDR3_LOG_LEVEL	0
+#endif
+
+#define DDR3_PBS        1
+
+/* This flag allows the execution of SW WL/RL upon HW failure */
+#define DDR3_RUN_SW_WHEN_HW_FAIL    1
+
+/*
+ * General Configurations
+ *
+ * The following parameters are required for proper setup:
+ *
+ * DDR_TARGET_FABRIC   - Set desired fabric configuration
+ *                       (for sample@Reset fabfreq parameter)
+ * DRAM_ECC            - Set ECC support 1/0
+ * BUS_WIDTH           - 64/32 bit
+ * CONFIG_SPD_EEPROM   - Enables auto detection of DIMMs and their timing values
+ * DQS_CLK_ALIGNED     - Set this if CLK and DQS signals are aligned on board
+ * MIXED_DIMM_STATIC   - Mixed DIMM + On board devices support (ODT registers
+ *                       values are taken statically)
+ * DDR3_TRAINING_DEBUG - Debug prints of internal code
+ */
+#define DDR_TARGET_FABRIC			5
+#define DRAM_ECC				0
+
+#ifdef MV_DDR_32BIT
+#define BUS_WIDTH                               32
+#else
+#define BUS_WIDTH				64
+#endif
+
+#undef DQS_CLK_ALIGNED
+#undef MIXED_DIMM_STATIC
+#define DDR3_TRAINING_DEBUG			0
+#define REG_DIMM_SKIP_WL			0
+
+/* Marvell boards specific configurations */
+#if defined(DB_78X60_PCAC)
+#undef CONFIG_SPD_EEPROM
+#define STATIC_TRAINING
+#endif
+
+#if defined(DB_78X60_AMC)
+#undef CONFIG_SPD_EEPROM
+#undef  DRAM_ECC
+#define DRAM_ECC				1
+#endif
+
+#ifdef CONFIG_SPD_EEPROM
+/*
+ * DIMM support parameters:
+ * DRAM_2T - Set Desired 2T Mode - 0 - 1T, 0x1 - 2T, 0x2 - 3T
+ * DIMM_CS_BITMAP - bitmap representing the optional CS in DIMMs
+ * (0xF=CS0+CS1+CS2+CS3, 0xC=CS2+CS3...)
+ */
+#define DRAM_2T					0x0
+#define DIMM_CS_BITMAP				0xF
+#define DUNIT_SPD
+#endif
+
+#ifdef DRAM_ECC
+/*
+ * ECC support parameters:
+ *
+ * U_BOOT_START_ADDR, U_BOOT_SCRUB_SIZE - relevant when using ECC and need
+ * to configure the scrubbing area
+ */
+#define TRAINING_SIZE				0x20000
+#define U_BOOT_START_ADDR			0
+#define U_BOOT_SCRUB_SIZE			0x1000000 /* TRAINING_SIZE */
+#endif
+
+/*
+ * Registered DIMM Support - In case registered DIMM is attached,
+ * please supply the following values:
+ * (see JEDEC - JESD82-29A "Definition of the SSTE32882 Registering Clock
+ * Driver with Parity and Quad Chip
+ * Selects for DDR3/DDR3L/DDR3U RDIMM 1.5 V/1.35 V/1.25 V Applications")
+ * RC0: Global Features Control Word
+ * RC1: Clock Driver Enable Control Word
+ * RC2: Timing Control Word
+ * RC3-RC5 - taken from SPD
+ * RC8: Additional IBT Setting Control Word
+ * RC9: Power Saving Settings Control Word
+ * RC10: Encoding for RDIMM Operating Speed
+ * RC11: Operating Voltage VDD and VREFCA Control Word
+ */
+#define RDIMM_RC0				0
+#define RDIMM_RC1				0
+#define RDIMM_RC2				0
+#define RDIMM_RC8				0
+#define RDIMM_RC9				0
+#define RDIMM_RC10				0x2
+#define RDIMM_RC11				0x0
+
+#if defined(MIXED_DIMM_STATIC) || !defined(CONFIG_SPD_EEPROM)
+#define DUNIT_STATIC
+#endif
+
+#if defined(MIXED_DIMM_STATIC) || defined(CONFIG_SPD_EEPROM)
+/*
+ * This flag allows the user to change the dram refresh cycle in ps,
+ * only in case of SPD or MIX DIMM topology
+ */
+#define TREFI_USER_EN
+
+#ifdef TREFI_USER_EN
+#define TREFI_USER				3900000
+#endif
+#endif
+
+#ifdef CONFIG_SPD_EEPROM
+/*
+ * AUTO_DETECTION_SUPPORT - relevant ONLY for Marvell DB boards.
+ * Enables I2C auto detection different options
+ */
+#if defined(CONFIG_DB_88F78X60) || defined(CONFIG_DB_88F78X60_REV2) || \
+    defined(CONFIG_DB_784MP_GP)
+#define AUTO_DETECTION_SUPPORT
+#endif
+#endif
+
+#endif /* __DDR3_AXP_CONFIG_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_mc_static.h b/drivers/ddr/mvebu/ddr3_axp_mc_static.h
new file mode 100644
index 0000000..2c0e9075
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_axp_mc_static.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __AXP_MC_STATIC_H
+#define __AXP_MC_STATIC_H
+
+MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+	{0x00001400, 0x7301c924},	/*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
+#endif
+	{0x00001404, 0x3630b800},	/*Dunit Control Low Register */
+	{0x00001408, 0x43149775},	/*DDR SDRAM Timing (Low) Register */
+	/* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+	{0x0000140C, 0x38d83fe0},	/*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+	{0x00001410, 0x040F0001},	/*DDR SDRAM Address Control Register */
+#else
+	{0x00001410, 0x040F0000},	/*DDR SDRAM Open Pages Control Register */
+#endif
+
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0000D3FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000F8830},	/*Dunit Control High Register */
+	{0x0000142C, 0x214C2F38},	/*Dunit Control High Register */
+	{0x0000147C, 0x0000c671},
+
+	{0x000014a0, 0x000002A9},
+	{0x000014a8, 0x00000101},	/*2:1 */
+	{0x00020220, 0x00000007},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000301},	/*DDR Dunit ODT Control Register */
+
+	{0x000014C0, 0x192434e9},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0x092434e9},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x7FFFFFF1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	/*     {0x00001524, 0x0000C800},  */
+	{0x00001538, 0x0000000b},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000d},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000640},	/*MR0 */
+	{0x000015D4, 0x00000046},	/*MR1 */
+	{0x000015D8, 0x00000010},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQC Configuration Register */
+	{0x000015EC, 0xd800aa25},	/*DDR PHY */
+	{0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+	{0x00001400, 0x7301c924},	/*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
+#endif
+	{0x00001404, 0x3630b800},	/*Dunit Control Low Register */
+	{0x00001408, 0x43149775},	/*DDR SDRAM Timing (Low) Register */
+	/* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+	{0x0000140C, 0x38d83fe0},	/*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+	{0x00001410, 0x040F0001},	/*DDR SDRAM Address Control Register */
+#else
+	{0x00001410, 0x040F000C},	/*DDR SDRAM Open Pages Control Register */
+#endif
+
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0000D3FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000F8830},	/*Dunit Control High Register */
+	{0x0000142C, 0x214C2F38},	/*Dunit Control High Register */
+	{0x0000147C, 0x0000c671},
+
+	{0x000014a0, 0x000002A9},
+	{0x000014a8, 0x00000101},	/*2:1 */
+	{0x00020220, 0x00000007},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000301},	/*DDR Dunit ODT Control Register */
+
+	{0x000014C0, 0x192434e9},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0x092434e9},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x3FFFFFF1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	/*     {0x00001524, 0x0000C800},  */
+	{0x00001538, 0x0000000b},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000d},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000640},	/*MR0 */
+	{0x000015D4, 0x00000046},	/*MR1 */
+	{0x000015D8, 0x00000010},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQC Configuration Register */
+	{0x000015EC, 0xd800aa25},	/*DDR PHY */
+	{0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+	{0x00001400, 0x73004C30},	/*DDR SDRAM Configuration Register */
+#else /* MV_DDR_64BIT */
+	{0x00001400, 0x7300CC30},	/*DDR SDRAM Configuration Register */
+#endif
+	{0x00001404, 0x3630B840},	/*Dunit Control Low Register */
+	{0x00001408, 0x33137663},	/*DDR SDRAM Timing (Low) Register */
+	{0x0000140C, 0x38000C55},	/*DDR SDRAM Timing (High) Register */
+	{0x00001410, 0x040F0000},	/*DDR SDRAM Address Control Register */
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x0000141C, 0x00000672},	/*DDR SDRAM Mode Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0100D3FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000D6720},	/*Dunit Control High Register */
+	{0x0000142C, 0x014C2F38},	/*Dunit Control High Register */
+	{0x0000147C, 0x00006571},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000301},	/*DDR Dunit ODT Control Register */
+
+	{0x000014a0, 0x000002A9},
+	{0x000014a8, 0x00000101},	/*2:1 */
+	{0x00020220, 0x00000007},
+
+	{0x000014C0, 0x192424C8},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0xEFB24C8},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x7FFFFFF1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	{0x00001538, 0x00000008},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000A},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000630},	/*MR0 */
+	{0x000015D4, 0x00000046},	/*MR1 */
+	{0x000015D8, 0x00000008},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQDS Configuration Register */
+	/* {0x000015EC, 0xDE000025}, *//*DDR PHY */
+	{0x000015EC, 0xF800AA25},	/*DDR PHY */
+	{0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+	{0x00001400, 0x73014A28},	/*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
+#endif
+	{0x00001404, 0x3630B040},	/*Dunit Control Low Register */
+	{0x00001408, 0x44149887},	/*DDR SDRAM Timing (Low) Register */
+	/* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+	{0x0000140C, 0x38D83FE0},	/*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+	{0x00001410, 0x040F0001},	/*DDR SDRAM Address Control Register */
+#else
+	{0x00001410, 0x040F0000},	/*DDR SDRAM Open Pages Control Register */
+#endif
+
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0100D1FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000F8830},	/*Dunit Control High Register */
+	{0x0000142C, 0x214C2F38},	/*Dunit Control High Register */
+	{0x0000147C, 0x0000c671},
+
+	{0x000014a8, 0x00000101},	/*2:1 */
+	{0x00020220, 0x00000007},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000301},	/*DDR Dunit ODT Control Register */
+
+	{0x000014C0, 0x192424C8},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0xEFB24C8},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x7FFFFFF1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	/*     {0x00001524, 0x0000C800},  */
+	{0x00001538, 0x0000000b},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000d},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000650},	/*MR0 */
+	{0x000015D4, 0x00000046},	/*MR1 */
+	{0x000015D8, 0x00000010},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQC Configuration Register */
+	{0x000015EC, 0xDE000025},	/*DDR PHY */
+	{0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_Z1_db_300[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+	{0x00001400, 0x73004C30},	/*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+	{0x00001400, 0x7300CC30},	/*DDR SDRAM Configuration Register */
+	/*{0x00001400, 0x7304CC30},  *//*DDR SDRAM Configuration Register */
+#endif
+	{0x00001404, 0x3630B840},	/*Dunit Control Low Register */
+	{0x00001408, 0x33137663},	/*DDR SDRAM Timing (Low) Register */
+	{0x0000140C, 0x38000C55},	/*DDR SDRAM Timing (High) Register */
+	{0x00001410, 0x040F0000},	/*DDR SDRAM Address Control Register */
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x0000141C, 0x00000672},	/*DDR SDRAM Mode Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0100F1FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000D6720},	/*Dunit Control High Register */
+	{0x0000142C, 0x014C2F38},	/*Dunit Control High Register */
+	{0x0000147C, 0x00006571},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000301},	/*DDR Dunit ODT Control Register */
+
+	{0x000014C0, 0x192424C8},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0xEFB24C8},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x7FFFFFF1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	{0x00001538, 0x00000008},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000A},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000630},	/*MR0 */
+	{0x000015D4, 0x00000046},	/*MR1 */
+	{0x000015D8, 0x00000008},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQDS Configuration Register */
+	{0x000015EC, 0xDE000025},	/*DDR PHY */
+
+	{0x0, 0x0}
+};
+
+#endif /* __AXP_MC_STATIC_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_training_static.h b/drivers/ddr/mvebu/ddr3_axp_training_static.h
new file mode 100644
index 0000000..4e61547
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_axp_training_static.h
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __AXP_TRAINING_STATIC_H
+#define __AXP_TRAINING_STATIC_H
+
+/*
+ * STATIC_TRAINING - Set only if static parameters for training are set and
+ * required
+ */
+
+MV_DRAM_TRAINING_INIT ddr3_db_rev2_667[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0     */
+	{0x000016A0, 0xC002011A},
+	/*1 */
+	{0x000016A0, 0xC0420100},
+	/*2 */
+	{0x000016A0, 0xC082020A},
+	/*3 */
+	{0x000016A0, 0xC0C20017},
+	/*4 */
+	{0x000016A0, 0xC1020113},
+	/*5 */
+	{0x000016A0, 0xC1420107},
+	/*6 */
+	{0x000016A0, 0xC182011F},
+	/*7 */
+	{0x000016A0, 0xC1C2001C},
+	/*8 */
+	{0x000016A0, 0xC202010D},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0004A06},
+	/*1 */
+	{0x000016A0, 0xC040690D},
+	/*2 */
+	{0x000016A0, 0xC0806A0D},
+	/*3 */
+	{0x000016A0, 0xC0C0A01B},
+	/*4 */
+	{0x000016A0, 0xC1003A01},
+	/*5 */
+	{0x000016A0, 0xC1408113},
+	/*6 */
+	{0x000016A0, 0xC1805609},
+	/*7 */
+	{0x000016A0, 0xC1C04504},
+	/*8 */
+	{0x000016A0, 0xC2009518},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_rev2_800[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0     */
+	{0x000016A0, 0xC0020301},
+	/*1 */
+	{0x000016A0, 0xC0420202},
+	/*2 */
+	{0x000016A0, 0xC0820314},
+	/*3 */
+	{0x000016A0, 0xC0C20117},
+	/*4 */
+	{0x000016A0, 0xC1020219},
+	/*5 */
+	{0x000016A0, 0xC142020B},
+	/*6 */
+	{0x000016A0, 0xC182030A},
+	/*7 */
+	{0x000016A0, 0xC1C2011D},
+	/*8 */
+	{0x000016A0, 0xC2020212},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0007A12},
+	/*1 */
+	{0x000016A0, 0xC0408D16},
+	/*2 */
+	{0x000016A0, 0xC0809E1B},
+	/*3 */
+	{0x000016A0, 0xC0C0AC1F},
+	/*4 */
+	{0x000016A0, 0xC1005E0A},
+	/*5 */
+	{0x000016A0, 0xC140A91D},
+	/*6 */
+	{0x000016A0, 0xC1808E17},
+	/*7 */
+	{0x000016A0, 0xC1C05509},
+	/*8 */
+	{0x000016A0, 0xC2003A01},
+
+	/* PBS Leveling */
+	/*0 */
+	{0x000016A0, 0xC0007A12},
+	/*1 */
+	{0x000016A0, 0xC0408D16},
+	/*2 */
+	{0x000016A0, 0xC0809E1B},
+	/*3 */
+	{0x000016A0, 0xC0C0AC1F},
+	/*4 */
+	{0x000016A0, 0xC1005E0A},
+	/*5 */
+	{0x000016A0, 0xC140A91D},
+	/*6 */
+	{0x000016A0, 0xC1808E17},
+	/*7 */
+	{0x000016A0, 0xC1C05509},
+	/*8 */
+	{0x000016A0, 0xC2003A01},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000B},
+
+	{0x00001538, 0x0000000D},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x00000011},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0             2               4               15 */
+	{0x000016A0, 0xC002010C},
+	/*1             2               4               2 */
+	{0x000016A0, 0xC042001C},
+	/*2             2               4               27 */
+	{0x000016A0, 0xC0820115},
+	/*3             2               4               0 */
+	{0x000016A0, 0xC0C20019},
+	/*4             2               4               13 */
+	{0x000016A0, 0xC1020108},
+	/*5             2               4               5 */
+	{0x000016A0, 0xC1420100},
+	/*6             2               4               19 */
+	{0x000016A0, 0xC1820111},
+	/*7             2               4               0 */
+	{0x000016A0, 0xC1C2001B},
+	/*8             2               4               10 */
+	/*{0x000016A0, 0xC2020117}, */
+	{0x000016A0, 0xC202010C},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0005508},
+	/*1 */
+	{0x000016A0, 0xC0409819},
+	/*2 */
+	{0x000016A0, 0xC080650C},
+	/*3 */
+	{0x000016A0, 0xC0C0700F},
+	/*4 */
+	{0x000016A0, 0xC1004103},
+	/*5 */
+	{0x000016A0, 0xC140A81D},
+	/*6 */
+	{0x000016A0, 0xC180650C},
+	/*7 */
+	{0x000016A0, 0xC1C08013},
+	/*8 */
+	{0x000016A0, 0xC2005508},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x00000008},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000A},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_533[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0             2               4               15 */
+	{0x000016A0, 0xC002040C},
+	/*1             2               4               2 */
+	{0x000016A0, 0xC0420117},
+	/*2             2               4               27 */
+	{0x000016A0, 0xC082041B},
+	/*3             2               4               0 */
+	{0x000016A0, 0xC0C20117},
+	/*4             2               4               13 */
+	{0x000016A0, 0xC102040A},
+	/*5             2               4               5 */
+	{0x000016A0, 0xC1420117},
+	/*6             2               4               19 */
+	{0x000016A0, 0xC1820419},
+	/*7             2               4               0 */
+	{0x000016A0, 0xC1C20117},
+	/*8             2               4               10 */
+	{0x000016A0, 0xC2020117},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0008113},
+	/*1 */
+	{0x000016A0, 0xC0404504},
+	/*2 */
+	{0x000016A0, 0xC0808514},
+	/*3 */
+	{0x000016A0, 0xC0C09418},
+	/*4 */
+	{0x000016A0, 0xC1006D0E},
+	/*5 */
+	{0x000016A0, 0xC1405508},
+	/*6 */
+	{0x000016A0, 0xC1807D12},
+	/*7 */
+	{0x000016A0, 0xC1C0b01F},
+	/*8 */
+	{0x000016A0, 0xC2005D0A},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x00000008},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000A},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0             2               3               1 */
+	{0x000016A0, 0xC0020104},
+	/*1             2               2               6 */
+	{0x000016A0, 0xC0420010},
+	/*2             2               3               16 */
+	{0x000016A0, 0xC0820112},
+	/*3             2               1               26 */
+	{0x000016A0, 0xC0C20009},
+	/*4             2               2               29 */
+	{0x000016A0, 0xC102001F},
+	/*5             2               2               13 */
+	{0x000016A0, 0xC1420014},
+	/*6             2               3               6 */
+	{0x000016A0, 0xC1820109},
+	/*7             2               1               31 */
+	{0x000016A0, 0xC1C2000C},
+	/*8             2               2               22 */
+	{0x000016A0, 0xC2020112},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0009919},
+	/*1 */
+	{0x000016A0, 0xC0405508},
+	/*2 */
+	{0x000016A0, 0xC0809919},
+	/*3 */
+	{0x000016A0, 0xC0C09C1A},
+	/*4 */
+	{0x000016A0, 0xC1008113},
+	/*5 */
+	{0x000016A0, 0xC140650C},
+	/*6 */
+	{0x000016A0, 0xC1809518},
+	/*7 */
+	{0x000016A0, 0xC1C04103},
+	/*8 */
+	{0x000016A0, 0xC2006D0E},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
+
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0             2               3               1 */
+	{0x000016A0, 0xC0020103},
+	/*1            2               2               6 */
+	{0x000016A0, 0xC0420012},
+	/*2            2               3               16 */
+	{0x000016A0, 0xC0820113},
+	/*3            2               1               26 */
+	{0x000016A0, 0xC0C20012},
+	/*4            2               2               29 */
+	{0x000016A0, 0xC1020100},
+	/*5            2               2               13 */
+	{0x000016A0, 0xC1420016},
+	/*6            2               3               6 */
+	{0x000016A0, 0xC1820109},
+	/*7            2               1               31 */
+	{0x000016A0, 0xC1C20010},
+	/*8            2               2               22 */
+	{0x000016A0, 0xC2020112},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC000b11F},
+	/*1 */
+	{0x000016A0, 0xC040690D},
+	/*2 */
+	{0x000016A0, 0xC0803600},
+	/*3 */
+	{0x000016A0, 0xC0C0a81D},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC180ad1e},
+	/*7 */
+	{0x000016A0, 0xC1C04d06},
+	/*8 */
+	{0x000016A0, 0xC2008514},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_800[MV_MAX_DDR3_STATIC_SIZE] = {
+
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0             2               3               1 */
+	{0x000016A0, 0xC0020213},
+	/*1            2               2               6 */
+	{0x000016A0, 0xC0420108},
+	/*2            2               3               16 */
+	{0x000016A0, 0xC0820210},
+	/*3            2               1               26 */
+	{0x000016A0, 0xC0C20108},
+	/*4            2               2               29 */
+	{0x000016A0, 0xC102011A},
+	/*5            2               2               13 */
+	{0x000016A0, 0xC1420300},
+	/*6            2               3               6 */
+	{0x000016A0, 0xC1820204},
+	/*7            2               1               31 */
+	{0x000016A0, 0xC1C20106},
+	/*8            2               2               22 */
+	{0x000016A0, 0xC2020112},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC000620B},
+	/*1 */
+	{0x000016A0, 0xC0408D16},
+	/*2 */
+	{0x000016A0, 0xC0806A0D},
+	/*3 */
+	{0x000016A0, 0xC0C03D02},
+	/*4 */
+	{0x000016A0, 0xC1004a05},
+	/*5 */
+	{0x000016A0, 0xC140A11B},
+	/*6 */
+	{0x000016A0, 0xC1805E0A},
+	/*7 */
+	{0x000016A0, 0xC1C06D0E},
+	/*8 */
+	{0x000016A0, 0xC200AD1E},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000C},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000E},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_0[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0 */
+	{0x000016A0, 0xC002010E},
+	/*1 */
+	{0x000016A0, 0xC042001E},
+	/*2 */
+	{0x000016A0, 0xC0820118},
+	/*3 */
+	{0x000016A0, 0xC0C2001E},
+	/*4 */
+	{0x000016A0, 0xC102010C},
+	/*5 */
+	{0x000016A0, 0xC1420102},
+	/*6 */
+	{0x000016A0, 0xC1820111},
+	/*7 */
+	{0x000016A0, 0xC1C2001C},
+	/*8 */
+	{0x000016A0, 0xC2020109},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0003600},
+	/*1 */
+	{0x000016A0, 0xC040690D},
+	/*2 */
+	{0x000016A0, 0xC0805207},
+	/*3 */
+	{0x000016A0, 0xC0C0A81D},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC1803E02},
+	/*7 */
+	{0x000016A0, 0xC1C05107},
+	/*8 */
+	{0x000016A0, 0xC2008113},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_1[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0 */
+	{0x000016A0, 0xC0020106},
+	/*1 */
+	{0x000016A0, 0xC0420016},
+	/*2 */
+	{0x000016A0, 0xC0820117},
+	/*3 */
+	{0x000016A0, 0xC0C2000F},
+	/*4 */
+	{0x000016A0, 0xC1020105},
+	/*5 */
+	{0x000016A0, 0xC142001B},
+	/*6 */
+	{0x000016A0, 0xC182010C},
+	/*7 */
+	{0x000016A0, 0xC1C20011},
+	/*8 */
+	{0x000016A0, 0xC2020101},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0003600},
+	/*1 */
+	{0x000016A0, 0xC0406D0E},
+	/*2 */
+	{0x000016A0, 0xC0803600},
+	/*3 */
+	{0x000016A0, 0xC0C04504},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC1803600},
+	/*7 */
+	{0x000016A0, 0xC1C0610B},
+	/*8 */
+	{0x000016A0, 0xC2008113},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_2[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0 */
+	{0x000016A0, 0xC002010C},
+	/*1 */
+	{0x000016A0, 0xC042001B},
+	/*2 */
+	{0x000016A0, 0xC082011D},
+	/*3 */
+	{0x000016A0, 0xC0C20015},
+	/*4 */
+	{0x000016A0, 0xC102010B},
+	/*5 */
+	{0x000016A0, 0xC1420101},
+	/*6 */
+	{0x000016A0, 0xC1820113},
+	/*7 */
+	{0x000016A0, 0xC1C20017},
+	/*8 */
+	{0x000016A0, 0xC2020107},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0003600},
+	/*1 */
+	{0x000016A0, 0xC0406D0E},
+	/*2 */
+	{0x000016A0, 0xC0803600},
+	/*3 */
+	{0x000016A0, 0xC0C04504},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC180B11F},
+	/*7 */
+	{0x000016A0, 0xC1C0610B},
+	/*8 */
+	{0x000016A0, 0xC2008113},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_667_M[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/* CS 0 */
+	/*0             2               3               1 */
+	{0x000016A0, 0xC0020103},
+	/*1            2               2               6 */
+	{0x000016A0, 0xC0420012},
+	/*2            2               3               16 */
+	{0x000016A0, 0xC0820113},
+	/*3            2               1               26 */
+	{0x000016A0, 0xC0C20012},
+	/*4            2               2               29 */
+	{0x000016A0, 0xC1020100},
+	/*5            2               2               13 */
+	{0x000016A0, 0xC1420016},
+	/*6            2               3               6 */
+	{0x000016A0, 0xC1820109},
+	/*7            2               1               31 */
+	{0x000016A0, 0xC1C20010},
+	/*8            2               2               22 */
+	{0x000016A0, 0xC2020112},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC000b11F},
+	/*1 */
+	{0x000016A0, 0xC040690D},
+	/*2 */
+	{0x000016A0, 0xC0803600},
+	/*3 */
+	{0x000016A0, 0xC0C0a81D},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC180ad1e},
+	/*7 */
+	{0x000016A0, 0xC1C04d06},
+	/*8 */
+	{0x000016A0, 0xC2008514},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	/* CS 1 */
+
+	{0x000016A0, 0xC0060103},
+	/*1            2               2               6 */
+	{0x000016A0, 0xC0460012},
+	/*2            2               3               16 */
+	{0x000016A0, 0xC0860113},
+	/*3            2               1               26 */
+	{0x000016A0, 0xC0C60012},
+	/*4            2               2               29 */
+	{0x000016A0, 0xC1060100},
+	/*5            2               2               13 */
+	{0x000016A0, 0xC1460016},
+	/*6            2               3               6 */
+	{0x000016A0, 0xC1860109},
+	/*7            2               1               31 */
+	{0x000016A0, 0xC1C60010},
+	/*8            2               2               22 */
+	{0x000016A0, 0xC2060112},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC004b11F},
+	/*1 */
+	{0x000016A0, 0xC044690D},
+	/*2 */
+	{0x000016A0, 0xC0843600},
+	/*3 */
+	{0x000016A0, 0xC0C4a81D},
+	/*4 */
+	{0x000016A0, 0xC1049919},
+	/*5 */
+	{0x000016A0, 0xC1447911},
+	/*6 */
+	{0x000016A0, 0xC184ad1e},
+	/*7 */
+	{0x000016A0, 0xC1C44d06},
+	/*8 */
+	{0x000016A0, 0xC2048514},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC807000F},
+
+	/* Both CS */
+
+	{0x00001538, 0x00000B0B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x00000F0F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_3[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0 */
+	{0x000016A0, 0xC0020118},
+	/*1 */
+	{0x000016A0, 0xC0420108},
+	/*2 */
+	{0x000016A0, 0xC0820202},
+	/*3 */
+	{0x000016A0, 0xC0C20108},
+	/*4 */
+	{0x000016A0, 0xC1020117},
+	/*5 */
+	{0x000016A0, 0xC142010C},
+	/*6 */
+	{0x000016A0, 0xC182011B},
+	/*7 */
+	{0x000016A0, 0xC1C20107},
+	/*8 */
+	{0x000016A0, 0xC2020113},
+
+	/* Write Leveling */
+	/*0 */
+	{0x000016A0, 0xC0003600},
+	/*1 */
+	{0x000016A0, 0xC0406D0E},
+	/*2 */
+	{0x000016A0, 0xC0805207},
+	/*3 */
+	{0x000016A0, 0xC0C0A81D},
+	/*4 */
+	{0x000016A0, 0xC1009919},
+	/*5 */
+	{0x000016A0, 0xC1407911},
+	/*6 */
+	{0x000016A0, 0xC1803E02},
+	/*7 */
+	{0x000016A0, 0xC1C04D06},
+	/*8 */
+	{0x000016A0, 0xC2008113},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+
+	{0x00001538, 0x0000000B},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000F},	/*Read Data Ready Delay Register */
+
+	/*init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_pcac_600[MV_MAX_DDR3_STATIC_SIZE] = {
+	/* Read Leveling */
+	/*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+	/*0 */
+	{0x000016A0, 0xC0020404},
+	/* 1           2               2               6 */
+	{0x000016A0, 0xC042031E},
+	/* 2           2               3               16 */
+	{0x000016A0, 0xC0820411},
+	/* 3           2               1               26 */
+	{0x000016A0, 0xC0C20400},
+	/* 4           2               2               29 */
+	{0x000016A0, 0xC1020404},
+	/* 5           2               2               13 */
+	{0x000016A0, 0xC142031D},
+	/* 6           2               3               6 */
+	{0x000016A0, 0xC182040C},
+	/* 7           2               1               31 */
+	{0x000016A0, 0xC1C2031B},
+	/* 8           2               2               22 */
+	{0x000016A0, 0xC2020112},
+
+	/*  Write Leveling */
+	/* 0 */
+	{0x000016A0, 0xC0004905},
+	/* 1 */
+	{0x000016A0, 0xC040A81D},
+	/* 2 */
+	{0x000016A0, 0xC0804504},
+	/* 3 */
+	{0x000016A0, 0xC0C08013},
+	/* 4 */
+	{0x000016A0, 0xC1004504},
+	/* 5 */
+	{0x000016A0, 0xC140A81D},
+	/* 6 */
+	{0x000016A0, 0xC1805909},
+	/* 7 */
+	{0x000016A0, 0xC1C09418},
+	/* 8 */
+	{0x000016A0, 0xC2006D0E},
+
+	/*center DQS on read cycle */
+	{0x000016A0, 0xC803000F},
+	{0x00001538, 0x00000009},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x0000000D},	/*Read Data Ready Delay Register */
+	/* init DRAM */
+	{0x00001480, 0x00000001},
+	{0x0, 0x0}
+};
+
+#endif /* __AXP_TRAINING_STATIC_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_vars.h b/drivers/ddr/mvebu/ddr3_axp_vars.h
new file mode 100644
index 0000000..1b0ab56
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_axp_vars.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __AXP_VARS_H
+#define __AXP_VARS_H
+
+#include "ddr3_axp_config.h"
+#include "ddr3_axp_mc_static.h"
+#include "ddr3_axp_training_static.h"
+
+MV_DRAM_MODES ddr_modes[MV_DDR3_MODES_NUMBER] = {
+	/*      Conf name               CPUFreq         FabFreq         Chip ID Chip/Board      MC regs                 Training Values */
+	/* db board values: */
+	{"db_800-400", 0xA, 0x5, 0x0, A0, ddr3_A0_db_400, NULL},
+	{"db_1200-300", 0x2, 0xC, 0x0, A0, ddr3_A0_db_400, NULL},
+	{"db_1200-600", 0x2, 0x5, 0x0, A0, NULL, NULL},
+	{"db_1333-667", 0x3, 0x5, 0x0, A0, ddr3_A0_db_667, ddr3_db_rev2_667},
+	{"db_1600-800", 0xB, 0x5, 0x0, A0, ddr3_A0_db_667, ddr3_db_rev2_800},
+	{"amc_1333-667", 0x3, 0x5, 0x0, A0_AMC, ddr3_A0_AMC_667, NULL},
+	{"db_667-667", 0x9, 0x13, 0x0, Z1, ddr3_Z1_db_600, ddr3_db_667},
+	{"db_800-400", 0xA, 0x1, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_400},
+	{"db_1066-533", 0x1, 0x1, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_533},
+	{"db_1200-300", 0x2, 0xC, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_667},
+	{"db_1200-600", 0x2, 0x5, 0x0, Z1, ddr3_Z1_db_600, NULL},
+	{"db_1333-333", 0x3, 0xC, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_400},
+	{"db_1333-667", 0x3, 0x5, 0x0, Z1, ddr3_Z1_db_600, ddr3_db_667},
+	/* pcac board values (Z1 device): */
+	{"pcac_1200-600", 0x2, 0x5, 0x0, Z1_PCAC, ddr3_Z1_db_600,
+	 ddr3_pcac_600},
+	/* rd board values (Z1 device): */
+	{"rd_667_0", 0x3, 0x5, 0x0, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_0},
+	{"rd_667_1", 0x3, 0x5, 0x1, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_1},
+	{"rd_667_2", 0x3, 0x5, 0x2, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_2},
+	{"rd_667_3", 0x3, 0x5, 0x3, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_3}
+};
+
+/* ODT settings - if needed update the following tables: (ODT_OPT - represents the CS configuration bitmap) */
+
+u16 odt_static[ODT_OPT][MAX_CS] = {	/*        NearEnd/FarEnd */
+	{0, 0, 0, 0},		/* 0000         0/0 - Not supported */
+	{ODT40, 0, 0, 0},	/* 0001         0/1 */
+	{0, 0, 0, 0},		/* 0010         0/0 - Not supported */
+	{ODT40, ODT40, 0, 0},	/* 0011         0/2 */
+	{0, 0, ODT40, 0},	/* 0100         1/0 */
+	{ODT30, 0, ODT30, 0},	/* 0101         1/1 */
+	{0, 0, 0, 0},		/* 0110         0/0 - Not supported */
+	{ODT120, ODT20, ODT20, 0},	/* 0111         1/2 */
+	{0, 0, 0, 0},		/* 1000         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1001         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1010         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1011         0/0 - Not supported */
+	{0, 0, ODT40, 0},	/* 1100         2/0 */
+	{ODT20, 0, ODT120, ODT20},	/* 1101         2/1 */
+	{0, 0, 0, 0},		/* 1110         0/0 - Not supported */
+	{ODT120, ODT30, ODT120, ODT30}	/* 1111         2/2 */
+};
+
+u16 odt_dynamic[ODT_OPT][MAX_CS] = {	/*        NearEnd/FarEnd */
+	{0, 0, 0, 0},		/* 0000         0/0 */
+	{0, 0, 0, 0},		/* 0001         0/1 */
+	{0, 0, 0, 0},		/* 0010         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 0011         0/2 */
+	{0, 0, 0, 0},		/* 0100         1/0 */
+	{ODT120D, 0, ODT120D, 0},	/* 0101         1/1 */
+	{0, 0, 0, 0},		/* 0110         0/0 - Not supported */
+	{0, 0, ODT120D, 0},	/* 0111         1/2 */
+	{0, 0, 0, 0},		/* 1000         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1001         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1010         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1011         0/0 - Not supported */
+	{0, 0, 0, 0},		/* 1100         2/0 */
+	{ODT120D, 0, 0, 0},	/* 1101         2/1 */
+	{0, 0, 0, 0},		/* 1110         0/0 - Not supported */
+	{0, 0, 0, 0}		/* 1111         2/2 */
+};
+
+u32 odt_config[ODT_OPT] = {
+	0, 0x00010000, 0, 0x00030000, 0x04000000, 0x05050104, 0, 0x07430340, 0,
+	    0, 0, 0,
+	0x30000, 0x1C0D100C, 0, 0x3CC330C0
+};
+
+/*
+ * User can manually set SPD values (in case SPD is not available on
+ * DIMM/System).
+ * SPD Values can simplify calculating the DUNIT registers values
+ */
+u8 spd_data[SPD_SIZE] = {
+	/* AXP DB Board DIMM SPD Values - manually set */
+	0x92, 0x10, 0x0B, 0x2, 0x3, 0x19, 0x0, 0x9, 0x09, 0x52, 0x1, 0x8, 0x0C,
+	0x0, 0x7E, 0x0, 0x69, 0x78,
+	0x69, 0x30, 0x69, 0x11, 0x20, 0x89, 0x0, 0x5, 0x3C, 0x3C, 0x0, 0xF0,
+	0x82, 0x5, 0x80, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0F, 0x1, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x80, 0x2C, 0x1, 0x10, 0x23, 0x35, 0x28, 0xEB, 0xCA, 0x19, 0x8F
+};
+
+/*
+ * Controller Specific configurations Starts Here - DO NOT MODIFY
+ */
+
+/* Frequency - values are 1/HCLK in ps */
+u32 cpu_fab_clk_to_hclk[FAB_OPT][CLK_CPU] =
+/* CPU Frequency:
+	1000	1066	1200	1333	1500	1666	1800	2000	600		667		800		1600	Fabric */
+{
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 2500, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 4500, 3750, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{4000, 3750, 3333, 3000, 2666, 2400, 0, 0, 0, 0, 5000, 2500},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 5000, 0, 4000, 0, 0, 0, 0, 0, 0, 3750},
+	{5000, 0, 0, 3750, 3333, 0, 0, 0, 0, 0, 0, 3125},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 3330, 3000, 0, 0, 0, 0, 0, 0, 0, 2500},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3750},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 2500, 0},
+	{3000, 0, 2500, 0, 0, 0, 0, 0, 0, 0, 3750, 0}
+};
+
+u32 cpu_ddr_ratios[FAB_OPT][CLK_CPU] =
+/* CPU Frequency:
+	1000	1066	1200	1333	1500	1666	1800	2000	600		667		800		1600	Fabric */
+{
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_333, DDR_400, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_444, DDR_533, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, DDR_400, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{DDR_500, DDR_533, DDR_600, DDR_666, DDR_750, DDR_833, 0, 0, 0, 0,
+	 DDR_400, DDR_800},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_333, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{DDR_400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, DDR_400, 0, DDR_500, 0, 0, 0, 0, 0, 0, DDR_533},
+	{DDR_400, 0, 0, DDR_533, DDR_600, 0, 0, 0, 0, 0, 0, DDR_640},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, DDR_300, DDR_333, 0, 0, 0, 0, 0, 0, 0, DDR_400},
+	{0, 0, 0, 0, 0, 0, DDR_600, DDR_666, 0, 0, 0, DDR_533},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_666, DDR_800, 0},
+	{DDR_666, 0, DDR_800, 0, 0, 0, 0, 0, 0, 0, DDR_533, 0}
+};
+
+u8 div_ratio1to1[CLK_VCO][CLK_DDR] =
+/* DDR Frequency:
+	100		300	360	400	444	500	533	600	666	750	800	833  */
+{ {0xA, 3, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1000  */
+{0xB, 3, 0, 3, 0, 0, 2, 0, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1066  */
+{0xC, 4, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1200  */
+{0xD, 4, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0},	/*      1:1     CLK_CPU_1333  */
+{0xF, 5, 0, 4, 0, 3, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1500  */
+{0x11, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1666  */
+{0x12, 6, 5, 4, 0, 0, 0, 3, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1800  */
+{0x14, 7, 0, 5, 0, 4, 0, 0, 3, 0, 0, 0},	/*      1:1     CLK_CPU_2000  */
+{0x6, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1 CLK_CPU_600   */
+{0x6, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_667   */
+{0x8, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1 CLK_CPU_800   */
+{0x10, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1 CLK_CPU_1600   */
+{0x14, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1000 VCO_2000 */
+{0x15, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1066 VCO_2133 */
+{0x18, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0},	/*  1:1     CLK_CPU_1200 VCO_2400 */
+{0x1A, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1333 VCO_2666 */
+{0x1E, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1500 VCO_3000 */
+{0x21, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1666 VCO_3333 */
+{0x24, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_1800 VCO_3600 */
+{0x28, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_2000 VCO_4000 */
+{0xC, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1 CLK_CPU_600 VCO_1200 */
+{0xD, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},	/*      1:1     CLK_CPU_667 VCO_1333 */
+{0x10, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},	/*  1:1 CLK_CPU_800 VCO_1600 */
+{0x20, 10, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0}	/*      1:1 CLK_CPU_1600 VCO_3200 */
+};
+
+u8 div_ratio2to1[CLK_VCO][CLK_DDR] =
+/* DDR Frequency:
+		100	300	360	400	444	500	533	600	666	750	800	833  */
+{ {0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0},	/*      2:1     CLK_CPU_1000  */
+{0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1066  */
+{0, 0, 0, 3, 5, 0, 0, 2, 0, 0, 3, 3},	/*      2:1     CLK_CPU_1200  */
+{0, 0, 0, 0, 0, 0, 5, 0, 2, 0, 3, 0},	/*      2:1     CLK_CPU_1333  */
+{0, 0, 0, 0, 0, 3, 0, 5, 0, 2, 0, 0},	/*      2:1     CLK_CPU_1500  */
+{0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 2},	/*      2:1     CLK_CPU_1666  */
+{0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 0},	/*      2:1     CLK_CPU_1800  */
+{0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 5},	/*      2:1     CLK_CPU_2000  */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_600   */
+{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},	/*  2:1 CLK_CPU_667   */
+{0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0},	/*      2:1 CLK_CPU_800   */
+{0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0},	/*      2:1 CLK_CPU_1600   */
+{0, 0, 0, 5, 0, 0, 0, 0, 3, 0, 0, 0},	/*      2:1     CLK_CPU_1000 VCO_2000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1066 VCO_2133 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0},	/*      2:1     CLK_CPU_1200 VCO_2400 */
+{0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1333 VCO_2666 */
+{0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1500 VCO_3000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1666 VCO_3333 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_1800 VCO_3600 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_2000 VCO_4000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*      2:1     CLK_CPU_600 VCO_1200 */
+{0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0},	/*  2:1 CLK_CPU_667 VCO_1333 */
+{0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0},	/*      2:1 CLK_CPU_800 VCO_1600 */
+{0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0}	/*      2:1 CLK_CPU_1600 VCO_3200 */
+};
+
+#endif /* __AXP_VARS_H */
diff --git a/drivers/ddr/mvebu/ddr3_dfs.c b/drivers/ddr/mvebu/ddr3_dfs.c
new file mode 100644
index 0000000..9347773
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_dfs.c
@@ -0,0 +1,1552 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_DFS_C(s, d, l) \
+	DEBUG_DFS_S(s); DEBUG_DFS_D(d, l); DEBUG_DFS_S("\n")
+#define DEBUG_DFS_FULL_C(s, d, l) \
+	DEBUG_DFS_FULL_S(s); DEBUG_DFS_FULL_D(d, l); DEBUG_DFS_FULL_S("\n")
+
+#ifdef MV_DEBUG_DFS
+#define DEBUG_DFS_S(s)			puts(s)
+#define DEBUG_DFS_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_DFS_S(s)
+#define DEBUG_DFS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_DFS_FULL
+#define DEBUG_DFS_FULL_S(s)		puts(s)
+#define DEBUG_DFS_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_DFS_FULL_S(s)
+#define DEBUG_DFS_FULL_D(d, l)
+#endif
+
+#if defined(MV88F672X)
+extern u8 div_ratio[CLK_VCO][CLK_DDR];
+extern void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps);
+#else
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+extern u8 div_ratio1to1[CLK_CPU][CLK_DDR];
+extern u8 div_ratio2to1[CLK_CPU][CLK_DDR];
+#endif
+extern u16 odt_static[ODT_OPT][MAX_CS];
+
+extern u32 cpu_fab_clk_to_hclk[FAB_OPT][CLK_CPU];
+
+extern u32 ddr3_get_vco_freq(void);
+
+u32 ddr3_get_freq_parameter(u32 target_freq, int ratio_2to1);
+
+#ifdef MV_DEBUG_DFS
+static inline void dfs_reg_write(u32 addr, u32 val)
+{
+	printf("\n write reg 0x%08x = 0x%08x", addr, val);
+	writel(val, INTER_REGS_BASE + addr);
+}
+#else
+static inline void dfs_reg_write(u32 addr, u32 val)
+{
+	writel(val, INTER_REGS_BASE + addr);
+}
+#endif
+
+static void wait_refresh_op_complete(void)
+{
+	u32 reg;
+
+	/* Poll - Wait for Refresh operation completion */
+	do {
+		reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+			REG_SDRAM_OPERATION_CMD_RFRS_DONE;
+	} while (reg);		/* Wait for '0' */
+}
+
+/*
+ * Name:     ddr3_get_freq_parameter
+ * Desc:     Finds CPU/DDR frequency ratio according to Sample@reset and table.
+ * Args:     target_freq - target frequency
+ * Notes:
+ * Returns:  freq_par - the ratio parameter
+ */
+u32 ddr3_get_freq_parameter(u32 target_freq, int ratio_2to1)
+{
+	u32 ui_vco_freq, freq_par;
+
+	ui_vco_freq = ddr3_get_vco_freq();
+
+#if defined(MV88F672X)
+	freq_par = div_ratio[ui_vco_freq][target_freq];
+#else
+	/* Find the ratio between PLL frequency and ddr-clk */
+	if (ratio_2to1)
+		freq_par = div_ratio2to1[ui_vco_freq][target_freq];
+	else
+		freq_par = div_ratio1to1[ui_vco_freq][target_freq];
+#endif
+
+	return freq_par;
+}
+
+/*
+ * Name:     ddr3_dfs_high_2_low
+ * Desc:
+ * Args:     freq - target frequency
+ * Notes:
+ * Returns:  MV_OK - success, MV_FAIL - fail
+ */
+int ddr3_dfs_high_2_low(u32 freq, MV_DRAM_INFO *dram_info)
+{
+#if defined(MV88F78X60) || defined(MV88F672X)
+	/* This Flow is relevant for ArmadaXP A0 */
+	u32 reg, freq_par, tmp;
+	u32 cs = 0;
+
+	DEBUG_DFS_C("DDR3 - DFS - High To Low - Starting DFS procedure to Frequency - ",
+		    freq, 1);
+
+	/* target frequency - 100MHz */
+	freq_par = ddr3_get_freq_parameter(freq, 0);
+
+#if defined(MV88F672X)
+	u32 hclk;
+	u32 cpu_freq = ddr3_get_cpu_freq();
+	get_target_freq(cpu_freq, &tmp, &hclk);
+#endif
+
+	/* Configure - DRAM DLL final state after DFS is complete - Enable */
+	reg = reg_read(REG_DFS_ADDR);
+	/* [0] - DfsDllNextState - Disable */
+	reg |= (1 << REG_DFS_DLLNEXTSTATE_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Configure - XBAR Retry response during Block to enable internal
+	 * access - Disable
+	 */
+	reg = reg_read(REG_METAL_MASK_ADDR);
+	/* [0] - RetryMask - Disable */
+	reg &= ~(1 << REG_METAL_MASK_RETRY_OFFS);
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	/* Configure - Block new external transactions - Enable */
+	reg = reg_read(REG_DFS_ADDR);
+	reg |= (1 << REG_DFS_BLOCK_OFFS);	/* [1] - DfsBlock - Enable  */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Registered DIMM support */
+	if (dram_info->reg_dimm) {
+		/*
+		 * Configure - Disable Register DIMM CKE Power
+		 * Down mode - CWA_RC
+		 */
+		reg = (0x9 & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+			REG_SDRAM_OPERATION_CWA_RC_OFFS;
+		/*
+		 * Configure - Disable Register DIMM CKE Power
+		 * Down mode - CWA_DATA
+		 */
+		reg |= ((0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+			REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+
+		/*
+		 * Configure - Disable Register DIMM CKE Power
+		 * Down mode - Set Delay - tMRD
+		 */
+		reg |= (0 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+
+		/* Configure - Issue CWA command with the above parameters */
+		reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+			~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+		/* 0x1418 - SDRAM Operation Register */
+		dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+		/* Poll - Wait for CWA operation completion */
+		do {
+			reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+			       (REG_SDRAM_OPERATION_CMD_MASK);
+		} while (reg);
+
+		/* Configure - Disable outputs floating during Self Refresh */
+		reg = reg_read(REG_REGISTERED_DRAM_CTRL_ADDR);
+		/* [15] - SRFloatEn - Disable */
+		reg &= ~(1 << REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS);
+		/* 0x16D0 - DDR3 Registered DRAM Control */
+		dfs_reg_write(REG_REGISTERED_DRAM_CTRL_ADDR, reg);
+	}
+
+	/* Optional - Configure - DDR3_Rtt_nom_CS# */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS));
+			reg &= REG_DDR3_MR1_RTT_MASK;
+			dfs_reg_write(REG_DDR3_MR1_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* Configure - Move DRAM into Self Refresh */
+	reg = reg_read(REG_DFS_ADDR);
+	reg |= (1 << REG_DFS_SR_OFFS);	/* [2] - DfsSR - Enable */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Poll - Wait for Self Refresh indication */
+	do {
+		reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+	} while (reg == 0x0);	/* 0x1528 [3] - DfsAtSR - Wait for '1' */
+
+	/* Start of clock change procedure (PLL) */
+#if defined(MV88F672X)
+	/* avantaLP */
+	/* Configure    cpupll_clkdiv_reset_mask */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL0_MASK;
+	/* 0xE8264[7:0]   0xff CPU Clock Dividers Reset mask */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, (reg + 0xFF));
+
+	/* Configure    cpu_clkdiv_reload_smooth    */
+	reg = reg_read(CPU_PLL_CNTRL0);
+	reg &= CPU_PLL_CNTRL0_RELOAD_SMOOTH_MASK;
+	/* 0xE8260   [15:8]  0x2 CPU Clock Dividers Reload Smooth enable */
+	dfs_reg_write(CPU_PLL_CNTRL0,
+		      (reg + (2 << CPU_PLL_CNTRL0_RELOAD_SMOOTH_OFFS)));
+
+	/* Configure    cpupll_clkdiv_relax_en */
+	reg = reg_read(CPU_PLL_CNTRL0);
+	reg &= CPU_PLL_CNTRL0_RELAX_EN_MASK;
+	/* 0xE8260 [31:24] 0x2 Relax Enable */
+	dfs_reg_write(CPU_PLL_CNTRL0,
+		      (reg + (2 << CPU_PLL_CNTRL0_RELAX_EN_OFFS)));
+
+	/* Configure    cpupll_clkdiv_ddr_clk_ratio */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL1);
+	/*
+	 * 0xE8268  [13:8]  N   Set Training clock:
+	 * APLL Out Clock (VCO freq) / N = 100 MHz
+	 */
+	reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL1_MASK;
+	reg |= (freq_par << 8);	/* full Integer ratio from PLL-out to ddr-clk */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL1, reg);
+
+	/* Configure    cpupll_clkdiv_reload_ratio  */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+	/* 0xE8264 [8]=0x1 CPU Clock Dividers Reload Ratio trigger set */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0,
+		      (reg + (1 << CPU_PLL_CLOCK_RELOAD_RATIO_OFFS)));
+
+	udelay(1);
+
+	/* Configure    cpupll_clkdiv_reload_ratio  */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+	/* 0xE8264 [8]=0x0 CPU Clock Dividers Reload Ratio trigger clear */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, reg);
+
+	udelay(5);
+
+#else
+	/*
+	 * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+	 * and in the same chance, block reassertions of reset [15:8] and
+	 * force reserved bits[7:0].
+	 */
+	reg = 0x0000FDFF;
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	/*
+	 * RelaX whenever reset is asserted to that channel
+	 * (good for any case)
+	 */
+	reg = 0x0000FF00;
+	/* 0x18704 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	reg = reg_read(REG_CPU_DIV_CLK_CTRL_2_ADDR) &
+		REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+
+	/* full Integer ratio from PLL-out to ddr-clk */
+	reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+	/* 0x1870C - CPU Div CLK control 3 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_2_ADDR, reg);
+
+	/*
+	 * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+	 * All the rest are kept as is (forced, but could be read-modify-write).
+	 * This is done now by RMW above.
+	 */
+
+	/* Clock is not shut off gracefully - keep it running */
+	reg = 0x000FFF02;
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+	/* Wait before replacing the clock on the DDR Phy Channel. */
+	udelay(1);
+
+	/*
+	 * This for triggering the frequency update. Bit[24] is the
+	 * central control
+	 * bits [23:16] == which channels to change ==2 ==>
+	 *                 only DDR Phy (smooth transition)
+	 * bits [15:8] == mask reset reassertion due to clock modification
+	 *                to these channels.
+	 * bits [7:0] == not in use
+	 */
+	reg = 0x0102FDFF;
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(1);		/* Wait 1usec */
+
+	/*
+	 * Poll Div CLK status 0 register - indication that the clocks
+	 * are active - 0x18718 [8]
+	 */
+	do {
+		reg = (reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR)) &
+			(1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+	} while (reg == 0);
+
+	/*
+	 * Clean the CTRL0, to be ready for next resets and next requests
+	 * of ratio modifications.
+	 */
+	reg = 0x000000FF;
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(5);
+#endif
+	/* End of clock change procedure (PLL) */
+
+	/* Configure - Select normal clock for the DDR PHY - Enable */
+	reg = reg_read(REG_DRAM_INIT_CTRL_STATUS_ADDR);
+	/* [16] - ddr_phy_trn_clk_sel - Enable  */
+	reg |= (1 << REG_DRAM_INIT_CTRL_TRN_CLK_OFFS);
+	/* 0x18488 - DRAM Init control status register */
+	dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+	/* Configure - Set Correct Ratio - 1:1 */
+	/* [15] - Phy2UnitClkRatio = 0 - Set 1:1 Ratio between Dunit and Phy */
+
+	reg = reg_read(REG_DDR_IO_ADDR) & ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	dfs_reg_write(REG_DDR_IO_ADDR, reg);	/* 0x1524 - DDR IO Register */
+
+	/* Configure - 2T Mode - Restore original configuration */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	/* [3:4] 2T - 1T Mode - low freq */
+	reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+	/* 0x1404 - DDR Controller Control Low Register */
+	dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+	/* Configure - Restore CL and CWL - MRS Commands */
+	reg = reg_read(REG_DFS_ADDR);
+	reg &= ~(REG_DFS_CL_NEXT_STATE_MASK << REG_DFS_CL_NEXT_STATE_OFFS);
+	reg &= ~(REG_DFS_CWL_NEXT_STATE_MASK << REG_DFS_CWL_NEXT_STATE_OFFS);
+	/* [8] - DfsCLNextState - MRS CL=6 after DFS (due to DLL-off mode) */
+	reg |= (0x4 << REG_DFS_CL_NEXT_STATE_OFFS);
+	/* [12] - DfsCWLNextState - MRS CWL=6 after DFS (due to DLL-off mode) */
+	reg |= (0x1 << REG_DFS_CWL_NEXT_STATE_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Poll - Wait for APLL + ADLLs lock on new frequency */
+	do {
+		reg = (reg_read(REG_PHY_LOCK_STATUS_ADDR)) &
+			REG_PHY_LOCK_APLL_ADLL_STATUS_MASK;
+		/* 0x1674 [10:0] - Phy lock status Register */
+	} while (reg != REG_PHY_LOCK_APLL_ADLL_STATUS_MASK);
+
+	/* Configure - Reset the PHY Read FIFO and Write channels - Set Reset */
+	reg = (reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK);
+	/* [30:29] = 0 - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/*
+	 * Configure - DRAM Data PHY Read [30], Write [29] path
+	 * reset - Release Reset
+	 */
+	reg = (reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK);
+	/* [30:29] = '11' - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/* Registered DIMM support */
+	if (dram_info->reg_dimm) {
+		/*
+		 * Configure - Change register DRAM operating speed
+		 * (below 400MHz) - CWA_RC
+		 */
+		reg = (0xA & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+			REG_SDRAM_OPERATION_CWA_RC_OFFS;
+
+		/*
+		 * Configure - Change register DRAM operating speed
+		 * (below 400MHz) - CWA_DATA
+		 */
+		reg |= ((0x0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+			REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+
+		/* Configure - Set Delay - tSTAB */
+		reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+
+		/* Configure - Issue CWA command with the above parameters */
+		reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+			~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+		/* 0x1418 - SDRAM Operation Register */
+		dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+		/* Poll - Wait for CWA operation completion */
+		do {
+			reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+				(REG_SDRAM_OPERATION_CMD_MASK);
+		} while (reg);
+	}
+
+	/* Configure - Exit Self Refresh */
+	/* [2] - DfsSR  */
+	reg = (reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS));
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll - DFS Register - 0x1528 [3] - DfsAtSR - All DRAM devices
+	 * on all ranks are NOT in self refresh mode
+	 */
+	do {
+		reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+	} while (reg);		/* Wait for '0' */
+
+	/* Configure - Issue Refresh command */
+	/* [3-0] = 0x2 - Refresh Command, [11-8] - enabled Cs */
+	reg = REG_SDRAM_OPERATION_CMD_RFRS;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs))
+			reg &= ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+	}
+
+	/* 0x1418 - SDRAM Operation Register */
+	dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+	/* Poll - Wait for Refresh operation completion */
+	wait_refresh_op_complete();
+
+	/* Configure - Block new external transactions - Disable */
+	reg = reg_read(REG_DFS_ADDR);
+	reg &= ~(1 << REG_DFS_BLOCK_OFFS);	/* [1] - DfsBlock - Disable  */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Configure -  XBAR Retry response during Block to enable
+	 * internal access - Disable
+	 */
+	reg = reg_read(REG_METAL_MASK_ADDR);
+	/* [0] - RetryMask - Enable */
+	reg |= (1 << REG_METAL_MASK_RETRY_OFFS);
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			/* Configure - Set CL */
+			reg = reg_read(REG_DDR3_MR0_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS)) &
+				~REG_DDR3_MR0_CL_MASK;
+			tmp = 0x4;	/* CL=6 - 0x4 */
+			reg |= ((tmp & 0x1) << REG_DDR3_MR0_CL_OFFS);
+			reg |= ((tmp & 0xE) << REG_DDR3_MR0_CL_HIGH_OFFS);
+			dfs_reg_write(REG_DDR3_MR0_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+
+			/* Configure - Set CWL */
+			reg = reg_read(REG_DDR3_MR2_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS))
+				& ~(REG_DDR3_MR2_CWL_MASK << REG_DDR3_MR2_CWL_OFFS);
+			/* CWL=6 - 0x1 */
+			reg |= ((0x1) << REG_DDR3_MR2_CWL_OFFS);
+			dfs_reg_write(REG_DDR3_MR2_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	DEBUG_DFS_C("DDR3 - DFS - High To Low - Ended successfuly - new Frequency - ",
+		    freq, 1);
+
+	return MV_OK;
+#else
+	/* This Flow is relevant for Armada370 A0 and ArmadaXP Z1 */
+
+	u32 reg, freq_par;
+	u32 cs = 0;
+
+	DEBUG_DFS_C("DDR3 - DFS - High To Low - Starting DFS procedure to Frequency - ",
+		    freq, 1);
+
+	/* target frequency - 100MHz */
+	freq_par = ddr3_get_freq_parameter(freq, 0);
+
+	reg = 0x0000FF00;
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	/* 0x1600 - ODPG_CNTRL_Control */
+	reg = reg_read(REG_ODPG_CNTRL_ADDR);
+	/* [21] = 1 - auto refresh disable */
+	reg |= (1 << REG_ODPG_CNTRL_OFFS);
+	dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+	/* 0x1670 - PHY lock mask register */
+	reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+	reg &= REG_PHY_LOCK_MASK_MASK;	/* [11:0] = 0 */
+	dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+	reg = reg_read(REG_DFS_ADDR);	/* 0x1528 - DFS register */
+
+	/* Disable reconfig */
+	reg &= ~0x10;	/* [4] - Enable reconfig MR registers after DFS_ERG */
+	reg |= 0x1;	/* [0] - DRAM DLL disabled after DFS */
+
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	reg = reg_read(REG_METAL_MASK_ADDR) & ~(1 << 0); /* [0] - disable */
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	/* [1] - DFS Block enable  */
+	reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_BLOCK_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* [2] - DFS Self refresh enable  */
+	reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_SR_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll DFS Register - 0x1528 [3] - DfsAtSR -
+	 * All DRAM devices on all ranks are in self refresh mode -
+	 * DFS can be executed afterwards
+	 */
+	do {
+		reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+	} while (reg == 0x0);	/* Wait for '1' */
+
+	/* Disable ODT on DLL-off mode */
+	dfs_reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR,
+		      REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK);
+
+	/* [11:0] = 0 */
+	reg = (reg_read(REG_PHY_LOCK_MASK_ADDR) & REG_PHY_LOCK_MASK_MASK);
+	/* 0x1670 - PHY lock mask register */
+	dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+	/* Add delay between entering SR and start ratio modification */
+	udelay(1);
+
+	/*
+	 * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+	 * and in the same chance, block reassertions of reset [15:8] and
+	 * force reserved bits[7:0].
+	 */
+	reg = 0x0000FDFF;
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	/*
+	 * RelaX whenever reset is asserted to that channel (good for any case)
+	 */
+	reg = 0x0000FF00;
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	reg = reg_read(REG_CPU_DIV_CLK_CTRL_3_ADDR) &
+		REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+	/* Full Integer ratio from PLL-out to ddr-clk */
+	reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+	/* 0x1870C - CPU Div CLK control 3 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_3_ADDR, reg);
+
+	/*
+	 * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+	 * All the rest are kept as is (forced, but could be read-modify-write).
+	 * This is done now by RMW above.
+	 */
+
+	/* Clock is not shut off gracefully - keep it running */
+	reg = 0x000FFF02;
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+	/* Wait before replacing the clock on the DDR Phy Channel. */
+	udelay(1);
+
+	/*
+	 * This for triggering the frequency update. Bit[24] is the
+	 * central control
+	 * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+	 *                 (smooth transition)
+	 * bits [15:8] == mask reset reassertion due to clock modification
+	 *                to these channels.
+	 * bits [7:0] == not in use
+	 */
+	reg = 0x0102FDFF;
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(1);		/* Wait 1usec */
+
+	/*
+	 * Poll Div CLK status 0 register - indication that the clocks
+	 * are active - 0x18718 [8]
+	 */
+	do {
+		reg = (reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR)) &
+			(1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+	} while (reg == 0);
+
+	/*
+	 * Clean the CTRL0, to be ready for next resets and next requests of
+	 * ratio modifications.
+	 */
+	reg = 0x000000FF;
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(5);
+
+	/* Switch HCLK Mux to training clk (100Mhz), keep DFS request bit */
+	reg = 0x20050000;
+	/* 0x18488 - DRAM Init control status register */
+	dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+	reg = reg_read(REG_DDR_IO_ADDR) & ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	/* [15] = 0 - Set 1:1 Ratio between Dunit and Phy */
+	dfs_reg_write(REG_DDR_IO_ADDR, reg);	/* 0x1524 - DDR IO Regist */
+
+	reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK;
+	/* [31:30]] - reset pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	reg = (reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK);
+	/* [31:30] - normal pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	udelay(1);		/* Wait 1usec */
+
+	/* 0x1404 */
+	reg = (reg_read(REG_DUNIT_CTRL_LOW_ADDR) & 0xFFFFFFE7);
+	dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+	/* Poll Phy lock status register - APLL lock indication - 0x1674 */
+	do {
+		reg = (reg_read(REG_PHY_LOCK_STATUS_ADDR)) &
+			REG_PHY_LOCK_STATUS_LOCK_MASK;
+	} while (reg != REG_PHY_LOCK_STATUS_LOCK_MASK);	/* Wait for '0xFFF' */
+
+	reg = (reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK);
+	/* [30:29] = 0 - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+	/* [30:29] = '11' - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	udelay(1000);		/* Wait 1msec */
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			/* Config CL and CWL with MR0 and MR2 registers */
+			reg = reg_read(REG_DDR3_MR0_ADDR);
+			reg &= ~0x74;	/* CL [3:0]; [6:4],[2] */
+			reg |= (1 << 5);	/* CL = 4, CAS is 6 */
+			dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+			reg = REG_SDRAM_OPERATION_CMD_MR0 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			reg = reg_read(REG_DDR3_MR2_ADDR);
+			reg &= ~0x38;	/* CWL [5:3] */
+			reg |= (1 << 3);	/* CWL = 1, CWL is 6 */
+			dfs_reg_write(REG_DDR3_MR2_ADDR, reg);
+
+			reg = REG_SDRAM_OPERATION_CMD_MR2 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			/* Set current rd_sample_delay  */
+			reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+				 (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			reg |= (5 << (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			dfs_reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+			/* Set current rd_ready_delay  */
+			reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+				 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			reg |= ((6) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			dfs_reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+		}
+	}
+
+	/* [2] - DFS Self refresh disable  */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* [1] - DFS Block enable  */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_BLOCK_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll DFS Register - 0x1528 [3] - DfsAtSR -
+	 * All DRAM devices on all ranks are in self refresh mode - DFS can
+	 * be executed afterwards
+	 */
+	do {
+		reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+	} while (reg);		/* Wait for '1' */
+
+	reg = (reg_read(REG_METAL_MASK_ADDR) | (1 << 0));
+	/* [0] - Enable Dunit to crossbar retry */
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	/* 0x1600 - PHY lock mask register */
+	reg = reg_read(REG_ODPG_CNTRL_ADDR);
+	reg &= ~(1 << REG_ODPG_CNTRL_OFFS);	/* [21] = 0 */
+	dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+	/* 0x1670 - PHY lock mask register */
+	reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+	reg |= ~REG_PHY_LOCK_MASK_MASK;	/* [11:0] = FFF */
+	dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+	DEBUG_DFS_C("DDR3 - DFS - High To Low - Ended successfuly - new Frequency - ",
+		    freq, 1);
+
+	return MV_OK;
+#endif
+}
+
+/*
+ * Name:     ddr3_dfs_low_2_high
+ * Desc:
+ * Args:     freq - target frequency
+ * Notes:
+ * Returns:  MV_OK - success, MV_FAIL - fail
+ */
+int ddr3_dfs_low_2_high(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+#if defined(MV88F78X60) || defined(MV88F672X)
+	/* This Flow is relevant for ArmadaXP A0 */
+	u32 reg, freq_par, tmp;
+	u32 cs = 0;
+
+	DEBUG_DFS_C("DDR3 - DFS - Low To High - Starting DFS procedure to Frequency - ",
+		    freq, 1);
+
+	/* target frequency - freq */
+	freq_par = ddr3_get_freq_parameter(freq, ratio_2to1);
+
+#if defined(MV88F672X)
+	u32 hclk;
+	u32 cpu_freq = ddr3_get_cpu_freq();
+	get_target_freq(cpu_freq, &tmp, &hclk);
+#endif
+
+	/* Configure - DRAM DLL final state after DFS is complete - Enable */
+	reg = reg_read(REG_DFS_ADDR);
+	/* [0] - DfsDllNextState - Enable */
+	reg &= ~(1 << REG_DFS_DLLNEXTSTATE_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Configure -  XBAR Retry response during Block to enable
+	 * internal access - Disable
+	 */
+	reg = reg_read(REG_METAL_MASK_ADDR);
+	/* [0] - RetryMask - Disable */
+	reg &= ~(1 << REG_METAL_MASK_RETRY_OFFS);
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	/* Configure - Block new external transactions - Enable */
+	reg = reg_read(REG_DFS_ADDR);
+	reg |= (1 << REG_DFS_BLOCK_OFFS);	/* [1] - DfsBlock - Enable  */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Configure - Move DRAM into Self Refresh */
+	reg = reg_read(REG_DFS_ADDR);
+	reg |= (1 << REG_DFS_SR_OFFS);	/* [2] - DfsSR - Enable */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Poll - Wait for Self Refresh indication */
+	do {
+		reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+	} while (reg == 0x0);	/* 0x1528 [3] - DfsAtSR - Wait for '1' */
+
+	/* Start of clock change procedure (PLL) */
+#if defined(MV88F672X)
+	/* avantaLP */
+	/* Configure    cpupll_clkdiv_reset_mask */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL0_MASK;
+	/* 0xE8264[7:0]   0xff CPU Clock Dividers Reset mask */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, (reg + 0xFF));
+
+	/* Configure    cpu_clkdiv_reload_smooth    */
+	reg = reg_read(CPU_PLL_CNTRL0);
+	reg &= CPU_PLL_CNTRL0_RELOAD_SMOOTH_MASK;
+	/* 0xE8260   [15:8]  0x2 CPU Clock Dividers Reload Smooth enable */
+	dfs_reg_write(CPU_PLL_CNTRL0,
+		      reg + (2 << CPU_PLL_CNTRL0_RELOAD_SMOOTH_OFFS));
+
+	/* Configure    cpupll_clkdiv_relax_en */
+	reg = reg_read(CPU_PLL_CNTRL0);
+	reg &= CPU_PLL_CNTRL0_RELAX_EN_MASK;
+	/* 0xE8260 [31:24] 0x2 Relax Enable */
+	dfs_reg_write(CPU_PLL_CNTRL0,
+		      reg + (2 << CPU_PLL_CNTRL0_RELAX_EN_OFFS));
+
+	/* Configure    cpupll_clkdiv_ddr_clk_ratio */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL1);
+	/*
+	 * 0xE8268  [13:8]  N   Set Training clock:
+	 * APLL Out Clock (VCO freq) / N = 100 MHz
+	 */
+	reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL1_MASK;
+	reg |= (freq_par << 8);	/* full Integer ratio from PLL-out to ddr-clk */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL1, reg);
+	/* Configure    cpupll_clkdiv_reload_ratio  */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+	/* 0xE8264 [8]=0x1 CPU Clock Dividers Reload Ratio trigger set */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0,
+		      reg + (1 << CPU_PLL_CLOCK_RELOAD_RATIO_OFFS));
+
+	udelay(1);
+
+	/* Configure    cpupll_clkdiv_reload_ratio  */
+	reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+	reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+	/* 0xE8264 [8]=0x0 CPU Clock Dividers Reload Ratio trigger clear */
+	dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, reg);
+
+	udelay(5);
+
+#else
+	/*
+	 * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+	 * and in the same chance, block reassertions of reset [15:8]
+	 * and force reserved bits[7:0].
+	 */
+	reg = 0x0000FFFF;
+
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	/*
+	 * RelaX whenever reset is asserted to that channel (good for any case)
+	 */
+	reg = 0x0000FF00;
+	/* 0x18704 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	reg = reg_read(REG_CPU_DIV_CLK_CTRL_2_ADDR) &
+		REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+	reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+	/* full Integer ratio from PLL-out to ddr-clk */
+	/* 0x1870C - CPU Div CLK control 3 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_2_ADDR, reg);
+
+	/*
+	 * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+	 * All the rest are kept as is (forced, but could be read-modify-write).
+	 * This is done now by RMW above.
+	 */
+	reg = 0x000FFF02;
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+	/* Wait before replacing the clock on the DDR Phy Channel. */
+	udelay(1);
+
+	reg = 0x0102FDFF;
+	/*
+	 * This for triggering the frequency update. Bit[24] is the
+	 * central control
+	 * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+	 *                 (smooth transition)
+	 * bits [15:8] == mask reset reassertion due to clock modification
+	 *                to these channels.
+	 * bits [7:0] == not in use
+	 */
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(1);
+
+	/*
+	 * Poll Div CLK status 0 register - indication that the clocks
+	 * are active - 0x18718 [8]
+	 */
+	do {
+		reg = reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR) &
+			(1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+	} while (reg == 0);
+
+	reg = 0x000000FF;
+	/*
+	 * Clean the CTRL0, to be ready for next resets and next requests
+	 * of ratio modifications.
+	 */
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+#endif
+	/* End of clock change procedure (PLL) */
+
+	if (ratio_2to1) {
+		/* Configure - Select normal clock for the DDR PHY - Disable */
+		reg = reg_read(REG_DRAM_INIT_CTRL_STATUS_ADDR);
+		/* [16] - ddr_phy_trn_clk_sel - Disable  */
+		reg &= ~(1 << REG_DRAM_INIT_CTRL_TRN_CLK_OFFS);
+		/* 0x18488 - DRAM Init control status register */
+		dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+	}
+
+	/*
+	 * Configure - Set Correct Ratio - according to target ratio
+	 * parameter - 2:1/1:1
+	 */
+	if (ratio_2to1) {
+		/*
+		 * [15] - Phy2UnitClkRatio = 1 - Set 2:1 Ratio between
+		 * Dunit and Phy
+		 */
+		reg = reg_read(REG_DDR_IO_ADDR) |
+			(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	} else {
+		/*
+		 * [15] - Phy2UnitClkRatio = 0 - Set 1:1 Ratio between
+		 * Dunit and Phy
+		 */
+		reg = reg_read(REG_DDR_IO_ADDR) &
+			~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	}
+	dfs_reg_write(REG_DDR_IO_ADDR, reg);	/* 0x1524 - DDR IO Register */
+
+	/* Configure - 2T Mode - Restore original configuration */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	/* [3:4] 2T - Restore value */
+	reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+	reg |= ((dram_info->mode_2t & REG_DUNIT_CTRL_LOW_2T_MASK) <<
+		REG_DUNIT_CTRL_LOW_2T_OFFS);
+	/* 0x1404 - DDR Controller Control Low Register */
+	dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+	/* Configure - Restore CL and CWL - MRS Commands */
+	reg = reg_read(REG_DFS_ADDR);
+	reg &= ~(REG_DFS_CL_NEXT_STATE_MASK << REG_DFS_CL_NEXT_STATE_OFFS);
+	reg &= ~(REG_DFS_CWL_NEXT_STATE_MASK << REG_DFS_CWL_NEXT_STATE_OFFS);
+
+	if (freq == DDR_400) {
+		if (dram_info->target_frequency == 0x8)
+			tmp = ddr3_cl_to_valid_cl(5);
+		else
+			tmp = ddr3_cl_to_valid_cl(6);
+	} else {
+		tmp = ddr3_cl_to_valid_cl(dram_info->cl);
+	}
+
+	/* [8] - DfsCLNextState */
+	reg |= ((tmp & REG_DFS_CL_NEXT_STATE_MASK) << REG_DFS_CL_NEXT_STATE_OFFS);
+	if (freq == DDR_400) {
+		/* [12] - DfsCWLNextState */
+		reg |= (((0) & REG_DFS_CWL_NEXT_STATE_MASK) <<
+			REG_DFS_CWL_NEXT_STATE_OFFS);
+	} else {
+		/* [12] - DfsCWLNextState */
+		reg |= (((dram_info->cwl) & REG_DFS_CWL_NEXT_STATE_MASK) <<
+			REG_DFS_CWL_NEXT_STATE_OFFS);
+	}
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Optional - Configure - DDR3_Rtt_nom_CS# */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS));
+			reg &= REG_DDR3_MR1_RTT_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+			dfs_reg_write(REG_DDR3_MR1_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* Configure - Reset ADLLs - Set Reset */
+	reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK;
+	/* [31:30]] - reset pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config Register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	/* Configure - Reset ADLLs - Release Reset */
+	reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK;
+	/* [31:30] - normal pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	/* Poll - Wait for APLL + ADLLs lock on new frequency */
+	do {
+		reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+			REG_PHY_LOCK_APLL_ADLL_STATUS_MASK;
+		/* 0x1674 [10:0] - Phy lock status Register */
+	} while (reg != REG_PHY_LOCK_APLL_ADLL_STATUS_MASK);
+
+	/* Configure - Reset the PHY SDR clock divider */
+	if (ratio_2to1) {
+		/* Pup Reset Divider B - Set Reset */
+		/* [28] - DataPupRdRST = 0 */
+		reg = reg_read(REG_SDRAM_CONFIG_ADDR) &
+			~(1 << REG_SDRAM_CONFIG_PUPRSTDIV_OFFS);
+		/* [28] - DataPupRdRST = 1 */
+		tmp = reg_read(REG_SDRAM_CONFIG_ADDR) |
+			(1 << REG_SDRAM_CONFIG_PUPRSTDIV_OFFS);
+		/* 0x1400 - SDRAM Configuration register */
+		dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+		/* Pup Reset Divider B - Release Reset */
+		/* 0x1400 - SDRAM Configuration register */
+		dfs_reg_write(REG_SDRAM_CONFIG_ADDR, tmp);
+	}
+
+	/* Configure - Reset the PHY Read FIFO and Write channels - Set Reset */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK;
+	/* [30:29] = 0 - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/*
+	 * Configure - DRAM Data PHY Read [30], Write [29] path reset -
+	 * Release Reset
+	 */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+	/* [30:29] = '11' - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/* Registered DIMM support */
+	if (dram_info->reg_dimm) {
+		/*
+		 * Configure - Change register DRAM operating speed
+		 * (DDR3-1333 / DDR3-1600) - CWA_RC
+		 */
+		reg = (0xA & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+			REG_SDRAM_OPERATION_CWA_RC_OFFS;
+		if (freq <= DDR_400) {
+			/*
+			 * Configure - Change register DRAM operating speed
+			 * (DDR3-800) - CWA_DATA
+			 */
+			reg |= ((0x0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+				REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+		} else if ((freq > DDR_400) && (freq <= DDR_533)) {
+			/*
+			 * Configure - Change register DRAM operating speed
+			 * (DDR3-1066) - CWA_DATA
+			 */
+			reg |= ((0x1 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+				REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+		} else if ((freq > DDR_533) && (freq <= DDR_666)) {
+			/*
+			 * Configure - Change register DRAM operating speed
+			 * (DDR3-1333) - CWA_DATA
+			 */
+			reg |= ((0x2 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+				REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+		} else {
+			/*
+			 * Configure - Change register DRAM operating speed
+			 * (DDR3-1600) - CWA_DATA
+			 */
+			reg |= ((0x3 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+				REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+		}
+
+		/* Configure - Set Delay - tSTAB */
+		reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+		/* Configure - Issue CWA command with the above parameters */
+		reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+			~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+		/* 0x1418 - SDRAM Operation Register */
+		dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+		/* Poll - Wait for CWA operation completion */
+		do {
+			reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+				REG_SDRAM_OPERATION_CMD_MASK;
+		} while (reg);
+	}
+
+	/* Configure - Exit Self Refresh */
+	/* [2] - DfsSR  */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll - DFS Register - 0x1528 [3] - DfsAtSR - All DRAM
+	 * devices on all ranks are NOT in self refresh mode
+	 */
+	do {
+		reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	/* Configure - Issue Refresh command */
+	/* [3-0] = 0x2 - Refresh Command, [11-8] - enabled Cs */
+	reg = REG_SDRAM_OPERATION_CMD_RFRS;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs))
+			reg &= ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+	}
+
+	/* 0x1418 - SDRAM Operation Register */
+	dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+	/* Poll - Wait for Refresh operation completion */
+	wait_refresh_op_complete();
+
+	/* Configure - Block new external transactions - Disable */
+	reg = reg_read(REG_DFS_ADDR);
+	reg &= ~(1 << REG_DFS_BLOCK_OFFS);	/* [1] - DfsBlock - Disable  */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Configure -  XBAR Retry response during Block to enable
+	 * internal access - Disable
+	 */
+	reg = reg_read(REG_METAL_MASK_ADDR);
+	/* [0] - RetryMask - Enable */
+	reg |= (1 << REG_METAL_MASK_RETRY_OFFS);
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			/* Configure - Set CL */
+			reg = reg_read(REG_DDR3_MR0_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS)) &
+				~REG_DDR3_MR0_CL_MASK;
+			if (freq == DDR_400)
+				tmp = ddr3_cl_to_valid_cl(6);
+			else
+				tmp = ddr3_cl_to_valid_cl(dram_info->cl);
+			reg |= ((tmp & 0x1) << REG_DDR3_MR0_CL_OFFS);
+			reg |= ((tmp & 0xE) << REG_DDR3_MR0_CL_HIGH_OFFS);
+			dfs_reg_write(REG_DDR3_MR0_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+
+			/* Configure - Set CWL */
+			reg = reg_read(REG_DDR3_MR2_CS_ADDR +
+				       (cs << MR_CS_ADDR_OFFS)) &
+				~(REG_DDR3_MR2_CWL_MASK << REG_DDR3_MR2_CWL_OFFS);
+			if (freq == DDR_400)
+				reg |= ((0) << REG_DDR3_MR2_CWL_OFFS);
+			else
+				reg |= ((dram_info->cwl) << REG_DDR3_MR2_CWL_OFFS);
+			dfs_reg_write(REG_DDR3_MR2_CS_ADDR +
+				      (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	DEBUG_DFS_C("DDR3 - DFS - Low To High - Ended successfuly - new Frequency - ",
+		    freq, 1);
+
+	return MV_OK;
+
+#else
+
+	/* This Flow is relevant for Armada370 A0 and ArmadaXP Z1 */
+
+	u32 reg, freq_par, tmp;
+	u32 cs = 0;
+
+	DEBUG_DFS_C("DDR3 - DFS - Low To High - Starting DFS procedure to Frequency - ",
+		    freq, 1);
+
+	/* target frequency - freq */
+	freq_par = ddr3_get_freq_parameter(freq, ratio_2to1);
+
+	reg = 0x0000FF00;
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	/* 0x1600 - PHY lock mask register */
+	reg = reg_read(REG_ODPG_CNTRL_ADDR);
+	reg |= (1 << REG_ODPG_CNTRL_OFFS);	/* [21] = 1 */
+	dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+	/* 0x1670 - PHY lock mask register */
+	reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+	reg &= REG_PHY_LOCK_MASK_MASK;	/* [11:0] = 0 */
+	dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+	/* Enable reconfig MR Registers after DFS */
+	reg = reg_read(REG_DFS_ADDR);	/* 0x1528 - DFS register */
+	/* [4] - Disable - reconfig MR registers after DFS_ERG */
+	reg &= ~0x11;
+	/* [0] - Enable - DRAM DLL after DFS */
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Disable DRAM Controller to crossbar retry */
+	/* [0] - disable */
+	reg = reg_read(REG_METAL_MASK_ADDR) & ~(1 << 0);
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	/* Enable DRAM Blocking */
+	/* [1] - DFS Block enable  */
+	reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_BLOCK_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Enable Self refresh */
+	/* [2] - DFS Self refresh enable  */
+	reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_SR_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll DFS Register - All DRAM devices on all ranks are in
+	 * self refresh mode - DFS can be executed afterwards
+	 */
+	/* 0x1528 [3] - DfsAtSR  */
+	do {
+		reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+	} while (reg == 0x0);	/* Wait for '1' */
+
+	/*
+	 * Set Correct Ratio - if freq>MARGIN_FREQ use 2:1 ratio
+	 * else use 1:1 ratio
+	 */
+	if (ratio_2to1) {
+		/* [15] = 1 - Set 2:1 Ratio between Dunit and Phy */
+		reg = reg_read(REG_DDR_IO_ADDR) |
+			(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	} else {
+		/* [15] = 0 - Set 1:1 Ratio between Dunit and Phy */
+		reg = reg_read(REG_DDR_IO_ADDR) &
+			~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+	}
+	dfs_reg_write(REG_DDR_IO_ADDR, reg);	/* 0x1524 - DDR IO Register */
+
+	/* Switch HCLK Mux from (100Mhz) [16]=0, keep DFS request bit */
+	reg = 0x20040000;
+	/*
+	 * [29] - training logic request DFS, [28:27] -
+	 * preload patterns frequency [18]
+	 */
+
+	/* 0x18488 - DRAM Init control status register */
+	dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+	/* Add delay between entering SR and start ratio modification */
+	udelay(1);
+
+	/*
+	 * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+	 * and in the same chance, block reassertions of reset [15:8] and
+	 * force reserved bits[7:0].
+	 */
+	reg = 0x0000FFFF;
+	/* 0x18700 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	/*
+	 * RelaX whenever reset is asserted to that channel (good for any case)
+	 */
+	reg = 0x0000FF00;
+	/* 0x18704 - CPU Div CLK control 0 */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+	reg = reg_read(REG_CPU_DIV_CLK_CTRL_3_ADDR) &
+		REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+	reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+	/* Full Integer ratio from PLL-out to ddr-clk */
+	/* 0x1870C - CPU Div CLK control 3 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_3_ADDR, reg);
+
+	/*
+	 * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+	 * All the rest are kept as is (forced, but could be read-modify-write).
+	 * This is done now by RMW above.
+	 */
+
+	reg = 0x000FFF02;
+
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+	/* Wait before replacing the clock on the DDR Phy Channel. */
+	udelay(1);
+
+	reg = 0x0102FDFF;
+	/*
+	 * This for triggering the frequency update. Bit[24] is the
+	 * central control
+	 * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+	 *                 (smooth transition)
+	 * bits [15:8] == mask reset reassertion due to clock modification
+	 *                to these channels.
+	 * bits [7:0] == not in use
+	 */
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(1);
+
+	/*
+	 * Poll Div CLK status 0 register - indication that the clocks are
+	 * active - 0x18718 [8]
+	 */
+	do {
+		reg = reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR) &
+			(1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+	} while (reg == 0);
+
+	reg = 0x000000FF;
+	/*
+	 * Clean the CTRL0, to be ready for next resets and next requests of
+	 * ratio modifications.
+	 */
+	/* 0x18700 - CPU Div CLK control 0 register */
+	dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+	udelay(5);
+
+	if (ratio_2to1) {
+		/* Pup Reset Divider B - Set Reset */
+		/* [28] = 0 - Pup Reset Divider B */
+		reg = reg_read(REG_SDRAM_CONFIG_ADDR) & ~(1 << 28);
+		/* [28] = 1 - Pup Reset Divider B */
+		tmp = reg_read(REG_SDRAM_CONFIG_ADDR) | (1 << 28);
+		/* 0x1400 - SDRAM Configuration register */
+		dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+		/* Pup Reset Divider B - Release Reset */
+		/* 0x1400 - SDRAM Configuration register */
+		dfs_reg_write(REG_SDRAM_CONFIG_ADDR, tmp);
+	}
+
+	/* DRAM Data PHYs ADLL Reset - Set Reset */
+	reg = (reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK);
+	/* [31:30]] - reset pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config Register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	udelay(25);
+
+	/* APLL lock indication - Poll Phy lock status Register - 0x1674 [9] */
+	do {
+		reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+			(1 << REG_PHY_LOCK_STATUS_LOCK_OFFS);
+	} while (reg == 0);
+
+	/* DRAM Data PHYs ADLL Reset - Release Reset */
+	reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK;
+	/* [31:30] - normal pup data ctrl ADLL */
+	/* 0x15EC - DRAM PHY Config register */
+	dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+	udelay(10000);		/* Wait 10msec */
+
+	/*
+	 * APLL lock indication - Poll Phy lock status Register - 0x1674 [11:0]
+	 */
+	do {
+		reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+			REG_PHY_LOCK_STATUS_LOCK_MASK;
+	} while (reg != REG_PHY_LOCK_STATUS_LOCK_MASK);
+
+	/* DRAM Data PHY Read [30], Write [29] path reset - Set Reset */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK;
+	/* [30:29] = 0 - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/* DRAM Data PHY Read [30], Write [29] path reset - Release Reset */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+	/* [30:29] = '11' - Data Pup R/W path reset */
+	/* 0x1400 - SDRAM Configuration register */
+	dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/* Disable DFS Reconfig */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << 4);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* [2] - DFS Self refresh disable  */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/*
+	 * Poll DFS Register - 0x1528 [3] - DfsAtSR - All DRAM devices on
+	 * all ranks are NOT in self refresh mode
+	 */
+	do {
+		reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	/* 0x1404 */
+	reg = (reg_read(REG_DUNIT_CTRL_LOW_ADDR) & 0xFFFFFFE7) | 0x2;
+
+	/* Configure - 2T Mode - Restore original configuration */
+	/* [3:4] 2T - Restore value */
+	reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+	reg |= ((dram_info->mode_2t & REG_DUNIT_CTRL_LOW_2T_MASK) <<
+		REG_DUNIT_CTRL_LOW_2T_OFFS);
+	dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+	udelay(1);		/* Wait 1us */
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = (reg_read(REG_DDR3_MR1_ADDR));
+			/* DLL Enable */
+			reg &= ~(1 << REG_DDR3_MR1_DLL_ENA_OFFS);
+			dfs_reg_write(REG_DDR3_MR1_ADDR, reg);
+
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			/* DLL Reset - MR0 */
+			reg = reg_read(REG_DDR3_MR0_ADDR);
+			dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR0 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			reg = reg_read(REG_DDR3_MR0_ADDR);
+			reg &= ~0x74;	/* CL [3:0]; [6:4],[2] */
+
+			if (freq == DDR_400)
+				tmp = ddr3_cl_to_valid_cl(6) & 0xF;
+			else
+				tmp = ddr3_cl_to_valid_cl(dram_info->cl) & 0xF;
+
+			reg |= ((tmp & 0x1) << 2);
+			reg |= ((tmp >> 1) << 4);	/* to bit 4 */
+			dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+
+			reg = REG_SDRAM_OPERATION_CMD_MR0 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			reg = reg_read(REG_DDR3_MR2_ADDR);
+			reg &= ~0x38;	/* CWL [5:3] */
+			/* CWL = 0 ,for 400 MHg is 5 */
+			if (freq != DDR_400)
+				reg |= dram_info->cwl << REG_DDR3_MR2_CWL_OFFS;
+			dfs_reg_write(REG_DDR3_MR2_ADDR, reg);
+			reg = REG_SDRAM_OPERATION_CMD_MR2 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/* 0x1418 - SDRAM Operation Register */
+			dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			/* Poll - Wait for Refresh operation completion */
+			wait_refresh_op_complete();
+
+			/* Set current rd_sample_delay  */
+			reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+				 (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			reg |= (dram_info->cl <<
+				(REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			dfs_reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+			/* Set current rd_ready_delay  */
+			reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+				 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			reg |= ((dram_info->cl + 1) <<
+				(REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			dfs_reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+		}
+	}
+
+	/* Enable ODT on DLL-on mode */
+	dfs_reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, 0);
+
+	/* [1] - DFS Block disable  */
+	reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_BLOCK_OFFS);
+	dfs_reg_write(REG_DFS_ADDR, reg);	/* 0x1528 - DFS register */
+
+	/* Change DDR frequency to 100MHz procedure: */
+	/* 0x1600 - PHY lock mask register */
+	reg = reg_read(REG_ODPG_CNTRL_ADDR);
+	reg &= ~(1 << REG_ODPG_CNTRL_OFFS);	/* [21] = 0 */
+	dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+	/* Change DDR frequency to 100MHz procedure: */
+	/* 0x1670 - PHY lock mask register */
+	reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+	reg |= ~REG_PHY_LOCK_MASK_MASK;	/* [11:0] = FFF */
+	dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+	reg = reg_read(REG_METAL_MASK_ADDR) | (1 << 0);	/* [0] - disable */
+	/* 0x14B0 - Dunit MMask Register */
+	dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+	DEBUG_DFS_C("DDR3 - DFS - Low To High - Ended successfuly - new Frequency - ",
+		    freq, 1);
+	return MV_OK;
+#endif
+}
diff --git a/drivers/ddr/mvebu/ddr3_dqs.c b/drivers/ddr/mvebu/ddr3_dqs.c
new file mode 100644
index 0000000..71a986d
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_dqs.c
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_DQS_C(s, d, l) \
+	DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
+#define DEBUG_DQS_FULL_C(s, d, l) \
+	DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
+#define DEBUG_DQS_RESULTS_C(s, d, l) \
+	DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
+#define DEBUG_PER_DQ_C(s, d, l) \
+	puts(s); printf("%x", d); puts("\n")
+
+#define DEBUG_DQS_RESULTS_S(s) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_DQS_RESULTS_D(d, l) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+
+#define DEBUG_PER_DQ_S(s) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
+#define DEBUG_PER_DQ_D(d, l) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
+#define DEBUG_PER_DQ_DD(d, l) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
+
+#ifdef MV_DEBUG_DQS
+#define DEBUG_DQS_S(s)			puts(s)
+#define DEBUG_DQS_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_DQS_S(s)
+#define DEBUG_DQS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_DQS_FULL
+#define DEBUG_DQS_FULL_S(s)		puts(s)
+#define DEBUG_DQS_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_DQS_FULL_S(s)
+#define DEBUG_DQS_FULL_D(d, l)
+#endif
+
+/* State machine for centralization - find low & high limit */
+enum {
+	PUP_ADLL_LIMITS_STATE_FAIL,
+	PUP_ADLL_LIMITS_STATE_PASS,
+	PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
+};
+
+/* Hold centralization low results */
+static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
+/* Hold centralization high results */
+static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
+
+int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
+int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
+			  int *size_valid);
+static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+			    int is_tx);
+int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+			      int is_tx, u32 special_pattern_pup);
+int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+				   int is_tx, u32 special_pattern_pup);
+int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+				    int is_tx);
+
+#ifdef MV88F78X60
+extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
+extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
+extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#else
+extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
+extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
+#if defined(MV88F672X)
+extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#endif
+#endif
+extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
+
+static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
+{
+	u32 *pattern_ptr;
+
+	/* Choose pattern */
+	switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+	case 16:
+		pattern_ptr = (u32 *)&killer_pattern[victim_dq];
+		break;
+#endif
+	case 32:
+		pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
+		break;
+#if defined(MV88F78X60)
+	case 64:
+		pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
+		break;
+#endif
+	default:
+#if defined(MV88F78X60)
+		pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
+#else
+		pattern_ptr = (u32 *)&killer_pattern[victim_dq];
+#endif
+		break;
+	}
+
+	return pattern_ptr;
+}
+
+/*
+ * Name:     ddr3_dqs_centralization_rx
+ * Desc:     Execute the DQS centralization RX phase.
+ * Args:     dram_info
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
+{
+	u32 cs, ecc, reg;
+	int status;
+
+	DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
+
+	reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	/* Loop for each CS */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
+					 (u32) cs, 1);
+
+			for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+
+				/* ECC Support - Switch ECC Mux on ecc=1 */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg |= (dram_info->ecc_ena *
+					ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+				if (ecc)
+					DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
+				else
+					DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
+
+				DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
+
+				status = ddr3_find_adll_limits(dram_info, cs,
+							       ecc, 0);
+				if (MV_OK != status)
+					return status;
+
+				DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
+
+				status = ddr3_center_calc(dram_info, cs, ecc,
+							  0);
+				if (MV_OK != status)
+					return status;
+			}
+		}
+	}
+
+	/* ECC Support - Disable ECC MUX */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dqs_centralization_tx
+ * Desc:     Execute the DQS centralization TX phase.
+ * Args:     dram_info
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
+{
+	u32 cs, ecc, reg;
+	int status;
+
+	DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
+
+	reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	/* Loop for each CS */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
+					 (u32) cs, 1);
+			for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+				/* ECC Support - Switch ECC Mux on ecc=1 */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg |= (dram_info->ecc_ena *
+					ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+				if (ecc)
+					DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
+				else
+					DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
+
+				DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
+
+				status = ddr3_find_adll_limits(dram_info, cs,
+							       ecc, 1);
+				if (MV_OK != status)
+					return status;
+
+				DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
+
+				status = ddr3_center_calc(dram_info, cs, ecc,
+							  1);
+				if (MV_OK != status)
+					return status;
+			}
+		}
+	}
+
+	/* ECC Support - Disable ECC MUX */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_find_adll_limits
+ * Desc:     Execute the Find ADLL limits phase.
+ * Args:     dram_info
+ *           cs
+ *           ecc_ena
+ *           is_tx             Indicate whether Rx or Tx
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
+{
+	u32 victim_dq, pup, tmp;
+	u32 adll_addr;
+	u32 max_pup;		/* maximal pup index */
+	u32 pup_mask = 0;
+	u32 unlock_pup;		/* bit array of un locked pups */
+	u32 new_unlock_pup;	/* bit array of compare failed pups */
+	u32 curr_adll;
+	u32 adll_start_val;	/* adll start loop value - for rx or tx limit */
+	u32 high_limit;	/* holds found High Limit */
+	u32 low_limit;		/* holds found Low Limit */
+	int win_valid;
+	int update_win;
+	u32 sdram_offset;
+	u32 uj, cs_count, cs_tmp, ii;
+	u32 *pattern_ptr;
+	u32 dq;
+	u32 adll_end_val;	/* adll end of loop val - for rx or tx limit */
+	u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
+	u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
+	int pup_adll_limit_state[MAX_PUP_NUM];	/* hold state of each pup */
+
+	adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
+	adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
+	adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
+	max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+	DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
+
+	/* init the array */
+	for (pup = 0; pup < max_pup; pup++) {
+		centralization_low_limit[pup] = ADLL_MIN;
+		centralization_high_limit[pup] = ADLL_MAX;
+	}
+
+	/* Killer Pattern */
+	cs_count = 0;
+	for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+		if (dram_info->cs_ena & (1 << cs_tmp))
+			cs_count++;
+	}
+	sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
+	sdram_offset += ((is_tx == 1) ?
+			 SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
+
+	/* Prepare pup masks */
+	for (pup = 0; pup < max_pup; pup++)
+		pup_mask |= (1 << pup);
+
+	for (pup = 0; pup < max_pup; pup++) {
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			analog_pbs_sum[pup][dq][0] = adll_start_val;
+			analog_pbs_sum[pup][dq][1] = adll_end_val;
+		}
+	}
+
+	/* Loop - use different pattern for each victim_dq */
+	for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+		DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
+				 (u32)victim_dq, 1);
+		/*
+		 * The pups 3 bit arrays represent state machine. with
+		 * 3 stages for each pup.
+		 * 1. fail and didn't get pass in earlier compares.
+		 * 2. pass compare
+		 * 3. fail after pass - end state.
+		 * The window limits are the adll values where the adll
+		 * was in the pass stage.
+		 */
+
+		/* Set all states to Fail (1st state) */
+		for (pup = 0; pup < max_pup; pup++)
+			pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
+
+		/* Set current valid pups */
+		unlock_pup = pup_mask;
+
+		/* Set ADLL to start value */
+		curr_adll = adll_start_val;
+
+#if defined(MV88F78X60)
+		for (pup = 0; pup < max_pup; pup++) {
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				analog_pbs[victim_dq][pup][dq][0] =
+					adll_start_val;
+				analog_pbs[victim_dq][pup][dq][1] =
+					adll_end_val;
+				per_bit_data[pup][dq] = 0;
+			}
+		}
+#endif
+
+		for (uj = 0; uj < ADLL_MAX; uj++) {
+			DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
+					 curr_adll, 2);
+			for (pup = 0; pup < max_pup; pup++) {
+				if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+					tmp = ((is_tx == 1) ? curr_adll +
+					       dram_info->wl_val[cs]
+					       [pup * (1 - ecc) + ecc * ECC_PUP]
+					       [D] : curr_adll);
+					ddr3_write_pup_reg(adll_addr, cs, pup +
+						(ecc * ECC_PUP), 0, tmp);
+				}
+			}
+
+			/* Choose pattern */
+			pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
+							      victim_dq);
+
+			/* '1' - means pup failed, '0' - means pup pass */
+			new_unlock_pup = 0;
+
+			/* Read and compare results for Victim_DQ# */
+			for (ii = 0; ii < 3; ii++) {
+				u32 tmp = 0;
+				if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
+							   unlock_pup, &tmp,
+							   pattern_ptr,
+							   LEN_KILLER_PATTERN,
+							   sdram_offset +
+							   LEN_KILLER_PATTERN *
+							   4 * victim_dq,
+							   is_tx, 0, NULL,
+							   0))
+					return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
+
+				new_unlock_pup |= tmp;
+			}
+
+			pup = 0;
+			DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
+					 unlock_pup, 2);
+			DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
+					 new_unlock_pup, 2);
+
+			/* Update pup state */
+			for (pup = 0; pup < max_pup; pup++) {
+				if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
+					DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
+							 pup, 1);
+					continue;
+				}
+
+				/*
+				 * Still didn't find the window limit of the pup
+				 */
+				if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
+					/* Current compare result == fail */
+					if (pup_adll_limit_state[pup] ==
+					    PUP_ADLL_LIMITS_STATE_PASS) {
+						/*
+						 * If now it failed but passed
+						 * earlier
+						 */
+						DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
+						DEBUG_DQS_D(cs, 1);
+						DEBUG_DQS_S(", DQ - ");
+						DEBUG_DQS_D(victim_dq, 1);
+						DEBUG_DQS_S(", Pup - ");
+						DEBUG_DQS_D(pup, 1);
+						DEBUG_DQS_S(", ADLL - ");
+						DEBUG_DQS_D(curr_adll, 2);
+						DEBUG_DQS_S("\n");
+
+#if defined(MV88F78X60)
+						for (dq = 0; dq < DQ_NUM; dq++) {
+							if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
+							    && (analog_pbs[victim_dq][pup]
+								[dq][1] == adll_end_val))
+								analog_pbs
+									[victim_dq]
+									[pup][dq]
+									[1] =
+									curr_adll;
+						}
+#endif
+						win_valid = 1;
+						update_win = 0;
+
+						/* Keep min / max limit value */
+						if (is_tx == 0) {
+							/* RX - found upper limit */
+							if (centralization_high_limit[pup] >
+							    (curr_adll - 1)) {
+								high_limit =
+									curr_adll - 1;
+								low_limit =
+									centralization_low_limit[pup];
+								update_win = 1;
+							}
+						} else {
+							/* TX - found lower limit */
+							if (centralization_low_limit[pup] < (curr_adll + 1)) {
+								high_limit =
+									centralization_high_limit
+									[pup];
+								low_limit =
+									curr_adll + 1;
+								update_win =
+									1;
+							}
+						}
+
+						if (update_win == 1) {
+							/*
+							 * Before updating
+							 * window limits we need
+							 * to check that the
+							 * limits are valid
+							 */
+							if (MV_OK !=
+							    ddr3_check_window_limits
+							    (pup, high_limit,
+							     low_limit, is_tx,
+							     &win_valid))
+								return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
+
+							if (win_valid == 1) {
+								/*
+								 * Window limits
+								 * should be
+								 * updated
+								 */
+								centralization_low_limit
+									[pup] =
+									low_limit;
+								centralization_high_limit
+									[pup] =
+									high_limit;
+							}
+						}
+
+						if (win_valid == 1) {
+							/* Found end of window - lock the pup */
+							pup_adll_limit_state[pup] =
+								PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
+							unlock_pup &= ~(1 << pup);
+						} else {
+							/* Probably false pass - reset status */
+							pup_adll_limit_state[pup] =
+								PUP_ADLL_LIMITS_STATE_FAIL;
+
+#if defined(MV88F78X60)
+							/* Clear logging array of win size (per Dq) */
+							for (dq = 0;
+							     dq < DQ_NUM;
+							     dq++) {
+								analog_pbs
+									[victim_dq]
+									[pup][dq]
+									[0] =
+									adll_start_val;
+								analog_pbs
+									[victim_dq]
+									[pup][dq]
+									[1] =
+									adll_end_val;
+								per_bit_data
+									[pup][dq]
+									= 0;
+							}
+#endif
+						}
+					}
+				} else {
+					/* Current compare result == pass */
+					if (pup_adll_limit_state[pup] ==
+					    PUP_ADLL_LIMITS_STATE_FAIL) {
+						/* If now it passed but failed earlier */
+						DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
+						DEBUG_DQS_D(cs, 1);
+						DEBUG_DQS_S(", DQ - ");
+						DEBUG_DQS_D(victim_dq, 1);
+						DEBUG_DQS_S(", Pup - ");
+						DEBUG_DQS_D(pup, 1);
+						DEBUG_DQS_S(", ADLL - ");
+						DEBUG_DQS_D(curr_adll, 2);
+						DEBUG_DQS_S("\n");
+
+#if defined(MV88F78X60)
+						for (dq = 0; dq < DQ_NUM;
+						     dq++) {
+							if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
+								analog_pbs
+								    [victim_dq]
+								    [pup][dq]
+								    [0] =
+								    curr_adll;
+						}
+#endif
+						/* Found start of window */
+						pup_adll_limit_state[pup] =
+						    PUP_ADLL_LIMITS_STATE_PASS;
+
+						/* Keep min / max limit value */
+						if (is_tx == 0) {
+							/* RX - found low limit */
+							if (centralization_low_limit[pup] <= curr_adll)
+								centralization_low_limit
+								    [pup] =
+								    curr_adll;
+						} else {
+							/* TX - found high limit */
+							if (centralization_high_limit[pup] >= curr_adll)
+								centralization_high_limit
+								    [pup] =
+								    curr_adll;
+						}
+					}
+				}
+			}
+
+			if (unlock_pup == 0) {
+				/* Found limit to all pups */
+				DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
+				break;
+			}
+
+			/*
+			 * Increment / decrement (Move to right / left
+			 * one phase - ADLL) dqs RX / TX delay (for all un
+			 * lock pups
+			 */
+			if (is_tx == 0)
+				curr_adll++;
+			else
+				curr_adll--;
+		}
+
+		if (unlock_pup != 0) {
+			/*
+			 * Found pups that didn't reach to the end of the
+			 * state machine
+			 */
+			DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
+				    unlock_pup, 1);
+
+			for (pup = 0; pup < max_pup; pup++) {
+				if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+					if (pup_adll_limit_state[pup] ==
+					    PUP_ADLL_LIMITS_STATE_FAIL) {
+						/* ERROR - found fail for all window size */
+						DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
+						DEBUG_DQS_D(pup, 1);
+						DEBUG_DQS_C(" victim DQ ",
+							    victim_dq, 1);
+
+						/* For debug - set min limit to illegal limit */
+						centralization_low_limit[pup]
+							= ADLL_ERROR;
+						/*
+						 * In case the pup is in mode
+						 * PASS - the limit is the min
+						 * / max adll, no need to
+						 * update because of the results
+						 * array default value
+						 */
+						return MV_DDR3_TRAINING_ERR_PUP_RANGE;
+					}
+				}
+			}
+		}
+	}
+
+	DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
+	for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+		for (pup = 0; pup < max_pup; pup++) {
+			DEBUG_DQS_S("Victim DQ-");
+			DEBUG_DQS_D(victim_dq, 1);
+			DEBUG_DQS_S(", PUP-");
+			DEBUG_DQS_D(pup, 1);
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				DEBUG_DQS_S(", DQ-");
+				DEBUG_DQS_D(dq, 1);
+				DEBUG_DQS_S(",S-");
+				DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
+					    [0], 2);
+				DEBUG_DQS_S(",E-");
+				DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
+					    [1], 2);
+
+				if (is_tx == 0) {
+					if (analog_pbs[victim_dq][pup][dq][0]
+					    > analog_pbs_sum[pup][dq][0])
+						analog_pbs_sum[pup][dq][0] =
+						    analog_pbs[victim_dq][pup]
+						    [dq][0];
+					if (analog_pbs[victim_dq][pup][dq][1]
+					    < analog_pbs_sum[pup][dq][1])
+						analog_pbs_sum[pup][dq][1] =
+						    analog_pbs[victim_dq][pup]
+						    [dq][1];
+				} else {
+					if (analog_pbs[victim_dq][pup][dq][0]
+					    < analog_pbs_sum[pup][dq][0])
+						analog_pbs_sum[pup][dq][0] =
+						    analog_pbs[victim_dq][pup]
+						    [dq][0];
+					if (analog_pbs[victim_dq][pup][dq][1]
+					    > analog_pbs_sum[pup][dq][1])
+						analog_pbs_sum[pup][dq][1] =
+						    analog_pbs[victim_dq][pup]
+						    [dq][1];
+				}
+			}
+			DEBUG_DQS_S("\n");
+		}
+	}
+
+	if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
+		u32 dq;
+
+		DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
+		if (is_tx) {
+			DEBUG_PER_DQ_C("DDR3 - TX  CS: ", cs, 1);
+		} else {
+			DEBUG_PER_DQ_C("DDR3 - RX  CS: ", cs, 1);
+		}
+
+		if (ecc == 0) {
+			DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
+		} else {
+			DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
+		}
+
+		/* Since all dq has the same value we take 0 as representive */
+		dq = 0;
+		for (pup = 0; pup < max_pup; pup++) {
+			if (ecc == 0) {
+				DEBUG_PER_DQ_S("\nBYTE:");
+				DEBUG_PER_DQ_D(pup, 1);
+				DEBUG_PER_DQ_S("\n");
+			} else {
+				DEBUG_PER_DQ_S("\nECC BYTE:\n");
+			}
+			DEBUG_PER_DQ_S("  DQ's        LOW       HIGH       WIN-SIZE\n");
+			DEBUG_PER_DQ_S("============================================\n");
+			for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+				if (ecc == 0) {
+					DEBUG_PER_DQ_S("DQ[");
+					DEBUG_PER_DQ_DD((victim_dq +
+							 DQ_NUM * pup), 2);
+					DEBUG_PER_DQ_S("]");
+				} else {
+					DEBUG_PER_DQ_S("CB[");
+					DEBUG_PER_DQ_DD(victim_dq, 2);
+					DEBUG_PER_DQ_S("]");
+				}
+				if (is_tx) {
+					DEBUG_PER_DQ_S("      0x");
+					DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2);	/* low value */
+					DEBUG_PER_DQ_S("        0x");
+					DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);	/* high value */
+					DEBUG_PER_DQ_S("        0x");
+					DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2);	/* win-size */
+				} else {
+					DEBUG_PER_DQ_S("     0x");
+					DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);	/* low value */
+					DEBUG_PER_DQ_S("       0x");
+					DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2);	/* high value */
+					DEBUG_PER_DQ_S("       0x");
+					DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2);	/* win-size */
+				}
+				DEBUG_PER_DQ_S("\n");
+			}
+		}
+		DEBUG_PER_DQ_S("\n");
+	}
+
+	if (is_tx) {
+		DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
+	} else {
+		DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
+	}
+
+	for (pup = 0; pup < max_pup; pup++) {
+		DEBUG_DQS_S("PUP-");
+		DEBUG_DQS_D(pup, 1);
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			DEBUG_DQS_S(", DQ-");
+			DEBUG_DQS_D(dq, 1);
+			DEBUG_DQS_S(",S-");
+			DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
+			DEBUG_DQS_S(",E-");
+			DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
+		}
+		DEBUG_DQS_S("\n");
+	}
+
+	if (is_tx) {
+		DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
+	} else {
+		DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
+	}
+
+	for (pup = 0; pup < max_pup; pup++) {
+		if (max_pup == 1) {
+			/* For ECC PUP */
+			DEBUG_DQS_S("DDR3 - DQS8");
+		} else {
+			DEBUG_DQS_S("DDR3 - DQS");
+			DEBUG_DQS_D(pup, 1);
+		}
+
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			DEBUG_DQS_S(", DQ-");
+			DEBUG_DQS_D(dq, 1);
+			DEBUG_DQS_S("::S-");
+			DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
+			DEBUG_DQS_S(",E-");
+			DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
+		}
+		DEBUG_DQS_S("\n");
+	}
+
+	DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_check_window_limits
+ * Desc:     Check window High & Low limits.
+ * Args:     pup                pup index
+ *           high_limit           window high limit
+ *           low_limit            window low limit
+ *           is_tx                Indicate whether Rx or Tx
+ *           size_valid          Indicate whether window size is valid
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
+			     int *size_valid)
+{
+	DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
+
+	if (low_limit > high_limit) {
+		DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+		DEBUG_DQS_D(pup, 1);
+		DEBUG_DQS_S(" Low Limit grater than High Limit\n");
+		*size_valid = 0;
+		return MV_OK;
+	}
+
+	/*
+	 * Check that window size is valid, if not it was probably false pass
+	 * before
+	 */
+	if ((high_limit - low_limit) < MIN_WIN_SIZE) {
+		/*
+		 * Since window size is too small probably there was false
+		 * pass
+		 */
+		*size_valid = 0;
+
+		DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+		DEBUG_DQS_D(pup, 1);
+		DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
+
+	} else if ((high_limit - low_limit) > ADLL_MAX) {
+		*size_valid = 0;
+
+		DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+		DEBUG_DQS_D(pup, 1);
+		DEBUG_DQS_S
+		    (" Window size is bigger than max ADLL taps (31)  Exiting.\n");
+
+		return MV_FAIL;
+
+	} else {
+		*size_valid = 1;
+
+		DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
+		DEBUG_DQS_FULL_D(pup, 1);
+		DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
+				 2);
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_center_calc
+ * Desc:     Execute the calculate the center of windows phase.
+ * Args:     pDram Info
+ *           is_tx             Indicate whether Rx or Tx
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+			    int is_tx)
+{
+	/* bit array of pups that need specail search */
+	u32 special_pattern_i_pup = 0;
+	u32 special_pattern_ii_pup = 0;
+	u32 pup;
+	u32 max_pup;
+
+	max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+	for (pup = 0; pup < max_pup; pup++) {
+		if (is_tx == 0) {
+			/* Check special pattern I */
+			/*
+			 * Special pattern Low limit search - relevant only
+			 * for Rx, win size < threshold and low limit = 0
+			 */
+			if (((centralization_high_limit[pup] -
+			      centralization_low_limit[pup]) < VALID_WIN_THRS)
+			    && (centralization_low_limit[pup] == MIN_DELAY))
+				special_pattern_i_pup |= (1 << pup);
+
+			/* Check special pattern II */
+			/*
+			 * Special pattern High limit search - relevant only
+			 * for Rx, win size < threshold and high limit = 31
+			 */
+			if (((centralization_high_limit[pup] -
+			      centralization_low_limit[pup]) < VALID_WIN_THRS)
+			    && (centralization_high_limit[pup] == MAX_DELAY))
+				special_pattern_ii_pup |= (1 << pup);
+		}
+	}
+
+	/* Run special pattern Low limit search - for relevant pup */
+	if (special_pattern_i_pup != 0) {
+		DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
+		if (MV_OK !=
+		    ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
+					      special_pattern_i_pup))
+			return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
+	}
+
+	/* Run special pattern High limit search - for relevant pup */
+	if (special_pattern_ii_pup != 0) {
+		DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
+		if (MV_OK !=
+		    ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
+						   special_pattern_ii_pup))
+			return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
+	}
+
+	/* Set adll to center = (General_High_limit + General_Low_limit)/2 */
+	return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
+}
+
+/*
+ * Name:     ddr3_special_pattern_i_search
+ * Desc:     Execute special pattern low limit search.
+ * Args:
+ *           special_pattern_pup  The pups that need the special search
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+				  int is_tx, u32 special_pattern_pup)
+{
+	u32 victim_dq;		/* loop index - victim DQ */
+	u32 adll_idx;
+	u32 pup;
+	u32 unlock_pup;		/* bit array of the unlock pups  */
+	u32 first_fail;	/* bit array - of pups that  get first fail */
+	u32 new_lockup_pup;	/* bit array of compare failed pups */
+	u32 pass_pup;		/* bit array of compare pass pup */
+	u32 sdram_offset;
+	u32 max_pup;
+	u32 comp_val;
+	u32 special_res[MAX_PUP_NUM];	/* hold tmp results */
+
+	DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
+
+	max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
+
+	/* Init the temporary results to max ADLL value */
+	for (pup = 0; pup < max_pup; pup++)
+		special_res[pup] = ADLL_MAX;
+
+	/* Run special pattern for all DQ - use the same pattern */
+	for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+		unlock_pup = special_pattern_pup;
+		first_fail = 0;
+
+		sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
+			LEN_KILLER_PATTERN * 4 * victim_dq;
+
+		for (pup = 0; pup < max_pup; pup++) {
+			/* Set adll value per PUP. adll = high limit per pup */
+			if (IS_PUP_ACTIVE(unlock_pup, pup)) {
+				/* only for pups that need special search */
+				ddr3_write_pup_reg(PUP_DQS_RD, cs,
+						   pup + (ecc * ECC_PUP), 0,
+						   centralization_high_limit
+						   [pup]);
+			}
+		}
+
+		adll_idx = 0;
+		do {
+			/*
+			 * Perform read and compare simultaneously for all
+			 * un-locked MC use the special pattern mask
+			 */
+			new_lockup_pup = 0;
+
+			if (MV_OK !=
+			    ddr3_sdram_dqs_compare(dram_info, unlock_pup,
+						   &new_lockup_pup,
+						   special_pattern
+						   [victim_dq],
+						   LEN_SPECIAL_PATTERN,
+						   sdram_offset, 0,
+						   0, NULL, 1))
+				return MV_FAIL;
+
+			DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
+			DEBUG_DQS_D(adll_idx, 2);
+			DEBUG_DQS_S(", UnlockPup: ");
+			DEBUG_DQS_D(unlock_pup, 2);
+			DEBUG_DQS_S(", NewLockPup: ");
+			DEBUG_DQS_D(new_lockup_pup, 2);
+			DEBUG_DQS_S("\n");
+
+			if (unlock_pup != new_lockup_pup)
+				DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
+
+			/* Search for pups with passed compare & already fail */
+			pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
+			first_fail |= new_lockup_pup;
+			unlock_pup &= ~pass_pup;
+
+			/* Get pass pups */
+			if (pass_pup != 0) {
+				for (pup = 0; pup < max_pup; pup++) {
+					if (IS_PUP_ACTIVE(pass_pup, pup) ==
+					    1) {
+						/* If pup passed and has first fail = 1 */
+						/* keep min value of ADLL max value - current adll */
+						/* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
+						comp_val =
+						    (ADLL_MAX -
+						     (centralization_high_limit
+						      [pup] + adll_idx));
+
+						DEBUG_DQS_C
+						    ("DDR3 - DQS - Special I - Pup - ",
+						     pup, 1);
+						DEBUG_DQS_C
+						    (" comp_val = ",
+						     comp_val, 2);
+
+						if (comp_val <
+						    special_res[pup]) {
+							special_res[pup] =
+							    comp_val;
+							centralization_low_limit
+							    [pup] =
+							    (-1) *
+							    comp_val;
+
+							DEBUG_DQS_C
+							    ("DDR3 - DQS - Special I - Pup - ",
+							     pup, 1);
+							DEBUG_DQS_C
+							    (" Changed Low limit to ",
+							     centralization_low_limit
+							     [pup], 2);
+						}
+					}
+				}
+			}
+
+			/*
+			 * Did all PUP found missing window?
+			 * Check for each pup if adll (different for each pup)
+			 * reach maximum if reach max value - lock the pup
+			 * if not - increment (Move to right one phase - ADLL)
+			 * dqs RX delay
+			 */
+			adll_idx++;
+			for (pup = 0; pup < max_pup; pup++) {
+				if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+					/* Check only unlocked pups */
+					if ((centralization_high_limit[pup] +
+					     adll_idx) >= ADLL_MAX) {
+						/* reach maximum - lock the pup */
+						DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
+							    pup, 1);
+						unlock_pup &= ~(1 << pup);
+					} else {
+						/* Didn't reach maximum - increment ADLL */
+						ddr3_write_pup_reg(PUP_DQS_RD,
+								   cs,
+								   pup +
+								   (ecc *
+								    ECC_PUP), 0,
+								   (centralization_high_limit
+								    [pup] +
+								    adll_idx));
+					}
+				}
+			}
+		} while (unlock_pup != 0);
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_special_pattern_ii_search
+ * Desc:     Execute special pattern high limit search.
+ * Args:
+ *           special_pattern_pup  The pups that need the special search
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+				   int is_tx, u32 special_pattern_pup)
+{
+	u32 victim_dq;		/* loop index - victim DQ */
+	u32 adll_idx;
+	u32 pup;
+	u32 unlock_pup;		/* bit array of the unlock pups  */
+	u32 first_fail;	/* bit array - of pups that  get first fail */
+	u32 new_lockup_pup;	/* bit array of compare failed pups */
+	u32 pass_pup;		/* bit array of compare pass pup */
+	u32 sdram_offset;
+	u32 max_pup;
+	u32 comp_val;
+	u32 special_res[MAX_PUP_NUM];	/* hold tmp results */
+
+	DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
+
+	max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+	/* init the tmporary results to max ADLL value */
+	for (pup = 0; pup < max_pup; pup++)
+		special_res[pup] = ADLL_MAX;
+
+	sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
+
+	/* run special pattern for all DQ - use the same pattern */
+	for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+		unlock_pup = special_pattern_pup;
+		first_fail = 0;
+
+		for (pup = 0; pup < max_pup; pup++) {
+			/* Set adll value per PUP. adll = 0 */
+			if (IS_PUP_ACTIVE(unlock_pup, pup)) {
+				/* Only for pups that need special search */
+				ddr3_write_pup_reg(PUP_DQS_RD, cs,
+						   pup + (ecc * ECC_PUP), 0,
+						   ADLL_MIN);
+			}
+		}
+
+		adll_idx = 0;
+		do {
+			/*
+			 * Perform read and compare simultaneously for all
+			 * un-locked MC use the special pattern mask
+			 */
+			new_lockup_pup = 0;
+
+			if (MV_OK != ddr3_sdram_dqs_compare(
+				    dram_info, unlock_pup, &new_lockup_pup,
+				    special_pattern[victim_dq],
+				    LEN_SPECIAL_PATTERN,
+				    sdram_offset, 0, 0, NULL, 0))
+				return MV_FAIL;
+
+			DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
+			DEBUG_DQS_D(adll_idx, 2);
+			DEBUG_DQS_S("unlock_pup ");
+			DEBUG_DQS_D(unlock_pup, 1);
+			DEBUG_DQS_S("new_lockup_pup ");
+			DEBUG_DQS_D(new_lockup_pup, 1);
+			DEBUG_DQS_S("\n");
+
+			if (unlock_pup != new_lockup_pup) {
+				DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
+			}
+
+			/* Search for pups with passed compare & already fail */
+			pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
+			first_fail |= new_lockup_pup;
+			unlock_pup &= ~pass_pup;
+
+			/* Get pass pups */
+			if (pass_pup != 0) {
+				for (pup = 0; pup < max_pup; pup++) {
+					if (IS_PUP_ACTIVE(pass_pup, pup) ==
+					    1) {
+						/* If pup passed and has first fail = 1 */
+						/* keep min value of ADLL max value - current adll */
+						/* (adll_idx) = current adll !!! */
+						comp_val = adll_idx;
+
+						DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
+							    pup, 1);
+						DEBUG_DQS_C(" comp_val = ",
+							    comp_val, 1);
+
+						if (comp_val <
+						    special_res[pup]) {
+							special_res[pup] =
+							    comp_val;
+							centralization_high_limit
+							    [pup] =
+							    ADLL_MAX +
+							    comp_val;
+
+							DEBUG_DQS_C
+							    ("DDR3 - DQS - Special II - Pup - ",
+							     pup, 1);
+							DEBUG_DQS_C
+							    (" Changed High limit to ",
+							     centralization_high_limit
+							     [pup], 2);
+						}
+					}
+				}
+			}
+
+			/*
+			 * Did all PUP found missing window?
+			 * Check for each pup if adll (different for each pup)
+			 * reach maximum if reach max value - lock the pup
+			 * if not - increment (Move to right one phase - ADLL)
+			 * dqs RX delay
+			 */
+			adll_idx++;
+			for (pup = 0; pup < max_pup; pup++) {
+				if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+					/* Check only unlocked pups */
+					if ((adll_idx) >= ADLL_MAX) {
+						/* Reach maximum - lock the pup */
+						DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
+							    pup, 1);
+						unlock_pup &= ~(1 << pup);
+					} else {
+						/* Didn't reach maximum - increment ADLL */
+						ddr3_write_pup_reg(PUP_DQS_RD,
+								   cs,
+								   pup +
+								   (ecc *
+								    ECC_PUP), 0,
+								   (adll_idx));
+					}
+				}
+			}
+		} while (unlock_pup != 0);
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_set_dqs_centralization_results
+ * Desc:     Set to HW the DQS centralization phase results.
+ * Args:
+ *           is_tx             Indicates whether to set Tx or RX results
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
+					u32 ecc, int is_tx)
+{
+	u32 pup, pup_num;
+	int addl_val;
+	u32 max_pup;
+
+	max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+	DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");;
+
+	if (is_tx) {
+		DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
+				    cs, 1);
+	} else {
+		DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
+				    cs, 1);
+	}
+
+	/* Set adll to center = (General_High_limit + General_Low_limit)/2 */
+	DEBUG_DQS_RESULTS_S("\nDQS    LOW     HIGH     WIN-SIZE      Set\n");
+	DEBUG_DQS_RESULTS_S("==============================================\n");
+	for (pup = 0; pup < max_pup; pup++) {
+		addl_val = (centralization_high_limit[pup] +
+			    centralization_low_limit[pup]) / 2;
+
+		pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
+
+		DEBUG_DQS_RESULTS_D(pup_num, 1);
+		DEBUG_DQS_RESULTS_S("     0x");
+		DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
+		DEBUG_DQS_RESULTS_S("      0x");
+		DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
+		DEBUG_DQS_RESULTS_S("      0x");
+		DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
+				    centralization_low_limit[pup], 2);
+		DEBUG_DQS_RESULTS_S("       0x");
+		DEBUG_DQS_RESULTS_D(addl_val, 2);
+		DEBUG_DQS_RESULTS_S("\n");
+
+		if (addl_val < ADLL_MIN) {
+			addl_val = ADLL_MIN;
+			DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
+		}
+
+		if (addl_val > ADLL_MAX) {
+			addl_val = ADLL_MAX;
+			DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
+		}
+
+		if (is_tx) {
+			ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
+					   addl_val +
+					   dram_info->wl_val[cs][pup_num][D]);
+		} else {
+			ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
+					   addl_val);
+		}
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
+{
+	u32 cs, cs_count, cs_tmp, victim_dq;
+	u32 sdram_addr;
+	u32 *pattern_ptr;
+
+	/* Loop for each CS */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			cs_count = 0;
+			for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+				if (dram_info->cs_ena & (1 << cs_tmp))
+					cs_count++;
+			}
+
+			/* Init killer pattern */
+			sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+				      SDRAM_DQS_RX_OFFS);
+			for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+				pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
+								      victim_dq);
+				if (MV_OK != ddr3_sdram_dqs_compare(
+					    dram_info, (u32)NULL, NULL,
+					    pattern_ptr, LEN_KILLER_PATTERN,
+					    sdram_addr + LEN_KILLER_PATTERN *
+					    4 * victim_dq, 1, 0, NULL,
+					    0))
+					return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
+			}
+
+			/* Init special-killer pattern */
+			sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+				      SDRAM_DQS_RX_SPECIAL_OFFS);
+			for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+				if (MV_OK != ddr3_sdram_dqs_compare(
+					    dram_info, (u32)NULL, NULL,
+					    special_pattern[victim_dq],
+					    LEN_KILLER_PATTERN, sdram_addr +
+					    LEN_KILLER_PATTERN * 4 * victim_dq,
+					    1, 0, NULL, 0))
+					return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
+			}
+		}
+	}
+
+	return MV_OK;
+}
diff --git a/drivers/ddr/mvebu/ddr3_hw_training.c b/drivers/ddr/mvebu/ddr3_hw_training.c
new file mode 100644
index 0000000..a8c5e6a
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_hw_training.c
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+#include "ddr3_hw_training.h"
+#include "xor.h"
+
+#ifdef MV88F78X60
+#include "ddr3_patterns_64bit.h"
+#else
+#include "ddr3_patterns_16bit.h"
+#if defined(MV88F672X)
+#include "ddr3_patterns_16bit.h"
+#endif
+#endif
+
+/*
+ * Debug
+ */
+
+#define DEBUG_MAIN_C(s, d, l) \
+	DEBUG_MAIN_S(s); DEBUG_MAIN_D(d, l); DEBUG_MAIN_S("\n")
+#define DEBUG_MAIN_FULL_C(s, d, l) \
+	DEBUG_MAIN_FULL_S(s); DEBUG_MAIN_FULL_D(d, l); DEBUG_MAIN_FULL_S("\n")
+
+#ifdef MV_DEBUG_MAIN
+#define DEBUG_MAIN_S(s)			puts(s)
+#define DEBUG_MAIN_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_MAIN_S(s)
+#define DEBUG_MAIN_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_MAIN_FULL
+#define DEBUG_MAIN_FULL_S(s)		puts(s)
+#define DEBUG_MAIN_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_MAIN_FULL_S(s)
+#define DEBUG_MAIN_FULL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_SUSPEND_RESUME
+#define DEBUG_SUSPEND_RESUME_S(s)	puts(s)
+#define DEBUG_SUSPEND_RESUME_D(d, l)	printf("%x", d)
+#else
+#define DEBUG_SUSPEND_RESUME_S(s)
+#define DEBUG_SUSPEND_RESUME_D(d, l)
+#endif
+
+static u32 ddr3_sw_wl_rl_debug;
+static u32 ddr3_run_pbs = 1;
+
+void ddr3_print_version(void)
+{
+	puts("DDR3 Training Sequence - Ver 5.7.");
+}
+
+void ddr3_set_sw_wl_rl_debug(u32 val)
+{
+	ddr3_sw_wl_rl_debug = val;
+}
+
+void ddr3_set_pbs(u32 val)
+{
+	ddr3_run_pbs = val;
+}
+
+int ddr3_hw_training(u32 target_freq, u32 ddr_width, int xor_bypass,
+		     u32 scrub_offs, u32 scrub_size, int dqs_clk_aligned,
+		     int debug_mode, int reg_dimm_skip_wl)
+{
+	/* A370 has no PBS mechanism */
+	__maybe_unused u32 first_loop_flag = 0;
+	u32 freq, reg;
+	MV_DRAM_INFO dram_info;
+	int ratio_2to1 = 0;
+	int tmp_ratio = 1;
+	int status;
+
+	if (debug_mode)
+		DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 1\n");
+
+	memset(&dram_info, 0, sizeof(dram_info));
+	dram_info.num_cs = ddr3_get_cs_num_from_reg();
+	dram_info.cs_ena = ddr3_get_cs_ena_from_reg();
+	dram_info.target_frequency = target_freq;
+	dram_info.ddr_width = ddr_width;
+	dram_info.num_of_std_pups = ddr_width / PUP_SIZE;
+	dram_info.rl400_bug = 0;
+	dram_info.multi_cs_mr_support = 0;
+#ifdef MV88F67XX
+	dram_info.rl400_bug = 1;
+#endif
+
+	/* Ignore ECC errors - if ECC is enabled */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+	if (reg & (1 << REG_SDRAM_CONFIG_ECC_OFFS)) {
+		dram_info.ecc_ena = 1;
+		reg |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
+		reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+	} else {
+		dram_info.ecc_ena = 0;
+	}
+
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+	if (reg & (1 << REG_SDRAM_CONFIG_REGDIMM_OFFS))
+		dram_info.reg_dimm = 1;
+	else
+		dram_info.reg_dimm = 0;
+
+	dram_info.num_of_total_pups = ddr_width / PUP_SIZE + dram_info.ecc_ena;
+
+	/* Get target 2T value */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	dram_info.mode_2t = (reg >> REG_DUNIT_CTRL_LOW_2T_OFFS) &
+		REG_DUNIT_CTRL_LOW_2T_MASK;
+
+	/* Get target CL value */
+#ifdef MV88F67XX
+	reg = reg_read(REG_DDR3_MR0_ADDR) >> 2;
+#else
+	reg = reg_read(REG_DDR3_MR0_CS_ADDR) >> 2;
+#endif
+
+	reg = (((reg >> 1) & 0xE) | (reg & 0x1)) & 0xF;
+	dram_info.cl = ddr3_valid_cl_to_cl(reg);
+
+	/* Get target CWL value */
+#ifdef MV88F67XX
+	reg = reg_read(REG_DDR3_MR2_ADDR) >> REG_DDR3_MR2_CWL_OFFS;
+#else
+	reg = reg_read(REG_DDR3_MR2_CS_ADDR) >> REG_DDR3_MR2_CWL_OFFS;
+#endif
+
+	reg &= REG_DDR3_MR2_CWL_MASK;
+	dram_info.cwl = reg;
+#if !defined(MV88F67XX)
+	/* A370 has no PBS mechanism */
+#if defined(MV88F78X60)
+	if ((dram_info.target_frequency > DDR_400) && (ddr3_run_pbs))
+		first_loop_flag = 1;
+#else
+	/* first_loop_flag = 1; skip mid freq at ALP/A375 */
+	if ((dram_info.target_frequency > DDR_400) && (ddr3_run_pbs) &&
+	    (mv_ctrl_revision_get() >= UMC_A0))
+		first_loop_flag = 1;
+	else
+		first_loop_flag = 0;
+#endif
+#endif
+
+	freq = dram_info.target_frequency;
+
+	/* Set ODT to always on */
+	ddr3_odt_activate(1);
+
+	/* Init XOR */
+	mv_sys_xor_init(&dram_info);
+
+	/* Get DRAM/HCLK ratio */
+	if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+		ratio_2to1 = 1;
+
+	/*
+	 * Xor Bypass - ECC support in AXP is currently available for 1:1
+	 * modes frequency modes.
+	 * Not all frequency modes support the ddr3 training sequence
+	 * (Only 1200/300).
+	 * Xor Bypass allows using the Xor initializations and scrubbing
+	 * inside the ddr3 training sequence without running the training
+	 * itself.
+	 */
+	if (xor_bypass == 0) {
+		if (ddr3_run_pbs) {
+			DEBUG_MAIN_S("DDR3 Training Sequence - Run with PBS.\n");
+		} else {
+			DEBUG_MAIN_S("DDR3 Training Sequence - Run without PBS.\n");
+		}
+
+		if (dram_info.target_frequency > DFS_MARGIN) {
+			tmp_ratio = 0;
+			freq = DDR_100;
+
+			if (dram_info.reg_dimm == 1)
+				freq = DDR_300;
+
+			if (MV_OK != ddr3_dfs_high_2_low(freq, &dram_info)) {
+				/* Set low - 100Mhz DDR Frequency by HW */
+				DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs High2Low)\n");
+				return MV_DDR3_TRAINING_ERR_DFS_H2L;
+			}
+
+			if ((dram_info.reg_dimm == 1) &&
+			    (reg_dimm_skip_wl == 0)) {
+				if (MV_OK !=
+				    ddr3_write_leveling_hw_reg_dimm(freq,
+								    &dram_info))
+					DEBUG_MAIN_S("DDR3 Training Sequence - Registered DIMM Low WL - SKIP\n");
+			}
+
+			if (ddr3_get_log_level() >= MV_LOG_LEVEL_1)
+				ddr3_print_freq(freq);
+
+			if (debug_mode)
+				DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 2\n");
+		} else {
+			if (!dqs_clk_aligned) {
+#ifdef MV88F67XX
+				/*
+				 * If running training sequence without DFS,
+				 * we must run Write leveling before writing
+				 * the patterns
+				 */
+
+				/*
+				 * ODT - Multi CS system use SW WL,
+				 * Single CS System use HW WL
+				 */
+				if (dram_info.cs_ena > 1) {
+					if (MV_OK !=
+					    ddr3_write_leveling_sw(
+						    freq, tmp_ratio,
+						    &dram_info)) {
+						DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+						return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+					}
+				} else {
+					if (MV_OK !=
+					    ddr3_write_leveling_hw(freq,
+								   &dram_info)) {
+						DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+						return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+					}
+				}
+#else
+				if (MV_OK != ddr3_write_leveling_hw(
+					    freq, &dram_info)) {
+					DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+					if (ddr3_sw_wl_rl_debug) {
+						if (MV_OK !=
+						    ddr3_write_leveling_sw(
+							    freq, tmp_ratio,
+							    &dram_info)) {
+							DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+							return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+						}
+					} else {
+						return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+					}
+				}
+#endif
+			}
+
+			if (debug_mode)
+				DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 3\n");
+		}
+
+		if (MV_OK != ddr3_load_patterns(&dram_info, 0)) {
+			DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Loading Patterns)\n");
+			return MV_DDR3_TRAINING_ERR_LOAD_PATTERNS;
+		}
+
+		/*
+		 * TODO:
+		 * The mainline U-Boot port of the bin_hdr DDR training code
+		 * needs a delay of minimum 20ms here (10ms is a bit too short
+		 * and the CPU hangs). The bin_hdr code doesn't have this delay.
+		 * To be save here, lets add a delay of 50ms here.
+		 *
+		 * Tested on the Marvell DB-MV784MP-GP board
+		 */
+		mdelay(50);
+
+		do {
+			freq = dram_info.target_frequency;
+			tmp_ratio = ratio_2to1;
+			DEBUG_MAIN_FULL_S("DDR3 Training Sequence - DEBUG - 4\n");
+
+#if defined(MV88F78X60)
+			/*
+			 * There is a difference on the DFS frequency at the
+			 * first iteration of this loop
+			 */
+			if (first_loop_flag) {
+				freq = DDR_400;
+				tmp_ratio = 0;
+			}
+#endif
+
+			if (MV_OK != ddr3_dfs_low_2_high(freq, tmp_ratio,
+							 &dram_info)) {
+				DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs Low2High)\n");
+				return MV_DDR3_TRAINING_ERR_DFS_H2L;
+			}
+
+			if (ddr3_get_log_level() >= MV_LOG_LEVEL_1) {
+				ddr3_print_freq(freq);
+			}
+
+			if (debug_mode)
+				DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 5\n");
+
+			/* Write leveling */
+			if (!dqs_clk_aligned) {
+#ifdef MV88F67XX
+				/*
+				 * ODT - Multi CS system that not support Multi
+				 * CS MRS commands must use SW WL
+				 */
+				if (dram_info.cs_ena > 1) {
+					if (MV_OK != ddr3_write_leveling_sw(
+						    freq, tmp_ratio, &dram_info)) {
+						DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+						return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+					}
+				} else {
+					if (MV_OK != ddr3_write_leveling_hw(
+						    freq, &dram_info)) {
+						DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+						return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+					}
+				}
+#else
+				if ((dram_info.reg_dimm == 1) &&
+				    (freq == DDR_400)) {
+					if (reg_dimm_skip_wl == 0) {
+						if (MV_OK != ddr3_write_leveling_hw_reg_dimm(
+							    freq, &dram_info))
+							DEBUG_MAIN_S("DDR3 Training Sequence - Registered DIMM WL - SKIP\n");
+					}
+				} else {
+					if (MV_OK != ddr3_write_leveling_hw(
+						    freq, &dram_info)) {
+						DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+						if (ddr3_sw_wl_rl_debug) {
+							if (MV_OK != ddr3_write_leveling_sw(
+								    freq, tmp_ratio, &dram_info)) {
+								DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+								return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+							}
+						} else {
+							return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+						}
+					}
+				}
+#endif
+				if (debug_mode)
+					DEBUG_MAIN_S
+					    ("DDR3 Training Sequence - DEBUG - 6\n");
+			}
+
+			/* Read Leveling */
+			/*
+			 * Armada 370 - Support for HCLK @ 400MHZ - must use
+			 * SW read leveling
+			 */
+			if (freq == DDR_400 && dram_info.rl400_bug) {
+				status = ddr3_read_leveling_sw(freq, tmp_ratio,
+						       &dram_info);
+				if (MV_OK != status) {
+					DEBUG_MAIN_S
+					    ("DDR3 Training Sequence - FAILED (Read Leveling Sw)\n");
+					return status;
+				}
+			} else {
+				if (MV_OK != ddr3_read_leveling_hw(
+					    freq, &dram_info)) {
+					DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Hw)\n");
+					if (ddr3_sw_wl_rl_debug) {
+						if (MV_OK != ddr3_read_leveling_sw(
+							    freq, tmp_ratio,
+							    &dram_info)) {
+							DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Sw)\n");
+							return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+						}
+					} else {
+						return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+					}
+				}
+			}
+
+			if (debug_mode)
+				DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 7\n");
+
+			if (MV_OK != ddr3_wl_supplement(&dram_info)) {
+				DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hi-Freq Sup)\n");
+				return MV_DDR3_TRAINING_ERR_WR_LVL_HI_FREQ;
+			}
+
+			if (debug_mode)
+				DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 8\n");
+#if !defined(MV88F67XX)
+			/* A370 has no PBS mechanism */
+#if defined(MV88F78X60) || defined(MV88F672X)
+			if (first_loop_flag == 1) {
+				first_loop_flag = 0;
+
+				status = MV_OK;
+				status = ddr3_pbs_rx(&dram_info);
+				if (MV_OK != status) {
+					DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (PBS RX)\n");
+					return status;
+				}
+
+				if (debug_mode)
+					DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 9\n");
+
+				status = ddr3_pbs_tx(&dram_info);
+				if (MV_OK != status) {
+					DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (PBS TX)\n");
+					return status;
+				}
+
+				if (debug_mode)
+					DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 10\n");
+			}
+#endif
+#endif
+		} while (freq != dram_info.target_frequency);
+
+		status = ddr3_dqs_centralization_rx(&dram_info);
+		if (MV_OK != status) {
+			DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (DQS Centralization RX)\n");
+			return status;
+		}
+
+		if (debug_mode)
+			DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 11\n");
+
+		status = ddr3_dqs_centralization_tx(&dram_info);
+		if (MV_OK != status) {
+			DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (DQS Centralization TX)\n");
+			return status;
+		}
+
+		if (debug_mode)
+			DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 12\n");
+	}
+
+	ddr3_set_performance_params(&dram_info);
+
+	if (dram_info.ecc_ena) {
+		/* Need to SCRUB the DRAM memory area to load U-boot */
+		mv_sys_xor_finish();
+		dram_info.num_cs = 1;
+		dram_info.cs_ena = 1;
+		mv_sys_xor_init(&dram_info);
+		mv_xor_mem_init(0, scrub_offs, scrub_size, 0xdeadbeef,
+				0xdeadbeef);
+
+		/* Wait for previous transfer completion */
+		while (mv_xor_state_get(0) != MV_IDLE)
+			;
+
+		if (debug_mode)
+			DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 13\n");
+	}
+
+	/* Return XOR State */
+	mv_sys_xor_finish();
+
+#if defined(MV88F78X60)
+	/* Save training results in memeory for resume state */
+	ddr3_save_training(&dram_info);
+#endif
+	/* Clear ODT always on */
+	ddr3_odt_activate(0);
+
+	/* Configure Dynamic read ODT */
+	ddr3_odt_read_dynamic_config(&dram_info);
+
+	return MV_OK;
+}
+
+void ddr3_set_performance_params(MV_DRAM_INFO *dram_info)
+{
+	u32 twr2wr, trd2rd, trd2wr_wr2rd;
+	u32 tmp1, tmp2, reg;
+
+	DEBUG_MAIN_FULL_C("Max WL Phase: ", dram_info->wl_max_phase, 2);
+	DEBUG_MAIN_FULL_C("Min WL Phase: ", dram_info->wl_min_phase, 2);
+	DEBUG_MAIN_FULL_C("Max RL Phase: ", dram_info->rl_max_phase, 2);
+	DEBUG_MAIN_FULL_C("Min RL Phase: ", dram_info->rl_min_phase, 2);
+
+	if (dram_info->wl_max_phase < 2)
+		twr2wr = 0x2;
+	else
+		twr2wr = 0x3;
+
+	trd2rd = 0x1 + (dram_info->rl_max_phase + 1) / 2 +
+		(dram_info->rl_max_phase + 1) % 2;
+
+	tmp1 = (dram_info->rl_max_phase - dram_info->wl_min_phase) / 2 +
+		(((dram_info->rl_max_phase - dram_info->wl_min_phase) % 2) >
+		 0 ? 1 : 0);
+	tmp2 = (dram_info->wl_max_phase - dram_info->rl_min_phase) / 2 +
+		((dram_info->wl_max_phase - dram_info->rl_min_phase) % 2 >
+		 0 ? 1 : 0);
+	trd2wr_wr2rd = (tmp1 >= tmp2) ? tmp1 : tmp2;
+
+	trd2wr_wr2rd += 2;
+	trd2rd += 2;
+	twr2wr += 2;
+
+	DEBUG_MAIN_FULL_C("WR 2 WR: ", twr2wr, 2);
+	DEBUG_MAIN_FULL_C("RD 2 RD: ", trd2rd, 2);
+	DEBUG_MAIN_FULL_C("RD 2 WR / WR 2 RD: ", trd2wr_wr2rd, 2);
+
+	reg = reg_read(REG_SDRAM_TIMING_HIGH_ADDR);
+
+	reg &= ~(REG_SDRAM_TIMING_H_W2W_MASK << REG_SDRAM_TIMING_H_W2W_OFFS);
+	reg |= ((twr2wr & REG_SDRAM_TIMING_H_W2W_MASK) <<
+		REG_SDRAM_TIMING_H_W2W_OFFS);
+
+	reg &= ~(REG_SDRAM_TIMING_H_R2R_MASK << REG_SDRAM_TIMING_H_R2R_OFFS);
+	reg &= ~(REG_SDRAM_TIMING_H_R2R_H_MASK <<
+		 REG_SDRAM_TIMING_H_R2R_H_OFFS);
+	reg |= ((trd2rd & REG_SDRAM_TIMING_H_R2R_MASK) <<
+		REG_SDRAM_TIMING_H_R2R_OFFS);
+	reg |= (((trd2rd >> 2) & REG_SDRAM_TIMING_H_R2R_H_MASK) <<
+		REG_SDRAM_TIMING_H_R2R_H_OFFS);
+
+	reg &= ~(REG_SDRAM_TIMING_H_R2W_W2R_MASK <<
+		 REG_SDRAM_TIMING_H_R2W_W2R_OFFS);
+	reg &= ~(REG_SDRAM_TIMING_H_R2W_W2R_H_MASK <<
+		 REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS);
+	reg |= ((trd2wr_wr2rd & REG_SDRAM_TIMING_H_R2W_W2R_MASK) <<
+		REG_SDRAM_TIMING_H_R2W_W2R_OFFS);
+	reg |= (((trd2wr_wr2rd >> 2) & REG_SDRAM_TIMING_H_R2W_W2R_H_MASK) <<
+		REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS);
+
+	reg_write(REG_SDRAM_TIMING_HIGH_ADDR, reg);
+}
+
+/*
+ * Perform DDR3 PUP Indirect Write
+ */
+void ddr3_write_pup_reg(u32 mode, u32 cs, u32 pup, u32 phase, u32 delay)
+{
+	u32 reg = 0;
+
+	if (pup == PUP_BC)
+		reg |= (1 << REG_PHY_BC_OFFS);
+	else
+		reg |= (pup << REG_PHY_PUP_OFFS);
+
+	reg |= ((0x4 * cs + mode) << REG_PHY_CS_OFFS);
+	reg |= (phase << REG_PHY_PHASE_OFFS) | delay;
+
+	if (mode == PUP_WL_MODE)
+		reg |= ((INIT_WL_DELAY + delay) << REG_PHY_DQS_REF_DLY_OFFS);
+
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+	reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+
+	do {
+		reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+			REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+	} while (reg);	/* Wait for '0' to mark the end of the transaction */
+
+	/* If read Leveling mode - need to write to register 3 separetly */
+	if (mode == PUP_RL_MODE) {
+		reg = 0;
+
+		if (pup == PUP_BC)
+			reg |= (1 << REG_PHY_BC_OFFS);
+		else
+			reg |= (pup << REG_PHY_PUP_OFFS);
+
+		reg |= ((0x4 * cs + mode + 1) << REG_PHY_CS_OFFS);
+		reg |= (INIT_RL_DELAY);
+
+		reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg); /* 0x16A0 */
+		reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+		reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg); /* 0x16A0 */
+
+		do {
+			reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+				REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+		} while (reg);
+	}
+}
+
+/*
+ * Perform DDR3 PUP Indirect Read
+ */
+u32 ddr3_read_pup_reg(u32 mode, u32 cs, u32 pup)
+{
+	u32 reg;
+
+	reg = (pup << REG_PHY_PUP_OFFS) |
+		((0x4 * cs + mode) << REG_PHY_CS_OFFS);
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+
+	reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_RD;
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+
+	do {
+		reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+			REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+	} while (reg);	/* Wait for '0' to mark the end of the transaction */
+
+	return reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR);	/* 0x16A0 */
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_patterns(MV_DRAM_INFO *dram_info, int resume)
+{
+	u32 reg;
+
+	/* Enable SW override - Required for the ECC Pup */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	if (resume == 0) {
+#if defined(MV88F78X60) || defined(MV88F672X)
+		ddr3_load_pbs_patterns(dram_info);
+#endif
+		ddr3_load_dqs_patterns(dram_info);
+	}
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	/* Set Base Addr */
+#if defined(MV88F67XX)
+	reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR, 0);
+#else
+	if (resume == 0)
+		reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR, 0);
+	else
+		reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR,
+			  RESUME_RL_PATTERNS_ADDR);
+#endif
+
+	/* Set Patterns */
+	if (resume == 0) {
+		reg = (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS) |
+			(1 << REG_DRAM_TRAINING_PATTERNS_OFFS);
+	} else {
+		reg = (0x1 << REG_DRAM_TRAINING_CS_OFFS) |
+			(1 << REG_DRAM_TRAINING_PATTERNS_OFFS);
+	}
+
+	reg |= (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+	udelay(100);
+
+	/* Check if Successful */
+	if (reg_read(REG_DRAM_TRAINING_ADDR) &
+	    (1 << REG_DRAM_TRAINING_ERROR_OFFS))
+		return MV_OK;
+	else
+		return MV_FAIL;
+}
+
+#if !defined(MV88F67XX)
+/*
+ * Name:     ddr3_save_training(MV_DRAM_INFO *dram_info)
+ * Desc:     saves the training results to memeory (RL,WL,PBS,Rx/Tx
+ *           Centeralization)
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_save_training(MV_DRAM_INFO *dram_info)
+{
+	u32 val, pup, tmp_cs, cs, i, dq;
+	u32 crc = 0;
+	u32 regs = 0;
+	u32 *sdram_offset = (u32 *)RESUME_TRAINING_VALUES_ADDR;
+	u32 mode_config[MAX_TRAINING_MODE];
+
+	mode_config[DQS_WR_MODE] = PUP_DQS_WR;
+	mode_config[WL_MODE_] = PUP_WL_MODE;
+	mode_config[RL_MODE_] = PUP_RL_MODE;
+	mode_config[DQS_RD_MODE] = PUP_DQS_RD;
+	mode_config[PBS_TX_DM_MODE] = PUP_PBS_TX_DM;
+	mode_config[PBS_TX_MODE] = PUP_PBS_TX;
+	mode_config[PBS_RX_MODE] = PUP_PBS_RX;
+
+	/* num of training modes */
+	for (i = 0; i < MAX_TRAINING_MODE; i++) {
+		tmp_cs = dram_info->cs_ena;
+		/* num of CS */
+		for (cs = 0; cs < MAX_CS; cs++) {
+			if (tmp_cs & (1 << cs)) {
+				/* num of PUPs */
+				for (pup = 0; pup < dram_info->num_of_total_pups;
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups &&
+					    dram_info->ecc_ena)
+						pup = ECC_PUP;
+					if (i == PBS_TX_DM_MODE) {
+						/*
+						 * Change CS bitmask because
+						 * PBS works only with CS0
+						 */
+						tmp_cs = 0x1;
+						val = ddr3_read_pup_reg(
+							mode_config[i], CS0, pup);
+					} else if (i == PBS_TX_MODE ||
+						   i == PBS_RX_MODE) {
+						/*
+						 * Change CS bitmask because
+						 * PBS works only with CS0
+						 */
+						tmp_cs = 0x1;
+						for (dq = 0; dq <= DQ_NUM;
+						     dq++) {
+							val = ddr3_read_pup_reg(
+								mode_config[i] + dq,
+								CS0,
+								pup);
+							(*sdram_offset) = val;
+							crc += *sdram_offset;
+							sdram_offset++;
+							regs++;
+						}
+						continue;
+					} else {
+						val = ddr3_read_pup_reg(
+							mode_config[i], cs, pup);
+					}
+
+					*sdram_offset = val;
+					crc += *sdram_offset;
+					sdram_offset++;
+					regs++;
+				}
+			}
+		}
+	}
+
+	*sdram_offset = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+	crc += *sdram_offset;
+	sdram_offset++;
+	regs++;
+	*sdram_offset = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+	crc += *sdram_offset;
+	sdram_offset++;
+	regs++;
+	sdram_offset = (u32 *)NUM_OF_REGISTER_ADDR;
+	*sdram_offset = regs;
+	DEBUG_SUSPEND_RESUME_S("Training Results CheckSum write= ");
+	DEBUG_SUSPEND_RESUME_D(crc, 8);
+	DEBUG_SUSPEND_RESUME_S("\n");
+	sdram_offset = (u32 *)CHECKSUM_RESULT_ADDR;
+	*sdram_offset = crc;
+}
+
+/*
+ * Name:     ddr3_read_training_results()
+ * Desc:     Reads the training results from memeory (RL,WL,PBS,Rx/Tx
+ *           Centeralization)
+ *           and writes them to the relevant registers
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  None.
+ */
+int ddr3_read_training_results(void)
+{
+	u32 val, reg, idx, dqs_wr_idx = 0, crc = 0;
+	u32 *sdram_offset = (u32 *)RESUME_TRAINING_VALUES_ADDR;
+	u32 training_val[RESUME_TRAINING_VALUES_MAX] = { 0 };
+	u32 regs = *((u32 *)NUM_OF_REGISTER_ADDR);
+
+	/*
+	 * Read Training results & Dunit registers from memory and write
+	 * it to an array
+	 */
+	for (idx = 0; idx < regs; idx++) {
+		training_val[idx] = *sdram_offset;
+		crc += *sdram_offset;
+		sdram_offset++;
+	}
+
+	sdram_offset = (u32 *)CHECKSUM_RESULT_ADDR;
+
+	if ((*sdram_offset) == crc) {
+		DEBUG_SUSPEND_RESUME_S("Training Results CheckSum read PASS= ");
+		DEBUG_SUSPEND_RESUME_D(crc, 8);
+		DEBUG_SUSPEND_RESUME_S("\n");
+	} else {
+		DEBUG_MAIN_S("Wrong Training Results CheckSum\n");
+		return MV_FAIL;
+	}
+
+	/*
+	 * We iterate through all the registers except for the last 2 since
+	 * they are Dunit registers (and not PHY registers)
+	 */
+	for (idx = 0; idx < (regs - 2); idx++) {
+		val = training_val[idx];
+		reg = (val >> REG_PHY_CS_OFFS) & 0x3F; /*read the phy address */
+
+		/* Check if the values belongs to the DQS WR */
+		if (reg == PUP_WL_MODE) {
+			/* bit[5:0] in DQS_WR are delay */
+			val = (training_val[dqs_wr_idx++] & 0x3F);
+			/*
+			 * bit[15:10] are DQS_WR delay & bit[9:0] are
+			 * WL phase & delay
+			 */
+			val = (val << REG_PHY_DQS_REF_DLY_OFFS) |
+				(training_val[idx] & 0x3C003FF);
+			/* Add Request pending and write operation bits */
+			val |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+		} else if (reg == PUP_DQS_WR) {
+			/*
+			 * Do nothing since DQS_WR will be done in PUP_WL_MODE
+			 */
+			continue;
+		}
+
+		val |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+		reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, val);
+		do {
+			val = (reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR)) &
+				REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+		} while (val);	/* Wait for '0' to mark the end of the transaction */
+	}
+
+	/* write last 2 Dunit configurations */
+	val = training_val[idx];
+	reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, val);	/* reg 0x1538 */
+	val = training_val[idx + 1];
+	reg_write(REG_READ_DATA_READY_DELAYS_ADDR, val);	/* reg 0x153c */
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_check_if_resume_mode()
+ * Desc:     Reads the address (0x3000) of the Resume Magic word (0xDEADB002)
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  return (magic_word == SUSPEND_MAGIC_WORD)
+ */
+int ddr3_check_if_resume_mode(MV_DRAM_INFO *dram_info, u32 freq)
+{
+	u32 magic_word;
+	u32 *sdram_offset = (u32 *)BOOT_INFO_ADDR;
+
+	if (dram_info->reg_dimm != 1) {
+		/*
+		 * Perform write levleling in order initiate the phy with
+		 * low frequency
+		 */
+		if (MV_OK != ddr3_write_leveling_hw(freq, dram_info)) {
+			DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+			return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+		}
+	}
+
+	if (MV_OK != ddr3_load_patterns(dram_info, 1)) {
+		DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Loading Patterns)\n");
+		return MV_DDR3_TRAINING_ERR_LOAD_PATTERNS;
+	}
+
+	/* Enable CS0 only for RL */
+	dram_info->cs_ena = 0x1;
+
+	/* Perform Read levleling in order to get stable memory */
+	if (MV_OK != ddr3_read_leveling_hw(freq, dram_info)) {
+		DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Hw)\n");
+		return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+	}
+
+	/* Back to relevant CS */
+	dram_info->cs_ena = ddr3_get_cs_ena_from_reg();
+
+	magic_word = *sdram_offset;
+	return magic_word == SUSPEND_MAGIC_WORD;
+}
+
+/*
+ * Name:     ddr3_training_suspend_resume()
+ * Desc:     Execute the Resume state
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  return (magic_word == SUSPEND_MAGIC_WORD)
+ */
+int ddr3_training_suspend_resume(MV_DRAM_INFO *dram_info)
+{
+	u32 freq, reg;
+	int tmp_ratio;
+
+	/* Configure DDR */
+	if (MV_OK != ddr3_read_training_results())
+		return MV_FAIL;
+
+	/* Reset read FIFO */
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+
+	/* Start Auto Read Leveling procedure */
+	reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) +
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+
+	/* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	udelay(2);
+
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+	/* Clear Auto Read Leveling procedure */
+	reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	/* Return to target frequency */
+	freq = dram_info->target_frequency;
+	tmp_ratio = 1;
+	if (MV_OK != ddr3_dfs_low_2_high(freq, tmp_ratio, dram_info)) {
+		DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs Low2High)\n");
+		return MV_DDR3_TRAINING_ERR_DFS_H2L;
+	}
+
+	if (dram_info->ecc_ena) {
+		/* Scabbling the RL area pattern and the training area */
+		mv_sys_xor_finish();
+		dram_info->num_cs = 1;
+		dram_info->cs_ena = 1;
+		mv_sys_xor_init(dram_info);
+		mv_xor_mem_init(0, RESUME_RL_PATTERNS_ADDR,
+				RESUME_RL_PATTERNS_SIZE, 0xFFFFFFFF, 0xFFFFFFFF);
+
+		/* Wait for previous transfer completion */
+
+		while (mv_xor_state_get(0) != MV_IDLE)
+			;
+
+		/* Return XOR State */
+		mv_sys_xor_finish();
+	}
+
+	return MV_OK;
+}
+#endif
+
+void ddr3_print_freq(u32 freq)
+{
+	u32 tmp_freq;
+
+	switch (freq) {
+	case 0:
+		tmp_freq = 100;
+		break;
+	case 1:
+		tmp_freq = 300;
+		break;
+	case 2:
+		tmp_freq = 360;
+		break;
+	case 3:
+		tmp_freq = 400;
+		break;
+	case 4:
+		tmp_freq = 444;
+		break;
+	case 5:
+		tmp_freq = 500;
+		break;
+	case 6:
+		tmp_freq = 533;
+		break;
+	case 7:
+		tmp_freq = 600;
+		break;
+	case 8:
+		tmp_freq = 666;
+		break;
+	case 9:
+		tmp_freq = 720;
+		break;
+	case 10:
+		tmp_freq = 800;
+		break;
+	default:
+		tmp_freq = 100;
+	}
+
+	printf("Current frequency is: %dMHz\n", tmp_freq);
+}
+
+int ddr3_get_min_max_read_sample_delay(u32 cs_enable, u32 reg, u32 *min,
+				       u32 *max, u32 *cs_max)
+{
+	u32 cs, delay;
+
+	*min = 0xFFFFFFFF;
+	*max = 0x0;
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if ((cs_enable & (1 << cs)) == 0)
+			continue;
+
+		delay = ((reg >> (cs * 8)) & 0x1F);
+
+		if (delay < *min)
+			*min = delay;
+
+		if (delay > *max) {
+			*max = delay;
+			*cs_max = cs;
+		}
+	}
+
+	return MV_OK;
+}
+
+int ddr3_get_min_max_rl_phase(MV_DRAM_INFO *dram_info, u32 *min, u32 *max,
+			      u32 cs)
+{
+	u32 pup, reg, phase;
+
+	*min = 0xFFFFFFFF;
+	*max = 0x0;
+
+	for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+		reg = ddr3_read_pup_reg(PUP_RL_MODE, cs, pup);
+		phase = ((reg >> 8) & 0x7);
+
+		if (phase < *min)
+			*min = phase;
+
+		if (phase > *max)
+			*max = phase;
+	}
+
+	return MV_OK;
+}
+
+int ddr3_odt_activate(int activate)
+{
+	u32 reg, mask;
+
+	mask = (1 << REG_DUNIT_ODT_CTRL_OVRD_OFFS) |
+		(1 << REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS);
+	/* {0x0000149C}  -   DDR Dunit ODT Control Register */
+	reg = reg_read(REG_DUNIT_ODT_CTRL_ADDR);
+	if (activate)
+		reg |= mask;
+	else
+		reg &= ~mask;
+
+	reg_write(REG_DUNIT_ODT_CTRL_ADDR, reg);
+
+	return MV_OK;
+}
+
+int ddr3_odt_read_dynamic_config(MV_DRAM_INFO *dram_info)
+{
+	u32 min_read_sample_delay, max_read_sample_delay, max_rl_phase;
+	u32 min, max, cs_max;
+	u32 cs_ena, reg;
+
+	reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+	cs_ena = ddr3_get_cs_ena_from_reg();
+
+	/* Get minimum and maximum of read sample delay of all CS */
+	ddr3_get_min_max_read_sample_delay(cs_ena, reg, &min_read_sample_delay,
+					   &max_read_sample_delay, &cs_max);
+
+	/*
+	 * Get minimum and maximum read leveling phase which belongs to the
+	 * maximal read sample delay
+	 */
+	ddr3_get_min_max_rl_phase(dram_info, &min, &max, cs_max);
+	max_rl_phase = max;
+
+	/* DDR ODT Timing (Low) Register calculation */
+	reg = reg_read(REG_ODT_TIME_LOW_ADDR);
+	reg &= ~(0x1FF << REG_ODT_ON_CTL_RD_OFFS);
+	reg |= (((min_read_sample_delay - 1) & 0xF) << REG_ODT_ON_CTL_RD_OFFS);
+	reg |= (((max_read_sample_delay + 4 + (((max_rl_phase + 1) / 2) + 1)) &
+		 0x1F) << REG_ODT_OFF_CTL_RD_OFFS);
+	reg_write(REG_ODT_TIME_LOW_ADDR, reg);
+
+	return MV_OK;
+}
diff --git a/drivers/ddr/mvebu/ddr3_hw_training.h b/drivers/ddr/mvebu/ddr3_hw_training.h
new file mode 100644
index 0000000..cffa7c4
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_hw_training.h
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DDR3_TRAINING_H
+#define __DDR3_TRAINING_H
+
+#include "ddr3_init.h"
+
+#ifdef MV88F78X60
+#include "ddr3_axp.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375.h"
+#endif
+
+/* The following is a list of Marvell status    */
+#define MV_ERROR	(-1)
+#define MV_OK		(0x00)	/* Operation succeeded                   */
+#define MV_FAIL		(0x01)	/* Operation failed                      */
+#define MV_BAD_VALUE	(0x02)	/* Illegal value (general)               */
+#define MV_OUT_OF_RANGE	(0x03)	/* The value is out of range             */
+#define MV_BAD_PARAM	(0x04)	/* Illegal parameter in function called  */
+#define MV_BAD_PTR	(0x05)	/* Illegal pointer value                 */
+#define MV_BAD_SIZE	(0x06)	/* Illegal size                          */
+#define MV_BAD_STATE	(0x07)	/* Illegal state of state machine        */
+#define MV_SET_ERROR	(0x08)	/* Set operation failed                  */
+#define MV_GET_ERROR	(0x09)	/* Get operation failed                  */
+#define MV_CREATE_ERROR	(0x0A)	/* Fail while creating an item           */
+#define MV_NOT_FOUND	(0x0B)	/* Item not found                        */
+#define MV_NO_MORE	(0x0C)	/* No more items found                   */
+#define MV_NO_SUCH	(0x0D)	/* No such item                          */
+#define MV_TIMEOUT	(0x0E)	/* Time Out                              */
+#define MV_NO_CHANGE	(0x0F)	/* Parameter(s) is already in this value */
+#define MV_NOT_SUPPORTED (0x10)	/* This request is not support           */
+#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/
+#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized          */
+#define MV_NO_RESOURCE	(0x13)	/* Resource not available (memory ...)   */
+#define MV_FULL		(0x14)	/* Item is full (Queue or table etc...)  */
+#define MV_EMPTY	(0x15)	/* Item is empty (Queue or table etc...) */
+#define MV_INIT_ERROR	(0x16)	/* Error occured while INIT process      */
+#define MV_HW_ERROR	(0x17)	/* Hardware error                        */
+#define MV_TX_ERROR	(0x18)	/* Transmit operation not succeeded      */
+#define MV_RX_ERROR	(0x19)	/* Recieve operation not succeeded       */
+#define MV_NOT_READY	(0x1A)	/* The other side is not ready yet       */
+#define MV_ALREADY_EXIST (0x1B)	/* Tried to create existing item         */
+#define MV_OUT_OF_CPU_MEM   (0x1C) /* Cpu memory allocation failed.      */
+#define MV_NOT_STARTED	(0x1D)	/* Not started yet                       */
+#define MV_BUSY		(0x1E)	/* Item is busy.                         */
+#define MV_TERMINATE	(0x1F)	/* Item terminates it's work.            */
+#define MV_NOT_ALIGNED	(0x20)	/* Wrong alignment                       */
+#define MV_NOT_ALLOWED	(0x21)	/* Operation NOT allowed                 */
+#define MV_WRITE_PROTECT (0x22)	/* Write protected                       */
+
+#define MV_INVALID	(int)(-1)
+
+/*
+ * Debug (Enable/Disable modules) and Error report
+ */
+
+#ifdef BASIC_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS_RESULTS
+#endif
+
+#ifdef FULL_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS
+
+#define MV_DEBUG_PBS
+#define MV_DEBUG_DFS
+#define MV_DEBUG_MAIN_FULL
+#define MV_DEBUG_DFS_FULL
+#define MV_DEBUG_DQS_FULL
+#define MV_DEBUG_RL_FULL
+#define MV_DEBUG_WL_FULL
+#endif
+
+/*
+ * General Consts
+ */
+
+#define SDRAM_READ_WRITE_LEN_IN_WORDS           16
+#define SDRAM_READ_WRITE_LEN_IN_DOUBLE_WORDS    8
+#define CACHE_LINE_SIZE                         0x20
+
+#define SDRAM_CS_BASE                           0x0
+
+#define SRAM_BASE                               0x40000000
+#define SRAM_SIZE                               0xFFF
+
+#define LEN_64BIT_STD_PATTERN                   16
+#define LEN_64BIT_KILLER_PATTERN                128
+#define LEN_64BIT_SPECIAL_PATTERN               128
+#define LEN_64BIT_PBS_PATTERN                   16
+#define LEN_WL_SUP_PATTERN		                32
+
+#define LEN_16BIT_STD_PATTERN                   4
+#define LEN_16BIT_KILLER_PATTERN                128
+#define LEN_16BIT_SPECIAL_PATTERN               128
+#define LEN_16BIT_PBS_PATTERN                   4
+
+#define CMP_BYTE_SHIFT                          8
+#define CMP_BYTE_MASK                           0xFF
+#define PUP_SIZE                                8
+
+#define S 0
+#define C 1
+#define P 2
+#define D 3
+#define DQS 6
+#define PS 2
+#define DS 3
+#define PE 4
+#define DE 5
+
+#define CS0                                     0
+#define MAX_DIMM_NUM                            2
+#define MAX_DELAY                               0x1F
+
+/*
+ * Invertion limit and phase1 limit are WA for the RL @ 1:1 design bug -
+ * Armada 370 & AXP Z1
+ */
+#define MAX_DELAY_INV_LIMIT                     0x5
+#define MIN_DELAY_PHASE_1_LIMIT                 0x10
+
+#define MAX_DELAY_INV                           (0x3F - MAX_DELAY_INV_LIMIT)
+#define MIN_DELAY                               0
+#define MAX_PUP_NUM                             9
+#define ECC_PUP                                 8
+#define DQ_NUM                                  8
+#define DQS_DQ_NUM                              8
+#define INIT_WL_DELAY                           13
+#define INIT_RL_DELAY                           15
+#define TWLMRD_DELAY                            20
+#define TCLK_3_DELAY                            3
+#define ECC_BIT                                 8
+#define DMA_SIZE                                64
+#define MV_DMA_0                                0
+#define MAX_TRAINING_RETRY                      10
+
+#define PUP_RL_MODE                             0x2
+#define PUP_WL_MODE                             0
+#define PUP_PBS_TX                              0x10
+#define PUP_PBS_TX_DM                           0x1A
+#define PUP_PBS_RX                              0x30
+#define PUP_DQS_WR                              0x1
+#define PUP_DQS_RD                              0x3
+#define PUP_BC                                  10
+#define PUP_DELAY_MASK                          0x1F
+#define PUP_PHASE_MASK                          0x7
+#define PUP_NUM_64BIT                           8
+#define PUP_NUM_32BIT                           4
+#define PUP_NUM_16BIT                           2
+
+/* control PHY registers */
+#define CNTRL_PUP_DESKEW                        0x10
+
+/* WL */
+#define COUNT_WL_HI_FREQ                        2
+#define COUNT_WL                                2
+#define COUNT_WL_RFRS                           9
+#define WL_HI_FREQ_SHIFT                        2
+#define WL_HI_FREQ_STATE                        1
+#define COUNT_HW_WL                             2
+
+/* RL */
+/*
+ * RL_MODE - this define uses the RL mode SW RL instead of the functional
+ * window SW RL
+ */
+#define RL_MODE
+#define RL_WINDOW_WA
+#define MAX_PHASE_1TO1                          2
+#define MAX_PHASE_2TO1                          4
+
+#define MAX_PHASE_RL_UL_1TO1                    0
+#define MAX_PHASE_RL_L_1TO1                     4
+#define MAX_PHASE_RL_UL_2TO1                    3
+#define MAX_PHASE_RL_L_2TO1                     7
+
+#define RL_UNLOCK_STATE                         0
+#define RL_WINDOW_STATE                         1
+#define RL_FINAL_STATE                          2
+#define RL_RETRY_COUNT                          2
+#define COUNT_HW_RL                             2
+
+/* PBS */
+#define MAX_PBS                                 31
+#define MIN_PBS                                 0
+#define COUNT_PBS_PATTERN                       2
+#define COUNT_PBS_STARTOVER                     2
+#define COUNT_PBS_REPEAT                        3
+#define COUNT_PBS_COMP_RETRY_NUM                2
+#define PBS_DIFF_LIMIT                          31
+#define PATTERN_PBS_TX_A                        0x55555555
+#define PATTERN_PBS_TX_B                        0xAAAAAAAA
+
+/* DQS */
+#define ADLL_ERROR                              0x55
+#define ADLL_MAX                                31
+#define ADLL_MIN                                0
+#define MIN_WIN_SIZE                            4
+#define VALID_WIN_THRS                          MIN_WIN_SIZE
+
+#define MODE_2TO1                               1
+#define MODE_1TO1                               0
+
+/*
+ * Macros
+ */
+#define IS_PUP_ACTIVE(_data_, _pup_)        (((_data_) >> (_pup_)) & 0x1)
+
+/*
+ * Internal ERROR codes
+ */
+#define MV_DDR3_TRAINING_ERR_WR_LVL_HW              0xDD302001
+#define MV_DDR3_TRAINING_ERR_LOAD_PATTERNS          0xDD302002
+#define MV_DDR3_TRAINING_ERR_WR_LVL_HI_FREQ         0xDD302003
+#define MV_DDR3_TRAINING_ERR_DFS_H2L                0xDD302004
+#define MV_DDR3_TRAINING_ERR_DRAM_COMPARE           0xDD302005
+#define MV_DDR3_TRAINING_ERR_WIN_LIMITS             0xDD302006
+#define MV_DDR3_TRAINING_ERR_PUP_RANGE              0xDD302025
+#define MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH   0xDD302007
+#define MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH  0xDD302008
+#define MV_DDR3_TRAINING_ERR_DQS_PATTERN            0xDD302009
+#define MV_DDR3_TRAINING_ERR_PBS_ADLL_SHR_1PHASE    0xDD302010
+#define MV_DDR3_TRAINING_ERR_PBS_TX_MAX_VAL         0xDD302011
+#define MV_DDR3_TRAINING_ERR_PBS_RX_PER_BIT         0xDD302012
+#define MV_DDR3_TRAINING_ERR_PBS_TX_PER_BIT         0xDD302013
+#define MV_DDR3_TRAINING_ERR_PBS_RX_MAX_VAL         0xDD302014
+#define MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP 0xDD302015
+#define MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_MAX_VAL  0xDD302016
+#define MV_DDR3_TRAINING_ERR_RD_LVL_RL_PATTERN      0xDD302017
+#define MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK   0xDD302018
+#define MV_DDR3_TRAINING_ERR_RD_LVL_PUP_UNLOCK      0xDD302019
+#define MV_DDR3_TRAINING_ERR_WR_LVL_SW              0xDD302020
+#define MV_DDR3_TRAINING_ERR_PRBS_RX                0xDD302021
+#define MV_DDR3_TRAINING_ERR_DQS_RX                 0xDD302022
+#define MV_DDR3_TRAINING_ERR_PRBS_TX                0xDD302023
+#define MV_DDR3_TRAINING_ERR_DQS_TX                 0xDD302024
+
+/*
+ * DRAM information structure
+ */
+typedef struct dram_info {
+	u32 num_cs;
+	u32 cs_ena;
+	u32 num_of_std_pups;	/* Q value = ddrWidth/8 - Without ECC!! */
+	u32 num_of_total_pups;	/* numOfStdPups + eccEna */
+	u32 target_frequency;	/* DDR Frequency */
+	u32 ddr_width;		/* 32/64 Bit or 16/32 Bit */
+	u32 ecc_ena;		/* 0/1 */
+	u32 wl_val[MAX_CS][MAX_PUP_NUM][7];
+	u32 rl_val[MAX_CS][MAX_PUP_NUM][7];
+	u32 rl_max_phase;
+	u32 rl_min_phase;
+	u32 wl_max_phase;
+	u32 wl_min_phase;
+	u32 rd_smpl_dly;
+	u32 rd_rdy_dly;
+	u32 cl;
+	u32 cwl;
+	u32 mode_2t;
+	int rl400_bug;
+	int multi_cs_mr_support;
+	int reg_dimm;
+} MV_DRAM_INFO;
+
+enum training_modes  {
+	DQS_WR_MODE,
+	WL_MODE_,
+	RL_MODE_,
+	DQS_RD_MODE,
+	PBS_TX_DM_MODE,
+	PBS_TX_MODE,
+	PBS_RX_MODE,
+	MAX_TRAINING_MODE,
+};
+
+typedef struct dram_training_init {
+	u32 reg_addr;
+	u32 reg_value;
+} MV_DRAM_TRAINING_INIT;
+
+typedef struct dram_mv_init {
+	u32 reg_addr;
+	u32 reg_value;
+} MV_DRAM_MC_INIT;
+
+/* Board/Soc revisions define */
+enum board_rev {
+	Z1,
+	Z1_PCAC,
+	Z1_RD_SLED,
+	A0,
+	A0_AMC
+};
+
+typedef struct dram_modes {
+	char *mode_name;
+	u8 cpu_freq;
+	u8 fab_freq;
+	u8 chip_id;
+	int chip_board_rev;
+	MV_DRAM_MC_INIT *regs;
+	MV_DRAM_TRAINING_INIT *vals;
+} MV_DRAM_MODES;
+
+/*
+ * Function Declarations
+ */
+
+u32 cache_inv(u32 addr);
+void flush_l1_v7(u32 line);
+void flush_l1_v6(u32 line);
+
+u32 ddr3_cl_to_valid_cl(u32 cl);
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl);
+
+void ddr3_write_pup_reg(u32 mode, u32 cs, u32 pup, u32 phase, u32 delay);
+u32 ddr3_read_pup_reg(u32 mode, u32 cs, u32 pup);
+
+int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked, int is_tx,
+			   u32 pbs_pattern_idx, u32 pbs_curr_val,
+			   u32 pbs_lock_val, u32 *skew_array,
+			   u8 *unlock_pup_dq_array, u32 ecc);
+
+int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			   u32 *new_locked_pup, u32 *pattern,
+			   u32 pattern_len, u32 sdram_offset, int write,
+			   int mask, u32 *mask_pattern, int b_special_compare);
+
+int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+		       u32 *new_locked_pup, u32 *pattern, u32 pattern_len,
+		       u32 sdram_offset, int write, int mask,
+		       u32 *mask_pattern, int b_special_compare);
+
+int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			      u32 *new_locked_pup, u32 *pattern,
+			      u32 pattern_len, u32 sdram_offset, int write,
+			      int mask, u32 *mask_pattern);
+
+int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			  u32 *new_locked_pup, u32 *pattern,
+			  u32 sdram_offset);
+int ddr3_dram_sram_read(u32 src, u32 dst, u32 len);
+int ddr3_load_patterns(MV_DRAM_INFO *dram_info, int resume);
+
+int ddr3_read_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_read_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+
+int ddr3_write_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_write_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+int ddr3_write_leveling_hw_reg_dimm(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_wl_supplement(MV_DRAM_INFO *dram_info);
+
+int ddr3_dfs_high_2_low(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_dfs_low_2_high(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+
+int ddr3_pbs_tx(MV_DRAM_INFO *dram_info);
+int ddr3_pbs_rx(MV_DRAM_INFO *dram_info);
+int ddr3_load_pbs_patterns(MV_DRAM_INFO *dram_info);
+
+int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info);
+int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info);
+int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info);
+
+void ddr3_static_training_init(void);
+
+u8 ddr3_get_eprom_fabric(void);
+void ddr3_set_performance_params(MV_DRAM_INFO *dram_info);
+int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len);
+void ddr3_save_training(MV_DRAM_INFO *dram_info);
+int ddr3_read_training_results(void);
+int ddr3_training_suspend_resume(MV_DRAM_INFO *dram_info);
+int ddr3_get_min_max_read_sample_delay(u32 cs_enable, u32 reg, u32 *min,
+				       u32 *max, u32 *cs_max);
+int ddr3_get_min_max_rl_phase(MV_DRAM_INFO *dram_info, u32 *min, u32 *max,
+			      u32 cs);
+int ddr3_odt_activate(int activate);
+int ddr3_odt_read_dynamic_config(MV_DRAM_INFO *dram_info);
+void ddr3_print_freq(u32 freq);
+void ddr3_reset_phy_read_fifo(void);
+
+#endif /* __DDR3_TRAINING_H */
diff --git a/drivers/ddr/mvebu/ddr3_init.c b/drivers/ddr/mvebu/ddr3_init.c
new file mode 100644
index 0000000..11b8591
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_init.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+
+#if defined(MV88F78X60)
+#include "ddr3_axp_vars.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370_vars.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375_vars.h"
+#endif
+
+#ifdef STATIC_TRAINING
+static void ddr3_static_training_init(void);
+#endif
+#ifdef DUNIT_STATIC
+static void ddr3_static_mc_init(void);
+#endif
+#if defined(DUNIT_STATIC) || defined(STATIC_TRAINING)
+MV_DRAM_MODES *ddr3_get_static_ddr_mode(void);
+#endif
+#if defined(MV88F672X)
+void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps);
+#endif
+u32 mv_board_id_get(void);
+extern void ddr3_set_sw_wl_rl_debug(u32);
+extern void ddr3_set_pbs(u32);
+extern void ddr3_set_log_level(u32 val);
+
+static u32 log_level = DDR3_LOG_LEVEL;
+
+static u32 ddr3_init_main(void);
+
+/*
+ * Name:     ddr3_set_log_level
+ * Desc:     This routine initialize the log_level acording to nLogLevel
+ *           which getting from user
+ * Args:     nLogLevel
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_set_log_level(u32 val)
+{
+	log_level = val;
+}
+
+/*
+ * Name:     ddr3_get_log_level
+ * Desc:     This routine returns the log level
+ * Args:     none
+ * Notes:
+ * Returns:  log level.
+ */
+u32 ddr3_get_log_level(void)
+{
+	return log_level;
+}
+
+static void debug_print_reg(u32 reg)
+{
+	printf("0x%08x = 0x%08x\n", reg, reg_read(reg));
+}
+
+static void print_dunit_setup(void)
+{
+	puts("\n########### LOG LEVEL 1 (D-UNIT SETUP)###########\n");
+
+#ifdef DUNIT_STATIC
+	puts("\nStatic D-UNIT Setup:\n");
+#endif
+#ifdef DUNIT_SPD
+	puts("\nDynamic(using SPD) D-UNIT Setup:\n");
+#endif
+	debug_print_reg(REG_SDRAM_CONFIG_ADDR);
+	debug_print_reg(REG_DUNIT_CTRL_LOW_ADDR);
+	debug_print_reg(REG_SDRAM_TIMING_LOW_ADDR);
+	debug_print_reg(REG_SDRAM_TIMING_HIGH_ADDR);
+	debug_print_reg(REG_SDRAM_ADDRESS_CTRL_ADDR);
+	debug_print_reg(REG_SDRAM_OPEN_PAGES_ADDR);
+	debug_print_reg(REG_SDRAM_OPERATION_ADDR);
+	debug_print_reg(REG_SDRAM_MODE_ADDR);
+	debug_print_reg(REG_SDRAM_EXT_MODE_ADDR);
+	debug_print_reg(REG_DDR_CONT_HIGH_ADDR);
+	debug_print_reg(REG_ODT_TIME_LOW_ADDR);
+	debug_print_reg(REG_SDRAM_ERROR_ADDR);
+	debug_print_reg(REG_SDRAM_AUTO_PWR_SAVE_ADDR);
+	debug_print_reg(REG_OUDDR3_TIMING_ADDR);
+	debug_print_reg(REG_ODT_TIME_HIGH_ADDR);
+	debug_print_reg(REG_SDRAM_ODT_CTRL_LOW_ADDR);
+	debug_print_reg(REG_SDRAM_ODT_CTRL_HIGH_ADDR);
+	debug_print_reg(REG_DUNIT_ODT_CTRL_ADDR);
+#ifndef MV88F67XX
+	debug_print_reg(REG_DRAM_FIFO_CTRL_ADDR);
+	debug_print_reg(REG_DRAM_AXI_CTRL_ADDR);
+	debug_print_reg(REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR);
+	debug_print_reg(REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR);
+	debug_print_reg(REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR);
+	debug_print_reg(REG_DRAM_MAIN_PADS_CAL_ADDR);
+	debug_print_reg(REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR);
+	debug_print_reg(REG_CS_SIZE_SCRATCH_ADDR);
+	debug_print_reg(REG_DYNAMIC_POWER_SAVE_ADDR);
+	debug_print_reg(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+	debug_print_reg(REG_READ_DATA_READY_DELAYS_ADDR);
+	debug_print_reg(REG_DDR3_MR0_ADDR);
+	debug_print_reg(REG_DDR3_MR1_ADDR);
+	debug_print_reg(REG_DDR3_MR2_ADDR);
+	debug_print_reg(REG_DDR3_MR3_ADDR);
+	debug_print_reg(REG_DDR3_RANK_CTRL_ADDR);
+	debug_print_reg(REG_DRAM_PHY_CONFIG_ADDR);
+	debug_print_reg(REG_STATIC_DRAM_DLB_CONTROL);
+	debug_print_reg(DLB_BUS_OPTIMIZATION_WEIGHTS_REG);
+	debug_print_reg(DLB_AGING_REGISTER);
+	debug_print_reg(DLB_EVICTION_CONTROL_REG);
+	debug_print_reg(DLB_EVICTION_TIMERS_REGISTER_REG);
+#if defined(MV88F672X)
+	debug_print_reg(REG_FASTPATH_WIN_CTRL_ADDR(0));
+	debug_print_reg(REG_FASTPATH_WIN_BASE_ADDR(0));
+	debug_print_reg(REG_FASTPATH_WIN_CTRL_ADDR(1));
+	debug_print_reg(REG_FASTPATH_WIN_BASE_ADDR(1));
+#else
+	debug_print_reg(REG_FASTPATH_WIN_0_CTRL_ADDR);
+#endif
+	debug_print_reg(REG_CDI_CONFIG_ADDR);
+#endif
+}
+
+#if !defined(STATIC_TRAINING)
+static void ddr3_restore_and_set_final_windows(u32 *win_backup)
+{
+	u32 ui, reg, cs;
+	u32 win_ctrl_reg, num_of_win_regs;
+	u32 cs_ena = ddr3_get_cs_ena_from_reg();
+
+#if defined(MV88F672X)
+	if (DDR3_FAST_PATH_EN == 0)
+		return;
+#endif
+
+#if defined(MV88F672X)
+	win_ctrl_reg = REG_XBAR_WIN_16_CTRL_ADDR;
+	num_of_win_regs = 8;
+#else
+	win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+	num_of_win_regs = 16;
+#endif
+
+	/* Return XBAR windows 4-7 or 16-19 init configuration */
+	for (ui = 0; ui < num_of_win_regs; ui++)
+		reg_write((win_ctrl_reg + 0x4 * ui), win_backup[ui]);
+
+	DEBUG_INIT_FULL_S("DDR3 Training Sequence - Switching XBAR Window to FastPath Window\n");
+
+#if defined(MV88F672X)
+	/* Set L2 filtering to 1G */
+	reg_write(0x8c04, 0x40000000);
+
+	/* Open fast path windows */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			/* set fast path window control for the cs */
+			reg = 0x1FFFFFE1;
+			reg |= (cs << 2);
+			reg |= (SDRAM_CS_SIZE & 0xFFFF0000);
+			/* Open fast path Window */
+			reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg);
+			/* set fast path window base address for the cs */
+			reg = (((SDRAM_CS_SIZE + 1) * cs) & 0xFFFF0000);
+			/* Set base address */
+			reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg);
+		}
+	}
+#else
+	reg = 0x1FFFFFE1;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg |= (cs << 2);
+			break;
+		}
+	}
+
+	/* Open fast path Window to - 0.5G */
+	reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, reg);
+#endif
+}
+
+static void ddr3_save_and_set_training_windows(u32 *win_backup)
+{
+	u32 cs_ena = ddr3_get_cs_ena_from_reg();
+	u32 reg, tmp_count, cs, ui;
+	u32 win_ctrl_reg, win_base_reg, win_remap_reg;
+	u32 num_of_win_regs, win_jump_index;
+
+#if defined(MV88F672X)
+	/* Disable L2 filtering */
+	reg_write(0x8c04, 0);
+
+	win_ctrl_reg = REG_XBAR_WIN_16_CTRL_ADDR;
+	win_base_reg = REG_XBAR_WIN_16_BASE_ADDR;
+	win_remap_reg = REG_XBAR_WIN_16_REMAP_ADDR;
+	win_jump_index = 0x8;
+	num_of_win_regs = 8;
+#else
+	win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+	win_base_reg = REG_XBAR_WIN_4_BASE_ADDR;
+	win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR;
+	win_jump_index = 0x10;
+	num_of_win_regs = 16;
+#endif
+
+	/* Close XBAR Window 19 - Not needed */
+	/* {0x000200e8}  -   Open Mbus Window - 2G */
+	reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0);
+
+	/* Save XBAR Windows 4-19 init configurations */
+	for (ui = 0; ui < num_of_win_regs; ui++)
+		win_backup[ui] = reg_read(win_ctrl_reg + 0x4 * ui);
+
+	/* Open XBAR Windows 4-7 or 16-19 for other CS */
+	reg = 0;
+	tmp_count = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			switch (cs) {
+			case 0:
+				reg = 0x0E00;
+				break;
+			case 1:
+				reg = 0x0D00;
+				break;
+			case 2:
+				reg = 0x0B00;
+				break;
+			case 3:
+				reg = 0x0700;
+				break;
+			}
+			reg |= (1 << 0);
+			reg |= (SDRAM_CS_SIZE & 0xFFFF0000);
+
+			reg_write(win_ctrl_reg + win_jump_index * tmp_count,
+				  reg);
+			reg = ((SDRAM_CS_SIZE + 1) * (tmp_count)) & 0xFFFF0000;
+			reg_write(win_base_reg + win_jump_index * tmp_count,
+				  reg);
+
+			if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) {
+				reg_write(win_remap_reg +
+					  win_jump_index * tmp_count, 0);
+			}
+
+			tmp_count++;
+		}
+	}
+}
+#endif /*  !defined(STATIC_TRAINING) */
+
+/*
+ * Name:     ddr3_init - Main DDR3 Init function
+ * Desc:     This routine initialize the DDR3 MC and runs HW training.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+int ddr3_init(void)
+{
+	unsigned int status;
+
+	ddr3_set_pbs(DDR3_PBS);
+	ddr3_set_sw_wl_rl_debug(DDR3_RUN_SW_WHEN_HW_FAIL);
+
+	status = ddr3_init_main();
+	if (status == MV_DDR3_TRAINING_ERR_BAD_SAR)
+		DEBUG_INIT_S("DDR3 Training Error: Bad sample at reset");
+	if (status == MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP)
+		DEBUG_INIT_S("DDR3 Training Error: Bad DIMM setup");
+	if (status == MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT)
+		DEBUG_INIT_S("DDR3 Training Error: Max CS limit");
+	if (status == MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT)
+		DEBUG_INIT_S("DDR3 Training Error: Max enable CS limit");
+	if (status == MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP)
+		DEBUG_INIT_S("DDR3 Training Error: Bad R-DIMM setup");
+	if (status == MV_DDR3_TRAINING_ERR_TWSI_FAIL)
+		DEBUG_INIT_S("DDR3 Training Error: TWSI failure");
+	if (status == MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH)
+		DEBUG_INIT_S("DDR3 Training Error: DIMM type no match");
+	if (status == MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE)
+		DEBUG_INIT_S("DDR3 Training Error: TWSI bad type");
+	if (status == MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH)
+		DEBUG_INIT_S("DDR3 Training Error: bus width no match");
+	if (status > MV_DDR3_TRAINING_ERR_HW_FAIL_BASE)
+		DEBUG_INIT_C("DDR3 Training Error: HW Failure 0x", status, 8);
+
+	return status;
+}
+
+static void print_ddr_target_freq(u32 cpu_freq, u32 fab_opt)
+{
+	puts("\nDDR3 Training Sequence - Run DDR3 at ");
+
+	switch (cpu_freq) {
+#if defined(MV88F672X)
+	case 21:
+		puts("533 Mhz\n");
+		break;
+#else
+	case 1:
+		puts("533 Mhz\n");
+		break;
+	case 2:
+		if (fab_opt == 5)
+			puts("600 Mhz\n");
+		if (fab_opt == 9)
+			puts("400 Mhz\n");
+		break;
+	case 3:
+		puts("667 Mhz\n");
+		break;
+	case 4:
+		if (fab_opt == 5)
+			puts("750 Mhz\n");
+		if (fab_opt == 9)
+			puts("500 Mhz\n");
+		break;
+	case 0xa:
+		puts("400 Mhz\n");
+		break;
+	case 0xb:
+		if (fab_opt == 5)
+			puts("800 Mhz\n");
+		if (fab_opt == 9)
+			puts("553 Mhz\n");
+		if (fab_opt == 0xA)
+			puts("640 Mhz\n");
+		break;
+#endif
+	default:
+		puts("NOT DEFINED FREQ\n");
+	}
+}
+
+static u32 ddr3_init_main(void)
+{
+	u32 target_freq;
+	u32 reg = 0;
+	u32 cpu_freq, fab_opt, hclk_time_ps, soc_num;
+	__maybe_unused u32 ecc = DRAM_ECC;
+	__maybe_unused int dqs_clk_aligned = 0;
+	__maybe_unused u32 scrub_offs, scrub_size;
+	__maybe_unused u32 ddr_width = BUS_WIDTH;
+	__maybe_unused int status;
+	__maybe_unused u32 win_backup[16];
+
+	/* SoC/Board special Initializtions */
+	fab_opt = ddr3_get_fab_opt();
+
+#ifdef CONFIG_SPD_EEPROM
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
+
+	ddr3_print_version();
+	DEBUG_INIT_S("4\n");
+	/* Lib version 5.5.4 */
+
+	fab_opt = ddr3_get_fab_opt();
+
+	/* Switching CPU to MRVL ID */
+	soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >>
+		SAR1_CPU_CORE_OFFSET;
+	switch (soc_num) {
+	case 0x3:
+		reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
+		reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
+	case 0x1:
+		reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
+	case 0x0:
+		reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET);
+	default:
+		break;
+	}
+
+	/* Power down deskew PLL */
+#if !defined(MV88F672X)
+	/* 0x18780 [25] */
+	reg = (reg_read(REG_DDRPHY_APLL_CTRL_ADDR) & ~(1 << 25));
+	reg_write(REG_DDRPHY_APLL_CTRL_ADDR, reg);
+#endif
+
+	/*
+	 * Stage 0 - Set board configuration
+	 */
+	cpu_freq = ddr3_get_cpu_freq();
+	if (fab_opt > FAB_OPT)
+		fab_opt = FAB_OPT - 1;
+
+	if (ddr3_get_log_level() > 0)
+		print_ddr_target_freq(cpu_freq, fab_opt);
+
+#if defined(MV88F672X)
+	get_target_freq(cpu_freq, &target_freq, &hclk_time_ps);
+#else
+	target_freq = cpu_ddr_ratios[fab_opt][cpu_freq];
+	hclk_time_ps = cpu_fab_clk_to_hclk[fab_opt][cpu_freq];
+#endif
+	if ((target_freq == 0) || (hclk_time_ps == 0)) {
+		DEBUG_INIT_S("DDR3 Training Sequence - FAILED - Wrong Sample at Reset Configurations\n");
+		if (target_freq == 0) {
+			DEBUG_INIT_C("target_freq", target_freq, 2);
+			DEBUG_INIT_C("fab_opt", fab_opt, 2);
+			DEBUG_INIT_C("cpu_freq", cpu_freq, 2);
+		} else if (hclk_time_ps == 0) {
+			DEBUG_INIT_C("hclk_time_ps", hclk_time_ps, 2);
+			DEBUG_INIT_C("fab_opt", fab_opt, 2);
+			DEBUG_INIT_C("cpu_freq", cpu_freq, 2);
+		}
+
+		return MV_DDR3_TRAINING_ERR_BAD_SAR;
+	}
+
+#if defined(ECC_SUPPORT)
+	scrub_offs = U_BOOT_START_ADDR;
+	scrub_size = U_BOOT_SCRUB_SIZE;
+#else
+	scrub_offs = 0;
+	scrub_size = 0;
+#endif
+
+#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
+	ecc = DRAM_ECC;
+#endif
+
+#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
+	ecc = 0;
+	if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_ECC))
+		ecc = 1;
+#endif
+
+#ifdef DQS_CLK_ALIGNED
+	dqs_clk_aligned = 1;
+#endif
+
+	/* Check if DRAM is already initialized  */
+	if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
+	    (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
+		DEBUG_INIT_S("DDR3 Training Sequence - 2nd boot - Skip\n");
+		return MV_OK;
+	}
+
+	/*
+	 * Stage 1 - Dunit Setup
+	 */
+
+#ifdef DUNIT_STATIC
+	/*
+	 * For Static D-Unit Setup use must set the correct static values
+	 * at the ddr3_*soc*_vars.h file
+	 */
+	DEBUG_INIT_FULL_S("DDR3 Training Sequence - Static MC Init\n");
+	ddr3_static_mc_init();
+
+#ifdef ECC_SUPPORT
+	ecc = DRAM_ECC;
+	if (ecc) {
+		reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+		reg |= (1 << REG_SDRAM_CONFIG_ECC_OFFS);
+		reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+	}
+#endif
+#endif
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+#if defined(AUTO_DETECTION_SUPPORT)
+	/*
+	 * Configurations for both static and dynamic MC setups
+	 *
+	 * Dynamically Set 32Bit and ECC for AXP (Relevant only for
+	 * Marvell DB boards)
+	 */
+	if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_BUS_WIDTH)) {
+		ddr_width = 32;
+		DEBUG_INIT_S("DDR3 Training Sequence - DRAM bus width 32Bit\n");
+	}
+#endif
+
+#if defined(MV88F672X)
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+	if ((reg >> 15) & 1)
+		ddr_width = 32;
+	else
+		ddr_width = 16;
+#endif
+#endif
+
+#ifdef DUNIT_SPD
+	status = ddr3_dunit_setup(ecc, hclk_time_ps, &ddr_width);
+	if (MV_OK != status) {
+		DEBUG_INIT_S("DDR3 Training Sequence - FAILED (ddr3 Dunit Setup)\n");
+		return status;
+	}
+#endif
+
+	/* Fix read ready phases for all SOC in reg 0x15C8 */
+	reg = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+	reg &= ~(REG_TRAINING_DEBUG_3_MASK);
+	reg |= 0x4;		/* Phase 0 */
+	reg &= ~(REG_TRAINING_DEBUG_3_MASK << REG_TRAINING_DEBUG_3_OFFS);
+	reg |= (0x4 << (1 * REG_TRAINING_DEBUG_3_OFFS));	/* Phase 1 */
+	reg &= ~(REG_TRAINING_DEBUG_3_MASK << (3 * REG_TRAINING_DEBUG_3_OFFS));
+	reg |= (0x6 << (3 * REG_TRAINING_DEBUG_3_OFFS));	/* Phase 3 */
+	reg &= ~(REG_TRAINING_DEBUG_3_MASK << (4 * REG_TRAINING_DEBUG_3_OFFS));
+	reg |= (0x6 << (4 * REG_TRAINING_DEBUG_3_OFFS));
+	reg &= ~(REG_TRAINING_DEBUG_3_MASK << (5 * REG_TRAINING_DEBUG_3_OFFS));
+	reg |= (0x6 << (5 * REG_TRAINING_DEBUG_3_OFFS));
+	reg_write(REG_TRAINING_DEBUG_3_ADDR, reg);
+
+#if defined(MV88F672X)
+	/*
+	 * AxiBrespMode[8] = Compliant,
+	 * AxiAddrDecodeCntrl[11] = Internal,
+	 * AxiDataBusWidth[0] = 128bit
+	 */
+	/* 0x14A8 - AXI Control Register */
+	reg_write(REG_DRAM_AXI_CTRL_ADDR, 0);
+#else
+	/* 0x14A8 - AXI Control Register */
+	reg_write(REG_DRAM_AXI_CTRL_ADDR, 0x00000100);
+	reg_write(REG_CDI_CONFIG_ADDR, 0x00000006);
+
+	if ((ddr_width == 64) && (reg_read(REG_DDR_IO_ADDR) &
+				  (1 << REG_DDR_IO_CLK_RATIO_OFFS))) {
+		/* 0x14A8 - AXI Control Register */
+		reg_write(REG_DRAM_AXI_CTRL_ADDR, 0x00000101);
+		reg_write(REG_CDI_CONFIG_ADDR, 0x00000007);
+	}
+#endif
+
+#if !defined(MV88F67XX)
+	/*
+	 * ARMADA-370 activate DLB later at the u-boot,
+	 * Armada38x - No DLB activation at this time
+	 */
+	reg_write(DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x18C01E);
+
+#if defined(MV88F78X60)
+	/* WA according to eratta GL-8672902*/
+	if (mv_ctrl_rev_get() == MV_78XX0_B0_REV)
+		reg_write(DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0xc19e);
+#endif
+
+	reg_write(DLB_AGING_REGISTER, 0x0f7f007f);
+	reg_write(DLB_EVICTION_CONTROL_REG, 0x0);
+	reg_write(DLB_EVICTION_TIMERS_REGISTER_REG, 0x00FF3C1F);
+
+	reg_write(MBUS_UNITS_PRIORITY_CONTROL_REG, 0x55555555);
+	reg_write(FABRIC_UNITS_PRIORITY_CONTROL_REG, 0xAA);
+	reg_write(MBUS_UNITS_PREFETCH_CONTROL_REG, 0xffff);
+	reg_write(FABRIC_UNITS_PREFETCH_CONTROL_REG, 0xf0f);
+
+#if defined(MV88F78X60)
+	/* WA according to eratta GL-8672902 */
+	if (mv_ctrl_rev_get() == MV_78XX0_B0_REV) {
+		reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL);
+		reg |= DLB_ENABLE;
+		reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg);
+	}
+#endif /* end defined(MV88F78X60) */
+#endif /* end !defined(MV88F67XX) */
+
+	if (ddr3_get_log_level() >= MV_LOG_LEVEL_1)
+		print_dunit_setup();
+
+	/*
+	 * Stage 2 - Training Values Setup
+	 */
+#ifdef STATIC_TRAINING
+	/*
+	 * DRAM Init - After all the D-unit values are set, its time to init
+	 * the D-unit
+	 */
+	/* Wait for '0' */
+	reg_write(REG_SDRAM_INIT_CTRL_ADDR, 0x1);
+	do {
+		reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+			(1 << REG_SDRAM_INIT_CTRL_OFFS);
+	} while (reg);
+
+	/* ddr3 init using static parameters - HW training is disabled */
+	DEBUG_INIT_FULL_S("DDR3 Training Sequence - Static Training Parameters\n");
+	ddr3_static_training_init();
+
+#if defined(MV88F78X60)
+	/*
+	 * If ECC is enabled, need to scrub the U-Boot area memory region -
+	 * Run training function with Xor bypass just to scrub the memory
+	 */
+	status = ddr3_hw_training(target_freq, ddr_width,
+				  1, scrub_offs, scrub_size,
+				  dqs_clk_aligned, DDR3_TRAINING_DEBUG,
+				  REG_DIMM_SKIP_WL);
+	if (MV_OK != status) {
+		DEBUG_INIT_FULL_S("DDR3 Training Sequence - FAILED\n");
+		return status;
+	}
+#endif
+#else
+	/* Set X-BAR windows for the training sequence */
+	ddr3_save_and_set_training_windows(win_backup);
+
+	/* Run DDR3 Training Sequence */
+	/* DRAM Init */
+	reg_write(REG_SDRAM_INIT_CTRL_ADDR, 0x1);
+	do {
+		reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+			(1 << REG_SDRAM_INIT_CTRL_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	/* ddr3 init using DDR3 HW training procedure */
+	DEBUG_INIT_FULL_S("DDR3 Training Sequence - HW Training Procedure\n");
+	status = ddr3_hw_training(target_freq, ddr_width,
+				  0, scrub_offs, scrub_size,
+				  dqs_clk_aligned, DDR3_TRAINING_DEBUG,
+				  REG_DIMM_SKIP_WL);
+	if (MV_OK != status) {
+		DEBUG_INIT_FULL_S("DDR3 Training Sequence - FAILED\n");
+		return status;
+	}
+#endif
+
+	/*
+	 * Stage 3 - Finish
+	 */
+#if defined(MV88F78X60) || defined(MV88F672X)
+	/* Disable ECC Ignore bit */
+	reg = reg_read(REG_SDRAM_CONFIG_ADDR) &
+		~(1 << REG_SDRAM_CONFIG_IERR_OFFS);
+	reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+#endif
+
+#if !defined(STATIC_TRAINING)
+	/* Restore and set windows */
+	ddr3_restore_and_set_final_windows(win_backup);
+#endif
+
+	/* Update DRAM init indication in bootROM register */
+	reg = reg_read(REG_BOOTROM_ROUTINE_ADDR);
+	reg_write(REG_BOOTROM_ROUTINE_ADDR,
+		  reg | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS));
+
+#if !defined(MV88F67XX)
+#if defined(MV88F78X60)
+	if (mv_ctrl_rev_get() == MV_78XX0_B0_REV) {
+		reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+		if (ecc == 0)
+			reg_write(REG_SDRAM_CONFIG_ADDR, reg | (1 << 19));
+	}
+#endif /* end defined(MV88F78X60) */
+
+	reg_write(DLB_EVICTION_CONTROL_REG, 0x9);
+
+	reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL);
+	reg |= (DLB_ENABLE | DLB_WRITE_COALESING | DLB_AXI_PREFETCH_EN |
+		DLB_MBUS_PREFETCH_EN | PREFETCH_NLNSZTR);
+	reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg);
+#endif /* end !defined(MV88F67XX) */
+
+#ifdef STATIC_TRAINING
+	DEBUG_INIT_S("DDR3 Training Sequence - Ended Successfully (S)\n");
+#else
+	DEBUG_INIT_S("DDR3 Training Sequence - Ended Successfully\n");
+#endif
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_get_cpu_freq
+ * Desc:     read S@R and return CPU frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+
+u32 ddr3_get_cpu_freq(void)
+{
+	u32 reg, cpu_freq;
+
+#if defined(MV88F672X)
+	/* Read sample at reset setting */
+	reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);	/* 0xE8200 */
+	cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+		REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+#else
+	/* Read sample at reset setting */
+	reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR);	/* 0x18230 [23:21] */
+#if defined(MV88F78X60)
+	cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+		REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+	reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);	/* 0x18234 [20] */
+	cpu_freq |= (((reg >> REG_SAMPLE_RESET_HIGH_CPU_FREQ_OFFS) & 0x1) << 3);
+#elif defined(MV88F67XX)
+	cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+		REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+#endif
+#endif
+
+	return cpu_freq;
+}
+
+/*
+ * Name:     ddr3_get_fab_opt
+ * Desc:     read S@R and return CPU frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_get_fab_opt(void)
+{
+	__maybe_unused u32 reg, fab_opt;
+
+#if defined(MV88F672X)
+	return 0;		/* No fabric */
+#else
+	/* Read sample at reset setting */
+	reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR);
+	fab_opt = (reg & REG_SAMPLE_RESET_FAB_MASK) >>
+		REG_SAMPLE_RESET_FAB_OFFS;
+
+#if defined(MV88F78X60)
+	reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);
+	fab_opt |= (((reg >> 19) & 0x1) << 4);
+#endif
+
+	return fab_opt;
+#endif
+}
+
+/*
+ * Name:     ddr3_get_vco_freq
+ * Desc:     read S@R and return VCO frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_get_vco_freq(void)
+{
+	u32 fab, cpu_freq, ui_vco_freq;
+
+	fab = ddr3_get_fab_opt();
+	cpu_freq = ddr3_get_cpu_freq();
+
+	if (fab == 2 || fab == 3 || fab == 7 || fab == 8 || fab == 10 ||
+	    fab == 15 || fab == 17 || fab == 20)
+		ui_vco_freq = cpu_freq + CLK_CPU;
+	else
+		ui_vco_freq = cpu_freq;
+
+	return ui_vco_freq;
+}
+
+#ifdef STATIC_TRAINING
+/*
+ * Name:     ddr3_static_training_init - Init DDR3 Training with
+ *           static parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_static_training_init(void)
+{
+	MV_DRAM_MODES *ddr_mode;
+	u32 reg;
+	int j;
+
+	ddr_mode = ddr3_get_static_ddr_mode();
+
+	j = 0;
+	while (ddr_mode->vals[j].reg_addr != 0) {
+		udelay(10);	/* haim want to delay each write */
+		reg_write(ddr_mode->vals[j].reg_addr,
+			  ddr_mode->vals[j].reg_value);
+
+		if (ddr_mode->vals[j].reg_addr ==
+		    REG_PHY_REGISTRY_FILE_ACCESS_ADDR)
+			do {
+				reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+					REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+			} while (reg);
+		j++;
+	}
+}
+#endif
+
+/*
+ * Name:     ddr3_get_static_mc_value - Init Memory controller with static
+ *           parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, u32 offset2,
+			     u32 mask2)
+{
+	u32 reg, tmp;
+
+	reg = reg_read(reg_addr);
+
+	tmp = (reg >> offset1) & mask1;
+	if (mask2)
+		tmp |= (reg >> offset2) & mask2;
+
+	return tmp;
+}
+
+/*
+ * Name:     ddr3_get_static_ddr_mode - Init Memory controller with static
+ *           parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+__weak MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
+{
+	u32 chip_board_rev, i;
+	u32 size;
+
+	/* Do not modify this code. relevant only for marvell Boards */
+#if defined(DB_78X60_PCAC)
+	chip_board_rev = Z1_PCAC;
+#elif defined(DB_78X60_AMC)
+	chip_board_rev = A0_AMC;
+#elif defined(DB_88F6710_PCAC)
+	chip_board_rev = A0_PCAC;
+#elif defined(RD_88F6710)
+	chip_board_rev = A0_RD;
+#elif defined(MV88F672X)
+	chip_board_rev = mv_board_id_get();
+#else
+	chip_board_rev = A0;
+#endif
+
+	size = sizeof(ddr_modes) / sizeof(MV_DRAM_MODES);
+	for (i = 0; i < size; i++) {
+		if ((ddr3_get_cpu_freq() == ddr_modes[i].cpu_freq) &&
+		    (ddr3_get_fab_opt() == ddr_modes[i].fab_freq) &&
+		    (chip_board_rev == ddr_modes[i].chip_board_rev))
+			return &ddr_modes[i];
+	}
+
+	return &ddr_modes[0];
+}
+
+#ifdef DUNIT_STATIC
+/*
+ * Name:     ddr3_static_mc_init - Init Memory controller with static parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_static_mc_init(void)
+{
+	MV_DRAM_MODES *ddr_mode;
+	u32 reg;
+	int j;
+
+	ddr_mode = ddr3_get_static_ddr_mode();
+	j = 0;
+	while (ddr_mode->regs[j].reg_addr != 0) {
+		reg_write(ddr_mode->regs[j].reg_addr,
+			  ddr_mode->regs[j].reg_value);
+		if (ddr_mode->regs[j].reg_addr ==
+		    REG_PHY_REGISTRY_FILE_ACCESS_ADDR)
+			do {
+				reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+					REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+			} while (reg);
+		j++;
+	}
+}
+#endif
+
+/*
+ * Name:     ddr3_check_config - Check user configurations: ECC/MultiCS
+ * Desc:
+ * Args:     twsi Address
+ * Notes:    Only Available for ArmadaXP/Armada 370 DB boards
+ * Returns:  None.
+ */
+int ddr3_check_config(u32 twsi_addr, MV_CONFIG_TYPE config_type)
+{
+#ifdef AUTO_DETECTION_SUPPORT
+	u8 data = 0;
+	int ret;
+	int offset;
+
+	if ((config_type == CONFIG_ECC) || (config_type == CONFIG_BUS_WIDTH))
+		offset = 1;
+	else
+		offset = 0;
+
+	ret = i2c_read(twsi_addr, offset, 1, (u8 *)&data, 1);
+	if (!ret) {
+		switch (config_type) {
+		case CONFIG_ECC:
+			if (data & 0x2)
+				return 1;
+			break;
+		case CONFIG_BUS_WIDTH:
+			if (data & 0x1)
+				return 1;
+			break;
+#ifdef DB_88F6710
+		case CONFIG_MULTI_CS:
+			if (CFG_MULTI_CS_MODE(data))
+				return 1;
+			break;
+#else
+		case CONFIG_MULTI_CS:
+			break;
+#endif
+		}
+	}
+#endif
+
+	return 0;
+}
+
+#if defined(DB_88F78X60_REV2)
+/*
+ * Name:     ddr3_get_eprom_fabric - Get Fabric configuration from EPROM
+ * Desc:
+ * Args:     twsi Address
+ * Notes:    Only Available for ArmadaXP DB Rev2 boards
+ * Returns:  None.
+ */
+u8 ddr3_get_eprom_fabric(void)
+{
+#ifdef AUTO_DETECTION_SUPPORT
+	u8 data = 0;
+	int ret;
+
+	ret = i2c_read(NEW_FABRIC_TWSI_ADDR, 1, 1, (u8 *)&data, 1);
+	if (!ret)
+		return data & 0x1F;
+#endif
+
+	return 0;
+}
+
+#endif
+
+/*
+ * Name:     ddr3_cl_to_valid_cl - this return register matching CL value
+ * Desc:
+ * Args:     clValue - the value
+
+ * Notes:
+ * Returns:  required CL value
+ */
+u32 ddr3_cl_to_valid_cl(u32 cl)
+{
+	switch (cl) {
+	case 5:
+		return 2;
+		break;
+	case 6:
+		return 4;
+		break;
+	case 7:
+		return 6;
+		break;
+	case 8:
+		return 8;
+		break;
+	case 9:
+		return 10;
+		break;
+	case 10:
+		return 12;
+		break;
+	case 11:
+		return 14;
+		break;
+	case 12:
+		return 1;
+		break;
+	case 13:
+		return 3;
+		break;
+	case 14:
+		return 5;
+		break;
+	default:
+		return 2;
+	}
+}
+
+/*
+ * Name:     ddr3_cl_to_valid_cl - this return register matching CL value
+ * Desc:
+ * Args:     clValue - the value
+ * Notes:
+ * Returns:  required CL value
+ */
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl)
+{
+	switch (ui_valid_cl) {
+	case 1:
+		return 12;
+		break;
+	case 2:
+		return 5;
+		break;
+	case 3:
+		return 13;
+		break;
+	case 4:
+		return 6;
+		break;
+	case 5:
+		return 14;
+		break;
+	case 6:
+		return 7;
+		break;
+	case 8:
+		return 8;
+		break;
+	case 10:
+		return 9;
+		break;
+	case 12:
+		return 10;
+		break;
+	case 14:
+		return 11;
+		break;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * Name:     ddr3_get_cs_num_from_reg
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_cs_num_from_reg(void)
+{
+	u32 cs_ena = ddr3_get_cs_ena_from_reg();
+	u32 cs_count = 0;
+	u32 cs;
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs))
+			cs_count++;
+	}
+
+	return cs_count;
+}
+
+/*
+ * Name:     ddr3_get_cs_ena_from_reg
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_cs_ena_from_reg(void)
+{
+	return reg_read(REG_DDR3_RANK_CTRL_ADDR) &
+		REG_DDR3_RANK_CTRL_CS_ENA_MASK;
+}
+
+/*
+ * mv_ctrl_rev_get - Get Marvell controller device revision number
+ *
+ * DESCRIPTION:
+ *       This function returns 8bit describing the device revision as defined
+ *       in PCI Express Class Code and Revision ID Register.
+ *
+ * INPUT:
+ *       None.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       8bit desscribing Marvell controller revision number
+ *
+ */
+#if !defined(MV88F672X)
+u8 mv_ctrl_rev_get(void)
+{
+	u8 rev_num;
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	/* Check pex power state */
+	u32 pex_power;
+	pex_power = mv_ctrl_pwr_clck_get(PEX_UNIT_ID, 0);
+	if (pex_power == 0)
+		mv_ctrl_pwr_clck_set(PEX_UNIT_ID, 0, 1);
+#endif
+	rev_num = (u8)reg_read(PEX_CFG_DIRECT_ACCESS(0,
+			PCI_CLASS_CODE_AND_REVISION_ID));
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+	/* Return to power off state */
+	if (pex_power == 0)
+		mv_ctrl_pwr_clck_set(PEX_UNIT_ID, 0, 0);
+#endif
+
+	return (rev_num & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS;
+}
+
+#endif
+
+#if defined(MV88F672X)
+void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps)
+{
+	u32 tmp, hclk;
+
+	switch (freq_mode) {
+	case CPU_333MHz_DDR_167MHz_L2_167MHz:
+		hclk = 84;
+		tmp = DDR_100;
+		break;
+	case CPU_266MHz_DDR_266MHz_L2_133MHz:
+	case CPU_333MHz_DDR_222MHz_L2_167MHz:
+	case CPU_400MHz_DDR_200MHz_L2_200MHz:
+	case CPU_400MHz_DDR_267MHz_L2_200MHz:
+	case CPU_533MHz_DDR_267MHz_L2_267MHz:
+	case CPU_500MHz_DDR_250MHz_L2_250MHz:
+	case CPU_600MHz_DDR_300MHz_L2_300MHz:
+	case CPU_800MHz_DDR_267MHz_L2_400MHz:
+	case CPU_900MHz_DDR_300MHz_L2_450MHz:
+		tmp = DDR_300;
+		hclk = 150;
+		break;
+	case CPU_333MHz_DDR_333MHz_L2_167MHz:
+	case CPU_500MHz_DDR_334MHz_L2_250MHz:
+	case CPU_666MHz_DDR_333MHz_L2_333MHz:
+		tmp = DDR_333;
+		hclk = 165;
+		break;
+	case CPU_533MHz_DDR_356MHz_L2_267MHz:
+		tmp = DDR_360;
+		hclk = 180;
+		break;
+	case CPU_400MHz_DDR_400MHz_L2_200MHz:
+	case CPU_600MHz_DDR_400MHz_L2_300MHz:
+	case CPU_800MHz_DDR_400MHz_L2_400MHz:
+	case CPU_400MHz_DDR_400MHz_L2_400MHz:
+		tmp = DDR_400;
+		hclk = 200;
+		break;
+	case CPU_666MHz_DDR_444MHz_L2_333MHz:
+	case CPU_900MHz_DDR_450MHz_L2_450MHz:
+		tmp = DDR_444;
+		hclk = 222;
+		break;
+	case CPU_500MHz_DDR_500MHz_L2_250MHz:
+	case CPU_1000MHz_DDR_500MHz_L2_500MHz:
+	case CPU_1000MHz_DDR_500MHz_L2_333MHz:
+		tmp = DDR_500;
+		hclk = 250;
+		break;
+	case CPU_533MHz_DDR_533MHz_L2_267MHz:
+	case CPU_800MHz_DDR_534MHz_L2_400MHz:
+	case CPU_1100MHz_DDR_550MHz_L2_550MHz:
+		tmp = DDR_533;
+		hclk = 267;
+		break;
+	case CPU_600MHz_DDR_600MHz_L2_300MHz:
+	case CPU_900MHz_DDR_600MHz_L2_450MHz:
+	case CPU_1200MHz_DDR_600MHz_L2_600MHz:
+		tmp = DDR_600;
+		hclk = 300;
+		break;
+	case CPU_666MHz_DDR_666MHz_L2_333MHz:
+	case CPU_1000MHz_DDR_667MHz_L2_500MHz:
+		tmp = DDR_666;
+		hclk = 333;
+		break;
+	default:
+		*ddr_freq = 0;
+		*hclk_ps = 0;
+		break;
+	}
+
+	*ddr_freq = tmp;		/* DDR freq define */
+	*hclk_ps = 1000000 / hclk;	/* values are 1/HCLK in ps */
+
+	return;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_init.h b/drivers/ddr/mvebu/ddr3_init.h
new file mode 100644
index 0000000..b259e09
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_init.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DDR3_INIT_H
+#define __DDR3_INIT_H
+
+/*
+ * Debug
+ */
+
+/*
+ * MV_DEBUG_INIT need to be defines, otherwise the output of the
+ * DDR2 training code is not complete and misleading
+ */
+#define MV_DEBUG_INIT
+
+#ifdef MV_DEBUG_INIT
+#define DEBUG_INIT_S(s)			puts(s)
+#define DEBUG_INIT_D(d, l)		printf("%x", d)
+#define DEBUG_INIT_D_10(d, l)		printf("%d", d)
+#else
+#define DEBUG_INIT_S(s)
+#define DEBUG_INIT_D(d, l)
+#define DEBUG_INIT_D_10(d, l)
+#endif
+
+#ifdef MV_DEBUG_INIT_FULL
+#define DEBUG_INIT_FULL_S(s)		puts(s)
+#define DEBUG_INIT_FULL_D(d, l)		printf("%x", d)
+#define DEBUG_INIT_FULL_D_10(d, l)	printf("%d", d)
+#define DEBUG_WR_REG(reg, val) \
+	{ DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+	  DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#define DEBUG_RD_REG(reg, val) \
+	{ DEBUG_INIT_S("Read  Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+	  DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#else
+#define DEBUG_INIT_FULL_S(s)
+#define DEBUG_INIT_FULL_D(d, l)
+#define DEBUG_INIT_FULL_D_10(d, l)
+#define DEBUG_WR_REG(reg, val)
+#define DEBUG_RD_REG(reg, val)
+#endif
+
+#define DEBUG_INIT_FULL_C(s, d, l) \
+	{ DEBUG_INIT_FULL_S(s); DEBUG_INIT_FULL_D(d, l); DEBUG_INIT_FULL_S("\n"); }
+#define DEBUG_INIT_C(s, d, l) \
+	{ DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); }
+
+#define MV_MBUS_REGS_OFFSET                 (0x20000)
+
+#include "ddr3_hw_training.h"
+
+#define MAX_DIMM_NUM			2
+#define SPD_SIZE			128
+
+#ifdef MV88F78X60
+#include "ddr3_axp.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375.h"
+#endif
+
+/* DRR training Error codes */
+/* Stage 0 errors */
+#define MV_DDR3_TRAINING_ERR_BAD_SAR			0xDD300001
+/* Stage 1 errors */
+#define MV_DDR3_TRAINING_ERR_TWSI_FAIL			0xDD301001
+#define MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH		0xDD301001
+#define MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE		0xDD301003
+#define MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH	0xDD301004
+#define MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP		0xDD301005
+#define MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT		0xDD301006
+#define MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT		0xDD301007
+#define MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP		0xDD301008
+/* Stage 2 errors */
+#define MV_DDR3_TRAINING_ERR_HW_FAIL_BASE		0xDD302000
+
+typedef enum config_type {
+	CONFIG_ECC,
+	CONFIG_MULTI_CS,
+	CONFIG_BUS_WIDTH
+} MV_CONFIG_TYPE;
+
+enum log_level  {
+	MV_LOG_LEVEL_0,
+	MV_LOG_LEVEL_1,
+	MV_LOG_LEVEL_2,
+	MV_LOG_LEVEL_3
+};
+
+int ddr3_hw_training(u32 target_freq, u32 ddr_width,
+		     int xor_bypass, u32 scrub_offs, u32 scrub_size,
+		     int dqs_clk_aligned, int debug_mode, int reg_dimm_skip_wl);
+
+void ddr3_print_version(void);
+void fix_pll_val(u8 target_fab);
+u8 ddr3_get_eprom_fabric(void);
+u32 ddr3_get_fab_opt(void);
+u32 ddr3_get_cpu_freq(void);
+u32 ddr3_get_vco_freq(void);
+int ddr3_check_config(u32 addr, MV_CONFIG_TYPE config_type);
+u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, u32 offset2,
+			     u32 mask2);
+u32 ddr3_cl_to_valid_cl(u32 cl);
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl);
+u32 ddr3_get_cs_num_from_reg(void);
+u32 ddr3_get_cs_ena_from_reg(void);
+u8 mv_ctrl_rev_get(void);
+
+u32 ddr3_get_log_level(void);
+
+/* SPD */
+int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width);
+
+/*
+ * Accessor functions for the registers
+ */
+static inline void reg_write(u32 addr, u32 val)
+{
+	writel(val, INTER_REGS_BASE + addr);
+}
+
+static inline u32 reg_read(u32 addr)
+{
+	return readl(INTER_REGS_BASE + addr);
+}
+
+static inline void reg_bit_set(u32 addr, u32 mask)
+{
+	setbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+static inline void reg_bit_clr(u32 addr, u32 mask)
+{
+	clrbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+#endif /* __DDR3_INIT_H */
diff --git a/drivers/ddr/mvebu/ddr3_patterns_64bit.h b/drivers/ddr/mvebu/ddr3_patterns_64bit.h
new file mode 100644
index 0000000..1b57328
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_patterns_64bit.h
@@ -0,0 +1,924 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DDR3_PATTERNS_64_H
+#define __DDR3_PATTERNS_64_H
+
+/*
+ * Patterns Declerations
+ */
+
+u32 wl_sup_pattern[LEN_WL_SUP_PATTERN] __aligned(32) = {
+	0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d,
+	0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d,
+	0x24232221, 0x28272625, 0x2c2b2a29, 0x302f2e2d,
+	0x34333231, 0x38373635, 0x3c3b3a39, 0x403f3e3d,
+	0x44434241, 0x48474645, 0x4c4b4a49, 0x504f4e4d,
+	0x54535251, 0x58575655, 0x5c5b5a59, 0x605f5e5d,
+	0x64636261, 0x68676665, 0x6c6b6a69, 0x706f6e6d,
+	0x74737271, 0x78777675, 0x7c7b7a79, 0x807f7e7d
+};
+
+u32 pbs_pattern_32b[2][LEN_PBS_PATTERN] __aligned(32) = {
+	{
+		0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+		0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+		0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+		0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555
+	},
+	{
+		0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+		0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+		0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+		0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA
+	}
+};
+
+u32 pbs_pattern_64b[2][LEN_PBS_PATTERN] __aligned(32) = {
+	{
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+		0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555
+	},
+	{
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+		0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA
+	}
+};
+
+u32 rl_pattern[LEN_STD_PATTERN] __aligned(32) = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x01010101, 0x01010101, 0x01010101, 0x01010101
+};
+
+u32 killer_pattern_32b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+	{
+		0x01010101, 0x00000000, 0x01010101, 0xFFFFFFFF,
+		0x01010101, 0x00000000, 0x01010101, 0xFFFFFFFF,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0xFEFEFEFE,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0xFEFEFEFE,
+		0x01010101, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0x01010101, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0xFEFEFEFE, 0x01010101, 0xFEFEFEFE, 0x00000000,
+		0xFEFEFEFE, 0x01010101, 0xFEFEFEFE, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x01010101,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x01010101,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xFEFEFEFE,
+		0x00000000, 0x00000000, 0x00000000, 0xFEFEFEFE,
+		0xFEFEFEFE, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFEFEFEFE, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFEFEFEFE, 0x00000000, 0xFEFEFEFE, 0x00000000,
+		0xFEFEFEFE, 0x00000000, 0xFEFEFEFE, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x01010101,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x01010101,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x00000000,
+		0x01010101, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x01010101, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE
+	},
+	{
+		0x02020202, 0x00000000, 0x02020202, 0xFFFFFFFF,
+		0x02020202, 0x00000000, 0x02020202, 0xFFFFFFFF,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0xFDFDFDFD,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0xFDFDFDFD,
+		0x02020202, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0x02020202, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0xFDFDFDFD, 0x02020202, 0xFDFDFDFD, 0x00000000,
+		0xFDFDFDFD, 0x02020202, 0xFDFDFDFD, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x02020202,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x02020202,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xFDFDFDFD,
+		0x00000000, 0x00000000, 0x00000000, 0xFDFDFDFD,
+		0xFDFDFDFD, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFDFDFDFD, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFDFDFDFD, 0x00000000, 0xFDFDFDFD, 0x00000000,
+		0xFDFDFDFD, 0x00000000, 0xFDFDFDFD, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x02020202,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x02020202,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x00000000,
+		0x02020202, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x02020202, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD
+	},
+	{
+		0x04040404, 0x00000000, 0x04040404, 0xFFFFFFFF,
+		0x04040404, 0x00000000, 0x04040404, 0xFFFFFFFF,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0xFBFBFBFB,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0xFBFBFBFB,
+		0x04040404, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0x04040404, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0xFBFBFBFB, 0x04040404, 0xFBFBFBFB, 0x00000000,
+		0xFBFBFBFB, 0x04040404, 0xFBFBFBFB, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x04040404,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x04040404,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xFBFBFBFB,
+		0x00000000, 0x00000000, 0x00000000, 0xFBFBFBFB,
+		0xFBFBFBFB, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFBFBFBFB, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFBFBFBFB, 0x00000000, 0xFBFBFBFB, 0x00000000,
+		0xFBFBFBFB, 0x00000000, 0xFBFBFBFB, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x04040404,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x04040404,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x00000000,
+		0x04040404, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x04040404, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB
+	},
+	{
+		0x08080808, 0x00000000, 0x08080808, 0xFFFFFFFF,
+		0x08080808, 0x00000000, 0x08080808, 0xFFFFFFFF,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0xF7F7F7F7,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0xF7F7F7F7,
+		0x08080808, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0x08080808, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0xF7F7F7F7, 0x08080808, 0xF7F7F7F7, 0x00000000,
+		0xF7F7F7F7, 0x08080808, 0xF7F7F7F7, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x08080808,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x08080808,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xF7F7F7F7,
+		0x00000000, 0x00000000, 0x00000000, 0xF7F7F7F7,
+		0xF7F7F7F7, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xF7F7F7F7, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xF7F7F7F7, 0x00000000, 0xF7F7F7F7, 0x00000000,
+		0xF7F7F7F7, 0x00000000, 0xF7F7F7F7, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x08080808,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x08080808,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x00000000,
+		0x08080808, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x08080808, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7
+	},
+	{
+		0x10101010, 0x00000000, 0x10101010, 0xFFFFFFFF,
+		0x10101010, 0x00000000, 0x10101010, 0xFFFFFFFF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0xEFEFEFEF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0xEFEFEFEF,
+		0x10101010, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0x10101010, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0xEFEFEFEF, 0x10101010, 0xEFEFEFEF, 0x00000000,
+		0xEFEFEFEF, 0x10101010, 0xEFEFEFEF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x10101010,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x10101010,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xEFEFEFEF,
+		0x00000000, 0x00000000, 0x00000000, 0xEFEFEFEF,
+		0xEFEFEFEF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xEFEFEFEF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xEFEFEFEF, 0x00000000, 0xEFEFEFEF, 0x00000000,
+		0xEFEFEFEF, 0x00000000, 0xEFEFEFEF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x10101010,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x10101010,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x00000000,
+		0x10101010, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x10101010, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF
+	},
+	{
+		0x20202020, 0x00000000, 0x20202020, 0xFFFFFFFF,
+		0x20202020, 0x00000000, 0x20202020, 0xFFFFFFFF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0xDFDFDFDF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0xDFDFDFDF,
+		0x20202020, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0x20202020, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0xDFDFDFDF, 0x20202020, 0xDFDFDFDF, 0x00000000,
+		0xDFDFDFDF, 0x20202020, 0xDFDFDFDF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x20202020,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x20202020,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xDFDFDFDF,
+		0x00000000, 0x00000000, 0x00000000, 0xDFDFDFDF,
+		0xDFDFDFDF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xDFDFDFDF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xDFDFDFDF, 0x00000000, 0xDFDFDFDF, 0x00000000,
+		0xDFDFDFDF, 0x00000000, 0xDFDFDFDF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x20202020,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x20202020,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x00000000,
+		0x20202020, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x20202020, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF
+	},
+	{
+		0x40404040, 0x00000000, 0x40404040, 0xFFFFFFFF,
+		0x40404040, 0x00000000, 0x40404040, 0xFFFFFFFF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0xBFBFBFBF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0xBFBFBFBF,
+		0x40404040, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0x40404040, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0xBFBFBFBF, 0x40404040, 0xBFBFBFBF, 0x00000000,
+		0xBFBFBFBF, 0x40404040, 0xBFBFBFBF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x40404040,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x40404040,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0xBFBFBFBF,
+		0x00000000, 0x00000000, 0x00000000, 0xBFBFBFBF,
+		0xBFBFBFBF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xBFBFBFBF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xBFBFBFBF, 0x00000000, 0xBFBFBFBF, 0x00000000,
+		0xBFBFBFBF, 0x00000000, 0xBFBFBFBF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x40404040,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x40404040,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x00000000,
+		0x40404040, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x40404040, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF
+	},
+	{
+		0x80808080, 0x00000000, 0x80808080, 0xFFFFFFFF,
+		0x80808080, 0x00000000, 0x80808080, 0xFFFFFFFF,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x7F7F7F7F,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x7F7F7F7F,
+		0x80808080, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x80808080, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x7F7F7F7F, 0x80808080, 0x7F7F7F7F, 0x00000000,
+		0x7F7F7F7F, 0x80808080, 0x7F7F7F7F, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x80808080,
+		0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x80808080,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x7F7F7F7F,
+		0x00000000, 0x00000000, 0x00000000, 0x7F7F7F7F,
+		0x7F7F7F7F, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x7F7F7F7F, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+		0x7F7F7F7F, 0x00000000, 0x7F7F7F7F, 0x00000000,
+		0x7F7F7F7F, 0x00000000, 0x7F7F7F7F, 0x00000000,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x80808080,
+		0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x80808080,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x00000000,
+		0x80808080, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x80808080, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F
+	}
+};
+
+u32 killer_pattern_64b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+	{
+		0x01010101, 0x01010101, 0x00000000, 0x00000000,
+		0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x01010101, 0x01010101, 0x01010101, 0x01010101,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFEFEFEFE, 0xFEFEFEFE,
+		0xFEFEFEFE, 0xFEFEFEFE, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x01010101, 0x01010101, 0x00000000, 0x00000000,
+		0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE
+	},
+	{
+		0x02020202, 0x02020202, 0x00000000, 0x00000000,
+		0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x02020202, 0x02020202, 0x02020202, 0x02020202,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFDFDFDFD, 0xFDFDFDFD,
+		0xFDFDFDFD, 0xFDFDFDFD, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x02020202, 0x02020202, 0x00000000, 0x00000000,
+		0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD
+	},
+	{
+		0x04040404, 0x04040404, 0x00000000, 0x00000000,
+		0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x04040404, 0x04040404, 0x04040404, 0x04040404,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFBFBFBFB, 0xFBFBFBFB,
+		0xFBFBFBFB, 0xFBFBFBFB, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x04040404, 0x04040404, 0x00000000, 0x00000000,
+		0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB
+	},
+	{
+		0x08080808, 0x08080808, 0x00000000, 0x00000000,
+		0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x08080808, 0x08080808, 0x08080808, 0x08080808,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xF7F7F7F7, 0xF7F7F7F7,
+		0xF7F7F7F7, 0xF7F7F7F7, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x08080808, 0x08080808, 0x00000000, 0x00000000,
+		0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7
+	},
+	{
+		0x10101010, 0x10101010, 0x00000000, 0x00000000,
+		0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x10101010, 0x10101010, 0x10101010, 0x10101010,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xEFEFEFEF, 0xEFEFEFEF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x10101010, 0x10101010, 0x00000000, 0x00000000,
+		0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF
+	},
+	{
+		0x20202020, 0x20202020, 0x00000000, 0x00000000,
+		0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x20202020, 0x20202020, 0x20202020, 0x20202020,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xDFDFDFDF, 0xDFDFDFDF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x20202020, 0x20202020, 0x00000000, 0x00000000,
+		0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF
+	},
+	{
+		0x40404040, 0x40404040, 0x00000000, 0x00000000,
+		0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x40404040, 0x40404040, 0x40404040, 0x40404040,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xBFBFBFBF, 0xBFBFBFBF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x40404040, 0x40404040, 0x00000000, 0x00000000,
+		0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF
+	},
+	{
+		0x80808080, 0x80808080, 0x00000000, 0x00000000,
+		0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x80808080, 0x80808080, 0x80808080, 0x80808080,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x7F7F7F7F, 0x7F7F7F7F, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x80808080, 0x80808080, 0x00000000, 0x00000000,
+		0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F
+	}
+};
+
+u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN] __aligned(32) = {
+	{
+		0x00000000, 0x00000000, 0x01010101, 0x01010101,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+		0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x01010101, 0x01010101, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x00000000, 0x00000000, 0xFEFEFEFE, 0xFEFEFEFE,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+		0x00000000, 0x00000000, 0x01010101, 0x01010101,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+		0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x02020202, 0x02020202,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+		0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x02020202, 0x02020202, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x00000000, 0x00000000, 0xFDFDFDFD, 0xFDFDFDFD,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+		0x00000000, 0x00000000, 0x02020202, 0x02020202,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+		0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x04040404, 0x04040404,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+		0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x04040404, 0x04040404, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x00000000, 0x00000000, 0xFBFBFBFB, 0xFBFBFBFB,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+		0x00000000, 0x00000000, 0x04040404, 0x04040404,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+		0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x08080808, 0x08080808,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+		0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x08080808, 0x08080808, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x00000000, 0x00000000, 0xF7F7F7F7, 0xF7F7F7F7,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+		0x00000000, 0x00000000, 0x08080808, 0x08080808,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+		0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x10101010, 0x10101010,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+		0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x10101010, 0x10101010, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x00000000, 0x00000000, 0xEFEFEFEF, 0xEFEFEFEF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+		0x00000000, 0x00000000, 0x10101010, 0x10101010,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+		0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x20202020, 0x20202020,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+		0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x20202020, 0x20202020, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x00000000, 0x00000000, 0xDFDFDFDF, 0xDFDFDFDF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+		0x00000000, 0x00000000, 0x20202020, 0x20202020,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+		0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x40404040, 0x40404040,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+		0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x40404040, 0x40404040, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x00000000, 0x00000000, 0xBFBFBFBF, 0xBFBFBFBF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+		0x00000000, 0x00000000, 0x40404040, 0x40404040,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+		0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000
+	},
+	{
+		0x00000000, 0x00000000, 0x80808080, 0x80808080,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+		0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x80808080, 0x80808080, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x00000000, 0x00000000, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+		0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+		0x00000000, 0x00000000, 0x80808080, 0x80808080,
+		0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+		0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000
+	}
+};
+
+/* Fabric ratios table */
+u32 fabric_ratio[FAB_OPT] = {
+	0x04010204,
+	0x04020202,
+	0x08020306,
+	0x08020303,
+	0x04020303,
+	0x04020204,
+	0x04010202,
+	0x08030606,
+	0x08030505,
+	0x04020306,
+	0x0804050A,
+	0x04030606,
+	0x04020404,
+	0x04030306,
+	0x04020505,
+	0x08020505,
+	0x04010303,
+	0x08050A0A,
+	0x04030408,
+	0x04010102,
+	0x08030306
+};
+
+u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM] = {
+	{3, 2, 5, 7, 1, 0, 6, 4},
+	{2, 3, 6, 7, 1, 0, 4, 5},
+	{1, 3, 5, 6, 0, 2, 4, 7},
+	{0, 2, 4, 7, 1, 3, 5, 6},
+	{3, 0, 4, 6, 1, 2, 5, 7},
+	{0, 3, 5, 7, 1, 2, 4, 6},
+	{2, 3, 5, 7, 1, 0, 4, 6},
+	{0, 2, 5, 4, 1, 3, 6, 7},
+	{2, 3, 4, 7, 0, 1, 5, 6}
+};
+
+#endif /* __DDR3_PATTERNS_64_H */
diff --git a/drivers/ddr/mvebu/ddr3_pbs.c b/drivers/ddr/mvebu/ddr3_pbs.c
new file mode 100644
index 0000000..00ea3fd
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_pbs.c
@@ -0,0 +1,1592 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_PBS_FULL_C(s, d, l) \
+	DEBUG_PBS_FULL_S(s); DEBUG_PBS_FULL_D(d, l); DEBUG_PBS_FULL_S("\n")
+#define DEBUG_PBS_C(s, d, l) \
+	DEBUG_PBS_S(s); DEBUG_PBS_D(d, l); DEBUG_PBS_S("\n")
+
+#ifdef MV_DEBUG_PBS
+#define DEBUG_PBS_S(s)			puts(s)
+#define DEBUG_PBS_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_PBS_S(s)
+#define DEBUG_PBS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_FULL_PBS
+#define DEBUG_PBS_FULL_S(s)		puts(s)
+#define DEBUG_PBS_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_PBS_FULL_S(s)
+#define DEBUG_PBS_FULL_D(d, l)
+#endif
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+
+/* Temp array for skew data storage */
+static u32 skew_array[(MAX_PUP_NUM) * DQ_NUM] = { 0 };
+
+/* PBS locked dq (per pup) */
+extern u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM];
+extern u32 pbs_locked_dm[MAX_PUP_NUM];
+extern u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM];
+
+#if defined(MV88F672X)
+extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN];
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+#else
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN];
+#endif
+
+extern u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM];
+
+static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info,
+		u32 cur_pup, u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup,
+		u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx,
+		u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx);
+static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay);
+
+/*
+ * Name:     ddr3_pbs_tx
+ * Desc:     Execute the PBS TX phase.
+ * Args:     dram_info   ddr3 training information struct
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_pbs_tx(MV_DRAM_INFO *dram_info)
+{
+	/* Array of Deskew results */
+
+	/*
+	 * Array to hold the total sum of skew from all iterations
+	 * (for average purpose)
+	 */
+	u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+	/*
+	 * Array to hold the total average skew from both patterns
+	 * (for average purpose)
+	 */
+	u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+	u32 pbs_rep_time = 0;	/* counts number of loop in case of fail */
+	/* bit array for unlock pups - used to repeat on the RX operation */
+	u32 cur_pup;
+	u32 max_pup;
+	u32 pbs_retry;
+	u32 pup, dq, pups, cur_max_pup, valid_pup, reg;
+	u32 pattern_idx;
+	u32 ecc;
+	/* indicates whether we need to start the loop again */
+	int start_over;
+
+	DEBUG_PBS_S("DDR3 - PBS TX - Starting PBS TX procedure\n");
+
+	pups = dram_info->num_of_total_pups;
+	max_pup = dram_info->num_of_total_pups;
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_PBS_S("DDR3 - PBS RX - SW Override Enabled\n");
+
+	reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS;
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	/* Running twice for 2 different patterns. each patterns - 3 times */
+	for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) {
+		DEBUG_PBS_C("DDR3 - PBS TX - Working with pattern - ",
+			    pattern_idx, 1);
+
+		/* Reset sum array */
+		for (pup = 0; pup < pups; pup++) {
+			for (dq = 0; dq < DQ_NUM; dq++)
+				skew_sum_array[pup][dq] = 0;
+		}
+
+		/*
+		 * Perform PBS several of times (3 for each pattern).
+		 * At the end, we'll use the average
+		 */
+		/* If there is ECC, do each PBS again with mux change */
+		for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) {
+			for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+
+				/*
+				 * This parameter stores the current PUP
+				 * num - ecc mode dependent - 4-8 / 1 pups
+				 */
+				cur_max_pup = (1 - ecc) *
+					dram_info->num_of_std_pups + ecc;
+
+				if (ecc) {
+					/* Only 1 pup in this case */
+					valid_pup = 0x1;
+				} else if (cur_max_pup > 4) {
+					/* 64 bit - 8 pups */
+					valid_pup = 0xFF;
+				} else if (cur_max_pup == 4) {
+					/* 32 bit - 4 pups */
+					valid_pup = 0xF;
+				} else {
+					/* 16 bit - 2 pups */
+					valid_pup = 0x3;
+				}
+
+				/* ECC Support - Switch ECC Mux on ecc=1 */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg |= (dram_info->ecc_ena * ecc <<
+					REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+				if (ecc)
+					DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Enabled\n");
+				else
+					DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Disabled\n");
+
+				/* Init iteration values */
+				/* Clear the locked DQs */
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						pbs_locked_dq[
+							pup + ecc *
+							(max_pup - 1)][dq] =
+							0;
+					}
+				}
+
+				pbs_rep_time = 0;
+				cur_pup = valid_pup;
+				start_over = 0;
+
+				/*
+				 * Run loop On current Pattern and current
+				 * pattern iteration (just to cover the false
+				 * fail problem)
+				 */
+				do {
+					DEBUG_PBS_S("DDR3 - PBS Tx - Pbs Rep Loop is ");
+					DEBUG_PBS_D(pbs_rep_time, 1);
+					DEBUG_PBS_S(", for Retry No.");
+					DEBUG_PBS_D(pbs_retry, 1);
+					DEBUG_PBS_S("\n");
+
+					/* Set all PBS values to MIN (0) */
+					DEBUG_PBS_S("DDR3 - PBS Tx - Set all PBS values to MIN\n");
+
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						ddr3_write_pup_reg(
+							PUP_PBS_TX +
+							pbs_dq_mapping[pup *
+								(1 - ecc) +
+								ecc * ECC_PUP]
+							[dq], CS0, (1 - ecc) *
+							PUP_BC + ecc * ECC_PUP, 0,
+							0);
+					}
+
+					/*
+					 * Shift DQ ADLL right, One step before
+					 * fail
+					 */
+					DEBUG_PBS_S("DDR3 - PBS Tx - ADLL shift right one phase before fail\n");
+
+					if (MV_OK != ddr3_tx_shift_dqs_adll_step_before_fail
+					    (dram_info, cur_pup, pattern_idx,
+					     ecc))
+						return MV_DDR3_TRAINING_ERR_PBS_ADLL_SHR_1PHASE;
+
+					/* PBS For each bit */
+					DEBUG_PBS_S("DDR3 - PBS Tx - perform PBS for each bit\n");
+
+					/*
+					 * In this stage - start_over = 0
+					 */
+					if (MV_OK != ddr3_pbs_per_bit(
+						    dram_info, &start_over, 1,
+						    &cur_pup, pattern_idx, ecc))
+						return MV_DDR3_TRAINING_ERR_PBS_TX_PER_BIT;
+
+				} while ((start_over == 1) &&
+					 (++pbs_rep_time < COUNT_PBS_STARTOVER));
+
+				if (pbs_rep_time == COUNT_PBS_STARTOVER &&
+				    start_over == 1) {
+					DEBUG_PBS_S("DDR3 - PBS Tx - FAIL - Adll reach max value\n");
+					return MV_DDR3_TRAINING_ERR_PBS_TX_MAX_VAL;
+				}
+
+				DEBUG_PBS_FULL_C("DDR3 - PBS TX - values for iteration - ",
+						 pbs_retry, 1);
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					/*
+					 * To minimize delay elements, inc
+					 * from pbs value the min pbs val
+					 */
+					DEBUG_PBS_S("DDR3 - PBS - PUP");
+					DEBUG_PBS_D((pup + (ecc * ECC_PUP)), 1);
+					DEBUG_PBS_S(": ");
+
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						/* Set skew value for all dq */
+						/*
+						 * Bit# Deskew <- Bit# Deskew -
+						 * last / first  failing bit
+						 * Deskew For all bits (per PUP)
+						 * (minimize delay elements)
+						 */
+						DEBUG_PBS_S("DQ");
+						DEBUG_PBS_D(dq, 1);
+						DEBUG_PBS_S("-");
+						DEBUG_PBS_D(skew_array
+							    [((pup) * DQ_NUM) +
+							     dq], 2);
+						DEBUG_PBS_S(", ");
+					}
+					DEBUG_PBS_S("\n");
+				}
+
+				/*
+				 * Collect the results we got on this trial
+				 * of PBS
+				 */
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						skew_sum_array[pup + (ecc * (max_pup - 1))]
+							[dq] += skew_array
+							[((pup) * DQ_NUM) + dq];
+					}
+				}
+
+				/* ECC Support - Disable ECC MUX */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+			}
+		}
+
+		DEBUG_PBS_C("DDR3 - PBS TX - values for current pattern - ",
+			    pattern_idx, 1);
+		for (pup = 0; pup < max_pup; pup++) {
+			/*
+			 * To minimize delay elements, inc from pbs value the
+			 * min pbs val
+			 */
+			DEBUG_PBS_S("DDR3 - PBS - PUP");
+			DEBUG_PBS_D(pup, 1);
+			DEBUG_PBS_S(": ");
+
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				/* set skew value for all dq */
+				/* Bit# Deskew <- Bit# Deskew - last / first  failing bit Deskew For all bits (per PUP) (minimize delay elements) */
+				DEBUG_PBS_S("DQ");
+				DEBUG_PBS_D(dq, 1);
+				DEBUG_PBS_S("-");
+				DEBUG_PBS_D(skew_sum_array[pup][dq] /
+					    COUNT_PBS_REPEAT, 2);
+				DEBUG_PBS_S(", ");
+			}
+			DEBUG_PBS_S("\n");
+		}
+
+		/*
+		 * Calculate the average skew for current pattern for each
+		 * pup and each bit
+		 */
+		DEBUG_PBS_C("DDR3 - PBS TX - Average for pattern - ",
+			    pattern_idx, 1);
+
+		for (pup = 0; pup < max_pup; pup++) {
+			/*
+			 * FOR ECC only :: found min and max value for current
+			 * pattern skew array
+			 */
+			/* Loop for all dqs */
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				pattern_skew_array[pup][dq] +=
+					(skew_sum_array[pup][dq] /
+					 COUNT_PBS_REPEAT);
+			}
+		}
+	}
+
+	/* Calculate the average skew */
+	for (pup = 0; pup < max_pup; pup++) {
+		for (dq = 0; dq < DQ_NUM; dq++)
+			skew_array[((pup) * DQ_NUM) + dq] =
+				pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN;
+	}
+
+	DEBUG_PBS_S("DDR3 - PBS TX - Average for all patterns:\n");
+	for (pup = 0; pup < max_pup; pup++) {
+		/*
+		 * To minimize delay elements, inc from pbs value the min
+		 * pbs val
+		 */
+		DEBUG_PBS_S("DDR3 - PBS - PUP");
+		DEBUG_PBS_D(pup, 1);
+		DEBUG_PBS_S(": ");
+
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			/* Set skew value for all dq */
+			/*
+			 * Bit# Deskew <- Bit# Deskew - last / first
+			 * failing bit Deskew For all bits (per PUP)
+			 * (minimize delay elements)
+			 */
+			DEBUG_PBS_S("DQ");
+			DEBUG_PBS_D(dq, 1);
+			DEBUG_PBS_S("-");
+			DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2);
+			DEBUG_PBS_S(", ");
+		}
+		DEBUG_PBS_S("\n");
+	}
+
+	/* Return ADLL to default value */
+	for (pup = 0; pup < max_pup; pup++) {
+		if (pup == (max_pup - 1) && dram_info->ecc_ena)
+			pup = ECC_PUP;
+		ddr3_pbs_write_pup_dqs_reg(CS0, pup, INIT_WL_DELAY);
+	}
+
+	/* Set averaged PBS results */
+	ddr3_set_pbs_results(dram_info, 1);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	DEBUG_PBS_S("DDR3 - PBS Tx - PBS TX ended successfuly\n");
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_tx_shift_dqs_adll_step_before_fail
+ * Desc:     Execute the Tx shift DQ phase.
+ * Args:     dram_info            ddr3 training information struct
+ *           cur_pup              bit array of the function active pups.
+ *           pbs_pattern_idx      Index of PBS pattern
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info,
+						   u32 cur_pup,
+						   u32 pbs_pattern_idx, u32 ecc)
+{
+	u32 unlock_pup;		/* bit array of unlock pups  */
+	u32 new_lockup_pup;	/* bit array of compare failed pups */
+	u32 adll_val = 4;	/* INIT_WL_DELAY */
+	u32 cur_max_pup, pup;
+	u32 dqs_dly_set[MAX_PUP_NUM] = { 0 };
+	u32 *pattern_ptr;
+
+	/* Choose pattern */
+	switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+	case 16:
+		pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+		break;
+#endif
+	case 32:
+		pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+		break;
+#if defined(MV88F78X60)
+	case 64:
+		pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+		break;
+#endif
+	default:
+		return MV_FAIL;
+	}
+
+	/* Set current pup number */
+	if (cur_pup == 0x1)	/* Ecc mode */
+		cur_max_pup = 1;
+	else
+		cur_max_pup = dram_info->num_of_std_pups;
+
+	unlock_pup = cur_pup;	/* '1' for each unlocked pup */
+
+	/* Loop on all ADLL Vaules */
+	do {
+		/* Loop until found first fail */
+		adll_val++;
+
+		/*
+		 * Increment (Move to right - ADLL) DQ TX delay
+		 * (broadcast to all Data PUPs)
+		 */
+		for (pup = 0; pup < cur_max_pup; pup++)
+			ddr3_pbs_write_pup_dqs_reg(CS0,
+						   pup * (1 - ecc) +
+						   ECC_PUP * ecc, adll_val);
+
+		/*
+		 * Write and Read, compare results (read was already verified)
+		 */
+		/* 0 - all locked */
+		new_lockup_pup = 0;
+
+		if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup,
+						&new_lockup_pup,
+						pattern_ptr, LEN_PBS_PATTERN,
+						SDRAM_PBS_TX_OFFS, 1, 0,
+						NULL,
+						0))
+			return MV_FAIL;
+
+		unlock_pup &= ~new_lockup_pup;
+
+		DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: ");
+		DEBUG_PBS_FULL_D(unlock_pup, 2);
+		DEBUG_PBS_FULL_C(", Set ADLL value = ", adll_val, 2);
+
+		/* If any PUP failed there is '1' to mark the PUP */
+		if (new_lockup_pup != 0) {
+			/*
+			 * Decrement (Move Back to Left two steps - ADLL)
+			 * DQ TX delay for current failed pups and save
+			 */
+			for (pup = 0; pup < cur_max_pup; pup++) {
+				if (((new_lockup_pup >> pup) & 0x1) &&
+				    dqs_dly_set[pup] == 0)
+					dqs_dly_set[pup] = adll_val - 1;
+			}
+		}
+	} while ((unlock_pup != 0) && (adll_val != ADLL_MAX));
+
+	if (unlock_pup != 0) {
+		DEBUG_PBS_FULL_S("DDR3 - PBS Tx - Shift DQ - Adll value reached maximum\n");
+
+		for (pup = 0; pup < cur_max_pup; pup++) {
+			if (((unlock_pup >> pup) & 0x1) &&
+			    dqs_dly_set[pup] == 0)
+				dqs_dly_set[pup] = adll_val - 1;
+		}
+	}
+
+	DEBUG_PBS_FULL_C("PBS TX one step before fail last pups locked Adll ",
+			 adll_val - 2, 2);
+
+	/* Set the PUP DQS DLY Values */
+	for (pup = 0; pup < cur_max_pup; pup++)
+		ddr3_pbs_write_pup_dqs_reg(CS0, pup * (1 - ecc) + ECC_PUP * ecc,
+					   dqs_dly_set[pup]);
+
+	/* Found one phase before fail */
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_pbs_rx
+ * Desc:     Execute the PBS RX phase.
+ * Args:     dram_info   ddr3 training information struct
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_pbs_rx(MV_DRAM_INFO *dram_info)
+{
+	/*
+	 * Array to hold the total sum of skew from all iterations
+	 * (for average purpose)
+	 */
+	u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+	/*
+	 * Array to hold the total average skew from both patterns
+	 * (for average purpose)
+	 */
+	u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+	u32 pbs_rep_time = 0;	/* counts number of loop in case of fail */
+	/* bit array for unlock pups - used to repeat on the RX operation */
+	u32 cur_pup;
+	u32 max_pup;
+	u32 pbs_retry;
+	u32 pup, dq, pups, cur_max_pup, valid_pup, reg;
+	u32 pattern_idx;
+	u32 ecc;
+	/* indicates whether we need to start the loop again */
+	int start_over;
+	int status;
+
+	DEBUG_PBS_S("DDR3 - PBS RX - Starting PBS RX procedure\n");
+
+	pups = dram_info->num_of_total_pups;
+	max_pup = dram_info->num_of_total_pups;
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_PBS_FULL_S("DDR3 - PBS RX - SW Override Enabled\n");
+
+	reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS;
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	/* Running twice for 2 different patterns. each patterns - 3 times */
+	for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) {
+		DEBUG_PBS_FULL_C("DDR3 - PBS RX - Working with pattern - ",
+				 pattern_idx, 1);
+
+		/* Reset sum array */
+		for (pup = 0; pup < pups; pup++) {
+			for (dq = 0; dq < DQ_NUM; dq++)
+				skew_sum_array[pup][dq] = 0;
+		}
+
+		/*
+		 * Perform PBS several of times (3 for each pattern).
+		 * At the end, we'll use the average
+		 */
+		/* If there is ECC, do each PBS again with mux change */
+		for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) {
+			for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+				/*
+				 * This parameter stores the current PUP
+				 * num - ecc mode dependent - 4-8 / 1 pups
+				 */
+				cur_max_pup = (1 - ecc) *
+					dram_info->num_of_std_pups + ecc;
+
+				if (ecc) {
+					/* Only 1 pup in this case */
+					valid_pup = 0x1;
+				} else if (cur_max_pup > 4) {
+					/* 64 bit - 8 pups */
+					valid_pup = 0xFF;
+				} else if (cur_max_pup == 4) {
+					/* 32 bit - 4 pups */
+					valid_pup = 0xF;
+				} else {
+					/* 16 bit - 2 pups */
+					valid_pup = 0x3;
+				}
+
+				/* ECC Support - Switch ECC Mux on ecc=1 */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg |= (dram_info->ecc_ena * ecc <<
+					REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+				if (ecc)
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Enabled\n");
+				else
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Disabled\n");
+
+				/* Init iteration values */
+				/* Clear the locked DQs */
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						pbs_locked_dq[
+							pup + ecc * (max_pup - 1)][dq] =
+							0;
+					}
+				}
+
+				pbs_rep_time = 0;
+				cur_pup = valid_pup;
+				start_over = 0;
+
+				/*
+				 * Run loop On current Pattern and current
+				 * pattern iteration (just to cover the false
+				 * fail problem
+				 */
+				do {
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Pbs Rep Loop is ");
+					DEBUG_PBS_FULL_D(pbs_rep_time, 1);
+					DEBUG_PBS_FULL_S(", for Retry No.");
+					DEBUG_PBS_FULL_D(pbs_retry, 1);
+					DEBUG_PBS_FULL_S("\n");
+
+					/* Set all PBS values to MAX (31) */
+					for (pup = 0; pup < cur_max_pup; pup++) {
+						for (dq = 0; dq < DQ_NUM; dq++)
+							ddr3_write_pup_reg(
+								PUP_PBS_RX +
+								pbs_dq_mapping[
+								pup * (1 - ecc)
+								+ ecc * ECC_PUP]
+								[dq], CS0,
+								pup + ecc * ECC_PUP,
+								0, MAX_PBS);
+					}
+
+					/* Set all DQS PBS values to MIN (0) */
+					for (pup = 0; pup < cur_max_pup; pup++) {
+						ddr3_write_pup_reg(PUP_PBS_RX +
+								   DQ_NUM, CS0,
+								   pup +
+								   ecc *
+								   ECC_PUP, 0,
+								   0);
+					}
+
+					/* Shift DQS, To first Fail */
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift RX DQS to first fail\n");
+
+					status = ddr3_rx_shift_dqs_to_first_fail
+						(dram_info, cur_pup,
+						 pattern_idx, ecc);
+					if (MV_OK != status) {
+						DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_rx_shift_dqs_to_first_fail failed.\n");
+						DEBUG_PBS_D(status, 8);
+						DEBUG_PBS_S("\nDDR3 - PBS Rx - SKIP.\n");
+
+						/* Reset read FIFO */
+						reg = reg_read(REG_DRAM_TRAINING_ADDR);
+						/* Start Auto Read Leveling procedure */
+						reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+						/* 0x15B0 - Training Register */
+						reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+						reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+						reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS)
+							+ (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+						/* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+						/* 0x15B8 - Training SW 2 Register */
+						reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+						do {
+							reg = (reg_read(REG_DRAM_TRAINING_2_ADDR))
+								& (1 <<	REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+						} while (reg);	/* Wait for '0' */
+
+						reg = reg_read(REG_DRAM_TRAINING_ADDR);
+						/* Clear Auto Read Leveling procedure */
+						reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+						/* 0x15B0 - Training Register */
+						reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+						/* Set ADLL to 15 */
+						for (pup = 0; pup < max_pup;
+						     pup++) {
+							ddr3_write_pup_reg
+							    (PUP_DQS_RD, CS0,
+							     pup +
+							     (ecc * ECC_PUP), 0,
+							     15);
+						}
+
+						/* Set all PBS values to MIN (0) */
+						for (pup = 0; pup < cur_max_pup;
+						     pup++) {
+							for (dq = 0;
+							     dq < DQ_NUM; dq++)
+								ddr3_write_pup_reg
+								    (PUP_PBS_RX +
+								     pbs_dq_mapping
+								     [pup * (1 - ecc) +
+								      ecc * ECC_PUP]
+								     [dq], CS0,
+								     pup + ecc * ECC_PUP,
+								     0, MIN_PBS);
+						}
+
+						return MV_OK;
+					}
+
+					/* PBS For each bit */
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - perform PBS for each bit\n");
+					/* in this stage - start_over = 0; */
+					if (MV_OK != ddr3_pbs_per_bit(
+						    dram_info, &start_over,
+						    0, &cur_pup,
+						    pattern_idx, ecc)) {
+						DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_pbs_per_bit failed.");
+						return MV_DDR3_TRAINING_ERR_PBS_RX_PER_BIT;
+					}
+
+				} while ((start_over == 1) &&
+					 (++pbs_rep_time < COUNT_PBS_STARTOVER));
+
+				if (pbs_rep_time == COUNT_PBS_STARTOVER &&
+				    start_over == 1) {
+					DEBUG_PBS_FULL_S("DDR3 - PBS Rx - FAIL - Algorithm failed doing RX PBS\n");
+					return MV_DDR3_TRAINING_ERR_PBS_RX_MAX_VAL;
+				}
+
+				/* Return DQS ADLL to default value - 15 */
+				/* Set all DQS PBS values to MIN (0) */
+				for (pup = 0; pup < cur_max_pup; pup++)
+					ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+							   pup + ecc * ECC_PUP,
+							   0, INIT_RL_DELAY);
+
+				DEBUG_PBS_FULL_C("DDR3 - PBS RX - values for iteration - ",
+						 pbs_retry, 1);
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					/*
+					 * To minimize delay elements, inc from
+					 * pbs value the min pbs val
+					 */
+					DEBUG_PBS_FULL_S("DDR3 - PBS - PUP");
+					DEBUG_PBS_FULL_D((pup +
+							  (ecc * ECC_PUP)), 1);
+					DEBUG_PBS_FULL_S(": ");
+
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						/* Set skew value for all dq */
+						/*
+						 * Bit# Deskew <- Bit# Deskew -
+						 * last / first  failing bit
+						 * Deskew For all bits (per PUP)
+						 * (minimize delay elements)
+						 */
+						DEBUG_PBS_FULL_S("DQ");
+						DEBUG_PBS_FULL_D(dq, 1);
+						DEBUG_PBS_FULL_S("-");
+						DEBUG_PBS_FULL_D(skew_array
+								 [((pup) *
+								   DQ_NUM) +
+								  dq], 2);
+						DEBUG_PBS_FULL_S(", ");
+					}
+					DEBUG_PBS_FULL_S("\n");
+				}
+
+				/*
+				 * Collect the results we got on this trial
+				 * of PBS
+				 */
+				for (pup = 0; pup < cur_max_pup; pup++) {
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						skew_sum_array
+							[pup + (ecc * (max_pup - 1))]
+							[dq] +=
+							skew_array[((pup) * DQ_NUM) + dq];
+					}
+				}
+
+				/* ECC Support - Disable ECC MUX */
+				reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+					~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+				reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+			}
+		}
+
+		/*
+		 * Calculate the average skew for current pattern for each
+		 * pup and each bit
+		 */
+		DEBUG_PBS_FULL_C("DDR3 - PBS RX - Average for pattern - ",
+				 pattern_idx, 1);
+		for (pup = 0; pup < max_pup; pup++) {
+			/*
+			 * FOR ECC only :: found min and max value for
+			 * current pattern skew array
+			 */
+			/* Loop for all dqs */
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				pattern_skew_array[pup][dq] +=
+					(skew_sum_array[pup][dq] /
+					 COUNT_PBS_REPEAT);
+			}
+		}
+
+		DEBUG_PBS_C("DDR3 - PBS RX - values for current pattern - ",
+			    pattern_idx, 1);
+		for (pup = 0; pup < max_pup; pup++) {
+			/*
+			 * To minimize delay elements, inc from pbs value the
+			 * min pbs val
+			 */
+			DEBUG_PBS_S("DDR3 - PBS RX - PUP");
+			DEBUG_PBS_D(pup, 1);
+			DEBUG_PBS_S(": ");
+
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				/* Set skew value for all dq */
+				/*
+				 * Bit# Deskew <- Bit# Deskew - last / first
+				 * failing bit Deskew For all bits (per PUP)
+				 * (minimize delay elements)
+				 */
+				DEBUG_PBS_S("DQ");
+				DEBUG_PBS_D(dq, 1);
+				DEBUG_PBS_S("-");
+				DEBUG_PBS_D(skew_sum_array[pup][dq] /
+					    COUNT_PBS_REPEAT, 2);
+				DEBUG_PBS_S(", ");
+			}
+			DEBUG_PBS_S("\n");
+		}
+	}
+
+	/* Calculate the average skew */
+	for (pup = 0; pup < max_pup; pup++) {
+		for (dq = 0; dq < DQ_NUM; dq++)
+			skew_array[((pup) * DQ_NUM) + dq] =
+				pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN;
+	}
+
+	DEBUG_PBS_S("DDR3 - PBS RX - Average for all patterns:\n");
+	for (pup = 0; pup < max_pup; pup++) {
+		/*
+		 * To minimize delay elements, inc from pbs value the
+		 * min pbs val
+		 */
+		DEBUG_PBS_S("DDR3 - PBS - PUP");
+		DEBUG_PBS_D(pup, 1);
+		DEBUG_PBS_S(": ");
+
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			/* Set skew value for all dq */
+			/*
+			 * Bit# Deskew <- Bit# Deskew - last / first
+			 * failing bit Deskew For all bits (per PUP)
+			 * (minimize delay elements)
+			 */
+			DEBUG_PBS_S("DQ");
+			DEBUG_PBS_D(dq, 1);
+			DEBUG_PBS_S("-");
+			DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2);
+			DEBUG_PBS_S(", ");
+		}
+		DEBUG_PBS_S("\n");
+	}
+
+	/* Return ADLL to default value */
+	ddr3_write_pup_reg(PUP_DQS_RD, CS0, PUP_BC, 0, INIT_RL_DELAY);
+
+	/* Set averaged PBS results */
+	ddr3_set_pbs_results(dram_info, 0);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	DEBUG_PBS_FULL_S("DDR3 - PBS RX - ended successfuly\n");
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_rx_shift_dqs_to_first_fail
+ * Desc:     Execute the Rx shift DQ phase.
+ * Args:     dram_info           ddr3 training information struct
+ *           cur_pup             bit array of the function active pups.
+ *           pbs_pattern_idx     Index of PBS pattern
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup,
+					   u32 pbs_pattern_idx, u32 ecc)
+{
+	u32 unlock_pup;		/* bit array of unlock pups  */
+	u32 new_lockup_pup;	/* bit array of compare failed pups */
+	u32 adll_val = MAX_DELAY;
+	u32 dqs_deskew_val = 0;	/* current value of DQS PBS deskew */
+	u32 cur_max_pup, pup, pass_pup;
+	u32 *pattern_ptr;
+
+	/* Choose pattern */
+	switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+	case 16:
+		pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+		break;
+#endif
+	case 32:
+		pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+		break;
+#if defined(MV88F78X60)
+	case 64:
+		pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+		break;
+#endif
+	default:
+		return MV_FAIL;
+	}
+
+	/* Set current pup number */
+	if (cur_pup == 0x1)	/* Ecc mode */
+		cur_max_pup = 1;
+	else
+		cur_max_pup = dram_info->num_of_std_pups;
+
+	unlock_pup = cur_pup;	/* '1' for each unlocked pup */
+
+	DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Starting...\n");
+
+	/* Set DQS ADLL to MAX */
+	DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Set DQS ADLL to Max for all PUPs\n");
+	for (pup = 0; pup < cur_max_pup; pup++)
+		ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP, 0,
+				   MAX_DELAY);
+
+	/* Loop on all ADLL Vaules */
+	do {
+		/* Loop until found fail for all pups */
+		new_lockup_pup = 0;
+		if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup,
+						&new_lockup_pup,
+						pattern_ptr, LEN_PBS_PATTERN,
+						SDRAM_PBS_I_OFFS +
+						pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS,
+						0, 0, NULL, 0)) {
+			DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n");
+			return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+		}
+
+		if ((new_lockup_pup != 0) && (dqs_deskew_val <= 1)) {
+			/* Fail on start with first deskew value */
+			/* Decrement DQS ADLL */
+			--adll_val;
+			if (adll_val == ADLL_MIN) {
+				DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - fail on start with first deskew value\n");
+				return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+			}
+			ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP,
+					   0, adll_val);
+			continue;
+		}
+
+		/* Update all new locked pups */
+		unlock_pup &= ~new_lockup_pup;
+
+		if ((unlock_pup == 0) || (dqs_deskew_val == MAX_PBS)) {
+			if (dqs_deskew_val == MAX_PBS) {
+				/*
+				 * Reach max value of dqs deskew or get fail
+				 * for all pups
+				 */
+				DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - DQS deskew reached maximum value\n");
+			}
+			break;
+		}
+
+		DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Inc DQS deskew for PUPs: ");
+		DEBUG_PBS_FULL_D(unlock_pup, 2);
+		DEBUG_PBS_FULL_C(", deskew = ", dqs_deskew_val, 2);
+
+		/* Increment DQS deskew elements - Only for unlocked pups */
+		dqs_deskew_val++;
+		for (pup = 0; pup < cur_max_pup; pup++) {
+			if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+				ddr3_write_pup_reg(PUP_PBS_RX + DQS_DQ_NUM, CS0,
+						   pup + ecc * ECC_PUP, 0,
+						   dqs_deskew_val);
+			}
+		}
+	} while (1);
+
+	DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - ADLL shift one step before fail\n");
+	/* Continue to ADLL shift one step before fail */
+	unlock_pup = cur_pup;
+	do {
+		/* Loop until pass compare for all pups */
+		new_lockup_pup = 0;
+		/* Read and compare results  */
+		if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup, &new_lockup_pup,
+						pattern_ptr, LEN_PBS_PATTERN,
+						SDRAM_PBS_I_OFFS +
+						pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS,
+						1, 0, NULL, 0)) {
+			DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n");
+			return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+		}
+
+		/*
+		 * Get mask for pup which passed so their adll will be
+		 * changed to 2 steps before fails
+		 */
+		pass_pup = unlock_pup & ~new_lockup_pup;
+
+		DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: ");
+		DEBUG_PBS_FULL_D(pass_pup, 2);
+		DEBUG_PBS_FULL_C(", Set ADLL value = ", (adll_val - 2), 2);
+
+		/* Only for pass pups   */
+		for (pup = 0; pup < cur_max_pup; pup++) {
+			if (IS_PUP_ACTIVE(pass_pup, pup) == 1) {
+				ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+						   pup + ecc * ECC_PUP, 0,
+						   (adll_val - 2));
+			}
+		}
+
+		/* Locked pups that compare success  */
+		unlock_pup &= new_lockup_pup;
+
+		if (unlock_pup == 0) {
+			/* All pups locked */
+			break;
+		}
+
+		/* Found error */
+		if (adll_val == 0) {
+			DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift DQS - Adll reach min value\n");
+			return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_MAX_VAL;
+		}
+
+		/*
+		 * Decrement (Move Back to Left one phase - ADLL) dqs RX delay
+		 */
+		adll_val--;
+		for (pup = 0; pup < cur_max_pup; pup++) {
+			if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+				ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+						   pup + ecc * ECC_PUP, 0,
+						   adll_val);
+			}
+		}
+	} while (1);
+
+	return MV_OK;
+}
+
+/*
+ * lock_pups() extracted from ddr3_pbs_per_bit(). This just got too
+ * much indented making it hard to read / edit.
+ */
+static void lock_pups(u32 pup, u32 *pup_locked, u8 *unlock_pup_dq_array,
+		      u32 pbs_curr_val, u32 start_pbs, u32 ecc, int is_tx)
+{
+	u32 dq;
+	int idx;
+
+	/* Lock PBS value for all remaining PUPs bits */
+	DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Lock PBS value for all remaining PUPs bits, pup ");
+	DEBUG_PBS_FULL_D(pup, 1);
+	DEBUG_PBS_FULL_C(" pbs value ", pbs_curr_val, 2);
+
+	idx = pup * (1 - ecc) + ecc * ECC_PUP;
+	*pup_locked &= ~(1 << pup);
+
+	for (dq = 0; dq < DQ_NUM; dq++) {
+		if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup) == 1) {
+			int offs;
+
+			/* Lock current dq */
+			unlock_pup_dq_array[dq] &= ~(1 << pup);
+			skew_array[(pup * DQ_NUM) + dq] = pbs_curr_val;
+
+			if (is_tx == 1)
+				offs = PUP_PBS_TX;
+			else
+				offs = PUP_PBS_RX;
+
+			ddr3_write_pup_reg(offs +
+					   pbs_dq_mapping[idx][dq], CS0,
+					   idx, 0, start_pbs);
+		}
+	}
+}
+
+/*
+ * Name:     ddr3_pbs_per_bit
+ * Desc:     Execute the Per Bit Skew phase.
+ * Args:     start_over      Return whether need to start over the algorithm
+ *           is_tx           Indicate whether Rx or Tx
+ *           pcur_pup        bit array of the function active pups. return the
+ *                           pups that need to repeat on the PBS
+ *           pbs_pattern_idx Index of PBS pattern
+ *
+ * Notes:    Current implementation supports double activation of this function.
+ *           i.e. in order to activate this function (using start_over) more than
+ *           twice, the implementation should change.
+ *           imlementation limitation are marked using
+ *           ' CHIP-ONLY! - Implementation Limitation '
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx,
+			    u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc)
+{
+	/*
+	 * Bit array to indicate if we already get fail on bit per pup & dq bit
+	 */
+	u8 unlock_pup_dq_array[DQ_NUM] = {
+		*pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup,
+		*pcur_pup, *pcur_pup, *pcur_pup
+	};
+
+	u8 cmp_unlock_pup_dq_array[COUNT_PBS_COMP_RETRY_NUM][DQ_NUM];
+	u32 pup, dq;
+	/* value of pbs is according to RX or TX */
+	u32 start_pbs, last_pbs;
+	u32 pbs_curr_val;
+	/* bit array that indicates all dq of the pup locked */
+	u32 pup_locked;
+	u32 first_fail[MAX_PUP_NUM] = { 0 };	/* count first fail per pup */
+	/* indicates whether we get first fail per pup */
+	int first_failed[MAX_PUP_NUM] = { 0 };
+	/* bit array that indicates pup already get fail */
+	u32 sum_pup_fail;
+	/* use to calculate diff between curr pbs to first fail pbs */
+	u32 calc_pbs_diff;
+	u32 pbs_cmp_retry;
+	u32 max_pup;
+
+	/* Set init values for retry array - 8 retry */
+	for (pbs_cmp_retry = 0; pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM;
+	     pbs_cmp_retry++) {
+		for (dq = 0; dq < DQ_NUM; dq++)
+			cmp_unlock_pup_dq_array[pbs_cmp_retry][dq] = *pcur_pup;
+	}
+
+	memset(&skew_array, 0, MAX_PUP_NUM * DQ_NUM * sizeof(u32));
+
+	DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Started\n");
+
+	/* The pbs value depends if rx or tx */
+	if (is_tx == 1) {
+		start_pbs = MIN_PBS;
+		last_pbs = MAX_PBS;
+	} else {
+		start_pbs = MAX_PBS;
+		last_pbs = MIN_PBS;
+	}
+
+	pbs_curr_val = start_pbs;
+	pup_locked = *pcur_pup;
+
+	/* Set current pup number */
+	if (pup_locked == 0x1)	/* Ecc mode */
+		max_pup = 1;
+	else
+		max_pup = dram_info->num_of_std_pups;
+
+	do {
+		/* Increment/ decrement PBS for un-lock bits only */
+		if (is_tx == 1)
+			pbs_curr_val++;
+		else
+			pbs_curr_val--;
+
+		/* Set Current PBS delay  */
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			/* Check DQ bits to see if locked in all pups */
+			if (unlock_pup_dq_array[dq] == 0) {
+				DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - All pups are locked for DQ ");
+				DEBUG_PBS_FULL_D(dq, 1);
+				DEBUG_PBS_FULL_S("\n");
+				continue;
+			}
+
+			for (pup = 0; pup < max_pup; pup++) {
+				int idx;
+
+				idx = pup * (1 - ecc) + ecc * ECC_PUP;
+
+				if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup)
+				    == 0)
+					continue;
+
+				if (is_tx == 1)
+					ddr3_write_pup_reg(
+						PUP_PBS_TX + pbs_dq_mapping[idx][dq],
+						CS0, idx, 0, pbs_curr_val);
+				else
+					ddr3_write_pup_reg(
+						PUP_PBS_RX + pbs_dq_mapping[idx][dq],
+						CS0, idx, 0, pbs_curr_val);
+			}
+		}
+
+		/*
+		 * Write Read and compare results - run the test
+		 * DDR_PBS_COMP_RETRY_NUM times
+		 */
+		/* Run number of read and write to verify */
+		for (pbs_cmp_retry = 0;
+		     pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM;
+		     pbs_cmp_retry++) {
+
+			if (MV_OK !=
+			    ddr3_sdram_pbs_compare(dram_info, pup_locked, is_tx,
+						   pbs_pattern_idx,
+						   pbs_curr_val, start_pbs,
+						   skew_array,
+						   cmp_unlock_pup_dq_array
+						   [pbs_cmp_retry], ecc))
+				return MV_FAIL;
+
+			for (pup = 0; pup < max_pup; pup++) {
+				for (dq = 0; dq < DQ_NUM; dq++) {
+					if ((IS_PUP_ACTIVE(unlock_pup_dq_array[dq],
+							   pup) == 1)
+					    && (IS_PUP_ACTIVE(cmp_unlock_pup_dq_array
+					      [pbs_cmp_retry][dq],
+					      pup) == 0)) {
+						DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PbsCurrVal: ");
+						DEBUG_PBS_FULL_D(pbs_curr_val, 2);
+						DEBUG_PBS_FULL_S(" PUP: ");
+						DEBUG_PBS_FULL_D(pup, 1);
+						DEBUG_PBS_FULL_S(" DQ: ");
+						DEBUG_PBS_FULL_D(dq, 1);
+						DEBUG_PBS_FULL_S(" - failed\n");
+					}
+				}
+			}
+
+			for (dq = 0; dq < DQ_NUM; dq++) {
+				unlock_pup_dq_array[dq] &=
+				    cmp_unlock_pup_dq_array[pbs_cmp_retry][dq];
+			}
+		}
+
+		pup_locked = 0;
+		sum_pup_fail = *pcur_pup;
+
+		/* Check which DQ is failed */
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			/* Summarize the locked pup */
+			pup_locked |= unlock_pup_dq_array[dq];
+
+			/* Check if get fail */
+			sum_pup_fail &= unlock_pup_dq_array[dq];
+		}
+
+		/* If all PUPS are locked in all DQ - Break */
+		if (pup_locked == 0) {
+			/* All pups are locked */
+			*start_over = 0;
+			DEBUG_PBS_FULL_S("DDR3 - PBS Per bit -  All bit in all pups are successfully locked\n");
+			break;
+		}
+
+		/* PBS deskew elements reach max ? */
+		if (pbs_curr_val == last_pbs) {
+			DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PBS deskew elements reach max\n");
+			/* CHIP-ONLY! - Implementation Limitation */
+			*start_over = (sum_pup_fail != 0) && (!(*start_over));
+			*pcur_pup = pup_locked;
+
+			DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - StartOver: ");
+			DEBUG_PBS_FULL_D(*start_over, 1);
+			DEBUG_PBS_FULL_S("  pup_locked: ");
+			DEBUG_PBS_FULL_D(pup_locked, 2);
+			DEBUG_PBS_FULL_S("  sum_pup_fail: ");
+			DEBUG_PBS_FULL_D(sum_pup_fail, 2);
+			DEBUG_PBS_FULL_S("\n");
+
+			/* Lock PBS value for all remaining  bits */
+			for (pup = 0; pup < max_pup; pup++) {
+				/* Check if current pup already received error */
+				if (IS_PUP_ACTIVE(pup_locked, pup) == 1) {
+					/* Valid pup for current function */
+					if (IS_PUP_ACTIVE(sum_pup_fail, pup) ==
+					    1 && (*start_over == 1)) {
+						DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - skipping lock of pup (first loop of pbs)",
+								 pup, 1);
+						continue;
+					} else
+					    if (IS_PUP_ACTIVE(sum_pup_fail, pup)
+						== 1) {
+						DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - Locking pup %d (even though it wasn't supposed to be locked)",
+								 pup, 1);
+					}
+
+					/* Already got fail on the PUP */
+					/* Lock PBS value for all remaining bits */
+					DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Locking remaning DQs for pup - ");
+					DEBUG_PBS_FULL_D(pup, 1);
+					DEBUG_PBS_FULL_S(": ");
+
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						if (IS_PUP_ACTIVE
+						    (unlock_pup_dq_array[dq],
+						     pup) == 1) {
+							DEBUG_PBS_FULL_D(dq, 1);
+							DEBUG_PBS_FULL_S(",");
+							/* set current PBS */
+							skew_array[((pup) *
+								    DQ_NUM) +
+								   dq] =
+							    pbs_curr_val;
+						}
+					}
+
+					if (*start_over == 1) {
+						/*
+						 * Reset this pup bit - when
+						 * restart the PBS, ignore this
+						 * pup
+						 */
+						*pcur_pup &= ~(1 << pup);
+					}
+					DEBUG_PBS_FULL_S("\n");
+				} else {
+					DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Pup ");
+					DEBUG_PBS_FULL_D(pup, 1);
+					DEBUG_PBS_FULL_C(" is not set in puplocked - ",
+							 pup_locked, 1);
+				}
+			}
+
+			/* Need to start the PBS again */
+			if (*start_over == 1) {
+				DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - false fail - returning to start\n");
+				return MV_OK;
+			}
+			break;
+		}
+
+		/* Diff Check */
+		for (pup = 0; pup < max_pup; pup++) {
+			if (IS_PUP_ACTIVE(pup_locked, pup) == 1) {
+				/* pup is not locked */
+				if (first_failed[pup] == 0) {
+					/* No first fail until now */
+					if (IS_PUP_ACTIVE(sum_pup_fail, pup) ==
+					    0) {
+						/* Get first fail */
+						DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - First fail in pup ",
+								 pup, 1);
+						first_failed[pup] = 1;
+						first_fail[pup] = pbs_curr_val;
+					}
+				} else {
+					/* Already got first fail */
+					if (is_tx == 1) {
+						/* TX - inc pbs */
+						calc_pbs_diff =	pbs_curr_val -
+							first_fail[pup];
+					} else {
+						/* RX - dec pbs */
+						calc_pbs_diff = first_fail[pup] -
+							pbs_curr_val;
+					}
+
+					if (calc_pbs_diff >= PBS_DIFF_LIMIT) {
+						lock_pups(pup, &pup_locked,
+							  unlock_pup_dq_array,
+							  pbs_curr_val,
+							  start_pbs, ecc, is_tx);
+					}
+				}
+			}
+		}
+	} while (1);
+
+	return MV_OK;
+}
+
+/*
+ * Name:         ddr3_set_pbs_results
+ * Desc:         Set to HW the PBS phase results.
+ * Args:         is_tx       Indicates whether to set Tx or RX results
+ * Notes:
+ * Returns:      MV_OK if success, other error code if fail.
+ */
+static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx)
+{
+	u32 pup, phys_pup, dq;
+	u32 max_pup;		/* number of valid pups */
+	u32 pbs_min;		/* minimal pbs val per pup */
+	u32 pbs_max;		/* maximum pbs val per pup */
+	u32 val[9];
+
+	max_pup = dram_info->num_of_total_pups;
+	DEBUG_PBS_FULL_S("DDR3 - PBS - ddr3_set_pbs_results:\n");
+
+	/* Loop for all dqs & pups */
+	for (pup = 0; pup < max_pup; pup++) {
+		if (pup == (max_pup - 1) && dram_info->ecc_ena)
+			phys_pup = ECC_PUP;
+		else
+			phys_pup = pup;
+
+		/*
+		 * To minimize delay elements, inc from pbs value the min
+		 * pbs val
+		 */
+		pbs_min = MAX_PBS;
+		pbs_max = 0;
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			if (pbs_min > skew_array[(pup * DQ_NUM) + dq])
+				pbs_min = skew_array[(pup * DQ_NUM) + dq];
+
+			if (pbs_max < skew_array[(pup * DQ_NUM) + dq])
+				pbs_max = skew_array[(pup * DQ_NUM) + dq];
+		}
+
+		pbs_max -= pbs_min;
+
+		DEBUG_PBS_FULL_S("DDR3 - PBS - PUP");
+		DEBUG_PBS_FULL_D(phys_pup, 1);
+		DEBUG_PBS_FULL_S(": Min Val = ");
+		DEBUG_PBS_FULL_D(pbs_min, 2);
+		DEBUG_PBS_FULL_C(", Max Val = ", pbs_max, 2);
+
+		val[pup] = 0;
+
+		for (dq = 0; dq < DQ_NUM; dq++) {
+			int idx;
+			int offs;
+
+			/* Set skew value for all dq */
+			/*
+			 * Bit# Deskew <- Bit# Deskew - last / first
+			 * failing bit Deskew For all bits (per PUP)
+			 * (minimize delay elements)
+			 */
+
+			DEBUG_PBS_FULL_S("DQ");
+			DEBUG_PBS_FULL_D(dq, 1);
+			DEBUG_PBS_FULL_S("-");
+			DEBUG_PBS_FULL_D((skew_array[(pup * DQ_NUM) + dq] -
+					  pbs_min), 2);
+			DEBUG_PBS_FULL_S(", ");
+
+			idx = (pup * DQ_NUM) + dq;
+
+			if (is_tx == 1)
+				offs = PUP_PBS_TX;
+			else
+				offs = PUP_PBS_RX;
+
+			ddr3_write_pup_reg(offs + pbs_dq_mapping[phys_pup][dq],
+					   CS0, phys_pup, 0,
+					   skew_array[idx] - pbs_min);
+
+			if (is_tx == 1)
+				val[pup] += skew_array[idx] - pbs_min;
+		}
+
+		DEBUG_PBS_FULL_S("\n");
+
+		/* Set the DQS the half of the Max PBS of the DQs  */
+		if (is_tx == 1) {
+			ddr3_write_pup_reg(PUP_PBS_TX + 8, CS0, phys_pup, 0,
+					   pbs_max / 2);
+			ddr3_write_pup_reg(PUP_PBS_TX + 0xa, CS0, phys_pup, 0,
+					   val[pup] / 8);
+		} else
+			ddr3_write_pup_reg(PUP_PBS_RX + 8, CS0, phys_pup, 0,
+					   pbs_max / 2);
+	}
+
+	return MV_OK;
+}
+
+static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay)
+{
+	u32 reg, delay;
+
+	reg = (ddr3_read_pup_reg(PUP_WL_MODE, cs, pup) & 0x3FF);
+	delay = reg & PUP_DELAY_MASK;
+	reg |= ((dqs_delay + delay) << REG_PHY_DQS_REF_DLY_OFFS);
+	reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+	reg |= (pup << REG_PHY_PUP_OFFS);
+	reg |= ((0x4 * cs + PUP_WL_MODE) << REG_PHY_CS_OFFS);
+
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+	do {
+		reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+			REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+	} while (reg);	/* Wait for '0' to mark the end of the transaction */
+
+	udelay(10);
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_pbs_patterns(MV_DRAM_INFO *dram_info)
+{
+	u32 cs, cs_count, cs_tmp;
+	u32 sdram_addr;
+	u32 *pattern_ptr0, *pattern_ptr1;
+
+	/* Choose pattern */
+	switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+	case 16:
+		pattern_ptr0 = (u32 *)&pbs_pattern[0];
+		pattern_ptr1 = (u32 *)&pbs_pattern[1];
+		break;
+#endif
+	case 32:
+		pattern_ptr0 = (u32 *)&pbs_pattern_32b[0];
+		pattern_ptr1 = (u32 *)&pbs_pattern_32b[1];
+		break;
+#if defined(MV88F78X60)
+	case 64:
+		pattern_ptr0 = (u32 *)&pbs_pattern_64b[0];
+		pattern_ptr1 = (u32 *)&pbs_pattern_64b[1];
+		break;
+#endif
+	default:
+		return MV_FAIL;
+	}
+
+	/* Loop for each CS */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			cs_count = 0;
+			for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+				if (dram_info->cs_ena & (1 << cs_tmp))
+					cs_count++;
+			}
+
+			/* Init PBS I pattern */
+			sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+				      SDRAM_PBS_I_OFFS);
+			if (MV_OK !=
+			    ddr3_sdram_compare(dram_info, (u32) NULL, NULL,
+					       pattern_ptr0, LEN_STD_PATTERN,
+					       sdram_addr, 1, 0, NULL,
+					       0))
+				return MV_FAIL;
+
+			/* Init PBS II pattern */
+			sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+				      SDRAM_PBS_II_OFFS);
+			if (MV_OK !=
+			    ddr3_sdram_compare(dram_info, (u32) NULL, NULL,
+					       pattern_ptr1, LEN_STD_PATTERN,
+					       sdram_addr, 1, 0, NULL,
+					       0))
+				return MV_FAIL;
+		}
+	}
+
+	return MV_OK;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_read_leveling.c b/drivers/ddr/mvebu/ddr3_read_leveling.c
new file mode 100644
index 0000000..4662bde
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_read_leveling.c
@@ -0,0 +1,1214 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_RL_C(s, d, l) \
+	DEBUG_RL_S(s); DEBUG_RL_D(d, l); DEBUG_RL_S("\n")
+#define DEBUG_RL_FULL_C(s, d, l) \
+	DEBUG_RL_FULL_S(s); DEBUG_RL_FULL_D(d, l); DEBUG_RL_FULL_S("\n")
+
+#ifdef MV_DEBUG_RL
+#define DEBUG_RL_S(s) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_RL_D(d, l) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+#else
+#define DEBUG_RL_S(s)
+#define DEBUG_RL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_RL_FULL
+#define DEBUG_RL_FULL_S(s)		puts(s)
+#define DEBUG_RL_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_RL_FULL_S(s)
+#define DEBUG_RL_FULL_D(d, l)
+#endif
+
+extern u32 rl_pattern[LEN_STD_PATTERN];
+
+#ifdef RL_MODE
+static int ddr3_read_leveling_single_cs_rl_mode(u32 cs, u32 freq,
+						int ratio_2to1, u32 ecc,
+						MV_DRAM_INFO *dram_info);
+#else
+static int ddr3_read_leveling_single_cs_window_mode(u32 cs, u32 freq,
+						    int ratio_2to1, u32 ecc,
+						    MV_DRAM_INFO *dram_info);
+#endif
+
+/*
+ * Name:     ddr3_read_leveling_hw
+ * Desc:     Execute the Read leveling phase by HW
+ * Args:     dram_info - main struct
+ *           freq      - current sequence frequency
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_read_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info)
+{
+	u32 reg;
+
+	/* Debug message - Start Read leveling procedure */
+	DEBUG_RL_S("DDR3 - Read Leveling - Starting HW RL procedure\n");
+
+	/* Start Auto Read Leveling procedure */
+	reg = 1 << REG_DRAM_TRAINING_RL_OFFS;
+	/* Config the retest number */
+	reg |= (COUNT_HW_RL << REG_DRAM_TRAINING_RETEST_OFFS);
+
+	/* Enable CS in the automatic process */
+	reg |= (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS);
+
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+	/* Wait */
+	do {
+		reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+			(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	/* Check if Successful */
+	if (reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+	    (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+		u32 delay, phase, pup, cs;
+
+		dram_info->rl_max_phase = 0;
+		dram_info->rl_min_phase = 10;
+
+		/* Read results to arrays */
+		for (cs = 0; cs < MAX_CS; cs++) {
+			if (dram_info->cs_ena & (1 << cs)) {
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups
+					    && dram_info->ecc_ena)
+						pup = ECC_PUP;
+					reg =
+					    ddr3_read_pup_reg(PUP_RL_MODE, cs,
+							      pup);
+					phase = (reg >> REG_PHY_PHASE_OFFS) &
+						PUP_PHASE_MASK;
+					delay = reg & PUP_DELAY_MASK;
+					dram_info->rl_val[cs][pup][P] = phase;
+					if (phase > dram_info->rl_max_phase)
+						dram_info->rl_max_phase = phase;
+					if (phase < dram_info->rl_min_phase)
+						dram_info->rl_min_phase = phase;
+					dram_info->rl_val[cs][pup][D] = delay;
+					dram_info->rl_val[cs][pup][S] =
+					    RL_FINAL_STATE;
+					reg =
+					    ddr3_read_pup_reg(PUP_RL_MODE + 0x1,
+							      cs, pup);
+					dram_info->rl_val[cs][pup][DQS] =
+					    (reg & 0x3F);
+				}
+#ifdef MV_DEBUG_RL
+				/* Print results */
+				DEBUG_RL_C("DDR3 - Read Leveling - Results for CS - ",
+					   (u32) cs, 1);
+
+				for (pup = 0;
+				     pup < (dram_info->num_of_total_pups);
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups
+					    && dram_info->ecc_ena)
+						pup = ECC_PUP;
+					DEBUG_RL_S("DDR3 - Read Leveling - PUP: ");
+					DEBUG_RL_D((u32) pup, 1);
+					DEBUG_RL_S(", Phase: ");
+					DEBUG_RL_D((u32) dram_info->
+						   rl_val[cs][pup][P], 1);
+					DEBUG_RL_S(", Delay: ");
+					DEBUG_RL_D((u32) dram_info->
+						   rl_val[cs][pup][D], 2);
+					DEBUG_RL_S("\n");
+				}
+#endif
+			}
+		}
+
+		dram_info->rd_rdy_dly =
+			reg_read(REG_READ_DATA_READY_DELAYS_ADDR) &
+			REG_READ_DATA_SAMPLE_DELAYS_MASK;
+		dram_info->rd_smpl_dly =
+			reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR) &
+			REG_READ_DATA_READY_DELAYS_MASK;
+#ifdef MV_DEBUG_RL
+		DEBUG_RL_C("DDR3 - Read Leveling - Read Sample Delay: ",
+			   dram_info->rd_smpl_dly, 2);
+		DEBUG_RL_C("DDR3 - Read Leveling - Read Ready Delay: ",
+			   dram_info->rd_rdy_dly, 2);
+		DEBUG_RL_S("DDR3 - Read Leveling - HW RL Ended Successfully\n");
+#endif
+		return MV_OK;
+
+	} else {
+		DEBUG_RL_S("DDR3 - Read Leveling - HW RL Error\n");
+		return MV_FAIL;
+	}
+}
+
+/*
+ * Name:     ddr3_read_leveling_sw
+ * Desc:     Execute the Read leveling phase by SW
+ * Args:     dram_info - main struct
+ *           freq      - current sequence frequency
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_read_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+	u32 reg, cs, ecc, pup_num, phase, delay, pup;
+	int status;
+
+	/* Debug message - Start Read leveling procedure */
+	DEBUG_RL_S("DDR3 - Read Leveling - Starting SW RL procedure\n");
+
+	/* Enable SW Read Leveling */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_RL_MODE_OFFS);
+	/* [0]=1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+#ifdef RL_MODE
+	reg = (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS) |
+		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+#endif
+
+	/* Loop for each CS */
+	for (cs = 0; cs < dram_info->num_cs; cs++) {
+		DEBUG_RL_C("DDR3 - Read Leveling - CS - ", (u32) cs, 1);
+
+		for (ecc = 0; ecc <= (dram_info->ecc_ena); ecc++) {
+			/* ECC Support - Switch ECC Mux on ecc=1 */
+			reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+				~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+			reg |= (dram_info->ecc_ena *
+				ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+			reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+			if (ecc)
+				DEBUG_RL_S("DDR3 - Read Leveling - ECC Mux Enabled\n");
+			else
+				DEBUG_RL_S("DDR3 - Read Leveling - ECC Mux Disabled\n");
+
+			/* Set current sample delays */
+			reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+				 (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			reg |= (dram_info->cl <<
+				(REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+			reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+			/* Set current Ready delay */
+			reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+			reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+				 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			if (!ratio_2to1) {
+				/* 1:1 mode */
+				reg |= ((dram_info->cl + 1) <<
+					(REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			} else {
+				/* 2:1 mode */
+				reg |= ((dram_info->cl + 2) <<
+					(REG_READ_DATA_READY_DELAYS_OFFS * cs));
+			}
+			reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+
+			/* Read leveling Single CS[cs] */
+#ifdef RL_MODE
+			status =
+			    ddr3_read_leveling_single_cs_rl_mode(cs, freq,
+								 ratio_2to1,
+								 ecc,
+								 dram_info);
+			if (MV_OK != status)
+				return status;
+#else
+			status =
+			    ddr3_read_leveling_single_cs_window_mode(cs, freq,
+								     ratio_2to1,
+								     ecc,
+								     dram_info)
+			    if (MV_OK != status)
+				return status;
+#endif
+		}
+
+		/* Print results */
+		DEBUG_RL_C("DDR3 - Read Leveling - Results for CS - ", (u32) cs,
+			   1);
+
+		for (pup = 0;
+		     pup < (dram_info->num_of_std_pups + dram_info->ecc_ena);
+		     pup++) {
+			DEBUG_RL_S("DDR3 - Read Leveling - PUP: ");
+			DEBUG_RL_D((u32) pup, 1);
+			DEBUG_RL_S(", Phase: ");
+			DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][P], 1);
+			DEBUG_RL_S(", Delay: ");
+			DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][D], 2);
+			DEBUG_RL_S("\n");
+		}
+
+		DEBUG_RL_C("DDR3 - Read Leveling - Read Sample Delay: ",
+			   dram_info->rd_smpl_dly, 2);
+		DEBUG_RL_C("DDR3 - Read Leveling - Read Ready Delay: ",
+			   dram_info->rd_rdy_dly, 2);
+
+		/* Configure PHY with average of 3 locked leveling settings */
+		for (pup = 0;
+		     pup < (dram_info->num_of_std_pups + dram_info->ecc_ena);
+		     pup++) {
+			/* ECC support - bit 8 */
+			pup_num = (pup == dram_info->num_of_std_pups) ? ECC_BIT : pup;
+
+			/* For now, set last cnt result */
+			phase = dram_info->rl_val[cs][pup][P];
+			delay = dram_info->rl_val[cs][pup][D];
+			ddr3_write_pup_reg(PUP_RL_MODE, cs, pup_num, phase,
+					   delay);
+		}
+	}
+
+	/* Reset PHY read FIFO */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	do {
+		reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+			(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	/* ECC Support - Switch ECC Mux off ecc=0 */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+#ifdef RL_MODE
+	reg_write(REG_DRAM_TRAINING_ADDR, 0);	/* 0x15B0 - Training Register */
+#endif
+
+	/* Disable SW Read Leveling */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* [0] = 0 - Disable SW override  */
+	reg = (reg | (0x1 << REG_DRAM_TRAINING_2_RL_MODE_OFFS));
+	/* [3] = 1 - Disable RL MODE */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	DEBUG_RL_S("DDR3 - Read Leveling - Finished RL procedure for all CS\n");
+	return MV_OK;
+}
+
+#ifdef RL_MODE
+/*
+ * overrun() extracted from ddr3_read_leveling_single_cs_rl_mode().
+ * This just got too much indented making it hard to read / edit.
+ */
+static void overrun(u32 cs, MV_DRAM_INFO *info, u32 pup, u32 locked_pups,
+		    u32 *locked_sum, u32 ecc, int *first_octet_locked,
+		    int *counter_in_progress, int final_delay, u32 delay,
+		    u32 phase)
+{
+	/* If no OverRun */
+	if (((~locked_pups >> pup) & 0x1) && (final_delay == 0)) {
+		int idx;
+
+		idx = pup + ecc * ECC_BIT;
+
+		/* PUP passed, start examining */
+		if (info->rl_val[cs][idx][S] == RL_UNLOCK_STATE) {
+			/* Must be RL_UNLOCK_STATE */
+			/* Match expected value ? - Update State Machine */
+			if (info->rl_val[cs][idx][C] < RL_RETRY_COUNT) {
+				DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have no overrun and a match on pup: ",
+						(u32)pup, 1);
+				info->rl_val[cs][idx][C]++;
+
+				/* If pup got to last state - lock the delays */
+				if (info->rl_val[cs][idx][C] == RL_RETRY_COUNT) {
+					info->rl_val[cs][idx][C] = 0;
+					info->rl_val[cs][idx][DS] = delay;
+					info->rl_val[cs][idx][PS] = phase;
+
+					/* Go to Final State */
+					info->rl_val[cs][idx][S] = RL_FINAL_STATE;
+					*locked_sum = *locked_sum + 1;
+					DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have locked pup: ",
+							(u32)pup, 1);
+
+					/*
+					 * If first lock - need to lock delays
+					 */
+					if (*first_octet_locked == 0) {
+						DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got first lock on pup: ",
+								(u32)pup, 1);
+						*first_octet_locked = 1;
+					}
+
+					/*
+					 * If pup is in not in final state but
+					 * there was match - dont increment
+					 * counter
+					 */
+				} else {
+					*counter_in_progress = 1;
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Name:     ddr3_read_leveling_single_cs_rl_mode
+ * Desc:     Execute Read leveling for single Chip select
+ * Args:     cs        - current chip select
+ *           freq      - current sequence frequency
+ *           ecc       - ecc iteration indication
+ *           dram_info - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_read_leveling_single_cs_rl_mode(u32 cs, u32 freq,
+						int ratio_2to1, u32 ecc,
+						MV_DRAM_INFO *dram_info)
+{
+	u32 reg, delay, phase, pup, rd_sample_delay, add, locked_pups,
+		repeat_max_cnt, sdram_offset, locked_sum;
+	u32 phase_min, ui_max_delay;
+	int all_locked, first_octet_locked, counter_in_progress;
+	int final_delay = 0;
+
+	DEBUG_RL_FULL_C("DDR3 - Read Leveling - Single CS - ", (u32) cs, 1);
+
+	/* Init values */
+	phase = 0;
+	delay = 0;
+	rd_sample_delay = dram_info->cl;
+	all_locked = 0;
+	first_octet_locked = 0;
+	repeat_max_cnt = 0;
+	locked_sum = 0;
+
+	for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+	     pup++)
+		dram_info->rl_val[cs][pup + ecc * ECC_BIT][S] = 0;
+
+	/* Main loop */
+	while (!all_locked) {
+		counter_in_progress = 0;
+
+		DEBUG_RL_FULL_S("DDR3 - Read Leveling - RdSmplDly = ");
+		DEBUG_RL_FULL_D(rd_sample_delay, 2);
+		DEBUG_RL_FULL_S(", RdRdyDly = ");
+		DEBUG_RL_FULL_D(dram_info->rd_rdy_dly, 2);
+		DEBUG_RL_FULL_S(", Phase = ");
+		DEBUG_RL_FULL_D(phase, 1);
+		DEBUG_RL_FULL_S(", Delay = ");
+		DEBUG_RL_FULL_D(delay, 2);
+		DEBUG_RL_FULL_S("\n");
+
+		/*
+		 * Broadcast to all PUPs current RL delays: DQS phase,
+		 * leveling delay
+		 */
+		ddr3_write_pup_reg(PUP_RL_MODE, cs, PUP_BC, phase, delay);
+
+		/* Reset PHY read FIFO */
+		reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+			(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+		/* 0x15B8 - Training SW 2 Register */
+		reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+		do {
+			reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+				(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+		} while (reg);	/* Wait for '0' */
+
+		/* Read pattern from SDRAM */
+		sdram_offset = cs * (SDRAM_CS_SIZE + 1) + SDRAM_RL_OFFS;
+		locked_pups = 0;
+		if (MV_OK !=
+		    ddr3_sdram_compare(dram_info, 0xFF, &locked_pups,
+				       rl_pattern, LEN_STD_PATTERN,
+				       sdram_offset, 0, 0, NULL, 0))
+			return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PATTERN;
+
+		/* Octet evaluation */
+		/* pup_num = Q or 1 for ECC */
+		for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+			/* Check Overrun */
+			if (!((reg_read(REG_DRAM_TRAINING_2_ADDR) >>
+			       (REG_DRAM_TRAINING_2_OVERRUN_OFFS + pup)) & 0x1)) {
+				overrun(cs, dram_info, pup, locked_pups,
+					&locked_sum, ecc, &first_octet_locked,
+					&counter_in_progress, final_delay,
+					delay, phase);
+			} else {
+				DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got overrun on pup: ",
+						(u32)pup, 1);
+			}
+		}
+
+		if (locked_sum == (dram_info->num_of_std_pups *
+				   (1 - ecc) + ecc)) {
+			all_locked = 1;
+			DEBUG_RL_FULL_S("DDR3 - Read Leveling - Single Cs - All pups locked\n");
+		}
+
+		/*
+		 * This is a fix for unstable condition where pups are
+		 * toggling between match and no match
+		 */
+		/*
+		 * If some of the pups is >1 <3, check if we did it too
+		 * many times
+		 */
+		if (counter_in_progress == 1) {
+			/* Notify at least one Counter is >=1 and < 3 */
+			if (repeat_max_cnt < RL_RETRY_COUNT) {
+				repeat_max_cnt++;
+				counter_in_progress = 1;
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - Counter is >=1 and <3\n");
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - So we will not increment the delay to see if locked again\n");
+			} else {
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - repeat_max_cnt reached max so now we will increment the delay\n");
+				counter_in_progress = 0;
+			}
+		}
+
+		/*
+		 * Check some of the pups are in the middle of state machine
+		 * and don't increment the delays
+		 */
+		if (!counter_in_progress && !all_locked) {
+			int idx;
+
+			idx = pup + ecc * ECC_BIT;
+
+			repeat_max_cnt = 0;
+			/* if 1:1 mode */
+			if ((!ratio_2to1) && ((phase == 0) || (phase == 4)))
+				ui_max_delay = MAX_DELAY_INV;
+			else
+				ui_max_delay = MAX_DELAY;
+
+			/* Increment Delay */
+			if (delay < ui_max_delay) {
+				delay++;
+				/*
+				 * Mark the last delay/pahse place for
+				 * window final place
+				 */
+				if (delay == ui_max_delay) {
+					if ((!ratio_2to1 && phase ==
+					     MAX_PHASE_RL_L_1TO1)
+					    || (ratio_2to1 && phase ==
+						MAX_PHASE_RL_L_2TO1))
+						final_delay = 1;
+				}
+			} else {
+				/* Phase+CL Incrementation */
+				delay = 0;
+
+				if (!ratio_2to1) {
+					/* 1:1 mode */
+					if (first_octet_locked) {
+						/* some Pup was Locked */
+						if (phase < MAX_PHASE_RL_L_1TO1) {
+							if (phase == 1) {
+								phase = 4;
+							} else {
+								phase++;
+								delay = MIN_DELAY_PHASE_1_LIMIT;
+							}
+						} else {
+							DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+							DEBUG_RL_S("1)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked n");
+							return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK;
+						}
+					} else {
+						/* NO Pup was Locked */
+						if (phase < MAX_PHASE_RL_UL_1TO1) {
+							phase++;
+							delay =
+							    MIN_DELAY_PHASE_1_LIMIT;
+						} else {
+							phase = 0;
+						}
+					}
+				} else {
+					/* 2:1 mode */
+					if (first_octet_locked) {
+						/* some Pup was Locked */
+						if (phase < MAX_PHASE_RL_L_2TO1) {
+							phase++;
+						} else {
+							DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+							DEBUG_RL_S("2)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+							for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+								/* pup_num = Q or 1 for ECC */
+								if (dram_info->rl_val[cs][idx][S]
+								    == 0) {
+									DEBUG_RL_C("Failed byte is = ",
+										   pup, 1);
+								}
+							}
+							return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK;
+						}
+					} else {
+						/* No Pup was Locked */
+						if (phase < MAX_PHASE_RL_UL_2TO1)
+							phase++;
+						else
+							phase = 0;
+					}
+				}
+
+				/*
+				 * If we finished a full Phases cycle (so now
+				 * phase = 0, need to increment rd_sample_dly
+				 */
+				if (phase == 0 && first_octet_locked == 0) {
+					rd_sample_delay++;
+					if (rd_sample_delay == 0x10) {
+						DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+						DEBUG_RL_S("3)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+						for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+							/* pup_num = Q or 1 for ECC */
+							if (dram_info->
+							    rl_val[cs][idx][S] == 0) {
+								DEBUG_RL_C("Failed byte is = ",
+									   pup, 1);
+							}
+						}
+						return MV_DDR3_TRAINING_ERR_RD_LVL_PUP_UNLOCK;
+					}
+
+					/* Set current rd_sample_delay  */
+					reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+					reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK
+					      << (REG_READ_DATA_SAMPLE_DELAYS_OFFS
+						  * cs));
+					reg |= (rd_sample_delay <<
+						(REG_READ_DATA_SAMPLE_DELAYS_OFFS *
+						 cs));
+					reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR,
+						  reg);
+				}
+
+				/*
+				 * Set current rdReadyDelay according to the
+				 * hash table (Need to do this in every phase
+				 * change)
+				 */
+				if (!ratio_2to1) {
+					/* 1:1 mode */
+					add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+					switch (phase) {
+					case 0:
+						add = (add >>
+						       REG_TRAINING_DEBUG_2_OFFS);
+						break;
+					case 1:
+						add = (add >>
+						       (REG_TRAINING_DEBUG_2_OFFS
+							+ 3));
+						break;
+					case 4:
+						add = (add >>
+						       (REG_TRAINING_DEBUG_2_OFFS
+							+ 6));
+						break;
+					case 5:
+						add = (add >>
+						       (REG_TRAINING_DEBUG_2_OFFS
+							+ 9));
+						break;
+					}
+					add &= REG_TRAINING_DEBUG_2_MASK;
+				} else {
+					/* 2:1 mode */
+					add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+					add = (add >>
+					       (phase *
+						REG_TRAINING_DEBUG_3_OFFS));
+					add &= REG_TRAINING_DEBUG_3_MASK;
+				}
+
+				reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+				reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+					 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+				reg |= ((rd_sample_delay + add) <<
+					(REG_READ_DATA_READY_DELAYS_OFFS * cs));
+				reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+				dram_info->rd_smpl_dly = rd_sample_delay;
+				dram_info->rd_rdy_dly = rd_sample_delay + add;
+			}
+
+			/* Reset counters for pups with states<RD_STATE_COUNT */
+			for (pup = 0; pup <
+				     (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+			     pup++) {
+				if (dram_info->rl_val[cs][idx][C] < RL_RETRY_COUNT)
+					dram_info->rl_val[cs][idx][C] = 0;
+			}
+		}
+	}
+
+	phase_min = 10;
+
+	for (pup = 0; pup < (dram_info->num_of_std_pups); pup++) {
+		if (dram_info->rl_val[cs][pup][PS] < phase_min)
+			phase_min = dram_info->rl_val[cs][pup][PS];
+	}
+
+	/*
+	 * Set current rdReadyDelay according to the hash table (Need to
+	 * do this in every phase change)
+	 */
+	if (!ratio_2to1) {
+		/* 1:1 mode */
+		add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+		switch (phase_min) {
+		case 0:
+			add = (add >> REG_TRAINING_DEBUG_2_OFFS);
+			break;
+		case 1:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 3));
+			break;
+		case 4:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 6));
+			break;
+		case 5:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 9));
+			break;
+		}
+		add &= REG_TRAINING_DEBUG_2_MASK;
+	} else {
+		/* 2:1 mode */
+		add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+		add = (add >> (phase_min * REG_TRAINING_DEBUG_3_OFFS));
+		add &= REG_TRAINING_DEBUG_3_MASK;
+	}
+
+	reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+	reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+		 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+	reg |= ((rd_sample_delay + add) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+	reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+	dram_info->rd_rdy_dly = rd_sample_delay + add;
+
+	for (cs = 0; cs < dram_info->num_cs; cs++) {
+		for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+			reg = ddr3_read_pup_reg(PUP_RL_MODE + 0x1, cs, pup);
+			dram_info->rl_val[cs][pup][DQS] = (reg & 0x3F);
+		}
+	}
+
+	return MV_OK;
+}
+
+#else
+
+/*
+ * Name:     ddr3_read_leveling_single_cs_window_mode
+ * Desc:     Execute Read leveling for single Chip select
+ * Args:     cs        - current chip select
+ *           freq      - current sequence frequency
+ *           ecc       - ecc iteration indication
+ *           dram_info - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_read_leveling_single_cs_window_mode(u32 cs, u32 freq,
+						    int ratio_2to1, u32 ecc,
+						    MV_DRAM_INFO *dram_info)
+{
+	u32 reg, delay, phase, sum, pup, rd_sample_delay, add, locked_pups,
+	    repeat_max_cnt, sdram_offset, final_sum, locked_sum;
+	u32 delay_s, delay_e, tmp, phase_min, ui_max_delay;
+	int all_locked, first_octet_locked, counter_in_progress;
+	int final_delay = 0;
+
+	DEBUG_RL_FULL_C("DDR3 - Read Leveling - Single CS - ", (u32) cs, 1);
+
+	/* Init values */
+	phase = 0;
+	delay = 0;
+	rd_sample_delay = dram_info->cl;
+	all_locked = 0;
+	first_octet_locked = 0;
+	repeat_max_cnt = 0;
+	sum = 0;
+	final_sum = 0;
+	locked_sum = 0;
+
+	for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+	     pup++)
+		dram_info->rl_val[cs][pup + ecc * ECC_BIT][S] = 0;
+
+	/* Main loop */
+	while (!all_locked) {
+		counter_in_progress = 0;
+
+		DEBUG_RL_FULL_S("DDR3 - Read Leveling - RdSmplDly = ");
+		DEBUG_RL_FULL_D(rd_sample_delay, 2);
+		DEBUG_RL_FULL_S(", RdRdyDly = ");
+		DEBUG_RL_FULL_D(dram_info->rd_rdy_dly, 2);
+		DEBUG_RL_FULL_S(", Phase = ");
+		DEBUG_RL_FULL_D(phase, 1);
+		DEBUG_RL_FULL_S(", Delay = ");
+		DEBUG_RL_FULL_D(delay, 2);
+		DEBUG_RL_FULL_S("\n");
+
+		/*
+		 * Broadcast to all PUPs current RL delays: DQS phase,leveling
+		 * delay
+		 */
+		ddr3_write_pup_reg(PUP_RL_MODE, cs, PUP_BC, phase, delay);
+
+		/* Reset PHY read FIFO */
+		reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+			(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+		/* 0x15B8 - Training SW 2 Register */
+		reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+		do {
+			reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+				(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+		} while (reg);	/* Wait for '0' */
+
+		/* Read pattern from SDRAM */
+		sdram_offset = cs * (SDRAM_CS_SIZE + 1) + SDRAM_RL_OFFS;
+		locked_pups = 0;
+		if (MV_OK !=
+		    ddr3_sdram_compare(dram_info, 0xFF, &locked_pups,
+				       rl_pattern, LEN_STD_PATTERN,
+				       sdram_offset, 0, 0, NULL, 0))
+			return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PATTERN;
+
+		/* Octet evaluation */
+		for (pup = 0; pup < (dram_info->num_of_std_pups *
+				     (1 - ecc) + ecc); pup++) {
+			/* pup_num = Q or 1 for ECC */
+			int idx;
+
+			idx = pup + ecc * ECC_BIT;
+
+			/* Check Overrun */
+			if (!((reg_read(REG_DRAM_TRAINING_2_ADDR) >>
+			      (REG_DRAM_TRAINING_2_OVERRUN_OFFS +
+			       pup)) & 0x1)) {
+				/* If no OverRun */
+
+				/* Inside the window */
+				if (dram_info->rl_val[cs][idx][S] == RL_WINDOW_STATE) {
+					/*
+					 * Match expected value ? - Update
+					 * State Machine
+					 */
+					if (((~locked_pups >> pup) & 0x1)
+					    && (final_delay == 0)) {
+						/* Match - Still inside the Window */
+						DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got another match inside the window  for pup: ",
+								(u32)pup, 1);
+
+					} else {
+						/* We got fail -> this is the end of the window */
+						dram_info->rl_val[cs][idx][DE] = delay;
+						dram_info->rl_val[cs][idx][PE] = phase;
+						/* Go to Final State */
+						dram_info->rl_val[cs][idx][S]++;
+						final_sum++;
+						DEBUG_RL_FULL_C("DDR3 - Read Leveling - We finished the window for pup: ",
+								(u32)pup, 1);
+					}
+
+					/* Before the start of the window */
+				} else if (dram_info->rl_val[cs][idx][S] ==
+					   RL_UNLOCK_STATE) {
+					/* Must be RL_UNLOCK_STATE */
+					/*
+					 * Match expected value ? - Update
+					 * State Machine
+					 */
+					if (dram_info->rl_val[cs][idx][C] <
+					    RL_RETRY_COUNT) {
+						if (((~locked_pups >> pup) & 0x1)) {
+							/* Match */
+							DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have no overrun and a match on pup: ",
+									(u32)pup, 1);
+							dram_info->rl_val[cs][idx][C]++;
+
+							/* If pup got to last state - lock the delays */
+							if (dram_info->rl_val[cs][idx][C] ==
+							    RL_RETRY_COUNT) {
+								dram_info->rl_val[cs][idx][C] = 0;
+								dram_info->rl_val[cs][idx][DS] =
+									delay;
+								dram_info->rl_val[cs][idx][PS] =
+									phase;
+								dram_info->rl_val[cs][idx][S]++;	/* Go to Window State */
+								locked_sum++;
+								/* Will count the pups that got locked */
+
+								/* IF First lock - need to lock delays */
+								if (first_octet_locked == 0) {
+									DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got first lock on pup: ",
+											(u32)pup, 1);
+									first_octet_locked
+									    =
+									    1;
+								}
+							}
+
+							/* if pup is in not in final state but there was match - dont increment counter */
+							else {
+								counter_in_progress
+								    = 1;
+							}
+						}
+					}
+				}
+			} else {
+				DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got overrun on pup: ",
+						(u32)pup, 1);
+				counter_in_progress = 1;
+			}
+		}
+
+		if (final_sum == (dram_info->num_of_std_pups * (1 - ecc) + ecc)) {
+			all_locked = 1;
+			DEBUG_RL_FULL_S("DDR3 - Read Leveling - Single Cs - All pups locked\n");
+		}
+
+		/*
+		 * This is a fix for unstable condition where pups are
+		 * toggling between match and no match
+		 */
+		/*
+		 * If some of the pups is >1 <3, check if we did it too many
+		 * times
+		 */
+		if (counter_in_progress == 1) {
+			if (repeat_max_cnt < RL_RETRY_COUNT) {
+				/* Notify at least one Counter is >=1 and < 3 */
+				repeat_max_cnt++;
+				counter_in_progress = 1;
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - Counter is >=1 and <3\n");
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - So we will not increment the delay to see if locked again\n");
+			} else {
+				DEBUG_RL_FULL_S("DDR3 - Read Leveling - repeat_max_cnt reached max so now we will increment the delay\n");
+				counter_in_progress = 0;
+			}
+		}
+
+		/*
+		 * Check some of the pups are in the middle of state machine
+		 * and don't increment the delays
+		 */
+		if (!counter_in_progress && !all_locked) {
+			repeat_max_cnt = 0;
+			if (!ratio_2to1)
+				ui_max_delay = MAX_DELAY_INV;
+			else
+				ui_max_delay = MAX_DELAY;
+
+			/* Increment Delay */
+			if (delay < ui_max_delay) {
+				/* Delay Incrementation */
+				delay++;
+				if (delay == ui_max_delay) {
+					/*
+					 * Mark the last delay/pahse place
+					 * for window final place
+					 */
+					if ((!ratio_2to1
+					     && phase == MAX_PHASE_RL_L_1TO1)
+					    || (ratio_2to1
+						&& phase ==
+						MAX_PHASE_RL_L_2TO1))
+						final_delay = 1;
+				}
+			} else {
+				/* Phase+CL Incrementation */
+				delay = 0;
+				if (!ratio_2to1) {
+					/* 1:1 mode */
+					if (first_octet_locked) {
+						/* some pupet was Locked */
+						if (phase < MAX_PHASE_RL_L_1TO1) {
+#ifdef RL_WINDOW_WA
+							if (phase == 0)
+#else
+							if (phase == 1)
+#endif
+								phase = 4;
+							else
+								phase++;
+						} else {
+							DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+							return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PUP_UNLOCK;
+						}
+					} else {
+						/* No Pup was Locked */
+						if (phase < MAX_PHASE_RL_UL_1TO1) {
+#ifdef RL_WINDOW_WA
+							if (phase == 0)
+								phase = 4;
+#else
+							phase++;
+#endif
+						} else
+							phase = 0;
+					}
+				} else {
+					/* 2:1 mode */
+					if (first_octet_locked) {
+						/* Some Pup was Locked */
+						if (phase < MAX_PHASE_RL_L_2TO1) {
+							phase++;
+						} else {
+							DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+							return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PUP_UNLOCK;
+						}
+					} else {
+						/* No Pup was Locked */
+						if (phase < MAX_PHASE_RL_UL_2TO1)
+							phase++;
+						else
+							phase = 0;
+					}
+				}
+
+				/*
+				 * If we finished a full Phases cycle (so
+				 * now phase = 0, need to increment
+				 * rd_sample_dly
+				 */
+				if (phase == 0 && first_octet_locked == 0) {
+					rd_sample_delay++;
+
+					/* Set current rd_sample_delay  */
+					reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+					reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+						 (REG_READ_DATA_SAMPLE_DELAYS_OFFS
+						  * cs));
+					reg |= (rd_sample_delay <<
+						(REG_READ_DATA_SAMPLE_DELAYS_OFFS *
+						 cs));
+					reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR,
+						  reg);
+				}
+
+				/*
+				 * Set current rdReadyDelay according to the
+				 * hash table (Need to do this in every phase
+				 * change)
+				 */
+				if (!ratio_2to1) {
+					/* 1:1 mode */
+					add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+					switch (phase) {
+					case 0:
+						add = add >>
+							REG_TRAINING_DEBUG_2_OFFS;
+						break;
+					case 1:
+						add = add >>
+							(REG_TRAINING_DEBUG_2_OFFS
+							 + 3);
+						break;
+					case 4:
+						add = add >>
+							(REG_TRAINING_DEBUG_2_OFFS
+							 + 6);
+						break;
+					case 5:
+						add = add >>
+							(REG_TRAINING_DEBUG_2_OFFS
+							 + 9);
+						break;
+					}
+				} else {
+					/* 2:1 mode */
+					add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+					add = (add >> phase *
+					       REG_TRAINING_DEBUG_3_OFFS);
+				}
+				add &= REG_TRAINING_DEBUG_2_MASK;
+				reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+				reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+					 (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+				reg |= ((rd_sample_delay + add) <<
+					(REG_READ_DATA_READY_DELAYS_OFFS * cs));
+				reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+				dram_info->rd_smpl_dly = rd_sample_delay;
+				dram_info->rd_rdy_dly = rd_sample_delay + add;
+			}
+
+			/* Reset counters for pups with states<RD_STATE_COUNT */
+			for (pup = 0;
+			     pup <
+			     (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+			     pup++) {
+				if (dram_info->rl_val[cs][idx][C] < RL_RETRY_COUNT)
+					dram_info->rl_val[cs][idx][C] = 0;
+			}
+		}
+	}
+
+	phase_min = 10;
+
+	for (pup = 0; pup < (dram_info->num_of_std_pups); pup++) {
+		DEBUG_RL_S("DDR3 - Read Leveling - Window info - PUP: ");
+		DEBUG_RL_D((u32) pup, 1);
+		DEBUG_RL_S(", PS: ");
+		DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][PS], 1);
+		DEBUG_RL_S(", DS: ");
+		DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][DS], 2);
+		DEBUG_RL_S(", PE: ");
+		DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][PE], 1);
+		DEBUG_RL_S(", DE: ");
+		DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][DE], 2);
+		DEBUG_RL_S("\n");
+	}
+
+	/* Find center of the window procedure */
+	for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+	     pup++) {
+#ifdef RL_WINDOW_WA
+		if (!ratio_2to1) {	/* 1:1 mode */
+			if (dram_info->rl_val[cs][idx][PS] == 4)
+				dram_info->rl_val[cs][idx][PS] = 1;
+			if (dram_info->rl_val[cs][idx][PE] == 4)
+				dram_info->rl_val[cs][idx][PE] = 1;
+
+			delay_s = dram_info->rl_val[cs][idx][PS] *
+				MAX_DELAY_INV + dram_info->rl_val[cs][idx][DS];
+			delay_e = dram_info->rl_val[cs][idx][PE] *
+				MAX_DELAY_INV + dram_info->rl_val[cs][idx][DE];
+
+			tmp = (delay_e - delay_s) / 2 + delay_s;
+			phase = tmp / MAX_DELAY_INV;
+			if (phase == 1)	/* 1:1 mode */
+				phase = 4;
+
+			if (phase < phase_min)	/* for the read ready delay */
+				phase_min = phase;
+
+			dram_info->rl_val[cs][idx][P] = phase;
+			dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY_INV;
+
+		} else {
+			delay_s = dram_info->rl_val[cs][idx][PS] *
+				MAX_DELAY + dram_info->rl_val[cs][idx][DS];
+			delay_e = dram_info->rl_val[cs][idx][PE] *
+				MAX_DELAY + dram_info->rl_val[cs][idx][DE];
+
+			tmp = (delay_e - delay_s) / 2 + delay_s;
+			phase = tmp / MAX_DELAY;
+
+			if (phase < phase_min)	/* for the read ready delay */
+				phase_min = phase;
+
+			dram_info->rl_val[cs][idx][P] = phase;
+			dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY;
+		}
+#else
+		if (!ratio_2to1) {	/* 1:1 mode */
+			if (dram_info->rl_val[cs][idx][PS] > 1)
+				dram_info->rl_val[cs][idx][PS] -= 2;
+			if (dram_info->rl_val[cs][idx][PE] > 1)
+				dram_info->rl_val[cs][idx][PE] -= 2;
+		}
+
+		delay_s = dram_info->rl_val[cs][idx][PS] * MAX_DELAY +
+			dram_info->rl_val[cs][idx][DS];
+		delay_e = dram_info->rl_val[cs][idx][PE] * MAX_DELAY +
+			dram_info->rl_val[cs][idx][DE];
+
+		tmp = (delay_e - delay_s) / 2 + delay_s;
+		phase = tmp / MAX_DELAY;
+		if (!ratio_2to1 && phase > 1)	/* 1:1 mode */
+			phase += 2;
+
+		if (phase < phase_min)	/* for the read ready delay */
+			phase_min = phase;
+
+		dram_info->rl_val[cs][idx][P] = phase;
+		dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY;
+#endif
+	}
+
+	/* Set current rdReadyDelay according to the hash table (Need to do this in every phase change) */
+	if (!ratio_2to1) {	/* 1:1 mode */
+		add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+		switch (phase_min) {
+		case 0:
+			add = (add >> REG_TRAINING_DEBUG_2_OFFS);
+			break;
+		case 1:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 3));
+			break;
+		case 4:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 6));
+			break;
+		case 5:
+			add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 9));
+			break;
+		}
+	} else {		/* 2:1 mode */
+		add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+		add = (add >> phase_min * REG_TRAINING_DEBUG_3_OFFS);
+	}
+
+	add &= REG_TRAINING_DEBUG_2_MASK;
+	reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+	reg &=
+	    ~(REG_READ_DATA_READY_DELAYS_MASK <<
+	      (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+	reg |=
+	    ((rd_sample_delay + add) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+	reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+	dram_info->rd_rdy_dly = rd_sample_delay + add;
+
+	for (cs = 0; cs < dram_info->num_cs; cs++) {
+		for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+			reg = ddr3_read_pup_reg(PUP_RL_MODE + 0x1, cs, pup);
+			dram_info->rl_val[cs][pup][DQS] = (reg & 0x3F);
+		}
+	}
+
+	return MV_OK;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_sdram.c b/drivers/ddr/mvebu/ddr3_sdram.c
new file mode 100644
index 0000000..50c1bf8
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_sdram.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+#include "xor.h"
+#include "xor_regs.h"
+
+static void ddr3_flush_l1_line(u32 line);
+
+extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN];
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+#if defined(MV88F78X60)
+extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN];
+#endif
+extern u32 pbs_dq_mapping[PUP_NUM_64BIT][DQ_NUM];
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+/* PBS locked dq (per pup) */
+u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM] = { { 0 } };
+u32 pbs_locked_dm[MAX_PUP_NUM] = { 0 };
+u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM] = { { 0 } };
+
+int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#endif
+
+static u32 sdram_data[LEN_KILLER_PATTERN] __aligned(32) = { 0 };
+
+static struct crc_dma_desc dma_desc __aligned(32) = { 0 };
+
+#define XOR_TIMEOUT 0x8000000
+
+struct xor_channel_t {
+	struct crc_dma_desc *desc;
+	unsigned long desc_phys_addr;
+};
+
+#define XOR_CAUSE_DONE_MASK(chan)	((0x1 | 0x2) << (chan * 16))
+
+void xor_waiton_eng(int chan)
+{
+	int timeout;
+
+	timeout = 0;
+	while (!(reg_read(XOR_CAUSE_REG(XOR_UNIT(chan))) &
+		 XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))) {
+		if (timeout > XOR_TIMEOUT)
+			goto timeout;
+
+		timeout++;
+	}
+
+	timeout = 0;
+	while (mv_xor_state_get(chan) != MV_IDLE) {
+		if (timeout > XOR_TIMEOUT)
+			goto timeout;
+
+		timeout++;
+	}
+
+	/* Clear int */
+	reg_write(XOR_CAUSE_REG(XOR_UNIT(chan)),
+		  ~(XOR_CAUSE_DONE_MASK(XOR_CHAN(chan))));
+
+timeout:
+	return;
+}
+
+static int special_compare_pattern(u32 uj)
+{
+	if ((uj == 30) || (uj == 31) || (uj == 61) || (uj == 62) ||
+	    (uj == 93) || (uj == 94) || (uj == 126) || (uj == 127))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Compare code extracted as its used by multiple functions. This
+ * reduces code-size and makes it easier to maintain it. Additionally
+ * the code is not indented that much and therefore easier to read.
+ */
+static void compare_pattern_v1(u32 uj, u32 *pup, u32 *pattern,
+			       u32 pup_groups, int debug_dqs)
+{
+	u32 val;
+	u32 uk;
+	u32 var1;
+	u32 var2;
+	__maybe_unused u32 dq;
+
+	if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0xFF)) {
+		for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+			val = CMP_BYTE_SHIFT * uk;
+			var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK);
+			var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK);
+
+			if (var1 != var2) {
+				*pup |= (1 << (uk + (PUP_NUM_32BIT *
+						     (uj % pup_groups))));
+
+#ifdef MV_DEBUG_DQS
+				if (!debug_dqs)
+					continue;
+
+				for (dq = 0; dq < DQ_NUM; dq++) {
+					val = uk + (PUP_NUM_32BIT *
+						    (uj % pup_groups));
+					if (((var1 >> dq) & 0x1) !=
+					    ((var2 >> dq) & 0x1))
+						per_bit_data[val][dq] = 1;
+					else
+						per_bit_data[val][dq] = 0;
+				}
+#endif
+			}
+		}
+	}
+}
+
+static void compare_pattern_v2(u32 uj, u32 *pup, u32 *pattern)
+{
+	u32 val;
+	u32 uk;
+	u32 var1;
+	u32 var2;
+
+	if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0x3)) {
+		/* Found error */
+		for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+			val = CMP_BYTE_SHIFT * uk;
+			var1 = (sdram_data[uj] >> val) & CMP_BYTE_MASK;
+			var2 = (pattern[uj] >> val) & CMP_BYTE_MASK;
+			if (var1 != var2)
+				*pup |= (1 << (uk % PUP_NUM_16BIT));
+		}
+	}
+}
+
+/*
+ * Name:     ddr3_sdram_compare
+ * Desc:     Execute compare per PUP
+ * Args:     unlock_pup      Bit array of the unlock pups
+ *           new_locked_pup  Output  bit array of the pups with failed compare
+ *           pattern         Pattern to compare
+ *           pattern_len     Length of pattern (in bytes)
+ *           sdram_offset    offset address to the SDRAM
+ *           write           write to the SDRAM before read
+ *           mask            compare pattern with mask;
+ *           mask_pattern    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+		       u32 *new_locked_pup, u32 *pattern,
+		       u32 pattern_len, u32 sdram_offset, int write,
+		       int mask, u32 *mask_pattern,
+		       int special_compare)
+{
+	u32 uj;
+	__maybe_unused u32 pup_groups;
+	__maybe_unused u32 dq;
+
+#if !defined(MV88F67XX)
+	if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+		pup_groups = 2;
+	else
+		pup_groups = 1;
+#endif
+
+	ddr3_reset_phy_read_fifo();
+
+	/* Check if need to write to sdram before read */
+	if (write == 1)
+		ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len);
+
+	ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len);
+
+	/* Compare read result to write */
+	for (uj = 0; uj < pattern_len; uj++) {
+		if (special_compare && special_compare_pattern(uj))
+			continue;
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+		compare_pattern_v1(uj, new_locked_pup, pattern, pup_groups, 1);
+#elif defined(MV88F67XX)
+		compare_pattern_v2(uj, new_locked_pup, pattern);
+#endif
+	}
+
+	return MV_OK;
+}
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+/*
+ * Name:     ddr3_sdram_dm_compare
+ * Desc:     Execute compare per PUP
+ * Args:     unlock_pup      Bit array of the unlock pups
+ *           new_locked_pup  Output  bit array of the pups with failed compare
+ *           pattern         Pattern to compare
+ *           pattern_len     Length of pattern (in bytes)
+ *           sdram_offset    offset address to the SDRAM
+ *           write           write to the SDRAM before read
+ *           mask            compare pattern with mask;
+ *           mask_pattern    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			  u32 *new_locked_pup, u32 *pattern,
+			  u32 sdram_offset)
+{
+	u32 uj, uk, var1, var2, pup_groups;
+	u32 val;
+	u32 pup = 0;
+
+	if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+		pup_groups = 2;
+	else
+		pup_groups = 1;
+
+	ddr3_dram_sram_burst((u32)pattern, SDRAM_PBS_TX_OFFS,
+			     LEN_PBS_PATTERN);
+	ddr3_dram_sram_burst(SDRAM_PBS_TX_OFFS, (u32)sdram_data,
+			     LEN_PBS_PATTERN);
+
+	/* Validate the correctness of the results */
+	for (uj = 0; uj < LEN_PBS_PATTERN; uj++)
+		compare_pattern_v1(uj, &pup, pattern, pup_groups, 0);
+
+	/* Test the DM Signals */
+	*(u32 *)(SDRAM_PBS_TX_OFFS + 0x10) = 0x12345678;
+	*(u32 *)(SDRAM_PBS_TX_OFFS + 0x14) = 0x12345678;
+
+	sdram_data[0] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10);
+	sdram_data[1] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14);
+
+	for (uj = 0; uj < 2; uj++) {
+		if (((sdram_data[uj]) != (pattern[uj])) &&
+		    (*new_locked_pup != 0xFF)) {
+			for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+				val = CMP_BYTE_SHIFT * uk;
+				var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK);
+				var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK);
+				if (var1 != var2) {
+					*new_locked_pup |= (1 << (uk +
+						(PUP_NUM_32BIT * (uj % pup_groups))));
+					*new_locked_pup |= pup;
+				}
+			}
+		}
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_sdram_pbs_compare
+ * Desc:     Execute SRAM compare per PUP and DQ.
+ * Args:     pup_locked             bit array of locked pups
+ *           is_tx                  Indicate whether Rx or Tx
+ *           pbs_pattern_idx        Index of PBS pattern
+ *           pbs_curr_val           The PBS value
+ *           pbs_lock_val           The value to set to locked PBS
+ *           skew_array             Global array to update with the compare results
+ *           ai_unlock_pup_dq_array bit array of the locked / unlocked pups per dq.
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked,
+			   int is_tx, u32 pbs_pattern_idx,
+			   u32 pbs_curr_val, u32 pbs_lock_val,
+			   u32 *skew_array, u8 *unlock_pup_dq_array,
+			   u32 ecc)
+{
+	/* bit array failed dq per pup for current compare */
+	u32 pbs_write_pup[DQ_NUM] = { 0 };
+	u32 update_pup;	/* pup as HW convention */
+	u32 max_pup;	/* maximal pup index */
+	u32 pup_addr;
+	u32 ui, dq, pup;
+	int var1, var2;
+	u32 sdram_offset, pup_groups, tmp_pup;
+	u32 *pattern_ptr;
+	u32 val;
+
+	/* Choose pattern */
+	switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+	case 16:
+		pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+		break;
+#endif
+	case 32:
+		pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+		break;
+#if defined(MV88F78X60)
+	case 64:
+		pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+		break;
+#endif
+	default:
+		return MV_FAIL;
+	}
+
+	max_pup = dram_info->num_of_std_pups;
+
+	sdram_offset = SDRAM_PBS_I_OFFS + pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS;
+
+	if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+		pup_groups = 2;
+	else
+		pup_groups = 1;
+
+	ddr3_reset_phy_read_fifo();
+
+	/* Check if need to write to sdram before read */
+	if (is_tx == 1) {
+		ddr3_dram_sram_burst((u32)pattern_ptr, sdram_offset,
+				     LEN_PBS_PATTERN);
+	}
+
+	ddr3_dram_sram_read(sdram_offset, (u32)sdram_data, LEN_PBS_PATTERN);
+
+	/* Compare read result to write */
+	for (ui = 0; ui < LEN_PBS_PATTERN; ui++) {
+		if ((sdram_data[ui]) != (pattern_ptr[ui])) {
+			/* found error */
+			/* error in low pup group */
+			for (pup = 0; pup < PUP_NUM_32BIT; pup++) {
+				val = CMP_BYTE_SHIFT * pup;
+				var1 = ((sdram_data[ui] >> val) &
+					CMP_BYTE_MASK);
+				var2 = ((pattern_ptr[ui] >> val) &
+					CMP_BYTE_MASK);
+
+				if (var1 != var2) {
+					if (dram_info->ddr_width > 16) {
+						tmp_pup = (pup + PUP_NUM_32BIT *
+							   (ui % pup_groups));
+					} else {
+						tmp_pup = (pup % PUP_NUM_16BIT);
+					}
+
+					update_pup = (1 << tmp_pup);
+					if (ecc && (update_pup != 0x1))
+						continue;
+
+					/*
+					 * Pup is failed - Go over all DQs and
+					 * look for failures
+					 */
+					for (dq = 0; dq < DQ_NUM; dq++) {
+						val = tmp_pup * (1 - ecc) +
+							ecc * ECC_PUP;
+						if (((var1 >> dq) & 0x1) !=
+						    ((var2 >> dq) & 0x1)) {
+							if (pbs_locked_dq[val][dq] == 1 &&
+							    pbs_locked_value[val][dq] != pbs_curr_val)
+								continue;
+
+							/*
+							 * Activate write to
+							 * update PBS to
+							 * pbs_lock_val
+							 */
+							pbs_write_pup[dq] |=
+								update_pup;
+
+							/*
+							 * Update the
+							 * unlock_pup_dq_array
+							 */
+							unlock_pup_dq_array[dq] &=
+								~update_pup;
+
+							/*
+							 * Lock PBS value for
+							 * failed bits in
+							 * compare operation
+							 */
+							skew_array[tmp_pup * DQ_NUM + dq] =
+								pbs_curr_val;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	pup_addr = (is_tx == 1) ? PUP_PBS_TX : PUP_PBS_RX;
+
+	/* Set last failed bits PBS to min / max pbs value */
+	for (dq = 0; dq < DQ_NUM; dq++) {
+		for (pup = 0; pup < max_pup; pup++) {
+			if (pbs_write_pup[dq] & (1 << pup)) {
+				val = pup * (1 - ecc) + ecc * ECC_PUP;
+				if (pbs_locked_dq[val][dq] == 1 &&
+				    pbs_locked_value[val][dq] != pbs_curr_val)
+					continue;
+
+				/* Mark the dq as locked */
+				pbs_locked_dq[val][dq] = 1;
+				pbs_locked_value[val][dq] = pbs_curr_val;
+				ddr3_write_pup_reg(pup_addr +
+						   pbs_dq_mapping[val][dq],
+						   CS0, val, 0, pbs_lock_val);
+			}
+		}
+	}
+
+	return MV_OK;
+}
+#endif
+
+/*
+ * Name:     ddr3_sdram_direct_compare
+ * Desc:     Execute compare  per PUP without DMA (no burst mode)
+ * Args:     unlock_pup       Bit array of the unlock pups
+ *           new_locked_pup   Output  bit array of the pups with failed compare
+ *           pattern          Pattern to compare
+ *           pattern_len      Length of pattern (in bytes)
+ *           sdram_offset     offset address to the SDRAM
+ *           write            write to the SDRAM before read
+ *           mask             compare pattern with mask;
+ *           auiMaskPatter    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			      u32 *new_locked_pup, u32 *pattern,
+			      u32 pattern_len, u32 sdram_offset,
+			      int write, int mask, u32 *mask_pattern)
+{
+	u32 uj, uk, pup_groups;
+	u32 *sdram_addr;	/* used to read from SDRAM */
+
+	sdram_addr = (u32 *)sdram_offset;
+
+	if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+		pup_groups = 2;
+	else
+		pup_groups = 1;
+
+	/* Check if need to write before read */
+	if (write == 1) {
+		for (uk = 0; uk < pattern_len; uk++) {
+			*sdram_addr = pattern[uk];
+			sdram_addr++;
+		}
+	}
+
+	sdram_addr = (u32 *)sdram_offset;
+
+	for (uk = 0; uk < pattern_len; uk++) {
+		sdram_data[uk] = *sdram_addr;
+		sdram_addr++;
+	}
+
+	/* Compare read result to write */
+	for (uj = 0; uj < pattern_len; uj++) {
+		if (dram_info->ddr_width > 16) {
+			compare_pattern_v1(uj, new_locked_pup, pattern,
+					   pup_groups, 0);
+		} else {
+			compare_pattern_v2(uj, new_locked_pup, pattern);
+		}
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dram_sram_burst
+ * Desc:     Read from the SDRAM in burst of 64 bytes
+ * Args:     src
+ *           dst
+ * Notes:    Using the XOR mechanism
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len)
+{
+	u32 chan, byte_count, cs_num, byte;
+	struct xor_channel_t channel;
+
+	chan = 0;
+	byte_count = len * 4;
+
+	/* Wait for previous transfer completion */
+	while (mv_xor_state_get(chan) != MV_IDLE)
+		;
+
+	/* Build the channel descriptor */
+	channel.desc = &dma_desc;
+
+	/* Enable Address Override and set correct src and dst */
+	if (src < SRAM_BASE) {
+		/* src is DRAM CS, dst is SRAM */
+		cs_num = (src / (1 + SDRAM_CS_SIZE));
+		reg_write(XOR_ADDR_OVRD_REG(0, 0),
+			  ((cs_num << 1) | (1 << 0)));
+		channel.desc->src_addr0 = (src % (1 + SDRAM_CS_SIZE));
+		channel.desc->dst_addr = dst;
+	} else {
+		/* src is SRAM, dst is DRAM CS */
+		cs_num = (dst / (1 + SDRAM_CS_SIZE));
+		reg_write(XOR_ADDR_OVRD_REG(0, 0),
+			  ((cs_num << 25) | (1 << 24)));
+		channel.desc->src_addr0 = (src);
+		channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE));
+		channel.desc->src_addr0 = src;
+		channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE));
+	}
+
+	channel.desc->src_addr1 = 0;
+	channel.desc->byte_cnt = byte_count;
+	channel.desc->next_desc_ptr = 0;
+	channel.desc->status = 1 << 31;
+	channel.desc->desc_cmd = 0x0;
+	channel.desc_phys_addr = (unsigned long)&dma_desc;
+
+	ddr3_flush_l1_line((u32)&dma_desc);
+
+	/* Issue the transfer */
+	if (mv_xor_transfer(chan, MV_DMA, channel.desc_phys_addr) != MV_OK)
+		return MV_FAIL;
+
+	/* Wait for completion */
+	xor_waiton_eng(chan);
+
+	if (dst > SRAM_BASE) {
+		for (byte = 0; byte < byte_count; byte += 0x20)
+			cache_inv(dst + byte);
+	}
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_flush_l1_line
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static void ddr3_flush_l1_line(u32 line)
+{
+	u32 reg;
+
+#if defined(MV88F672X)
+	reg = 1;
+#else
+	reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR) &
+		(1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS);
+#ifdef MV88F67XX
+	reg = ~reg & (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS);
+#endif
+#endif
+
+	if (reg) {
+		/* V7 Arch mode */
+		flush_l1_v7(line);
+		flush_l1_v7(line + CACHE_LINE_SIZE);
+	} else {
+		/* V6 Arch mode */
+		flush_l1_v6(line);
+		flush_l1_v6(line + CACHE_LINE_SIZE);
+	}
+}
+
+int ddr3_dram_sram_read(u32 src, u32 dst, u32 len)
+{
+	u32 ui;
+	u32 *dst_ptr, *src_ptr;
+
+	dst_ptr = (u32 *)dst;
+	src_ptr = (u32 *)src;
+
+	for (ui = 0; ui < len; ui++) {
+		*dst_ptr = *src_ptr;
+		dst_ptr++;
+		src_ptr++;
+	}
+
+	return MV_OK;
+}
+
+int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+			   u32 *new_locked_pup, u32 *pattern,
+			   u32 pattern_len, u32 sdram_offset, int write,
+			   int mask, u32 *mask_pattern,
+			   int special_compare)
+{
+	u32 uj, pup_groups;
+
+	if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+		pup_groups = 2;
+	else
+		pup_groups = 1;
+
+	ddr3_reset_phy_read_fifo();
+
+	/* Check if need to write to sdram before read */
+	if (write == 1)
+		ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len);
+
+	ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len);
+
+	/* Compare read result to write */
+	for (uj = 0; uj < pattern_len; uj++) {
+		if (special_compare && special_compare_pattern(uj))
+			continue;
+
+		if (dram_info->ddr_width > 16) {
+			compare_pattern_v1(uj, new_locked_pup, pattern,
+					   pup_groups, 1);
+		} else {
+			compare_pattern_v2(uj, new_locked_pup, pattern);
+		}
+	}
+
+	return MV_OK;
+}
+
+void ddr3_reset_phy_read_fifo(void)
+{
+	u32 reg;
+
+	/* reset read FIFO */
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+	/* Start Auto Read Leveling procedure */
+	reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+
+	/* 0x15B0 - Training Register */
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) +
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+
+	/* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	do {
+		reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+			(1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+	} while (reg);	/* Wait for '0' */
+
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+
+	/* Clear Auto Read Leveling procedure */
+	reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+
+	/* 0x15B0 - Training Register */
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);
+}
diff --git a/drivers/ddr/mvebu/ddr3_spd.c b/drivers/ddr/mvebu/ddr3_spd.c
new file mode 100644
index 0000000..f4f94c5
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_spd.c
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+
+#if defined(MV88F78X60)
+#include "ddr3_axp_config.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370_config.h"
+#endif
+
+#if defined(MV88F672X)
+#include "ddr3_a375_config.h"
+#endif
+
+#ifdef DUNIT_SPD
+
+/* DIMM SPD offsets */
+#define SPD_DEV_TYPE_BYTE		2
+
+#define SPD_MODULE_TYPE_BYTE		3
+#define SPD_MODULE_MASK			0xf
+#define SPD_MODULE_TYPE_RDIMM		1
+#define SPD_MODULE_TYPE_UDIMM		2
+
+#define SPD_DEV_DENSITY_BYTE		4
+#define SPD_DEV_DENSITY_MASK		0xf
+
+#define SPD_ROW_NUM_BYTE		5
+#define SPD_ROW_NUM_MIN			12
+#define SPD_ROW_NUM_OFF			3
+#define SPD_ROW_NUM_MASK		(7 << SPD_ROW_NUM_OFF)
+
+#define SPD_COL_NUM_BYTE		5
+#define SPD_COL_NUM_MIN			9
+#define SPD_COL_NUM_OFF			0
+#define SPD_COL_NUM_MASK		(7 << SPD_COL_NUM_OFF)
+
+#define SPD_MODULE_ORG_BYTE		7
+#define SPD_MODULE_SDRAM_DEV_WIDTH_OFF 	0
+#define SPD_MODULE_SDRAM_DEV_WIDTH_MASK	(7 << SPD_MODULE_SDRAM_DEV_WIDTH_OFF)
+#define SPD_MODULE_BANK_NUM_MIN		1
+#define SPD_MODULE_BANK_NUM_OFF		3
+#define SPD_MODULE_BANK_NUM_MASK	(7 << SPD_MODULE_BANK_NUM_OFF)
+
+#define SPD_BUS_WIDTH_BYTE		8
+#define SPD_BUS_WIDTH_OFF		0
+#define SPD_BUS_WIDTH_MASK		(7 << SPD_BUS_WIDTH_OFF)
+#define SPD_BUS_ECC_OFF			3
+#define SPD_BUS_ECC_MASK		(3 << SPD_BUS_ECC_OFF)
+
+#define SPD_MTB_DIVIDEND_BYTE		10
+#define SPD_MTB_DIVISOR_BYTE		11
+#define SPD_TCK_BYTE			12
+#define SPD_SUP_CAS_LAT_LSB_BYTE	14
+#define SPD_SUP_CAS_LAT_MSB_BYTE	15
+#define SPD_TAA_BYTE			16
+#define SPD_TWR_BYTE			17
+#define SPD_TRCD_BYTE			18
+#define SPD_TRRD_BYTE			19
+#define SPD_TRP_BYTE			20
+
+#define SPD_TRAS_MSB_BYTE		21
+#define SPD_TRAS_MSB_MASK		0xf
+
+#define SPD_TRC_MSB_BYTE		21
+#define SPD_TRC_MSB_MASK		0xf0
+
+#define SPD_TRAS_LSB_BYTE		22
+#define SPD_TRC_LSB_BYTE		23
+#define SPD_TRFC_LSB_BYTE		24
+#define SPD_TRFC_MSB_BYTE		25
+#define SPD_TWTR_BYTE			26
+#define SPD_TRTP_BYTE			27
+
+#define SPD_TFAW_MSB_BYTE		28
+#define SPD_TFAW_MSB_MASK		0xf
+
+#define SPD_TFAW_LSB_BYTE		29
+#define SPD_OPT_FEATURES_BYTE		30
+#define SPD_THERMAL_REFRESH_OPT_BYTE	31
+
+#define SPD_ADDR_MAP_BYTE		63
+#define SPD_ADDR_MAP_MIRROR_OFFS	0
+
+#define SPD_RDIMM_RC_BYTE		69
+#define SPD_RDIMM_RC_NIBBLE_MASK	0xF
+#define SPD_RDIMM_RC_NUM		16
+
+/* Dimm Memory Type values */
+#define SPD_MEM_TYPE_SDRAM		0x4
+#define SPD_MEM_TYPE_DDR1		0x7
+#define SPD_MEM_TYPE_DDR2		0x8
+#define SPD_MEM_TYPE_DDR3		0xB
+
+#define DIMM_MODULE_MANU_OFFS		64
+#define DIMM_MODULE_MANU_SIZE		8
+#define DIMM_MODULE_VEN_OFFS		73
+#define DIMM_MODULE_VEN_SIZE		25
+#define DIMM_MODULE_ID_OFFS		99
+#define DIMM_MODULE_ID_SIZE		18
+
+/* enumeration for voltage levels. */
+enum dimm_volt_if {
+	TTL_5V_TOLERANT,
+	LVTTL,
+	HSTL_1_5V,
+	SSTL_3_3V,
+	SSTL_2_5V,
+	VOLTAGE_UNKNOWN,
+};
+
+/* enumaration for SDRAM CAS Latencies. */
+enum dimm_sdram_cas {
+	SD_CL_1 = 1,
+	SD_CL_2,
+	SD_CL_3,
+	SD_CL_4,
+	SD_CL_5,
+	SD_CL_6,
+	SD_CL_7,
+	SD_FAULT
+};
+
+/* enumeration for memory types */
+enum memory_type {
+	MEM_TYPE_SDRAM,
+	MEM_TYPE_DDR1,
+	MEM_TYPE_DDR2,
+	MEM_TYPE_DDR3
+};
+
+/* DIMM information structure */
+typedef struct dimm_info {
+	/* DIMM dimensions */
+	u32 num_of_module_ranks;
+	u32 data_width;
+	u32 rank_capacity;
+	u32 num_of_devices;
+
+	u32 sdram_width;
+	u32 num_of_banks_on_each_device;
+	u32 sdram_capacity;
+
+	u32 num_of_row_addr;
+	u32 num_of_col_addr;
+
+	u32 addr_mirroring;
+
+	u32 err_check_type;			/* ECC , PARITY.. */
+	u32 type_info;				/* DDR2 only */
+
+	/* DIMM timing parameters */
+	u32 supported_cas_latencies;
+	u32 refresh_interval;
+	u32 min_cycle_time;
+	u32 min_row_precharge_time;
+	u32 min_row_active_to_row_active;
+	u32 min_ras_to_cas_delay;
+	u32 min_write_recovery_time;		/* DDR3/2 only */
+	u32 min_write_to_read_cmd_delay;	/* DDR3/2 only */
+	u32 min_read_to_prech_cmd_delay;	/* DDR3/2 only */
+	u32 min_active_to_precharge;
+	u32 min_refresh_recovery;		/* DDR3/2 only */
+	u32 min_cas_lat_time;
+	u32 min_four_active_win_delay;
+	u8 dimm_rc[SPD_RDIMM_RC_NUM];
+
+	/* DIMM vendor ID */
+	u32 vendor;
+} MV_DIMM_INFO;
+
+static int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info,
+			     u32 dimm);
+static u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val);
+static u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val);
+static int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width);
+static u32 ddr3_div(u32 val, u32 divider, u32 sub);
+
+extern u8 spd_data[SPD_SIZE];
+extern u32 odt_config[ODT_OPT];
+extern u16 odt_static[ODT_OPT][MAX_CS];
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+
+#if !(defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710))
+/*
+ * Name:     ddr3_get_dimm_num - Find number of dimms and their addresses
+ * Desc:
+ * Args:     dimm_addr - array of dimm addresses
+ * Notes:
+ * Returns:  None.
+ */
+static u32 ddr3_get_dimm_num(u32 *dimm_addr)
+{
+	u32 dimm_cur_addr;
+	u8 data[3];
+	u32 dimm_num = 0;
+	int ret;
+
+	/* Read the dimm eeprom */
+	for (dimm_cur_addr = MAX_DIMM_ADDR; dimm_cur_addr > MIN_DIMM_ADDR;
+	     dimm_cur_addr--) {
+		data[SPD_DEV_TYPE_BYTE] = 0;
+
+		/* Far-End DIMM must be connected */
+		if ((dimm_num == 0) && (dimm_cur_addr < FAR_END_DIMM_ADDR))
+			return 0;
+
+		ret = i2c_read(dimm_cur_addr, 0, 1, (uchar *)data, 3);
+		if (!ret) {
+			if (data[SPD_DEV_TYPE_BYTE] == SPD_MEM_TYPE_DDR3) {
+				dimm_addr[dimm_num] = dimm_cur_addr;
+				dimm_num++;
+			}
+		}
+	}
+
+	return dimm_num;
+}
+#endif
+
+/*
+ * Name:     dimmSpdInit - Get the SPD parameters.
+ * Desc:     Read the DIMM SPD parameters into given struct parameter.
+ * Args:     dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator.
+ *           info - DIMM information structure.
+ * Notes:
+ * Returns:  MV_OK if function could read DIMM parameters, 0 otherwise.
+ */
+int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width)
+{
+	u32 tmp;
+	u32 time_base;
+	int ret;
+	__maybe_unused u32 rc;
+	__maybe_unused u8 vendor_high, vendor_low;
+
+	if (dimm_addr != 0) {
+		memset(spd_data, 0, SPD_SIZE * sizeof(u8));
+
+		ret = i2c_read(dimm_addr, 0, 1, (uchar *)spd_data, SPD_SIZE);
+		if (ret)
+			return MV_DDR3_TRAINING_ERR_TWSI_FAIL;
+	}
+
+	/* Check if DDR3 */
+	if (spd_data[SPD_DEV_TYPE_BYTE] != SPD_MEM_TYPE_DDR3)
+		return MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE;
+
+	/* Error Check Type */
+	/* No byte for error check in DDR3 SPD, use DDR2 convention */
+	info->err_check_type = 0;
+
+	/* Check if ECC */
+	if ((spd_data[SPD_BUS_WIDTH_BYTE] & 0x18) >> 3)
+		info->err_check_type = 1;
+
+	DEBUG_INIT_FULL_C("DRAM err_check_type ", info->err_check_type, 1);
+	switch (spd_data[SPD_MODULE_TYPE_BYTE]) {
+	case 1:
+		/* support RDIMM */
+		info->type_info = SPD_MODULE_TYPE_RDIMM;
+		break;
+	case 2:
+		/* support UDIMM */
+		info->type_info = SPD_MODULE_TYPE_UDIMM;
+		break;
+	case 11:		/* LRDIMM current not supported */
+	default:
+		info->type_info = (spd_data[SPD_MODULE_TYPE_BYTE]);
+		break;
+	}
+
+	/* Size Calculations: */
+
+	/* Number Of Row Addresses - 12/13/14/15/16 */
+	info->num_of_row_addr =
+		(spd_data[SPD_ROW_NUM_BYTE] & SPD_ROW_NUM_MASK) >>
+		SPD_ROW_NUM_OFF;
+	info->num_of_row_addr += SPD_ROW_NUM_MIN;
+	DEBUG_INIT_FULL_C("DRAM num_of_row_addr ", info->num_of_row_addr, 2);
+
+	/* Number Of Column Addresses - 9/10/11/12 */
+	info->num_of_col_addr =
+		(spd_data[SPD_COL_NUM_BYTE] & SPD_COL_NUM_MASK) >>
+		SPD_COL_NUM_OFF;
+	info->num_of_col_addr += SPD_COL_NUM_MIN;
+	DEBUG_INIT_FULL_C("DRAM num_of_col_addr ", info->num_of_col_addr, 1);
+
+	/* Number Of Ranks = number of CS on Dimm - 1/2/3/4 Ranks */
+	info->num_of_module_ranks =
+		(spd_data[SPD_MODULE_ORG_BYTE] & SPD_MODULE_BANK_NUM_MASK) >>
+		SPD_MODULE_BANK_NUM_OFF;
+	info->num_of_module_ranks += SPD_MODULE_BANK_NUM_MIN;
+	DEBUG_INIT_FULL_C("DRAM numOfModuleBanks ", info->num_of_module_ranks,
+			  1);
+
+	/* Data Width - 8/16/32/64 bits */
+	info->data_width =
+		1 << (3 + (spd_data[SPD_BUS_WIDTH_BYTE] & SPD_BUS_WIDTH_MASK));
+	DEBUG_INIT_FULL_C("DRAM data_width ", info->data_width, 1);
+
+	/* Number Of Banks On Each Device - 8/16/32/64 banks */
+	info->num_of_banks_on_each_device =
+		1 << (3 + ((spd_data[SPD_DEV_DENSITY_BYTE] >> 4) & 0x7));
+	DEBUG_INIT_FULL_C("DRAM num_of_banks_on_each_device ",
+			  info->num_of_banks_on_each_device, 1);
+
+	/* Total SDRAM capacity - 256Mb/512Mb/1Gb/2Gb/4Gb/8Gb/16Gb - MegaBits */
+	info->sdram_capacity =
+		spd_data[SPD_DEV_DENSITY_BYTE] & SPD_DEV_DENSITY_MASK;
+
+	/* Sdram Width - 4/8/16/32 bits */
+	info->sdram_width = 1 << (2 + (spd_data[SPD_MODULE_ORG_BYTE] &
+				       SPD_MODULE_SDRAM_DEV_WIDTH_MASK));
+	DEBUG_INIT_FULL_C("DRAM sdram_width ", info->sdram_width, 1);
+
+	/* CS (Rank) Capacity - MB */
+	/*
+	 * DDR3 device uiDensity val are: (device capacity/8) *
+	 * (Module_width/Device_width)
+	 */
+	/* Jedec SPD DDR3 - page 7, Save spd_data in Mb  - 2048=2GB */
+	if (dimm_width == 32) {
+		info->rank_capacity =
+			((1 << info->sdram_capacity) * 256 *
+			 (info->data_width / info->sdram_width)) << 16;
+		/* CS size = CS size / 2  */
+	} else {
+		info->rank_capacity =
+			((1 << info->sdram_capacity) * 256 *
+			 (info->data_width / info->sdram_width) * 0x2) << 16;
+		/* 0x2 =>  0x100000-1Mbit / 8-bit->byte / 0x10000  */
+	}
+	DEBUG_INIT_FULL_C("DRAM rank_capacity[31] ", info->rank_capacity, 1);
+
+	/* Number of devices includeing Error correction */
+	info->num_of_devices =
+		((info->data_width / info->sdram_width) *
+		 info->num_of_module_ranks) + info->err_check_type;
+	DEBUG_INIT_FULL_C("DRAM num_of_devices  ", info->num_of_devices, 1);
+
+	/* Address Mapping from Edge connector to DRAM - mirroring option */
+	info->addr_mirroring =
+		spd_data[SPD_ADDR_MAP_BYTE] & (1 << SPD_ADDR_MAP_MIRROR_OFFS);
+
+	/* Timings - All in ps */
+
+	time_base = (1000 * spd_data[SPD_MTB_DIVIDEND_BYTE]) /
+		spd_data[SPD_MTB_DIVISOR_BYTE];
+
+	/* Minimum Cycle Time At Max CasLatancy */
+	info->min_cycle_time = spd_data[SPD_TCK_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM tCKmin ", info->min_cycle_time, 1);
+
+	/* Refresh Interval */
+	/* No byte for refresh interval in DDR3 SPD, use DDR2 convention */
+	/*
+	 * JEDEC param are 0 <= Tcase <= 85: 7.8uSec, 85 <= Tcase
+	 * <= 95: 3.9uSec
+	 */
+	info->refresh_interval = 7800000;	/* Set to 7.8uSec */
+	DEBUG_INIT_FULL_C("DRAM refresh_interval ", info->refresh_interval, 1);
+
+	/* Suported Cas Latencies -  DDR 3: */
+
+	/*
+	 *         bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+	 *******-******-******-******-******-******-******-*******-*******
+	 CAS =      11  |  10  |  9   |  8   |  7   |  6   |  5   |  4   *
+	 *********************************************************-*******
+	 *******-******-******-******-******-******-******-*******-*******
+	 *        bit15 |bit14 |bit13 |bit12 |bit11 |bit10 | bit9 | bit8 *
+	 *******-******-******-******-******-******-******-*******-*******
+	 CAS =     TBD  |  18  |  17  |  16  |  15  |  14  |  13  |  12  *
+	*/
+
+	/* DDR3 include 2 byte of CAS support */
+	info->supported_cas_latencies =
+		(spd_data[SPD_SUP_CAS_LAT_MSB_BYTE] << 8) |
+		spd_data[SPD_SUP_CAS_LAT_LSB_BYTE];
+	DEBUG_INIT_FULL_C("DRAM supported_cas_latencies ",
+			  info->supported_cas_latencies, 1);
+
+	/* Minimum Cycle Time At Max CasLatancy */
+	info->min_cas_lat_time = (spd_data[SPD_TAA_BYTE] * time_base);
+	/*
+	 * This field divided by the cycleTime will give us the CAS latency
+	 * to config
+	 */
+
+	/*
+	 * For DDR3 and DDR2 includes Write Recovery Time field.
+	 * Other SDRAM ignore
+	 */
+	info->min_write_recovery_time = spd_data[SPD_TWR_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_write_recovery_time ",
+			  info->min_write_recovery_time, 1);
+
+	/* Mininmum Ras to Cas Delay */
+	info->min_ras_to_cas_delay = spd_data[SPD_TRCD_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_ras_to_cas_delay ",
+			  info->min_ras_to_cas_delay, 1);
+
+	/* Minimum Row Active to Row Active Time */
+	info->min_row_active_to_row_active =
+	    spd_data[SPD_TRRD_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_row_active_to_row_active ",
+			  info->min_row_active_to_row_active, 1);
+
+	/* Minimum Row Precharge Delay Time */
+	info->min_row_precharge_time = spd_data[SPD_TRP_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_row_precharge_time ",
+			  info->min_row_precharge_time, 1);
+
+	/* Minimum Active to Precharge Delay Time - tRAS   ps */
+	info->min_active_to_precharge =
+		(spd_data[SPD_TRAS_MSB_BYTE] & SPD_TRAS_MSB_MASK) << 8;
+	info->min_active_to_precharge |= spd_data[SPD_TRAS_LSB_BYTE];
+	info->min_active_to_precharge *= time_base;
+	DEBUG_INIT_FULL_C("DRAM min_active_to_precharge ",
+			  info->min_active_to_precharge, 1);
+
+	/* Minimum Refresh Recovery Delay Time - tRFC  ps */
+	info->min_refresh_recovery = spd_data[SPD_TRFC_MSB_BYTE] << 8;
+	info->min_refresh_recovery |= spd_data[SPD_TRFC_LSB_BYTE];
+	info->min_refresh_recovery *= time_base;
+	DEBUG_INIT_FULL_C("DRAM min_refresh_recovery ",
+			  info->min_refresh_recovery, 1);
+
+	/*
+	 * For DDR3 and DDR2 includes Internal Write To Read Command Delay
+	 * field.
+	 */
+	info->min_write_to_read_cmd_delay = spd_data[SPD_TWTR_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_write_to_read_cmd_delay ",
+			  info->min_write_to_read_cmd_delay, 1);
+
+	/*
+	 * For DDR3 and DDR2 includes Internal Read To Precharge Command Delay
+	 * field.
+	 */
+	info->min_read_to_prech_cmd_delay = spd_data[SPD_TRTP_BYTE] * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_read_to_prech_cmd_delay ",
+			  info->min_read_to_prech_cmd_delay, 1);
+
+	/*
+	 * For DDR3 includes Minimum Activate to Activate/Refresh Command
+	 * field
+	 */
+	tmp = ((spd_data[SPD_TFAW_MSB_BYTE] & SPD_TFAW_MSB_MASK) << 8) |
+		spd_data[SPD_TFAW_LSB_BYTE];
+	info->min_four_active_win_delay = tmp * time_base;
+	DEBUG_INIT_FULL_C("DRAM min_four_active_win_delay ",
+			  info->min_four_active_win_delay, 1);
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+	/* Registered DIMM support */
+	if (info->type_info == SPD_MODULE_TYPE_RDIMM) {
+		for (rc = 2; rc < 6; rc += 2) {
+			tmp = spd_data[SPD_RDIMM_RC_BYTE + rc / 2];
+			info->dimm_rc[rc] =
+				spd_data[SPD_RDIMM_RC_BYTE + rc / 2] &
+				SPD_RDIMM_RC_NIBBLE_MASK;
+			info->dimm_rc[rc + 1] =
+				(spd_data[SPD_RDIMM_RC_BYTE + rc / 2] >> 4) &
+				SPD_RDIMM_RC_NIBBLE_MASK;
+		}
+
+		vendor_low = spd_data[66];
+		vendor_high = spd_data[65];
+		info->vendor = (vendor_high << 8) + vendor_low;
+		DEBUG_INIT_C("DDR3 Training Sequence - Registered DIMM vendor ID 0x",
+			     info->vendor, 4);
+
+		info->dimm_rc[0] = RDIMM_RC0;
+		info->dimm_rc[1] = RDIMM_RC1;
+		info->dimm_rc[2] = RDIMM_RC2;
+		info->dimm_rc[8] = RDIMM_RC8;
+		info->dimm_rc[9] = RDIMM_RC9;
+		info->dimm_rc[10] = RDIMM_RC10;
+		info->dimm_rc[11] = RDIMM_RC11;
+	}
+#endif
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_spd_sum_init - Get the SPD parameters.
+ * Desc:     Read the DIMM SPD parameters into given struct parameter.
+ * Args:     dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator.
+ *           info - DIMM information structure.
+ * Notes:
+ * Returns:  MV_OK if function could read DIMM parameters, 0 otherwise.
+ */
+int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info, u32 dimm)
+{
+	if (dimm == 0) {
+		memcpy(sum_info, info, sizeof(MV_DIMM_INFO));
+		return MV_OK;
+	}
+	if (sum_info->type_info != info->type_info) {
+		DEBUG_INIT_S("DDR3 Dimm Compare - DIMM type does not match - FAIL\n");
+		return MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH;
+	}
+	if (sum_info->err_check_type > info->err_check_type) {
+		sum_info->err_check_type = info->err_check_type;
+		DEBUG_INIT_S("DDR3 Dimm Compare - ECC does not match. ECC is disabled\n");
+	}
+	if (sum_info->data_width != info->data_width) {
+		DEBUG_INIT_S("DDR3 Dimm Compare - DRAM bus width does not match - FAIL\n");
+		return MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH;
+	}
+	if (sum_info->min_cycle_time < info->min_cycle_time)
+		sum_info->min_cycle_time = info->min_cycle_time;
+	if (sum_info->refresh_interval < info->refresh_interval)
+		sum_info->refresh_interval = info->refresh_interval;
+	sum_info->supported_cas_latencies &= info->supported_cas_latencies;
+	if (sum_info->min_cas_lat_time < info->min_cas_lat_time)
+		sum_info->min_cas_lat_time = info->min_cas_lat_time;
+	if (sum_info->min_write_recovery_time < info->min_write_recovery_time)
+		sum_info->min_write_recovery_time =
+		    info->min_write_recovery_time;
+	if (sum_info->min_ras_to_cas_delay < info->min_ras_to_cas_delay)
+		sum_info->min_ras_to_cas_delay = info->min_ras_to_cas_delay;
+	if (sum_info->min_row_active_to_row_active <
+	    info->min_row_active_to_row_active)
+		sum_info->min_row_active_to_row_active =
+		    info->min_row_active_to_row_active;
+	if (sum_info->min_row_precharge_time < info->min_row_precharge_time)
+		sum_info->min_row_precharge_time = info->min_row_precharge_time;
+	if (sum_info->min_active_to_precharge < info->min_active_to_precharge)
+		sum_info->min_active_to_precharge =
+		    info->min_active_to_precharge;
+	if (sum_info->min_refresh_recovery < info->min_refresh_recovery)
+		sum_info->min_refresh_recovery = info->min_refresh_recovery;
+	if (sum_info->min_write_to_read_cmd_delay <
+	    info->min_write_to_read_cmd_delay)
+		sum_info->min_write_to_read_cmd_delay =
+		    info->min_write_to_read_cmd_delay;
+	if (sum_info->min_read_to_prech_cmd_delay <
+	    info->min_read_to_prech_cmd_delay)
+		sum_info->min_read_to_prech_cmd_delay =
+		    info->min_read_to_prech_cmd_delay;
+	if (sum_info->min_four_active_win_delay <
+	    info->min_four_active_win_delay)
+		sum_info->min_four_active_win_delay =
+		    info->min_four_active_win_delay;
+	if (sum_info->min_write_to_read_cmd_delay <
+	    info->min_write_to_read_cmd_delay)
+		sum_info->min_write_to_read_cmd_delay =
+			info->min_write_to_read_cmd_delay;
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dunit_setup
+ * Desc:     Set the controller with the timing values.
+ * Args:     ecc_ena - User ECC setup
+ * Notes:
+ * Returns:
+ */
+int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width)
+{
+	u32 reg, tmp, cwl;
+	u32 ddr_clk_time;
+	MV_DIMM_INFO dimm_info[2];
+	MV_DIMM_INFO sum_info;
+	u32 stat_val, spd_val;
+	u32 cs, cl, cs_num, cs_ena;
+	u32 dimm_num = 0;
+	int status;
+	u32 rc;
+	__maybe_unused u32 dimm_cnt, cs_count, dimm;
+	__maybe_unused u32 dimm_addr[2] = { 0, 0 };
+
+#if defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710)
+	/* Armada 370 - SPD is not available on DIMM */
+	/*
+	 * Set MC registers according to Static SPD values Values -
+	 * must be set manually
+	 */
+	/*
+	 * We only have one optional DIMM for the DB and we already got the
+	 * SPD matching values
+	 */
+	status = ddr3_spd_init(&dimm_info[0], 0, *ddr_width);
+	if (MV_OK != status)
+		return status;
+
+	dimm_num = 1;
+	/* Use JP8 to enable multiCS support for Armada 370 DB */
+	if (!ddr3_check_config(EEPROM_MODULE_ADDR, CONFIG_MULTI_CS))
+		dimm_info[0].num_of_module_ranks = 1;
+	status = ddr3_spd_sum_init(&dimm_info[0], &sum_info, 0);
+	if (MV_OK != status)
+		return status;
+#else
+	/* Dynamic D-Unit Setup - Read SPD values */
+#ifdef DUNIT_SPD
+	dimm_num = ddr3_get_dimm_num(dimm_addr);
+	if (dimm_num == 0) {
+#ifdef MIXED_DIMM_STATIC
+		DEBUG_INIT_S("DDR3 Training Sequence - No DIMMs detected\n");
+#else
+		DEBUG_INIT_S("DDR3 Training Sequence - FAILED (Wrong DIMMs Setup)\n");
+		return MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP;
+#endif
+	} else {
+		DEBUG_INIT_C("DDR3 Training Sequence - Number of DIMMs detected: ",
+			     dimm_num, 1);
+	}
+
+	for (dimm = 0; dimm < dimm_num; dimm++) {
+		status = ddr3_spd_init(&dimm_info[dimm], dimm_addr[dimm],
+				       *ddr_width);
+		if (MV_OK != status)
+			return status;
+		status = ddr3_spd_sum_init(&dimm_info[dimm], &sum_info, dimm);
+		if (MV_OK != status)
+			return status;
+	}
+#endif
+#endif
+
+	/* Set number of enabled CS */
+	cs_num = 0;
+#ifdef DUNIT_STATIC
+	cs_num = ddr3_get_cs_num_from_reg();
+#endif
+#ifdef DUNIT_SPD
+	for (dimm = 0; dimm < dimm_num; dimm++)
+		cs_num += dimm_info[dimm].num_of_module_ranks;
+#endif
+	if (cs_num > MAX_CS) {
+		DEBUG_INIT_C("DDR3 Training Sequence - Number of CS exceed limit -  ",
+			     MAX_CS, 1);
+		return MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT;
+	}
+
+	/* Set bitmap of enabled CS */
+	cs_ena = 0;
+#ifdef DUNIT_STATIC
+	cs_ena = ddr3_get_cs_ena_from_reg();
+#endif
+#ifdef DUNIT_SPD
+	dimm = 0;
+
+	if (dimm_num) {
+		for (cs = 0; cs < MAX_CS; cs += 2) {
+			if (((1 << cs) & DIMM_CS_BITMAP) &&
+			    !(cs_ena & (1 << cs))) {
+				if (dimm_info[dimm].num_of_module_ranks == 1)
+					cs_ena |= (0x1 << cs);
+				else if (dimm_info[dimm].num_of_module_ranks == 2)
+					cs_ena |= (0x3 << cs);
+				else if (dimm_info[dimm].num_of_module_ranks == 3)
+					cs_ena |= (0x7 << cs);
+				else if (dimm_info[dimm].num_of_module_ranks == 4)
+					cs_ena |= (0xF << cs);
+
+				dimm++;
+				if (dimm == dimm_num)
+					break;
+			}
+		}
+	}
+#endif
+
+	if (cs_ena > 0xF) {
+		DEBUG_INIT_C("DDR3 Training Sequence - Number of enabled CS exceed limit -  ",
+			     MAX_CS, 1);
+		return MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT;
+	}
+
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Number of CS = ", cs_num, 1);
+
+	/* Check Ratio - '1' - 2:1, '0' - 1:1 */
+	if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+		ddr_clk_time = hclk_time / 2;
+	else
+		ddr_clk_time = hclk_time;
+
+#ifdef DUNIT_STATIC
+	/* Get target CL value from set register */
+	reg = (reg_read(REG_DDR3_MR0_ADDR) >> 2);
+	reg = ((((reg >> 1) & 0xE)) | (reg & 0x1)) & 0xF;
+
+	cl = ddr3_get_max_val(ddr3_div(sum_info.min_cas_lat_time,
+				       ddr_clk_time, 0),
+			      dimm_num, ddr3_valid_cl_to_cl(reg));
+#else
+	cl = ddr3_div(sum_info.min_cas_lat_time, ddr_clk_time, 0);
+#endif
+	if (cl < 5)
+		cl = 5;
+
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Cas Latency = ", cl, 1);
+
+	/* {0x00001400} -   DDR SDRAM Configuration Register */
+	reg = 0x73004000;
+	stat_val = ddr3_get_static_mc_value(
+		REG_SDRAM_CONFIG_ADDR, REG_SDRAM_CONFIG_ECC_OFFS, 0x1, 0, 0);
+	if (ecc_ena && ddr3_get_min_val(sum_info.err_check_type, dimm_num,
+					stat_val)) {
+		reg |= (1 << REG_SDRAM_CONFIG_ECC_OFFS);
+		reg |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Enabled\n");
+	} else {
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Disabled\n");
+	}
+
+	if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) {
+#ifdef DUNIT_STATIC
+		DEBUG_INIT_S("DDR3 Training Sequence - FAIL - Illegal R-DIMM setup\n");
+		return MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP;
+#endif
+		reg |= (1 << REG_SDRAM_CONFIG_REGDIMM_OFFS);
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - R-DIMM\n");
+	} else {
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - U-DIMM\n");
+	}
+
+#ifndef MV88F67XX
+#ifdef DUNIT_STATIC
+	if (ddr3_get_min_val(sum_info.data_width, dimm_num, BUS_WIDTH) == 64) {
+#else
+	if (*ddr_width == 64) {
+#endif
+		reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS);
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 64Bits\n");
+	} else {
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n");
+	}
+#else
+	DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n");
+#endif
+
+#if defined(MV88F672X)
+	if (*ddr_width == 32) {
+		reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS);
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n");
+	} else {
+		DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n");
+	}
+#endif
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_CONFIG_ADDR, 0,
+					       REG_SDRAM_CONFIG_RFRS_MASK, 0, 0);
+	tmp = ddr3_get_min_val(sum_info.refresh_interval / hclk_time,
+			       dimm_num, stat_val);
+
+#ifdef TREFI_USER_EN
+	tmp = min(TREFI_USER / hclk_time, tmp);
+#endif
+
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - RefreshInterval/Hclk = ", tmp, 4);
+	reg |= tmp;
+
+	if (cl != 3)
+		reg |= (1 << 16);	/*  If 2:1 need to set P2DWr */
+
+#if defined(MV88F672X)
+	reg |= (1 << 27);	/* PhyRfRST = Disable */
+#endif
+	reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+	/*{0x00001404}  -   DDR SDRAM Configuration Register */
+	reg = 0x3630B800;
+#ifdef DUNIT_SPD
+	reg |= (DRAM_2T << REG_DUNIT_CTRL_LOW_2T_OFFS);
+#endif
+	reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+	/* {0x00001408}  -   DDR SDRAM Timing (Low) Register */
+	reg = 0x0;
+
+	/* tRAS - (0:3,20) */
+	spd_val = ddr3_div(sum_info.min_active_to_precharge,
+			    ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    0, 0xF, 16, 0x10);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRAS-1 = ", tmp, 1);
+	reg |= (tmp & 0xF);
+	reg |= ((tmp & 0x10) << 16);	/* to bit 20 */
+
+	/* tRCD - (4:7) */
+	spd_val = ddr3_div(sum_info.min_ras_to_cas_delay, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    4, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRCD-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 4);
+
+	/* tRP - (8:11) */
+	spd_val = ddr3_div(sum_info.min_row_precharge_time, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    8, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRP-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 8);
+
+	/* tWR - (12:15) */
+	spd_val = ddr3_div(sum_info.min_write_recovery_time, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    12, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWR-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 12);
+
+	/* tWTR - (16:19) */
+	spd_val = ddr3_div(sum_info.min_write_to_read_cmd_delay, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    16, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWTR-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 16);
+
+	/* tRRD - (24:27) */
+	spd_val = ddr3_div(sum_info.min_row_active_to_row_active, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    24, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRRD-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 24);
+
+	/* tRTP - (28:31) */
+	spd_val = ddr3_div(sum_info.min_read_to_prech_cmd_delay, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+					    28, 0xF, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRTP-1 = ", tmp, 1);
+	reg |= ((tmp & 0xF) << 28);
+
+	if (cl < 7)
+		reg = 0x33137663;
+
+	reg_write(REG_SDRAM_TIMING_LOW_ADDR, reg);
+
+	/*{0x0000140C}  -   DDR SDRAM Timing (High) Register */
+	/* Add cycles to R2R W2W */
+	reg = 0x39F8FF80;
+
+	/* tRFC - (0:6,16:18) */
+	spd_val = ddr3_div(sum_info.min_refresh_recovery, ddr_clk_time, 1);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_HIGH_ADDR,
+					    0, 0x7F, 9, 0x380);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRFC-1 = ", tmp, 1);
+	reg |= (tmp & 0x7F);
+	reg |= ((tmp & 0x380) << 9);	/* to bit 16 */
+	reg_write(REG_SDRAM_TIMING_HIGH_ADDR, reg);
+
+	/*{0x00001410}  -   DDR SDRAM Address Control Register */
+	reg = 0x000F0000;
+
+	/* tFAW - (24:28)  */
+#if (defined(MV88F78X60) || defined(MV88F672X))
+	tmp = sum_info.min_four_active_win_delay;
+	spd_val = ddr3_div(tmp, ddr_clk_time, 0);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR,
+					    24, 0x3F, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW = ", tmp, 1);
+	reg |= ((tmp & 0x3F) << 24);
+#else
+	tmp = sum_info.min_four_active_win_delay -
+		4 * (sum_info.min_row_active_to_row_active);
+	spd_val = ddr3_div(tmp, ddr_clk_time, 0);
+	stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR,
+					    24, 0x1F, 0, 0);
+	tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+	DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW-4*tRRD = ", tmp, 1);
+	reg |= ((tmp & 0x1F) << 24);
+#endif
+
+	/* SDRAM device capacity */
+#ifdef DUNIT_STATIC
+	reg |= (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & 0xF0FFFF);
+#endif
+
+#ifdef DUNIT_SPD
+	cs_count = 0;
+	dimm_cnt = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+			if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+				dimm_cnt++;
+				cs_count = 0;
+			}
+			cs_count++;
+			if (dimm_info[dimm_cnt].sdram_capacity < 0x3) {
+				reg |= ((dimm_info[dimm_cnt].sdram_capacity + 1) <<
+					(REG_SDRAM_ADDRESS_SIZE_OFFS +
+					 (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs)));
+			} else if (dimm_info[dimm_cnt].sdram_capacity > 0x3) {
+				reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x3) <<
+					(REG_SDRAM_ADDRESS_SIZE_OFFS +
+					 (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs)));
+				reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x4) <<
+					(REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs));
+			}
+		}
+	}
+
+	/* SDRAM device structure */
+	cs_count = 0;
+	dimm_cnt = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+			if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+				dimm_cnt++;
+				cs_count = 0;
+			}
+			cs_count++;
+			if (dimm_info[dimm_cnt].sdram_width == 16)
+				reg |= (1 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs));
+		}
+	}
+#endif
+	reg_write(REG_SDRAM_ADDRESS_CTRL_ADDR, reg);
+
+	/*{0x00001418}  -   DDR SDRAM Operation Register */
+	reg = 0xF00;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs))
+			reg &= ~(1 << (cs + REG_SDRAM_OPERATION_CS_OFFS));
+	}
+	reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+	/*{0x00001420}  -   DDR SDRAM Extended Mode Register */
+	reg = 0x00000004;
+	reg_write(REG_SDRAM_EXT_MODE_ADDR, reg);
+
+	/*{0x00001424}  -   DDR Controller Control (High) Register */
+#if (defined(MV88F78X60) || defined(MV88F672X))
+	reg = 0x0000D3FF;
+#else
+	reg = 0x0100D1FF;
+#endif
+	reg_write(REG_DDR_CONT_HIGH_ADDR, reg);
+
+	/*{0x0000142C}  -   DDR3 Timing Register */
+	reg = 0x014C2F38;
+#if defined(MV88F78X60) || defined(MV88F672X)
+	reg = 0x1FEC2F38;
+#endif
+	reg_write(0x142C, reg);
+
+	/*{0x00001484}  - MBus CPU Block Register */
+#ifdef MV88F67XX
+	if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+		reg_write(REG_MBUS_CPU_BLOCK_ADDR, 0x0000E907);
+#endif
+
+	/*
+	 * In case of mixed dimm and on-board devices setup paramters will
+	 * be taken statically
+	 */
+	/*{0x00001494}  -   DDR SDRAM ODT Control (Low) Register */
+	reg = odt_config[cs_ena];
+	reg_write(REG_SDRAM_ODT_CTRL_LOW_ADDR, reg);
+
+	/*{0x00001498}  -   DDR SDRAM ODT Control (High) Register */
+	reg = 0x00000000;
+	reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+	/*{0x0000149C}  -   DDR Dunit ODT Control Register */
+	reg = cs_ena;
+	reg_write(REG_DUNIT_ODT_CTRL_ADDR, reg);
+
+	/*{0x000014A0}  -   DDR Dunit ODT Control Register */
+#if defined(MV88F672X)
+	reg = 0x000006A9;
+	reg_write(REG_DRAM_FIFO_CTRL_ADDR, reg);
+#endif
+
+	/*{0x000014C0}  -   DRAM address and Control Driving Strenght */
+	reg_write(REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR, 0x192435e9);
+
+	/*{0x000014C4}  -   DRAM Data and DQS Driving Strenght */
+	reg_write(REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR, 0xB2C35E9);
+
+#if (defined(MV88F78X60) || defined(MV88F672X))
+	/*{0x000014CC}  -   DRAM Main Pads Calibration Machine Control Register */
+	reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR);
+	reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg | (1 << 0));
+#endif
+
+#if defined(MV88F672X)
+	/* DRAM Main Pads Calibration Machine Control Register */
+	/* 0x14CC[4:3] - CalUpdateControl = IntOnly */
+	reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR);
+	reg &= 0xFFFFFFE7;
+	reg |= (1 << 3);
+	reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg);
+#endif
+
+#ifdef DUNIT_SPD
+	cs_count = 0;
+	dimm_cnt = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if ((1 << cs) & DIMM_CS_BITMAP) {
+			if ((1 << cs) & cs_ena) {
+				if (dimm_info[dimm_cnt].num_of_module_ranks ==
+				    cs_count) {
+					dimm_cnt++;
+					cs_count = 0;
+				}
+				cs_count++;
+				reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8),
+					  dimm_info[dimm_cnt].rank_capacity - 1);
+			} else {
+				reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8), 0);
+			}
+		}
+	}
+#endif
+
+	/*{0x00020184}  -   Close FastPath - 2G */
+	reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, 0);
+
+	/*{0x00001538}  -    Read Data Sample Delays Register */
+	reg = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs))
+			reg |= (cl << (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+	}
+
+	reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+	DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Sample Delays = ", reg,
+			  1);
+
+	/*{0x0000153C}  -   Read Data Ready Delay Register */
+	reg = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg |= ((cl + 2) <<
+				(REG_READ_DATA_READY_DELAYS_OFFS * cs));
+		}
+	}
+	reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+	DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Ready Delays = ", reg, 1);
+
+	/* Set MR registers */
+	/* MR0 */
+	reg = 0x00000600;
+	tmp = ddr3_cl_to_valid_cl(cl);
+	reg |= ((tmp & 0x1) << 2);
+	reg |= ((tmp & 0xE) << 3);	/* to bit 4 */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg_write(REG_DDR3_MR0_CS_ADDR +
+				  (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* MR1 */
+	reg = 0x00000044 & REG_DDR3_MR1_ODT_MASK;
+	if (cs_num > 1)
+		reg = 0x00000046 & REG_DDR3_MR1_ODT_MASK;
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg |= odt_static[cs_ena][cs];
+			reg_write(REG_DDR3_MR1_CS_ADDR +
+				  (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* MR2 */
+	if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+		tmp = hclk_time / 2;
+	else
+		tmp = hclk_time;
+
+	if (tmp >= 2500)
+		cwl = 5;	/* CWL = 5 */
+	else if (tmp >= 1875 && tmp < 2500)
+		cwl = 6;	/* CWL = 6 */
+	else if (tmp >= 1500 && tmp < 1875)
+		cwl = 7;	/* CWL = 7 */
+	else if (tmp >= 1250 && tmp < 1500)
+		cwl = 8;	/* CWL = 8 */
+	else if (tmp >= 1070 && tmp < 1250)
+		cwl = 9;	/* CWL = 9 */
+	else if (tmp >= 935 && tmp < 1070)
+		cwl = 10;	/* CWL = 10 */
+	else if (tmp >= 833 && tmp < 935)
+		cwl = 11;	/* CWL = 11 */
+	else if (tmp >= 750 && tmp < 833)
+		cwl = 12;	/* CWL = 12 */
+	else {
+		cwl = 12;	/* CWL = 12 */
+		printf("Unsupported hclk %d MHz\n", tmp);
+	}
+
+	reg = ((cwl - 5) << REG_DDR3_MR2_CWL_OFFS);
+
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg &= REG_DDR3_MR2_ODT_MASK;
+			reg |= odt_dynamic[cs_ena][cs];
+			reg_write(REG_DDR3_MR2_CS_ADDR +
+				  (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* MR3 */
+	reg = 0x00000000;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs)) {
+			reg_write(REG_DDR3_MR3_CS_ADDR +
+				  (cs << MR_CS_ADDR_OFFS), reg);
+		}
+	}
+
+	/* {0x00001428}  -   DDR ODT Timing (Low) Register */
+	reg = 0;
+	reg |= (((cl - cwl + 1) & 0xF) << 4);
+	reg |= (((cl - cwl + 6) & 0xF) << 8);
+	reg |= ((((cl - cwl + 6) >> 4) & 0x1) << 21);
+	reg |= (((cl - 1) & 0xF) << 12);
+	reg |= (((cl + 6) & 0x1F) << 16);
+	reg_write(REG_ODT_TIME_LOW_ADDR, reg);
+
+	/* {0x0000147C}  -   DDR ODT Timing (High) Register */
+	reg = 0x00000071;
+	reg |= ((cwl - 1) << 8);
+	reg |= ((cwl + 5) << 12);
+	reg_write(REG_ODT_TIME_HIGH_ADDR, reg);
+
+#ifdef DUNIT_SPD
+	/*{0x000015E0} - DDR3 Rank Control Register */
+	reg = cs_ena;
+	cs_count = 0;
+	dimm_cnt = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+			if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+				dimm_cnt++;
+				cs_count = 0;
+			}
+			cs_count++;
+
+			if (dimm_info[dimm_cnt].addr_mirroring &&
+			    (cs == 1 || cs == 3) &&
+			    (sum_info.type_info != SPD_MODULE_TYPE_RDIMM)) {
+				reg |= (1 << (REG_DDR3_RANK_CTRL_MIRROR_OFFS + cs));
+				DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Setting Address Mirroring for CS = ",
+						  cs, 1);
+			}
+		}
+	}
+	reg_write(REG_DDR3_RANK_CTRL_ADDR, reg);
+#endif
+
+	/*{0xD00015E4}  -   ZQDS Configuration Register */
+	reg = 0x00203c18;
+	reg_write(REG_ZQC_CONF_ADDR, reg);
+
+	/* {0x00015EC}  -   DDR PHY */
+#if defined(MV88F78X60)
+	reg = 0xF800AAA5;
+	if (mv_ctrl_rev_get() == MV_78XX0_B0_REV)
+		reg = 0xF800A225;
+#else
+	reg = 0xDE000025;
+#if defined(MV88F672X)
+	reg = 0xF800A225;
+#endif
+#endif
+	reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+#if (defined(MV88F78X60) || defined(MV88F672X))
+	/* Registered DIMM support - supported only in AXP A0 devices */
+	/* Currently supported for SPD detection only */
+	/*
+	 * Flow is according to the Registered DIMM chapter in the
+	 * Functional Spec
+	 */
+	if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) {
+		DEBUG_INIT_S("DDR3 Training Sequence - Registered DIMM detected\n");
+
+		/* Set commands parity completion */
+		reg = reg_read(REG_REGISTERED_DRAM_CTRL_ADDR);
+		reg &= ~REG_REGISTERED_DRAM_CTRL_PARITY_MASK;
+		reg |= 0x8;
+		reg_write(REG_REGISTERED_DRAM_CTRL_ADDR, reg);
+
+		/* De-assert M_RESETn and assert M_CKE */
+		reg_write(REG_SDRAM_INIT_CTRL_ADDR,
+			  1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS);
+		do {
+			reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+				(1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS);
+		} while (reg);
+
+		for (rc = 0; rc < SPD_RDIMM_RC_NUM; rc++) {
+			if (rc != 6 && rc != 7) {
+				/* Set CWA Command */
+				reg = (REG_SDRAM_OPERATION_CMD_CWA &
+				       ~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+				reg |= ((dimm_info[0].dimm_rc[rc] &
+					 REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+					REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+				reg |= rc << REG_SDRAM_OPERATION_CWA_RC_OFFS;
+				/* Configure - Set Delay - tSTAB/tMRD */
+				if (rc == 2 || rc == 10)
+					reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+				/* 0x1418 - SDRAM Operation Register */
+				reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+				/*
+				 * Poll the "cmd" field in the SDRAM OP
+				 * register for 0x0
+				 */
+				do {
+					reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+						(REG_SDRAM_OPERATION_CMD_MASK);
+				} while (reg);
+			}
+		}
+	}
+#endif
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_div - this function divides integers
+ * Desc:
+ * Args:     val - the value
+ *           divider - the divider
+ *           sub - substruction value
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_div(u32 val, u32 divider, u32 sub)
+{
+	return val / divider + (val % divider > 0 ? 1 : 0) - sub;
+}
+
+/*
+ * Name:     ddr3_get_max_val
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val)
+{
+#ifdef DUNIT_STATIC
+	if (dimm_num > 0) {
+		if (spd_val >= static_val)
+			return spd_val;
+		else
+			return static_val;
+	} else {
+		return static_val;
+	}
+#else
+	return spd_val;
+#endif
+}
+
+/*
+ * Name:     ddr3_get_min_val
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val)
+{
+#ifdef DUNIT_STATIC
+	if (dimm_num > 0) {
+		if (spd_val <= static_val)
+			return spd_val;
+		else
+			return static_val;
+	} else
+		return static_val;
+#else
+	return spd_val;
+#endif
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_write_leveling.c b/drivers/ddr/mvebu/ddr3_write_leveling.c
new file mode 100644
index 0000000..df3a3df
--- /dev/null
+++ b/drivers/ddr/mvebu/ddr3_write_leveling.c
@@ -0,0 +1,1366 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_WL_C(s, d, l) \
+	DEBUG_WL_S(s); DEBUG_WL_D(d, l); DEBUG_WL_S("\n")
+#define DEBUG_WL_FULL_C(s, d, l) \
+	DEBUG_WL_FULL_S(s); DEBUG_WL_FULL_D(d, l); DEBUG_WL_FULL_S("\n")
+
+#ifdef MV_DEBUG_WL
+#define DEBUG_RL_S(s) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_RL_D(d, l) \
+	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+#else
+#define DEBUG_WL_S(s)
+#define DEBUG_WL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_WL_FULL
+#define DEBUG_WL_FULL_S(s)		puts(s)
+#define DEBUG_WL_FULL_D(d, l)		printf("%x", d)
+#else
+#define DEBUG_WL_FULL_S(s)
+#define DEBUG_WL_FULL_D(d, l)
+#endif
+
+#define WL_SUP_EXPECTED_DATA		0x21
+#define WL_SUP_READ_DRAM_ENTRY		0x8
+
+static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
+					 u32 *result,
+					 MV_DRAM_INFO *dram_info);
+static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr,
+				    u32 data);
+
+extern u16 odt_static[ODT_OPT][MAX_CS];
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+extern u32 wl_sup_pattern[LEN_WL_SUP_PATTERN];
+
+/*
+ * Name:     ddr3_write_leveling_hw
+ * Desc:     Execute Write leveling phase by HW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info)
+{
+	u32 reg, phase, delay, cs, pup;
+#ifdef MV88F67XX
+	int dpde_flag = 0;
+#endif
+	/* Debug message - Start Read leveling procedure */
+	DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+		dpde_flag = 1;
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+	}
+#endif
+
+	reg = 1 << REG_DRAM_TRAINING_WL_OFFS;
+	/* Config the retest number */
+	reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
+	reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	reg =  reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+	/* Wait */
+	do {
+		reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+			(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+	/* Check if Successful */
+	if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+		/*
+		 * Read results to arrays - Results are required for WL
+		 * High freq Supplement and DQS Centralization
+		 */
+		for (cs = 0; cs < MAX_CS; cs++) {
+			if (dram_info->cs_ena & (1 << cs)) {
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups
+					    && dram_info->ecc_ena)
+						pup = ECC_PUP;
+					reg =
+					    ddr3_read_pup_reg(PUP_WL_MODE, cs,
+							      pup);
+					phase =
+					    (reg >> REG_PHY_PHASE_OFFS) &
+					    PUP_PHASE_MASK;
+					delay = reg & PUP_DELAY_MASK;
+					dram_info->wl_val[cs][pup][P] = phase;
+					dram_info->wl_val[cs][pup][D] = delay;
+					dram_info->wl_val[cs][pup][S] =
+					    WL_HI_FREQ_STATE - 1;
+					reg =
+					    ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
+							      cs, pup);
+					dram_info->wl_val[cs][pup][DQS] =
+					    (reg & 0x3F);
+				}
+
+#ifdef MV_DEBUG_WL
+				/* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
+				DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
+				DEBUG_WL_D((u32) cs, 1);
+				DEBUG_WL_S(" Results:\n");
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups
+					    && dram_info->ecc_ena)
+						pup = ECC_PUP;
+					DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
+					DEBUG_WL_D((u32) pup, 1);
+					DEBUG_WL_S(", Phase: ");
+					DEBUG_WL_D((u32)
+						   dram_info->wl_val[cs][pup]
+						   [P], 1);
+					DEBUG_WL_S(", Delay: ");
+					DEBUG_WL_D((u32)
+						   dram_info->wl_val[cs][pup]
+						   [D], 2);
+					DEBUG_WL_S("\n");
+				}
+#endif
+			}
+		}
+
+		/* Dynamic pad issue (BTS669) during WL */
+#ifdef MV88F67XX
+		if (dpde_flag) {
+			reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+				(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+			reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+		}
+#endif
+
+		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+
+		return MV_OK;
+	} else {
+		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Error\n");
+		return MV_FAIL;
+	}
+}
+
+/*
+ * Name:     ddr3_wl_supplement
+ * Desc:     Write Leveling Supplement
+ * Args:     dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_wl_supplement(MV_DRAM_INFO *dram_info)
+{
+	u32 cs, cnt, pup_num, sum, phase, delay, max_pup_num, pup, sdram_offset;
+	u32 tmp_count, ecc, reg;
+	u32 ddr_width, tmp_pup, idx;
+	u32 sdram_pup_val, uj;
+	u32 one_clk_err = 0, align_err = 0, no_err = 0, err = 0, err_n = 0;
+	u32 sdram_data[LEN_WL_SUP_PATTERN] __aligned(32) = { 0 };
+
+	ddr_width = dram_info->ddr_width;
+	no_err = 0;
+
+	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Starting\n");
+
+	switch (ddr_width) {
+		/* Data error from pos-adge to pos-adge */
+	case 16:
+		one_clk_err = 4;
+		align_err = 4;
+		break;
+	case 32:
+		one_clk_err = 8;
+		align_err = 8;
+		break;
+	case 64:
+		one_clk_err = 0x10;
+		align_err = 0x10;
+		break;
+	default:
+		DEBUG_WL_S("Error - bus width!!!\n");
+		return MV_FAIL;
+	}
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - SW Override Enabled\n");
+	reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+	tmp_count = 0;
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			sum = 0;
+			/*
+			 * 2 iterations loop: 1)actual WL results 2) fix WL
+			 * if needed
+			 */
+			for (cnt = 0; cnt < COUNT_WL_HI_FREQ; cnt++) {
+				DEBUG_WL_C("COUNT = ", cnt, 1);
+				for (ecc = 0; ecc < (dram_info->ecc_ena + 1);
+				     ecc++) {
+					if (ecc) {
+						DEBUG_WL_S("ECC PUP:\n");
+					} else {
+						DEBUG_WL_S("DATA PUP:\n");
+					}
+
+					max_pup_num =
+					    dram_info->num_of_std_pups * (1 -
+									  ecc) +
+					    ecc;
+					/* ECC Support - Switch ECC Mux on ecc=1 */
+					reg =
+					    (reg_read(REG_DRAM_TRAINING_2_ADDR)
+					     & ~(1 <<
+						 REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
+					reg |=
+					    (dram_info->ecc_ena *
+					     ecc <<
+					     REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+					reg_write(REG_DRAM_TRAINING_2_ADDR,
+						  reg);
+					ddr3_reset_phy_read_fifo();
+
+					/* Write to memory */
+					sdram_offset =
+					    tmp_count * (SDRAM_CS_SIZE + 1) +
+					    0x200;
+					if (MV_OK != ddr3_dram_sram_burst((u32)
+									  wl_sup_pattern,
+									  sdram_offset,
+									  LEN_WL_SUP_PATTERN))
+						return MV_FAIL;
+
+					/* Read from memory */
+					if (MV_OK !=
+					    ddr3_dram_sram_burst(sdram_offset,
+								 (u32)
+								 sdram_data,
+								 LEN_WL_SUP_PATTERN))
+						return MV_FAIL;
+
+					/* Print the buffer */
+					for (uj = 0; uj < LEN_WL_SUP_PATTERN;
+					     uj++) {
+						if ((uj % 4 == 0) && (uj != 0)) {
+							DEBUG_WL_S("\n");
+						}
+						DEBUG_WL_D(sdram_data[uj],
+							   8);
+						DEBUG_WL_S(" ");
+					}
+
+					/* Check pup which DQS/DATA is error */
+					for (pup = 0; pup < max_pup_num; pup++) {
+						/* ECC support - bit 8 */
+						pup_num = (ecc) ? ECC_PUP : pup;
+						if (pup < 4) {	/* lower 32 bit */
+							tmp_pup = pup;
+							idx =
+							    WL_SUP_READ_DRAM_ENTRY;
+						} else {	/* higher 32 bit */
+							tmp_pup = pup - 4;
+							idx =
+							    WL_SUP_READ_DRAM_ENTRY
+							    + 1;
+						}
+						DEBUG_WL_S("\nCS: ");
+						DEBUG_WL_D((u32) cs, 1);
+						DEBUG_WL_S(" PUP: ");
+						DEBUG_WL_D((u32) pup_num, 1);
+						DEBUG_WL_S("\n");
+						sdram_pup_val =
+						    ((sdram_data[idx] >>
+						      ((tmp_pup) * 8)) & 0xFF);
+						DEBUG_WL_C("Actual Data = ",
+							   sdram_pup_val, 2);
+						DEBUG_WL_C("Expected Data = ",
+							   (WL_SUP_EXPECTED_DATA
+							    + pup), 2);
+						/*
+						 * ALINGHMENT: calculate
+						 * expected data vs actual data
+						 */
+						err =
+						    (WL_SUP_EXPECTED_DATA +
+						     pup) - sdram_pup_val;
+						/*
+						 * CLOCK LONG: calculate
+						 * expected data vs actual data
+						 */
+						err_n =
+						    sdram_pup_val -
+						    (WL_SUP_EXPECTED_DATA +
+						     pup);
+						DEBUG_WL_C("err = ", err, 2);
+						DEBUG_WL_C("err_n = ", err_n,
+							   2);
+						if (err == no_err) {
+							/* PUP is correct - increment State */
+							dram_info->wl_val[cs]
+							    [pup_num]
+							    [S] = 1;
+						} else if (err_n == one_clk_err) {
+							/* clock is longer than DQS */
+							phase =
+							    ((dram_info->wl_val
+							      [cs]
+							      [pup_num][P] +
+							      WL_HI_FREQ_SHIFT)
+							     % MAX_PHASE_2TO1);
+							dram_info->wl_val[cs]
+							    [pup_num]
+							    [P] = phase;
+							delay =
+							    dram_info->wl_val
+							    [cs][pup_num]
+							    [D];
+							DEBUG_WL_S("#### Clock is longer than DQS more than one clk cycle ####\n");
+							ddr3_write_pup_reg
+							    (PUP_WL_MODE, cs,
+							     pup * (1 - ecc) +
+							     ECC_PUP * ecc,
+							     phase, delay);
+						} else if (err == align_err) {
+							/* clock is align to DQS */
+							phase =
+							    dram_info->wl_val
+							    [cs][pup_num]
+							    [P];
+							delay =
+							    dram_info->wl_val
+							    [cs][pup_num]
+							    [D];
+							DEBUG_WL_S("#### Alignment PUPS problem ####\n");
+							if ((phase == 0)
+							    || ((phase == 1)
+								&& (delay <=
+								    0x10))) {
+								DEBUG_WL_S("#### Warning - Possible Layout Violation (DQS is longer than CLK)####\n");
+							}
+
+							phase = 0x0;
+							delay = 0x0;
+							dram_info->wl_val[cs]
+							    [pup_num]
+							    [P] = phase;
+							dram_info->wl_val[cs]
+							    [pup_num]
+							    [D] = delay;
+							ddr3_write_pup_reg
+							    (PUP_WL_MODE, cs,
+							     pup * (1 - ecc) +
+							     ECC_PUP * ecc,
+							     phase, delay);
+						}
+						/* Stop condition for ECC phase */
+						pup = (ecc) ? max_pup_num : pup;
+					}
+
+					/* ECC Support - Disable ECC MUX */
+					reg =
+					    (reg_read(REG_DRAM_TRAINING_2_ADDR)
+					     & ~(1 <<
+						 REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
+					reg_write(REG_DRAM_TRAINING_2_ADDR,
+						  reg);
+				}
+			}
+
+			for (pup = 0; pup < dram_info->num_of_std_pups; pup++)
+				sum += dram_info->wl_val[cs][pup][S];
+
+			if (dram_info->ecc_ena)
+				sum += dram_info->wl_val[cs][ECC_PUP][S];
+
+			/* Checks if any pup is not locked after the change */
+			if (sum < (WL_HI_FREQ_STATE * (dram_info->num_of_total_pups))) {
+				DEBUG_WL_C("DDR3 - Write Leveling Hi-Freq Supplement - didn't work for Cs - ",
+					   (u32) cs, 1);
+				return MV_FAIL;
+			}
+			tmp_count++;
+		}
+	}
+
+	dram_info->wl_max_phase = 0;
+	dram_info->wl_min_phase = 10;
+
+	/*
+	 * Read results to arrays - Results are required for DQS Centralization
+	 */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+				if (pup == dram_info->num_of_std_pups
+				    && dram_info->ecc_ena)
+					pup = ECC_PUP;
+				reg = ddr3_read_pup_reg(PUP_WL_MODE, cs, pup);
+				phase =
+				    (reg >> REG_PHY_PHASE_OFFS) &
+				    PUP_PHASE_MASK;
+				if (phase > dram_info->wl_max_phase)
+					dram_info->wl_max_phase = phase;
+				if (phase < dram_info->wl_min_phase)
+					dram_info->wl_min_phase = phase;
+			}
+		}
+	}
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Ended Successfully\n");
+
+	return MV_OK;
+}
+
+/*
+ * Name:     ddr3_write_leveling_hw_reg_dimm
+ * Desc:     Execute Write leveling phase by HW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_hw_reg_dimm(u32 freq, MV_DRAM_INFO *dram_info)
+{
+	u32 reg, phase, delay, cs, pup, pup_num;
+	__maybe_unused int dpde_flag = 0;
+
+	/* Debug message - Start Read leveling procedure */
+	DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
+
+	if (dram_info->num_cs > 2) {
+		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+		return MV_NO_CHANGE;
+	}
+
+	/* If target freq = 400 move clock start point */
+	/* Write to control PUP to Control Deskew Regs */
+	if (freq <= DDR_400) {
+		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+			/* PUP_DELAY_MASK 0x1F */
+			/* reg = 0x0C10001F + (uj << 16); */
+			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+						0x1F);
+		}
+	}
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+		dpde_flag = 1;
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+	}
+#endif
+
+	reg = (1 << REG_DRAM_TRAINING_WL_OFFS);
+	/* Config the retest number */
+	reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
+	reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
+	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
+
+	reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+	/* Wait */
+	do {
+		reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+			(1 << REG_DRAM_TRAINING_AUTO_OFFS);
+	} while (reg);		/* Wait for '0' */
+
+	reg = reg_read(REG_DRAM_TRAINING_ADDR);
+	/* Check if Successful */
+	if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+		/*
+		 * Read results to arrays - Results are required for WL High
+		 * freq Supplement and DQS Centralization
+		 */
+		for (cs = 0; cs < MAX_CS; cs++) {
+			if (dram_info->cs_ena & (1 << cs)) {
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					if (pup == dram_info->num_of_std_pups
+					    && dram_info->ecc_ena)
+						pup = ECC_BIT;
+					reg =
+					    ddr3_read_pup_reg(PUP_WL_MODE, cs,
+							      pup);
+					phase =
+					    (reg >> REG_PHY_PHASE_OFFS) &
+					    PUP_PHASE_MASK;
+					delay = reg & PUP_DELAY_MASK;
+					dram_info->wl_val[cs][pup][P] = phase;
+					dram_info->wl_val[cs][pup][D] = delay;
+					if ((phase == 1) && (delay >= 0x1D)) {
+						/*
+						 * Need to do it here for
+						 * uncorrect WL values
+						 */
+						ddr3_write_pup_reg(PUP_WL_MODE,
+								   cs, pup, 0,
+								   0);
+						dram_info->wl_val[cs][pup][P] =
+						    0;
+						dram_info->wl_val[cs][pup][D] =
+						    0;
+					}
+					dram_info->wl_val[cs][pup][S] =
+					    WL_HI_FREQ_STATE - 1;
+					reg =
+					    ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
+							      cs, pup);
+					dram_info->wl_val[cs][pup][DQS] =
+					    (reg & 0x3F);
+				}
+#ifdef MV_DEBUG_WL
+				/*
+				 * Debug message - Print res for cs[i]:
+				 * cs,PUP,Phase,Delay
+				 */
+				DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
+				DEBUG_WL_D((u32) cs, 1);
+				DEBUG_WL_S(" Results:\n");
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					DEBUG_WL_S
+					    ("DDR3 - Write Leveling - PUP: ");
+					DEBUG_WL_D((u32) pup, 1);
+					DEBUG_WL_S(", Phase: ");
+					DEBUG_WL_D((u32)
+						   dram_info->wl_val[cs][pup]
+						   [P], 1);
+					DEBUG_WL_S(", Delay: ");
+					DEBUG_WL_D((u32)
+						   dram_info->wl_val[cs][pup]
+						   [D], 2);
+					DEBUG_WL_S("\n");
+				}
+#endif
+			}
+		}
+
+#ifdef MV88F67XX
+		/* Dynamic pad issue (BTS669) during WL */
+		if (dpde_flag) {
+			reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+				(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+			reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+		}
+#endif
+		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+
+		/* If target freq = 400 move clock back */
+		/* Write to control PUP to Control Deskew Regs */
+		if (freq <= DDR_400) {
+			for (pup = 0; pup <= dram_info->num_of_total_pups;
+			     pup++) {
+				ddr3_write_ctrl_pup_reg(1, pup,
+							CNTRL_PUP_DESKEW + pup, 0);
+			}
+		}
+
+		return MV_OK;
+	} else {
+		/* Configure Each PUP with locked leveling settings */
+		for (cs = 0; cs < MAX_CS; cs++) {
+			if (dram_info->cs_ena & (1 << cs)) {
+				for (pup = 0;
+				     pup < dram_info->num_of_total_pups;
+				     pup++) {
+					/* ECC support - bit 8 */
+					pup_num = (pup == dram_info->num_of_std_pups) ?
+						ECC_BIT : pup;
+					ddr3_write_pup_reg(PUP_WL_MODE, cs,
+							   pup_num, 0, 0);
+				}
+			}
+		}
+
+		reg_write(REG_DRAM_TRAINING_ADDR, 0);
+
+		/* If target freq = 400 move clock back */
+		/* Write to control PUP to Control Deskew Regs */
+		if (freq <= DDR_400) {
+			for (pup = 0; pup <= dram_info->num_of_total_pups;
+			     pup++) {
+				ddr3_write_ctrl_pup_reg(1, pup,
+							CNTRL_PUP_DESKEW + pup, 0);
+			}
+		}
+
+		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+		return MV_NO_CHANGE;
+	}
+}
+
+/*
+ * Name:     ddr3_write_leveling_sw
+ * Desc:     Execute Write leveling phase by SW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+	u32 reg, cs, cnt, pup, max_pup_num;
+	u32 res[MAX_CS];
+	max_pup_num = dram_info->num_of_total_pups;
+	__maybe_unused int dpde_flag = 0;
+
+	/* Debug message - Start Write leveling procedure */
+	DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+		dpde_flag = 1;
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+	}
+#endif
+
+	/* Set Output buffer-off to all CS and correct ODT values */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_ODT_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+
+			/* 0x15D0 - DDR3 MR0 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
+
+	/* Enable PHY write leveling mode */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+	/* [2] = 0 - TrnWLMode - Enable */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	/* Reset WL results arry */
+	memset(dram_info->wl_val, 0, sizeof(u32) * MAX_CS * MAX_PUP_NUM * 7);
+
+	/* Loop for each cs */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
+					(u32) cs, 1);
+			/* Refresh X9 current cs */
+			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
+			for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
+				reg =
+				    REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
+								     (REG_SDRAM_OPERATION_CS_OFFS
+								      + cs));
+				/* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
+				reg_write(REG_SDRAM_OPERATION_ADDR, reg);	/* 0x1418 - SDRAM Operation Register */
+
+				do {
+					reg =
+					    ((reg_read
+					      (REG_SDRAM_OPERATION_ADDR)) &
+					     REG_SDRAM_OPERATION_CMD_RFRS_DONE);
+				} while (reg);	/* Wait for '0' */
+			}
+
+			/* Configure MR1 in Cs[CsNum] - write leveling on, output buffer on */
+			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_OUTBUF_WL_MASK;
+			/* Set ODT Values */
+			reg &= REG_DDR3_MR1_ODT_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+			/* Enable WL MODE */
+			reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
+			/* [7]=1, [12]=0 - Output Buffer and write leveling enabled */
+			reg_write(REG_DDR3_MR1_ADDR, reg);	/* 0x15D4 - DDR3 MR1 Register */
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+
+			/* Write leveling  cs[cs] */
+			if (MV_OK !=
+			    ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
+							  (u32 *)(res + cs),
+							  dram_info)) {
+				DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
+						(u32) cs, 1);
+				for (pup = 0; pup < max_pup_num; pup++) {
+					if (((res[cs] >> pup) & 0x1) == 0) {
+						DEBUG_WL_C("Failed Byte : ",
+							   pup, 1);
+					}
+				}
+				return MV_FAIL;
+			}
+
+			/* Set TrnWLDeUpd - After each CS is done */
+			reg = reg_read(REG_TRAINING_WL_ADDR) |
+				(1 << REG_TRAINING_WL_CS_DONE_OFFS);
+			/* 0x16AC - Training Write leveling register */
+			reg_write(REG_TRAINING_WL_ADDR, reg);
+
+			/*
+			 * Debug message - Finished Write leveling cs[cs] -
+			 * each PUP Fail/Success
+			 */
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
+					1);
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
+					(u32) res[cs], 3);
+
+			/*
+			 * Configure MR1 in cs[cs] - write leveling off (0),
+			 * output buffer off (1)
+			 */
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_OUTBUF_WL_MASK;
+			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+			/* No need to sort ODT since it is same CS */
+			/* 0x15D4 - DDR3 MR1 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+	/* Disable WL Mode */
+	/* [2]=1 - TrnWLMode - Disable */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Set Output buffer-on to all CS and correct ODT values */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_ODT_MASK;
+			reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+
+			/* 0x15D0 - DDR3 MR1 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	if (dpde_flag) {
+		reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+			(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+	}
+#endif
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
+
+	return MV_OK;
+}
+
+#if !defined(MV88F672X)
+/*
+ * Name:     ddr3_write_leveling_sw
+ * Desc:     Execute Write leveling phase by SW
+ * Args:     freq        - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_sw_reg_dimm(u32 freq, int ratio_2to1,
+				    MV_DRAM_INFO *dram_info)
+{
+	u32 reg, cs, cnt, pup;
+	u32 res[MAX_CS];
+	__maybe_unused int dpde_flag = 0;
+
+	/* Debug message - Start Write leveling procedure */
+	DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+		dpde_flag = 1;
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+	}
+#endif
+
+	/* If target freq = 400 move clock start point */
+	/* Write to control PUP to Control Deskew Regs */
+	if (freq <= DDR_400) {
+		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+			/* PUP_DELAY_MASK 0x1F */
+			/* reg = 0x0C10001F + (uj << 16); */
+			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+						0x1F);
+		}
+	}
+
+	/* Set Output buffer-off to all CS and correct ODT values */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_ODT_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+
+			/* 0x15D0 - DDR3 MR0 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
+
+	/* Enable SW override */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* [0] = 1 - Enable SW override  */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
+
+	/* Enable PHY write leveling mode */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+		~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+	/* [2] = 0 - TrnWLMode - Enable */
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Loop for each cs */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
+					(u32) cs, 1);
+
+			/* Refresh X9 current cs */
+			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
+			for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
+				reg =
+				    REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
+								     (REG_SDRAM_OPERATION_CS_OFFS
+								      + cs));
+				/* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
+				reg_write(REG_SDRAM_OPERATION_ADDR, reg);	/* 0x1418 - SDRAM Operation Register */
+
+				do {
+					reg =
+					    ((reg_read
+					      (REG_SDRAM_OPERATION_ADDR)) &
+					     REG_SDRAM_OPERATION_CMD_RFRS_DONE);
+				} while (reg);	/* Wait for '0' */
+			}
+
+			/*
+			 * Configure MR1 in Cs[CsNum] - write leveling on,
+			 * output buffer on
+			 */
+			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_OUTBUF_WL_MASK;
+			/* Set ODT Values */
+			reg &= REG_DDR3_MR1_ODT_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+			/* Enable WL MODE */
+			reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
+			/*
+			 * [7]=1, [12]=0 - Output Buffer and write leveling
+			 * enabled
+			 */
+			/* 0x15D4 - DDR3 MR1 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+
+			/* Write leveling  cs[cs] */
+			if (MV_OK !=
+			    ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
+							  (u32 *)(res + cs),
+							  dram_info)) {
+				DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
+						(u32) cs, 1);
+				return MV_FAIL;
+			}
+
+			/* Set TrnWLDeUpd - After each CS is done */
+			reg = reg_read(REG_TRAINING_WL_ADDR) |
+				(1 << REG_TRAINING_WL_CS_DONE_OFFS);
+			/* 0x16AC - Training Write leveling register */
+			reg_write(REG_TRAINING_WL_ADDR, reg);
+
+			/*
+			 * Debug message - Finished Write leveling cs[cs] -
+			 * each PUP Fail/Success
+			 */
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
+					1);
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
+					(u32) res[cs], 3);
+
+			/* Configure MR1 in cs[cs] - write leveling off (0), output buffer off (1) */
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_OUTBUF_WL_MASK;
+			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+			/* No need to sort ODT since it is same CS */
+			/* 0x15D4 - DDR3 MR1 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+	/* Disable WL Mode */
+	/* [2]=1 - TrnWLMode - Disable */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Disable SW override - Must be in a different stage */
+	/* [0]=0 - Enable SW override  */
+	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+	/* 0x15B8 - Training SW 2 Register */
+	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+	/* Set Output buffer-on to all CS and correct ODT values */
+	for (cs = 0; cs < MAX_CS; cs++) {
+		if (dram_info->cs_ena & (1 << cs)) {
+			reg = reg_read(REG_DDR3_MR1_ADDR) &
+				REG_DDR3_MR1_ODT_MASK;
+			reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
+			reg |= odt_static[dram_info->cs_ena][cs];
+
+			/* 0x15D0 - DDR3 MR1 Register */
+			reg_write(REG_DDR3_MR1_ADDR, reg);
+			/* Issue MRS Command to current cs */
+			reg = REG_SDRAM_OPERATION_CMD_MR1 &
+				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+			/*
+			 * [3-0] = 0x4 - MR1 Command, [11-8] -
+			 * enable current cs
+			 */
+			/* 0x1418 - SDRAM Operation Register */
+			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+			udelay(MRS_DELAY);
+		}
+	}
+
+#ifdef MV88F67XX
+	/* Dynamic pad issue (BTS669) during WL */
+	if (dpde_flag) {
+		reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+			(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+		reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+	}
+#endif
+
+	/* If target freq = 400 move clock back */
+	/* Write to control PUP to Control Deskew Regs */
+	if (freq <= DDR_400) {
+		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+						0);
+		}
+	}
+
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
+	return MV_OK;
+}
+#endif
+
+/*
+ * Name:     ddr3_write_leveling_single_cs
+ * Desc:     Execute Write leveling for single Chip select
+ * Args:     cs          - current chip select
+ *           freq        - current sequence frequency
+ *           result      - res array
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
+					 u32 *result, MV_DRAM_INFO *dram_info)
+{
+	u32 reg, pup_num, delay, phase, phaseMax, max_pup_num, pup,
+		max_pup_mask;
+
+	max_pup_num = dram_info->num_of_total_pups;
+	*result = 0;
+	u32 flag[MAX_PUP_NUM] = { 0 };
+
+	DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - WL for Cs - ",
+			(u32) cs, 1);
+
+	switch (max_pup_num) {
+	case 2:
+		max_pup_mask = 0x3;
+		break;
+	case 4:
+		max_pup_mask = 0xf;
+		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+		break;
+	case 5:
+		max_pup_mask = 0x1f;
+		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+		break;
+	case 8:
+		max_pup_mask = 0xff;
+		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+		break;
+	case 9:
+		max_pup_mask = 0x1ff;
+		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+		break;
+	default:
+		DEBUG_WL_C("ddr3_write_leveling_single_cs wrong max_pup_num =  ",
+			   max_pup_num, 3);
+		return MV_FAIL;
+	}
+
+	/* CS ODT Override */
+	reg = reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
+		REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
+	reg |= (REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA << (2 * cs));
+	/* Set 0x3 - Enable ODT on the curent cs and disable on other cs */
+	/* 0x1498 - SDRAM ODT Control high */
+	reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - ODT Asserted for current Cs\n");
+
+	/* tWLMRD Delay */
+	/* Delay of minimum 40 Dram clock cycles - 20 Tclk cycles */
+	udelay(1);
+
+	/* [1:0] - current cs number */
+	reg = (reg_read(REG_TRAINING_WL_ADDR) & REG_TRAINING_WL_CS_MASK) | cs;
+	reg |= (1 << REG_TRAINING_WL_UPD_OFFS);	/* [2] - trnWLCsUpd */
+	/* 0x16AC - Training Write leveling register */
+	reg_write(REG_TRAINING_WL_ADDR, reg);
+
+	/* Broadcast to all PUPs: Reset DQS phase, reset leveling delay */
+	ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, 0, 0);
+
+	/* Seek Edge */
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Current Cs\n");
+
+	/* Drive DQS high for one cycle - All data PUPs */
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Driving DQS high for one cycle\n");
+	if (!ratio_2to1) {
+		reg = (reg_read(REG_TRAINING_WL_ADDR) &
+		       REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_1TO1;
+	} else {
+		reg = (reg_read(REG_TRAINING_WL_ADDR) &
+		       REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_2TO1;
+	}
+	/* 0x16AC - Training Write leveling register */
+	reg_write(REG_TRAINING_WL_ADDR, reg);
+
+	/* Wait tWLdelay */
+	do {
+		/* [29] - trnWLDelayExp */
+		reg = (reg_read(REG_TRAINING_WL_ADDR)) &
+			REG_TRAINING_WL_DELAYEXP_MASK;
+	} while (reg == 0x0);	/* Wait for '1' */
+
+	/* Read WL res */
+	reg = (reg_read(REG_TRAINING_WL_ADDR) >> REG_TRAINING_WL_RESULTS_OFFS) &
+		REG_TRAINING_WL_RESULTS_MASK;
+	/* [28:20] - TrnWLResult */
+
+	if (!ratio_2to1) /* Different phase options for 2:1 or 1:1 modes */
+		phaseMax = MAX_PHASE_1TO1;
+	else
+		phaseMax = MAX_PHASE_2TO1;
+
+	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Shift DQS + Octet Leveling\n");
+
+	/* Shift DQS + Octet leveling */
+	for (phase = 0; phase < phaseMax; phase++) {
+		for (delay = 0; delay < MAX_DELAY; delay++) {
+			/*  Broadcast to all PUPs: DQS phase,leveling delay */
+			ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, phase,
+					   delay);
+
+			udelay(1);	/* Delay of  3 Tclk cycles */
+
+			DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge: Phase = ");
+			DEBUG_WL_FULL_D((u32) phase, 1);
+			DEBUG_WL_FULL_S(", Delay = ");
+			DEBUG_WL_FULL_D((u32) delay, 1);
+			DEBUG_WL_FULL_S(", Counter = ");
+			DEBUG_WL_FULL_D((u32) i, 1);
+			DEBUG_WL_FULL_S("\n");
+
+			/* Drive DQS high for one cycle - All data PUPs */
+			if (!ratio_2to1) {
+				reg = (reg_read(REG_TRAINING_WL_ADDR) &
+				       REG_TRAINING_WL_RATIO_MASK) |
+					REG_TRAINING_WL_1TO1;
+			} else {
+				reg = (reg_read(REG_TRAINING_WL_ADDR) &
+				       REG_TRAINING_WL_RATIO_MASK) |
+					REG_TRAINING_WL_2TO1;
+			}
+			reg_write(REG_TRAINING_WL_ADDR, reg);	/* 0x16AC  */
+
+			/* Wait tWLdelay */
+			do {
+				reg = (reg_read(REG_TRAINING_WL_ADDR)) &
+					REG_TRAINING_WL_DELAYEXP_MASK;
+			} while (reg == 0x0);	/* [29] Wait for '1' */
+
+			/* Read WL res */
+			reg = reg_read(REG_TRAINING_WL_ADDR);
+			reg = (reg >> REG_TRAINING_WL_RESULTS_OFFS) &
+				REG_TRAINING_WL_RESULTS_MASK;	/* [28:20] */
+
+			DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - Seek Edge: Results =  ",
+					(u32) reg, 3);
+
+			/* Update State machine */
+			for (pup = 0; pup < (max_pup_num); pup++) {
+				/* ECC support - bit 8 */
+				pup_num = (pup == dram_info->num_of_std_pups) ?
+					ECC_BIT : pup;
+				if (dram_info->wl_val[cs][pup][S] == 0) {
+					/* Update phase to PUP */
+					dram_info->wl_val[cs][pup][P] = phase;
+					/* Update delay to PUP */
+					dram_info->wl_val[cs][pup][D] = delay;
+				}
+
+				if (((reg >> pup_num) & 0x1) == 0)
+					flag[pup_num] = 1;
+
+				if (((reg >> pup_num) & 0x1)
+				    && (flag[pup_num] == 1)
+				    && (dram_info->wl_val[cs][pup][S] == 0)) {
+					/*
+					 * If the PUP is locked now and in last
+					 * counter states
+					 */
+					/* Go to next state */
+					dram_info->wl_val[cs][pup][S] = 1;
+					/* Set res */
+					*result = *result | (1 << pup_num);
+				}
+			}
+
+			/* If all locked - Break the loops - Finished */
+			if (*result == max_pup_mask) {
+				phase = phaseMax;
+				delay = MAX_DELAY;
+				DEBUG_WL_S("DDR3 - Write Leveling Single Cs - Seek Edge: All Locked\n");
+			}
+		}
+	}
+
+	/* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
+	DEBUG_WL_C("DDR3 - Write Leveling - Results for CS - ", (u32) cs, 1);
+	for (pup = 0; pup < (max_pup_num); pup++) {
+		DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
+		DEBUG_WL_D((u32) pup, 1);
+		DEBUG_WL_S(", Phase: ");
+		DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][P], 1);
+		DEBUG_WL_S(", Delay: ");
+		DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][D], 2);
+		DEBUG_WL_S("\n");
+	}
+
+	/* Check if some not locked and return error */
+	if (*result != max_pup_mask) {
+		DEBUG_WL_S("DDR3 - Write Leveling - ERROR - not all PUPS were locked\n");
+		return MV_FAIL;
+	}
+
+	/* Configure Each PUP with locked leveling settings */
+	for (pup = 0; pup < (max_pup_num); pup++) {
+		/* ECC support - bit 8 */
+		pup_num = (pup == dram_info->num_of_std_pups) ? ECC_BIT : pup;
+		phase = dram_info->wl_val[cs][pup][P];
+		delay = dram_info->wl_val[cs][pup][D];
+		ddr3_write_pup_reg(PUP_WL_MODE, cs, pup_num, phase, delay);
+	}
+
+	/* CS ODT Override */
+	reg =  reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
+		REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
+	/* 0x1498 - SDRAM ODT Control high */
+	reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+	return MV_OK;
+}
+
+/*
+ * Perform DDR3 Control PUP Indirect Write
+ */
+static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr, u32 data)
+{
+	u32 reg = 0;
+
+	/* Store value for write */
+	reg = (data & 0xFFFF);
+
+	/* Set bit 26 for control PHY access */
+	reg |= (1 << REG_PHY_CNTRL_OFFS);
+
+	/* Configure BC or UC access to PHYs */
+	if (bc_acc == 1)
+		reg |= (1 << REG_PHY_BC_OFFS);
+	else
+		reg |= (pup << REG_PHY_PUP_OFFS);
+
+	/* Set PHY register address to write to */
+	reg |= (reg_addr << REG_PHY_CS_OFFS);
+
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+	reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
+
+	do {
+		reg = (reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR)) &
+			REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+	} while (reg);		/* Wait for '0' to mark the end of the transaction */
+}
diff --git a/drivers/ddr/mvebu/xor.c b/drivers/ddr/mvebu/xor.c
new file mode 100644
index 0000000..66c96ae
--- /dev/null
+++ b/drivers/ddr/mvebu/xor.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "xor.h"
+#include "xor_regs.h"
+
+static u32 xor_regs_ctrl_backup;
+static u32 xor_regs_base_backup[MAX_CS];
+static u32 xor_regs_mask_backup[MAX_CS];
+
+static void mv_xor_hal_init(u32 chan_num);
+static int mv_xor_cmd_set(u32 chan, int command);
+static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
+
+void mv_sys_xor_init(MV_DRAM_INFO *dram_info)
+{
+	u32 reg, ui, base, cs_count;
+
+	xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
+	for (ui = 0; ui < MAX_CS; ui++)
+		xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui));
+	for (ui = 0; ui < MAX_CS; ui++)
+		xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui));
+
+	reg = 0;
+	for (ui = 0; ui < (dram_info->num_cs + 1); ui++) {
+		/* Enable Window x for each CS */
+		reg |= (0x1 << (ui));
+		/* Enable Window x for each CS */
+		reg |= (0x3 << ((ui * 2) + 16));
+	}
+
+	reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
+
+	/* Last window - Base - 0x40000000, Attribute 0x1E - SRAM */
+	base = (SRAM_BASE & 0xFFFF0000) | 0x1E00;
+	reg_write(XOR_BASE_ADDR_REG(0, dram_info->num_cs), base);
+	/* Last window - Size - 64 MB */
+	reg_write(XOR_SIZE_MASK_REG(0, dram_info->num_cs), 0x03FF0000);
+
+	cs_count = 0;
+	for (ui = 0; ui < MAX_CS; ui++) {
+		if (dram_info->cs_ena & (1 << ui)) {
+			/*
+			 * Window x - Base - 0x00000000, Attribute 0x0E - DRAM
+			 */
+			base = 0;
+			switch (ui) {
+			case 0:
+				base |= 0xE00;
+				break;
+			case 1:
+				base |= 0xD00;
+				break;
+			case 2:
+				base |= 0xB00;
+				break;
+			case 3:
+				base |= 0x700;
+				break;
+			}
+
+			reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
+
+			/* Window x - Size - 256 MB */
+			reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x0FFF0000);
+			cs_count++;
+		}
+	}
+
+	mv_xor_hal_init(1);
+
+	return;
+}
+
+void mv_sys_xor_finish(void)
+{
+	u32 ui;
+
+	reg_write(XOR_WINDOW_CTRL_REG(0, 0), xor_regs_ctrl_backup);
+	for (ui = 0; ui < MAX_CS; ui++)
+		reg_write(XOR_BASE_ADDR_REG(0, ui), xor_regs_base_backup[ui]);
+	for (ui = 0; ui < MAX_CS; ui++)
+		reg_write(XOR_SIZE_MASK_REG(0, ui), xor_regs_mask_backup[ui]);
+
+	reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
+}
+
+/*
+ * mv_xor_hal_init - Initialize XOR engine
+ *
+ * DESCRIPTION:
+ *               This function initialize XOR unit.
+ * INPUT:
+ *       None.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ */
+static void mv_xor_hal_init(u32 chan_num)
+{
+	u32 i;
+
+	/* Abort any XOR activity & set default configuration */
+	for (i = 0; i < chan_num; i++) {
+		mv_xor_cmd_set(i, MV_STOP);
+		mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
+				(4 << XEXCR_DST_BURST_LIMIT_OFFS) |
+				(4 << XEXCR_SRC_BURST_LIMIT_OFFS));
+	}
+}
+
+/*
+ * mv_xor_ctrl_set - Set XOR channel control registers
+ *
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ * NOTE:
+ *    This function does not modify the OperationMode field of control register.
+ *
+ */
+static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
+{
+	u32 val;
+
+	/* Update the XOR Engine [0..1] Configuration Registers (XExCR) */
+	val = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)))
+	    & XEXCR_OPERATION_MODE_MASK;
+	xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
+	xor_ctrl |= val;
+	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
+
+	return MV_OK;
+}
+
+int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
+		    u32 init_val_low)
+{
+	u32 tmp;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN)
+		return MV_BAD_PARAM;
+
+	if (MV_ACTIVE == mv_xor_state_get(chan))
+		return MV_BUSY;
+
+	if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
+	    (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
+		return MV_BAD_PARAM;
+
+	/* Set the operation mode to Memory Init */
+	tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	tmp &= ~XEXCR_OPERATION_MODE_MASK;
+	tmp |= XEXCR_OPERATION_MODE_MEM_INIT;
+	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
+
+	/*
+	 * Update the start_ptr field in XOR Engine [0..1] Destination Pointer
+	 * Register (XExDPR0)
+	 */
+	reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
+
+	/*
+	 * Update the BlockSize field in the XOR Engine[0..1] Block Size
+	 * Registers (XExBSR)
+	 */
+	reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+		  block_size);
+
+	/*
+	 * Update the field InitValL in the XOR Engine Initial Value Register
+	 * Low (XEIVRL)
+	 */
+	reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
+
+	/*
+	 * Update the field InitValH in the XOR Engine Initial Value Register
+	 * High (XEIVRH)
+	 */
+	reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
+
+	/* Start transfer */
+	reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+		    XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+/*
+ * mv_xor_transfer - Transfer data from source to destination on one of
+ *                 three modes (XOR,CRC32,DMA)
+ *
+ * DESCRIPTION:
+ *       This function initiates XOR channel, according to function parameters,
+ *       in order to perform XOR or CRC32 or DMA transaction.
+ *       To gain maximum performance the user is asked to keep the following
+ *       restrictions:
+ *       1) Selected engine is available (not busy).
+ *       1) This module does not take into consideration CPU MMU issues.
+ *          In order for the XOR engine to access the appropreate source
+ *          and destination, address parameters must be given in system
+ *          physical mode.
+ *       2) This API does not take care of cache coherency issues. The source,
+ *          destination and in case of chain the descriptor list are assumed
+ *          to be cache coherent.
+ *       4) Parameters validity. For example, does size parameter exceeds
+ *          maximum byte count of descriptor mode (16M or 64K).
+ *
+ * INPUT:
+ *       chan          - XOR channel number. See MV_XOR_CHANNEL enumerator.
+ *       xor_type      - One of three: XOR, CRC32 and DMA operations.
+ *       xor_chain_ptr - address of chain pointer
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURS:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ *
+ */
+int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr)
+{
+	u32 tmp;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+		return MV_BAD_PARAM;
+	}
+
+	if (MV_ACTIVE == mv_xor_state_get(chan)) {
+		debug("%s: ERR. Channel is already active\n", __func__);
+		return MV_BUSY;
+	}
+
+	if (0x0 == xor_chain_ptr) {
+		debug("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__);
+		return MV_BAD_PARAM;
+	}
+
+	/* Read configuration register and mask the operation mode field */
+	tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	tmp &= ~XEXCR_OPERATION_MODE_MASK;
+
+	switch (xor_type) {
+	case MV_XOR:
+		if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK)) {
+			debug("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
+			      __func__);
+			return MV_BAD_PARAM;
+		}
+
+		/* Set the operation mode to XOR */
+		tmp |= XEXCR_OPERATION_MODE_XOR;
+		break;
+
+	case MV_DMA:
+		if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK)) {
+			debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+			      __func__);
+			return MV_BAD_PARAM;
+		}
+
+		/* Set the operation mode to DMA */
+		tmp |= XEXCR_OPERATION_MODE_DMA;
+		break;
+
+	case MV_CRC32:
+		if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK)) {
+			debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+			      __func__);
+			return MV_BAD_PARAM;
+		}
+
+		/* Set the operation mode to CRC32 */
+		tmp |= XEXCR_OPERATION_MODE_CRC;
+		break;
+
+	default:
+		return MV_BAD_PARAM;
+	}
+
+	/* Write the operation mode to the register */
+	reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
+
+	/*
+	 * Update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
+	 * Pointer Register (XExNDPR)
+	 */
+	reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+		  xor_chain_ptr);
+
+	/* Start transfer */
+	reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+		    XEXACTR_XESTART_MASK);
+
+	return MV_OK;
+}
+
+/*
+ * mv_xor_state_get - Get XOR channel state.
+ *
+ * DESCRIPTION:
+ *       XOR channel activity state can be active, idle, paused.
+ *       This function retrunes the channel activity state.
+ *
+ * INPUT:
+ *       chan     - the channel number
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       XOR_CHANNEL_IDLE    - If the engine is idle.
+ *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
+ *       XOR_CHANNEL_PAUSED  - If the engine is paused.
+ *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
+ *                             such engine
+ *
+ */
+int mv_xor_state_get(u32 chan)
+{
+	u32 state;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+		return MV_UNDEFINED_STATE;
+	}
+
+	/* Read the current state */
+	state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+	state &= XEXACTR_XESTATUS_MASK;
+
+	/* Return the state */
+	switch (state) {
+	case XEXACTR_XESTATUS_IDLE:
+		return MV_IDLE;
+	case XEXACTR_XESTATUS_ACTIVE:
+		return MV_ACTIVE;
+	case XEXACTR_XESTATUS_PAUSED:
+		return MV_PAUSED;
+	}
+
+	return MV_UNDEFINED_STATE;
+}
+
+/*
+ * mv_xor_cmd_set - Set command of XOR channel
+ *
+ * DESCRIPTION:
+ *       XOR channel can be started, idle, paused and restarted.
+ *       Paused can be set only if channel is active.
+ *       Start can be set only if channel is idle or paused.
+ *       Restart can be set only if channel is paused.
+ *       Stop can be set only if channel is active.
+ *
+ * INPUT:
+ *       chan     - The channel number
+ *       command  - The command type (start, stop, restart, pause)
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
+ *       undefind XOR engine mode
+ *
+ */
+static int mv_xor_cmd_set(u32 chan, int command)
+{
+	int state;
+
+	/* Parameter checking */
+	if (chan >= MV_XOR_MAX_CHAN) {
+		debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+		return MV_BAD_PARAM;
+	}
+
+	/* Get the current state */
+	state = mv_xor_state_get(chan);
+
+	/* Command is start and current state is idle */
+	if ((command == MV_START) && (state == MV_IDLE)) {
+		reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+			    XEXACTR_XESTART_MASK);
+		return MV_OK;
+	}
+	/* Command is stop and current state is active */
+	else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
+		reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+			    XEXACTR_XESTOP_MASK);
+		return MV_OK;
+	}
+	/* Command is paused and current state is active */
+	else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) {
+		reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+			    XEXACTR_XEPAUSE_MASK);
+		return MV_OK;
+	}
+	/* Command is restart and current state is paused */
+	else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
+		reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+			    XEXACTR_XERESTART_MASK);
+		return MV_OK;
+	}
+	/* Command is stop and current state is active */
+	else if ((command == MV_STOP) && (state == MV_IDLE))
+		return MV_OK;
+
+	/* Illegal command */
+	debug("%s: ERR. Illegal command\n", __func__);
+
+	return MV_BAD_PARAM;
+}
diff --git a/drivers/ddr/mvebu/xor.h b/drivers/ddr/mvebu/xor.h
new file mode 100644
index 0000000..3536487
--- /dev/null
+++ b/drivers/ddr/mvebu/xor.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __XOR_H
+#define __XOR_H
+
+#include "ddr3_hw_training.h"
+
+#define MV_XOR_MAX_CHAN         4 /* total channels for all units together */
+
+/*
+ * This enumerator describes the type of functionality the XOR channel
+ * can have while using the same data structures.
+ */
+enum xor_type {
+	MV_XOR,		/* XOR channel functions as XOR accelerator     */
+	MV_DMA,		/* XOR channel functions as IDMA channel        */
+	MV_CRC32	/* XOR channel functions as CRC 32 calculator   */
+};
+
+/*
+ * This enumerator describes the set of commands that can be applied on
+ * an engine (e.g. IDMA, XOR). Appling a comman depends on the current
+ * status (see MV_STATE enumerator)
+ * Start can be applied only when status is IDLE
+ * Stop can be applied only when status is IDLE, ACTIVE or PAUSED
+ * Pause can be applied only when status is ACTIVE
+ * Restart can be applied only when status is PAUSED
+ */
+enum mv_command {
+	MV_START,		/* Start     */
+	MV_STOP,		/* Stop     */
+	MV_PAUSE,		/* Pause    */
+	MV_RESTART		/* Restart  */
+};
+
+/*
+ * This enumerator describes the set of state conditions.
+ * Moving from one state to other is stricted.
+ */
+enum mv_state {
+	MV_IDLE,
+	MV_ACTIVE,
+	MV_PAUSED,
+	MV_UNDEFINED_STATE
+};
+
+/* XOR descriptor structure for CRC and DMA descriptor */
+struct crc_dma_desc {
+	u32 status;		/* Successful descriptor execution indication */
+	u32 crc32_result;	/* Result of CRC-32 calculation */
+	u32 desc_cmd;		/* type of operation to be carried out on the data */
+	u32 next_desc_ptr;	/* Next descriptor address pointer */
+	u32 byte_cnt;		/* Size of source block part represented by the descriptor */
+	u32 dst_addr;		/* Destination Block address pointer (not used in CRC32 */
+	u32 src_addr0;		/* Mode: Source Block address pointer */
+	u32 src_addr1;		/* Mode: Source Block address pointer */
+} __packed;
+
+int mv_xor_state_get(u32 chan);
+void mv_sys_xor_init(MV_DRAM_INFO *dram_info);
+void mv_sys_xor_finish(void);
+int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr);
+int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
+		    u32 init_val_low);
+
+#endif /* __XOR_H */
diff --git a/drivers/ddr/mvebu/xor_regs.h b/drivers/ddr/mvebu/xor_regs.h
new file mode 100644
index 0000000..884aa15
--- /dev/null
+++ b/drivers/ddr/mvebu/xor_regs.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __XOR_REGS_H
+#define __XOR_REGS_H
+
+/*
+ * For controllers that have two XOR units, then chans 2 & 3 will be mapped
+ * to channels 0 & 1 of unit 1
+ */
+#define XOR_UNIT(chan)			((chan) >> 1)
+#define XOR_CHAN(chan)			((chan) & 1)
+
+#define MV_XOR_REGS_OFFSET(unit)	(0x60900)
+#define MV_XOR_REGS_BASE(unit)		(MV_XOR_REGS_OFFSET(unit))
+
+/* XOR Engine Control Register Map */
+#define XOR_CHANNEL_ARBITER_REG(unit)	(MV_XOR_REGS_BASE(unit))
+#define XOR_CONFIG_REG(unit, chan)	(MV_XOR_REGS_BASE(unit) + (0x10 + ((chan) * 4)))
+#define XOR_ACTIVATION_REG(unit, chan)	(MV_XOR_REGS_BASE(unit) + (0x20 + ((chan) * 4)))
+
+/* XOR Engine Interrupt Register Map */
+#define XOR_CAUSE_REG(unit)		(MV_XOR_REGS_BASE(unit) + 0x30)
+#define XOR_MASK_REG(unit)		(MV_XOR_REGS_BASE(unit) + 0x40)
+#define XOR_ERROR_CAUSE_REG(unit)	(MV_XOR_REGS_BASE(unit) + 0x50)
+#define XOR_ERROR_ADDR_REG(unit)	(MV_XOR_REGS_BASE(unit) + 0x60)
+
+/* XOR Engine Descriptor Register Map */
+#define XOR_NEXT_DESC_PTR_REG(unit, chan)	(MV_XOR_REGS_BASE(unit) + (0x200 + ((chan) * 4)))
+#define XOR_CURR_DESC_PTR_REG(unit, chan)	(MV_XOR_REGS_BASE(unit) + (0x210 + ((chan) * 4)))
+#define XOR_BYTE_COUNT_REG(unit, chan)		(MV_XOR_REGS_BASE(unit) + (0x220 + ((chan) * 4)))
+
+#define XOR_DST_PTR_REG(unit, chan)		(MV_XOR_REGS_BASE(unit) + (0x2B0 + ((chan) * 4)))
+#define XOR_BLOCK_SIZE_REG(unit, chan)		(MV_XOR_REGS_BASE(unit) + (0x2C0 + ((chan) * 4)))
+#define XOR_TIMER_MODE_CTRL_REG(unit)		(MV_XOR_REGS_BASE(unit) + 0x2D0)
+#define XOR_TIMER_MODE_INIT_VAL_REG(unit)	(MV_XOR_REGS_BASE(unit) + 0x2D4)
+#define XOR_TIMER_MODE_CURR_VAL_REG(unit)	(MV_XOR_REGS_BASE(unit) + 0x2D8)
+#define XOR_INIT_VAL_LOW_REG(unit)		(MV_XOR_REGS_BASE(unit) + 0x2E0)
+#define XOR_INIT_VAL_HIGH_REG(unit)		(MV_XOR_REGS_BASE(unit) + 0x2E4)
+
+/* XOR register fileds */
+
+/* XOR Engine [0..1] Configuration Registers (XExCR) */
+#define XEXCR_OPERATION_MODE_OFFS	(0)
+#define XEXCR_OPERATION_MODE_MASK	(7 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_XOR	(0 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_CRC	(1 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_DMA	(2 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_ECC	(3 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_MEM_INIT	(4 << XEXCR_OPERATION_MODE_OFFS)
+
+#define XEXCR_SRC_BURST_LIMIT_OFFS	(4)
+#define XEXCR_SRC_BURST_LIMIT_MASK	(7 << XEXCR_SRC_BURST_LIMIT_OFFS)
+#define XEXCR_DST_BURST_LIMIT_OFFS	(8)
+#define XEXCR_DST_BURST_LIMIT_MASK	(7 << XEXCR_DST_BURST_LIMIT_OFFS)
+#define XEXCR_DRD_RES_SWP_OFFS		(12)
+#define XEXCR_DRD_RES_SWP_MASK		(1 << XEXCR_DRD_RES_SWP_OFFS)
+#define XEXCR_DWR_REQ_SWP_OFFS		(13)
+#define XEXCR_DWR_REQ_SWP_MASK		(1 << XEXCR_DWR_REQ_SWP_OFFS)
+#define XEXCR_DES_SWP_OFFS		(14)
+#define XEXCR_DES_SWP_MASK		(1 << XEXCR_DES_SWP_OFFS)
+#define XEXCR_REG_ACC_PROTECT_OFFS	(15)
+#define XEXCR_REG_ACC_PROTECT_MASK	(1 << XEXCR_REG_ACC_PROTECT_OFFS)
+
+/* XOR Engine [0..1] Activation Registers (XExACTR) */
+#define XEXACTR_XESTART_OFFS		(0)
+#define XEXACTR_XESTART_MASK		(1 << XEXACTR_XESTART_OFFS)
+#define XEXACTR_XESTOP_OFFS		(1)
+#define XEXACTR_XESTOP_MASK		(1 << XEXACTR_XESTOP_OFFS)
+#define XEXACTR_XEPAUSE_OFFS		(2)
+#define XEXACTR_XEPAUSE_MASK		(1 << XEXACTR_XEPAUSE_OFFS)
+#define XEXACTR_XERESTART_OFFS		(3)
+#define XEXACTR_XERESTART_MASK		(1 << XEXACTR_XERESTART_OFFS)
+#define XEXACTR_XESTATUS_OFFS		(4)
+#define XEXACTR_XESTATUS_MASK		(3 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_IDLE		(0 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_ACTIVE		(1 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_PAUSED		(2 << XEXACTR_XESTATUS_OFFS)
+
+/* XOR Engine [0..1] Destination Pointer Register (XExDPR0) */
+#define XEXDPR_DST_PTR_OFFS		(0)
+#define XEXDPR_DST_PTR_MASK		(0xFFFFFFFF << XEXDPR_DST_PTR_OFFS)
+#define XEXDPR_DST_PTR_XOR_MASK		(0x3F)
+#define XEXDPR_DST_PTR_DMA_MASK		(0x1F)
+#define XEXDPR_DST_PTR_CRC_MASK		(0x1F)
+
+/* XOR Engine[0..1] Block Size Registers (XExBSR) */
+#define XEXBSR_BLOCK_SIZE_OFFS		(0)
+#define XEXBSR_BLOCK_SIZE_MASK		(0xFFFFFFFF << XEXBSR_BLOCK_SIZE_OFFS)
+#define XEXBSR_BLOCK_SIZE_MIN_VALUE	(128)
+#define XEXBSR_BLOCK_SIZE_MAX_VALUE	(0xFFFFFFFF)
+
+/* XOR Engine Address Decoding Register Map */
+#define XOR_WINDOW_CTRL_REG(unit, chan)	(MV_XOR_REGS_BASE(unit) + (0x240 + ((chan) * 4)))
+#define XOR_BASE_ADDR_REG(unit, win)	(MV_XOR_REGS_BASE(unit) + (0x250 + ((win) * 4)))
+#define XOR_SIZE_MASK_REG(unit, win)	(MV_XOR_REGS_BASE(unit) + (0x270 + ((win) * 4)))
+#define XOR_HIGH_ADDR_REMAP_REG(unit, win) (MV_XOR_REGS_BASE(unit) + (0x290 + ((win) * 4)))
+#define XOR_ADDR_OVRD_REG(unit, win)	(MV_XOR_REGS_BASE(unit) + (0x2A0 + ((win) * 4)))
+
+#endif /* __XOR_REGS_H */
diff --git a/drivers/demo/Kconfig b/drivers/demo/Kconfig
new file mode 100644
index 0000000..7a8ce18
--- /dev/null
+++ b/drivers/demo/Kconfig
@@ -0,0 +1,26 @@
+config DM_DEMO
+	bool "Enable demo uclass support"
+	depends on DM
+	help
+	  This uclass allows you to play around with driver model. It provides
+	  an interface to a couple of demo devices. You can access it using
+	  the 'demo' command or by calling the uclass functions from your
+	  own code.
+
+config DM_DEMO_SIMPLE
+	bool "Enable simple demo device for driver model"
+	depends on DM_DEMO
+	help
+	  This device allows you to play around with driver model. It prints
+	  a message when the 'demo hello' command is executed which targets
+	  this device. It can be used to help understand how driver model
+	  works.
+
+config DM_DEMO_SHAPE
+	bool "Enable shape demo device for driver model"
+	depends on DM_DEMO
+	help
+	  This device allows you to play around with driver model. It prints
+	  a shape when the 'demo hello' command is executed which targets
+	  this device. It can be used to help understand how driver model
+	  works.
diff --git a/drivers/demo/demo-shape.c b/drivers/demo/demo-shape.c
index 3fa9c59..d908736 100644
--- a/drivers/demo/demo-shape.c
+++ b/drivers/demo/demo-shape.c
@@ -11,6 +11,7 @@
 #include <malloc.h>
 #include <dm-demo.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -20,6 +21,8 @@
 
 struct shape_data {
 	int num_chars;	/* Number of non-space characters output so far */
+	struct gpio_desc gpio_desc[8];
+	int gpio_count;
 };
 
 /* Crazy little function to draw shapes on the console */
@@ -89,9 +92,52 @@
 	return 0;
 }
 
+static int set_light(struct udevice *dev, int light)
+{
+	struct shape_data *priv = dev_get_priv(dev);
+	struct gpio_desc *desc;
+	int ret;
+	int i;
+
+	desc = priv->gpio_desc;
+	for (i = 0; i < priv->gpio_count; i++, desc++) {
+		uint mask = 1 << i;
+
+		ret = dm_gpio_set_value(desc, light & mask);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int get_light(struct udevice *dev)
+{
+	struct shape_data *priv = dev_get_priv(dev);
+	struct gpio_desc *desc;
+	uint value = 0;
+	int ret;
+	int i;
+
+	desc = priv->gpio_desc;
+	for (i = 0; i < priv->gpio_count; i++, desc++) {
+		uint mask = 1 << i;
+
+		ret = dm_gpio_get_value(desc);
+		if (ret < 0)
+			return ret;
+		if (ret)
+			value |= mask;
+	}
+
+	return value;
+}
+
 static const struct demo_ops shape_ops = {
 	.hello = shape_hello,
 	.status = shape_status,
+	.get_light = get_light,
+	.set_light = set_light,
 };
 
 static int shape_ofdata_to_platdata(struct udevice *dev)
@@ -111,6 +157,29 @@
 	return 0;
 }
 
+static int dm_shape_probe(struct udevice *dev)
+{
+	struct shape_data *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
+					ARRAY_SIZE(priv->gpio_desc),
+					GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	if (ret < 0)
+		return ret;
+	priv->gpio_count = ret;
+	debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
+
+	return 0;
+}
+
+static int dm_shape_remove(struct udevice *dev)
+{
+	struct shape_data *priv = dev_get_priv(dev);
+
+	return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
+}
+
 static const struct udevice_id demo_shape_id[] = {
 	{ "demo-shape", 0 },
 	{ },
@@ -122,6 +191,8 @@
 	.id	= UCLASS_DEMO,
 	.ofdata_to_platdata = shape_ofdata_to_platdata,
 	.ops	= &shape_ops,
+	.probe = dm_shape_probe,
+	.remove = dm_shape_remove,
 	.priv_auto_alloc_size = sizeof(struct shape_data),
 	.platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
 };
diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c
index f6510d6..725f068 100644
--- a/drivers/demo/demo-uclass.c
+++ b/drivers/demo/demo-uclass.c
@@ -43,6 +43,26 @@
 	return ops->status(dev, status);
 }
 
+int demo_get_light(struct udevice *dev)
+{
+	const struct demo_ops *ops = device_get_ops(dev);
+
+	if (!ops->get_light)
+		return -ENOSYS;
+
+	return ops->get_light(dev);
+}
+
+int demo_set_light(struct udevice *dev, int light)
+{
+	const struct demo_ops *ops = device_get_ops(dev);
+
+	if (!ops->set_light)
+		return -ENOSYS;
+
+	return ops->set_light(dev, light);
+}
+
 int demo_parse_dt(struct udevice *dev)
 {
 	struct dm_demo_pdata *pdata = dev_get_platdata(dev);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d21302f..b609e73 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -2,5 +2,8 @@
 	bool "Enable Driver Model for GPIO drivers"
 	depends on DM
 	help
-	  If you want to use driver model for GPIO drivers, say Y.
-	  To use legacy GPIO drivers, say N.
+	  Enable driver model for GPIO access. The standard GPIO
+	  interface (gpio_get_value(), etc.) is then implemented by
+	  the GPIO uclass. Drivers provide methods to query the
+	  particular GPIOs that they provide. The uclass interface
+	  is defined in include/asm-generic/gpio.h.
diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c
index 6129c02..22fbd63 100644
--- a/drivers/gpio/at91_gpio.c
+++ b/drivers/gpio/at91_gpio.c
@@ -451,7 +451,7 @@
 /* set GPIO pin 'gpio' as an input */
 static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_priv *port = dev_get_platdata(dev);
+	struct at91_port_priv *port = dev_get_priv(dev);
 
 	at91_set_port_input(port->regs, offset, 0);
 
@@ -462,7 +462,7 @@
 static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
-	struct at91_port_priv *port = dev_get_platdata(dev);
+	struct at91_port_priv *port = dev_get_priv(dev);
 
 	at91_set_port_output(port->regs, offset, value);
 
@@ -472,7 +472,7 @@
 /* read GPIO IN value of pin 'gpio' */
 static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_priv *port = dev_get_platdata(dev);
+	struct at91_port_priv *port = dev_get_priv(dev);
 
 	return at91_get_port_value(port->regs, offset);
 }
@@ -481,7 +481,7 @@
 static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
-	struct at91_port_priv *port = dev_get_platdata(dev);
+	struct at91_port_priv *port = dev_get_priv(dev);
 
 	at91_set_port_value(port->regs, offset, value);
 
@@ -490,7 +490,7 @@
 
 static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
 {
-	struct at91_port_priv *port = dev_get_platdata(dev);
+	struct at91_port_priv *port = dev_get_priv(dev);
 
 	/* GPIOF_FUNC is not implemented yet */
 	if (at91_get_port_output(port->regs, offset))
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 255700a..a69bbd2 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -7,20 +7,25 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <fdtdec.h>
 #include <malloc.h>
 #include <asm/gpio.h>
 #include <linux/ctype.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /**
  * gpio_to_device() - Convert global GPIO number to device, number
- * gpio:	The numeric representation of the GPIO
  *
  * Convert the GPIO number to an entry in the list of GPIOs
  * or GPIO blocks registered with the GPIO controller. Returns
  * entry on success, NULL on error.
+ *
+ * @gpio:	The numeric representation of the GPIO
+ * @desc:	Returns description (desc->flags will always be 0)
+ * @return 0 if found, -ENOENT if not found
  */
-static int gpio_to_device(unsigned int gpio, struct udevice **devp,
-			  unsigned int *offset)
+static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
 {
 	struct gpio_dev_priv *uc_priv;
 	struct udevice *dev;
@@ -32,14 +37,15 @@
 		uc_priv = dev->uclass_priv;
 		if (gpio >= uc_priv->gpio_base &&
 		    gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
-			*devp = dev;
-			*offset = gpio - uc_priv->gpio_base;
+			desc->dev = dev;
+			desc->offset = gpio - uc_priv->gpio_base;
+			desc->flags = 0;
 			return 0;
 		}
 	}
 
 	/* No such GPIO */
-	return ret ? ret : -EINVAL;
+	return ret ? ret : -ENOENT;
 }
 
 int gpio_lookup_name(const char *name, struct udevice **devp,
@@ -88,6 +94,57 @@
 	return 0;
 }
 
+static int gpio_find_and_xlate(struct gpio_desc *desc,
+			       struct fdtdec_phandle_args *args)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+
+	/* Use the first argument as the offset by default */
+	if (args->args_count > 0)
+		desc->offset = args->args[0];
+	else
+		desc->offset = -1;
+	desc->flags = 0;
+
+	return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0;
+}
+
+static int dm_gpio_request(struct gpio_desc *desc, const char *label)
+{
+	struct udevice *dev = desc->dev;
+	struct gpio_dev_priv *uc_priv;
+	char *str;
+	int ret;
+
+	uc_priv = dev->uclass_priv;
+	if (uc_priv->name[desc->offset])
+		return -EBUSY;
+	str = strdup(label);
+	if (!str)
+		return -ENOMEM;
+	if (gpio_get_ops(dev)->request) {
+		ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+		if (ret) {
+			free(str);
+			return ret;
+		}
+	}
+	uc_priv->name[desc->offset] = str;
+
+	return 0;
+}
+
+static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
+{
+	va_list args;
+	char buf[40];
+
+	va_start(args, fmt);
+	vscnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	return dm_gpio_request(desc, buf);
+}
+
 /**
  * gpio_request() - [COMPAT] Request GPIO
  * gpio:	GPIO number
@@ -102,32 +159,14 @@
  */
 int gpio_request(unsigned gpio, const char *label)
 {
-	struct gpio_dev_priv *uc_priv;
-	unsigned int offset;
-	struct udevice *dev;
-	char *str;
+	struct gpio_desc desc;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
+	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
 
-	uc_priv = dev->uclass_priv;
-	if (uc_priv->name[offset])
-		return -EBUSY;
-	str = strdup(label);
-	if (!str)
-		return -ENOMEM;
-	if (gpio_get_ops(dev)->request) {
-		ret = gpio_get_ops(dev)->request(dev, offset, label);
-		if (ret) {
-			free(str);
-			return ret;
-		}
-	}
-	uc_priv->name[offset] = str;
-
-	return 0;
+	return dm_gpio_request(&desc, label);
 }
 
 /**
@@ -151,25 +190,11 @@
 	return gpio_request(gpio, buf);
 }
 
-/**
- * gpio_free() - [COMPAT] Relinquish GPIO
- * gpio:	GPIO number
- *
- * This function implements the API that's compatible with current
- * GPIO API used in U-Boot. The request is forwarded to particular
- * GPIO driver. Returns 0 on success, negative value on error.
- */
-int gpio_free(unsigned gpio)
+int _dm_gpio_free(struct udevice *dev, uint offset)
 {
 	struct gpio_dev_priv *uc_priv;
-	unsigned int offset;
-	struct udevice *dev;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
-	if (ret)
-		return ret;
-
 	uc_priv = dev->uclass_priv;
 	if (!uc_priv->name[offset])
 		return -ENXIO;
@@ -185,15 +210,35 @@
 	return 0;
 }
 
-static int check_reserved(struct udevice *dev, unsigned offset,
-			  const char *func)
+/**
+ * gpio_free() - [COMPAT] Relinquish GPIO
+ * gpio:	GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_free(unsigned gpio)
 {
-	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+	struct gpio_desc desc;
+	int ret;
 
-	if (!uc_priv->name[offset]) {
+	ret = gpio_to_device(gpio, &desc);
+	if (ret)
+		return ret;
+
+	return _dm_gpio_free(desc.dev, desc.offset);
+}
+
+static int check_reserved(struct gpio_desc *desc, const char *func)
+{
+	struct gpio_dev_priv *uc_priv = desc->dev->uclass_priv;
+
+	if (!uc_priv->name[desc->offset]) {
 		printf("%s: %s: error: gpio %s%d not reserved\n",
-		       dev->name, func,
-		       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+		       desc->dev->name, func,
+		       uc_priv->bank_name ? uc_priv->bank_name : "",
+		       desc->offset);
 		return -EBUSY;
 	}
 
@@ -210,16 +255,17 @@
  */
 int gpio_direction_input(unsigned gpio)
 {
-	unsigned int offset;
-	struct udevice *dev;
+	struct gpio_desc desc;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
+	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(dev, offset, "dir_input");
+	ret = check_reserved(&desc, "dir_input");
+	if (ret)
+		return ret;
 
-	return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
+	return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
 }
 
 /**
@@ -233,17 +279,81 @@
  */
 int gpio_direction_output(unsigned gpio, int value)
 {
-	unsigned int offset;
-	struct udevice *dev;
+	struct gpio_desc desc;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
+	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(dev, offset, "dir_output");
+	ret = check_reserved(&desc, "dir_output");
+	if (ret)
+		return ret;
 
-	return ret ? ret :
-		gpio_get_ops(dev)->direction_output(dev, offset, value);
+	return gpio_get_ops(desc.dev)->direction_output(desc.dev,
+							desc.offset, value);
+}
+
+int dm_gpio_get_value(struct gpio_desc *desc)
+{
+	int value;
+	int ret;
+
+	ret = check_reserved(desc, "get_value");
+	if (ret)
+		return ret;
+
+	value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+
+	return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
+}
+
+int dm_gpio_set_value(struct gpio_desc *desc, int value)
+{
+	int ret;
+
+	ret = check_reserved(desc, "set_value");
+	if (ret)
+		return ret;
+
+	if (desc->flags & GPIOD_ACTIVE_LOW)
+		value = !value;
+	gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
+	return 0;
+}
+
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+{
+	struct udevice *dev = desc->dev;
+	struct dm_gpio_ops *ops = gpio_get_ops(dev);
+	int ret;
+
+	ret = check_reserved(desc, "set_dir");
+	if (ret)
+		return ret;
+
+	if (flags & GPIOD_IS_OUT) {
+		int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+
+		if (flags & GPIOD_ACTIVE_LOW)
+			value = !value;
+		ret = ops->direction_output(dev, desc->offset, value);
+	} else  if (flags & GPIOD_IS_IN) {
+		ret = ops->direction_input(dev, desc->offset);
+	}
+	if (ret)
+		return ret;
+	/*
+	 * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in
+	 * futures
+	 */
+	desc->flags = flags;
+
+	return 0;
+}
+
+int dm_gpio_set_dir(struct gpio_desc *desc)
+{
+	return dm_gpio_set_dir_flags(desc, desc->flags);
 }
 
 /**
@@ -257,16 +367,14 @@
  */
 int gpio_get_value(unsigned gpio)
 {
-	unsigned int offset;
-	struct udevice *dev;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
+	struct gpio_desc desc;
+
+	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(dev, offset, "get_value");
-
-	return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
+	return dm_gpio_get_value(&desc);
 }
 
 /**
@@ -280,16 +388,13 @@
  */
 int gpio_set_value(unsigned gpio, int value)
 {
-	unsigned int offset;
-	struct udevice *dev;
+	struct gpio_desc desc;
 	int ret;
 
-	ret = gpio_to_device(gpio, &dev, &offset);
+	ret = gpio_to_device(gpio, &desc);
 	if (ret)
 		return ret;
-	ret = check_reserved(dev, offset, "set_value");
-
-	return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
+	return dm_gpio_set_value(&desc, value);
 }
 
 const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@@ -409,6 +514,155 @@
 	return vector;
 }
 
+static int _gpio_request_by_name_nodev(const void *blob, int node,
+				       const char *list_name, int index,
+				       struct gpio_desc *desc, int flags,
+				       bool add_index)
+{
+	struct fdtdec_phandle_args args;
+	int ret;
+
+	desc->dev = NULL;
+	desc->offset = 0;
+	ret = fdtdec_parse_phandle_with_args(blob, node, list_name,
+					     "#gpio-cells", 0, index, &args);
+	if (ret) {
+		debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__);
+		goto err;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node,
+					     &desc->dev);
+	if (ret) {
+		debug("%s: uclass_get_device_by_of_offset failed\n", __func__);
+		goto err;
+	}
+	ret = gpio_find_and_xlate(desc, &args);
+	if (ret) {
+		debug("%s: gpio_find_and_xlate failed\n", __func__);
+		goto err;
+	}
+	ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
+			       fdt_get_name(blob, node, NULL),
+			       list_name, index);
+	if (ret) {
+		debug("%s: dm_gpio_requestf failed\n", __func__);
+		goto err;
+	}
+	ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
+	if (ret) {
+		debug("%s: dm_gpio_set_dir failed\n", __func__);
+		goto err;
+	}
+
+	return 0;
+err:
+	debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
+	      __func__, fdt_get_name(blob, node, NULL), list_name, index, ret);
+	return ret;
+}
+
+int gpio_request_by_name_nodev(const void *blob, int node,
+			       const char *list_name, int index,
+			       struct gpio_desc *desc, int flags)
+{
+	return _gpio_request_by_name_nodev(blob, node, list_name, index, desc,
+					   flags, index > 0);
+}
+
+int gpio_request_by_name(struct udevice *dev,  const char *list_name, int index,
+			 struct gpio_desc *desc, int flags)
+{
+	/*
+	 * This isn't ideal since we don't use dev->name in the debug()
+	 * calls in gpio_request_by_name(), but we can do this until
+	 * gpio_request_by_name_nodev() can be dropped.
+	 */
+	return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
+					  list_name, index, desc, flags);
+}
+
+int gpio_request_list_by_name_nodev(const void *blob, int node,
+				    const char *list_name,
+				    struct gpio_desc *desc, int max_count,
+				    int flags)
+{
+	int count;
+	int ret;
+
+	for (count = 0; ; count++) {
+		if (count >= max_count) {
+			ret = -ENOSPC;
+			goto err;
+		}
+		ret = _gpio_request_by_name_nodev(blob, node, list_name, count,
+						  &desc[count], flags, true);
+		if (ret == -ENOENT)
+			break;
+		else if (ret)
+			goto err;
+	}
+
+	/* We ran out of GPIOs in the list */
+	return count;
+
+err:
+	gpio_free_list_nodev(desc, count - 1);
+
+	return ret;
+}
+
+int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
+			      struct gpio_desc *desc, int max_count,
+			      int flags)
+{
+	/*
+	 * This isn't ideal since we don't use dev->name in the debug()
+	 * calls in gpio_request_by_name(), but we can do this until
+	 * gpio_request_list_by_name_nodev() can be dropped.
+	 */
+	return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset,
+					       list_name, desc, max_count,
+					       flags);
+}
+
+int gpio_get_list_count(struct udevice *dev, const char *list_name)
+{
+	int ret;
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					     list_name, "#gpio-cells", 0, -1,
+					     NULL);
+	if (ret) {
+		debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
+		      __func__, dev->name, list_name, ret);
+	}
+
+	return ret;
+}
+
+int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
+{
+	/* For now, we don't do any checking of dev */
+	return _dm_gpio_free(desc->dev, desc->offset);
+}
+
+int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count)
+{
+	int i;
+
+	/* For now, we don't do any checking of dev */
+	for (i = 0; i < count; i++)
+		dm_gpio_free(dev, &desc[i]);
+
+	return 0;
+}
+
+int gpio_free_list_nodev(struct gpio_desc *desc, int count)
+{
+	return gpio_free_list(NULL, desc, count);
+}
+
 /* We need to renumber the GPIOs when any driver is probed/removed */
 static int gpio_renumber(struct udevice *removed_dev)
 {
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 8bb9e39..815407b 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -23,6 +23,7 @@
 #define GPIO_PER_BANK			32
 
 struct mxc_gpio_plat {
+	int bank_index;
 	struct gpio_regs *regs;
 };
 
@@ -150,6 +151,9 @@
 #endif
 
 #ifdef CONFIG_DM_GPIO
+#include <fdtdec.h>
+DECLARE_GLOBAL_DATA_PTR;
+
 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
 {
 	u32 val;
@@ -258,23 +262,6 @@
 	.get_function		= mxc_gpio_get_function,
 };
 
-static const struct mxc_gpio_plat mxc_plat[] = {
-	{ (struct gpio_regs *)GPIO1_BASE_ADDR },
-	{ (struct gpio_regs *)GPIO2_BASE_ADDR },
-	{ (struct gpio_regs *)GPIO3_BASE_ADDR },
-#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
-		defined(CONFIG_MX53) || defined(CONFIG_MX6)
-	{ (struct gpio_regs *)GPIO4_BASE_ADDR },
-#endif
-#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
-	{ (struct gpio_regs *)GPIO5_BASE_ADDR },
-	{ (struct gpio_regs *)GPIO6_BASE_ADDR },
-#endif
-#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
-	{ (struct gpio_regs *)GPIO7_BASE_ADDR },
-#endif
-};
-
 static int mxc_gpio_probe(struct udevice *dev)
 {
 	struct mxc_bank_info *bank = dev_get_priv(dev);
@@ -283,7 +270,7 @@
 	int banknum;
 	char name[18], *str;
 
-	banknum = plat - mxc_plat;
+	banknum = plat->bank_index;
 	sprintf(name, "GPIO%d_", banknum + 1);
 	str = strdup(name);
 	if (!str)
@@ -295,12 +282,72 @@
 	return 0;
 }
 
+static int mxc_gpio_bind(struct udevice *dev)
+{
+	struct mxc_gpio_plat *plat = dev->platdata;
+	fdt_addr_t addr;
+
+	/*
+	 * If platdata already exsits, directly return.
+	 * Actually only when DT is not supported, platdata
+	 * is statically initialized in U_BOOT_DEVICES.Here
+	 * will return.
+	 */
+	if (plat)
+		return 0;
+
+	addr = dev_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -ENODEV;
+
+	/*
+	 * TODO:
+	 * When every board is converted to driver model and DT is supported,
+	 * this can be done by auto-alloc feature, but not using calloc
+	 * to alloc memory for platdata.
+	 */
+	plat = calloc(1, sizeof(*plat));
+	if (!plat)
+		return -ENOMEM;
+
+	plat->regs = (struct gpio_regs *)addr;
+	plat->bank_index = dev->req_seq;
+	dev->platdata = plat;
+
+	return 0;
+}
+
+static const struct udevice_id mxc_gpio_ids[] = {
+	{ .compatible = "fsl,imx35-gpio" },
+	{ }
+};
+
 U_BOOT_DRIVER(gpio_mxc) = {
 	.name	= "gpio_mxc",
 	.id	= UCLASS_GPIO,
 	.ops	= &gpio_mxc_ops,
 	.probe	= mxc_gpio_probe,
 	.priv_auto_alloc_size = sizeof(struct mxc_bank_info),
+	.of_match = mxc_gpio_ids,
+	.bind	= mxc_gpio_bind,
+};
+
+#ifndef CONFIG_OF_CONTROL
+static const struct mxc_gpio_plat mxc_plat[] = {
+	{ 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
+	{ 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
+	{ 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+		defined(CONFIG_MX53) || defined(CONFIG_MX6)
+	{ 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+	{ 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
+	{ 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+	{ 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
+#endif
 };
 
 U_BOOT_DEVICES(mxc_gpios) = {
@@ -320,3 +367,4 @@
 #endif
 };
 #endif
+#endif
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index f3a7ccb..19fc451 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -291,7 +291,7 @@
 	struct gpio_bank *bank = dev_get_priv(dev);
 
 	/* GPIOF_FUNC is not implemented yet */
-	if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
+	if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT)
 		return GPIOF_OUTPUT;
 	else
 		return GPIOF_INPUT;
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 6c41a42..0a245ba 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -275,12 +276,22 @@
 		return GPIOF_FUNC;
 }
 
+static int exynos_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			     struct fdtdec_phandle_args *args)
+{
+	desc->offset = args->args[0];
+	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+	return 0;
+}
+
 static const struct dm_gpio_ops gpio_exynos_ops = {
 	.direction_input	= exynos_gpio_direction_input,
 	.direction_output	= exynos_gpio_direction_output,
 	.get_value		= exynos_gpio_get_value,
 	.set_value		= exynos_gpio_set_value,
 	.get_function		= exynos_gpio_get_function,
+	.xlate			= exynos_gpio_xlate,
 };
 
 static int gpio_exynos_probe(struct udevice *dev)
@@ -342,7 +353,7 @@
 					plat->bank_name, plat, -1, &dev);
 		if (ret)
 			return ret;
-		dev->of_offset = parent->of_offset;
+		dev->of_offset = node;
 	}
 
 	return 0;
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 53c80d5..d564c25 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -8,6 +8,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <asm/gpio.h>
+#include <dt-bindings/gpio/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -130,12 +131,31 @@
 	return GPIOF_INPUT;
 }
 
+static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			 struct fdtdec_phandle_args *args)
+{
+	desc->offset = args->args[0];
+	if (args->args_count < 2)
+		return 0;
+	if (args->args[1] & GPIO_ACTIVE_LOW)
+		desc->flags |= GPIOD_ACTIVE_LOW;
+	if (args->args[1] & 2)
+		desc->flags |= GPIOD_IS_IN;
+	if (args->args[1] & 4)
+		desc->flags |= GPIOD_IS_OUT;
+	if (args->args[1] & 8)
+		desc->flags |= GPIOD_IS_OUT_ACTIVE;
+
+	return 0;
+}
+
 static const struct dm_gpio_ops gpio_sandbox_ops = {
 	.direction_input	= sb_gpio_direction_input,
 	.direction_output	= sb_gpio_direction_output,
 	.get_value		= sb_gpio_get_value,
 	.set_value		= sb_gpio_set_value,
 	.get_function		= sb_gpio_get_function,
+	.xlate			= sb_gpio_xlate,
 };
 
 static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 88f7ef5..43928b8 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -21,6 +21,7 @@
 #include <asm/arch/tegra.h>
 #include <asm/gpio.h>
 #include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -251,6 +252,22 @@
 		return GPIOF_INPUT;
 }
 
+static int tegra_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			    struct fdtdec_phandle_args *args)
+{
+	int gpio, port, ret;
+
+	gpio = args->args[0];
+	port = gpio / TEGRA_GPIOS_PER_PORT;
+	ret = device_get_child(dev, port, &desc->dev);
+	if (ret)
+		return ret;
+	desc->offset = gpio % TEGRA_GPIOS_PER_PORT;
+	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+	return 0;
+}
+
 static const struct dm_gpio_ops gpio_tegra_ops = {
 	.request		= tegra_gpio_request,
 	.direction_input	= tegra_gpio_direction_input,
@@ -258,6 +275,7 @@
 	.get_value		= tegra_gpio_get_value,
 	.set_value		= tegra_gpio_set_value,
 	.get_function		= tegra_gpio_get_function,
+	.xlate			= tegra_gpio_xlate,
 };
 
 /**
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index e69de29..692810d 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -0,0 +1,39 @@
+config DM_I2C
+	bool "Enable Driver Model for I2C drivers"
+	depends on DM
+	help
+	  Enable driver model for I2C. This SPI flash interface
+	  (spi_flash_probe(), spi_flash_write(), etc.) is then
+	  implemented by the SPI flash uclass. There is one standard
+	  SPI flash driver which knows how to probe most chips
+	  supported by U-Boot. The uclass interface is defined in
+	  include/spi_flash.h, but is currently fully compatible
+	  with the old interface to avoid confusion and duplication
+	  during the transition parent. SPI and SPI flash must be
+	  enabled together (it is not possible to use driver model
+	  for one and not the other).
+
+config DM_I2C_COMPAT
+	bool "Enable I2C compatibility layer"
+	depends on DM
+	help
+	  Enable old-style I2C functions for compatibility with existing code.
+	  This option can be enabled as a temporary measure to avoid needing
+	  to convert all code for a board in a single commit. It should not
+	  be enabled for any board in an official release.
+
+config SYS_I2C_UNIPHIER
+	bool "UniPhier I2C driver"
+	depends on ARCH_UNIPHIER && DM_I2C
+	default y
+	help
+	  Support for Panasonic UniPhier I2C controller driver.  This I2C
+	  controller is used on PH1-LD4, PH1-sLD8 or older UniPhier SoCs.
+
+config SYS_I2C_UNIPHIER_F
+	bool "UniPhier FIFO-builtin I2C driver"
+	depends on ARCH_UNIPHIER && DM_I2C
+	default y
+	help
+	  Support for Panasonic UniPhier FIFO-builtin I2C controller driver.
+	  This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 6f3c86c..774bc94 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -5,6 +5,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 obj-$(CONFIG_DM_I2C) += i2c-uclass.o
+obj-$(CONFIG_DM_I2C_COMPAT) += i2c-uclass-compat.o
 
 obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
 obj-$(CONFIG_I2C_MV) += mv_i2c.o
@@ -31,4 +32,6 @@
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
+obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
+obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
 obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
index 20495b1..c58f14a 100644
--- a/drivers/i2c/adi_i2c.c
+++ b/drivers/i2c/adi_i2c.c
@@ -63,7 +63,7 @@
 #endif
 
 /* All transfers are described by this data structure */
-struct i2c_msg {
+struct adi_i2c_msg {
 	u8 flags;
 #define I2C_M_COMBO		0x4
 #define I2C_M_STOP		0x2
@@ -81,7 +81,7 @@
  * wait_for_completion - manage the actual i2c transfer
  *	@msg: the i2c msg
  */
-static int wait_for_completion(struct twi_regs *twi, struct i2c_msg *msg)
+static int wait_for_completion(struct twi_regs *twi, struct adi_i2c_msg *msg)
 {
 	u16 int_stat, ctl;
 	ulong timebase = get_timer(0);
@@ -151,7 +151,7 @@
 		(addr >>  8),
 		(addr >> 16),
 	};
-	struct i2c_msg msg = {
+	struct adi_i2c_msg msg = {
 		.flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
 		.buf   = buffer,
 		.len   = len,
diff --git a/drivers/i2c/i2c-uclass-compat.c b/drivers/i2c/i2c-uclass-compat.c
new file mode 100644
index 0000000..223f238
--- /dev/null
+++ b/drivers/i2c/i2c-uclass-compat.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+
+static int cur_busnum;
+
+static int i2c_compat_get_device(uint chip_addr, int alen,
+				 struct udevice **devp)
+{
+	struct dm_i2c_chip *chip;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, alen, devp);
+	if (ret)
+		return ret;
+	chip = dev_get_parent_platdata(*devp);
+	if (chip->offset_len != alen) {
+		printf("I2C chip %x: requested alen %d does not match chip offset_len %d\n",
+		       chip_addr, alen, chip->offset_len);
+		return -EADDRNOTAVAIL;
+	}
+
+	return 0;
+}
+
+int i2c_probe(uint8_t chip_addr)
+{
+	struct udevice *bus, *dev;
+	int ret;
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, cur_busnum, &bus);
+	if (ret) {
+		debug("Cannot find I2C bus %d: err=%d\n", cur_busnum, ret);
+		return ret;
+	}
+
+	if (!bus)
+		return -ENOENT;
+
+	return dm_i2c_probe(bus, chip_addr, 0, &dev);
+}
+
+int i2c_read(uint8_t chip_addr, unsigned int addr, int alen, uint8_t *buffer,
+	     int len)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_compat_get_device(chip_addr, alen, &dev);
+	if (ret)
+		return ret;
+
+	return dm_i2c_read(dev, addr, buffer, len);
+}
+
+int i2c_write(uint8_t chip_addr, unsigned int addr, int alen, uint8_t *buffer,
+	      int len)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_compat_get_device(chip_addr, alen, &dev);
+	if (ret)
+		return ret;
+
+	return dm_i2c_write(dev, addr, buffer, len);
+}
+
+int i2c_get_bus_num_fdt(int node)
+{
+	struct udevice *bus;
+	int ret;
+
+	ret = uclass_get_device_by_of_offset(UCLASS_I2C, node, &bus);
+	if (ret)
+		return ret;
+
+	return bus->seq;
+}
+
+unsigned int i2c_get_bus_num(void)
+{
+	return cur_busnum;
+}
+
+int i2c_set_bus_num(unsigned int bus)
+{
+	cur_busnum = bus;
+
+	return 0;
+}
+
+void i2c_init(int speed, int slaveaddr)
+{
+	/* Nothing to do here - the init happens through driver model */
+}
+
+void board_i2c_init(const void *blob)
+{
+	/* Nothing to do here - the init happens through driver model */
+}
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 005bf86..a6991bf 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -50,7 +50,7 @@
 static int i2c_read_bytewise(struct udevice *dev, uint offset,
 			     uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -79,7 +79,7 @@
 static int i2c_write_bytewise(struct udevice *dev, uint offset,
 			     const uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -100,9 +100,9 @@
 	return 0;
 }
 
-int i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
+int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -130,9 +130,10 @@
 	return ops->xfer(bus, msg, msg_count);
 }
 
-int i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, int len)
+int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
+		 int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -219,10 +220,10 @@
 	return ops->xfer(bus, msg, 1);
 }
 
-static int i2c_bind_driver(struct udevice *bus, uint chip_addr,
+static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
 			   struct udevice **devp)
 {
-	struct dm_i2c_chip chip;
+	struct dm_i2c_chip *chip;
 	char name[30], *str;
 	struct udevice *dev;
 	int ret;
@@ -235,11 +236,11 @@
 		goto err_bind;
 
 	/* Tell the device what we know about it */
-	memset(&chip, '\0', sizeof(chip));
-	chip.chip_addr = chip_addr;
-	chip.offset_len = 1;	/* we assume */
-	ret = device_probe_child(dev, &chip);
-	debug("%s:  device_probe_child: ret=%d\n", __func__, ret);
+	chip = dev_get_parent_platdata(dev);
+	chip->chip_addr = chip_addr;
+	chip->offset_len = offset_len;
+	ret = device_probe(dev);
+	debug("%s:  device_probe: ret=%d\n", __func__, ret);
 	if (ret)
 		goto err_probe;
 
@@ -247,13 +248,18 @@
 	return 0;
 
 err_probe:
+	/*
+	 * If the device failed to probe, unbind it. There is nothing there
+	 * on the bus so we don't want to leave it lying around
+	 */
 	device_unbind(dev);
 err_bind:
 	free(str);
 	return ret;
 }
 
-int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp)
+int i2c_get_chip(struct udevice *bus, uint chip_addr, uint offset_len,
+		 struct udevice **devp)
 {
 	struct udevice *dev;
 
@@ -261,15 +267,9 @@
 	      bus->name, chip_addr);
 	for (device_find_first_child(bus, &dev); dev;
 			device_find_next_child(&dev)) {
-		struct dm_i2c_chip store;
-		struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+		struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 		int ret;
 
-		if (!chip) {
-			chip = &store;
-			i2c_chip_ofdata_to_platdata(gd->fdt_blob,
-						    dev->of_offset, chip);
-		}
 		if (chip->chip_addr == chip_addr) {
 			ret = device_probe(dev);
 			debug("found, ret=%d\n", ret);
@@ -280,10 +280,11 @@
 		}
 	}
 	debug("not found\n");
-	return i2c_bind_driver(bus, chip_addr, devp);
+	return i2c_bind_driver(bus, chip_addr, offset_len, devp);
 }
 
-int i2c_get_chip_for_busnum(int busnum, int chip_addr, struct udevice **devp)
+int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
+			    struct udevice **devp)
 {
 	struct udevice *bus;
 	int ret;
@@ -293,7 +294,7 @@
 		debug("Cannot find I2C bus %d\n", busnum);
 		return ret;
 	}
-	ret = i2c_get_chip(bus, chip_addr, devp);
+	ret = i2c_get_chip(bus, chip_addr, offset_len, devp);
 	if (ret) {
 		debug("Cannot find I2C chip %02x on bus %d\n", chip_addr,
 		      busnum);
@@ -303,8 +304,8 @@
 	return 0;
 }
 
-int i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
-	      struct udevice **devp)
+int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
+		 struct udevice **devp)
 {
 	int ret;
 
@@ -318,13 +319,13 @@
 		return ret;
 
 	/* The chip was found, see if we have a driver, and probe it */
-	ret = i2c_get_chip(bus, chip_addr, devp);
+	ret = i2c_get_chip(bus, chip_addr, 1, devp);
 	debug("%s:  i2c_get_chip: ret=%d\n", __func__, ret);
 
 	return ret;
 }
 
-int i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+int dm_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 {
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct dm_i2c_bus *i2c = bus->uclass_priv;
@@ -345,12 +346,7 @@
 	return 0;
 }
 
-/*
- * i2c_get_bus_speed:
- *
- *  Returns speed of selected I2C bus in Hz
- */
-int i2c_get_bus_speed(struct udevice *bus)
+int dm_i2c_get_bus_speed(struct udevice *bus)
 {
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct dm_i2c_bus *i2c = bus->uclass_priv;
@@ -364,7 +360,7 @@
 int i2c_set_chip_flags(struct udevice *dev, uint flags)
 {
 	struct udevice *bus = dev->parent;
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	int ret;
 
@@ -380,7 +376,7 @@
 
 int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	*flagsp = chip->flags;
 
@@ -389,7 +385,7 @@
 
 int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	if (offset_len > I2C_MAX_OFFSET_LEN)
 		return -EINVAL;
@@ -419,7 +415,8 @@
 int i2c_chip_ofdata_to_platdata(const void *blob, int node,
 				struct dm_i2c_chip *chip)
 {
-	chip->offset_len = 1;	/* default */
+	chip->offset_len = fdtdec_get_int(gd->fdt_blob, node,
+					  "u-boot,i2c-offset-len", 1);
 	chip->flags = 0;
 	chip->chip_addr = fdtdec_get_int(gd->fdt_blob, node, "reg", -1);
 	if (chip->chip_addr == -1) {
@@ -438,21 +435,34 @@
 	i2c->speed_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 				     "clock-frequency", 100000);
 
-	return i2c_set_bus_speed(dev, i2c->speed_hz);
+	return dm_i2c_set_bus_speed(dev, i2c->speed_hz);
 }
 
-int i2c_post_bind(struct udevice *dev)
+static int i2c_post_bind(struct udevice *dev)
 {
 	/* Scan the bus for devices */
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
+static int i2c_child_post_bind(struct udevice *dev)
+{
+	struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
+
+	if (dev->of_offset == -1)
+		return 0;
+
+	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+}
+
 UCLASS_DRIVER(i2c) = {
 	.id		= UCLASS_I2C,
 	.name		= "i2c",
-	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_bind	= i2c_post_bind,
 	.post_probe	= i2c_post_probe,
+	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
+	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.child_post_bind = i2c_child_post_bind,
 };
 
 UCLASS_DRIVER(i2c_generic) = {
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
new file mode 100644
index 0000000..6707edd
--- /dev/null
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <i2c.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct uniphier_fi2c_regs {
+	u32 cr;				/* control register */
+#define I2C_CR_MST	(1 << 3)	/* master mode */
+#define I2C_CR_STA	(1 << 2)	/* start condition */
+#define I2C_CR_STO	(1 << 1)	/* stop condition */
+#define I2C_CR_NACK	(1 << 0)	/* not ACK */
+	u32 dttx;			/* send FIFO (write-only) */
+#define dtrx		dttx		/* receive FIFO (read-only) */
+#define I2C_DTTX_CMD	(1 << 8)	/* send command (slave addr) */
+#define I2C_DTTX_RD	(1 << 0)	/* read */
+	u32 __reserved;			/* no register at offset 0x08 */
+	u32 slad;			/* slave address */
+	u32 cyc;			/* clock cycle control */
+	u32 lctl;			/* clock low period control */
+	u32 ssut;			/* restart/stop setup time control */
+	u32 dsut;			/* data setup time control */
+	u32 intr;			/* interrupt status */
+	u32 ie;				/* interrupt enable */
+	u32 ic;				/* interrupt clear */
+#define I2C_INT_TE	(1 << 9)	/* TX FIFO empty */
+#define I2C_INT_RB	(1 << 4)	/* received specified bytes */
+#define I2C_INT_NA	(1 << 2)	/* no answer */
+#define I2C_INT_AL	(1 << 1)	/* arbitration lost */
+	u32 sr;				/* status register */
+#define I2C_SR_DB	(1 << 12)	/* device busy */
+#define I2C_SR_BB	(1 << 8)	/* bus busy */
+#define I2C_SR_RFF	(1 << 3)	/* Rx FIFO full */
+#define I2C_SR_RNE	(1 << 2)	/* Rx FIFO not empty */
+#define I2C_SR_TNF	(1 << 1)	/* Tx FIFO not full */
+#define I2C_SR_TFE	(1 << 0)	/* Tx FIFO empty */
+	u32 __reserved2;		/* no register at offset 0x30 */
+	u32 rst;			/* reset control */
+#define I2C_RST_TBRST	(1 << 2)	/* clear Tx FIFO */
+#define I2C_RST_RBRST	(1 << 1)	/* clear Rx FIFO */
+#define I2C_RST_RST	(1 << 0)	/* forcible bus reset */
+	u32 bm;				/* bus monitor */
+	u32 noise;			/* noise filter control */
+	u32 tbc;			/* Tx byte count setting */
+	u32 rbc;			/* Rx byte count setting */
+	u32 tbcm;			/* Tx byte count monitor */
+	u32 rbcm;			/* Rx byte count monitor */
+	u32 brst;			/* bus reset */
+#define I2C_BRST_FOEN	(1 << 1)	/* normal operation */
+#define I2C_BRST_RSCLO	(1 << 0)	/* release SCL low fixing */
+};
+
+#define FIOCLK	50000000
+
+struct uniphier_fi2c_dev {
+	struct uniphier_fi2c_regs __iomem *regs;	/* register base */
+	unsigned long fioclk;			/* internal operation clock */
+	unsigned long timeout;			/* time out (us) */
+};
+
+static int poll_status(u32 __iomem *reg, u32 flag)
+{
+	int wait = 1000000; /* 1 sec is long enough */
+
+	while (readl(reg) & flag) {
+		if (wait-- < 0)
+			return -EREMOTEIO;
+		udelay(1);
+	}
+
+	return 0;
+}
+
+static int reset_bus(struct uniphier_fi2c_regs __iomem *regs)
+{
+	int ret;
+
+	/* bus forcible reset */
+	writel(I2C_RST_RST, &regs->rst);
+	ret = poll_status(&regs->rst, I2C_RST_RST);
+	if (ret < 0)
+		debug("error: fail to reset I2C controller\n");
+
+	return ret;
+}
+
+static int check_device_busy(struct uniphier_fi2c_regs __iomem *regs)
+{
+	int ret;
+
+	ret = poll_status(&regs->sr, I2C_SR_DB);
+	if (ret < 0) {
+		debug("error: device busy too long. reset...\n");
+		ret = reset_bus(regs);
+	}
+
+	return ret;
+}
+
+static int uniphier_fi2c_probe(struct udevice *dev)
+{
+	fdt_addr_t addr;
+	fdt_size_t size;
+	struct uniphier_fi2c_dev *priv = dev_get_priv(dev);
+	int ret;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg",
+				    &size);
+
+	priv->regs = map_sysmem(addr, size);
+
+	if (!priv->regs)
+		return -ENOMEM;
+
+	priv->fioclk = FIOCLK;
+
+	/* bus forcible reset */
+	ret = reset_bus(priv->regs);
+	if (ret < 0)
+		return ret;
+
+	writel(I2C_BRST_FOEN | I2C_BRST_RSCLO, &priv->regs->brst);
+
+	return 0;
+}
+
+static int uniphier_fi2c_remove(struct udevice *dev)
+{
+	struct uniphier_fi2c_dev *priv = dev_get_priv(dev);
+
+	unmap_sysmem(priv->regs);
+
+	return 0;
+}
+
+static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
+			bool *stop)
+{
+	u32 irq;
+	unsigned long wait = dev->timeout;
+	int ret = -EREMOTEIO;
+
+	do {
+		udelay(1);
+		irq = readl(&dev->regs->intr);
+	} while (!(irq & flags) && wait--);
+
+	if (wait < 0) {
+		debug("error: time out\n");
+		return ret;
+	}
+
+	if (irq & I2C_INT_AL) {
+		debug("error: arbitration lost\n");
+		*stop = false;
+		return ret;
+	}
+
+	if (irq & I2C_INT_NA) {
+		debug("error: no answer\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int issue_stop(struct uniphier_fi2c_dev *dev, int old_ret)
+{
+	int ret;
+
+	debug("stop condition\n");
+	writel(I2C_CR_MST | I2C_CR_STO, &dev->regs->cr);
+
+	ret = poll_status(&dev->regs->sr, I2C_SR_DB);
+	if (ret < 0)
+		debug("error: device busy after operation\n");
+
+	return old_ret ? old_ret : ret;
+}
+
+static int uniphier_fi2c_transmit(struct uniphier_fi2c_dev *dev, uint addr,
+				  uint len, const u8 *buf, bool *stop)
+{
+	int ret;
+	const u32 irq_flags = I2C_INT_TE | I2C_INT_NA | I2C_INT_AL;
+	struct uniphier_fi2c_regs __iomem *regs = dev->regs;
+
+	debug("%s: addr = %x, len = %d\n", __func__, addr, len);
+
+	writel(I2C_DTTX_CMD | addr << 1, &regs->dttx);
+
+	writel(irq_flags, &regs->ie);
+	writel(irq_flags, &regs->ic);
+
+	debug("start condition\n");
+	writel(I2C_CR_MST | I2C_CR_STA, &regs->cr);
+
+	ret = wait_for_irq(dev, irq_flags, stop);
+	if (ret < 0)
+		goto error;
+
+	while (len--) {
+		debug("sending %x\n", *buf);
+		writel(*buf++, &regs->dttx);
+
+		writel(irq_flags, &regs->ic);
+
+		ret = wait_for_irq(dev, irq_flags, stop);
+		if (ret < 0)
+			goto error;
+	}
+
+error:
+	writel(irq_flags, &regs->ic);
+
+	if (*stop)
+		ret = issue_stop(dev, ret);
+
+	return ret;
+}
+
+static int uniphier_fi2c_receive(struct uniphier_fi2c_dev *dev, uint addr,
+				 uint len, u8 *buf, bool *stop)
+{
+	int ret = 0;
+	const u32 irq_flags = I2C_INT_RB | I2C_INT_NA | I2C_INT_AL;
+	struct uniphier_fi2c_regs __iomem *regs = dev->regs;
+
+	debug("%s: addr = %x, len = %d\n", __func__, addr, len);
+
+	/*
+	 * In case 'len == 0', only the slave address should be sent
+	 * for probing, which is covered by the transmit function.
+	 */
+	if (len == 0)
+		return uniphier_fi2c_transmit(dev, addr, len, buf, stop);
+
+	writel(I2C_DTTX_CMD | I2C_DTTX_RD | addr << 1, &regs->dttx);
+
+	writel(0, &regs->rbc);
+	writel(irq_flags, &regs->ie);
+	writel(irq_flags, &regs->ic);
+
+	debug("start condition\n");
+	writel(I2C_CR_MST | I2C_CR_STA | (len == 1 ? I2C_CR_NACK : 0),
+	       &regs->cr);
+
+	while (len--) {
+		ret = wait_for_irq(dev, irq_flags, stop);
+		if (ret < 0)
+			goto error;
+
+		*buf++ = readl(&regs->dtrx);
+		debug("received %x\n", *(buf - 1));
+
+		if (len == 1)
+			writel(I2C_CR_MST | I2C_CR_NACK, &regs->cr);
+
+		writel(irq_flags, &regs->ic);
+	}
+
+error:
+	writel(irq_flags, &regs->ic);
+
+	if (*stop)
+		ret = issue_stop(dev, ret);
+
+	return ret;
+}
+
+static int uniphier_fi2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+			     int nmsgs)
+{
+	int ret;
+	struct uniphier_fi2c_dev *dev = dev_get_priv(bus);
+	bool stop;
+
+	ret = check_device_busy(dev->regs);
+	if (ret < 0)
+		return ret;
+
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		/* If next message is read, skip the stop condition */
+		stop = nmsgs > 1 && msg[1].flags & I2C_M_RD ? false : true;
+
+		if (msg->flags & I2C_M_RD)
+			ret = uniphier_fi2c_receive(dev, msg->addr, msg->len,
+						    msg->buf, &stop);
+		else
+			ret = uniphier_fi2c_transmit(dev, msg->addr, msg->len,
+						     msg->buf, &stop);
+
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static int uniphier_fi2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	int ret;
+	unsigned int clk_count;
+	struct uniphier_fi2c_dev *dev = dev_get_priv(bus);
+	struct uniphier_fi2c_regs __iomem *regs = dev->regs;
+
+	/* max supported frequency is 400 kHz */
+	if (speed > 400000)
+		return -EINVAL;
+
+	ret = check_device_busy(dev->regs);
+	if (ret < 0)
+		return ret;
+
+	/* make sure the bus is idle when changing the frequency */
+	writel(I2C_BRST_RSCLO, &regs->brst);
+
+	clk_count = dev->fioclk / speed;
+
+	writel(clk_count, &regs->cyc);
+	writel(clk_count / 2, &regs->lctl);
+	writel(clk_count / 2, &regs->ssut);
+	writel(clk_count / 16, &regs->dsut);
+
+	writel(I2C_BRST_FOEN | I2C_BRST_RSCLO, &regs->brst);
+
+	/*
+	 * Theoretically, each byte can be transferred in
+	 * 1000000 * 9 / speed usec.
+	 * This time out value is long enough.
+	 */
+	dev->timeout = 100000000L / speed;
+
+	return 0;
+}
+
+static const struct dm_i2c_ops uniphier_fi2c_ops = {
+	.xfer = uniphier_fi2c_xfer,
+	.set_bus_speed = uniphier_fi2c_set_bus_speed,
+};
+
+static const struct udevice_id uniphier_fi2c_of_match[] = {
+	{ .compatible = "panasonic,uniphier-fi2c" },
+	{},
+};
+
+U_BOOT_DRIVER(uniphier_fi2c) = {
+	.name = "uniphier-fi2c",
+	.id = UCLASS_I2C,
+	.of_match = uniphier_fi2c_of_match,
+	.probe = uniphier_fi2c_probe,
+	.remove = uniphier_fi2c_remove,
+	.priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev),
+	.ops = &uniphier_fi2c_ops,
+};
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
new file mode 100644
index 0000000..64a9ed8
--- /dev/null
+++ b/drivers/i2c/i2c-uniphier.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <i2c.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct uniphier_i2c_regs {
+	u32 dtrm;			/* data transmission */
+#define I2C_DTRM_STA	(1 << 10)
+#define I2C_DTRM_STO	(1 << 9)
+#define I2C_DTRM_NACK	(1 << 8)
+#define I2C_DTRM_RD	(1 << 0)
+	u32 drec;			/* data reception */
+#define I2C_DREC_STS	(1 << 12)
+#define I2C_DREC_LRB	(1 << 11)
+#define I2C_DREC_LAB	(1 << 9)
+	u32 myad;			/* slave address */
+	u32 clk;			/* clock frequency control */
+	u32 brst;			/* bus reset */
+#define I2C_BRST_FOEN	(1 << 1)
+#define I2C_BRST_BRST	(1 << 0)
+	u32 hold;			/* hold time control */
+	u32 bsts;			/* bus status monitor */
+	u32 noise;			/* noise filter control */
+	u32 setup;			/* setup time control */
+};
+
+#define IOBUS_FREQ	100000000
+
+struct uniphier_i2c_dev {
+	struct uniphier_i2c_regs __iomem *regs;	/* register base */
+	unsigned long input_clk;	/* master clock (Hz) */
+	unsigned long wait_us;		/* wait for every byte transfer (us) */
+};
+
+static int uniphier_i2c_probe(struct udevice *dev)
+{
+	fdt_addr_t addr;
+	fdt_size_t size;
+	struct uniphier_i2c_dev *priv = dev_get_priv(dev);
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+
+	priv->regs = map_sysmem(addr, size);
+
+	if (!priv->regs)
+		return -ENOMEM;
+
+	priv->input_clk = IOBUS_FREQ;
+
+	/* deassert reset */
+	writel(0x3, &priv->regs->brst);
+
+	return 0;
+}
+
+static int uniphier_i2c_remove(struct udevice *dev)
+{
+	struct uniphier_i2c_dev *priv = dev_get_priv(dev);
+
+	unmap_sysmem(priv->regs);
+
+	return 0;
+}
+
+static int send_and_recv_byte(struct uniphier_i2c_dev *dev, u32 dtrm)
+{
+	writel(dtrm, &dev->regs->dtrm);
+
+	/*
+	 * This controller only provides interruption to inform the completion
+	 * of each byte transfer.  (No status register to poll it.)
+	 * Unfortunately, U-Boot does not have a good support of interrupt.
+	 * Wait for a while.
+	 */
+	udelay(dev->wait_us);
+
+	return readl(&dev->regs->drec);
+}
+
+static int send_byte(struct uniphier_i2c_dev *dev, u32 dtrm, bool *stop)
+{
+	int ret = 0;
+	u32 drec;
+
+	drec = send_and_recv_byte(dev, dtrm);
+
+	if (drec & I2C_DREC_LAB) {
+		debug("uniphier_i2c: bus arbitration failed\n");
+		*stop = false;
+		ret = -EREMOTEIO;
+	}
+	if (drec & I2C_DREC_LRB) {
+		debug("uniphier_i2c: slave did not return ACK\n");
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+static int uniphier_i2c_transmit(struct uniphier_i2c_dev *dev, uint addr,
+				 uint len, const u8 *buf, bool *stop)
+{
+	int ret;
+
+	debug("%s: addr = %x, len = %d\n", __func__, addr, len);
+
+	ret = send_byte(dev, I2C_DTRM_STA | I2C_DTRM_NACK | addr << 1, stop);
+	if (ret < 0)
+		goto fail;
+
+	while (len--) {
+		ret = send_byte(dev, I2C_DTRM_NACK | *buf++, stop);
+		if (ret < 0)
+			goto fail;
+	}
+
+fail:
+	if (*stop)
+		writel(I2C_DTRM_STO | I2C_DTRM_NACK, &dev->regs->dtrm);
+
+	return ret;
+}
+
+static int uniphier_i2c_receive(struct uniphier_i2c_dev *dev, uint addr,
+				uint len, u8 *buf, bool *stop)
+{
+	int ret;
+
+	debug("%s: addr = %x, len = %d\n", __func__, addr, len);
+
+	ret = send_byte(dev, I2C_DTRM_STA | I2C_DTRM_NACK |
+			I2C_DTRM_RD | addr << 1, stop);
+	if (ret < 0)
+		goto fail;
+
+	while (len--)
+		*buf++ = send_and_recv_byte(dev, len ? 0 : I2C_DTRM_NACK);
+
+fail:
+	if (*stop)
+		writel(I2C_DTRM_STO | I2C_DTRM_NACK, &dev->regs->dtrm);
+
+	return ret;
+}
+
+static int uniphier_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+			     int nmsgs)
+{
+	int ret = 0;
+	struct uniphier_i2c_dev *dev = dev_get_priv(bus);
+	bool stop;
+
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		/* If next message is read, skip the stop condition */
+		stop = nmsgs > 1 && msg[1].flags & I2C_M_RD ? false : true;
+
+		if (msg->flags & I2C_M_RD)
+			ret = uniphier_i2c_receive(dev, msg->addr, msg->len,
+						   msg->buf, &stop);
+		else
+			ret = uniphier_i2c_transmit(dev, msg->addr, msg->len,
+						    msg->buf, &stop);
+
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static int uniphier_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	struct uniphier_i2c_dev *priv = dev_get_priv(bus);
+
+	/* max supported frequency is 400 kHz */
+	if (speed > 400000)
+		return -EINVAL;
+
+	/* bus reset: make sure the bus is idle when change the frequency */
+	writel(0x1, &priv->regs->brst);
+
+	writel((priv->input_clk / speed / 2 << 16) | (priv->input_clk / speed),
+	       &priv->regs->clk);
+
+	writel(0x3, &priv->regs->brst);
+
+	/*
+	 * Theoretically, each byte can be transferred in
+	 * 1000000 * 9 / speed usec.  For safety, wait more than double.
+	 */
+	priv->wait_us = 20000000 / speed;
+
+	return 0;
+}
+
+
+static const struct dm_i2c_ops uniphier_i2c_ops = {
+	.xfer = uniphier_i2c_xfer,
+	.set_bus_speed = uniphier_i2c_set_bus_speed,
+};
+
+static const struct udevice_id uniphier_i2c_of_match[] = {
+	{ .compatible = "panasonic,uniphier-i2c" },
+	{},
+};
+
+U_BOOT_DRIVER(uniphier_i2c) = {
+	.name = "uniphier-i2c",
+	.id = UCLASS_I2C,
+	.of_match = uniphier_i2c_of_match,
+	.probe = uniphier_i2c_probe,
+	.remove = uniphier_i2c_remove,
+	.priv_auto_alloc_size = sizeof(struct uniphier_i2c_dev),
+	.ops = &uniphier_i2c_ops,
+};
diff --git a/drivers/i2c/kona_i2c.c b/drivers/i2c/kona_i2c.c
index 5eab338..9af496b 100644
--- a/drivers/i2c/kona_i2c.c
+++ b/drivers/i2c/kona_i2c.c
@@ -156,7 +156,7 @@
 #define I2C_M_RD	0x0001	/* read data */
 #define I2C_M_NOSTART	0x4000	/* no restart between msgs */
 
-struct i2c_msg {
+struct kona_i2c_msg {
 	uint16_t addr;
 	uint16_t flags;
 	uint16_t len;
@@ -297,7 +297,7 @@
 
 /* Read any amount of data using the RX FIFO from the i2c bus */
 static int bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev,
-				  struct i2c_msg *msg)
+				  struct kona_i2c_msg *msg)
 {
 	unsigned int bytes_to_read = MAX_RX_FIFO_SIZE;
 	unsigned int last_byte_nak = 0;
@@ -392,7 +392,7 @@
 
 /* Write any amount of data using TX FIFO to the i2c bus */
 static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev,
-				   struct i2c_msg *msg)
+				   struct kona_i2c_msg *msg)
 {
 	unsigned int bytes_to_write = MAX_TX_FIFO_SIZE;
 	unsigned int bytes_written = 0;
@@ -418,7 +418,7 @@
 
 /* Send i2c address */
 static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev,
-				struct i2c_msg *msg)
+				struct kona_i2c_msg *msg)
 {
 	unsigned char addr;
 
@@ -480,9 +480,9 @@
 
 /* Master transfer function */
 static int bcm_kona_i2c_xfer(struct bcm_kona_i2c_dev *dev,
-			     struct i2c_msg msgs[], int num)
+			     struct kona_i2c_msg msgs[], int num)
 {
-	struct i2c_msg *pmsg;
+	struct kona_i2c_msg *pmsg;
 	int rc = 0;
 	int i;
 
@@ -635,7 +635,7 @@
 			 int alen, uchar *buffer, int len)
 {
 	/* msg[0] writes the addr, msg[1] reads the data */
-	struct i2c_msg msg[2];
+	struct kona_i2c_msg msg[2];
 	unsigned char msgbuf0[64];
 	struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
 
@@ -663,7 +663,7 @@
 static int kona_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
 			  int alen, uchar *buffer, int len)
 {
-	struct i2c_msg msg[1];
+	struct kona_i2c_msg msg[1];
 	unsigned char msgbuf0[64];
 	unsigned int i;
 	struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c
index dac3463..e65cce0 100644
--- a/drivers/i2c/mv_i2c.c
+++ b/drivers/i2c/mv_i2c.c
@@ -31,7 +31,7 @@
 #endif
 
 /* All transfers are described by this data structure */
-struct i2c_msg {
+struct mv_i2c_msg {
 	u8 condition;
 	u8 acknack;
 	u8 direction;
@@ -157,7 +157,7 @@
  *          -5: illegal parameters
  *          -6: bus is busy and couldn't be aquired
  */
-int i2c_transfer(struct i2c_msg *msg)
+int i2c_transfer(struct mv_i2c_msg *msg)
 {
 	int ret;
 
@@ -286,7 +286,7 @@
  */
 int i2c_probe(uchar chip)
 {
-	struct i2c_msg msg;
+	struct mv_i2c_msg msg;
 
 	i2c_reset();
 
@@ -322,7 +322,7 @@
  */
 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
-	struct i2c_msg msg;
+	struct mv_i2c_msg msg;
 	u8 addr_bytes[3]; /* lowest...highest byte of data address */
 
 	PRINTD(("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, "
@@ -410,7 +410,7 @@
  */
 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
-	struct i2c_msg msg;
+	struct mv_i2c_msg msg;
 	u8 addr_bytes[3]; /* lowest...highest byte of data address */
 
 	PRINTD(("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, "
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index fd328f0..b4ee33f 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -9,8 +9,9 @@
  * as they seem to have the same I2C controller inside.
  * The different address mapping is handled by the s3c24xx.h files below.
  */
-
 #include <common.h>
+#include <errno.h>
+#include <dm.h>
 #include <fdtdec.h>
 #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 #include <asm/arch/clk.h>
@@ -111,9 +112,9 @@
 #define I2C_START_STOP	0x20	/* START / STOP */
 #define I2C_TXRX_ENA	0x10	/* I2C Tx/Rx enable */
 
-#define I2C_TIMEOUT_MS 1000		/* 1 second */
+#define I2C_TIMEOUT_MS 10		/* 10 ms */
 
-#define	HSI2C_TIMEOUT_US 100000 /* 100 ms, finer granularity */
+#define	HSI2C_TIMEOUT_US 10000 /* 10 ms, finer granularity */
 
 
 /* To support VCMA9 boards and other who dont define max_i2c_num */
@@ -121,13 +122,23 @@
 #define CONFIG_MAX_I2C_NUM 1
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * For SPL boot some boards need i2c before SDRAM is initialised so force
  * variables to live in SRAM
  */
+#ifdef CONFIG_SYS_I2C
 static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
 			__attribute__((section(".data")));
+#endif
 
+enum exynos_i2c_type {
+	EXYNOS_I2C_STD,
+	EXYNOS_I2C_HS,
+};
+
+#ifdef CONFIG_SYS_I2C
 /**
  * Get a pointer to the given bus index
  *
@@ -147,6 +158,7 @@
 	debug("Undefined bus: %d\n", bus_idx);
 	return NULL;
 }
+#endif
 
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 static int GetI2CSDA(void)
@@ -251,6 +263,7 @@
 	writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
 }
 
+#ifdef CONFIG_SYS_I2C
 static struct s3c24x0_i2c *get_base_i2c(int bus)
 {
 #ifdef CONFIG_EXYNOS4
@@ -267,6 +280,7 @@
 	return s3c24x0_get_base_i2c();
 #endif
 }
+#endif
 
 static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
 {
@@ -326,7 +340,7 @@
 			return 0;
 		}
 	}
-	return -1;
+	return -EINVAL;
 }
 
 static void hsi2c_ch_init(struct s3c24x0_i2c_bus *i2c_bus)
@@ -398,18 +412,20 @@
 	hsi2c_ch_init(i2c_bus);
 }
 
+#ifdef CONFIG_SYS_I2C
 static void s3c24x0_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
 {
 	struct s3c24x0_i2c *i2c;
 	struct s3c24x0_i2c_bus *bus;
-
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
 #endif
 	ulong start_time = get_timer(0);
 
-	/* By default i2c channel 0 is the current bus */
 	i2c = get_base_i2c(adap->hwadapnr);
+	bus = &i2c_bus[adap->hwadapnr];
+	if (!bus)
+		return;
 
 	/*
 	 * In case the previous transfer is still going, wait to give it a
@@ -470,12 +486,13 @@
 #endif
 	}
 #endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
+
 	i2c_ch_init(i2c, speed, slaveadd);
 
-	bus = &i2c_bus[adap->hwadapnr];
 	bus->active = true;
 	bus->regs = i2c;
 }
+#endif /* CONFIG_SYS_I2C */
 
 /*
  * Poll the appropriate bit of the fifo status register until the interface is
@@ -698,20 +715,27 @@
 	return rv;
 }
 
+#ifdef CONFIG_SYS_I2C
 static unsigned int s3c24x0_i2c_set_bus_speed(struct i2c_adapter *adap,
-					  unsigned int speed)
+					      unsigned int speed)
+#else
+static int s3c24x0_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
+#endif
 {
 	struct s3c24x0_i2c_bus *i2c_bus;
 
+#ifdef CONFIG_SYS_I2C
 	i2c_bus = get_bus(adap->hwadapnr);
 	if (!i2c_bus)
-		return -1;
-
+		return -EFAULT;
+#else
+	i2c_bus = dev_get_priv(dev);
+#endif
 	i2c_bus->clock_frequency = speed;
 
 	if (i2c_bus->is_highspeed) {
 		if (hsi2c_get_clk_details(i2c_bus))
-			return -1;
+			return -EFAULT;
 		hsi2c_ch_init(i2c_bus);
 	} else {
 		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
@@ -721,17 +745,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_EXYNOS5
-static void exynos_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
-{
-	/* This will override the speed selected in the fdt for that port */
-	debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
-	if (i2c_set_bus_speed(speed))
-		printf("i2c_init: failed to init bus %d for speed = %d\n",
-						adap->hwadapnr, speed);
-}
-#endif
-
 /*
  * cmd_type is 0 for write, 1 for read.
  *
@@ -844,15 +857,23 @@
 	return result;
 }
 
+#ifdef CONFIG_SYS_I2C
 static int s3c24x0_i2c_probe(struct i2c_adapter *adap, uchar chip)
+#else
+static int s3c24x0_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
+#endif
 {
 	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar buf[1];
 	int ret;
 
+#ifdef CONFIG_SYS_I2C
 	i2c_bus = get_bus(adap->hwadapnr);
 	if (!i2c_bus)
-		return -1;
+		return -EFAULT;
+#else
+	i2c_bus = dev_get_priv(dev);
+#endif
 	buf[0] = 0;
 
 	/*
@@ -871,6 +892,7 @@
 	return ret != I2C_OK;
 }
 
+#ifdef CONFIG_SYS_I2C
 static int s3c24x0_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
 			    int alen, uchar *buffer, int len)
 {
@@ -878,9 +900,13 @@
 	uchar xaddr[4];
 	int ret;
 
+	i2c_bus = get_bus(adap->hwadapnr);
+	if (!i2c_bus)
+		return -EFAULT;
+
 	if (alen > 4) {
 		debug("I2C read: addr len %d not supported\n", alen);
-		return 1;
+		return -EADDRNOTAVAIL;
 	}
 
 	if (alen > 0) {
@@ -906,10 +932,6 @@
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c_bus = get_bus(adap->hwadapnr);
-	if (!i2c_bus)
-		return -1;
-
 	if (i2c_bus->is_highspeed)
 		ret = hsi2c_read(i2c_bus->hsregs, chip, &xaddr[4 - alen],
 				 alen, buffer, len);
@@ -921,7 +943,7 @@
 		if (i2c_bus->is_highspeed)
 			exynos5_i2c_reset(i2c_bus);
 		debug("I2c read failed %d\n", ret);
-		return 1;
+		return -EIO;
 	}
 	return 0;
 }
@@ -933,9 +955,13 @@
 	uchar xaddr[4];
 	int ret;
 
+	i2c_bus = get_bus(adap->hwadapnr);
+	if (!i2c_bus)
+		return -EFAULT;
+
 	if (alen > 4) {
 		debug("I2C write: addr len %d not supported\n", alen);
-		return 1;
+		return -EINVAL;
 	}
 
 	if (alen > 0) {
@@ -960,10 +986,6 @@
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c_bus = get_bus(adap->hwadapnr);
-	if (!i2c_bus)
-		return -1;
-
 	if (i2c_bus->is_highspeed)
 		ret = hsi2c_write(i2c_bus->hsregs, chip, &xaddr[4 - alen],
 				  alen, buffer, len, true);
@@ -985,7 +1007,7 @@
 			 int is_highspeed)
 {
 	struct s3c24x0_i2c_bus *bus;
-	int i;
+	int i, flags;
 
 	for (i = 0; i < count; i++) {
 		int node = node_list[i];
@@ -997,12 +1019,15 @@
 		bus->active = true;
 		bus->is_highspeed = is_highspeed;
 
-		if (is_highspeed)
+		if (is_highspeed) {
+			flags = PINMUX_FLAG_HS_MODE;
 			bus->hsregs = (struct exynos5_hsi2c *)
 					fdtdec_get_addr(blob, node, "reg");
-		else
+		} else {
+			flags = 0;
 			bus->regs = (struct s3c24x0_i2c *)
 					fdtdec_get_addr(blob, node, "reg");
+		}
 
 		bus->id = pinmux_decode_periph_id(blob, node);
 		bus->clock_frequency = fdtdec_get_int(blob, node,
@@ -1010,7 +1035,7 @@
 						CONFIG_SYS_I2C_S3C24X0_SPEED);
 		bus->node = node;
 		bus->bus_num = i;
-		exynos_pinmux_config(bus->id, 0);
+		exynos_pinmux_config(PERIPH_ID_I2C0 + bus->id, flags);
 
 		/* Mark position as used */
 		node_list[i] = -1;
@@ -1033,7 +1058,6 @@
 		COMPAT_SAMSUNG_EXYNOS5_I2C, node_list,
 		CONFIG_MAX_I2C_NUM);
 	process_nodes(blob, node_list, count, 1);
-
 }
 
 int i2c_get_bus_num_fdt(int node)
@@ -1046,7 +1070,7 @@
 	}
 
 	debug("%s: Can't find any matched I2C bus\n", __func__);
-	return -1;
+	return -EINVAL;
 }
 
 int i2c_reset_port_fdt(const void *blob, int node)
@@ -1057,18 +1081,18 @@
 	bus = i2c_get_bus_num_fdt(node);
 	if (bus < 0) {
 		debug("could not get bus for node %d\n", node);
-		return -1;
+		return bus;
 	}
 
 	i2c_bus = get_bus(bus);
 	if (!i2c_bus) {
-		debug("get_bus() failed for node node %d\n", node);
-		return -1;
+		debug("get_bus() failed for node %d\n", node);
+		return -EFAULT;
 	}
 
 	if (i2c_bus->is_highspeed) {
 		if (hsi2c_get_clk_details(i2c_bus))
-			return -1;
+			return -EINVAL;
 		hsi2c_ch_init(i2c_bus);
 	} else {
 		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
@@ -1077,7 +1101,17 @@
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_OF_CONTROL */
+
+#ifdef CONFIG_EXYNOS5
+static void exynos_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
+{
+	/* This will override the speed selected in the fdt for that port */
+	debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
+	if (i2c_set_bus_speed(speed))
+		error("i2c_init: failed to init bus for speed = %d", speed);
+}
+#endif /* CONFIG_EXYNOS5 */
 
 /*
  * Register s3c24x0 i2c adapters
@@ -1247,3 +1281,120 @@
 			CONFIG_SYS_I2C_S3C24X0_SPEED,
 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 0)
 #endif
+#endif /* CONFIG_SYS_I2C */
+
+#ifdef CONFIG_DM_I2C
+static int i2c_write_data(struct s3c24x0_i2c_bus *i2c_bus, uchar chip,
+			  uchar *buffer, int len, bool end_with_repeated_start)
+{
+	int ret;
+
+	if (i2c_bus->is_highspeed) {
+		ret = hsi2c_write(i2c_bus->hsregs, chip, 0, 0,
+				  buffer, len, true);
+		if (ret)
+			exynos5_i2c_reset(i2c_bus);
+	} else {
+		ret = i2c_transfer(i2c_bus->regs, I2C_WRITE,
+				   chip << 1, 0, 0, buffer, len);
+	}
+
+	return ret != I2C_OK;
+}
+
+static int i2c_read_data(struct s3c24x0_i2c_bus  *i2c_bus, uchar chip,
+			 uchar *buffer, int len)
+{
+	int ret;
+
+	if (i2c_bus->is_highspeed) {
+		ret = hsi2c_read(i2c_bus->hsregs, chip, 0, 0, buffer, len);
+		if (ret)
+			exynos5_i2c_reset(i2c_bus);
+	} else {
+		ret = i2c_transfer(i2c_bus->regs, I2C_READ,
+				   chip << 1, 0, 0, buffer, len);
+	}
+
+	return ret != I2C_OK;
+}
+
+static int s3c24x0_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+			    int nmsgs)
+{
+	struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
+	int ret;
+
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+
+		if (msg->flags & I2C_M_RD) {
+			ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+					    msg->len);
+		} else {
+			ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+					     msg->len, next_is_read);
+		}
+		if (ret)
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
+	int node, flags;
+
+	i2c_bus->is_highspeed = dev->of_id->data;
+	node = dev->of_offset;
+
+	if (i2c_bus->is_highspeed) {
+		flags = PINMUX_FLAG_HS_MODE;
+		i2c_bus->hsregs = (struct exynos5_hsi2c *)
+				fdtdec_get_addr(blob, node, "reg");
+	} else {
+		flags = 0;
+		i2c_bus->regs = (struct s3c24x0_i2c *)
+				fdtdec_get_addr(blob, node, "reg");
+	}
+
+	i2c_bus->id = pinmux_decode_periph_id(blob, node);
+
+	i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
+						"clock-frequency",
+						CONFIG_SYS_I2C_S3C24X0_SPEED);
+	i2c_bus->node = node;
+	i2c_bus->bus_num = dev->seq;
+
+	exynos_pinmux_config(i2c_bus->id, flags);
+
+	i2c_bus->active = true;
+
+	return 0;
+}
+
+static const struct dm_i2c_ops s3c_i2c_ops = {
+	.xfer		= s3c24x0_i2c_xfer,
+	.probe_chip	= s3c24x0_i2c_probe,
+	.set_bus_speed	= s3c24x0_i2c_set_bus_speed,
+};
+
+static const struct udevice_id s3c_i2c_ids[] = {
+	{ .compatible = "samsung,s3c2440-i2c", .data = EXYNOS_I2C_STD },
+	{ .compatible = "samsung,exynos5-hsi2c", .data = EXYNOS_I2C_HS },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_s3c) = {
+	.name	= "i2c_s3c",
+	.id	= UCLASS_I2C,
+	.of_match = s3c_i2c_ids,
+	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
+	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
+	.ops	= &s3c_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index f0e9f51..a943aa6 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -25,24 +25,24 @@
 static int get_emul(struct udevice *dev, struct udevice **devp,
 		    struct dm_i2c_ops **opsp)
 {
-	struct dm_i2c_chip *priv;
+	struct dm_i2c_chip *plat;
 	int ret;
 
 	*devp = NULL;
 	*opsp = NULL;
-	priv = dev_get_parentdata(dev);
-	if (!priv->emul) {
+	plat = dev_get_parent_platdata(dev);
+	if (!plat->emul) {
 		ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
 				       false);
 		if (ret)
 			return ret;
 
-		ret = device_get_child(dev, 0, &priv->emul);
+		ret = device_get_child(dev, 0, &plat->emul);
 		if (ret)
 			return ret;
 	}
-	*devp = priv->emul;
-	*opsp = i2c_get_ops(priv->emul);
+	*devp = plat->emul;
+	*opsp = i2c_get_ops(plat->emul);
 
 	return 0;
 }
@@ -60,7 +60,7 @@
 	if (msg->addr == SANDBOX_I2C_TEST_ADDR)
 		return 0;
 
-	ret = i2c_get_chip(bus, msg->addr, &dev);
+	ret = i2c_get_chip(bus, msg->addr, 1, &dev);
 	if (ret)
 		return ret;
 
@@ -82,20 +82,6 @@
 	.xfer		= sandbox_i2c_xfer,
 };
 
-static int sandbox_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	/* Ignore our test address */
-	if (i2c_chip->chip_addr == SANDBOX_I2C_TEST_ADDR)
-		return 0;
-	if (dev->of_offset == -1)
-		return 0;
-
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static const struct udevice_id sandbox_i2c_ids[] = {
 	{ .compatible = "sandbox,i2c" },
 	{ }
@@ -105,7 +91,5 @@
 	.name	= "i2c_sandbox",
 	.id	= UCLASS_I2C,
 	.of_match = sandbox_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = sandbox_i2c_child_pre_probe,
 	.ops	= &sandbox_i2c_ops,
 };
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 87290c3..f414287 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -484,21 +484,6 @@
 	.set_bus_speed	= tegra_i2c_set_bus_speed,
 };
 
-static int tegra_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
-static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
-{
-	return 0;
-}
-
 static const struct udevice_id tegra_i2c_ids[] = {
 	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
 	{ .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
@@ -510,10 +495,7 @@
 	.name	= "i2c_tegra",
 	.id	= UCLASS_I2C,
 	.of_match = tegra_i2c_ids,
-	.ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
 	.probe	= tegra_i2c_probe,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = tegra_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct i2c_bus),
 	.ops	= &tegra_i2c_ops,
 };
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index e69de29..bb00de7 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -0,0 +1,6 @@
+config CROS_EC_KEYB
+	bool "Enable Chrome OS EC keyboard support"
+	help
+	  Most ARM Chromebooks use an EC to provide access to the keyboard.
+	  Messages are used to request key scans from the EC and these are
+	  then decoded into keys by this driver.
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e69de29..0df25c3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -0,0 +1,55 @@
+config CMD_CROS_EC
+	bool "Enable crosec command"
+	depends on CROS_EC
+	help
+	  Enable command-line access to the Chrome OS EC (Embedded
+	  Controller). This provides the 'crosec' command which has
+	  a number of sub-commands for performing EC tasks such as
+	  updating its flash, accessing a small saved context area
+	  and talking to the I2C bus behind the EC (if there is one).
+
+config CROS_EC
+	bool "Enable Chrome OS EC"
+	help
+	  Enable access to the Chrome OS EC. This is a separate
+	  microcontroller typically available on a SPI bus on Chromebooks. It
+	  provides access to the keyboard, some internal storage and may
+	  control access to the battery and main PMIC depending on the
+	  device. You can use the 'crosec' command to access it.
+
+config CROS_EC_I2C
+	bool "Enable Chrome OS EC I2C driver"
+	depends on CROS_EC
+	help
+	  Enable I2C access to the Chrome OS EC. This is used on older
+	  ARM Chromebooks such as snow and spring before the standard bus
+	  changed to SPI. The EC will accept commands across the I2C using
+	  a special message protocol, and provide responses.
+
+config CROS_EC_LPC
+	bool "Enable Chrome OS EC LPC driver"
+	depends on CROS_EC
+	help
+	  Enable I2C access to the Chrome OS EC. This is used on x86
+	  Chromebooks such as link and falco. The keyboard is provided
+	  through a legacy port interface, so on x86 machines the main
+	  function of the EC is power and thermal management.
+
+config CROS_EC_SPI
+	bool "Enable Chrome OS EC SPI driver"
+	depends on CROS_EC
+	help
+	  Enable SPI access to the Chrome OS EC. This is used on newer
+	  ARM Chromebooks such as pit, pi and nyan-big. The SPI interface
+	  provides a faster and more robust interface than I2C but the bugs
+	  are less interesting.
+
+config DM_CROS_EC
+	bool "Enable Driver Model for Chrome OS EC"
+	depends on DM
+	help
+	  Enable driver model for the Chrome OS EC interface. This
+	  allows the cros_ec SPI driver to operate with CONFIG_DM_SPI
+	  but otherwise makes few changes. Since cros_ec also supports
+	  LPC (which doesn't support driver model yet), a full
+	  conversion is not yet possible.
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 9b4effb..5846e76 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -154,7 +154,9 @@
  * @param dev		CROS-EC device
  * @param dinp          Returns pointer to response data
  * @param din_len       Maximum size of response in bytes
- * @return number of bytes of response data, or <0 if error
+ * @return number of bytes of response data, or <0 if error. Note that error
+ * codes can be from errno.h or -ve EC_RES_INVALID_CHECKSUM values (and they
+ * overlap!)
  */
 static int handle_proto3_response(struct cros_ec_dev *dev,
 				  uint8_t **dinp, int din_len)
@@ -228,7 +230,7 @@
 
 #ifdef CONFIG_DM_CROS_EC
 	ops = dm_cros_ec_get_ops(dev->dev);
-	rv = ops->packet(dev->dev, out_bytes, in_bytes);
+	rv = ops->packet ? ops->packet(dev->dev, out_bytes, in_bytes) : -ENOSYS;
 #else
 	switch (dev->interface) {
 #ifdef CONFIG_CROS_EC_SPI
@@ -320,7 +322,7 @@
  *			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
+ * @return number of bytes in response, or -ve 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,
@@ -387,7 +389,7 @@
  *			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
+ * @return number of bytes in response, or -ve on error
  */
 static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 		      const void *dout, int dout_len,
@@ -606,10 +608,10 @@
 int cros_ec_interrupt_pending(struct cros_ec_dev *dev)
 {
 	/* no interrupt support : always poll */
-	if (!fdt_gpio_isvalid(&dev->ec_int))
+	if (!dm_gpio_is_valid(&dev->ec_int))
 		return -ENOENT;
 
-	return !gpio_get_value(dev->ec_int.gpio);
+	return dm_gpio_get_value(&dev->ec_int);
 }
 
 int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info)
@@ -1072,7 +1074,8 @@
 		return -1;
 	}
 
-	fdtdec_decode_gpio(blob, node, "ec-interrupt", &dev->ec_int);
+	gpio_request_by_name_nodev(blob, node, "ec-interrupt", 0, &dev->ec_int,
+				   GPIOD_IS_IN);
 	dev->optimise_flash_write = fdtdec_get_bool(blob, node,
 						    "optimise-flash-write");
 	*devp = dev;
@@ -1090,17 +1093,11 @@
 	char id[MSG_BYTES];
 
 	cdev->dev = dev;
-	fdtdec_decode_gpio(blob, node, "ec-interrupt", &cdev->ec_int);
+	gpio_request_by_name(dev, "ec-interrupt", 0, &cdev->ec_int,
+			     GPIOD_IS_IN);
 	cdev->optimise_flash_write = fdtdec_get_bool(blob, node,
 						     "optimise-flash-write");
 
-	/* we will poll the EC interrupt line */
-	fdtdec_setup_gpio(&cdev->ec_int);
-	if (fdt_gpio_isvalid(&cdev->ec_int)) {
-		gpio_request(cdev->ec_int.gpio, "cros-ec-irq");
-		gpio_direction_input(cdev->ec_int.gpio);
-	}
-
 	if (cros_ec_check_version(cdev)) {
 		debug("%s: Could not detect CROS-EC version\n", __func__);
 		return -CROS_EC_ERR_CHECK_VERSION;
@@ -1184,13 +1181,6 @@
 	}
 #endif
 
-	/* we will poll the EC interrupt line */
-	fdtdec_setup_gpio(&dev->ec_int);
-	if (fdt_gpio_isvalid(&dev->ec_int)) {
-		gpio_request(dev->ec_int.gpio, "cros-ec-irq");
-		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;
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
index 513cdb1..f9bc975 100644
--- a/drivers/misc/cros_ec_i2c.c
+++ b/drivers/misc/cros_ec_i2c.c
@@ -14,6 +14,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <i2c.h>
 #include <cros_ec.h>
 
@@ -23,11 +24,11 @@
 #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)
+static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd,
+			       int cmd_version, const uint8_t *dout,
+			       int dout_len, uint8_t **dinp, int din_len)
 {
-	int old_bus = 0;
+	struct cros_ec_dev *dev = udev->uclass_priv;
 	/* version8, cmd8, arglen8, out8[dout_len], csum8 */
 	int out_bytes = dout_len + 4;
 	/* response8, arglen8, in8[din_len], checksum8 */
@@ -37,8 +38,6 @@
 	uint8_t *in_ptr;
 	int len, csum, ret;
 
-	old_bus = i2c_get_bus_num();
-
 	/*
 	 * Sanity-check I/O sizes given transaction overhead in internal
 	 * buffers.
@@ -86,36 +85,24 @@
 	*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);
+	ret = dm_i2c_write(udev, 0, dev->dout, out_bytes);
 	if (ret) {
-		debug("%s: Cannot complete I2C write to 0x%x\n",
-			__func__, dev->addr);
+		debug("%s: Cannot complete I2C write to %s\n", __func__,
+		      udev->name);
 		ret = -1;
 	}
 
 	if (!ret) {
-		ret = i2c_read(dev->addr, 0, 0, in_ptr, in_bytes);
+		ret = dm_i2c_read(udev, 0, in_ptr, in_bytes);
 		if (ret) {
-			debug("%s: Cannot complete I2C read from 0x%x\n",
-				__func__, dev->addr);
+			debug("%s: Cannot complete I2C read from %s\n",
+			      __func__, udev->name);
 			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;
@@ -142,35 +129,24 @@
 	return din_len;
 }
 
-int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+static int cros_ec_probe(struct udevice *dev)
 {
-	/* 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;
+	return cros_ec_register(dev);
 }
 
-/**
- * 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);
+static struct dm_cros_ec_ops cros_ec_ops = {
+	.command = cros_ec_i2c_command,
+};
 
-	return 0;
-}
+static const struct udevice_id cros_ec_ids[] = {
+	{ .compatible = "google,cros-ec" },
+	{ }
+};
+
+U_BOOT_DRIVER(cros_ec_i2c) = {
+	.name		= "cros_ec",
+	.id		= UCLASS_CROS_EC,
+	.of_match	= cros_ec_ids,
+	.probe		= cros_ec_probe,
+	.ops		= &cros_ec_ops,
+};
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index e6dba29..9359c56 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -21,14 +21,9 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#ifdef CONFIG_DM_CROS_EC
 int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes)
 {
 	struct cros_ec_dev *dev = udev->uclass_priv;
-#else
-int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
-{
-#endif
 	struct spi_slave *slave = dev_get_parentdata(dev->dev);
 	int rv;
 
@@ -67,18 +62,11 @@
  * @param din_len	Maximum size of response in bytes
  * @return number of bytes in response, or -1 on error
  */
-#ifdef CONFIG_DM_CROS_EC
 int cros_ec_spi_command(struct udevice *udev, uint8_t cmd, int cmd_version,
 		     const uint8_t *dout, int dout_len,
 		     uint8_t **dinp, int din_len)
 {
 	struct cros_ec_dev *dev = udev->uclass_priv;
-#else
-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)
-{
-#endif
 	struct spi_slave *slave = dev_get_parentdata(dev->dev);
 	int in_bytes = din_len + 4;	/* status, length, checksum, trailer */
 	uint8_t *out;
@@ -166,65 +154,12 @@
 	return len;
 }
 
-#ifndef CONFIG_DM_CROS_EC
-int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+static int cros_ec_probe(struct udevice *dev)
 {
-	/* 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)
-{
-	int ret;
-
-	ret = spi_setup_slave_fdt(blob, dev->node, dev->parent_node,
-				  &slave);
-	if (ret) {
-		debug("%s: Could not setup SPI slave\n", __func__);
-		return ret;
-	}
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_DM_CROS_EC
-int cros_ec_probe(struct udevice *dev)
-{
-	struct spi_slave *slave = dev_get_parentdata(dev);
-	int ret;
-
-	/*
-	 * TODO(sjg@chromium.org)
-	 *
-	 * This is really horrible at present. It is an artifact of removing
-	 * the child_pre_probe() method for SPI. Everything here could go in
-	 * an automatic function, except that spi_get_bus_and_cs() wants to
-	 * set it up manually and call device_probe_child().
-	 *
-	 * The solution may be to re-enable the child_pre_probe() method for
-	 * SPI and have it do nothing if the child is already passed in via
-	 * device_probe_child().
-	 */
-	slave->dev = dev;
-	ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
-	if (ret)
-		return ret;
 	return cros_ec_register(dev);
 }
 
-struct dm_cros_ec_ops cros_ec_ops = {
+static struct dm_cros_ec_ops cros_ec_ops = {
 	.packet = cros_ec_spi_packet,
 	.command = cros_ec_spi_command,
 };
@@ -241,4 +176,3 @@
 	.probe		= cros_ec_probe,
 	.ops		= &cros_ec_ops,
 };
-#endif
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 4ba5878..ed73687 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_MXC_MMC) += mxcmmc.o
 obj-$(CONFIG_MXS_MMC) += mxsmmc.o
 obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
+obj-$(CONFIG_X86) += pci_mmc.o
 obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index b18c75d..76fa0b0 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -321,7 +321,7 @@
 	if (mmc->ddr_mode)
 		regs |= DWMCI_DDR_MODE;
 	else
-		regs &= DWMCI_DDR_MODE;
+		regs &= ~DWMCI_DDR_MODE;
 
 	dwmci_writel(host, DWMCI_UHS_REG, regs);
 
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index dfa209b..e083745 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -13,14 +13,20 @@
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch/power.h>
 #include <asm/gpio.h>
 #include <asm-generic/errno.h>
 
 #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
+#define	DWMMC_MMC0_SDR_TIMING_VAL	0x03030001
+#define	DWMMC_MMC2_SDR_TIMING_VAL	0x03020001
+
+/* Exynos implmentation specific drver private data */
+struct dwmci_exynos_priv_data {
+	u32 sdr_timing;
+};
 
 /*
  * Function used as callback function to initialise the
@@ -28,7 +34,9 @@
  */
 static void exynos_dwmci_clksel(struct dwmci_host *host)
 {
-	dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
+	struct dwmci_exynos_priv_data *priv = host->priv;
+
+	dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
 unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
@@ -55,6 +63,8 @@
 
 static void exynos_dwmci_board_init(struct dwmci_host *host)
 {
+	struct dwmci_exynos_priv_data *priv = host->priv;
+
 	if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) {
 		dwmci_writel(host, EMMCP_MPSBEGIN0, 0);
 		dwmci_writel(host, EMMCP_SEND0, 0);
@@ -64,12 +74,17 @@
 			     MPSCTRL_NON_SECURE_READ_BIT |
 			     MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID);
 	}
+
+	/* Set to timing value at initial time */
+	if (priv->sdr_timing)
+		exynos_dwmci_clksel(host);
 }
 
 static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
 {
 	unsigned int div;
 	unsigned long freq, sclk;
+	struct dwmci_exynos_priv_data *priv = host->priv;
 
 	if (host->bus_hz)
 		freq = host->bus_hz;
@@ -88,11 +103,11 @@
 #endif
 	host->board_init = exynos_dwmci_board_init;
 
-	if (!host->clksel_val) {
+	if (!priv->sdr_timing) {
 		if (index == 0)
-			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+			priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
 		else if (index == 2)
-			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+			priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
 	}
 
 	host->caps = MMC_MODE_DDR_52MHz;
@@ -118,6 +133,7 @@
 int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
 {
 	struct dwmci_host *host = NULL;
+	struct dwmci_exynos_priv_data *priv;
 
 	host = malloc(sizeof(struct dwmci_host));
 	if (!host) {
@@ -125,11 +141,19 @@
 		return -ENOMEM;
 	}
 
+	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
+	if (!priv) {
+		error("dwmci_exynos_priv_data malloc fail!\n");
+		return -ENOMEM;
+	}
+
 	host->ioaddr = (void *)regbase;
 	host->buswidth = bus_width;
 
 	if (clksel)
-		host->clksel_val = clksel;
+		priv->sdr_timing = clksel;
+
+	host->priv = priv;
 
 	return exynos_dwmci_core_init(host, index);
 }
@@ -157,7 +181,14 @@
 					struct dwmci_host *host)
 {
 	int err = 0;
-	u32 base, clksel_val, timing[3];
+	u32 base, timing[3];
+	struct dwmci_exynos_priv_data *priv;
+
+	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
+	if (!priv) {
+		error("dwmci_exynos_priv_data malloc fail!\n");
+		return -ENOMEM;
+	}
 
 	/* Extract device id for each mmc channel */
 	host->dev_id = pinmux_decode_periph_id(blob, node);
@@ -166,7 +197,6 @@
 	if (host->dev_index == host->dev_id)
 		host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
 
-
 	/* Get the bus width from the device node */
 	host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
 	if (host->buswidth <= 0) {
@@ -190,16 +220,24 @@
 		return -EINVAL;
 	}
 
-	clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+	priv->sdr_timing = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
 			DWMCI_SET_DRV_CLK(timing[1]) |
 			DWMCI_SET_DIV_RATIO(timing[2]));
-	if (clksel_val)
-		host->clksel_val = clksel_val;
+
+	/* sdr_timing didn't assigned anything, use the default value */
+	if (!priv->sdr_timing) {
+		if (host->dev_index == 0)
+			priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
+		else if (host->dev_index == 2)
+			priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
+	}
 
 	host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0);
 	host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0);
 	host->div = fdtdec_get_int(blob, node, "div", 0);
 
+	host->priv = priv;
+
 	return 0;
 }
 
@@ -229,12 +267,21 @@
 {
 	int compat_id;
 	int node_list[DWMMC_MAX_CH_NUM];
+	int boot_dev_node;
 	int err = 0, count;
 
 	compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC;
 
 	count = fdtdec_find_aliases_for_id(blob, "mmc",
 				compat_id, node_list, DWMMC_MAX_CH_NUM);
+
+	/* For DWMMC always set boot device as mmc 0 */
+	if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) {
+		boot_dev_node = node_list[2];
+		node_list[2] = node_list[0];
+		node_list[0] = boot_dev_node;
+	}
+
 	err = exynos_dwmci_process_node(blob, node_list, count);
 
 	return err;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b8039cd..a13769e 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1693,11 +1693,19 @@
 {
 	struct mmc *m;
 	struct list_head *entry;
+	char *mmc_type;
 
 	list_for_each(entry, &mmc_devices) {
 		m = list_entry(entry, struct mmc, link);
 
+		if (m->has_init)
+			mmc_type = IS_SD(m) ? "SD" : "eMMC";
+		else
+			mmc_type = NULL;
+
 		printf("%s: %d", m->cfg->name, m->block_dev.dev);
+		if (mmc_type)
+			printf(" (%s)", mmc_type);
 
 		if (entry->next != &mmc_devices) {
 			printf("%c", separator);
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index c880ced..dc725cb 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -134,6 +134,10 @@
 
 	pbias_lite = readl(&t2_base->pbias_lite);
 	pbias_lite &= ~(PBIASLITEPWRDNZ1 | PBIASLITEPWRDNZ0);
+#ifdef CONFIG_TARGET_OMAP3_CAIRO
+	/* for cairo board, we need to set up 1.8 Volt bias level on MMC1 */
+	pbias_lite &= ~PBIASLITEVMODE0;
+#endif
 	writel(pbias_lite, &t2_base->pbias_lite);
 
 	writel(pbias_lite | PBIASLITEPWRDNZ1 |
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
new file mode 100644
index 0000000..37171bf
--- /dev/null
+++ b/drivers/mmc/pci_mmc.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015, Google, Inc
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/pci.h>
+
+int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
+		 int num_ids)
+{
+	struct sdhci_host *mmc_host;
+	pci_dev_t devbusfn;
+	u32 iobase;
+	int ret;
+	int i;
+
+	for (i = 0; i < num_ids; i++) {
+		devbusfn = pci_find_devices(mmc_supported, i);
+		if (devbusfn == -1)
+			return -ENODEV;
+
+		mmc_host = malloc(sizeof(struct sdhci_host));
+		if (!mmc_host)
+			return -ENOMEM;
+
+		mmc_host->name = (char *)name;
+		pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
+		mmc_host->ioaddr = (void *)iobase;
+		mmc_host->quirks = 0;
+		ret = add_sdhci(mmc_host, 0, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index a5d3487..3899372 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -102,17 +102,14 @@
 
 static int do_sdhci_init(struct sdhci_host *host)
 {
-	char str[20];
 	int dev_id, flag;
 	int err = 0;
 
 	flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
 	dev_id = host->index + PERIPH_ID_SDMMC0;
 
-	if (fdt_gpio_isvalid(&host->pwr_gpio)) {
-		sprintf(str, "sdhci%d_power", host->index & 0xf);
-		gpio_request(host->pwr_gpio.gpio, str);
-		gpio_direction_output(host->pwr_gpio.gpio, 1);
+	if (dm_gpio_is_valid(&host->pwr_gpio)) {
+		dm_gpio_set_value(&host->pwr_gpio, 1);
 		err = exynos_pinmux_config(dev_id, flag);
 		if (err) {
 			debug("MMC not configured\n");
@@ -120,11 +117,8 @@
 		}
 	}
 
-	if (fdt_gpio_isvalid(&host->cd_gpio)) {
-		sprintf(str, "sdhci%d_cd", host->index & 0xf);
-		gpio_request(host->cd_gpio.gpio, str);
-		gpio_direction_input(host->cd_gpio.gpio);
-		if (gpio_get_value(host->cd_gpio.gpio))
+	if (dm_gpio_is_valid(&host->cd_gpio)) {
+		if (dm_gpio_get_value(&host->cd_gpio))
 			return -ENODEV;
 
 		err = exynos_pinmux_config(dev_id, flag);
@@ -166,8 +160,10 @@
 	}
 	host->ioaddr = (void *)base;
 
-	fdtdec_decode_gpio(blob, node, "pwr-gpios", &host->pwr_gpio);
-	fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio);
+	gpio_request_by_name_nodev(blob, node, "pwr-gpios", 0, &host->pwr_gpio,
+				   GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio,
+				   GPIOD_IS_IN);
 
 	return 0;
 }
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index de88e19..82d7984 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -374,7 +374,8 @@
 				(host->quirks & SDHCI_QUIRK_USE_WIDE8))
 			ctrl |= SDHCI_CTRL_8BITBUS;
 	} else {
-		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
+		if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
+				(host->quirks & SDHCI_QUIRK_USE_WIDE8))
 			ctrl &= ~SDHCI_CTRL_8BITBUS;
 		if (mmc->bus_width == 4)
 			ctrl |= SDHCI_CTRL_4BITBUS;
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 5104795..2233545 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -215,7 +215,7 @@
 	return 0;
 }
 
-static void mmc_set_ios(struct mmc *mmc)
+static void sunxi_mmc_set_ios(struct mmc *mmc)
 {
 	struct sunxi_mmc_host *mmchost = mmc->priv;
 
@@ -237,7 +237,7 @@
 		writel(0x0, &mmchost->reg->width);
 }
 
-static int mmc_core_init(struct mmc *mmc)
+static int sunxi_mmc_core_init(struct mmc *mmc)
 {
 	struct sunxi_mmc_host *mmchost = mmc->priv;
 
@@ -298,8 +298,8 @@
 	return 0;
 }
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-			struct mmc_data *data)
+static int sunxi_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			      struct mmc_data *data)
 {
 	struct sunxi_mmc_host *mmchost = mmc->priv;
 	unsigned int cmdval = SUNXI_MMC_CMD_START;
@@ -432,9 +432,9 @@
 }
 
 static const struct mmc_ops sunxi_mmc_ops = {
-	.send_cmd	= mmc_send_cmd,
-	.set_ios	= mmc_set_ios,
-	.init		= mmc_core_init,
+	.send_cmd	= sunxi_mmc_send_cmd,
+	.set_ios	= sunxi_mmc_set_ios,
+	.init		= sunxi_mmc_core_init,
 	.getcd		= sunxi_mmc_getcd,
 };
 
@@ -449,11 +449,7 @@
 
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	cfg->host_caps = MMC_MODE_4BIT;
-	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-    defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN9I)
-	cfg->host_caps |= MMC_MODE_HC;
-#endif
+	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
 	cfg->f_min = 400000;
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 2bd36b0..2cd8cf1 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -515,8 +515,8 @@
 
 	debug("tegra_mmc_getcd called\n");
 
-	if (fdt_gpio_isvalid(&host->cd_gpio))
-		return fdtdec_get_gpio(&host->cd_gpio);
+	if (dm_gpio_is_valid(&host->cd_gpio))
+		return dm_gpio_get_value(&host->cd_gpio);
 
 	return 1;
 }
@@ -531,7 +531,6 @@
 static int do_mmc_init(int dev_index)
 {
 	struct mmc_host *host;
-	char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */
 	struct mmc *mmc;
 
 	/* DT should have been read & host config filled in */
@@ -539,27 +538,15 @@
 	if (!host->enabled)
 		return -1;
 
-	debug(" do_mmc_init: index %d, bus width %d "
-		"pwr_gpio %d cd_gpio %d\n",
-		dev_index, host->width,
-		host->pwr_gpio.gpio, host->cd_gpio.gpio);
+	debug(" do_mmc_init: index %d, bus width %d pwr_gpio %d cd_gpio %d\n",
+	      dev_index, host->width, gpio_get_number(&host->pwr_gpio),
+	      gpio_get_number(&host->cd_gpio));
 
 	host->clock = 0;
 	clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
 
-	if (fdt_gpio_isvalid(&host->pwr_gpio)) {
-		sprintf(gpusage, "SD/MMC%d PWR", dev_index);
-		gpio_request(host->pwr_gpio.gpio, gpusage);
-		gpio_direction_output(host->pwr_gpio.gpio, 1);
-		debug(" Power GPIO name = %s\n", host->pwr_gpio.name);
-	}
-
-	if (fdt_gpio_isvalid(&host->cd_gpio)) {
-		sprintf(gpusage, "SD/MMC%d CD", dev_index);
-		gpio_request(host->cd_gpio.gpio, gpusage);
-		gpio_direction_input(host->cd_gpio.gpio);
-		debug(" CD GPIO name = %s\n", host->cd_gpio.name);
-	}
+	if (dm_gpio_is_valid(&host->pwr_gpio))
+		dm_gpio_set_value(&host->pwr_gpio, 1);
 
 	memset(&host->cfg, 0, sizeof(host->cfg));
 
@@ -626,9 +613,12 @@
 		debug("%s: no sdmmc width found\n", __func__);
 
 	/* These GPIOs are optional */
-	fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio);
-	fdtdec_decode_gpio(blob, node, "wp-gpios", &host->wp_gpio);
-	fdtdec_decode_gpio(blob, node, "power-gpios", &host->pwr_gpio);
+	gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio,
+				   GPIOD_IS_IN);
+	gpio_request_by_name_nodev(blob, node, "wp-gpios", 0, &host->wp_gpio,
+				   GPIOD_IS_IN);
+	gpio_request_by_name_nodev(blob, node, "power-gpios", 0,
+				   &host->pwr_gpio, GPIOD_IS_OUT);
 
 	debug("%s: found controller at %p, width = %d, periph_id = %d\n",
 		__func__, host->reg, host->width, host->mmc_id);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 415ab4e..59278d1 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1 +1,3 @@
 source "drivers/mtd/nand/Kconfig"
+
+source "drivers/mtd/spi/Kconfig"
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 620b6e8..b16e3aa 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -44,6 +44,7 @@
 	u8		pmecc_corr_cap;
 	u16		pmecc_sector_size;
 	u32		pmecc_index_table_offset;
+	u32		pmecc_version;
 
 	int		pmecc_bytes_per_sector;
 	int		pmecc_sector_number;
@@ -486,6 +487,10 @@
 	int i, err_nbr, eccbytes;
 	uint8_t *buf_pos;
 
+	/* SAMA5D4 PMECC IP can correct errors for all 0xff page */
+	if (host->pmecc_version >= PMECC_VERSION_SAMA5D4)
+		goto normal_check;
+
 	eccbytes = nand_chip->ecc.bytes;
 	for (i = 0; i < eccbytes; i++)
 		if (ecc[i] != 0xff)
@@ -961,6 +966,10 @@
 	nand->ecc.write_page = atmel_nand_pmecc_write_page;
 	nand->ecc.strength = cap;
 
+	/* Check the PMECC ip version */
+	host->pmecc_version = pmecc_readl(host->pmerrloc, version);
+	dev_dbg(host->dev, "PMECC IP version is: %x\n", host->pmecc_version);
+
 	atmel_pmecc_core_init(mtd);
 
 	return 0;
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
index eac860d..b2d2682 100644
--- a/drivers/mtd/nand/atmel_nand_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -123,6 +123,20 @@
 	u32 sigma[25];	/* 0x28-0x88 Error Location Sigma Registers */
 	u32 el[24];	/* 0x8C-0xE8 Error Location Registers */
 	u32 reserved1[5];	/* 0xEC-0xFC Reserved */
+
+	/*
+	 * 0x100-0x1F8:
+	 *   Reserved for AT91SAM9X5, AT91SAM9N12.
+	 *   HSMC registers for SAMA5D3, SAMA5D4.
+	 */
+	u32 reserved2[63];
+
+	/*
+	 * 0x1FC:
+	 *   PMECC version for AT91SAM9X5, AT91SAM9N12.
+	 *   HSMC version for SAMA5D3, SAMA5D4. Can refer as PMECC version.
+	 */
+	u32 version;
 };
 
 /* For Error Location Configuration Register */
@@ -137,6 +151,12 @@
 #define		PMERRLOC_ERR_NUM_MASK		(0x1f << 8)
 #define		PMERRLOC_CALC_DONE		(1 << 0)
 
+/* PMECC IP version */
+#define PMECC_VERSION_SAMA5D4			0x113
+#define PMECC_VERSION_SAMA5D3			0x112
+#define PMECC_VERSION_AT91SAM9N12		0x102
+#define PMECC_VERSION_AT91SAM9X5		0x101
+
 /* Galois field dimension */
 #define PMECC_GF_DIMENSION_13			13
 #define PMECC_GF_DIMENSION_14			14
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index fc64f48..24123fc 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -989,12 +989,15 @@
 	if (err)
 		return err;
 
-#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
 	/* TODO: Implement for 16-bit bus width */
 	if (nand->options & NAND_BUSWIDTH_16)
 		nand->read_buf = nand_read_buf16;
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
 	else
 		nand->read_buf = omap_nand_read_prefetch8;
+#else
+	else
+		nand->read_buf = nand_read_buf;
 #endif
 
 	nand->dev_ready = omap_dev_ready;
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index 163cf29..b660f3b 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -79,7 +79,7 @@
 struct fdt_nand {
 	struct nand_ctlr *reg;
 	int enabled;		/* 1 to enable, 0 to disable */
-	struct fdt_gpio_state wp_gpio;	/* write-protect GPIO */
+	struct gpio_desc wp_gpio;	/* write-protect GPIO */
 	s32 width;		/* bit width, normally 8 */
 	u32 timing[FDT_NAND_TIMING_COUNT];
 };
@@ -945,8 +945,8 @@
 	config->reg = (struct nand_ctlr *)fdtdec_get_addr(blob, node, "reg");
 	config->enabled = fdtdec_get_is_enabled(blob, node);
 	config->width = fdtdec_get_int(blob, node, "nvidia,nand-width", 8);
-	err = fdtdec_decode_gpio(blob, node, "nvidia,wp-gpios",
-				 &config->wp_gpio);
+	err = gpio_request_by_name_nodev(blob, node, "nvidia,wp-gpios", 0,
+				 &config->wp_gpio, GPIOD_IS_OUT);
 	if (err)
 		return err;
 	err = fdtdec_get_int_array(blob, node, "nvidia,timing",
@@ -1009,8 +1009,7 @@
 	/* Adjust timing for NAND device */
 	setup_timing(config->timing, info->reg);
 
-	fdtdec_setup_gpio(&config->wp_gpio);
-	gpio_direction_output(config->wp_gpio.gpio, 1);
+	dm_gpio_set_value(&config->wp_gpio, 1);
 
 	our_mtd = &nand_info[devnum];
 	our_mtd->priv = nand;
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
new file mode 100644
index 0000000..2dc46b4
--- /dev/null
+++ b/drivers/mtd/spi/Kconfig
@@ -0,0 +1,14 @@
+config DM_SPI_FLASH
+	bool "Enable Driver Model for SPI flash"
+	depends on DM && SPI
+	help
+	  Enable driver model for SPI flash. This SPI flash interface
+	  (spi_flash_probe(), spi_flash_write(), etc.) is then
+	  implemented by the SPI flash uclass. There is one standard
+	  SPI flash driver which knows how to probe most chips
+	  supported by U-Boot. The uclass interface is defined in
+	  include/spi_flash.h, but is currently fully compatible
+	  with the old interface to avoid confusion and duplication
+	  during the transition parent. SPI and SPI flash must be
+	  enabled together (it is not possible to use driver model
+	  for one and not the other).
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 3024b98..d576d31 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -141,8 +141,10 @@
 		assert(bus->seq != -1);
 		if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS)
 			spec = state->spi[bus->seq][cs].spec;
-		if (!spec)
-			return -ENOENT;
+		if (!spec) {
+			ret = -ENOENT;
+			goto error;
+		}
 
 		file = strchr(spec, ':');
 		if (!file) {
@@ -196,6 +198,7 @@
 	return 0;
 
  error:
+	debug("%s: Got error %d\n", __func__, ret);
 	return ret;
 }
 
@@ -587,6 +590,11 @@
 
 void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
 {
+	struct udevice *dev;
+
+	dev = state->spi[busnum][cs].emul;
+	device_remove(dev);
+	device_unbind(dev);
 	state->spi[busnum][cs].emul = NULL;
 }
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index ce9987f..4103723 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -481,11 +481,12 @@
 int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 	struct spi_flash *flash;
 
 	flash = dev->uclass_priv;
 	flash->dev = dev;
-	debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
+	debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
 	return spi_flash_probe_slave(slave, flash);
 }
 
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 584cf5f..290d524 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1358,6 +1358,10 @@
 out_class:
 	class_destroy(ubi_class);
 out:
+#ifdef __UBOOT__
+	/* Reset any globals that the driver depends on being zeroed */
+	mtd_devs = 0;
+#endif
 	ubi_err("cannot initialize UBI, error %d", err);
 	return err;
 }
@@ -1384,6 +1388,10 @@
 	misc_deregister(&ubi_ctrl_cdev);
 	class_remove_file(ubi_class, &ubi_version);
 	class_destroy(ubi_class);
+#ifdef __UBOOT__
+	/* Reset any globals that the driver depends on being zeroed */
+	mtd_devs = 0;
+#endif
 }
 module_exit(ubi_exit);
 
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 9ded895..c03e935 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -236,8 +236,10 @@
 
 	start = get_timer(0);
 	while (readl(&dma_p->busmode) & DMAMAC_SRST) {
-		if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT)
+		if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
+			printf("DMA reset timeout\n");
 			return -1;
+		}
 
 		mdelay(100);
 	};
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 6531030..cd44222 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -4927,22 +4927,23 @@
 fill_rx(struct e1000_hw *hw)
 {
 	struct e1000_rx_desc *rd;
-	uint32_t flush_start, flush_end;
+	unsigned long flush_start, flush_end;
 
 	rx_last = rx_tail;
 	rd = rx_base + rx_tail;
 	rx_tail = (rx_tail + 1) % 8;
 	memset(rd, 0, 16);
-	rd->buffer_addr = cpu_to_le64((u32)packet);
+	rd->buffer_addr = cpu_to_le64((unsigned long)packet);
 
 	/*
 	 * Make sure there are no stale data in WB over this area, which
 	 * might get written into the memory while the e1000 also writes
 	 * into the same memory area.
 	 */
-	invalidate_dcache_range((u32)packet, (u32)packet + 4096);
+	invalidate_dcache_range((unsigned long)packet,
+				(unsigned long)packet + 4096);
 	/* Dump the DMA descriptor into RAM. */
-	flush_start = ((u32)rd) & ~(ARCH_DMA_MINALIGN - 1);
+	flush_start = ((unsigned long)rd) & ~(ARCH_DMA_MINALIGN - 1);
 	flush_end = flush_start + roundup(sizeof(*rd), ARCH_DMA_MINALIGN);
 	flush_dcache_range(flush_start, flush_end);
 
@@ -4963,7 +4964,7 @@
 	unsigned long tipg, tarc;
 	uint32_t ipgr1, ipgr2;
 
-	E1000_WRITE_REG(hw, TDBAL, (u32) tx_base);
+	E1000_WRITE_REG(hw, TDBAL, (unsigned long)tx_base);
 	E1000_WRITE_REG(hw, TDBAH, 0);
 
 	E1000_WRITE_REG(hw, TDLEN, 128);
@@ -5107,7 +5108,7 @@
 		E1000_WRITE_FLUSH(hw);
 	}
 	/* Setup the Base and Length of the Rx Descriptor Ring */
-	E1000_WRITE_REG(hw, RDBAL, (u32) rx_base);
+	E1000_WRITE_REG(hw, RDBAL, (unsigned long)rx_base);
 	E1000_WRITE_REG(hw, RDBAH, 0);
 
 	E1000_WRITE_REG(hw, RDLEN, 128);
@@ -5138,14 +5139,14 @@
 {
 	struct e1000_hw *hw = nic->priv;
 	struct e1000_rx_desc *rd;
-	uint32_t inval_start, inval_end;
+	unsigned long inval_start, inval_end;
 	uint32_t len;
 
 	/* return true if there's an ethernet packet ready to read */
 	rd = rx_base + rx_last;
 
 	/* Re-load the descriptor from RAM. */
-	inval_start = ((u32)rd) & ~(ARCH_DMA_MINALIGN - 1);
+	inval_start = ((unsigned long)rd) & ~(ARCH_DMA_MINALIGN - 1);
 	inval_end = inval_start + roundup(sizeof(*rd), ARCH_DMA_MINALIGN);
 	invalidate_dcache_range(inval_start, inval_end);
 
@@ -5154,8 +5155,9 @@
 	/*DEBUGOUT("recv: packet len=%d \n", rd->length); */
 	/* Packet received, make sure the data are re-loaded from RAM. */
 	len = le32_to_cpu(rd->length);
-	invalidate_dcache_range((u32)packet,
-				(u32)packet + roundup(len, ARCH_DMA_MINALIGN));
+	invalidate_dcache_range((unsigned long)packet,
+				(unsigned long)packet +
+				roundup(len, ARCH_DMA_MINALIGN));
 	NetReceive((uchar *)packet, len);
 	fill_rx(hw);
 	return 1;
@@ -5170,7 +5172,7 @@
 	struct e1000_hw *hw = nic->priv;
 	struct e1000_tx_desc *txp;
 	int i = 0;
-	uint32_t flush_start, flush_end;
+	unsigned long flush_start, flush_end;
 
 	txp = tx_base + tx_tail;
 	tx_tail = (tx_tail + 1) % 8;
@@ -5180,10 +5182,11 @@
 	txp->upper.data = 0;
 
 	/* Dump the packet into RAM so e1000 can pick them. */
-	flush_dcache_range((u32)nv_packet,
-			   (u32)nv_packet + roundup(length, ARCH_DMA_MINALIGN));
+	flush_dcache_range((unsigned long)nv_packet,
+			   (unsigned long)nv_packet +
+			   roundup(length, ARCH_DMA_MINALIGN));
 	/* Dump the descriptor into RAM as well. */
-	flush_start = ((u32)txp) & ~(ARCH_DMA_MINALIGN - 1);
+	flush_start = ((unsigned long)txp) & ~(ARCH_DMA_MINALIGN - 1);
 	flush_end = flush_start + roundup(sizeof(*txp), ARCH_DMA_MINALIGN);
 	flush_dcache_range(flush_start, flush_end);
 
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index bedab1d..35f1a57 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -398,8 +398,6 @@
 	sys_has_mdio =
 		(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
 
-	keystone2_net_serdes_setup();
-
 	if (sys_has_mdio)
 		keystone2_mdio_reset(mdio_bus);
 
@@ -556,6 +554,8 @@
 			return res;
 	}
 
+	keystone2_net_serdes_setup();
+
 	/* Create phy device and bind it with driver */
 #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
 	phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 507b9a3..1815b29 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -22,6 +22,63 @@
 	.shutdown = &genphy_shutdown,
 };
 
+/**
+ * KSZ8895
+ */
+
+static unsigned short smireg_to_phy(unsigned short reg)
+{
+	return ((reg & 0xc0) >> 3) + 0x06 + ((reg & 0x20) >> 5);
+}
+
+static unsigned short smireg_to_reg(unsigned short reg)
+{
+	return reg & 0x1F;
+}
+
+static void ksz8895_write_smireg(struct phy_device *phydev, int smireg, int val)
+{
+	phydev->bus->write(phydev->bus, smireg_to_phy(smireg), MDIO_DEVAD_NONE,
+						smireg_to_reg(smireg), val);
+}
+
+#if 0
+static int ksz8895_read_smireg(struct phy_device *phydev, int smireg)
+{
+	return phydev->bus->read(phydev->bus, smireg_to_phy(smireg),
+					MDIO_DEVAD_NONE, smireg_to_reg(smireg));
+}
+#endif
+
+int ksz8895_config(struct phy_device *phydev)
+{
+	/* we are connected directly to the switch without
+	 * dedicated PHY. SCONF1 == 001 */
+	phydev->link = 1;
+	phydev->duplex = DUPLEX_FULL;
+	phydev->speed = SPEED_100;
+
+	/* Force the switch to start */
+	ksz8895_write_smireg(phydev, 1, 1);
+
+	return 0;
+}
+
+static int ksz8895_startup(struct phy_device *phydev)
+{
+	return 0;
+}
+
+static struct phy_driver ksz8895_driver = {
+	.name = "Micrel KSZ8895/KSZ8864",
+	.uid  = 0x221450,
+	.mask = 0xffffe1,
+	.features = PHY_BASIC_FEATURES,
+	.config   = &ksz8895_config,
+	.startup  = &ksz8895_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 #ifndef CONFIG_PHY_MICREL_KSZ9021
 /*
  * I can't believe Micrel used the exact same part number
@@ -221,5 +278,6 @@
 	phy_register(&KS8721_driver);
 #endif
 	phy_register(&ksz9031_driver);
+	phy_register(&ksz8895_driver);
 	return 0;
 }
diff --git a/drivers/net/smc91111.h b/drivers/net/smc91111.h
index d9135cb..e19c491 100644
--- a/drivers/net/smc91111.h
+++ b/drivers/net/smc91111.h
@@ -236,7 +236,36 @@
 					  *(__b2 + __i) = SMC_inb((a),(r));  \
 					};  \
 				}while(0)
-
+#elif defined(CONFIG_MS7206SE)
+#define SWAB7206(x) ({ word __x = x; ((__x << 8)|(__x >> 8)); })
+#define SMC_inw(a, r) *((volatile word*)((a)->iobase + (r)))
+#define SMC_inb(a, r) (*((volatile byte*)((a)->iobase + ((r) ^ 0x01))))
+#define SMC_insw(a, r, b, l) \
+	do { \
+		int __i; \
+		word *__b2 = (word *)(b);		  \
+		for (__i = 0; __i < (l); __i++) { \
+			*__b2++ = SWAB7206(SMC_inw(a, r));	\
+		} \
+	} while (0)
+#define	SMC_outw(a, d, r)	(*((volatile word *)((a)->iobase+(r))) = d)
+#define	SMC_outb(a, d, r)	({	word __d = (byte)(d);  \
+				word __w = SMC_inw((a), ((r)&(~1)));	\
+				if (((r) & 1)) \
+					__w = (__w & 0x00ff) | (__d << 8); \
+				else \
+					__w = (__w & 0xff00) | (__d); \
+				SMC_outw((a), __w, ((r)&(~1)));	      \
+			})
+#define SMC_outsw(a, r, b, l) \
+	do { \
+		int __i; \
+		word *__b2 = (word *)(b);		  \
+		for (__i = 0; __i < (l); __i++) { \
+			SMC_outw(a, SWAB7206(*__b2), r);	  \
+			__b2++; \
+		} \
+	} while (0)
 #else			/* if not CONFIG_CPU_PXA25X and not CONFIG_LEON */
 
 #ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 79d6561..dcdba4e 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -597,6 +597,8 @@
 		tsec_configure_serdes(priv);
 
 	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
+	if (!phydev)
+		return 0;
 
 	phydev->supported &= supported;
 	phydev->advertising = phydev->supported;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 950a247..e1296ca 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -15,6 +15,7 @@
 #include <common.h>
 
 #include <command.h>
+#include <errno.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <pci.h>
@@ -236,6 +237,48 @@
 	return -1;
 }
 
+pci_dev_t pci_find_class(uint find_class, int index)
+{
+	int bus;
+	int devnum;
+	pci_dev_t bdf;
+	uint32_t class;
+
+	for (bus = 0; bus <= pci_last_busno(); bus++) {
+		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
+			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
+					      PCI_CLASS_REVISION, &class);
+			if (class >> 16 == 0xffff)
+				continue;
+
+			for (bdf = PCI_BDF(bus, devnum, 0);
+					bdf <= PCI_BDF(bus, devnum,
+						PCI_MAX_PCI_FUNCTIONS - 1);
+					bdf += PCI_BDF(0, 0, 1)) {
+				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
+						      &class);
+				class >>= 8;
+
+				if (class != find_class)
+					continue;
+				/*
+				 * Decrement the index. We want to return the
+				 * correct device, so index is 0 for the first
+				 * matching device, 1 for the second, etc.
+				 */
+				if (index) {
+					index--;
+					continue;
+				}
+				/* Return index'th controller. */
+				return bdf;
+			}
+		}
+	}
+
+	return -ENODEV;
+}
+
 pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
 {
 	struct pci_device_id ids[2] = { {}, {0, 0} };
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index ed92857..378efbf 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -223,9 +223,12 @@
 	struct pci_region *pci_mem = hose->pci_mem;
 	struct pci_region *pci_prefetch = hose->pci_prefetch;
 	struct pci_region *pci_io = hose->pci_io;
-	u16 cmdstat;
+	u16 cmdstat, prefechable_64;
 
 	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
+	pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
+				&prefechable_64);
+	prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
 
 	/* Configure bus number registers */
 	pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
@@ -252,12 +255,26 @@
 		/* Set up memory and I/O filter limits, assume 32-bit I/O space */
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
 					(pci_prefetch->bus_lower & 0xfff00000) >> 16);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
+#ifdef CONFIG_SYS_PCI_64BIT
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_BASE_UPPER32,
+					pci_prefetch->bus_lower >> 32);
+#else
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_BASE_UPPER32,
+					0x0);
+#endif
 
 		cmdstat |= PCI_COMMAND_MEMORY;
 	} else {
 		/* We don't support prefetchable memory for now, so disable */
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) {
+			pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0);
+			pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0);
+		}
 	}
 
 	if (pci_io) {
@@ -297,11 +314,28 @@
 	}
 
 	if (pci_prefetch) {
+		u16 prefechable_64;
+
+		pci_hose_read_config_word(hose, dev,
+					PCI_PREF_MEMORY_LIMIT,
+					&prefechable_64);
+		prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
+
 		/* Round memory allocator to 1MB boundary */
 		pciauto_region_align(pci_prefetch, 0x100000);
 
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
 				(pci_prefetch->bus_lower - 1) >> 16);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
+#ifdef CONFIG_SYS_PCI_64BIT
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_LIMIT_UPPER32,
+					(pci_prefetch->bus_lower - 1) >> 32);
+#else
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_LIMIT_UPPER32,
+					0x0);
+#endif
 	}
 
 	if (pci_io) {
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index eb76591..48c0a77 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -98,7 +98,7 @@
 			       rom_address | PCI_ROM_ADDRESS_ENABLE);
 #endif
 	debug("Option ROM address %x\n", rom_address);
-	rom_header = (struct pci_rom_header *)rom_address;
+	rom_header = (struct pci_rom_header *)(unsigned long)rom_address;
 
 	debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n",
 	      le16_to_cpu(rom_header->signature),
@@ -228,11 +228,12 @@
 #endif
 }
 
-int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
 {
 	struct pci_rom_header *rom, *ram;
 	int vesa_mode = -1;
 	uint16_t class;
+	bool emulate;
 	int ret;
 
 	/* Only execute VGA ROMs */
@@ -262,6 +263,29 @@
 	vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
 #endif
 	debug("Selected vesa mode %#x\n", vesa_mode);
+
+	if (exec_method & PCI_ROM_USE_NATIVE) {
+#ifdef CONFIG_X86
+		emulate = false;
+#else
+		if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
+			printf("BIOS native execution is only available on x86\n");
+			return -ENOSYS;
+		}
+		emulate = true;
+#endif
+	} else {
+#ifdef CONFIG_BIOSEMU
+		emulate = true;
+#else
+		if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) {
+			printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
+			return -ENOSYS;
+		}
+		emulate = false;
+#endif
+	}
+
 	if (emulate) {
 #ifdef CONFIG_BIOSEMU
 		BE_VGAInfo *info;
@@ -274,9 +298,6 @@
 				  vesa_mode, &mode_info);
 		if (ret)
 			return ret;
-#else
-		printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
-		return -ENOSYS;
 #endif
 	} else {
 #ifdef CONFIG_X86
@@ -284,9 +305,6 @@
 
 		bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
 				&mode_info);
-#else
-		printf("BIOS native execution is only available on x86\n");
-		return -ENOSYS;
 #endif
 	}
 	debug("Final vesa mode %#x\n", mode_info.video_mode);
diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
index 4c6de79..a60bb5f 100644
--- a/drivers/power/as3722.c
+++ b/drivers/power/as3722.c
@@ -31,7 +31,7 @@
 {
 	int err;
 
-	err = i2c_read(pmic, reg, value, 1);
+	err = dm_i2c_read(pmic, reg, value, 1);
 	if (err < 0)
 		return err;
 
@@ -42,7 +42,7 @@
 {
 	int err;
 
-	err = i2c_write(pmic, reg, &value, 1);
+	err = dm_i2c_write(pmic, reg, &value, 1);
 	if (err < 0)
 		return err;
 
@@ -242,7 +242,7 @@
 	const unsigned int address = 0x40;
 	int err;
 
-	err = i2c_get_chip_for_busnum(bus, address, &pmic);
+	err = i2c_get_chip_for_busnum(bus, address, 1, &pmic);
 	if (err)
 		return err;
 	err = as3722_read_id(pmic, &id, &revision);
diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
index 58bbd45..3e07f23 100644
--- a/drivers/power/axp221.c
+++ b/drivers/power/axp221.c
@@ -29,9 +29,7 @@
 #else
 	int ret;
 
-	rsb_init();
-
-	ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
+	ret = rsb_init();
 	if (ret)
 		return ret;
 
diff --git a/drivers/power/tps6586x.c b/drivers/power/tps6586x.c
index 29bab4c..8650983 100644
--- a/drivers/power/tps6586x.c
+++ b/drivers/power/tps6586x.c
@@ -37,7 +37,7 @@
 	int	retval = -1;
 
 	for (i = 0; i < MAX_I2C_RETRY; ++i) {
-		if (!i2c_read(tps6586x_dev, reg,  &data, 1)) {
+		if (!dm_i2c_read(tps6586x_dev, reg,  &data, 1)) {
 			retval = (int)data;
 			goto exit;
 		}
@@ -60,7 +60,7 @@
 	int	retval = -1;
 
 	for (i = 0; i < MAX_I2C_RETRY; ++i) {
-		if (!i2c_write(tps6586x_dev, reg, data, len)) {
+		if (!dm_i2c_write(tps6586x_dev, reg, data, len)) {
 			retval = 0;
 			goto exit;
 		}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index a0b6e02..1686a1f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -2,8 +2,69 @@
 	bool "Enable Driver Model for serial drivers"
 	depends on DM
 	help
-	  If you want to use driver model for serial drivers, say Y.
-	  To use legacy serial drivers, say N.
+	  Enable driver model for serial. This replaces
+	  drivers/serial/serial.c with the serial uclass, which
+	  implements serial_putc() etc. The uclass interface is
+	  defined in include/serial.h.
+
+config DEBUG_UART
+	bool "Enable an early debug UART for debugging"
+	help
+	  The debug UART is intended for use very early in U-Boot to debug
+	  problems when an ICE or other debug mechanism is not available.
+
+	  To use it you should:
+	  - Make sure your UART supports this interface
+	  - Enable CONFIG_DEBUG_UART
+	  - Enable the CONFIG for your UART to tell it to provide this interface
+	        (e.g. CONFIG_DEBUG_UART_NS16550)
+	  - Define the required settings as needed (see below)
+	  - Call debug_uart_init() before use
+	  - Call debug_uart_putc() to output a character
+
+	  Depending on your platform it may be possible to use this UART before
+	  a stack is available.
+
+	  If your UART does not support this interface you can probably add
+	  support quite easily. Remember that you cannot use driver model and
+	  it is preferred to use no stack.
+
+	  You must not use this UART once driver model is working and the
+	  serial drivers are up and running (done in serial_init()). Otherwise
+	  the drivers may conflict and you will get strange output.
+
+choice
+	prompt "Select which UART will provide the debug UART"
+	depends on DEBUG_UART
+
+config DEBUG_UART_NS16550
+	bool "ns16550"
+	help
+	  Select this to enable a debug UART using the ns16550 driver. You
+	  will need to provide parameters to make this work. The driver will
+	  be available until the real driver model serial is running.
+
+endchoice
+
+config DEBUG_UART_BASE
+	hex "Base address of UART"
+	depends on DEBUG_UART
+	help
+	  This is the base address of your UART for memory-mapped UARTs.
+
+	  A default should be provided by your board, but if not you will need
+	  to use the correct value here.
+
+config DEBUG_UART_CLOCK
+	int "UART input clock"
+	depends on DEBUG_UART
+	help
+	  The UART input clock determines the speed of the internal UART
+	  circuitry. The baud rate is derived from this by dividing the input
+	  clock down.
+
+	  A default should be provided by your board, but if not you will need
+	  to use the correct value here.
 
 config UNIPHIER_SERIAL
 	bool "UniPhier on-chip UART support"
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 4cc00cd..63b0cbf 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -8,6 +8,7 @@
 ifdef CONFIG_DM_SERIAL
 obj-y += serial-uclass.o
 obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
+obj-$(CONFIG_PPC) += serial_ppc.o
 else
 obj-y += serial.o
 obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 70c9462..eb00f1c 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -55,6 +55,37 @@
 #endif /* CONFIG_SYS_NS16550_IER */
 
 #ifdef CONFIG_DM_SERIAL
+
+static inline void serial_out_shift(unsigned char *addr, int shift, int value)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+	outb(value, (ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
+	out_le32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+	out_be32(addr, value);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+	writeb(value, addr + (1 << shift) - 1);
+#else
+	writeb(value, addr);
+#endif
+}
+
+static inline int serial_in_shift(unsigned char *addr, int shift)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+	return inb((ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
+	return in_le32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+	return in_be32(addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+	return readb(addr + (1 << reg_shift) - 1);
+#else
+	return readb(addr);
+#endif
+}
+
 static void ns16550_writeb(NS16550_t port, int offset, int value)
 {
 	struct ns16550_platdata *plat = port->plat;
@@ -66,17 +97,7 @@
 	 * As far as we know it doesn't make sense to support selection of
 	 * these options at run-time, so use the existing CONFIG options.
 	 */
-#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
-	outb(value, (ulong)addr);
-#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
-	out_le32(addr, value);
-#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
-	out_be32(addr, value);
-#elif defined(CONFIG_SYS_BIG_ENDIAN)
-	writeb(value, addr + (1 << plat->reg_shift) - 1);
-#else
-	writeb(value, addr);
-#endif
+	serial_out_shift(addr, plat->reg_shift, value);
 }
 
 static int ns16550_readb(NS16550_t port, int offset)
@@ -86,17 +107,8 @@
 
 	offset *= 1 << plat->reg_shift;
 	addr = map_sysmem(plat->base, 0) + offset;
-#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
-	return inb((ulong)addr);
-#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
-	return in_le32(addr);
-#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
-	return in_be32(addr);
-#elif defined(CONFIG_SYS_BIG_ENDIAN)
-	return readb(addr + (1 << plat->reg_shift) - 1);
-#else
-	return readb(addr);
-#endif
+
+	return serial_in_shift(addr, plat->reg_shift);
 }
 
 /* We can clean these up once everything is moved to driver model */
@@ -106,10 +118,15 @@
 	ns16550_readb(com_port, addr - (unsigned char *)com_port)
 #endif
 
-int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
+static inline int calc_divisor(NS16550_t port, int clock, int baudrate)
 {
 	const unsigned int mode_x_div = 16;
 
+	return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+}
+
+int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
+{
 #ifdef CONFIG_OMAP1510
 	/* If can't cleanly clock 115200 set div to 1 */
 	if ((clock == 12000000) && (baudrate == 115200)) {
@@ -119,7 +136,7 @@
 	port->osc_12m_sel = 0;			/* clear if previsouly set */
 #endif
 
-	return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+	return calc_divisor(port, clock, baudrate);
 }
 
 static void NS16550_setbrg(NS16550_t com_port, int baud_divisor)
@@ -219,6 +236,47 @@
 
 #endif /* CONFIG_NS16550_MIN_FUNCTIONS */
 
+#ifdef CONFIG_DEBUG_UART_NS16550
+
+#include <debug_uart.h>
+
+void debug_uart_init(void)
+{
+	struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
+	int baud_divisor;
+
+	/*
+	 * We copy the code from above because it is already horribly messy.
+	 * Trying to refactor to nicely remove the duplication doesn't seem
+	 * feasible. The better fix is to move all users of this driver to
+	 * driver model.
+	 */
+	baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
+				    CONFIG_BAUDRATE);
+
+	serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER);
+	serial_out_shift(&com_port->mcr, 0, UART_MCRVAL);
+	serial_out_shift(&com_port->fcr, 0, UART_FCRVAL);
+
+	serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL);
+	serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff);
+	serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff);
+	serial_out_shift(&com_port->lcr, 0, UART_LCRVAL);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+	struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
+
+	while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE))
+		;
+	serial_out_shift(&com_port->thr, 0, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
+
 #ifdef CONFIG_DM_SERIAL
 static int ns16550_serial_putc(struct udevice *dev, const char ch)
 {
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index d1b5777..3fc7104 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -258,6 +258,22 @@
 #endif
 	int ret;
 
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+	if (ops->setbrg)
+		ops->setbrg += gd->reloc_off;
+	if (ops->getc)
+		ops->getc += gd->reloc_off;
+	if (ops->putc)
+		ops->putc += gd->reloc_off;
+	if (ops->pending)
+		ops->pending += gd->reloc_off;
+	if (ops->clear)
+		ops->clear += gd->reloc_off;
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+	if (ops->loop)
+		ops->loop += gd->reloc_off
+#endif
+#endif
 	/* Set the baud rate */
 	if (ops->setbrg) {
 		ret = ops->setbrg(dev, gd->baudrate);
@@ -297,6 +313,7 @@
 UCLASS_DRIVER(serial) = {
 	.id		= UCLASS_SERIAL,
 	.name		= "serial",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_probe	= serial_post_probe,
 	.pre_remove	= serial_pre_remove,
 	.per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
diff --git a/drivers/serial/serial_ppc.c b/drivers/serial/serial_ppc.c
new file mode 100644
index 0000000..47141c6
--- /dev/null
+++ b/drivers/serial/serial_ppc.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+static const struct udevice_id ppc_serial_ids[] = {
+	{ .compatible = "ns16550" },
+	{ }
+};
+
+static int ppc_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ns16550_platdata *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = ns16550_serial_ofdata_to_platdata(dev);
+	if (ret)
+		return ret;
+	plat->clock = get_serial_clock();
+
+	return 0;
+}
+
+U_BOOT_DRIVER(serial_ns16550) = {
+	.name	= "serial_ppc",
+	.id	= UCLASS_SERIAL,
+	.of_match = ppc_serial_ids,
+	.ofdata_to_platdata = ppc_serial_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.probe = ns16550_serial_probe,
+	.ops	= &ns16550_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 7c1f271..3641c9f 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -1,18 +1,216 @@
 /*
  * SuperH SCIF device driver.
  * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu
+ * Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu
  * Copyright (C) 2002 - 2008  Paul Mundt
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
+#include <errno.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/processor.h>
-#include "serial_sh.h"
 #include <serial.h>
 #include <linux/compiler.h>
+#include <dm/platform_data/serial_sh.h>
+#include "serial_sh.h"
+
+#if defined(CONFIG_CPU_SH7760) || \
+	defined(CONFIG_CPU_SH7780) || \
+	defined(CONFIG_CPU_SH7785) || \
+	defined(CONFIG_CPU_SH7786)
+static int scif_rxfill(struct uart_port *port)
+{
+	return sci_in(port, SCRFDR) & 0xff;
+}
+#elif defined(CONFIG_CPU_SH7763)
+static int scif_rxfill(struct uart_port *port)
+{
+	if ((port->mapbase == 0xffe00000) ||
+	    (port->mapbase == 0xffe08000)) {
+		/* SCIF0/1*/
+		return sci_in(port, SCRFDR) & 0xff;
+	} else {
+		/* SCIF2 */
+		return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
+	}
+}
+#elif defined(CONFIG_ARCH_SH7372)
+static int scif_rxfill(struct uart_port *port)
+{
+	if (port->type == PORT_SCIFA)
+		return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+	else
+		return sci_in(port, SCRFDR);
+}
+#else
+static int scif_rxfill(struct uart_port *port)
+{
+	return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+}
+#endif
+
+static void sh_serial_init_generic(struct uart_port *port)
+{
+	sci_out(port, SCSCR , SCSCR_INIT(port));
+	sci_out(port, SCSCR , SCSCR_INIT(port));
+	sci_out(port, SCSMR, 0);
+	sci_out(port, SCSMR, 0);
+	sci_out(port, SCFCR, SCFCR_RFRST|SCFCR_TFRST);
+	sci_in(port, SCFCR);
+	sci_out(port, SCFCR, 0);
+}
+
+static void
+sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
+{
+	if (port->clk_mode == EXT_CLK) {
+		unsigned short dl = DL_VALUE(baudrate, clk);
+		sci_out(port, DL, dl);
+		/* Need wait: Clock * 1/dl $B!_(B 1/16 */
+		udelay((1000000 * dl * 16 / clk) * 1000 + 1);
+	} else {
+		sci_out(port, SCBRR, SCBRR_VALUE(baudrate, clk));
+	}
+}
+
+static void handle_error(struct uart_port *port)
+{
+	sci_in(port, SCxSR);
+	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+	sci_in(port, SCLSR);
+	sci_out(port, SCLSR, 0x00);
+}
+
+static int serial_raw_putc(struct uart_port *port, const char c)
+{
+	/* Tx fifo is empty */
+	if (!(sci_in(port, SCxSR) & SCxSR_TEND(port)))
+		return -EAGAIN;
+
+	sci_out(port, SCxTDR, c);
+	sci_out(port, SCxSR, sci_in(port, SCxSR) & ~SCxSR_TEND(port));
+
+	return 0;
+}
+
+static int serial_rx_fifo_level(struct uart_port *port)
+{
+	return scif_rxfill(port);
+}
+
+static int sh_serial_tstc_generic(struct uart_port *port)
+{
+	if (sci_in(port, SCxSR) & SCIF_ERRORS) {
+		handle_error(port);
+		return 0;
+	}
+
+	return serial_rx_fifo_level(port) ? 1 : 0;
+}
+
+static int serial_getc_check(struct uart_port *port)
+{
+	unsigned short status;
+
+	status = sci_in(port, SCxSR);
+
+	if (status & SCIF_ERRORS)
+		handle_error(port);
+	if (sci_in(port, SCLSR) & SCxSR_ORER(port))
+		handle_error(port);
+	return status & (SCIF_DR | SCxSR_RDxF(port));
+}
+
+static int sh_serial_getc_generic(struct uart_port *port)
+{
+	unsigned short status;
+	char ch;
+
+	if (!serial_getc_check(port))
+		return -EAGAIN;
+
+	ch = sci_in(port, SCxRDR);
+	status = sci_in(port, SCxSR);
+
+	sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+
+	if (status & SCIF_ERRORS)
+		handle_error(port);
+
+	if (sci_in(port, SCLSR) & SCxSR_ORER(port))
+		handle_error(port);
+
+	return ch;
+}
+
+#ifdef CONFIG_DM_SERIAL
+
+static int sh_serial_pending(struct udevice *dev, bool input)
+{
+	struct uart_port *priv = dev_get_priv(dev);
+
+	return sh_serial_tstc_generic(priv);
+}
+
+static int sh_serial_putc(struct udevice *dev, const char ch)
+{
+	struct uart_port *priv = dev_get_priv(dev);
+
+	return serial_raw_putc(priv, ch);
+}
+
+static int sh_serial_getc(struct udevice *dev)
+{
+	struct uart_port *priv = dev_get_priv(dev);
+
+	return sh_serial_getc_generic(priv);
+}
+
+static int sh_serial_setbrg(struct udevice *dev, int baudrate)
+{
+	struct sh_serial_platdata *plat = dev_get_platdata(dev);
+	struct uart_port *priv = dev_get_priv(dev);
+
+	sh_serial_setbrg_generic(priv, plat->clk, baudrate);
+
+	return 0;
+}
+
+static int sh_serial_probe(struct udevice *dev)
+{
+	struct sh_serial_platdata *plat = dev_get_platdata(dev);
+	struct uart_port *priv = dev_get_priv(dev);
+
+	priv->membase	= (unsigned char *)plat->base;
+	priv->mapbase	= plat->base;
+	priv->type	= plat->type;
+	priv->clk_mode	= plat->clk_mode;
+
+	sh_serial_init_generic(priv);
+
+	return 0;
+}
+
+static const struct dm_serial_ops sh_serial_ops = {
+	.putc = sh_serial_putc,
+	.pending = sh_serial_pending,
+	.getc = sh_serial_getc,
+	.setbrg = sh_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_sh) = {
+	.name	= "serial_sh",
+	.id	= UCLASS_SERIAL,
+	.probe	= sh_serial_probe,
+	.ops	= &sh_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size = sizeof(struct uart_port),
+};
+
+#else /* CONFIG_DM_SERIAL */
 
 #if defined(CONFIG_CONS_SCIF0)
 # define SCIF_BASE	SCIF0_BASE
@@ -41,148 +239,66 @@
 #endif
 
 static struct uart_port sh_sci = {
-	.membase	= (unsigned char*)SCIF_BASE,
+	.membase	= (unsigned char *)SCIF_BASE,
 	.mapbase	= SCIF_BASE,
 	.type		= SCIF_BASE_PORT,
+#ifdef CONFIG_SCIF_USE_EXT_CLK
+	.clk_mode =	EXT_CLK,
+#endif
 };
 
 static void sh_serial_setbrg(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
-#ifdef CONFIG_SCIF_USE_EXT_CLK
-	unsigned short dl = DL_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ);
-	sci_out(&sh_sci, DL, dl);
-	/* Need wait: Clock * 1/dl $B!_(B 1/16 */
-	udelay((1000000 * dl * 16 / CONFIG_SYS_CLK_FREQ) * 1000 + 1);
-#else
-	sci_out(&sh_sci, SCBRR,
-		SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ));
-#endif
+	struct uart_port *port = &sh_sci;
+
+	sh_serial_setbrg_generic(port, CONFIG_SH_SCIF_CLK_FREQ, gd->baudrate);
 }
 
 static int sh_serial_init(void)
 {
-	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci));
-	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci));
-	sci_out(&sh_sci, SCSMR, 0);
-	sci_out(&sh_sci, SCSMR, 0);
-	sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST);
-	sci_in(&sh_sci, SCFCR);
-	sci_out(&sh_sci, SCFCR, 0);
+	struct uart_port *port = &sh_sci;
 
+	sh_serial_init_generic(port);
 	serial_setbrg();
+
 	return 0;
 }
 
-#if defined(CONFIG_CPU_SH7760) || \
-	defined(CONFIG_CPU_SH7780) || \
-	defined(CONFIG_CPU_SH7785) || \
-	defined(CONFIG_CPU_SH7786)
-static int scif_rxfill(struct uart_port *port)
-{
-	return sci_in(port, SCRFDR) & 0xff;
-}
-#elif defined(CONFIG_CPU_SH7763)
-static int scif_rxfill(struct uart_port *port)
-{
-	if ((port->mapbase == 0xffe00000) ||
-		(port->mapbase == 0xffe08000)) {
-		/* SCIF0/1*/
-		return sci_in(port, SCRFDR) & 0xff;
-	} else {
-		/* SCIF2 */
-		return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
-	}
-}
-#elif defined(CONFIG_ARCH_SH7372)
-static int scif_rxfill(struct uart_port *port)
-{
-	if (port->type == PORT_SCIFA)
-		return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
-	else
-		return sci_in(port, SCRFDR);
-}
-#else
-static int scif_rxfill(struct uart_port *port)
-{
-	return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
-}
-#endif
-
-static int serial_rx_fifo_level(void)
-{
-	return scif_rxfill(&sh_sci);
-}
-
-static void handle_error(void)
-{
-	sci_in(&sh_sci, SCxSR);
-	sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci));
-	sci_in(&sh_sci, SCLSR);
-	sci_out(&sh_sci, SCLSR, 0x00);
-}
-
-static void serial_raw_putc(const char c)
-{
-	while (1) {
-		/* Tx fifo is empty */
-		if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci))
-			break;
-	}
-
-	sci_out(&sh_sci, SCxTDR, c);
-	sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci));
-}
-
 static void sh_serial_putc(const char c)
 {
-	if (c == '\n')
-		serial_raw_putc('\r');
-	serial_raw_putc(c);
+	struct uart_port *port = &sh_sci;
+
+	if (c == '\n') {
+		while (1) {
+			if  (serial_raw_putc(port, '\r') != -EAGAIN)
+				break;
+		}
+	}
+	while (1) {
+		if  (serial_raw_putc(port, c) != -EAGAIN)
+			break;
+	}
 }
 
 static int sh_serial_tstc(void)
 {
-	if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) {
-		handle_error();
-		return 0;
-	}
+	struct uart_port *port = &sh_sci;
 
-	return serial_rx_fifo_level() ? 1 : 0;
-}
-
-
-static int serial_getc_check(void)
-{
-	unsigned short status;
-
-	status = sci_in(&sh_sci, SCxSR);
-
-	if (status & SCIF_ERRORS)
-		handle_error();
-	if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci))
-		handle_error();
-	return status & (SCIF_DR | SCxSR_RDxF(&sh_sci));
+	return sh_serial_tstc_generic(port);
 }
 
 static int sh_serial_getc(void)
 {
-	unsigned short status;
-	char ch;
+	struct uart_port *port = &sh_sci;
+	int ch;
 
-	while (!serial_getc_check())
-		;
+	while (1) {
+		ch = sh_serial_getc_generic(port);
+		if (ch != -EAGAIN)
+			break;
+	}
 
-	ch = sci_in(&sh_sci, SCxRDR);
-	status = sci_in(&sh_sci, SCxSR);
-
-	sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci));
-
-	if (status & SCIF_ERRORS)
-			handle_error();
-
-	if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci))
-		handle_error();
 	return ch;
 }
 
@@ -206,3 +322,4 @@
 {
 	return &sh_serial_drv;
 }
+#endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index ef88c8f..528aa73 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -2,18 +2,16 @@
  * Copy and modify from linux/drivers/serial/sh-sci.h
  */
 
+#include <dm/platform_data/serial_sh.h>
+
 struct uart_port {
 	unsigned long	iobase;		/* in/out[bwl] */
 	unsigned char	*membase;	/* read/write[bwl] */
 	unsigned long	mapbase;	/* for ioremap */
-	unsigned int	type;		/* port type */
+	enum sh_serial_type type;	/* port type */
+	enum sh_clk_mode clk_mode;	/* clock mode */
 };
 
-#define PORT_SCI	52
-#define PORT_SCIF	53
-#define PORT_SCIFA	83
-#define PORT_SCIFB	93
-
 #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
 #include <asm/regs306x.h>
 #endif
@@ -526,6 +524,7 @@
 SCIF_FNS(SCxTDR, 0x20,  8)
 SCIF_FNS(SCxRDR, 0x24,  8)
 SCIF_FNS(SCLSR,  0x00,  0)
+SCIF_FNS(DL,	 0x00,  0) /* dummy */
 #elif defined(CONFIG_ARCH_SH7372) || \
 	defined(CONFIG_R8A7740)
 SCIF_FNS(SCSMR,  0x00, 16)
@@ -541,6 +540,7 @@
 SCIx_FNS(SCxTDR, 0x20,  8, 0x40,  8)
 SCIx_FNS(SCxRDR, 0x24,  8, 0x60,  8)
 SCIF_FNS(SCLSR,  0x00,  0)
+SCIF_FNS(DL,	 0x00,  0) /* dummy */
 #elif defined(CONFIG_CPU_SH7723) ||\
 	defined(CONFIG_CPU_SH7724)
 SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)
@@ -555,6 +555,7 @@
 SCIF_FNS(SCFCR,  0x18, 16)
 SCIF_FNS(SCFDR,  0x1c, 16)
 SCIF_FNS(SCLSR,  0x24, 16)
+SCIF_FNS(DL,	 0x00,  0) /* dummy */
 #else
 /*      reg      SCI/SH3   SCI/SH4  SCIF/SH3   SCIF/SH4  SCI/H8*/
 /*      name     off  sz   off  sz   off  sz   off  sz   off  sz*/
@@ -583,18 +584,21 @@
 SCIF_FNS(SCSPTR,			0,  0, 0x24, 16)
 SCIF_FNS(SCLSR,				0,  0, 0x28, 16)
 #else
+
 SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16)
 #if defined(CONFIG_CPU_SH7722)
 SCIF_FNS(SCSPTR,                        0,  0, 0, 0)
 #else
 SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16)
 #endif
+SCIF_FNS(SCLSR,                         0,  0, 0x24, 16)
+#endif
 #if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
 	defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
 SCIF_FNS(DL,				0,  0, 0x30, 16)
 SCIF_FNS(CKS,				0,  0, 0x34, 16)
-#endif
-SCIF_FNS(SCLSR,                         0,  0, 0x24, 16)
+#else
+SCIF_FNS(DL,				0,  0, 0x0,  0) /* dummy */
 #endif
 #endif
 #define sci_in(port, reg) sci_##reg##_in(port)
@@ -725,14 +729,14 @@
 #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
 #elif defined(CONFIG_CPU_SH7723) ||\
 	defined(CONFIG_CPU_SH7724)
-static inline int scbrr_calc(struct uart_port port, int bps, int clk)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
 {
-	if (port.type == PORT_SCIF)
+	if (port->type == PORT_SCIF)
 		return (clk+16*bps)/(32*bps)-1;
 	else
 		return ((clk*2)+16*bps)/(16*bps)-1;
 }
-#define SCBRR_VALUE(bps, clk) scbrr_calc(sh_sci, bps, clk)
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
 #elif defined(__H8300H__) || defined(__H8300S__)
 #define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
 #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
@@ -742,3 +746,7 @@
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
+
+#ifndef DL_VALUE
+#define DL_VALUE(bps, clk) 0
+#endif
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index e1678e6..7ae2727 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -2,5 +2,11 @@
 	bool "Enable Driver Model for SPI drivers"
 	depends on DM
 	help
-	  If you want to use driver model for SPI drivers, say Y.
-	  To use legacy SPI drivers, say N.
+	  Enable driver model for SPI. The SPI slave interface
+	  (spi_setup_slave(), spi_xfer(), etc.) is then implemented by
+	  the SPI uclass. Drivers provide methods to access the SPI
+	  buses that they control. The uclass interface is defined in
+	  include/spi.h. The existing spi_slave structure is attached
+	  as 'parent data' to every slave on each bus. Slaves
+	  typically use driver-private data instead of extending the
+	  spi_slave structure.
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 98ae3b8..a75fc46 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -340,6 +340,5 @@
 	.ofdata_to_platdata = cadence_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct cadence_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct cadence_spi_priv),
-	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 	.probe = cadence_spi_probe,
 };
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 700f616..2624844 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -421,6 +421,5 @@
 	.ofdata_to_platdata = dw_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct dw_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct dw_spi_priv),
-	.per_child_auto_alloc_size = sizeof(struct spi_slave),
 	.probe = dw_spi_probe,
 };
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index f078973..a46d8c1 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -425,6 +425,5 @@
 	.ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= exynos_spi_probe,
 };
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index fdff158..194e882 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
 #include <pci.h>
@@ -21,6 +22,7 @@
 struct ich_ctlr {
 	pci_dev_t dev;		/* PCI device number */
 	int ich_version;	/* Controller version, 7 or 9 */
+	bool use_sbase;		/* Use SBASE instead of RCB */
 	int ichspi_lock;
 	int locked;
 	uint8_t *opmenu;
@@ -145,7 +147,7 @@
 	 * ICH 7 SPI controller only supports array read command
 	 * and byte program command for SST flash
 	 */
-	if (ctlr.ich_version == 7) {
+	if (ctlr.ich_version == 7 || ctlr.use_sbase) {
 		ich->slave.op_mode_rx = SPI_OPM_RX_AS;
 		ich->slave.op_mode_tx = SPI_OPM_TX_BP;
 	}
@@ -175,13 +177,15 @@
 static int get_ich_version(uint16_t device_id)
 {
 	if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC ||
-	    device_id == PCI_DEVICE_ID_INTEL_ITC_LPC)
+	    device_id == PCI_DEVICE_ID_INTEL_ITC_LPC ||
+	    device_id == PCI_DEVICE_ID_INTEL_QRK_ILB)
 		return 7;
 
 	if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
 	     device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
 	    (device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
-	     device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX))
+	     device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
+	    device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
 		return 9;
 
 	return 0;
@@ -204,14 +208,14 @@
 	return speed == 1;
 }
 
-static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
+static int ich_find_spi_controller(struct ich_ctlr *ich)
 {
 	int last_bus = pci_last_busno();
 	int bus;
 
 	if (last_bus == -1) {
 		debug("No PCI busses?\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	for (bus = 0; bus <= last_bus; bus++) {
@@ -225,24 +229,33 @@
 		device_id = ids >> 16;
 
 		if (vendor_id == PCI_VENDOR_ID_INTEL) {
-			*devp = dev;
-			*ich_versionp = get_ich_version(device_id);
-			return 0;
+			ich->dev = dev;
+			ich->ich_version = get_ich_version(device_id);
+			if (device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
+				ich->use_sbase = true;
+			return ich->ich_version == 0 ? -ENODEV : 0;
 		}
 	}
 
 	debug("ICH SPI: No ICH found.\n");
-	return -1;
+	return -ENODEV;
 }
 
 static int ich_init_controller(struct ich_ctlr *ctlr)
 {
 	uint8_t *rcrb; /* Root Complex Register Block */
 	uint32_t rcba; /* Root Complex Base Address */
+	uint32_t sbase_addr;
+	uint8_t *sbase;
 
 	pci_read_config_dword(ctlr->dev, 0xf0, &rcba);
 	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
 	rcrb = (uint8_t *)(rcba & 0xffffc000);
+
+	/* SBASE is similar */
+	pci_read_config_dword(ctlr->dev, 0x54, &sbase_addr);
+	sbase = (uint8_t *)(sbase_addr & 0xfffffe00);
+
 	if (ctlr->ich_version == 7) {
 		struct ich7_spi_regs *ich7_spi;
 
@@ -262,7 +275,10 @@
 	} else if (ctlr->ich_version == 9) {
 		struct ich9_spi_regs *ich9_spi;
 
-		ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
+		if (ctlr->use_sbase)
+			ich9_spi = (struct ich9_spi_regs *)sbase;
+		else
+			ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
 		ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
 		ctlr->opmenu = ich9_spi->opmenu;
 		ctlr->menubytes = sizeof(ich9_spi->opmenu);
@@ -282,12 +298,13 @@
 		      ctlr->ich_version);
 		return -1;
 	}
-	debug("ICH SPI: Version %d detected\n", ctlr->ich_version);
 
 	/* Work out the maximum speed we can support */
 	ctlr->max_speed = 20000000;
 	if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev))
 		ctlr->max_speed = 33000000;
+	debug("ICH SPI: Version %d detected at %p, speed %ld\n",
+	      ctlr->ich_version, ctlr->base, ctlr->max_speed);
 
 	ich_set_bbar(ctlr, 0);
 
@@ -298,7 +315,7 @@
 {
 	uint8_t bios_cntl;
 
-	if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) {
+	if (ich_find_spi_controller(&ctlr)) {
 		printf("ICH SPI: Cannot find device\n");
 		return;
 	}
@@ -312,10 +329,20 @@
 	 * Disable the BIOS write protect so write commands are allowed.  On
 	 * v9, deassert SMM BIOS Write Protect Disable.
 	 */
-	pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
-	if (ctlr.ich_version == 9)
-		bios_cntl &= ~(1 << 5);
-	pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
+	if (ctlr.use_sbase) {
+		struct ich9_spi_regs *ich9_spi;
+
+		ich9_spi = (struct ich9_spi_regs *)ctlr.base;
+		bios_cntl = ich_readb(&ich9_spi->bcr);
+		bios_cntl &= ~(1 << 5);	/* clear Enable InSMM_STS (EISS) */
+		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
+		ich_writeb(bios_cntl, &ich9_spi->bcr);
+	} else {
+		pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
+		if (ctlr.ich_version == 9)
+			bios_cntl &= ~(1 << 5);
+		pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
+	}
 }
 
 int spi_claim_bus(struct spi_slave *slave)
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index d2e4b85..1419b23 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -37,18 +37,19 @@
 	uint8_t opmenu[8];		/* 0x98 */
 	uint32_t bbar;
 	uint8_t _reserved3[12];
-	uint32_t fdoc;
+	uint32_t fdoc;			/* 0xb0 */
 	uint32_t fdod;
 	uint8_t _reserved4[8];
-	uint32_t afc;
+	uint32_t afc;			/* 0xc0 */
 	uint32_t lvscc;
 	uint32_t uvscc;
 	uint8_t _reserved5[4];
-	uint32_t fpb;
+	uint32_t fpb;			/* 0xd0 */
 	uint8_t _reserved6[28];
-	uint32_t srdl;
+	uint32_t srdl;			/* 0xf0 */
 	uint32_t srdc;
-	uint32_t srd;
+	uint32_t scs;
+	uint32_t bcr;
 } __packed;
 
 enum {
diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c
index e717424..bad5660 100644
--- a/drivers/spi/sandbox_spi.c
+++ b/drivers/spi/sandbox_spi.c
@@ -160,6 +160,5 @@
 	.name	= "spi_sandbox",
 	.id	= UCLASS_SPI,
 	.of_match = sandbox_spi_ids,
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.ops	= &sandbox_spi_ops,
 };
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 5588036..6ae45f5 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -21,10 +21,10 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 struct soft_spi_platdata {
-	struct fdt_gpio_state cs;
-	struct fdt_gpio_state sclk;
-	struct fdt_gpio_state mosi;
-	struct fdt_gpio_state miso;
+	struct gpio_desc cs;
+	struct gpio_desc sclk;
+	struct gpio_desc mosi;
+	struct gpio_desc miso;
 	int spi_delay_us;
 };
 
@@ -35,9 +35,8 @@
 static int soft_spi_scl(struct udevice *dev, int bit)
 {
 	struct soft_spi_platdata *plat = dev->platdata;
-	struct soft_spi_priv *priv = dev_get_priv(dev);
 
-	gpio_set_value(plat->sclk.gpio, priv->mode & SPI_CPOL ? bit : !bit);
+	dm_gpio_set_value(&plat->sclk, bit);
 
 	return 0;
 }
@@ -46,7 +45,7 @@
 {
 	struct soft_spi_platdata *plat = dev->platdata;
 
-	gpio_set_value(plat->mosi.gpio, bit);
+	dm_gpio_set_value(&plat->mosi, bit);
 
 	return 0;
 }
@@ -54,11 +53,10 @@
 static int soft_spi_cs_activate(struct udevice *dev)
 {
 	struct soft_spi_platdata *plat = dev->platdata;
-	struct soft_spi_priv *priv = dev_get_priv(dev);
 
-	gpio_set_value(plat->cs.gpio, !(priv->mode & SPI_CS_HIGH));
-	gpio_set_value(plat->sclk.gpio, priv->mode & SPI_CPOL);
-	gpio_set_value(plat->cs.gpio, priv->mode & SPI_CS_HIGH);
+	dm_gpio_set_value(&plat->cs, 0);
+	dm_gpio_set_value(&plat->sclk, 0);
+	dm_gpio_set_value(&plat->cs, 1);
 
 	return 0;
 }
@@ -66,9 +64,8 @@
 static int soft_spi_cs_deactivate(struct udevice *dev)
 {
 	struct soft_spi_platdata *plat = dev->platdata;
-	struct soft_spi_priv *priv = dev_get_priv(dev);
 
-	gpio_set_value(plat->cs.gpio, !(priv->mode & SPI_CS_HIGH));
+	dm_gpio_set_value(&plat->cs, 0);
 
 	return 0;
 }
@@ -109,7 +106,6 @@
 	uchar		tmpdout = 0;
 	const u8	*txd = dout;
 	u8		*rxd = din;
-	int		cpol = priv->mode & SPI_CPOL;
 	int		cpha = priv->mode & SPI_CPHA;
 	unsigned int	j;
 
@@ -137,19 +133,19 @@
 		}
 
 		if (!cpha)
-			soft_spi_scl(dev, !cpol);
+			soft_spi_scl(dev, 0);
 		soft_spi_sda(dev, tmpdout & 0x80);
 		udelay(plat->spi_delay_us);
 		if (cpha)
-			soft_spi_scl(dev, !cpol);
+			soft_spi_scl(dev, 0);
 		else
-			soft_spi_scl(dev, cpol);
+			soft_spi_scl(dev, 1);
 		tmpdin	<<= 1;
-		tmpdin	|= gpio_get_value(plat->miso.gpio);
+		tmpdin	|= dm_gpio_get_value(&plat->miso);
 		tmpdout	<<= 1;
 		udelay(plat->spi_delay_us);
 		if (cpha)
-			soft_spi_scl(dev, cpol);
+			soft_spi_scl(dev, 1);
 	}
 	/*
 	 * If the number of bits isn't a multiple of 8, shift the last
@@ -183,14 +179,6 @@
 	return 0;
 }
 
-static int soft_spi_child_pre_probe(struct udevice *dev)
-{
-	struct spi_slave *slave = dev_get_parentdata(dev);
-
-	slave->dev = dev;
-	return spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
-}
-
 static const struct dm_spi_ops soft_spi_ops = {
 	.claim_bus	= soft_spi_claim_bus,
 	.release_bus	= soft_spi_release_bus,
@@ -205,11 +193,6 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev->of_offset;
 
-	if (fdtdec_decode_gpio(blob, node, "cs-gpio", &plat->cs) ||
-	    fdtdec_decode_gpio(blob, node, "sclk-gpio", &plat->sclk) ||
-	    fdtdec_decode_gpio(blob, node, "mosi-gpio", &plat->mosi) ||
-	    fdtdec_decode_gpio(blob, node, "miso-gpio", &plat->miso))
-		return -EINVAL;
 	plat->spi_delay_us = fdtdec_get_int(blob, node, "spi-delay-us", 0);
 
 	return 0;
@@ -219,16 +202,19 @@
 {
 	struct spi_slave *slave = dev_get_parentdata(dev);
 	struct soft_spi_platdata *plat = dev->platdata;
+	int cs_flags, clk_flags;
 
-	gpio_request(plat->cs.gpio, "soft_spi_cs");
-	gpio_request(plat->sclk.gpio, "soft_spi_sclk");
-	gpio_request(plat->mosi.gpio, "soft_spi_mosi");
-	gpio_request(plat->miso.gpio, "soft_spi_miso");
-
-	gpio_direction_output(plat->sclk.gpio, slave->mode & SPI_CPOL);
-	gpio_direction_output(plat->mosi.gpio, 1);
-	gpio_direction_input(plat->miso.gpio);
-	gpio_direction_output(plat->cs.gpio, !(slave->mode & SPI_CS_HIGH));
+	cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW;
+	clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0;
+	if (gpio_request_by_name(dev, "cs-gpio", 0, &plat->cs,
+				 GPIOD_IS_OUT | cs_flags) ||
+	    gpio_request_by_name(dev, "sclk-gpio", 0, &plat->sclk,
+				 GPIOD_IS_OUT | clk_flags) ||
+	    gpio_request_by_name(dev, "mosi-gpio", 0, &plat->mosi,
+				 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE) ||
+	    gpio_request_by_name(dev, "miso-gpio", 0, &plat->miso,
+				 GPIOD_IS_IN))
+		return -EINVAL;
 
 	return 0;
 }
@@ -246,7 +232,5 @@
 	.ofdata_to_platdata = soft_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct soft_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct soft_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= soft_spi_probe,
-	.child_pre_probe	= soft_spi_child_pre_probe,
 };
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 7a57bce..63a6217 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -98,21 +98,51 @@
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
-int spi_post_probe(struct udevice *dev)
+int spi_child_post_bind(struct udevice *dev)
 {
-	struct dm_spi_bus *spi = dev->uclass_priv;
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
-	spi->max_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+	if (dev->of_offset == -1)
+		return 0;
+
+	return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+}
+
+int spi_post_probe(struct udevice *bus)
+{
+	struct dm_spi_bus *spi = bus->uclass_priv;
+
+	spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
 				     "spi-max-frequency", 0);
 
 	return 0;
 }
 
+int spi_child_pre_probe(struct udevice *dev)
+{
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+	struct spi_slave *slave = dev_get_parentdata(dev);
+
+	/*
+	 * This is needed because we pass struct spi_slave around the place
+	 * instead slave->dev (a struct udevice). So we have to have some
+	 * way to access the slave udevice given struct spi_slave. Once we
+	 * change the SPI API to use udevice instead of spi_slave, we can
+	 * drop this.
+	 */
+	slave->dev = dev;
+
+	slave->max_hz = plat->max_hz;
+	slave->mode = plat->mode;
+
+	return 0;
+}
+
 int spi_chip_select(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
-	return slave ? slave->cs : -ENOENT;
+	return plat ? plat->cs : -ENOENT;
 }
 
 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
@@ -121,17 +151,11 @@
 
 	for (device_find_first_child(bus, &dev); dev;
 	     device_find_next_child(&dev)) {
-		struct spi_slave store;
-		struct spi_slave *slave = dev_get_parentdata(dev);
+		struct dm_spi_slave_platdata *plat;
 
-		if (!slave)  {
-			slave = &store;
-			spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					       slave);
-		}
-		debug("%s: slave=%p, cs=%d\n", __func__, slave,
-		      slave ? slave->cs : -1);
-		if (slave && slave->cs == cs) {
+		plat = dev_get_parent_platdata(dev);
+		debug("%s: plat=%p, cs=%d\n", __func__, plat, plat->cs);
+		if (plat->cs == cs) {
 			*devp = dev;
 			return 0;
 		}
@@ -215,7 +239,6 @@
 		       struct udevice **busp, struct spi_slave **devp)
 {
 	struct udevice *bus, *dev;
-	struct spi_slave *slave;
 	bool created = false;
 	int ret;
 
@@ -232,11 +255,17 @@
 	 * SPI flash chip - we will bind to the correct driver.
 	 */
 	if (ret == -ENODEV && drv_name) {
+		struct dm_spi_slave_platdata *plat;
+
 		debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
 		      __func__, dev_name, busnum, cs, drv_name);
 		ret = device_bind_driver(bus, drv_name, dev_name, &dev);
 		if (ret)
 			return ret;
+		plat = dev_get_parent_platdata(dev);
+		plat->cs = cs;
+		plat->max_hz = speed;
+		plat->mode = mode;
 		created = true;
 	} else if (ret) {
 		printf("Invalid chip select %d:%d (err=%d)\n", busnum, cs,
@@ -245,23 +274,13 @@
 	}
 
 	if (!device_active(dev)) {
-		slave = (struct spi_slave *)calloc(1,
-						   sizeof(struct spi_slave));
-		if (!slave) {
-			ret = -ENOMEM;
-			goto err;
-		}
+		struct spi_slave *slave;
 
-		ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					     slave);
+		ret = device_probe(dev);
 		if (ret)
 			goto err;
-		slave->cs = cs;
+		slave = dev_get_parentdata(dev);
 		slave->dev = dev;
-		ret = device_probe_child(dev, slave);
-		free(slave);
-		if (ret)
-			goto err;
 	}
 
 	ret = spi_set_speed_mode(bus, speed, mode);
@@ -275,6 +294,8 @@
 	return 0;
 
 err:
+	debug("%s: Error path, credted=%d, device '%s'\n", __func__,
+	      created, dev->name);
 	if (created) {
 		device_remove(dev);
 		device_unbind(dev);
@@ -321,13 +342,13 @@
 	slave->dev = NULL;
 }
 
-int spi_ofdata_to_platdata(const void *blob, int node,
-			   struct spi_slave *spi)
+int spi_slave_ofdata_to_platdata(const void *blob, int node,
+				 struct dm_spi_slave_platdata *plat)
 {
 	int mode = 0;
 
-	spi->cs = fdtdec_get_int(blob, node, "reg", -1);
-	spi->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
+	plat->cs = fdtdec_get_int(blob, node, "reg", -1);
+	plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
 	if (fdtdec_get_bool(blob, node, "spi-cpol"))
 		mode |= SPI_CPOL;
 	if (fdtdec_get_bool(blob, node, "spi-cpha"))
@@ -336,7 +357,7 @@
 		mode |= SPI_CS_HIGH;
 	if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
 		mode |= SPI_PREAMBLE;
-	spi->mode = mode;
+	plat->mode = mode;
 
 	return 0;
 }
@@ -344,9 +365,15 @@
 UCLASS_DRIVER(spi) = {
 	.id		= UCLASS_SPI,
 	.name		= "spi",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.post_bind	= spi_post_bind,
 	.post_probe	= spi_post_probe,
+	.child_pre_probe = spi_child_pre_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
+	.per_child_auto_alloc_size = sizeof(struct spi_slave),
+	.per_child_platdata_auto_alloc_size =
+			sizeof(struct dm_spi_slave_platdata),
+	.child_post_bind = spi_child_post_bind,
 };
 
 UCLASS_DRIVER(spi_generic) = {
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index 2d97625..53ff9ea 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -407,6 +407,5 @@
 	.ofdata_to_platdata = tegra114_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra114_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra114_spi_probe,
 };
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index 7d0d0f3..78c74cd 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -348,6 +348,5 @@
 	.ofdata_to_platdata = tegra20_sflash_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra20_sflash_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra20_sflash_probe,
 };
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 213fa5f..597d6ad 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -361,6 +361,5 @@
 	.ofdata_to_platdata = tegra30_spi_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
 	.priv_auto_alloc_size = sizeof(struct tegra30_spi_priv),
-	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
 	.probe	= tegra30_spi_probe,
 };
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
new file mode 100644
index 0000000..3c6b36d
--- /dev/null
+++ b/drivers/thermal/Kconfig
@@ -0,0 +1,7 @@
+config DM_THERMAL
+	bool "Driver support for thermal devices"
+	help
+	  Enable support for temporary-sensing devices. Some SoCs have on-chip
+	  temperature sensors to permit warnings, speed throttling or even
+	  automatic power-off when the temperature gets too high or low. Other
+	  devices may be discrete but connected on a suitable bus.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c11b551..66d6e9a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
 obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
 obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
 
 # designware
 obj-$(CONFIG_USB_DWC2) += dwc2.o
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 6fdbf57..f3c077d 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -31,7 +31,7 @@
 struct exynos_ehci {
 	struct exynos_usb_phy *usb;
 	struct ehci_hccr *hcd;
-	struct fdt_gpio_state vbus_gpio;
+	struct gpio_desc vbus_gpio;
 };
 
 static struct exynos_ehci exynos;
@@ -61,7 +61,8 @@
 	exynos->hcd = (struct ehci_hccr *)addr;
 
 	/* Vbus gpio */
-	fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio);
+	gpio_request_by_name_nodev(blob, node, "samsung,vbus-gpio", 0,
+				   &exynos->vbus_gpio, GPIOD_IS_OUT);
 
 	depth = 0;
 	node = fdtdec_next_compatible_subnode(blob, node,
@@ -236,9 +237,8 @@
 
 #ifdef CONFIG_OF_CONTROL
 	/* setup the Vbus gpio here */
-	if (fdt_gpio_isvalid(&ctx->vbus_gpio) &&
-	    !fdtdec_setup_gpio(&ctx->vbus_gpio))
-		gpio_direction_output(ctx->vbus_gpio.gpio, 1);
+	if (dm_gpio_is_valid(&ctx->vbus_gpio))
+		dm_gpio_set_value(&ctx->vbus_gpio, 1);
 #endif
 
 	setup_usb_phy(ctx->usb);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 991b199..b9eabc5 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -34,57 +34,6 @@
 	{0, 0}
 };
 #else
-static pci_dev_t ehci_find_class(int index)
-{
-	int bus;
-	int devnum;
-	pci_dev_t bdf;
-	uint32_t class;
-
-	for (bus = 0; bus <= pci_last_busno(); bus++) {
-		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) {
-			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
-					      PCI_CLASS_REVISION, &class);
-			if (class >> 16 == 0xffff)
-				continue;
-
-			for (bdf = PCI_BDF(bus, devnum, 0);
-					bdf <= PCI_BDF(bus, devnum,
-						PCI_MAX_PCI_FUNCTIONS - 1);
-					bdf += PCI_BDF(0, 0, 1)) {
-				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
-						      &class);
-				class >>= 8;
-				/*
-				 * Here be dragons! In case we have multiple
-				 * PCI EHCI controllers, this function will
-				 * be called multiple times as well. This
-				 * function will scan the PCI busses, always
-				 * starting from bus 0, device 0, function 0,
-				 * until it finds an USB controller. The USB
-				 * stack gives us an 'index' of a controller
-				 * that is currently being registered, which
-				 * is a number, starting from 0 and growing
-				 * in ascending order as controllers are added.
-				 * To avoid probing the same controller in tne
-				 * subsequent runs of this function, we will
-				 * skip 'index - 1' detected controllers and
-				 * report the index'th controller.
-				 */
-				if (class != PCI_CLASS_SERIAL_USB_EHCI)
-					continue;
-				if (index) {
-					index--;
-					continue;
-				}
-				/* Return index'th controller. */
-				return bdf;
-			}
-		}
-	}
-
-	return -ENODEV;
-}
 #endif
 
 /*
@@ -102,7 +51,7 @@
 #ifdef CONFIG_PCI_EHCI_DEVICE
 	pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE);
 #else
-	pdev = ehci_find_class(index);
+	pdev = pci_find_class(PCI_CLASS_SERIAL_USB_EHCI, index);
 #endif
 	if (pdev < 0) {
 		printf("EHCI host controller not found\n");
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 5f0a98e..b5ad1e3 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -72,8 +72,8 @@
 	enum usb_init_type init_type;
 	enum dr_mode dr_mode;	/* dual role mode */
 	enum periph_id periph_id;/* peripheral id */
-	struct fdt_gpio_state vbus_gpio;	/* GPIO for vbus enable */
-	struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */
+	struct gpio_desc vbus_gpio;	/* GPIO for vbus enable */
+	struct gpio_desc phy_reset_gpio; /* GPIO to reset ULPI phy */
 };
 
 static struct fdt_usb port[USB_PORTS_MAX];	/* List of valid USB ports */
@@ -252,17 +252,14 @@
 		return;
 	}
 
-	if (fdt_gpio_isvalid(&config->vbus_gpio)) {
+	if (dm_gpio_is_valid(&config->vbus_gpio)) {
 		int vbus_value;
 
-		fdtdec_setup_gpio(&config->vbus_gpio);
+		vbus_value = (init == USB_INIT_HOST);
+		dm_gpio_set_value(&config->vbus_gpio, vbus_value);
 
-		vbus_value = (init == USB_INIT_HOST) ^
-			     !!(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW);
-		gpio_direction_output(config->vbus_gpio.gpio, vbus_value);
-
-		debug("set_up_vbus: GPIO %d %d\n", config->vbus_gpio.gpio,
-		      vbus_value);
+		debug("set_up_vbus: GPIO %d %d\n",
+		      gpio_get_number(&config->vbus_gpio), vbus_value);
 	}
 }
 
@@ -360,7 +357,7 @@
 	 * mux must be switched to actually use a_sess_vld threshold.
 	 */
 	if (config->dr_mode == DR_MODE_OTG &&
-	    fdt_gpio_isvalid(&config->vbus_gpio))
+	    dm_gpio_is_valid(&config->vbus_gpio))
 		clrsetbits_le32(&usbctlr->usb1_legacy_ctrl,
 			VBUS_SENSE_CTL_MASK,
 			VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT);
@@ -569,11 +566,10 @@
 	clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK);
 
 	/* reset ULPI phy */
-	if (fdt_gpio_isvalid(&config->phy_reset_gpio)) {
-		fdtdec_setup_gpio(&config->phy_reset_gpio);
-		gpio_direction_output(config->phy_reset_gpio.gpio, 0);
+	if (dm_gpio_is_valid(&config->phy_reset_gpio)) {
+		dm_gpio_set_value(&config->phy_reset_gpio, 0);
 		mdelay(5);
-		gpio_set_value(config->phy_reset_gpio.gpio, 1);
+		dm_gpio_set_value(&config->phy_reset_gpio, 1);
 	}
 
 	/* Reset the usb controller */
@@ -685,14 +681,16 @@
 		debug("%s: Missing/invalid peripheral ID\n", __func__);
 		return -FDT_ERR_NOTFOUND;
 	}
-	fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio);
-	fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio",
-			&config->phy_reset_gpio);
+	gpio_request_by_name_nodev(blob, node, "nvidia,vbus-gpio", 0,
+				   &config->vbus_gpio, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(blob, node, "nvidia,phy-reset-gpio", 0,
+				   &config->phy_reset_gpio, GPIOD_IS_OUT);
 	debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, "
 		"vbus=%d, phy_reset=%d, dr_mode=%d\n",
 		config->enabled, config->has_legacy_mode, config->utmi,
-		config->ulpi, config->periph_id, config->vbus_gpio.gpio,
-		config->phy_reset_gpio.gpio, config->dr_mode);
+		config->ulpi, config->periph_id,
+		gpio_get_number(&config->vbus_gpio),
+		gpio_get_number(&config->phy_reset_gpio), config->dr_mode);
 
 	return 0;
 }
diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c
index b4946a3..a77c8bc 100644
--- a/drivers/usb/host/xhci-exynos5.c
+++ b/drivers/usb/host/xhci-exynos5.c
@@ -40,7 +40,7 @@
 	struct exynos_usb3_phy *usb3_phy;
 	struct xhci_hccr *hcd;
 	struct dwc3 *dwc3_reg;
-	struct fdt_gpio_state vbus_gpio;
+	struct gpio_desc vbus_gpio;
 };
 
 static struct exynos_xhci exynos;
@@ -69,7 +69,8 @@
 	exynos->hcd = (struct xhci_hccr *)addr;
 
 	/* Vbus gpio */
-	fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio);
+	gpio_request_by_name_nodev(blob, node, "samsung,vbus-gpio", 0,
+				   &exynos->vbus_gpio, GPIOD_IS_OUT);
 
 	depth = 0;
 	node = fdtdec_next_compatible_subnode(blob, node,
@@ -298,9 +299,8 @@
 
 #ifdef CONFIG_OF_CONTROL
 	/* setup the Vbus gpio here */
-	if (fdt_gpio_isvalid(&ctx->vbus_gpio) &&
-	    !fdtdec_setup_gpio(&ctx->vbus_gpio))
-		gpio_direction_output(ctx->vbus_gpio.gpio, 1);
+	if (dm_gpio_is_valid(&ctx->vbus_gpio))
+		dm_gpio_set_value(&ctx->vbus_gpio, 1);
 #endif
 
 	ret = exynos_xhci_core_init(ctx);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
new file mode 100644
index 0000000..361fcce
--- /dev/null
+++ b/drivers/usb/host/xhci-pci.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <pci.h>
+#include <usb.h>
+
+#include "xhci.h"
+
+/*
+ * Create the appropriate control structures to manage a new XHCI host
+ * controller.
+ */
+int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
+		  struct xhci_hcor **ret_hcor)
+{
+	struct xhci_hccr *hccr;
+	struct xhci_hcor *hcor;
+	pci_dev_t pdev;
+	uint32_t cmd;
+	int len;
+
+	pdev = pci_find_class(PCI_CLASS_SERIAL_USB_XHCI, index);
+	if (pdev < 0) {
+		printf("XHCI host controller not found\n");
+		return -1;
+	}
+
+	hccr = (struct xhci_hccr *)pci_map_bar(pdev,
+			PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	len = HC_LENGTH(xhci_readl(&hccr->cr_capbase));
+	hcor = (struct xhci_hcor *)((uint32_t)hccr + len);
+
+	debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
+	      (uint32_t)hccr, (uint32_t)hcor, len);
+
+	*ret_hccr = hccr;
+	*ret_hcor = hcor;
+
+	/* enable busmaster */
+	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_MASTER;
+	pci_write_config_dword(pdev, PCI_COMMAND, cmd);
+
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding * to the XHCI host
+ * controller
+ */
+void xhci_hcd_stop(int index)
+{
+}
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 778916d..fe45db1 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -22,7 +22,9 @@
  */
 #include <common.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
 #include <asm/arch/usbc.h>
+#include <asm-generic/gpio.h>
 #include "linux-compat.h"
 #include "musb_core.h"
 
@@ -145,16 +147,6 @@
 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
 }
 
-static void USBC_ForceVbusValidDisable(__iomem void *base)
-{
-	u32 reg_val;
-
-	reg_val = musb_readl(base, USBC_REG_o_ISCR);
-	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
-	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
-	musb_writel(base, USBC_REG_o_ISCR, reg_val);
-}
-
 static void USBC_ForceVbusValidToHigh(__iomem void *base)
 {
 	u32 reg_val;
@@ -234,6 +226,33 @@
 
 	pr_debug("%s():\n", __func__);
 
+	if (is_host_enabled(musb)) {
+		int vbus_det = sunxi_name_to_gpio(CONFIG_USB0_VBUS_DET);
+		if (vbus_det == -1) {
+			eprintf("Error invalid Vusb-det pin\n");
+			return -EINVAL;
+		}
+
+		err = gpio_request(vbus_det, "vbus0_det");
+		if (err)
+			return err;
+
+		err = gpio_direction_input(vbus_det);
+		if (err) {
+			gpio_free(vbus_det);
+			return err;
+		}
+
+		err = gpio_get_value(vbus_det);
+		if (err) {
+			eprintf("Error: A charger is plugged into the OTG\n");
+			gpio_free(vbus_det);
+			return -EIO;
+		}
+
+		gpio_free(vbus_det);
+	}
+
 	err = sunxi_usbc_request_resources(0);
 	if (err)
 		return err;
@@ -248,12 +267,11 @@
 	if (is_host_enabled(musb)) {
 		/* Host mode */
 		USBC_ForceIdToLow(musb->mregs);
-		USBC_ForceVbusValidToHigh(musb->mregs);
 	} else {
 		/* Peripheral mode */
 		USBC_ForceIdToHigh(musb->mregs);
-		USBC_ForceVbusValidDisable(musb->mregs);
 	}
+	USBC_ForceVbusValidToHigh(musb->mregs);
 
 	return 0;
 }
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index 935ae42..0ce2370 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -13,6 +13,10 @@
 #include <lcd.h>
 #include <atmel_hlcdc.h>
 
+#if defined(CONFIG_LCD_LOGO)
+#include <bmp_logo.h>
+#endif
+
 /* configurable parameters */
 #define ATMEL_LCDC_CVAL_DEFAULT		0xc8
 #define ATMEL_LCDC_DMA_BURST_LEN	8
@@ -37,6 +41,15 @@
 		panel_info.mmio + ATMEL_LCDC_LUT(regno));
 }
 
+ushort *configuration_get_cmap(void)
+{
+#if defined(CONFIG_LCD_LOGO)
+	return bmp_logo_palette;
+#else
+	return NULL;
+#endif
+}
+
 void lcd_ctrl_init(void *lcdbase)
 {
 	unsigned long value;
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 3cf008c..4ed3a49 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -11,6 +11,7 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
 #include <lcd.h>
+#include <bmp_layout.h>
 #include <atmel_lcdc.h>
 
 /* configurable parameters */
@@ -20,7 +21,7 @@
 #define ATMEL_LCDC_GUARD_TIME		1
 #endif
 
-#if defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91CAP9)
+#if defined(CONFIG_AT91SAM9263)
 #define ATMEL_LCDC_FIFO_SIZE		2048
 #else
 #define ATMEL_LCDC_FIFO_SIZE		512
@@ -29,6 +30,46 @@
 #define lcdc_readl(mmio, reg)		__raw_readl((mmio)+(reg))
 #define lcdc_writel(mmio, reg, val)	__raw_writel((val), (mmio)+(reg))
 
+ushort *configuration_get_cmap(void)
+{
+	return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));
+}
+
+#if defined(CONFIG_BMP_16BPP) && defined(CONFIG_ATMEL_LCD_BGR555)
+void fb_put_word(uchar **fb, uchar **from)
+{
+	*(*fb)++ = (((*from)[0] & 0x1f) << 2) | ((*from)[1] & 0x03);
+	*(*fb)++ = ((*from)[0] & 0xe0) | (((*from)[1] & 0x7c) >> 2);
+	*from += 2;
+}
+#endif
+
+#ifdef CONFIG_LCD_LOGO
+#include <bmp_logo.h>
+void lcd_logo_set_cmap(void)
+{
+	int i;
+	uint lut_entry;
+	ushort colreg;
+	uint *cmap = (uint *)configuration_get_cmap();
+
+	for (i = 0; i < BMP_LOGO_COLORS; ++i) {
+		colreg = bmp_logo_palette[i];
+#ifdef CONFIG_ATMEL_LCD_BGR555
+		lut_entry = ((colreg & 0x000F) << 11) |
+				((colreg & 0x00F0) <<  2) |
+				((colreg & 0x0F00) >>  7);
+#else
+		lut_entry = ((colreg & 0x000F) << 1) |
+				((colreg & 0x00F0) << 3) |
+				((colreg & 0x0F00) << 4);
+#endif
+		*(cmap + BMP_LOGO_OFFSET) = lut_entry;
+		cmap++;
+	}
+}
+#endif
+
 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
 {
 #if defined(CONFIG_ATMEL_LCD_BGR555)
@@ -40,6 +81,16 @@
 #endif
 }
 
+void lcd_set_cmap(bmp_image_t *bmp, unsigned colors)
+{
+	int i;
+
+	for (i = 0; i < colors; ++i) {
+		bmp_color_table_entry_t cte = bmp->color_table[i];
+		lcd_setcolreg(i, cte.red, cte.green, cte.blue);
+	}
+}
+
 void lcd_ctrl_init(void *lcdbase)
 {
 	unsigned long value;
diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c
index be35b98..c5d7330 100644
--- a/drivers/video/exynos_fb.c
+++ b/drivers/video/exynos_fb.c
@@ -37,6 +37,15 @@
 };
 #endif
 
+ushort *configuration_get_cmap(void)
+{
+#if defined(CONFIG_LCD_LOGO)
+	return bmp_logo_palette;
+#else
+	return NULL;
+#endif
+}
+
 static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
 {
 	unsigned long palette_size;
diff --git a/drivers/video/mpc8xx_lcd.c b/drivers/video/mpc8xx_lcd.c
index add7215..faa58c0 100644
--- a/drivers/video/mpc8xx_lcd.c
+++ b/drivers/video/mpc8xx_lcd.c
@@ -357,6 +357,35 @@
 
 /*----------------------------------------------------------------------*/
 
+ushort *configuration_get_cmap(void)
+{
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	cpm8xx_t *cp = &(immr->im_cpm);
+	return (ushort *)&(cp->lcd_cmap[255 * sizeof(ushort)]);
+}
+
+#if defined(CONFIG_MPC823)
+void fb_put_byte(uchar **fb, uchar **from)
+{
+	*(*fb)++ = (255 - *(*from)++);
+}
+#endif
+
+#ifdef CONFIG_LCD_LOGO
+#include <bmp_logo.h>
+void lcd_logo_set_cmap(void)
+{
+	int i;
+	ushort *cmap;
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	cpm8xx_t *cp = &(immr->im_cpm);
+	cmap = (ushort *)&(cp->lcd_cmap[BMP_LOGO_OFFSET * sizeof(ushort)]);
+
+	for (i = 0; i < BMP_LOGO_COLORS; ++i)
+		*cmap++ = bmp_logo_palette[i];
+}
+#endif
+
 void lcd_enable (void)
 {
 	volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
diff --git a/drivers/video/pxa_lcd.c b/drivers/video/pxa_lcd.c
index f66f615..04105d4 100644
--- a/drivers/video/pxa_lcd.c
+++ b/drivers/video/pxa_lcd.c
@@ -342,6 +342,12 @@
 /* ---------------  PXA chipset specific functions  ------------------- */
 /************************************************************************/
 
+ushort *configuration_get_cmap(void)
+{
+	struct pxafb_info *fbi = &panel_info.pxa;
+	return (ushort *)fbi->palette;
+}
+
 void lcd_ctrl_init (void *lcdbase)
 {
 	pxafb_init_mem(lcdbase, &panel_info);
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
index af728b5..4e12150 100644
--- a/drivers/video/sunxi_display.c
+++ b/drivers/video/sunxi_display.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
+#include <i2c.h>
 #include <video_fb.h>
 #include "videomodes.h"
 #include "hitachi_tx18d42vm_lcd.h"
@@ -46,6 +47,7 @@
 	GraphicDevice graphic_device;
 	enum sunxi_monitor monitor;
 	unsigned int depth;
+	unsigned int fb_size;
 } sunxi_display;
 
 #ifdef CONFIG_VIDEO_HDMI
@@ -591,7 +593,7 @@
 
 static void sunxi_lcdc_panel_enable(void)
 {
-	int pin;
+	int pin, reset_pin;
 
 	/*
 	 * Start with backlight disabled to avoid the screen flashing to
@@ -609,6 +611,12 @@
 		gpio_direction_output(pin, PWM_OFF);
 	}
 
+	reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
+	if (reset_pin != -1) {
+		gpio_request(reset_pin, "lcd_reset");
+		gpio_direction_output(reset_pin, 0); /* Assert reset */
+	}
+
 	/* Give the backlight some time to turn off and power up the panel. */
 	mdelay(40);
 	pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
@@ -616,6 +624,9 @@
 		gpio_request(pin, "lcd_power");
 		gpio_direction_output(pin, 1);
 	}
+
+	if (reset_pin != -1)
+		gpio_direction_output(reset_pin, 1); /* De-assert reset */
 }
 
 static void sunxi_lcdc_backlight_enable(void)
@@ -645,7 +656,8 @@
 	return (delay > 30) ? 30 : delay;
 }
 
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
+static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
+				      bool for_ext_vga_dac)
 {
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
@@ -719,6 +731,11 @@
 		val |= SUNXI_LCDC_TCON_HSYNC_MASK;
 	if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
 		val |= SUNXI_LCDC_TCON_VSYNC_MASK;
+
+#ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
+	if (for_ext_vga_dac)
+		val = 0;
+#endif
 	writel(val, &lcdc->tcon0_io_polarity);
 
 	writel(0, &lcdc->tcon0_io_tristate);
@@ -1014,8 +1031,14 @@
 			mdelay(50); /* Wait for lcd controller power on */
 			hitachi_tx18d42vm_init();
 		}
+		if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
+			unsigned int orig_i2c_bus = i2c_get_bus_num();
+			i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
+			i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
+			i2c_set_bus_num(orig_i2c_bus);
+		}
 		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon0_mode_set(mode);
+		sunxi_lcdc_tcon0_mode_set(mode, false);
 		sunxi_composer_enable();
 		sunxi_lcdc_enable();
 #ifdef CONFIG_VIDEO_LCD_SSD2828
@@ -1033,7 +1056,7 @@
 		sunxi_vga_enable();
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
 		sunxi_composer_mode_set(mode, address);
-		sunxi_lcdc_tcon0_mode_set(mode);
+		sunxi_lcdc_tcon0_mode_set(mode, true);
 		sunxi_composer_enable();
 		sunxi_lcdc_enable();
 		sunxi_vga_external_dac_enable();
@@ -1054,6 +1077,11 @@
 	return NULL; /* never reached */
 }
 
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
+}
+
 void *video_hw_init(void)
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@@ -1069,10 +1097,6 @@
 
 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
-	printf("Reserved %dkB of RAM for Framebuffer.\n",
-	       CONFIG_SUNXI_FB_SIZE >> 10);
-	gd->fb_base = gd->ram_top;
-
 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
 				 &sunxi_display.depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
@@ -1163,6 +1187,17 @@
 		       mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
 	}
 
+	sunxi_display.fb_size =
+		(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+	if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
+		printf("Error need %dkB for fb, but only %dkB is reserved\n",
+		       sunxi_display.fb_size >> 10,
+		       CONFIG_SUNXI_MAX_FB_SIZE >> 10);
+		return NULL;
+	}
+
+	gd->fb_base = gd->bd->bi_dram[0].start +
+		      gd->bd->bi_dram[0].size - sunxi_display.fb_size;
 	sunxi_engines_init();
 	sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
 
@@ -1188,6 +1223,7 @@
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
 	int offset, ret;
+	u64 start, size;
 	const char *pipeline = NULL;
 
 #ifdef CONFIG_MACH_SUN4I
@@ -1231,6 +1267,20 @@
 		return 0; /* Keep older kernels working */
 	}
 
+	/*
+	 * Do not report the framebuffer as free RAM to the OS, note we cannot
+	 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
+	 * and e.g. Linux refuses to iomap RAM on ARM, see:
+	 * linux/arch/arm/mm/ioremap.c around line 301.
+	 */
+	start = gd->bd->bi_dram[0].start;
+	size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+	ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
+	if (ret) {
+		eprintf("Cannot setup simplefb: Error reserving memory\n");
+		return ret;
+	}
+
 	ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
 			graphic_device->winSizeX, graphic_device->winSizeY,
 			graphic_device->winSizeX * graphic_device->gdfBytesPP,
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 57cb007..b8f3431 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -149,14 +149,18 @@
 					    FDT_LCD_CACHE_WRITE_BACK_FLUSH);
 
 	/* These GPIOs are all optional */
-	fdtdec_decode_gpio(blob, display_node, "nvidia,backlight-enable-gpios",
-			    &config->backlight_en);
-	fdtdec_decode_gpio(blob, display_node, "nvidia,lvds-shutdown-gpios",
-			   &config->lvds_shutdown);
-	fdtdec_decode_gpio(blob, display_node, "nvidia,backlight-vdd-gpios",
-			   &config->backlight_vdd);
-	fdtdec_decode_gpio(blob, display_node, "nvidia,panel-vdd-gpios",
-			   &config->panel_vdd);
+	gpio_request_by_name_nodev(blob, display_node,
+				   "nvidia,backlight-enable-gpios", 0,
+				   &config->backlight_en, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(blob, display_node,
+				   "nvidia,lvds-shutdown-gpios", 0,
+				   &config->lvds_shutdown, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(blob, display_node,
+				   "nvidia,backlight-vdd-gpios", 0,
+				   &config->backlight_vdd, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(blob, display_node,
+				   "nvidia,panel-vdd-gpios", 0,
+				   &config->panel_vdd, GPIOD_IS_OUT);
 
 	return fdtdec_get_int_array(blob, display_node, "nvidia,panel-timings",
 			config->panel_timings, FDT_LCD_TIMINGS);
@@ -196,36 +200,18 @@
 		 */
 
 		funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);
-
-		fdtdec_setup_gpio(&config.panel_vdd);
-		fdtdec_setup_gpio(&config.lvds_shutdown);
-		fdtdec_setup_gpio(&config.backlight_vdd);
-		fdtdec_setup_gpio(&config.backlight_en);
-
-		/*
-		 * TODO: If fdt includes output flag we can omit this code
-		 * since fdtdec_setup_gpio will do it for us.
-		 */
-		if (fdt_gpio_isvalid(&config.panel_vdd))
-			gpio_direction_output(config.panel_vdd.gpio, 0);
-		if (fdt_gpio_isvalid(&config.lvds_shutdown))
-			gpio_direction_output(config.lvds_shutdown.gpio, 0);
-		if (fdt_gpio_isvalid(&config.backlight_vdd))
-			gpio_direction_output(config.backlight_vdd.gpio, 0);
-		if (fdt_gpio_isvalid(&config.backlight_en))
-			gpio_direction_output(config.backlight_en.gpio, 0);
 		break;
 	case STAGE_PANEL_VDD:
-		if (fdt_gpio_isvalid(&config.panel_vdd))
-			gpio_direction_output(config.panel_vdd.gpio, 1);
+		if (dm_gpio_is_valid(&config.panel_vdd))
+			dm_gpio_set_value(&config.panel_vdd, 1);
 		break;
 	case STAGE_LVDS:
-		if (fdt_gpio_isvalid(&config.lvds_shutdown))
-			gpio_set_value(config.lvds_shutdown.gpio, 1);
+		if (dm_gpio_is_valid(&config.lvds_shutdown))
+			dm_gpio_set_value(&config.lvds_shutdown, 1);
 		break;
 	case STAGE_BACKLIGHT_VDD:
-		if (fdt_gpio_isvalid(&config.backlight_vdd))
-			gpio_set_value(config.backlight_vdd.gpio, 1);
+		if (dm_gpio_is_valid(&config.backlight_vdd))
+			dm_gpio_set_value(&config.backlight_vdd, 1);
 		break;
 	case STAGE_PWM:
 		/* Enable PWM at 15/16 high, 32768 Hz with divider 1 */
@@ -235,8 +221,8 @@
 		pwm_enable(config.pwm_channel, 32768, 0xdf, 1);
 		break;
 	case STAGE_BACKLIGHT_EN:
-		if (fdt_gpio_isvalid(&config.backlight_en))
-			gpio_set_value(config.backlight_en.gpio, 1);
+		if (dm_gpio_is_valid(&config.backlight_en))
+			dm_gpio_set_value(&config.backlight_en, 1);
 		break;
 	case STAGE_DONE:
 		break;
diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c
index 3dacafd..47f824a 100644
--- a/drivers/video/vesa_fb.c
+++ b/drivers/video/vesa_fb.c
@@ -23,6 +23,7 @@
 	{ .vendor = 0x1002, .device = 0x5159 },
 	{ .vendor = 0x1002, .device = 0x4752 },
 	{ .vendor = 0x1002, .device = 0x5452 },
+	{ .vendor = 0x8086, .device = 0x0f31 },
 	{},
 };
 
@@ -41,8 +42,10 @@
 			printf("no card detected\n");
 			return NULL;
 		}
-		printf("bdf %x\n", dev);
-		ret = pci_run_vga_bios(dev, NULL, true);
+		bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
+		ret = pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE |
+				       PCI_ROM_ALLOW_FALLBACK);
+		bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
 		if (ret) {
 			printf("failed to run video BIOS: %d\n", ret);
 			return NULL;
@@ -58,7 +61,7 @@
 	sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
 		bits_per_pixel);
 	printf("%s\n", gdev->modeIdent);
-	debug("Framex buffer at %x\n", gdev->pciBase);
+	debug("Frame buffer at %x\n", gdev->pciBase);
 
 	return (void *)gdev;
 }
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index ffd49a2..03c786c 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -30,7 +30,11 @@
 #define ticks_to_ms(t)	(((t + 1) * 1000) >> 8)
 
 /* Hardware timeout in seconds */
+#if !defined(CONFIG_AT91_HW_WDT_TIMEOUT)
 #define WDT_HW_TIMEOUT 2
+#else
+#define WDT_HW_TIMEOUT CONFIG_AT91_HW_WDT_TIMEOUT
+#endif
 
 /*
  * Set the watchdog time interval in 1/256Hz (write-once)
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c
index 0bf690e..920a0a9 100644
--- a/examples/standalone/stubs.c
+++ b/examples/standalone/stubs.c
@@ -2,6 +2,8 @@
 #include <exports.h>
 #include <linux/compiler.h>
 
+#define FO(x) offsetof(struct jt_funcs, x)
+
 #if defined(CONFIG_X86)
 /*
  * x86 does not have a dedicated register to store the pointer to
@@ -10,23 +12,23 @@
  * from flash memory. The global_data address is passed as argv[-1]
  * to the application program.
  */
-static void **jt;
+static struct jt_funcs *jt;
 gd_t *global_data;
 
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
 "	movl	%0, %%eax\n"		\
 "	movl	jt, %%ecx\n"		\
 "	jmp	*(%%ecx, %%eax)\n"	\
-	: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
+	: : "i"(FO(x)) : "eax", "ecx");
 #elif defined(CONFIG_PPC)
 /*
  * r2 holds the pointer to the global_data, r11 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
@@ -34,33 +36,33 @@
 "	lwz	%%r11, %1(%%r11)\n"	\
 "	mtctr	%%r11\n"		\
 "	bctr\n"				\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r11");
 #elif defined(CONFIG_ARM)
 #ifdef CONFIG_ARM64
 /*
  * x18 holds the pointer to the global_data, x9 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
 "	ldr	x9, [x18, %0]\n"		\
 "	ldr	x9, [x9, %1]\n"		\
 "	br	x9\n"		\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "x9");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "x9");
 #else
 /*
  * r9 holds the pointer to the global_data, ip is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
 "	ldr	ip, [r9, %0]\n"		\
 "	ldr	pc, [ip, %1]\n"		\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "ip");
 #endif
 #elif defined(CONFIG_MIPS)
 /*
@@ -70,19 +72,19 @@
  * it; however, GCC/mips generates an additional `nop' after each asm
  * statement
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
 "	lw	$25, %0($26)\n"		\
 "	lw	$25, %1($25)\n"		\
 "	jr	$25\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9");
 #elif defined(CONFIG_NIOS2)
 /*
  * gp holds the pointer to the global_data, r8 is call-clobbered
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
@@ -92,13 +94,13 @@
 "	ldw	r8, 0(r8)\n"		\
 "	ldw	r8, %1(r8)\n"		\
 "	jmp	r8\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "gp");
 #elif defined(CONFIG_M68K)
 /*
  * d7 holds the pointer to the global_data, a0 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
@@ -108,50 +110,50 @@
 "	adda.l	%1, %%a0\n"		\
 "	move.l	(%%a0), %%a0\n"		\
 "	jmp	(%%a0)\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "a0");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "a0");
 #elif defined(CONFIG_MICROBLAZE)
 /*
  * r31 holds the pointer to the global_data. r5 is a call-clobbered.
  */
-#define EXPORT_FUNC(x)				\
+#define EXPORT_FUNC(f, a, x, ...)				\
 	asm volatile (				\
 "	.globl " #x "\n"			\
 #x ":\n"					\
 "	lwi	r5, r31, %0\n"			\
 "	lwi	r5, r5, %1\n"			\
 "	bra	r5\n"				\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r5");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r5");
 #elif defined(CONFIG_BLACKFIN)
 /*
  * P3 holds the pointer to the global_data, P0 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x)			\
+#define EXPORT_FUNC(f, a, x, ...)			\
 	asm volatile (			\
 "	.globl _" #x "\n_"		\
 #x ":\n"				\
 "	P0 = [P3 + %0]\n"		\
 "	P0 = [P0 + %1]\n"		\
 "	JUMP (P0)\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "P0");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "P0");
 #elif defined(CONFIG_AVR32)
 /*
  * r6 holds the pointer to the global_data. r8 is call clobbered.
  */
-#define EXPORT_FUNC(x)					\
+#define EXPORT_FUNC(f, a, x, ...)					\
 	asm volatile(					\
 		"	.globl\t" #x "\n"		\
 		#x ":\n"				\
 		"	ld.w	r8, r6[%0]\n"		\
 		"	ld.w	pc, r8[%1]\n"		\
 		:					\
-		: "i"(offsetof(gd_t, jt)), "i"(XF_ ##x)	\
+		: "i"(offsetof(gd_t, jt)), "i"(FO(x))	\
 		: "r8");
 #elif defined(CONFIG_SH)
 /*
  * r13 holds the pointer to the global_data. r1 is a call clobbered.
  */
-#define EXPORT_FUNC(x)					\
+#define EXPORT_FUNC(f, a, x, ...)					\
 	asm volatile (					\
 		"	.align	2\n"			\
 		"	.globl " #x "\n"		\
@@ -164,12 +166,12 @@
 		"	jmp	@r1\n"			\
 		"	nop\n"				\
 		"	nop\n"				\
-		: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r1", "r2");
+		: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r1", "r2");
 #elif defined(CONFIG_SPARC)
 /*
  * g7 holds the pointer to the global_data. g1 is call clobbered.
  */
-#define EXPORT_FUNC(x)					\
+#define EXPORT_FUNC(f, a, x, ...)					\
 	asm volatile(					\
 "	.globl\t" #x "\n"				\
 #x ":\n"						\
@@ -179,26 +181,26 @@
 "	ld [%%g1 + %1], %%g1\n"				\
 "	jmp %%g1\n"					\
 "	nop\n"						\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "g1" );
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "g1");
 #elif defined(CONFIG_NDS32)
 /*
  * r16 holds the pointer to the global_data. gp is call clobbered.
  * not support reduced register (16 GPR).
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
 "	lwi	$r16, [$gp + (%0)]\n"	\
 "	lwi	$r16, [$r16 + (%1)]\n"	\
 "	jr	$r16\n"			\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "$r16");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "$r16");
 #elif defined(CONFIG_OPENRISC)
 /*
  * r10 holds the pointer to the global_data, r13 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile (			\
 "	.globl " #x "\n"		\
 #x ":\n"				\
@@ -206,12 +208,12 @@
 "	l.lwz	r13, %1(r13)\n"	\
 "	l.jr	r13\n"		\
 "	l.nop\n"				\
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r13");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r13");
 #elif defined(CONFIG_ARC)
 /*
  * r25 holds the pointer to the global_data. r10 is call clobbered.
   */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
 	asm volatile( \
 "	.align 4\n" \
 "	.globl " #x "\n" \
@@ -219,7 +221,7 @@
 "	ld	r10, [r25, %0]\n" \
 "	ld	r10, [r10, %1]\n" \
 "	j	[r10]\n" \
-	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r10");
+	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
 #else
 /*"	addi	$sp, $sp, -24\n"	\
 "	br	$r16\n"			\*/
diff --git a/fs/fs.c b/fs/fs.c
index ddd751c..483273f 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -79,6 +79,7 @@
 
 struct fstype_info {
 	int fstype;
+	char *name;
 	/*
 	 * Is it legal to pass NULL as .probe()'s  fs_dev_desc parameter? This
 	 * should be false in most cases. For "virtual" filesystems which
@@ -105,6 +106,7 @@
 #ifdef CONFIG_FS_FAT
 	{
 		.fstype = FS_TYPE_FAT,
+		.name = "fat",
 		.null_dev_desc_ok = false,
 		.probe = fat_set_blk_dev,
 		.close = fat_close,
@@ -123,6 +125,7 @@
 #ifdef CONFIG_FS_EXT4
 	{
 		.fstype = FS_TYPE_EXT,
+		.name = "ext4",
 		.null_dev_desc_ok = false,
 		.probe = ext4fs_probe,
 		.close = ext4fs_close,
@@ -141,6 +144,7 @@
 #ifdef CONFIG_SANDBOX
 	{
 		.fstype = FS_TYPE_SANDBOX,
+		.name = "sandbox",
 		.null_dev_desc_ok = true,
 		.probe = sandbox_fs_set_blk_dev,
 		.close = sandbox_fs_close,
@@ -154,6 +158,7 @@
 #endif
 	{
 		.fstype = FS_TYPE_ANY,
+		.name = "unsupported",
 		.null_dev_desc_ok = true,
 		.probe = fs_probe_unsupported,
 		.close = fs_close_unsupported,
@@ -190,6 +195,7 @@
 	if (!relocated) {
 		for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes);
 				i++, info++) {
+			info->name += gd->reloc_off;
 			info->probe += gd->reloc_off;
 			info->close += gd->reloc_off;
 			info->ls += gd->reloc_off;
@@ -503,3 +509,24 @@
 
 	return CMD_RET_SUCCESS;
 }
+
+int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct fstype_info *info;
+
+	if (argc < 3 || argc > 4)
+		return CMD_RET_USAGE;
+
+	if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_ANY))
+		return 1;
+
+	info = fs_get_info(fs_type);
+
+	if (argc == 4)
+		setenv(argv[3], info->name);
+	else
+		printf("%s\n", info->name);
+
+	return CMD_RET_SUCCESS;
+}
+
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 8c8c6ac..5efb349 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -12,4 +12,4 @@
 obj-y := ubifs.o io.o super.o sb.o master.o lpt.o
 obj-y += lpt_commit.o scan.o lprops.o
 obj-y += tnc.o tnc_misc.o debug.o crc16.o budget.o
-obj-y += log.o orphan.o recovery.o replay.o
+obj-y += log.o orphan.o recovery.o replay.o gc.o
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
new file mode 100644
index 0000000..c6657a2
--- /dev/null
+++ b/fs/ubifs/gc.c
@@ -0,0 +1,976 @@
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * Authors: Adrian Hunter
+ *          Artem Bityutskiy (Битюцкий Артём)
+ */
+
+/*
+ * This file implements garbage collection. The procedure for garbage collection
+ * is different depending on whether a LEB as an index LEB (contains index
+ * nodes) or not. For non-index LEBs, garbage collection finds a LEB which
+ * contains a lot of dirty space (obsolete nodes), and copies the non-obsolete
+ * nodes to the journal, at which point the garbage-collected LEB is free to be
+ * reused. For index LEBs, garbage collection marks the non-obsolete index nodes
+ * dirty in the TNC, and after the next commit, the garbage-collected LEB is
+ * to be reused. Garbage collection will cause the number of dirty index nodes
+ * to grow, however sufficient space is reserved for the index to ensure the
+ * commit will never run out of space.
+ *
+ * Notes about dead watermark. At current UBIFS implementation we assume that
+ * LEBs which have less than @c->dead_wm bytes of free + dirty space are full
+ * and not worth garbage-collecting. The dead watermark is one min. I/O unit
+ * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS
+ * Garbage Collector has to synchronize the GC head's write buffer before
+ * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can
+ * actually reclaim even very small pieces of dirty space by garbage collecting
+ * enough dirty LEBs, but we do not bother doing this at this implementation.
+ *
+ * Notes about dark watermark. The results of GC work depends on how big are
+ * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed,
+ * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would
+ * have to waste large pieces of free space at the end of LEB B, because nodes
+ * from LEB A would not fit. And the worst situation is when all nodes are of
+ * maximum size. So dark watermark is the amount of free + dirty space in LEB
+ * which are guaranteed to be reclaimable. If LEB has less space, the GC might
+ * be unable to reclaim it. So, LEBs with free + dirty greater than dark
+ * watermark are "good" LEBs from GC's point of few. The other LEBs are not so
+ * good, and GC takes extra care when moving them.
+ */
+#ifndef __UBOOT__
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/list_sort.h>
+#endif
+#include "ubifs.h"
+
+#ifndef __UBOOT__
+/*
+ * GC may need to move more than one LEB to make progress. The below constants
+ * define "soft" and "hard" limits on the number of LEBs the garbage collector
+ * may move.
+ */
+#define SOFT_LEBS_LIMIT 4
+#define HARD_LEBS_LIMIT 32
+
+/**
+ * switch_gc_head - switch the garbage collection journal head.
+ * @c: UBIFS file-system description object
+ * @buf: buffer to write
+ * @len: length of the buffer to write
+ * @lnum: LEB number written is returned here
+ * @offs: offset written is returned here
+ *
+ * This function switch the GC head to the next LEB which is reserved in
+ * @c->gc_lnum. Returns %0 in case of success, %-EAGAIN if commit is required,
+ * and other negative error code in case of failures.
+ */
+static int switch_gc_head(struct ubifs_info *c)
+{
+	int err, gc_lnum = c->gc_lnum;
+	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
+
+	ubifs_assert(gc_lnum != -1);
+	dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)",
+	       wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum,
+	       c->leb_size - wbuf->offs - wbuf->used);
+
+	err = ubifs_wbuf_sync_nolock(wbuf);
+	if (err)
+		return err;
+
+	/*
+	 * The GC write-buffer was synchronized, we may safely unmap
+	 * 'c->gc_lnum'.
+	 */
+	err = ubifs_leb_unmap(c, gc_lnum);
+	if (err)
+		return err;
+
+	err = ubifs_wbuf_sync_nolock(wbuf);
+	if (err)
+		return err;
+
+	err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
+	if (err)
+		return err;
+
+	c->gc_lnum = -1;
+	err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0);
+	return err;
+}
+
+/**
+ * data_nodes_cmp - compare 2 data nodes.
+ * @priv: UBIFS file-system description object
+ * @a: first data node
+ * @a: second data node
+ *
+ * This function compares data nodes @a and @b. Returns %1 if @a has greater
+ * inode or block number, and %-1 otherwise.
+ */
+static int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	ino_t inuma, inumb;
+	struct ubifs_info *c = priv;
+	struct ubifs_scan_node *sa, *sb;
+
+	cond_resched();
+	if (a == b)
+		return 0;
+
+	sa = list_entry(a, struct ubifs_scan_node, list);
+	sb = list_entry(b, struct ubifs_scan_node, list);
+
+	ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY);
+	ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY);
+	ubifs_assert(sa->type == UBIFS_DATA_NODE);
+	ubifs_assert(sb->type == UBIFS_DATA_NODE);
+
+	inuma = key_inum(c, &sa->key);
+	inumb = key_inum(c, &sb->key);
+
+	if (inuma == inumb) {
+		unsigned int blka = key_block(c, &sa->key);
+		unsigned int blkb = key_block(c, &sb->key);
+
+		if (blka <= blkb)
+			return -1;
+	} else if (inuma <= inumb)
+		return -1;
+
+	return 1;
+}
+
+/*
+ * nondata_nodes_cmp - compare 2 non-data nodes.
+ * @priv: UBIFS file-system description object
+ * @a: first node
+ * @a: second node
+ *
+ * This function compares nodes @a and @b. It makes sure that inode nodes go
+ * first and sorted by length in descending order. Directory entry nodes go
+ * after inode nodes and are sorted in ascending hash valuer order.
+ */
+static int nondata_nodes_cmp(void *priv, struct list_head *a,
+			     struct list_head *b)
+{
+	ino_t inuma, inumb;
+	struct ubifs_info *c = priv;
+	struct ubifs_scan_node *sa, *sb;
+
+	cond_resched();
+	if (a == b)
+		return 0;
+
+	sa = list_entry(a, struct ubifs_scan_node, list);
+	sb = list_entry(b, struct ubifs_scan_node, list);
+
+	ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY &&
+		     key_type(c, &sb->key) != UBIFS_DATA_KEY);
+	ubifs_assert(sa->type != UBIFS_DATA_NODE &&
+		     sb->type != UBIFS_DATA_NODE);
+
+	/* Inodes go before directory entries */
+	if (sa->type == UBIFS_INO_NODE) {
+		if (sb->type == UBIFS_INO_NODE)
+			return sb->len - sa->len;
+		return -1;
+	}
+	if (sb->type == UBIFS_INO_NODE)
+		return 1;
+
+	ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sa->key) == UBIFS_XENT_KEY);
+	ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sb->key) == UBIFS_XENT_KEY);
+	ubifs_assert(sa->type == UBIFS_DENT_NODE ||
+		     sa->type == UBIFS_XENT_NODE);
+	ubifs_assert(sb->type == UBIFS_DENT_NODE ||
+		     sb->type == UBIFS_XENT_NODE);
+
+	inuma = key_inum(c, &sa->key);
+	inumb = key_inum(c, &sb->key);
+
+	if (inuma == inumb) {
+		uint32_t hasha = key_hash(c, &sa->key);
+		uint32_t hashb = key_hash(c, &sb->key);
+
+		if (hasha <= hashb)
+			return -1;
+	} else if (inuma <= inumb)
+		return -1;
+
+	return 1;
+}
+
+/**
+ * sort_nodes - sort nodes for GC.
+ * @c: UBIFS file-system description object
+ * @sleb: describes nodes to sort and contains the result on exit
+ * @nondata: contains non-data nodes on exit
+ * @min: minimum node size is returned here
+ *
+ * This function sorts the list of inodes to garbage collect. First of all, it
+ * kills obsolete nodes and separates data and non-data nodes to the
+ * @sleb->nodes and @nondata lists correspondingly.
+ *
+ * Data nodes are then sorted in block number order - this is important for
+ * bulk-read; data nodes with lower inode number go before data nodes with
+ * higher inode number, and data nodes with lower block number go before data
+ * nodes with higher block number;
+ *
+ * Non-data nodes are sorted as follows.
+ *   o First go inode nodes - they are sorted in descending length order.
+ *   o Then go directory entry nodes - they are sorted in hash order, which
+ *     should supposedly optimize 'readdir()'. Direntry nodes with lower parent
+ *     inode number go before direntry nodes with higher parent inode number,
+ *     and direntry nodes with lower name hash values go before direntry nodes
+ *     with higher name hash values.
+ *
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
+		      struct list_head *nondata, int *min)
+{
+	int err;
+	struct ubifs_scan_node *snod, *tmp;
+
+	*min = INT_MAX;
+
+	/* Separate data nodes and non-data nodes */
+	list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
+		ubifs_assert(snod->type == UBIFS_INO_NODE  ||
+			     snod->type == UBIFS_DATA_NODE ||
+			     snod->type == UBIFS_DENT_NODE ||
+			     snod->type == UBIFS_XENT_NODE ||
+			     snod->type == UBIFS_TRUN_NODE);
+
+		if (snod->type != UBIFS_INO_NODE  &&
+		    snod->type != UBIFS_DATA_NODE &&
+		    snod->type != UBIFS_DENT_NODE &&
+		    snod->type != UBIFS_XENT_NODE) {
+			/* Probably truncation node, zap it */
+			list_del(&snod->list);
+			kfree(snod);
+			continue;
+		}
+
+		ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY ||
+			     key_type(c, &snod->key) == UBIFS_INO_KEY  ||
+			     key_type(c, &snod->key) == UBIFS_DENT_KEY ||
+			     key_type(c, &snod->key) == UBIFS_XENT_KEY);
+
+		err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
+					 snod->offs, 0);
+		if (err < 0)
+			return err;
+
+		if (!err) {
+			/* The node is obsolete, remove it from the list */
+			list_del(&snod->list);
+			kfree(snod);
+			continue;
+		}
+
+		if (snod->len < *min)
+			*min = snod->len;
+
+		if (key_type(c, &snod->key) != UBIFS_DATA_KEY)
+			list_move_tail(&snod->list, nondata);
+	}
+
+	/* Sort data and non-data nodes */
+	list_sort(c, &sleb->nodes, &data_nodes_cmp);
+	list_sort(c, nondata, &nondata_nodes_cmp);
+
+	err = dbg_check_data_nodes_order(c, &sleb->nodes);
+	if (err)
+		return err;
+	err = dbg_check_nondata_nodes_order(c, nondata);
+	if (err)
+		return err;
+	return 0;
+}
+
+/**
+ * move_node - move a node.
+ * @c: UBIFS file-system description object
+ * @sleb: describes the LEB to move nodes from
+ * @snod: the mode to move
+ * @wbuf: write-buffer to move node to
+ *
+ * This function moves node @snod to @wbuf, changes TNC correspondingly, and
+ * destroys @snod. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int move_node(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
+		     struct ubifs_scan_node *snod, struct ubifs_wbuf *wbuf)
+{
+	int err, new_lnum = wbuf->lnum, new_offs = wbuf->offs + wbuf->used;
+
+	cond_resched();
+	err = ubifs_wbuf_write_nolock(wbuf, snod->node, snod->len);
+	if (err)
+		return err;
+
+	err = ubifs_tnc_replace(c, &snod->key, sleb->lnum,
+				snod->offs, new_lnum, new_offs,
+				snod->len);
+	list_del(&snod->list);
+	kfree(snod);
+	return err;
+}
+
+/**
+ * move_nodes - move nodes.
+ * @c: UBIFS file-system description object
+ * @sleb: describes the LEB to move nodes from
+ *
+ * This function moves valid nodes from data LEB described by @sleb to the GC
+ * journal head. This function returns zero in case of success, %-EAGAIN if
+ * commit is required, and other negative error codes in case of other
+ * failures.
+ */
+static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
+{
+	int err, min;
+	LIST_HEAD(nondata);
+	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
+
+	if (wbuf->lnum == -1) {
+		/*
+		 * The GC journal head is not set, because it is the first GC
+		 * invocation since mount.
+		 */
+		err = switch_gc_head(c);
+		if (err)
+			return err;
+	}
+
+	err = sort_nodes(c, sleb, &nondata, &min);
+	if (err)
+		goto out;
+
+	/* Write nodes to their new location. Use the first-fit strategy */
+	while (1) {
+		int avail;
+		struct ubifs_scan_node *snod, *tmp;
+
+		/* Move data nodes */
+		list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
+			avail = c->leb_size - wbuf->offs - wbuf->used;
+			if  (snod->len > avail)
+				/*
+				 * Do not skip data nodes in order to optimize
+				 * bulk-read.
+				 */
+				break;
+
+			err = move_node(c, sleb, snod, wbuf);
+			if (err)
+				goto out;
+		}
+
+		/* Move non-data nodes */
+		list_for_each_entry_safe(snod, tmp, &nondata, list) {
+			avail = c->leb_size - wbuf->offs - wbuf->used;
+			if (avail < min)
+				break;
+
+			if  (snod->len > avail) {
+				/*
+				 * Keep going only if this is an inode with
+				 * some data. Otherwise stop and switch the GC
+				 * head. IOW, we assume that data-less inode
+				 * nodes and direntry nodes are roughly of the
+				 * same size.
+				 */
+				if (key_type(c, &snod->key) == UBIFS_DENT_KEY ||
+				    snod->len == UBIFS_INO_NODE_SZ)
+					break;
+				continue;
+			}
+
+			err = move_node(c, sleb, snod, wbuf);
+			if (err)
+				goto out;
+		}
+
+		if (list_empty(&sleb->nodes) && list_empty(&nondata))
+			break;
+
+		/*
+		 * Waste the rest of the space in the LEB and switch to the
+		 * next LEB.
+		 */
+		err = switch_gc_head(c);
+		if (err)
+			goto out;
+	}
+
+	return 0;
+
+out:
+	list_splice_tail(&nondata, &sleb->nodes);
+	return err;
+}
+
+/**
+ * gc_sync_wbufs - sync write-buffers for GC.
+ * @c: UBIFS file-system description object
+ *
+ * We must guarantee that obsoleting nodes are on flash. Unfortunately they may
+ * be in a write-buffer instead. That is, a node could be written to a
+ * write-buffer, obsoleting another node in a LEB that is GC'd. If that LEB is
+ * erased before the write-buffer is sync'd and then there is an unclean
+ * unmount, then an existing node is lost. To avoid this, we sync all
+ * write-buffers.
+ *
+ * This function returns %0 on success or a negative error code on failure.
+ */
+static int gc_sync_wbufs(struct ubifs_info *c)
+{
+	int err, i;
+
+	for (i = 0; i < c->jhead_cnt; i++) {
+		if (i == GCHD)
+			continue;
+		err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/**
+ * ubifs_garbage_collect_leb - garbage-collect a logical eraseblock.
+ * @c: UBIFS file-system description object
+ * @lp: describes the LEB to garbage collect
+ *
+ * This function garbage-collects an LEB and returns one of the @LEB_FREED,
+ * @LEB_RETAINED, etc positive codes in case of success, %-EAGAIN if commit is
+ * required, and other negative error codes in case of failures.
+ */
+int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
+{
+	struct ubifs_scan_leb *sleb;
+	struct ubifs_scan_node *snod;
+	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
+	int err = 0, lnum = lp->lnum;
+
+	ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 ||
+		     c->need_recovery);
+	ubifs_assert(c->gc_lnum != lnum);
+	ubifs_assert(wbuf->lnum != lnum);
+
+	if (lp->free + lp->dirty == c->leb_size) {
+		/* Special case - a free LEB  */
+		dbg_gc("LEB %d is free, return it", lp->lnum);
+		ubifs_assert(!(lp->flags & LPROPS_INDEX));
+
+		if (lp->free != c->leb_size) {
+			/*
+			 * Write buffers must be sync'd before unmapping
+			 * freeable LEBs, because one of them may contain data
+			 * which obsoletes something in 'lp->pnum'.
+			 */
+			err = gc_sync_wbufs(c);
+			if (err)
+				return err;
+			err = ubifs_change_one_lp(c, lp->lnum, c->leb_size,
+						  0, 0, 0, 0);
+			if (err)
+				return err;
+		}
+		err = ubifs_leb_unmap(c, lp->lnum);
+		if (err)
+			return err;
+
+		if (c->gc_lnum == -1) {
+			c->gc_lnum = lnum;
+			return LEB_RETAINED;
+		}
+
+		return LEB_FREED;
+	}
+
+	/*
+	 * We scan the entire LEB even though we only really need to scan up to
+	 * (c->leb_size - lp->free).
+	 */
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0);
+	if (IS_ERR(sleb))
+		return PTR_ERR(sleb);
+
+	ubifs_assert(!list_empty(&sleb->nodes));
+	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
+
+	if (snod->type == UBIFS_IDX_NODE) {
+		struct ubifs_gced_idx_leb *idx_gc;
+
+		dbg_gc("indexing LEB %d (free %d, dirty %d)",
+		       lnum, lp->free, lp->dirty);
+		list_for_each_entry(snod, &sleb->nodes, list) {
+			struct ubifs_idx_node *idx = snod->node;
+			int level = le16_to_cpu(idx->level);
+
+			ubifs_assert(snod->type == UBIFS_IDX_NODE);
+			key_read(c, ubifs_idx_key(c, idx), &snod->key);
+			err = ubifs_dirty_idx_node(c, &snod->key, level, lnum,
+						   snod->offs);
+			if (err)
+				goto out;
+		}
+
+		idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
+		if (!idx_gc) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		idx_gc->lnum = lnum;
+		idx_gc->unmap = 0;
+		list_add(&idx_gc->list, &c->idx_gc);
+
+		/*
+		 * Don't release the LEB until after the next commit, because
+		 * it may contain data which is needed for recovery. So
+		 * although we freed this LEB, it will become usable only after
+		 * the commit.
+		 */
+		err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0,
+					  LPROPS_INDEX, 1);
+		if (err)
+			goto out;
+		err = LEB_FREED_IDX;
+	} else {
+		dbg_gc("data LEB %d (free %d, dirty %d)",
+		       lnum, lp->free, lp->dirty);
+
+		err = move_nodes(c, sleb);
+		if (err)
+			goto out_inc_seq;
+
+		err = gc_sync_wbufs(c);
+		if (err)
+			goto out_inc_seq;
+
+		err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0);
+		if (err)
+			goto out_inc_seq;
+
+		/* Allow for races with TNC */
+		c->gced_lnum = lnum;
+		smp_wmb();
+		c->gc_seq += 1;
+		smp_wmb();
+
+		if (c->gc_lnum == -1) {
+			c->gc_lnum = lnum;
+			err = LEB_RETAINED;
+		} else {
+			err = ubifs_wbuf_sync_nolock(wbuf);
+			if (err)
+				goto out;
+
+			err = ubifs_leb_unmap(c, lnum);
+			if (err)
+				goto out;
+
+			err = LEB_FREED;
+		}
+	}
+
+out:
+	ubifs_scan_destroy(sleb);
+	return err;
+
+out_inc_seq:
+	/* We may have moved at least some nodes so allow for races with TNC */
+	c->gced_lnum = lnum;
+	smp_wmb();
+	c->gc_seq += 1;
+	smp_wmb();
+	goto out;
+}
+
+/**
+ * ubifs_garbage_collect - UBIFS garbage collector.
+ * @c: UBIFS file-system description object
+ * @anyway: do GC even if there are free LEBs
+ *
+ * This function does out-of-place garbage collection. The return codes are:
+ *   o positive LEB number if the LEB has been freed and may be used;
+ *   o %-EAGAIN if the caller has to run commit;
+ *   o %-ENOSPC if GC failed to make any progress;
+ *   o other negative error codes in case of other errors.
+ *
+ * Garbage collector writes data to the journal when GC'ing data LEBs, and just
+ * marking indexing nodes dirty when GC'ing indexing LEBs. Thus, at some point
+ * commit may be required. But commit cannot be run from inside GC, because the
+ * caller might be holding the commit lock, so %-EAGAIN is returned instead;
+ * And this error code means that the caller has to run commit, and re-run GC
+ * if there is still no free space.
+ *
+ * There are many reasons why this function may return %-EAGAIN:
+ * o the log is full and there is no space to write an LEB reference for
+ *   @c->gc_lnum;
+ * o the journal is too large and exceeds size limitations;
+ * o GC moved indexing LEBs, but they can be used only after the commit;
+ * o the shrinker fails to find clean znodes to free and requests the commit;
+ * o etc.
+ *
+ * Note, if the file-system is close to be full, this function may return
+ * %-EAGAIN infinitely, so the caller has to limit amount of re-invocations of
+ * the function. E.g., this happens if the limits on the journal size are too
+ * tough and GC writes too much to the journal before an LEB is freed. This
+ * might also mean that the journal is too large, and the TNC becomes to big,
+ * so that the shrinker is constantly called, finds not clean znodes to free,
+ * and requests commit. Well, this may also happen if the journal is all right,
+ * but another kernel process consumes too much memory. Anyway, infinite
+ * %-EAGAIN may happen, but in some extreme/misconfiguration cases.
+ */
+int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
+{
+	int i, err, ret, min_space = c->dead_wm;
+	struct ubifs_lprops lp;
+	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
+
+	ubifs_assert_cmt_locked(c);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+
+	if (ubifs_gc_should_commit(c))
+		return -EAGAIN;
+
+	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
+
+	if (c->ro_error) {
+		ret = -EROFS;
+		goto out_unlock;
+	}
+
+	/* We expect the write-buffer to be empty on entry */
+	ubifs_assert(!wbuf->used);
+
+	for (i = 0; ; i++) {
+		int space_before, space_after;
+
+		cond_resched();
+
+		/* Give the commit an opportunity to run */
+		if (ubifs_gc_should_commit(c)) {
+			ret = -EAGAIN;
+			break;
+		}
+
+		if (i > SOFT_LEBS_LIMIT && !list_empty(&c->idx_gc)) {
+			/*
+			 * We've done enough iterations. Indexing LEBs were
+			 * moved and will be available after the commit.
+			 */
+			dbg_gc("soft limit, some index LEBs GC'ed, -EAGAIN");
+			ubifs_commit_required(c);
+			ret = -EAGAIN;
+			break;
+		}
+
+		if (i > HARD_LEBS_LIMIT) {
+			/*
+			 * We've moved too many LEBs and have not made
+			 * progress, give up.
+			 */
+			dbg_gc("hard limit, -ENOSPC");
+			ret = -ENOSPC;
+			break;
+		}
+
+		/*
+		 * Empty and freeable LEBs can turn up while we waited for
+		 * the wbuf lock, or while we have been running GC. In that
+		 * case, we should just return one of those instead of
+		 * continuing to GC dirty LEBs. Hence we request
+		 * 'ubifs_find_dirty_leb()' to return an empty LEB if it can.
+		 */
+		ret = ubifs_find_dirty_leb(c, &lp, min_space, anyway ? 0 : 1);
+		if (ret) {
+			if (ret == -ENOSPC)
+				dbg_gc("no more dirty LEBs");
+			break;
+		}
+
+		dbg_gc("found LEB %d: free %d, dirty %d, sum %d (min. space %d)",
+		       lp.lnum, lp.free, lp.dirty, lp.free + lp.dirty,
+		       min_space);
+
+		space_before = c->leb_size - wbuf->offs - wbuf->used;
+		if (wbuf->lnum == -1)
+			space_before = 0;
+
+		ret = ubifs_garbage_collect_leb(c, &lp);
+		if (ret < 0) {
+			if (ret == -EAGAIN) {
+				/*
+				 * This is not error, so we have to return the
+				 * LEB to lprops. But if 'ubifs_return_leb()'
+				 * fails, its failure code is propagated to the
+				 * caller instead of the original '-EAGAIN'.
+				 */
+				err = ubifs_return_leb(c, lp.lnum);
+				if (err)
+					ret = err;
+				break;
+			}
+			goto out;
+		}
+
+		if (ret == LEB_FREED) {
+			/* An LEB has been freed and is ready for use */
+			dbg_gc("LEB %d freed, return", lp.lnum);
+			ret = lp.lnum;
+			break;
+		}
+
+		if (ret == LEB_FREED_IDX) {
+			/*
+			 * This was an indexing LEB and it cannot be
+			 * immediately used. And instead of requesting the
+			 * commit straight away, we try to garbage collect some
+			 * more.
+			 */
+			dbg_gc("indexing LEB %d freed, continue", lp.lnum);
+			continue;
+		}
+
+		ubifs_assert(ret == LEB_RETAINED);
+		space_after = c->leb_size - wbuf->offs - wbuf->used;
+		dbg_gc("LEB %d retained, freed %d bytes", lp.lnum,
+		       space_after - space_before);
+
+		if (space_after > space_before) {
+			/* GC makes progress, keep working */
+			min_space >>= 1;
+			if (min_space < c->dead_wm)
+				min_space = c->dead_wm;
+			continue;
+		}
+
+		dbg_gc("did not make progress");
+
+		/*
+		 * GC moved an LEB bud have not done any progress. This means
+		 * that the previous GC head LEB contained too few free space
+		 * and the LEB which was GC'ed contained only large nodes which
+		 * did not fit that space.
+		 *
+		 * We can do 2 things:
+		 * 1. pick another LEB in a hope it'll contain a small node
+		 *    which will fit the space we have at the end of current GC
+		 *    head LEB, but there is no guarantee, so we try this out
+		 *    unless we have already been working for too long;
+		 * 2. request an LEB with more dirty space, which will force
+		 *    'ubifs_find_dirty_leb()' to start scanning the lprops
+		 *    table, instead of just picking one from the heap
+		 *    (previously it already picked the dirtiest LEB).
+		 */
+		if (i < SOFT_LEBS_LIMIT) {
+			dbg_gc("try again");
+			continue;
+		}
+
+		min_space <<= 1;
+		if (min_space > c->dark_wm)
+			min_space = c->dark_wm;
+		dbg_gc("set min. space to %d", min_space);
+	}
+
+	if (ret == -ENOSPC && !list_empty(&c->idx_gc)) {
+		dbg_gc("no space, some index LEBs GC'ed, -EAGAIN");
+		ubifs_commit_required(c);
+		ret = -EAGAIN;
+	}
+
+	err = ubifs_wbuf_sync_nolock(wbuf);
+	if (!err)
+		err = ubifs_leb_unmap(c, c->gc_lnum);
+	if (err) {
+		ret = err;
+		goto out;
+	}
+out_unlock:
+	mutex_unlock(&wbuf->io_mutex);
+	return ret;
+
+out:
+	ubifs_assert(ret < 0);
+	ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
+	ubifs_wbuf_sync_nolock(wbuf);
+	ubifs_ro_mode(c, ret);
+	mutex_unlock(&wbuf->io_mutex);
+	ubifs_return_leb(c, lp.lnum);
+	return ret;
+}
+
+/**
+ * ubifs_gc_start_commit - garbage collection at start of commit.
+ * @c: UBIFS file-system description object
+ *
+ * If a LEB has only dirty and free space, then we may safely unmap it and make
+ * it free.  Note, we cannot do this with indexing LEBs because dirty space may
+ * correspond index nodes that are required for recovery.  In that case, the
+ * LEB cannot be unmapped until after the next commit.
+ *
+ * This function returns %0 upon success and a negative error code upon failure.
+ */
+int ubifs_gc_start_commit(struct ubifs_info *c)
+{
+	struct ubifs_gced_idx_leb *idx_gc;
+	const struct ubifs_lprops *lp;
+	int err = 0, flags;
+
+	ubifs_get_lprops(c);
+
+	/*
+	 * Unmap (non-index) freeable LEBs. Note that recovery requires that all
+	 * wbufs are sync'd before this, which is done in 'do_commit()'.
+	 */
+	while (1) {
+		lp = ubifs_fast_find_freeable(c);
+		if (IS_ERR(lp)) {
+			err = PTR_ERR(lp);
+			goto out;
+		}
+		if (!lp)
+			break;
+		ubifs_assert(!(lp->flags & LPROPS_TAKEN));
+		ubifs_assert(!(lp->flags & LPROPS_INDEX));
+		err = ubifs_leb_unmap(c, lp->lnum);
+		if (err)
+			goto out;
+		lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0);
+		if (IS_ERR(lp)) {
+			err = PTR_ERR(lp);
+			goto out;
+		}
+		ubifs_assert(!(lp->flags & LPROPS_TAKEN));
+		ubifs_assert(!(lp->flags & LPROPS_INDEX));
+	}
+
+	/* Mark GC'd index LEBs OK to unmap after this commit finishes */
+	list_for_each_entry(idx_gc, &c->idx_gc, list)
+		idx_gc->unmap = 1;
+
+	/* Record index freeable LEBs for unmapping after commit */
+	while (1) {
+		lp = ubifs_fast_find_frdi_idx(c);
+		if (IS_ERR(lp)) {
+			err = PTR_ERR(lp);
+			goto out;
+		}
+		if (!lp)
+			break;
+		idx_gc = kmalloc(sizeof(struct ubifs_gced_idx_leb), GFP_NOFS);
+		if (!idx_gc) {
+			err = -ENOMEM;
+			goto out;
+		}
+		ubifs_assert(!(lp->flags & LPROPS_TAKEN));
+		ubifs_assert(lp->flags & LPROPS_INDEX);
+		/* Don't release the LEB until after the next commit */
+		flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX;
+		lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1);
+		if (IS_ERR(lp)) {
+			err = PTR_ERR(lp);
+			kfree(idx_gc);
+			goto out;
+		}
+		ubifs_assert(lp->flags & LPROPS_TAKEN);
+		ubifs_assert(!(lp->flags & LPROPS_INDEX));
+		idx_gc->lnum = lp->lnum;
+		idx_gc->unmap = 1;
+		list_add(&idx_gc->list, &c->idx_gc);
+	}
+out:
+	ubifs_release_lprops(c);
+	return err;
+}
+
+/**
+ * ubifs_gc_end_commit - garbage collection at end of commit.
+ * @c: UBIFS file-system description object
+ *
+ * This function completes out-of-place garbage collection of index LEBs.
+ */
+int ubifs_gc_end_commit(struct ubifs_info *c)
+{
+	struct ubifs_gced_idx_leb *idx_gc, *tmp;
+	struct ubifs_wbuf *wbuf;
+	int err = 0;
+
+	wbuf = &c->jheads[GCHD].wbuf;
+	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
+	list_for_each_entry_safe(idx_gc, tmp, &c->idx_gc, list)
+		if (idx_gc->unmap) {
+			dbg_gc("LEB %d", idx_gc->lnum);
+			err = ubifs_leb_unmap(c, idx_gc->lnum);
+			if (err)
+				goto out;
+			err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC,
+					  LPROPS_NC, 0, LPROPS_TAKEN, -1);
+			if (err)
+				goto out;
+			list_del(&idx_gc->list);
+			kfree(idx_gc);
+		}
+out:
+	mutex_unlock(&wbuf->io_mutex);
+	return err;
+}
+#endif
+/**
+ * ubifs_destroy_idx_gc - destroy idx_gc list.
+ * @c: UBIFS file-system description object
+ *
+ * This function destroys the @c->idx_gc list. It is called when unmounting
+ * so locks are not needed. Returns zero in case of success and a negative
+ * error code in case of failure.
+ */
+void ubifs_destroy_idx_gc(struct ubifs_info *c)
+{
+	while (!list_empty(&c->idx_gc)) {
+		struct ubifs_gced_idx_leb *idx_gc;
+
+		idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb,
+				    list);
+		c->idx_gc_cnt -= 1;
+		list_del(&idx_gc->list);
+		kfree(idx_gc);
+	}
+}
+#ifndef __UBOOT__
+/**
+ * ubifs_get_idx_gc_leb - get a LEB from GC'd index LEB list.
+ * @c: UBIFS file-system description object
+ *
+ * Called during start commit so locks are not needed.
+ */
+int ubifs_get_idx_gc_leb(struct ubifs_info *c)
+{
+	struct ubifs_gced_idx_leb *idx_gc;
+	int lnum;
+
+	if (list_empty(&c->idx_gc))
+		return -ENOSPC;
+	idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list);
+	lnum = idx_gc->lnum;
+	/* c->idx_gc_cnt is updated by the caller when lprops are updated */
+	list_del(&idx_gc->list);
+	kfree(idx_gc);
+	return lnum;
+}
+#endif
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 7268b37..1064cb2 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -78,7 +78,6 @@
 	int dirty;
 };
 
-#ifndef __UBOOT__
 /**
  * set_bud_lprops - set free and dirty space used by a bud.
  * @c: UBIFS file-system description object
@@ -432,7 +431,6 @@
 	list_add_tail(&r->list, &c->replay_list);
 	return 0;
 }
-#endif
 
 /**
  * ubifs_validate_entry - validate directory or extended attribute entry node.
@@ -466,7 +464,6 @@
 	return 0;
 }
 
-#ifndef __UBOOT__
 /**
  * is_last_bud - check if the bud is the last in the journal head.
  * @c: UBIFS file-system description object
@@ -1063,4 +1060,3 @@
 	c->replaying = 0;
 	return err;
 }
-#endif
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 01d449a..10f8fff 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1049,7 +1049,6 @@
 	c->orph_buf = NULL;
 }
 
-#ifndef __UBOOT__
 /**
  * free_buds - free per-bud objects.
  * @c: UBIFS file-system description object
@@ -1061,7 +1060,6 @@
 	rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb)
 		kfree(bud);
 }
-#endif
 
 /**
  * check_volume_empty - check if the UBI volume is empty.
@@ -1242,6 +1240,7 @@
 
 	return 0;
 }
+#endif
 
 /**
  * destroy_journal - destroy journal data structures.
@@ -1272,7 +1271,6 @@
 	ubifs_tnc_close(c);
 	free_buds(c);
 }
-#endif
 
 /**
  * bu_init - initialize bulk-read information.
@@ -1502,11 +1500,9 @@
 	if (err)
 		goto out_lpt;
 
-#ifndef __UBOOT__
 	err = ubifs_replay_journal(c);
 	if (err)
 		goto out_journal;
-#endif
 
 	/* Calculate 'min_idx_lebs' after journal replay */
 	c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
@@ -1678,10 +1674,8 @@
 	spin_unlock(&ubifs_infos_lock);
 out_orphans:
 	free_orphans(c);
-#ifndef __UBOOT__
 out_journal:
 	destroy_journal(c);
-#endif
 out_lpt:
 	ubifs_lpt_free(c, 0);
 out_master:
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 95cae54..e20cedd 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -2827,7 +2827,6 @@
 	return ERR_PTR(err);
 }
 
-#ifndef __UBOOT__
 /**
  * tnc_destroy_cnext - destroy left-over obsolete znodes from a failed commit.
  * @c: UBIFS file-system description object
@@ -2869,7 +2868,6 @@
 	kfree(c->ilebs);
 	destroy_old_idx(c);
 }
-#endif
 
 /**
  * left_znode - get the znode to the left.
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 49e6f46..6dd6174 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -150,6 +150,12 @@
 
 	return 0;
 }
+
+/* from shrinker.c */
+
+/* Global clean znode counter (for all mounted UBIFS instances) */
+atomic_long_t ubifs_clean_zn_cnt;
+
 #endif
 
 /**
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index c120261..a51b237 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -31,6 +31,8 @@
 #include <linux/backing-dev.h>
 #include "ubifs-media.h"
 #else
+#include <asm/atomic.h>
+#include <asm-generic/atomic-long.h>
 #include <ubi_uboot.h>
 
 #include <linux/ctype.h>
@@ -63,16 +65,6 @@
 
 void iput(struct inode *inode);
 
-/*
- * The atomic operations are used for budgeting etc which is not
- * needed for the read-only U-Boot implementation:
- */
-#define atomic_long_inc(a)
-#define atomic_long_dec(a)
-#define	atomic_long_sub(a, b)
-
-typedef unsigned long atomic_long_t;
-
 /* linux/include/time.h */
 #define NSEC_PER_SEC	1000000000L
 #define get_seconds()	0
diff --git a/include/_exports.h b/include/_exports.h
index 349a3c5..5944703 100644
--- a/include/_exports.h
+++ b/include/_exports.h
@@ -1,32 +1,73 @@
 /*
- * You do not need to use #ifdef around functions that may not exist
+ * You need to use #ifdef around functions that may not exist
  * in the final configuration (such as i2c).
+ * use a dummyfunction as first parameter to EXPORT_FUNC.
+ * As an example see the CONFIG_CMD_I2C section below
  */
-EXPORT_FUNC(get_version)
-EXPORT_FUNC(getc)
-EXPORT_FUNC(tstc)
-EXPORT_FUNC(putc)
-EXPORT_FUNC(puts)
-EXPORT_FUNC(printf)
-EXPORT_FUNC(install_hdlr)
-EXPORT_FUNC(free_hdlr)
-EXPORT_FUNC(malloc)
-EXPORT_FUNC(free)
-EXPORT_FUNC(udelay)
-EXPORT_FUNC(get_timer)
-EXPORT_FUNC(vprintf)
-EXPORT_FUNC(do_reset)
-EXPORT_FUNC(getenv)
-EXPORT_FUNC(setenv)
-EXPORT_FUNC(simple_strtoul)
-EXPORT_FUNC(strict_strtoul)
-EXPORT_FUNC(simple_strtol)
-EXPORT_FUNC(strcmp)
-EXPORT_FUNC(i2c_write)
-EXPORT_FUNC(i2c_read)
-EXPORT_FUNC(spi_init)
-EXPORT_FUNC(spi_setup_slave)
-EXPORT_FUNC(spi_free_slave)
-EXPORT_FUNC(spi_claim_bus)
-EXPORT_FUNC(spi_release_bus)
-EXPORT_FUNC(spi_xfer)
+#ifndef EXPORT_FUNC
+#define EXPORT_FUNC(a, b, c, ...)
+#endif
+	EXPORT_FUNC(get_version, unsigned long, get_version, void)
+	EXPORT_FUNC(getc, int, getc, void)
+	EXPORT_FUNC(tstc, int, tstc, void)
+	EXPORT_FUNC(putc, void, putc, const char)
+	EXPORT_FUNC(puts, void, puts, const char *)
+	EXPORT_FUNC(printf, int, printf, const char*, ...)
+#if defined(CONFIG_X86) || defined(CONFIG_PPC)
+	EXPORT_FUNC(irq_install_handler, void, install_hdlr,
+		    int, interrupt_handler_t, void*)
+
+	EXPORT_FUNC(irq_free_handler, void, free_hdlr, int)
+#else
+	EXPORT_FUNC(dummy, void, install_hdlr, void)
+	EXPORT_FUNC(dummy, void, free_hdlr, void)
+#endif
+	EXPORT_FUNC(malloc, void *, malloc, size_t)
+	EXPORT_FUNC(free, void, free, void *)
+	EXPORT_FUNC(udelay, void, udelay, unsigned long)
+	EXPORT_FUNC(get_timer, unsigned long, get_timer, unsigned long)
+	EXPORT_FUNC(vprintf, int, vprintf, const char *, va_list)
+	EXPORT_FUNC(do_reset, int, do_reset, cmd_tbl_t *,
+		    int , int , char * const [])
+	EXPORT_FUNC(getenv, char  *, getenv, const char*)
+	EXPORT_FUNC(setenv, int, setenv, const char *, const char *)
+	EXPORT_FUNC(simple_strtoul, unsigned long, simple_strtoul,
+		    const char *, char **, unsigned int)
+	EXPORT_FUNC(strict_strtoul, int, strict_strtoul,
+		    const char *, unsigned int , unsigned long *)
+	EXPORT_FUNC(simple_strtol, long, simple_strtol,
+		    const char *, char **, unsigned int)
+	EXPORT_FUNC(strcmp, int, strcmp, const char *cs, const char *ct)
+#if defined(CONFIG_CMD_I2C) && \
+		(!defined(CONFIG_DM_I2C) || defined(CONFIG_DM_I2C_COMPAT))
+	EXPORT_FUNC(i2c_write, int, i2c_write, uchar, uint, int , uchar * , int)
+	EXPORT_FUNC(i2c_read, int, i2c_read, uchar, uint, int , uchar * , int)
+#else
+	EXPORT_FUNC(dummy, void, i2c_write, void)
+	EXPORT_FUNC(dummy, void, i2c_read, void)
+#endif
+
+#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
+	EXPORT_FUNC(dummy, void, spi_init, void)
+	EXPORT_FUNC(dummy, void, spi_setup_slave, void)
+	EXPORT_FUNC(dummy, void, spi_free_slave, void)
+#else
+	EXPORT_FUNC(spi_init, void, spi_init, void)
+	EXPORT_FUNC(spi_setup_slave, struct spi_slave *, spi_setup_slave,
+		    unsigned int, unsigned int, unsigned int, unsigned int)
+	EXPORT_FUNC(spi_free_slave, void, spi_free_slave, struct spi_slave *)
+#endif
+#ifndef CONFIG_CMD_SPI
+	EXPORT_FUNC(dummy, void, spi_claim_bus, void)
+	EXPORT_FUNC(dummy, void, spi_release_bus, void)
+	EXPORT_FUNC(dummy, void, spi_xfer, void)
+#else
+	EXPORT_FUNC(spi_claim_bus, int, spi_claim_bus, struct spi_slave *)
+	EXPORT_FUNC(spi_release_bus, void, spi_release_bus, struct spi_slave *)
+	EXPORT_FUNC(spi_xfer, int, spi_xfer, struct spi_slave *,
+		    unsigned int, const void *, void *, unsigned long)
+#endif
+	EXPORT_FUNC(ustrtoul, unsigned long, ustrtoul,
+		    const char *, char **, unsigned int)
+	EXPORT_FUNC(ustrtoull, unsigned long long, ustrtoull,
+		    const char *, char **, unsigned int)
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
new file mode 100644
index 0000000..d0469ef
--- /dev/null
+++ b/include/asm-generic/atomic-long.h
@@ -0,0 +1,260 @@
+#ifndef _ASM_GENERIC_ATOMIC_LONG_H
+#define _ASM_GENERIC_ATOMIC_LONG_H
+/*
+ * Copyright (C) 2005 Silicon Graphics, Inc.
+ *	Christoph Lameter
+ *
+ * Allows to provide arch independent atomic definitions without the need to
+ * edit all arch specific atomic.h files.
+ */
+
+#include <asm/types.h>
+
+/*
+ * Suppport for atomic_long_t
+ *
+ * Casts for parameters are avoided for existing atomic functions in order to
+ * avoid issues with cast-as-lval under gcc 4.x and other limitations that the
+ * macros of a platform may have.
+ */
+
+#if BITS_PER_LONG == 64
+
+typedef atomic64_t atomic_long_t;
+
+#define ATOMIC_LONG_INIT(i)	ATOMIC64_INIT(i)
+
+static inline long atomic_long_read(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_read(v);
+}
+
+static inline void atomic_long_set(atomic_long_t *l, long i)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	atomic64_set(v, i);
+}
+
+static inline void atomic_long_inc(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	atomic64_inc(v);
+}
+
+static inline void atomic_long_dec(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	atomic64_dec(v);
+}
+
+static inline void atomic_long_add(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	atomic64_add(i, v);
+}
+
+static inline void atomic_long_sub(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	atomic64_sub(i, v);
+}
+
+static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return atomic64_sub_and_test(i, v);
+}
+
+static inline int atomic_long_dec_and_test(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return atomic64_dec_and_test(v);
+}
+
+static inline int atomic_long_inc_and_test(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return atomic64_inc_and_test(v);
+}
+
+static inline int atomic_long_add_negative(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return atomic64_add_negative(i, v);
+}
+
+static inline long atomic_long_add_return(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_add_return(i, v);
+}
+
+static inline long atomic_long_sub_return(long i, atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_sub_return(i, v);
+}
+
+static inline long atomic_long_inc_return(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_inc_return(v);
+}
+
+static inline long atomic_long_dec_return(atomic_long_t *l)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_dec_return(v);
+}
+
+static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
+{
+	atomic64_t *v = (atomic64_t *)l;
+
+	return (long)atomic64_add_unless(v, a, u);
+}
+
+#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
+
+#define atomic_long_cmpxchg(l, old, new) \
+	(atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
+#define atomic_long_xchg(v, new) \
+	(atomic64_xchg((atomic64_t *)(v), (new)))
+
+#else  /*  BITS_PER_LONG == 64  */
+
+typedef atomic_t atomic_long_t;
+
+#define ATOMIC_LONG_INIT(i)	ATOMIC_INIT(i)
+static inline long atomic_long_read(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_read(v);
+}
+
+static inline void atomic_long_set(atomic_long_t *l, long i)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	atomic_set(v, i);
+}
+
+static inline void atomic_long_inc(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	atomic_inc(v);
+}
+
+static inline void atomic_long_dec(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	atomic_dec(v);
+}
+
+static inline void atomic_long_add(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	atomic_add(i, v);
+}
+
+static inline void atomic_long_sub(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	atomic_sub(i, v);
+}
+
+#ifndef __UBOOT__
+static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return atomic_sub_and_test(i, v);
+}
+
+static inline int atomic_long_dec_and_test(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return atomic_dec_and_test(v);
+}
+
+static inline int atomic_long_inc_and_test(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return atomic_inc_and_test(v);
+}
+
+static inline int atomic_long_add_negative(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return atomic_add_negative(i, v);
+}
+
+static inline long atomic_long_add_return(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_add_return(i, v);
+}
+
+static inline long atomic_long_sub_return(long i, atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_sub_return(i, v);
+}
+
+static inline long atomic_long_inc_return(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_inc_return(v);
+}
+
+static inline long atomic_long_dec_return(atomic_long_t *l)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_dec_return(v);
+}
+
+static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
+{
+	atomic_t *v = (atomic_t *)l;
+
+	return (long)atomic_add_unless(v, a, u);
+}
+
+#define atomic_long_inc_not_zero(l) atomic_inc_not_zero((atomic_t *)(l))
+
+#define atomic_long_cmpxchg(l, old, new) \
+	(atomic_cmpxchg((atomic_t *)(l), (old), (new)))
+#define atomic_long_xchg(v, new) \
+	(atomic_xchg((atomic_t *)(v), (new)))
+#endif  /*  __UBOOT__ */
+
+#endif  /*  BITS_PER_LONG == 64  */
+
+#endif  /*  _ASM_GENERIC_ATOMIC_LONG_H  */
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 3d14d5f..6747619 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -73,7 +73,7 @@
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
 	unsigned long fdt_size;	/* Space reserved for relocated FDT */
-	void **jt;		/* jump table */
+	struct jt_funcs *jt;		/* jump table */
 	char env_buf[32];	/* buffer for getenv() before reloc. */
 #ifdef CONFIG_TRACE
 	void		*trace_buff;	/* The trace buffer */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 36a36c6..3b96b82 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -10,6 +10,15 @@
 /*
  * Generic GPIO API for U-Boot
  *
+ * --
+ * NB: This is deprecated. Please use the driver model functions instead:
+ *
+ *    - gpio_request_by_name()
+ *    - dm_gpio_get_value() etc.
+ *
+ * For now we need a dm_ prefix on some functions to avoid name collision.
+ * --
+ *
  * GPIOs are numbered from 0 to GPIO_COUNT-1 which value is defined
  * by the SOC/architecture.
  *
@@ -26,6 +35,7 @@
  */
 
 /**
+ * @deprecated	Please use driver model instead
  * Request a GPIO. This should be called before any of the other functions
  * are used on this GPIO.
  *
@@ -39,6 +49,7 @@
 int gpio_request(unsigned gpio, const char *label);
 
 /**
+ * @deprecated	Please use driver model instead
  * Stop using the GPIO.  This function should not alter pin configuration.
  *
  * @param gpio	GPIO number
@@ -47,6 +58,7 @@
 int gpio_free(unsigned gpio);
 
 /**
+ * @deprecated	Please use driver model instead
  * Make a GPIO an input.
  *
  * @param gpio	GPIO number
@@ -55,6 +67,7 @@
 int gpio_direction_input(unsigned gpio);
 
 /**
+ * @deprecated	Please use driver model instead
  * Make a GPIO an output, and set its value.
  *
  * @param gpio	GPIO number
@@ -64,6 +77,7 @@
 int gpio_direction_output(unsigned gpio, int value);
 
 /**
+ * @deprecated	Please use driver model instead
  * Get a GPIO's value. This will work whether the GPIO is an input
  * or an output.
  *
@@ -73,6 +87,7 @@
 int gpio_get_value(unsigned gpio);
 
 /**
+ * @deprecated	Please use driver model instead
  * Set an output GPIO's value. The GPIO must already be an output or
  * this function may have no effect.
  *
@@ -95,6 +110,34 @@
 
 struct udevice;
 
+struct gpio_desc {
+	struct udevice *dev;	/* Device, NULL for invalid GPIO */
+	unsigned long flags;
+#define GPIOD_REQUESTED		(1 << 0)	/* Requested/claimed */
+#define GPIOD_IS_OUT		(1 << 1)	/* GPIO is an output */
+#define GPIOD_IS_IN		(1 << 2)	/* GPIO is an output */
+#define GPIOD_ACTIVE_LOW	(1 << 3)	/* value has active low */
+#define GPIOD_IS_OUT_ACTIVE	(1 << 4)	/* set output active */
+
+	uint offset;		/* GPIO offset within the device */
+	/*
+	 * We could consider adding the GPIO label in here. Possibly we could
+	 * use this structure for internal GPIO information.
+	 */
+};
+
+/**
+ * dm_gpio_is_valid() - Check if a GPIO is gpio_is_valie
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return true if valid, false if not
+ */
+static inline bool dm_gpio_is_valid(struct gpio_desc *desc)
+{
+	return desc->dev != NULL;
+}
+
 /**
  * gpio_get_status() - get the current GPIO status as a string
  *
@@ -106,6 +149,8 @@
  * which means this is GPIO bank b, offset 4, currently set to input, current
  * value 1, [x] means that it is requested and the owner is 'sdmmc_cd'
  *
+ * TODO(sjg@chromium.org): This should use struct gpio_desc
+ *
  * @dev:	Device to check
  * @offset:	Offset of device GPIO to check
  * @buf:	Place to put string
@@ -118,6 +163,8 @@
  *
  * Note this returns GPIOF_UNUSED if the GPIO is not requested.
  *
+ * TODO(sjg@chromium.org): This should use struct gpio_desc
+ *
  * @dev:	Device to check
  * @offset:	Offset of device GPIO to check
  * @namep:	If non-NULL, this is set to the nane given when the GPIO
@@ -135,6 +182,8 @@
  * Note this does not return GPIOF_UNUSED - it will always return the GPIO
  * driver's view of a pin function, even if it is not correctly set up.
  *
+ * TODO(sjg@chromium.org): This should use struct gpio_desc
+ *
  * @dev:	Device to check
  * @offset:	Offset of device GPIO to check
  * @namep:	If non-NULL, this is set to the nane given when the GPIO
@@ -155,6 +204,8 @@
 int gpio_requestf(unsigned gpio, const char *fmt, ...)
 		__attribute__ ((format (__printf__, 2, 3)));
 
+struct fdtdec_phandle_args;
+
 /**
  * struct struct dm_gpio_ops - Driver model GPIO operations
  *
@@ -198,6 +249,33 @@
 	 * @return current function - GPIOF_...
 	 */
 	int (*get_function)(struct udevice *dev, unsigned offset);
+
+	/**
+	 * xlate() - Translate phandle arguments into a GPIO description
+	 *
+	 * This function should set up the fields in desc according to the
+	 * information in the arguments. The uclass will have set up:
+	 *
+	 *   @desc->dev to @dev
+	 *   @desc->flags to 0
+	 *   @desc->offset to the value of the first argument in args, if any,
+	 *		otherwise -1 (which is invalid)
+	 *
+	 * This method is optional so if the above defaults suit it can be
+	 * omitted. Typical behaviour is to set up the GPIOD_ACTIVE_LOW flag
+	 * in desc->flags.
+	 *
+	 * Note that @dev is passed in as a parameter to follow driver model
+	 * uclass conventions, even though it is already available as
+	 * desc->dev.
+	 *
+	 * @dev:	GPIO device
+	 * @desc:	Place to put GPIO description
+	 * @args:	Arguments provided in descripion
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
+		     struct fdtdec_phandle_args *args);
 };
 
 /**
@@ -268,4 +346,191 @@
  */
 unsigned gpio_get_values_as_int(const int *gpio_list);
 
+/**
+ * gpio_request_by_name() - Locate and request a GPIO by name
+ *
+ * This operates by looking up the given list name in the device (device
+ * tree property) and requesting the GPIO for use. The property must exist
+ * in @dev's node.
+ *
+ * Use @flags to specify whether the GPIO should be an input or output. In
+ * principle this can also come from the device tree binding but most
+ * bindings don't provide this information. Specifically, when the GPIO uclass
+ * calls the xlate() method, it can return default flags, which are then
+ * ORed with this @flags.
+ *
+ * If we find that requesting the GPIO is not always needed we could add a
+ * new function or a new GPIOD_NO_REQUEST flag.
+ *
+ * At present driver model has no reference counting so if one device
+ * requests a GPIO which subsequently is unbound, the @desc->dev pointer
+ * will be invalid. However this will only happen if the GPIO device is
+ * unbound, not if it is removed, so this seems like a reasonable limitation
+ * for now. There is no real use case for unbinding drivers in normal
+ * operation.
+ *
+ * The device tree binding is doc/device-tree-bindings/gpio/gpio.txt in
+ * generate terms and each specific device may add additional details in
+ * a binding file in the same directory.
+ *
+ * @dev:	Device requesting the GPIO
+ * @list_name:	Name of GPIO list (e.g. "board-id-gpios")
+ * @index:	Index number of the GPIO in that list use request (0=first)
+ * @desc:	Returns GPIO description information. If there is no such
+ *		GPIO, dev->dev will be NULL.
+ * @flags:	Indicates the GPIO input/output settings (GPIOD_...)
+ * @return 0 if OK, -ENOENT if the GPIO does not exist, -EINVAL if there is
+ * something wrong with the list, or other -ve for another error (e.g.
+ * -EBUSY if a GPIO was already requested)
+ */
+int gpio_request_by_name(struct udevice *dev, const char *list_name,
+			 int index, struct gpio_desc *desc, int flags);
+
+/**
+ * gpio_request_list_by_name() - Request a list of GPIOs
+ *
+ * Reads all the GPIOs from a list and requetss them. See
+ * gpio_request_by_name() for additional details. Lists should not be
+ * misused to hold unrelated or optional GPIOs. They should only be used
+ * for things like parallel data lines. A zero phandle terminates the list
+ * the list.
+ *
+ * This function will either succeed, and request all GPIOs in the list, or
+ * fail and request none (it will free already-requested GPIOs in case of
+ * an error part-way through).
+ *
+ * @dev:	Device requesting the GPIO
+ * @list_name:	Name of GPIO list (e.g. "board-id-gpios")
+ * @desc_list:	Returns a list of GPIO description information
+ * @max_count:	Maximum number of GPIOs to return (@desc_list must be at least
+ *		this big)
+ * @flags:	Indicates the GPIO input/output settings (GPIOD_...)
+ * @return number of GPIOs requested, or -ve on error
+ */
+int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
+			      struct gpio_desc *desc_list, int max_count,
+			      int flags);
+
+/**
+ * gpio_get_list_count() - Returns the number of GPIOs in a list
+ *
+ * Counts the GPIOs in a list. See gpio_request_by_name() for additional
+ * details.
+ *
+ * @dev:	Device requesting the GPIO
+ * @list_name:	Name of GPIO list (e.g. "board-id-gpios")
+ * @return number of GPIOs (0 for an empty property) or -ENOENT if the list
+ * does not exist
+ */
+int gpio_get_list_count(struct udevice *dev, const char *list_name);
+
+/**
+ * gpio_request_by_name_nodev() - request GPIOs without a device
+ *
+ * This is a version of gpio_request_list_by_name() that does not use a
+ * device. Avoid it unless the caller is not yet using driver model
+ */
+int gpio_request_by_name_nodev(const void *blob, int node,
+			       const char *list_name,
+			       int index, struct gpio_desc *desc, int flags);
+
+/**
+ * gpio_request_list_by_name_nodev() - request GPIOs without a device
+ *
+ * This is a version of gpio_request_list_by_name() that does not use a
+ * device. Avoid it unless the caller is not yet using driver model
+ */
+int gpio_request_list_by_name_nodev(const void *blob, int node,
+				    const char *list_name,
+				    struct gpio_desc *desc_list, int max_count,
+				    int flags);
+
+/**
+ * dm_gpio_free() - Free a single GPIO
+ *
+ * This frees a single GPIOs previously returned from gpio_request_by_name().
+ *
+ * @dev:	Device which requested the GPIO
+ * @desc:	GPIO to free
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc);
+
+/**
+ * gpio_free_list() - Free a list of GPIOs
+ *
+ * This frees a list of GPIOs previously returned from
+ * gpio_request_list_by_name().
+ *
+ * @dev:	Device which requested the GPIOs
+ * @desc:	List of GPIOs to free
+ * @count:	Number of GPIOs in the list
+ * @return 0 if OK, -ve on error
+ */
+int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count);
+
+/**
+ * gpio_free_list_nodev() - free GPIOs without a device
+ *
+ * This is a version of gpio_free_list() that does not use a
+ * device. Avoid it unless the caller is not yet using driver model
+ */
+int gpio_free_list_nodev(struct gpio_desc *desc, int count);
+
+/**
+ * dm_gpio_get_value() - Get the value of a GPIO
+ *
+ * This is the driver model version of the existing gpio_get_value() function
+ * and should be used instead of that.
+ *
+ * For now, these functions have a dm_ prefix since they conflict with
+ * existing names.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return GPIO value (0 for inactive, 1 for active) or -ve on error
+ */
+int dm_gpio_get_value(struct gpio_desc *desc);
+
+int dm_gpio_set_value(struct gpio_desc *desc, int value);
+
+/**
+ * dm_gpio_set_dir() - Set the direction for a GPIO
+ *
+ * This sets up the direction according tot the provided flags. It will do
+ * nothing unless the direction is actually specified.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_set_dir(struct gpio_desc *desc);
+
+/**
+ * dm_gpio_set_dir_flags() - Set direction using specific flags
+ *
+ * This is like dm_gpio_set_dir() except that the flags value is provided
+ * instead of being used from desc->flags. This is needed because in many
+ * cases the GPIO description does not include direction information.
+ * Note that desc->flags is updated by this function.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @flags:	New flags to use
+ * @return 0 if OK, -ve on error, in which case desc->flags is not updated
+ */
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
+
+/**
+ * gpio_get_number() - Get the global GPIO number of a GPIO
+ *
+ * This should only be used for debugging or interest. It returns the nummber
+ * that should be used for gpio_get_value() etc. to access this GPIO.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return GPIO number, or -ve if not found
+ */
+int gpio_get_number(struct gpio_desc *desc);
+
 #endif	/* _ASM_GENERIC_GPIO_H_ */
diff --git a/include/asm-generic/u-boot.h b/include/asm-generic/u-boot.h
index aef39d7..a63a87a 100644
--- a/include/asm-generic/u-boot.h
+++ b/include/asm-generic/u-boot.h
@@ -32,6 +32,10 @@
 	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
 	unsigned long	bi_sramstart;	/* start of SRAM memory */
 	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
+#ifdef CONFIG_AVR32
+	unsigned char   bi_phy_id[4];   /* PHY address for ATAG_ETHERNET */
+	unsigned long   bi_board_number;/* ATAG_BOARDINFO */
+#endif
 #ifdef CONFIG_ARM
 	unsigned long	bi_arm_freq; /* arm frequency */
 	unsigned long	bi_dsp_freq; /* dsp core frequency */
diff --git a/include/atmel_lcd.h b/include/atmel_lcd.h
new file mode 100644
index 0000000..fa8aa29
--- /dev/null
+++ b/include/atmel_lcd.h
@@ -0,0 +1,38 @@
+/*
+ * atmel_lcd.h - Atmel LCD Controller structures
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ATMEL_LCD_H_
+#define _ATMEL_LCD_H_
+
+typedef struct vidinfo {
+	ushort vl_col;		/* Number of columns (i.e. 640) */
+	ushort vl_row;		/* Number of rows (i.e. 480) */
+	u_long vl_clk;	/* pixel clock in ps    */
+
+	/* LCD configuration register */
+	u_long vl_sync;		/* Horizontal / vertical sync */
+	u_long vl_bpix;	/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 = 16 */
+	u_long vl_tft;		/* 0 = passive, 1 = TFT */
+	u_long vl_cont_pol_low;	/* contrast polarity is low */
+	u_long vl_clk_pol;	/* clock polarity */
+
+	/* Horizontal control register. */
+	u_long vl_hsync_len;	/* Length of horizontal sync */
+	u_long vl_left_margin;	/* Time from sync to picture */
+	u_long vl_right_margin;	/* Time from picture to sync */
+
+	/* Vertical control register. */
+	u_long vl_vsync_len;	/* Length of vertical sync */
+	u_long vl_upper_margin;	/* Time from sync to picture */
+	u_long vl_lower_margin;	/* Time from picture to sync */
+
+	u_long	mmio;		/* Memory mapped registers */
+} vidinfo_t;
+
+#endif
diff --git a/include/axp221.h b/include/axp221.h
index 6f24a61..a20e25c 100644
--- a/include/axp221.h
+++ b/include/axp221.h
@@ -12,7 +12,6 @@
 
 #define AXP223_DEVICE_ADDR 0x3a3
 #define AXP223_RUNTIME_ADDR 0x2d
-#define AXP223_DEVICE_MODE_DATA 0x7c3e00
 
 /* Page 0 addresses */
 #define AXP221_CHIP_ID		0x03
diff --git a/include/bootstage.h b/include/bootstage.h
index df13ab2..0276cb3 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -86,9 +86,9 @@
 	BOOTSTAGE_ID_POST_FAIL_R,	/* Post failure reported after reloc */
 
 	/*
-	 * This set is reported ony by x86, and the meaning is different. In
+	 * This set is reported only by x86, and the meaning is different. In
 	 * this case we are reporting completion of a particular stage.
-	 * This should probably change in he x86 code (which doesn't report
+	 * This should probably change in the x86 code (which doesn't report
 	 * errors in any case), but discussion this can perhaps wait until we
 	 * have a generic board implementation.
 	 */
@@ -194,6 +194,7 @@
 	BOOTSTAGE_ID_MAIN_CPU_READY,
 
 	BOOTSTAGE_ID_ACCUM_LCD,
+	BOOTSTAGE_ID_ACCUM_SCSI,
 
 	/* a few spare for the user, from here */
 	BOOTSTAGE_ID_USER,
diff --git a/include/common.h b/include/common.h
index 4b3e0d3..77c55c6 100644
--- a/include/common.h
+++ b/include/common.h
@@ -183,6 +183,7 @@
 /*
  * Function Prototypes
  */
+int dram_init(void);
 
 void	hang		(void) __attribute__ ((noreturn));
 
@@ -228,12 +229,13 @@
 extern char console_buffer[];
 
 /* arch/$(ARCH)/lib/board.c */
-void	board_init_f(ulong);
-void	board_init_r  (gd_t *, ulong) __attribute__ ((noreturn));
-int	checkboard    (void);
-int	checkflash    (void);
-int	checkdram     (void);
-int	last_stage_init(void);
+void board_init_f(ulong);
+void board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
+int checkboard(void);
+int show_board_info(void);
+int checkflash(void);
+int checkdram(void);
+int last_stage_init(void);
 extern ulong monitor_flash_len;
 int mac_read_from_eeprom(void);
 extern u8 __dtb_dt_begin[];	/* embedded device tree blob */
@@ -251,6 +253,24 @@
 int arch_early_init_r(void);
 
 /**
+ * Reserve all necessary stacks
+ *
+ * This is used in generic board init sequence in common/board_f.c. Each
+ * architecture could provide this function to tailor the required stacks.
+ *
+ * On entry gd->start_addr_sp is pointing to the suggested top of the stack.
+ * The callee ensures gd->start_add_sp is 16-byte aligned, so architectures
+ * require only this can leave it untouched.
+ *
+ * On exit gd->start_addr_sp and gd->irq_sp should be set to the respective
+ * positions of the stack. The stack pointer(s) will be set to this later.
+ * gd->irq_sp is only required, if the architecture needs it.
+ *
+ * @return 0 if no error
+ */
+__weak int arch_reserve_stacks(void);
+
+/**
  * Show the DRAM size in a board-specific way
  *
  * This is used by boards to display DRAM information in their own way.
diff --git a/include/config_defaults.h b/include/config_defaults.h
index 4d49315..ad08c1d 100644
--- a/include/config_defaults.h
+++ b/include/config_defaults.h
@@ -20,10 +20,4 @@
 #define CONFIG_ZLIB 1
 #define CONFIG_PARTITIONS 1
 
-#ifndef CONFIG_SPL_BUILD
-#define CONFIG_DM_WARN
-#define CONFIG_DM_DEVICE_REMOVE
-#define CONFIG_DM_STDIO
-#endif
-
 #endif
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index becbe3f..07a0b3b 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -10,10 +10,14 @@
 #ifndef _CONFIG_CMD_DISTRO_BOOTCMD_H
 #define _CONFIG_CMD_DISTRO_BOOTCMD_H
 
+/* We need the part command */
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
 #define BOOTENV_SHARED_BLKDEV_BODY(devtypel) \
 		"if " #devtypel " dev ${devnum}; then " \
 			"setenv devtype " #devtypel "; " \
-			"run scan_dev_for_boot; " \
+			"run scan_dev_for_boot_part; " \
 		"fi\0"
 
 #define BOOTENV_SHARED_BLKDEV(devtypel) \
@@ -110,7 +114,7 @@
 #define BOOTENV_DEV_DHCP(devtypeu, devtypel, instance) \
 	"bootcmd_dhcp=" \
 		BOOTENV_RUN_USB_INIT \
-		"if dhcp ${scriptaddr} boot.scr.uimg; then " \
+		"if dhcp ${scriptaddr} ${boot_script_dhcp}; then " \
 			"source ${scriptaddr}; " \
 		"fi\0"
 #define BOOTENV_DEV_NAME_DHCP(devtypeu, devtypel, instance) \
@@ -154,8 +158,8 @@
 	BOOTENV_SHARED_IDE \
 	"boot_prefixes=/ /boot/\0" \
 	"boot_scripts=boot.scr.uimg boot.scr\0" \
+	"boot_script_dhcp=boot.scr.uimg\0" \
 	BOOTENV_BOOT_TARGETS \
-	"bootpart=1\0" \
 	\
 	"boot_extlinux="                                                  \
 		"sysboot ${devtype} ${devnum}:${bootpart} any "           \
@@ -186,17 +190,30 @@
 		"done\0"                                                  \
 	\
 	"scan_dev_for_boot="                                              \
-		"echo Scanning ${devtype} ${devnum}...; "                 \
+		"echo Scanning ${devtype} ${devnum}:${bootpart}...; "     \
 		"for prefix in ${boot_prefixes}; do "                     \
 			"run scan_dev_for_extlinux; "                     \
 			"run scan_dev_for_scripts; "                      \
 		"done\0"                                                  \
 	\
+	"scan_dev_for_boot_part="                                         \
+		"part list ${devtype} ${devnum} devplist; "               \
+		"for bootpart in ${devplist}; do "                        \
+			"if fstype ${devtype} ${devnum}:${bootpart} "     \
+					"bootfstype; then "               \
+				"run scan_dev_for_boot; "                 \
+			"fi; "                                            \
+		"done\0"                                                  \
+	\
 	BOOT_TARGET_DEVICES(BOOTENV_DEV)                                  \
 	\
-	"bootcmd=" BOOTENV_SET_SCSI_NEED_INIT                             \
+	"distro_bootcmd=" BOOTENV_SET_SCSI_NEED_INIT                      \
 		"for target in ${boot_targets}; do "                      \
 			"run bootcmd_${target}; "                         \
 		"done\0"
 
+#ifndef CONFIG_BOOTCOMMAND
+#define CONFIG_BOOTCOMMAND "run distro_bootcmd"
+#endif
+
 #endif  /* _CONFIG_CMD_DISTRO_BOOTCMD_H */
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 0004750..f1c270c 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -19,13 +19,11 @@
 #include <configs/ti_am335x_common.h>
 
 #ifndef CONFIG_SPL_BUILD
+#ifndef CONFIG_FIT
 # define CONFIG_FIT
+#endif
 # define CONFIG_TIMESTAMP
 # define CONFIG_LZO
-# ifdef CONFIG_ENABLE_VBOOT
-#  define CONFIG_FIT_SIGNATURE
-#  define CONFIG_RSA
-# endif
 #endif
 
 #define CONFIG_SYS_BOOTM_LEN		(16 << 20)
@@ -239,6 +237,7 @@
 #define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)
 /* NAND: driver related configs */
 #define CONFIG_NAND_OMAP_GPMC
+#define CONFIG_NAND_OMAP_GPMC_PREFETCH
 #define CONFIG_NAND_OMAP_ELM
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
 #define CONFIG_SYS_NAND_ECCPOS		{ 2, 3, 4, 5, 6, 7, 8, 9, \
diff --git a/include/configs/amcc-common.h b/include/configs/amcc-common.h
index 2aea899..73e1b0a 100644
--- a/include/configs/amcc-common.h
+++ b/include/configs/amcc-common.h
@@ -20,8 +20,10 @@
  */
 #define CONFIG_SYS_NS16550
 #define CONFIG_SYS_NS16550_SERIAL
+#ifndef CONFIG_DM_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	1
 #define CONFIG_SYS_NS16550_CLK		get_serial_clock()
+#endif
 #define CONFIG_BAUDRATE		115200
 #define CONFIG_SYS_BAUDRATE_TABLE  \
     {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
diff --git a/include/configs/arcangel4-be.h b/include/configs/arcangel4-be.h
deleted file mode 100644
index 76163ab..0000000
--- a/include/configs/arcangel4-be.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef _CONFIG_ARCANGEL4_H_
-#define _CONFIG_ARCANGEL4_H_
-
-/*
- *  CPU configuration
- */
-#define CONFIG_SYS_BIG_ENDIAN
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER		3
-#define CONFIG_SYS_CACHELINE_SIZE	64
-#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_CLK_FREQ
-
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
-/*
- * Memory configuration
- */
-#define CONFIG_SYS_TEXT_BASE		0x81000000
-#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
-
-#define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
-#define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
-#define CONFIG_SYS_SDRAM_SIZE		0x10000000	/* 256 Mb */
-
-#define CONFIG_SYS_INIT_SP_ADDR		\
-	(CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
-
-#define CONFIG_SYS_MALLOC_LEN		0x200000	/* 2 MB */
-#define CONFIG_SYS_BOOTM_LEN		0x2000000	/* 32 MB */
-#define CONFIG_SYS_LOAD_ADDR		0x82000000
-
-#define CONFIG_SYS_NO_FLASH
-
-/*
- * UART configuration
- *
- */
-#define CONFIG_ARC_SERIAL
-#define CONFIG_ARC_UART_BASE		0xC0FC1000
-#define CONFIG_BAUDRATE			115200
-
-/*
- * Command line configuration
- */
-#include <config_cmd_default.h>
-
-#define CONFIG_CMD_ELF
-
-#define CONFIG_OF_LIBFDT
-
-#define CONFIG_AUTO_COMPLETE
-#define CONFIG_SYS_MAXARGS		16
-
-/*
- * Environment settings
- */
-#define CONFIG_ENV_IS_NOWHERE
-#define CONFIG_ENV_SIZE			0x00200		/* 512 bytes */
-#define CONFIG_ENV_OFFSET		0
-
-/*
- * Environment configuration
- */
-#define CONFIG_BOOTDELAY		3
-#define CONFIG_BOOTFILE			"uImage"
-#define CONFIG_BOOTARGS			"console=ttyARC0,115200n8"
-#define CONFIG_LOADADDR			CONFIG_SYS_LOAD_ADDR
-
-/*
- * Console configuration
- */
-#define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_PROMPT		"arcangel4# "
-#define CONFIG_SYS_CBSIZE		256
-#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
-#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
-						sizeof(CONFIG_SYS_PROMPT) + 16)
-
-#endif /* _CONFIG_ARCANGEL4_H_ */
diff --git a/include/configs/arcangel4.h b/include/configs/arcangel4.h
index 81934a4..5e4097f 100644
--- a/include/configs/arcangel4.h
+++ b/include/configs/arcangel4.h
@@ -10,23 +10,11 @@
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER		3
-#define CONFIG_SYS_CACHELINE_SIZE	64
 #define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_CLK_FREQ
 
 /*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
-/*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE		0x81000000
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
diff --git a/include/configs/aristainetos.h b/include/configs/aristainetos.h
index e6a08df..3066fd0 100644
--- a/include/configs/aristainetos.h
+++ b/include/configs/aristainetos.h
@@ -1,4 +1,5 @@
 /*
+ * (C) Copyright 2015
  * (C) Copyright 2014
  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
  *
@@ -24,8 +25,7 @@
 #include <asm/imx-common/gpio.h>
 
 #define CONFIG_MACH_TYPE	4501
-#define CONFIG_MMCROOT		"/dev/mmcblk0p2"
-#define CONFIG_DEFAULT_FDT_FILE	"aristainetos.dtb"
+#define CONFIG_MMCROOT		"/dev/mmcblk0p1"
 #define CONFIG_HOSTNAME		aristainetos
 #define PHYS_SDRAM_SIZE		(1u * 1024 * 1024 * 1024)
 
@@ -81,7 +81,6 @@
 #define CONFIG_SF_DEFAULT_SPEED		20000000
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 #define CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_CONS_INDEX		1
@@ -101,84 +100,108 @@
 #define CONFIG_SYS_TEXT_BASE		0x17800000
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
-	"uimage=uImage\0" \
-	"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
-	"fdt_addr_r=0x11000000\0" \
-	"kernel_addr_r=0x12000000\0" \
-	"kernel_file=uImage\0" \
-	"boot_fdt=try\0" \
-	"ip_dyn=yes\0" \
+	"script=u-boot.scr\0" \
+	"fit_file=/boot/system.itb\0" \
+	"loadaddr=0x12000000\0" \
+	"fit_addr_r=0x14000000\0" \
+	"uboot=/boot/u-boot.imx\0" \
+	"uboot_sz=d0000\0" \
+	"rescue_sys_addr=f0000\0" \
+	"rescue_sys_length=f10000\0" \
+	"board_type=aristainetos7@1\0" \
+	"panel=lb07wv8\0" \
+	"splashpos=m,m\0" \
 	"console=" CONFIG_CONSOLE_DEV "\0" \
 	"fdt_high=0xffffffff\0"	  \
 	"initrd_high=0xffffffff\0" \
+	"mtdids=nand0=gpmi-nand,nor0=spi3.0\0" \
+	"mtdparts=mtdparts=spi3.0:832k(u-boot),64k(env),64k(env-red)," \
+		"-(rescue-system);gpmi-nand:-(ubi)\0" \
+	"addmisc=setenv bootargs ${bootargs} consoleblank=0\0" \
+	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \
+	"set_fit_default=fdt addr ${fit_addr_r};fdt set /configurations " \
+		"default ${board_type}\0" \
+	"get_env=mw ${loadaddr} 0 0x20000;" \
+		"mmc rescan;" \
+		"ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} env.txt;" \
+		"env import -t ${loadaddr}\0" \
+	"default_env=mw ${loadaddr} 0 0x20000;" \
+		"env export -t ${loadaddr} serial# ethaddr eth1addr " \
+		"board_type panel;" \
+		"env default -a;" \
+		"env import -t ${loadaddr}\0" \
+	"loadbootscript=" \
+		"ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+	"bootscript=echo Running bootscript from mmc ...; " \
+		"source\0" \
 	"mmcpart=1\0" \
-	"mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \
+	"mmcdev=0\0" \
 	"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
 	"mmcargs=setenv bootargs console=${console},${baudrate} " \
 		"root=${mmcroot}\0" \
-	"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${kernel_addr_r} " \
-		"${uimage}\0" \
-	"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} " \
-		"${fdt_file}\0" \
 	"mmcboot=echo Booting from mmc ...; " \
-		"run mmcargs;run loadimage loadfdt fdt_setup;" \
-		"bootm ${kernel_addr_r} - ${fdt_addr_r};\0" \
-	"rootpath=/opt/eldk-5.5/armv7a-hf/rootfs-sato-sdk\0" \
-	"nfsopts=nfsvers=3 nolock rw\0" \
-	"netdev=eth0\0" \
-	"fdt_setup=fdt addr ${fdt_addr_r};fdt resize;fdt chosen;fdt board\0"\
-	"load_fdt=tftp ${fdt_addr_r} ${fdt_file}\0" \
-	"load_kernel=tftp ${kernel_addr_r} ${kernel_file}\0" \
-	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \
-	"get_env=mw ${loadaddr} 0x00000000 0x20000;" \
-		"tftp ${loadaddr} /tftpboot/aristainetos/env.txt;" \
-		"env import -t ${loadaddr}\0" \
-	"addmisc=setenv bootargs ${bootargs} maxcpus=1 loglevel=8\0" \
-	"bootargs_defaults=setenv bootargs ${console} ${mtdoops} " \
-		"${optargs}\0" \
-	"net_args=run bootargs_defaults;setenv bootargs ${bootargs} " \
-		"root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} " \
-		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:" \
-		"${hostname}:${netdev}:off\0" \
-	"net_nfs=run load_kernel load_fdt;run net_args addmtd addmisc;" \
-		"run fdt_setup;bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-	"uboot=/tftpboot/aristainetos/u-boot.imx\0" \
-	"load_uboot=tftp ${loadaddr} ${uboot}\0" \
-	"uboot_sz=c0000\0" \
-	"upd_uboot=mw.b ${loadaddr} 0xff ${uboot_sz};" \
-		"mw.b 10200000 0x00 ${uboot_sz};" \
-		"run load_uboot;sf probe;sf erase 0 ${uboot_sz};" \
+		"run mmcargs addmtd addmisc set_fit_default;" \
+		"bootm ${fit_addr_r}\0" \
+	"mmc_load_fit=ext2load mmc ${mmcdev}:${mmcpart} ${fit_addr_r} " \
+		"${fit_file}\0" \
+	"mmc_load_uboot=ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} " \
+		"${uboot}\0" \
+	"mmc_upd_uboot=mw.b ${loadaddr} 0xff ${uboot_sz};" \
+		"setexpr cmp_buf ${loadaddr} + ${uboot_sz};" \
+		"setexpr uboot_maxsize ${uboot_sz} - 400;" \
+		"mw.b ${cmp_buf} 0x00 ${uboot_sz};" \
+		"run mmc_load_uboot;sf probe;sf erase 0 ${uboot_sz};" \
 		"sf write ${loadaddr} 400 ${filesize};" \
-		"sf read 10200000 400 ${uboot_sz};" \
-		"cmp.b ${loadaddr} 10200000 bc000\0" \
-	"ubi_prep=ubi part ubi 2048;ubifsmount ubi:kernel\0" \
-	"load_kernel_ubi=ubifsload ${kernel_addr_r} uImage\0" \
-	"load_fdt_ubi=ubifsload ${fdt_addr_r} aristainetos.dtb\0" \
-	"ubi_nfs=run ubiprep load_kernel_ubi load_fdt_ubi;" \
-		"run net_args addmtd addmisc;run fdt_setup;" \
-		"bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-	"rootfsname=rootfs\0" \
-	"ubi_args=run bootargs_defaults;setenv bootargs ${bootargs} " \
-		"ubi.mtd=0,2048 root=ubi0:${rootfsname} rootfstype=ubifs " \
-		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:" \
-		"${hostname}:${netdev}:off\0" \
-	"ubi_ubi=run ubi_prep load_kernel_ubi load_fdt_ubi;" \
-		"run bootargs_defaults ubi_args addmtd addmisc;" \
-		"run fdt_setup;bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-	"ubirootfs_file=/tftpboot/aristainetos/rootfs-minimal.ubifs\0" \
-	"upd_ubirootfs=run ubi_prep;tftp ${loadaddr} ${ubirootfs_file};" \
-		"ubi write ${loadaddr} rootfs ${filesize}\0" \
-	"ksz=800000\0" \
-	"rootsz=2000000\0" \
-	"usersz=8000000\0" \
-	"ubi_make=run ubi_prep;ubi create kernel ${ksz};" \
-		"ubi create rootfs ${rootsz};ubi create userfs ${usersz}\0"
+		"sf read ${cmp_buf} 400 ${uboot_sz};" \
+		"cmp.b ${loadaddr} ${cmp_buf} ${uboot_maxsize}\0" \
+	"ubiargs=setenv bootargs console=${console},${baudrate} " \
+		"ubi.mtd=0,2048 root=ubi0:rootfs rootfstype=ubifs\0 " \
+	"ubiboot=echo Booting from ubi ...; " \
+		"run ubiargs addmtd addmisc set_fit_default;" \
+		"bootm ${fit_addr_r}\0" \
+	"ubifs_load_fit=sf probe;ubi part ubi 2048;ubifsmount ubi:rootfs;" \
+		"ubifsload ${fit_addr_r} /boot/system.itb; " \
+		"imi ${fit_addr_r}\0 " \
+	"rescueargs=setenv bootargs console=${console},${baudrate} " \
+		"root=/dev/ram rw\0 " \
+	"rescueboot=echo Booting rescue system from NOR ...; " \
+		"run rescueargs addmtd addmisc set_fit_default;" \
+		"bootm ${fit_addr_r}\0" \
+	"rescue_load_fit=sf probe;sf read ${fit_addr_r} ${rescue_sys_addr} " \
+		"${rescue_sys_length}; imi ${fit_addr_r}\0 "
 
 #define CONFIG_BOOTCOMMAND \
 	"mmc dev ${mmcdev};" \
 	"if mmc rescan; then " \
-		"run mmcboot;" \
-	"else run ubi_ubi; fi"
+		"if run loadbootscript; then " \
+			"run bootscript; " \
+		"else " \
+			"if run mmc_load_fit; then " \
+				"run mmcboot; " \
+			"else " \
+				"if run ubifs_load_fit; then " \
+					"run ubiboot; " \
+				"else " \
+					"if run rescue_load_fit; then " \
+						"run rescueboot; " \
+					"else " \
+						"echo RESCUE SYSTEM BOOT " \
+							"FAILURE;" \
+					"fi; " \
+				"fi; " \
+			"fi; " \
+		"fi; " \
+	"else " \
+		"if run ubifs_load_fit; then " \
+			"run ubiboot; " \
+		"else " \
+			"if run rescue_load_fit; then " \
+				"run rescueboot; " \
+			"else " \
+				"echo RESCUE SYSTEM BOOT FAILURE;" \
+			"fi; " \
+		"fi; " \
+	"fi"
 
 #define CONFIG_ARP_TIMEOUT		200UL
 
@@ -227,8 +250,8 @@
 #define CONFIG_ENV_SPI_MAX_HZ		CONFIG_SF_DEFAULT_SPEED
 #define CONFIG_ENV_SPI_MODE		CONFIG_SF_DEFAULT_MODE
 #define CONFIG_ENV_SECT_SIZE		(0x010000)
-#define CONFIG_ENV_OFFSET		(0x0c0000)
-#define CONFIG_ENV_OFFSET_REDUND	(0x0d0000)
+#define CONFIG_ENV_OFFSET		(0x0d0000)
+#define CONFIG_ENV_OFFSET_REDUND	(0x0e0000)
 
 #define CONFIG_OF_LIBFDT
 
@@ -289,9 +312,6 @@
 #define CONFIG_CMD_UBI
 #define CONFIG_CMD_UBIFS
 
-#define MTDIDS_DEFAULT                  "nand0=gpmi-nand"
-#define MTDPARTS_DEFAULT                "mtdparts=gpmi-nand:-(ubi)"
-
 #define CONFIG_MTD_UBI_FASTMAP
 #define CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT	1
 
@@ -321,5 +341,4 @@
 
 #define CONFIG_PWM_IMX
 #define CONFIG_IMX6_PWM_PER_CLK	66000000
-
 #endif                         /* __ARISTAINETOS_CONFIG_H */
diff --git a/include/configs/arndale.h b/include/configs/arndale.h
index d68993b..3ad4a9b 100644
--- a/include/configs/arndale.h
+++ b/include/configs/arndale.h
@@ -51,8 +51,6 @@
 /* PMIC */
 #define CONFIG_PMIC
 #define CONFIG_POWER_I2C
-#define CONFIG_POWER_MAX77686
-
 
 #define CONFIG_PREBOOT
 
diff --git a/include/configs/at91sam9260ek.h b/include/configs/at91sam9260ek.h
index a6a80de..c4b2e16 100644
--- a/include/configs/at91sam9260ek.h
+++ b/include/configs/at91sam9260ek.h
@@ -90,7 +90,6 @@
 #define CONFIG_CMD_PING		1
 #define CONFIG_CMD_DHCP		1
 #define CONFIG_CMD_NAND		1
-#define CONFIG_CMD_MMC
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_USB		1
 
@@ -133,14 +132,17 @@
 # define CONFIG_MACH_TYPE MACH_TYPE_AT91SAM9260EK
 #endif
 
-/* DataFlash */
 #ifndef CONFIG_AT91SAM9G20EK_2MMC
+/* DataFlash */
 #define CONFIG_ATMEL_DATAFLASH_SPI
 #define CONFIG_HAS_DATAFLASH		1
 #define CONFIG_SYS_MAX_DATAFLASH_BANKS		2
 #define CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS0	0xC0000000	/* CS0 */
 #define CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1	0xD0000000	/* CS1 */
 #define AT91_SPI_CLK			15000000
+#else
+/* Enable MMC. The MCCK is conflicted with DataFlash */
+#define CONFIG_CMD_MMC
 #endif
 
 #ifdef CONFIG_AT91SAM9G20EK
diff --git a/include/configs/at91sam9x5ek.h b/include/configs/at91sam9x5ek.h
index b1d4baa..6d8b71d 100644
--- a/include/configs/at91sam9x5ek.h
+++ b/include/configs/at91sam9x5ek.h
@@ -203,11 +203,12 @@
 				"bootm 0x22000000"
 #else /* CONFIG_SYS_USE_MMC */
 /* bootstrap + u-boot + env + linux in mmc */
-#define CONFIG_ENV_IS_IN_MMC
-/* For FAT system, most cases it should be in the reserved sector */
-#define CONFIG_ENV_OFFSET	0x2000
-#define CONFIG_ENV_SIZE		0x1000
-#define CONFIG_SYS_MMC_ENV_DEV	0
+#define CONFIG_ENV_IS_IN_FAT
+#define CONFIG_FAT_WRITE
+#define FAT_ENV_INTERFACE	"mmc"
+#define FAT_ENV_FILE		"uboot.env"
+#define FAT_ENV_DEVICE_AND_PART "0"
+#define CONFIG_ENV_SIZE		0x4000
 #endif
 
 #ifdef CONFIG_SYS_USE_MMC
diff --git a/include/configs/atngw100.h b/include/configs/atngw100.h
index 9c81e31..540e86a 100644
--- a/include/configs/atngw100.h
+++ b/include/configs/atngw100.h
@@ -143,7 +143,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN			(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/atngw100mkii.h b/include/configs/atngw100mkii.h
index 7b4f9cf..35eae76 100644
--- a/include/configs/atngw100mkii.h
+++ b/include/configs/atngw100mkii.h
@@ -164,7 +164,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN		(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN	(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR		(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/atstk1002.h b/include/configs/atstk1002.h
index 8f3fd0b..a9c064a 100644
--- a/include/configs/atstk1002.h
+++ b/include/configs/atstk1002.h
@@ -104,6 +104,10 @@
 #define CONFIG_BOOTP_SUBNETMASK
 #define CONFIG_BOOTP_GATEWAY
 
+/* generic board */
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
 
 /*
  * Command line configuration.
@@ -158,7 +162,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN			(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/atstk1006.h b/include/configs/atstk1006.h
index bbe0aea..25090a6 100644
--- a/include/configs/atstk1006.h
+++ b/include/configs/atstk1006.h
@@ -159,7 +159,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN			(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/axs101.h b/include/configs/axs101.h
index c61ddd6..5fb8aca 100644
--- a/include/configs/axs101.h
+++ b/include/configs/axs101.h
@@ -10,22 +10,8 @@
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER		3
-#define CONFIG_SYS_CACHELINE_SIZE	32
 #define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_CLK_FREQ
 
-/* NAND controller DMA doesn't work correctly with D$ enabled */
-#define CONFIG_SYS_DCACHE_OFF
-
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
 #define ARC_FPGA_PERIPHERAL_BASE	0xE0000000
 #define ARC_APB_PERIPHERAL_BASE		0xF0000000
 #define ARC_DWMMC_BASE			(ARC_FPGA_PERIPHERAL_BASE + 0x15000)
@@ -34,7 +20,6 @@
 /*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE		0x81000000
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
diff --git a/include/configs/bct-brettl2.h b/include/configs/bct-brettl2.h
index 39982ef..2e0e922 100644
--- a/include/configs/bct-brettl2.h
+++ b/include/configs/bct-brettl2.h
@@ -97,7 +97,7 @@
 #define CONFIG_ENV_IS_IN_FLASH 1
 #define CONFIG_ENV_OFFSET	0x4000
 #define CONFIG_ENV_SIZE		0x2000
-#define CONFIG_ENV_SECT_SIZE	0x10000
+#define CONFIG_ENV_SECT_SIZE	0x12000
 
 #if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS)
 #define ENV_IS_EMBEDDED
diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h
index 8eeb15c..7a1499d 100644
--- a/include/configs/canyonlands.h
+++ b/include/configs/canyonlands.h
@@ -11,6 +11,10 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#include <linux/kconfig.h>
+
+#define CONFIG_SYS_GENERIC_BOARD
+
 /*-----------------------------------------------------------------------
  * High Level Configuration Options
  *----------------------------------------------------------------------*/
@@ -19,10 +23,10 @@
  * and Arches dual (460GT)
  */
 #ifdef CONFIG_CANYONLANDS
-#define CONFIG_460EX		1	/* Specific PPC460EX		*/
+#define CONFIG_460EX			/* Specific PPC460EX		*/
 #define CONFIG_HOSTNAME		canyonlands
 #else
-#define CONFIG_460GT		1	/* Specific PPC460GT		*/
+#define CONFIG_460GT			/* Specific PPC460GT		*/
 #ifdef CONFIG_GLACIER
 #define CONFIG_HOSTNAME		glacier
 #else
@@ -32,7 +36,7 @@
 #endif
 #endif
 
-#define CONFIG_440		1
+#define CONFIG_440
 
 #ifndef CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_TEXT_BASE	0xFFF80000
@@ -45,10 +49,10 @@
 
 #define CONFIG_SYS_CLK_FREQ	66666667	/* external freq to pll	*/
 
-#define CONFIG_BOARD_EARLY_INIT_F	1	/* Call board_early_init_f */
-#define CONFIG_BOARD_EARLY_INIT_R	1	/* Call board_early_init_r */
-#define CONFIG_MISC_INIT_R		1	/* Call misc_init_r */
-#define CONFIG_BOARD_TYPES		1	/* support board types */
+#define CONFIG_BOARD_EARLY_INIT_F		/* Call board_early_init_f */
+#define CONFIG_BOARD_EARLY_INIT_R		/* Call board_early_init_r */
+#define CONFIG_MISC_INIT_R			/* Call misc_init_r */
+#define CONFIG_BOARD_TYPES			/* support board types */
 
 /*-----------------------------------------------------------------------
  * Base addresses -- Note these are effective addresses where the
@@ -134,7 +138,7 @@
  *----------------------------------------------------------------------*/
 #define CONFIG_SYS_FLASH_CFI			/* The flash is CFI compatible	*/
 #define CONFIG_FLASH_CFI_DRIVER		/* Use common CFI driver	*/
-#define CONFIG_SYS_FLASH_CFI_AMD_RESET	1	/* Use AMD (Spansion) reset cmd */
+#define CONFIG_SYS_FLASH_CFI_AMD_RESET	/* Use AMD (Spansion) reset cmd */
 
 #define CONFIG_SYS_FLASH_BANKS_LIST    {CONFIG_SYS_FLASH_BASE}
 #define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of memory banks		*/
@@ -172,9 +176,9 @@
  * I2C SPD DIMM autodetection/calibration doesn't fit into the 4k of boot
  * code.
  */
-#define CONFIG_SPD_EEPROM	1	/* Use SPD EEPROM for setup	*/
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for setup	*/
 #define SPD_EEPROM_ADDRESS	{0x50, 0x51}	/* SPD i2c spd addresses*/
-#define CONFIG_DDR_ECC		1	/* with ECC support		*/
+#define CONFIG_DDR_ECC			/* with ECC support		*/
 #define CONFIG_DDR_RQDC_FIXED	0x80000038 /* fixed value for RQDC	*/
 
 #else /* defined(CONFIG_ARCHES) */
@@ -262,8 +266,8 @@
 #define CONFIG_4xx_CONFIG_BLOCKSIZE		16
 
 /* I2C SYSMON (LM75, AD7414 is almost compatible)			*/
-#define CONFIG_DTT_LM75		1		/* ON Semi's LM75	*/
-#define CONFIG_DTT_AD7414	1		/* use AD7414		*/
+#define CONFIG_DTT_LM75				/* ON Semi's LM75	*/
+#define CONFIG_DTT_AD7414			/* use AD7414		*/
 #define CONFIG_DTT_SENSORS	{0}		/* Sensor addresses	*/
 #define CONFIG_SYS_DTT_MAX_TEMP	70
 #define CONFIG_SYS_DTT_LOW_TEMP	-30
@@ -275,14 +279,14 @@
 
 #if !defined(CONFIG_ARCHES)
 /* RTC configuration */
-#define CONFIG_RTC_M41T62	1
+#define CONFIG_RTC_M41T62
 #define CONFIG_SYS_I2C_RTC_ADDR	0x68
 #endif
 
 /*-----------------------------------------------------------------------
  * Ethernet
  *----------------------------------------------------------------------*/
-#define CONFIG_IBM_EMAC4_V4	1
+#define CONFIG_IBM_EMAC4_V4
 
 #define CONFIG_HAS_ETH0
 #define CONFIG_HAS_ETH1
@@ -322,9 +326,9 @@
 #define CONFIG_GPCS_PHY2_ADDR   0xC
 #endif	/* !defined(CONFIG_ARCHES) */
 
-#define CONFIG_PHY_RESET	1	/* reset phy upon startup	*/
-#define CONFIG_PHY_GIGE		1	/* Include GbE speed/duplex detection */
-#define CONFIG_PHY_DYNAMIC_ANEG	1
+#define CONFIG_PHY_RESET		/* reset phy upon startup	*/
+#define CONFIG_PHY_GIGE			/* Include GbE speed/duplex detection */
+#define CONFIG_PHY_DYNAMIC_ANEG
 
 /*-----------------------------------------------------------------------
  * USB-OHCI
diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h
index f7277eb..4207504 100644
--- a/include/configs/cm_fx6.h
+++ b/include/configs/cm_fx6.h
@@ -21,14 +21,7 @@
 #define CONFIG_MACH_TYPE		4273
 
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-
-#define CONFIG_DM_GPIO
 #define CONFIG_CMD_GPIO
-
-#define CONFIG_DM_SERIAL
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 #endif
 
 /* Display information on boot */
@@ -103,97 +96,98 @@
 #define CONFIG_ENV_OFFSET		(768 * 1024)
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
-	"kernel=uImage-cm-fx6\0" \
+	"stdin=serial,usbkbd\0" \
+	"stdout=serial,vga\0" \
+	"stderr=serial,vga\0" \
+	"panel=HDMI\0" \
 	"autoload=no\0" \
+	"kernel=uImage-cm-fx6\0" \
+	"script=boot.scr\0" \
+	"dtb=cm-fx6.dtb\0" \
+	"bootm_low=18000000\0" \
 	"loadaddr=0x10800000\0" \
 	"fdtaddr=0x11000000\0" \
 	"console=ttymxc3,115200\0" \
 	"ethprime=FEC0\0" \
-	"bootscr=boot.scr\0" \
-	"bootm_low=18000000\0" \
 	"video_hdmi=mxcfb0:dev=hdmi,1920x1080M-32@50,if=RGB32\0" \
 	"video_dvi=mxcfb0:dev=dvi,1280x800M-32@50,if=RGB32\0" \
-	"fdtfile=cm-fx6.dtb\0" \
 	"doboot=bootm ${loadaddr}\0" \
-	"loadfdt=false\0" \
+	"doloadfdt=false\0" \
 	"setboottypez=setenv kernel zImage-cm-fx6;" \
 		"setenv doboot bootz ${loadaddr} - ${fdtaddr};" \
-		"setenv loadfdt true;\0" \
+		"setenv doloadfdt true;\0" \
 	"setboottypem=setenv kernel uImage-cm-fx6;" \
 		"setenv doboot bootm ${loadaddr};" \
-		"setenv loadfdt false;\0"\
-	"run_eboot=echo Starting EBOOT ...; "\
-		"mmc dev ${mmcdev} && " \
-		"mmc rescan && mmc read 10042000 a 400 && go 10042000\0" \
-	"mmcdev=2\0" \
+		"setenv doloadfdt false;\0"\
 	"mmcroot=/dev/mmcblk0p2 rw rootwait\0" \
-	"loadmmcbootscript=load mmc ${mmcdev} ${loadaddr} ${bootscr}\0" \
-	"mmcbootscript=echo Running bootscript from mmc ...; "\
-		"source ${loadaddr}\0" \
-	"mmcargs=setenv bootargs console=${console} " \
-		"root=${mmcroot} " \
-		"${video}\0" \
-	"mmcloadkernel=load mmc ${mmcdev} ${loadaddr} ${kernel}\0" \
-	"mmcloadfdt=load mmc ${mmcdev} ${fdtaddr} ${fdtfile}\0" \
-	"mmcboot=echo Booting from mmc ...; " \
-		"run mmcargs; " \
-		"run doboot\0" \
-	"satadev=0\0" \
 	"sataroot=/dev/sda2 rw rootwait\0" \
-	"sataargs=setenv bootargs console=${console} " \
-		"root=${sataroot} " \
-		"${video}\0" \
-	"loadsatabootscript=load sata ${satadev} ${loadaddr} ${bootscr}\0" \
-	"satabootscript=echo Running bootscript from sata ...; " \
-		"source ${loadaddr}\0" \
-	"sataloadkernel=load sata ${satadev} ${loadaddr} ${kernel}\0" \
-	"sataloadfdt=load sata ${satadev} ${fdtaddr} ${fdtfile}\0" \
-	"sataboot=echo Booting from sata ...; "\
-		"run sataargs; " \
-		"run doboot\0" \
 	"nandroot=/dev/mtdblock4 rw\0" \
 	"nandrootfstype=ubifs\0" \
+	"mmcargs=setenv bootargs console=${console} root=${mmcroot} " \
+		"${video}\0" \
+	"sataargs=setenv bootargs console=${console} root=${sataroot} " \
+		"${video}\0" \
 	"nandargs=setenv bootargs console=${console} " \
 		"root=${nandroot} " \
 		"rootfstype=${nandrootfstype} " \
 		"${video}\0" \
-	"nandloadfdt=nand read ${fdtaddr} 780000 80000;\0" \
-	"nandboot=echo Booting from nand ...; " \
-		"run nandargs; " \
-		"nand read ${loadaddr} 0 780000; " \
-		"if ${loadfdt}; then " \
+	"nandboot=if run nandloadkernel; then " \
 			"run nandloadfdt;" \
-		"fi; " \
-		"run doboot\0" \
-	"boot=mmc dev ${mmcdev}; " \
-		"if mmc rescan; then " \
-			"if run loadmmcbootscript; then " \
-				"run mmcbootscript;" \
-			"else " \
-				"if run mmcloadkernel; then " \
-					"if ${loadfdt}; then " \
-						"run mmcloadfdt;" \
-					"fi;" \
-					"run mmcboot;" \
-				"fi;" \
-			"fi;" \
+			"run setboottypem;" \
+			"run storagebootcmd;" \
+			"run setboottypez;" \
+			"run storagebootcmd;" \
+		"fi;\0" \
+	"run_eboot=echo Starting EBOOT ...; "\
+		"mmc dev 2 && " \
+		"mmc rescan && mmc read 10042000 a 400 && go 10042000\0" \
+	"loadscript=load ${storagetype} ${storagedev} ${loadaddr} ${script};\0"\
+	"loadkernel=load ${storagetype} ${storagedev} ${loadaddr} ${kernel};\0"\
+	"loadfdt=load ${storagetype} ${storagedev} ${fdtaddr} ${dtb};\0" \
+	"bootscript=echo Running bootscript from ${storagetype} ...;" \
+		   "source ${loadaddr};\0" \
+	"nandloadkernel=nand read ${loadaddr} 0 780000;\0" \
+	"nandloadfdt=nand read ${fdtaddr} 780000 80000;\0" \
+	"setupmmcboot=setenv storagetype mmc; setenv storagedev 2;\0" \
+	"setupsataboot=setenv storagetype sata; setenv storagedev 0;\0" \
+	"setupnandboot=setenv storagetype nand;\0" \
+	"setupusbboot=setenv storagetype usb; setenv storagedev 0;\0" \
+	"storagebootcmd=echo Booting from ${storagetype} ...;" \
+			"run ${storagetype}args; run doboot;\0" \
+	"trybootk=if run loadkernel; then " \
+		"if ${doloadfdt}; then " \
+			"run loadfdt;" \
 		"fi;" \
-		"if sata init; then " \
-			"if run loadsatabootscript; then " \
-				"run satabootscript;" \
-			"else "\
-				"if run sataloadkernel; then " \
-					"if ${loadfdt}; then " \
-						"run sataloadfdt; " \
-					"fi;" \
-					"run sataboot;" \
-				"fi;" \
-			"fi;" \
+		"run storagebootcmd;" \
+		"fi;\0" \
+	"trybootsmz=if run loadscript; then " \
+			"run bootscript;" \
 		"fi;" \
-		"run nandboot\0"
+		"run setboottypem;" \
+		"run trybootk;" \
+		"run setboottypez;" \
+		"run trybootk;\0"
 
 #define CONFIG_BOOTCOMMAND \
-	"run setboottypem; run boot"
+	"run setupmmcboot;" \
+	"mmc dev ${storagedev};" \
+	"if mmc rescan; then " \
+		"run trybootsmz;" \
+	"fi;" \
+	"run setupusbboot;" \
+	"if usb start; then "\
+		"if run loadscript; then " \
+			"run bootscript;" \
+		"fi;" \
+	"fi;" \
+	"run setupsataboot;" \
+	"if sata init; then " \
+		"run trybootsmz;" \
+	"fi;" \
+	"run setupnandboot;" \
+	"run nandboot;"
+
+#define CONFIG_PREBOOT		"usb start"
 
 /* SPI */
 #define CONFIG_SPI
@@ -243,6 +237,9 @@
 #define CONFIG_MXC_USB_FLAGS		0
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET	/* For OTG port */
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP
+#define CONFIG_SYS_STDIO_DEREGISTER
 
 /* I2C */
 #define CONFIG_CMD_I2C
@@ -281,7 +278,7 @@
 /* misc */
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_STACKSIZE			(128 * 1024)
-#define CONFIG_SYS_MALLOC_LEN			(2 * 1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN			(10 * 1024 * 1024)
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	800 /* 400 KB */
 #define CONFIG_OF_BOARD_SETUP
 
@@ -296,4 +293,24 @@
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	(64 * 1024)
 #define CONFIG_SPL_SPI_LOAD
 
+/* Display */
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_IPUV3
+#define CONFIG_IPUV3_CLK          260000000
+#define CONFIG_IMX_HDMI
+#define CONFIG_IMX_VIDEO_SKIP
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_VIDEO_SW_CURSOR
+
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SOURCE
+#define CONFIG_CMD_BMP
+#define CONFIG_VIDEO_BMP_RLE8
+
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_BMP_LOGO
+
 #endif	/* __CONFIG_CM_FX6_H */
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h
index 9767512..b2a9f35 100644
--- a/include/configs/cm_t35.h
+++ b/include/configs/cm_t35.h
@@ -310,6 +310,7 @@
 
 #define CONFIG_LCD
 #define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SOURCE
 #define CONFIG_CMD_BMP
 #define CONFIG_BMP_16BPP
 #define CONFIG_SCF0403_LCD
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
index cb03e33..1683a15 100644
--- a/include/configs/db-mv784mp-gp.h
+++ b/include/configs/db-mv784mp-gp.h
@@ -11,6 +11,8 @@
  * High Level Configuration Options (easy to change)
  */
 #define CONFIG_ARMADA_XP		/* SOC Family Name */
+#define CONFIG_DB_784MP_GP		/* Board target name for DDR training */
+
 #define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_DISPLAY_BOARDINFO_LATE
@@ -65,4 +67,51 @@
  */
 #include "mv-common.h"
 
+/*
+ * Memory layout while starting into the bin_hdr via the
+ * BootROM:
+ *
+ * 0x4000.4000 - 0x4003.4000	headers space (192KiB)
+ * 0x4000.4030			bin_hdr start address
+ * 0x4003.4000 - 0x4004.7c00	BootROM memory allocations (15KiB)
+ * 0x4007.fffc			BootROM stack top
+ *
+ * The address space between 0x4007.fffc and 0x400f.fff is not locked in
+ * L2 cache thus cannot be used.
+ */
+
+/* SPL */
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x40004030
+#define CONFIG_SPL_MAX_SIZE		((128 << 10) - 0x4030)
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + (128 << 10))
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR + \
+					 CONFIG_SPL_BSS_MAX_SIZE)
+#define CONFIG_SYS_SPL_MALLOC_SIZE	(16 << 10)
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_LDSCRIPT		"arch/arm/mvebu-common/u-boot-spl.lds"
+
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS		0
+#define CONFIG_SPL_SPI_CS		0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+
+/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
+#define CONFIG_SYS_MVEBU_DDR
+#define CONFIG_SPD_EEPROM		0x4e
+
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
diff --git a/include/configs/exynos-common.h b/include/configs/exynos-common.h
index 1f3ee55..59676ae 100644
--- a/include/configs/exynos-common.h
+++ b/include/configs/exynos-common.h
@@ -17,12 +17,6 @@
 #include <linux/sizes.h>
 
 #define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
-#define CONFIG_DM_SPI
-#define CONFIG_DM_SPI_FLASH
 
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_DISPLAY_CPUINFO
@@ -42,7 +36,6 @@
 #define CONFIG_ENV_OVERWRITE
 
 /* Size of malloc() pool before and after relocation */
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (80 << 20))
 
 /* select serial console configuration */
diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h
index ad63f3c..3ab8d55 100644
--- a/include/configs/exynos5-common.h
+++ b/include/configs/exynos5-common.h
@@ -126,12 +126,13 @@
 #define SPI_FLASH_UBOOT_POS	(CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
 
 /* I2C */
-#define CONFIG_SYS_I2C_INIT_BOARD
-#define CONFIG_SYS_I2C
+
+/* TODO(sjg@chromium.org): Move these two options to Kconfig */
+#define CONFIG_DM_I2C
+#define CONFIG_DM_I2C_COMPAT
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C_S3C24X0_SPEED	100000		/* 100 Kbps */
 #define CONFIG_SYS_I2C_S3C24X0
-#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_SYS_I2C_S3C24X0_SPEED	100000		/* 100 Kbps */
 #define CONFIG_SYS_I2C_S3C24X0_SLAVE    0x0
 #define CONFIG_I2C_EDID
 
diff --git a/include/configs/exynos5-dt-common.h b/include/configs/exynos5-dt-common.h
index 9cef0b0..b1b8e1a 100644
--- a/include/configs/exynos5-dt-common.h
+++ b/include/configs/exynos5-dt-common.h
@@ -24,9 +24,6 @@
 #define CONFIG_POWER_TPS65090
 
 /* Enable keyboard */
-#define CONFIG_CROS_EC		/* CROS_EC protocol */
-#define CONFIG_CROS_EC_KEYB	/* CROS_EC keyboard input */
-#define CONFIG_CMD_CROS_EC
 #define CONFIG_KEYBOARD
 
 #endif
diff --git a/include/configs/exynos5250-common.h b/include/configs/exynos5250-common.h
index 6714313..ae0e5ff 100644
--- a/include/configs/exynos5250-common.h
+++ b/include/configs/exynos5250-common.h
@@ -28,9 +28,6 @@
 
 #define CONFIG_SYS_INIT_SP_ADDR	CONFIG_IRAM_STACK
 
-/* PMIC */
-#define CONFIG_POWER_MAX77686
-
 /* Sound */
 #define CONFIG_CMD_SOUND
 #ifdef CONFIG_CMD_SOUND
diff --git a/include/configs/favr-32-ezkit.h b/include/configs/favr-32-ezkit.h
index 338d3dc..75bff4c 100644
--- a/include/configs/favr-32-ezkit.h
+++ b/include/configs/favr-32-ezkit.h
@@ -162,7 +162,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN			(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/galileo.h b/include/configs/galileo.h
new file mode 100644
index 0000000..d745f4e
--- /dev/null
+++ b/include/configs/galileo.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN		(1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_NR_DRAM_BANKS		1
+
+#define CONFIG_X86_SERIAL
+
+/* ns16550 UART is memory-mapped in Quark SoC */
+#undef  CONFIG_SYS_NS16550_PORT_MAPPED
+
+#define CONFIG_PCI_MEM_BUS		0x90000000
+#define CONFIG_PCI_MEM_PHYS		CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE		0x20000000
+
+#define CONFIG_PCI_PREF_BUS		0xb0000000
+#define CONFIG_PCI_PREF_PHYS		CONFIG_PCI_PREF_BUS
+#define CONFIG_PCI_PREF_SIZE		0x20000000
+
+#define CONFIG_PCI_IO_BUS		0x2000
+#define CONFIG_PCI_IO_PHYS		CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE		0xe000
+
+#define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_PCI_PNP
+
+#define CONFIG_STD_DEVICES_SETTINGS	"stdin=serial\0" \
+					"stdout=serial\0" \
+					"stderr=serial\0"
+
+/* SATA is not supported in Quark SoC */
+#undef CONFIG_SCSI_AHCI
+#undef CONFIG_CMD_SCSI
+
+/* Video is not supported in Quark SoC */
+#undef CONFIG_VIDEO
+#undef CONFIG_CFB_CONSOLE
+
+/* SD/MMC support */
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC_SDMA
+#define CONFIG_CMD_MMC
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/grasshopper.h b/include/configs/grasshopper.h
index 73534ad..54eb977 100644
--- a/include/configs/grasshopper.h
+++ b/include/configs/grasshopper.h
@@ -62,6 +62,10 @@
 #define CONFIG_USART_BASE		ATMEL_BASE_USART1
 #define CONFIG_USART_ID			1
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
+
 /* User serviceable stuff */
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
@@ -151,7 +155,6 @@
 					 CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN		(256*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN	(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR		(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
index 4f137fc..620f950 100644
--- a/include/configs/gw_ventana.h
+++ b/include/configs/gw_ventana.h
@@ -39,7 +39,6 @@
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(10 * 1024 * 1024)
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 
 /* Init Functions */
 #define CONFIG_BOARD_EARLY_INIT_F
diff --git a/include/configs/hammerhead.h b/include/configs/hammerhead.h
index 4f0603a..0bc42f1 100644
--- a/include/configs/hammerhead.h
+++ b/include/configs/hammerhead.h
@@ -137,7 +137,6 @@
 
 #define CONFIG_SYS_MALLOC_LEN			(256*1024)
 
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(CONFIG_SYS_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/ibf-dsp561.h b/include/configs/ibf-dsp561.h
index ac5ca9a..2a937c6 100644
--- a/include/configs/ibf-dsp561.h
+++ b/include/configs/ibf-dsp561.h
@@ -82,7 +82,7 @@
 #define CONFIG_ENV_OFFSET		0x4000
 #define CONFIG_ENV_ADDR		(CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
 #define CONFIG_ENV_SIZE		0x2000
-#define CONFIG_ENV_SECT_SIZE	0x10000	/* Total Size of Environment Sector */
+#define CONFIG_ENV_SECT_SIZE	0x12000	/* Total Size of Environment Sector */
 #if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS)
 #define ENV_IS_EMBEDDED
 #else
diff --git a/include/configs/ids8313.h b/include/configs/ids8313.h
index f084834..2384864 100644
--- a/include/configs/ids8313.h
+++ b/include/configs/ids8313.h
@@ -575,12 +575,9 @@
 
 #define CONFIG_VERSION_VARIABLE
 
-#define CONFIG_FIT
-#define CONFIG_FIT_SIGNATURE
 #define CONFIG_IMAGE_FORMAT_LEGACY
 #define CONFIG_CMD_FDT
 #define CONFIG_CMD_HASH
-#define CONFIG_RSA
 #define CONFIG_SHA1
 #define CONFIG_SHA256
 
diff --git a/include/configs/imx6_spl.h b/include/configs/imx6_spl.h
index 1b9c277..21c5dce 100644
--- a/include/configs/imx6_spl.h
+++ b/include/configs/imx6_spl.h
@@ -61,11 +61,19 @@
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #endif
 
+#if defined(CONFIG_MX6SX)
+#define CONFIG_SPL_BSS_START_ADDR      0x88200000
+#define CONFIG_SPL_BSS_MAX_SIZE        0x100000        /* 1 MB */
+#define CONFIG_SYS_SPL_MALLOC_START    0x88300000
+#define CONFIG_SYS_SPL_MALLOC_SIZE     0x3200000       /* 50 MB */
+#define CONFIG_SYS_TEXT_BASE           0x87800000
+#else
 #define CONFIG_SPL_BSS_START_ADDR	0x18200000
 #define CONFIG_SPL_BSS_MAX_SIZE		0x100000	/* 1 MB */
 #define CONFIG_SYS_SPL_MALLOC_START	0x18300000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x3200000	/* 50 MB */
 #define CONFIG_SYS_TEXT_BASE		0x17800000
 #endif
+#endif
 
 #endif
diff --git a/include/configs/ip04.h b/include/configs/ip04.h
index ec510bd..2ee215f 100644
--- a/include/configs/ip04.h
+++ b/include/configs/ip04.h
@@ -61,7 +61,7 @@
 #define CONFIG_EBIU_AMBCTL0_VAL	0xffc2ffc2
 #define CONFIG_EBIU_AMBCTL1_VAL	0xffc2ffc2
 
-#define CONFIG_SYS_MONITOR_LEN		(256 * 1024)
+#define CONFIG_SYS_MONITOR_LEN		(384 * 1024)
 #define CONFIG_SYS_MALLOC_LEN		(128 * 1024)
 
 
diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
index f780f8b..2ed0855 100644
--- a/include/configs/km/km_arm.h
+++ b/include/configs/km/km_arm.h
@@ -195,7 +195,7 @@
 				}
 
 #ifndef __ASSEMBLY__
-#include <asm/arch-kirkwood/gpio.h>
+#include <asm/arch/gpio.h>
 extern void __set_direction(unsigned pin, int high);
 void set_sda(int state);
 void set_scl(int state);
diff --git a/include/configs/km82xx.h b/include/configs/km82xx.h
index 14fd290..12f9d42 100644
--- a/include/configs/km82xx.h
+++ b/include/configs/km82xx.h
@@ -34,6 +34,8 @@
 
 #define	CONFIG_SYS_TEXT_BASE	0xFE000000
 
+#define CONFIG_MISC_INIT_R
+
 /* include common defines/options for all Keymile boards */
 #include "km/keymile-common.h"
 #include "km/km-powerpc.h"
diff --git a/include/configs/lsxl.h b/include/configs/lsxl.h
index a14bfe3..c354c29 100644
--- a/include/configs/lsxl.h
+++ b/include/configs/lsxl.h
@@ -56,6 +56,7 @@
  * Commands configuration
  */
 #include <config_cmd_default.h>
+#define CONFIG_CMD_BOOTZ
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_ELF
 #define CONFIG_CMD_ENV
@@ -78,6 +79,9 @@
  */
 #include "mv-common.h"
 
+/* loading initramfs images without uimage header */
+#define CONFIG_SUPPORT_RAW_INITRD
+
 /* ST M25P40 */
 #undef CONFIG_SPI_FLASH_MACRONIX
 #define CONFIG_SPI_FLASH_STMICRO
@@ -125,27 +129,31 @@
 	"hdpart=0:1\0"							\
 	"kernel_addr=0x00800000\0"					\
 	"ramdisk_addr=0x01000000\0"					\
-	"fdt_addr=0x01ff0000\0"						\
+	"fdt_addr=0x00ff0000\0"						\
 	"bootcmd_legacy=ide reset "					\
-		"&& load ide ${hdpart} 0x00100000 /uImage.buffalo "	\
-		"&& load ide ${hdpart} 0x00800000 /initrd.buffalo "	\
-		"&& bootm 0x00100000 0x00800000\0"			\
-	"bootcmd_net=bootp ${kernel_addr} uImage "			\
-		"&& tftpboot ${ramdisk_addr} uInitrd "			\
+		"&& load ide ${hdpart} ${kernel_addr} /uImage.buffalo "	\
+		"&& load ide ${hdpart} ${ramdisk_addr} /initrd.buffalo "\
+		"&& bootm ${kernel_addr} ${ramdisk_addr}\0"		\
+	"bootcmd_net=bootp ${kernel_addr} vmlinuz "			\
+		"&& tftpboot ${ramdisk_addr} initrd.img "		\
+		"&& setenv ramdisk_len ${filesize} "			\
 		"&& tftpboot ${fdt_addr} " CONFIG_FDTFILE " "		\
-		"&& bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}\0"	\
+		"&& bootz ${kernel_addr} "				\
+			"${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0"	\
 	"bootcmd_hdd=ide reset "					\
-		"&& load ide ${hdpart} ${kernel_addr} /uImage "		\
-		"&& load ide ${hdpart} ${ramdisk_addr} /uInitrd "	\
-		"&& load ide ${hdpart} ${fdt_addr} "			\
-			"/" CONFIG_FDTFILE " "				\
-		"&& bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}\0"	\
+		"&& load ide ${hdpart} ${kernel_addr} /vmlinuz "	\
+		"&& load ide ${hdpart} ${ramdisk_addr} /initrd.img "	\
+		"&& setenv ramdisk_len ${filesize} "			\
+		"&& load ide ${hdpart} ${fdt_addr} /dtb "		\
+		"&& bootz ${kernel_addr} "				\
+			"${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0"	\
 	"bootcmd_usb=usb start "					\
-		"&& load usb 0:1 ${kernel_addr} /uImage "		\
-		"&& load usb 0:1 ${ramdisk_addr} /uInitrd "		\
-		"&& load usb 0:1 ${fdt_addr} "				\
-			"/" CONFIG_FDTFILE " "				\
-		"&& bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}\0"	\
+		"&& load usb 0:1 ${kernel_addr} /vmlinuz "		\
+		"&& load usb 0:1 ${ramdisk_addr} /initrd.img "		\
+		"&& setenv ramdisk_len ${filesize} "			\
+		"&& load usb 0:1 ${fdt_addr} " CONFIG_FDTFILE " "	\
+		"&& bootz ${kernel_addr} "				\
+			"${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0"	\
 	"bootcmd_rescue=run config_nc_dhcp; run nc\0"			\
 	"eraseenv=sf probe 0 "						\
 		"&& sf erase " __stringify(CONFIG_ENV_OFFSET)		\
diff --git a/include/configs/malta.h b/include/configs/malta.h
index 684d249..354672e 100644
--- a/include/configs/malta.h
+++ b/include/configs/malta.h
@@ -71,6 +71,7 @@
 					 sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_MAXARGS		16
 
+#define CONFIG_SYS_HUSH_PARSER
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 
@@ -107,6 +108,16 @@
 	(CONFIG_SYS_FLASH_BASE + (4 << 20) - CONFIG_ENV_SIZE)
 
 /*
+ * IDE/ATA
+ */
+#define CONFIG_SYS_IDE_MAXBUS		1
+#define CONFIG_SYS_IDE_MAXDEVICE	2
+#define CONFIG_SYS_ATA_BASE_ADDR	CONFIG_SYS_ISA_IO_BASE_ADDRESS
+#define CONFIG_SYS_ATA_IDE0_OFFSET	0x01f0
+#define CONFIG_SYS_ATA_DATA_OFFSET	0
+#define CONFIG_SYS_ATA_REG_OFFSET	0
+
+/*
  * Commands
  */
 #include <config_cmd_default.h>
@@ -118,6 +129,8 @@
 
 #define CONFIG_CMD_DATE
 #define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_IDE
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_PING
 
diff --git a/include/configs/maxbcm.h b/include/configs/maxbcm.h
index 72217bd..5999d60 100644
--- a/include/configs/maxbcm.h
+++ b/include/configs/maxbcm.h
@@ -43,6 +43,8 @@
 #define CONFIG_SF_DEFAULT_SPEED		1000000
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
 #define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_SPI_FLASH_BAR
 
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_IS_IN_SPI_FLASH
@@ -65,4 +67,51 @@
  */
 #include "mv-common.h"
 
+/*
+ * Memory layout while starting into the bin_hdr via the
+ * BootROM:
+ *
+ * 0x4000.4000 - 0x4003.4000	headers space (192KiB)
+ * 0x4000.4030			bin_hdr start address
+ * 0x4003.4000 - 0x4004.7c00	BootROM memory allocations (15KiB)
+ * 0x4007.fffc			BootROM stack top
+ *
+ * The address space between 0x4007.fffc and 0x400f.fff is not locked in
+ * L2 cache thus cannot be used.
+ */
+
+/* SPL */
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x40004030
+#define CONFIG_SPL_MAX_SIZE		((128 << 10) - 0x4030)
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + (128 << 10))
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR + \
+					 CONFIG_SPL_BSS_MAX_SIZE)
+#define CONFIG_SYS_SPL_MALLOC_SIZE	(16 << 10)
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_LDSCRIPT		"arch/arm/mvebu-common/u-boot-spl.lds"
+
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS		0
+#define CONFIG_SPL_SPI_CS		0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+
+/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
+#define CONFIG_SYS_MVEBU_DDR
+#define CONFIG_DDR_FIXED_SIZE		(1 << 20)	/* 1GiB */
+
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index bb07060..166ab4f 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -106,62 +106,22 @@
 # define CONFIG_XILINX_TB_WATCHDOG
 #endif
 
-/*
- * memory layout - Example
- * CONFIG_SYS_TEXT_BASE = 0x1200_0000;	defined in config.mk
- * CONFIG_SYS_SRAM_BASE = 0x1000_0000;
- * CONFIG_SYS_SRAM_SIZE = 0x0400_0000;	64MB
- *
- * CONFIG_SYS_MONITOR_LEN = 0x40000
- * CONFIG_SYS_MALLOC_LEN = 3 * CONFIG_SYS_MONITOR_LEN = 0xC0000
- *
- * CONFIG_SYS_GBL_DATA_OFFSET = 0x1000_0000 + 0x0400_0000 - 0x1000 = 0x13FF_F000
- * CONFIG_SYS_MONITOR_BASE = 0x13FF_F000 - CONFIG_SYS_MONITOR_LEN = 0x13FB_F000
- * CONFIG_SYS_MALLOC_BASE = 0x13FB_F000 - CONFIG_SYS_MALLOC_LEN = 0x13EF_F000
- *
- * 0x1000_0000	CONFIG_SYS_SDRAM_BASE
- *					MEMTEST_AREA	 64kB
- *					FREE
- * 0x1200_0000	CONFIG_SYS_TEXT_BASE
- *		U-BOOT code
- * 0x1202_0000
- *					FREE
- *
- *					STACK
- * 0x13EF_F000	CONFIG_SYS_MALLOC_BASE
- *					MALLOC_AREA	768kB	Alloc
- * 0x13FB_F000	CONFIG_SYS_MONITOR_BASE
- *					MONITOR_CODE	256kB	Env
- * 0x13FF_F000	CONFIG_SYS_GBL_DATA_OFFSET
- *					GLOBAL_DATA	4kB	bd, gd
- * 0x1400_0000	CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE
- */
-
+#ifndef CONFIG_OF_CONTROL
 /* ddr sdram - main memory */
-#define	CONFIG_SYS_SDRAM_BASE		XILINX_RAM_START
-#define	CONFIG_SYS_SDRAM_SIZE		XILINX_RAM_SIZE
-#define	CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
-#define	CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_SDRAM_BASE + 0x1000)
+# define CONFIG_SYS_SDRAM_BASE	XILINX_RAM_START
+# define CONFIG_SYS_SDRAM_SIZE	XILINX_RAM_SIZE
+#endif
 
-/* global pointer */
-/* start of global data */
-#define	CONFIG_SYS_GBL_DATA_OFFSET \
-		(CONFIG_SYS_SDRAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_MALLOC_LEN	0xC0000
+#ifndef CONFIG_SPL_BUILD
+# define CONFIG_SYS_MALLOC_F_LEN	1024
+#else
+# define CONFIG_SYS_MALLOC_SIMPLE
+# define CONFIG_SYS_MALLOC_F_LEN	0x150
+#endif
 
-/* monitor code */
-#define	SIZE				0x40000
-#define	CONFIG_SYS_MONITOR_LEN		SIZE
-#define	CONFIG_SYS_MONITOR_BASE	\
-		(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
-			- CONFIG_SYS_MONITOR_LEN - GENERATED_BD_INFO_SIZE)
-#define	CONFIG_SYS_MONITOR_END \
-			(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
-#define	CONFIG_SYS_MALLOC_LEN		(SIZE * 3)
-#define	CONFIG_SYS_MALLOC_BASE \
-			(CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
-
-/* stack */
-#define	CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_MALLOC_BASE
+/* Stack location before relocation */
+#define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_TEXT_BASE
 
 /*
  * CFI flash memory layout - Example
@@ -452,7 +412,10 @@
 #define CONFIG_SPL_LDSCRIPT	"arch/microblaze/cpu/u-boot-spl.lds"
 
 #define CONFIG_SPL_RAM_DEVICE
-#define CONFIG_SPL_NOR_SUPPORT
+#ifdef CONFIG_SYS_FLASH_BASE
+# define CONFIG_SPL_NOR_SUPPORT
+# define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_FLASH_BASE
+#endif
 
 /* for booting directly linux */
 #define CONFIG_SPL_OS_BOOT
@@ -468,36 +431,20 @@
 /* BRAM start */
 #define CONFIG_SYS_INIT_RAM_ADDR	0x0
 /* BRAM size - will be generated */
-#define CONFIG_SYS_INIT_RAM_SIZE	0x10000
-/* Stack pointer prior relocation, must situated at on-chip RAM */
-#define CONFIG_SYS_SPL_MALLOC_END	(CONFIG_SYS_INIT_RAM_ADDR + \
+#define CONFIG_SYS_INIT_RAM_SIZE	0x100000
+
+# define CONFIG_SPL_STACK_ADDR		(CONFIG_SYS_INIT_RAM_ADDR + \
 					 CONFIG_SYS_INIT_RAM_SIZE - \
-					 GENERATED_GBL_DATA_SIZE)
-
-#define CONFIG_SYS_SPL_MALLOC_SIZE	0x100
-
-/*
- * The main reason to do it in this way is that MALLOC_START
- * can't be defined - common/spl/spl.c
- */
-#if (CONFIG_SYS_SPL_MALLOC_SIZE != 0)
-# define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SYS_SPL_MALLOC_END - \
-					 CONFIG_SYS_SPL_MALLOC_SIZE)
-# define CONFIG_SPL_STACK_ADDR		CONFIG_SYS_SPL_MALLOC_START
-#else
-# define CONFIG_SPL_STACK_ADDR		CONFIG_SYS_SPL_MALLOC_END
-#endif
+					 CONFIG_SYS_MALLOC_F_LEN)
 
 /* Just for sure that there is a space for stack */
 #define CONFIG_SPL_STACK_SIZE		0x100
 
-#define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_FLASH_BASE
 #define CONFIG_SYS_UBOOT_START		CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SPL_MAX_FOOTPRINT	(CONFIG_SYS_INIT_RAM_SIZE - \
 					 CONFIG_SYS_INIT_RAM_ADDR - \
-					 GENERATED_GBL_DATA_SIZE - \
-					 CONFIG_SYS_SPL_MALLOC_SIZE - \
+					 CONFIG_SYS_MALLOC_F_LEN - \
 					 CONFIG_SPL_STACK_SIZE)
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/mimc200.h b/include/configs/mimc200.h
index fc7ecfa..2fd3add 100644
--- a/include/configs/mimc200.h
+++ b/include/configs/mimc200.h
@@ -157,7 +157,6 @@
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_INTRAM_BASE + CONFIG_SYS_INTRAM_SIZE)
 
 #define CONFIG_SYS_MALLOC_LEN			(1024*1024)
-#define CONFIG_SYS_DMA_ALLOC_LEN		(16384)
 
 /* Allow 4MB for the kernel run-time image */
 #define CONFIG_SYS_LOAD_ADDR			(EBI_SDRAM_BASE + 0x00400000)
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
new file mode 100644
index 0000000..823e051
--- /dev/null
+++ b/include/configs/minnowmax.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_MONITOR_LEN		(1 << 20)
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_NR_DRAM_BANKS		1
+
+#define CONFIG_X86_SERIAL
+#define CONFIG_SMSC_LPC47M
+
+#define CONFIG_PCI_MEM_BUS		0xd0000000
+#define CONFIG_PCI_MEM_PHYS		CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE		0x10000000
+
+#define CONFIG_PCI_PREF_BUS		0xc0000000
+#define CONFIG_PCI_PREF_PHYS		CONFIG_PCI_PREF_BUS
+#define CONFIG_PCI_PREF_SIZE		0x10000000
+
+#define CONFIG_PCI_IO_BUS		0x2000
+#define CONFIG_PCI_IO_PHYS		CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE		0xe000
+
+#define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_PCI_PNP
+#define CONFIG_RTL8169
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
+					"stdout=vga,serial\0" \
+					"stderr=vga,serial\0"
+
+#define CONFIG_SCSI_DEV_LIST            \
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}
+#define CONFIG_SPI_FLASH_SST
+
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC_SDMA
+#define CONFIG_CMD_MMC
+
+#undef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT		1
+
+#define CONFIG_X86_OPTION_ROM_FILE		vga.bin
+#define CONFIG_X86_OPTION_ROM_ADDR		0xfff90000
+
+#ifndef CONFIG_SYS_COREBOOT
+#define CONFIG_VIDEO_VESA
+#endif
+#define VIDEO_IO_OFFSET				0
+#define CONFIG_X86EMU_RAW_IO
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+
+#define CONFIG_FIT_SIGNATURE
+#define CONFIG_RSA
+
+/* Avoid a warning in the Realtek Ethernet driver */
+#define CONFIG_SYS_CACHELINE_SIZE 16
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/mx6sabre_common.h b/include/configs/mx6sabre_common.h
index f0f721e..4aa8101 100644
--- a/include/configs/mx6sabre_common.h
+++ b/include/configs/mx6sabre_common.h
@@ -25,9 +25,6 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_REVISION_TAG
 
-#define CONFIG_DM
-#define CONFIG_DM_THERMAL
-#define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #define CONFIG_IMX6_THERMAL
 
 #define CONFIG_SYS_GENERIC_BOARD
diff --git a/include/configs/mx6slevk.h b/include/configs/mx6slevk.h
index e6c4130..c567d9d 100644
--- a/include/configs/mx6slevk.h
+++ b/include/configs/mx6slevk.h
@@ -198,7 +198,7 @@
 #define CONFIG_ENV_SPI_MODE             CONFIG_SF_DEFAULT_MODE
 #define CONFIG_ENV_SPI_MAX_HZ           CONFIG_SF_DEFAULT_SPEED
 #else
-#define CONFIG_ENV_OFFSET		(6 * SZ_64K)
+#define CONFIG_ENV_OFFSET		(8 * SZ_64K)
 #define CONFIG_ENV_IS_IN_MMC
 #endif
 
diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h
index fbaae3f..a290129 100644
--- a/include/configs/mx6sxsabresd.h
+++ b/include/configs/mx6sxsabresd.h
@@ -18,6 +18,12 @@
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#include "imx6_spl.h"
+#endif
+
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
@@ -28,7 +34,6 @@
 #define CONFIG_SYS_MALLOC_LEN		(3 * SZ_1M)
 
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_BOARD_LATE_INIT
 #define CONFIG_MXC_GPIO
 
 #define CONFIG_MXC_UART
@@ -222,9 +227,6 @@
 #define CONFIG_PCIE_IMX_POWER_GPIO	IMX_GPIO_NR(2, 1)
 #endif
 
-#define CONFIG_DM
-#define CONFIG_DM_THERMAL
-#define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #define CONFIG_IMX6_THERMAL
 
 #define CONFIG_CMD_FUSE
@@ -255,7 +257,7 @@
 #define FSL_QSPI_FLASH_NUM		2
 #endif
 
-#define CONFIG_ENV_OFFSET		(6 * SZ_64K)
+#define CONFIG_ENV_OFFSET		(8 * SZ_64K)
 #define CONFIG_ENV_SIZE			SZ_8K
 #define CONFIG_ENV_IS_IN_MMC
 
diff --git a/include/configs/nokia_rx51.h b/include/configs/nokia_rx51.h
index 982b689..46fc91e 100644
--- a/include/configs/nokia_rx51.h
+++ b/include/configs/nokia_rx51.h
@@ -28,6 +28,7 @@
 #define CONFIG_OMAP3_RX51		/* working with RX51 */
 #define CONFIG_SYS_L2CACHE_OFF		/* pretend there is no L2 CACHE */
 #define CONFIG_OMAP_COMMON
+#define CONFIG_SYS_GENERIC_BOARD
 
 #define CONFIG_MACH_TYPE		MACH_TYPE_NOKIA_RX51
 
diff --git a/include/configs/novena.h b/include/configs/novena.h
index ea75d2c..074110c 100644
--- a/include/configs/novena.h
+++ b/include/configs/novena.h
@@ -116,7 +116,6 @@
 #define CONFIG_SYS_MEMTEST_END		0x20000000
 
 #define CONFIG_SYS_MALLOC_LEN		(64 * 1024 * 1024)
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 
 /* SPL */
 #define CONFIG_SPL_FAT_SUPPORT
diff --git a/include/configs/odroid.h b/include/configs/odroid.h
index 807e96b..8b47537 100644
--- a/include/configs/odroid.h
+++ b/include/configs/odroid.h
@@ -177,12 +177,9 @@
 
 /* I2C */
 #define CONFIG_CMD_I2C
-#define CONFIG_SYS_I2C
 #define CONFIG_SYS_I2C_S3C24X0
 #define CONFIG_SYS_I2C_S3C24X0_SPEED	100000
 #define CONFIG_SYS_I2C_S3C24X0_SLAVE	0
-#define CONFIG_MAX_I2C_NUM		8
-#define CONFIG_SYS_I2C_INIT_BOARD
 
 /* POWER */
 #define CONFIG_POWER
diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h
index b2b3750..6295ec5 100644
--- a/include/configs/omap3_igep00x0.h
+++ b/include/configs/omap3_igep00x0.h
@@ -29,11 +29,21 @@
 
 #define CONFIG_REVISION_TAG		1
 
-/* define to enable boot progress via leds */
-#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020) || \
-    (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0030)
-#define CONFIG_SHOW_BOOT_PROGRESS
+/* Status LED */
+#define CONFIG_STATUS_LED
+#define CONFIG_BOARD_SPECIFIC_LED
+#define CONFIG_GPIO_LED
+#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0020)
+#define RED_LED_GPIO 27
 #endif
+#if (CONFIG_MACH_TYPE == MACH_TYPE_IGEP0030)
+#define RED_LED_GPIO 16
+#endif
+#define RED_LED_DEV				0
+#define STATUS_LED_BIT			RED_LED_GPIO
+#define STATUS_LED_STATE		STATUS_LED_ON
+#define STATUS_LED_PERIOD		(CONFIG_SYS_HZ / 2)
+#define STATUS_LED_BOOT			RED_LED_DEV
 
 /* GPIO banks */
 #define CONFIG_OMAP3_GPIO_3		/* GPIO64 .. 95 is in GPIO bank 3 */
diff --git a/include/configs/ot1200.h b/include/configs/ot1200.h
index 255c933..c061e93 100644
--- a/include/configs/ot1200.h
+++ b/include/configs/ot1200.h
@@ -108,6 +108,16 @@
 #endif
 
 
+/* SPL */
+#ifdef CONFIG_SPL
+#include "imx6_spl.h"
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     (64 * 1024)
+#define CONFIG_SPL_SPI_LOAD
+#endif
+
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
@@ -159,7 +169,6 @@
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS           1
 #define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE                (1u * 1024 * 1024 * 1024)
 
 #define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
diff --git a/include/configs/peach-pi.h b/include/configs/peach-pi.h
index a1c980d..f04f061 100644
--- a/include/configs/peach-pi.h
+++ b/include/configs/peach-pi.h
@@ -43,8 +43,6 @@
 #endif
 
 #define CONFIG_POWER_TPS65090_EC
-#define CONFIG_CROS_EC_SPI		/* Support CROS_EC over SPI */
-#define CONFIG_DM_CROS_EC
 
 #define CONFIG_USB_XHCI
 #define CONFIG_USB_XHCI_EXYNOS
diff --git a/include/configs/peach-pit.h b/include/configs/peach-pit.h
index 6516a72..b5efbdc 100644
--- a/include/configs/peach-pit.h
+++ b/include/configs/peach-pit.h
@@ -43,8 +43,6 @@
 #endif
 
 #define CONFIG_POWER_TPS65090_EC
-#define CONFIG_CROS_EC_SPI		/* Support CROS_EC over SPI */
-#define CONFIG_DM_CROS_EC
 
 #define CONFIG_USB_XHCI
 #define CONFIG_USB_XHCI_EXYNOS
diff --git a/include/configs/platinum.h b/include/configs/platinum.h
new file mode 100644
index 0000000..134bb45
--- /dev/null
+++ b/include/configs/platinum.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __PLATINUM_CONFIG_H__
+#define __PLATINUM_CONFIG_H__
+
+#define CONFIG_SYS_GENERIC_BOARD
+
+/* SPL */
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+
+/* Location in NAND to read U-Boot from */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS     (14 * 1024 * 1024)
+
+#include "imx6_spl.h"                  /* common IMX6 SPL configuration */
+#include "mx6_common.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/gpio.h>
+
+/*
+ * Console configuration
+ */
+
+#include <config_cmd_default.h>
+#define CONFIG_CMD_BMODE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FUSE
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_I2C
+#undef  CONFIG_CMD_IMLS
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NAND_TRIMFFS
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_TIME
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_USB
+
+/*
+ * Hardware configuration
+ */
+
+/* GPIO config */
+#define CONFIG_MXC_GPIO
+
+/* UART config */
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE			UART1_BASE
+#define CONFIG_BAUDRATE				115200
+#define CONFIG_CONS_INDEX			1
+
+/* I2C config */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_SPEED			100000
+
+/* MMC config */
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR		0
+#define CONFIG_SYS_FSL_USDHC_NUM		1
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_DOS_PARTITION
+
+/* Ethernet config */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE				ENET_BASE_ADDR
+
+#define CONFIG_PHYLIB
+
+/* USB config */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MX6
+#define CONFIG_USB_STORAGE
+#define CONFIG_MXC_USB_PORT			1
+#define CONFIG_MXC_USB_PORTSC			(PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS			0
+
+/* Memory config */
+#define CONFIG_NR_DRAM_BANKS			1
+#define PHYS_SDRAM				MMDC0_ARB_BASE_ADDR
+#ifndef PHYS_SDRAM_SIZE
+#define PHYS_SDRAM_SIZE				(1024 << 20)
+#endif
+
+#define CONFIG_SYS_SDRAM_BASE			PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR		IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE		IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET		(CONFIG_SYS_INIT_RAM_SIZE - \
+						 GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR			(CONFIG_SYS_INIT_RAM_ADDR + \
+						 CONFIG_SYS_INIT_SP_OFFSET)
+
+#define CONFIG_SYS_MALLOC_LEN			(16 * 1024 * 1024)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#ifdef CONFIG_CMD_NAND
+
+/* NAND config */
+#define CONFIG_NAND_MXS
+#ifndef CONFIG_SYS_NAND_MAX_CHIPS
+#define CONFIG_SYS_NAND_MAX_CHIPS		2
+#endif
+#define CONFIG_SYS_MAX_NAND_DEVICE		1
+#define CONFIG_SYS_NAND_BASE			0x40000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+
+/* DMA config, needed for GPMI/MXS NAND support */
+#define CONFIG_APBH_DMA
+#define CONFIG_APBH_DMA_BURST
+#define CONFIG_APBH_DMA_BURST8
+
+/* Fuse support */
+#define CONFIG_MXC_OCOTP
+
+/* Environment in NAND */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET		(16 << 20)
+#define CONFIG_ENV_SECT_SIZE		(128 << 10)
+#define CONFIG_ENV_SIZE			CONFIG_ENV_SECT_SIZE
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + (512 << 10))
+#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+
+#else /* CONFIG_CMD_NAND */
+
+/* Environment in MMC */
+#define CONFIG_ENV_SIZE			(8 << 10)
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET		(6 * 64 * 1024)
+#define CONFIG_SYS_MMC_ENV_DEV		0
+
+#endif /* CONFIG_CMD_NAND */
+
+/*
+ * U-Boot configuration
+ */
+
+/* Console boot messages */
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+/* Tag config */
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* Board startup config */
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_MISC_INIT_R
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/* Device tree support */
+#define CONFIG_OF_LIBFDT
+
+#define CONFIG_LOADADDR				0x12000000
+#define CONFIG_SYS_TEXT_BASE			0x17800000
+
+#define CONFIG_SYS_MEMTEST_START		PHYS_SDRAM
+#define CONFIG_SYS_MEMTEST_END			(CONFIG_SYS_MEMTEST_START + \
+						 PHYS_SDRAM_SIZE - (12 << 20))
+
+#define CONFIG_BOOTDELAY			3
+#define CONFIG_BOOTCOMMAND			"run bootubi_scr"
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_HUSH_PARSER
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_PREBOOT
+
+#define CONFIG_SYS_CBSIZE			256
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE			(CONFIG_SYS_CBSIZE + \
+						 sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS			16
+#define CONFIG_SYS_BARGSIZE			CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_LOAD_ADDR			CONFIG_LOADADDR
+
+/* MTD/UBI/UBIFS config */
+#define CONFIG_LZO
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_RBTREE
+
+#if (CONFIG_SYS_NAND_MAX_CHIPS == 1)
+#define MTDIDS_DEFAULT		"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT	"mtdparts=gpmi-nand:14M(spl),2M(uboot)," \
+				"512k(env1),512k(env2),-(ubi)"
+#elif (CONFIG_SYS_NAND_MAX_CHIPS == 2)
+#define MTDIDS_DEFAULT		"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT	"mtdparts=gpmi-nand:14M(spl),2M(uboot)," \
+				"512k(env1),512k(env2),495M(ubi0)," \
+				"14M(res0),2M(res1)," \
+				"512k(res2),512k(res3),-(ubi1)"
+#endif
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#define CONFIG_CMD_CACHE
+#endif
+
+/*
+ * Environment configuration
+ */
+
+#if (CONFIG_SYS_NAND_MAX_CHIPS == 1)
+#define CONFIG_COMMON_ENV_UBI						\
+	"setubipartition=env set ubipartition ubi\0"			\
+	"setubirfs=env set ubirfs $ubipartition:rootfs$boot_vol\0"
+#elif (CONFIG_SYS_NAND_MAX_CHIPS == 2)
+#define CONFIG_COMMON_ENV_UBI						\
+	"setubipartition=env set ubipartition ubi$boot_vol\0"		\
+	"setubirfs=env set ubirfs ubi0:rootfs\0"
+#endif
+
+#define CONFIG_COMMON_ENV_MISC						\
+	"user=user\0"							\
+	"project="CONFIG_PLATINUM_PROJECT"\0"				\
+	"uimage=uImage\0"						\
+	"dtb="CONFIG_PLATINUM_CPU"-platinum-"CONFIG_PLATINUM_PROJECT".dtb\0" \
+	"serverip=serverip\0"						\
+	"memaddrlinux=0x10800000\0"					\
+	"memaddrsrc=0x11000000\0"					\
+	"memaddrdtb=0x12000000\0"					\
+	"console=ttymxc0\0"						\
+	"baudrate=115200\0"						\
+	"boot_scr=boot.uboot\0"						\
+	"boot_vol=0\0"							\
+	"mtdids="MTDIDS_DEFAULT"\0"					\
+	"mtdparts="MTDPARTS_DEFAULT"\0"					\
+	"mmcfs=ext2\0"							\
+	"mmcrootpart=1\0"						\
+	\
+	"setnfspath=env set nfspath /home/nfs/$user/$project/root\0"	\
+	"settftpfilelinux=env set tftpfilelinux $user/$project/$uimage\0" \
+	"settftpfiledtb=env set tftpfiledtb $user/$project/$dtb\0"	\
+	"setubifilelinux=env set ubifilelinux boot/$uimage\0"		\
+	"setubipfiledtb=env set ubifiledtb boot/$dtb\0"			\
+	"setmmcrootdev=env set mmcrootdev /dev/mmcblk0p$mmcrootpart\0"	\
+	"setmmcfilelinux=env set mmcfilelinux /boot/$uimage\0"		\
+	"setmmcfiledtb=env set mmcfiledtb /boot/$dtb\0"			\
+	\
+	"loadtftpkernel=dhcp $memaddrlinux $tftpfilelinux\0"		\
+	"loadtftpdtb=dhcp $memaddrdtb $tftpfiledtb\0"			\
+	"loadubikernel=ubifsload $memaddrlinux $ubifilelinux\0"		\
+	"loadubidtb=ubifsload $memaddrdtb $ubifiledtb\0"		\
+	"loadmmckernel=${mmcfs}load mmc 0:$mmcrootpart $memaddrlinux "	\
+		"$mmcfilelinux\0"					\
+	"loadmmcdtb=${mmcfs}load mmc 0:$mmcrootpart $memaddrdtb "	\
+		"$mmcfiledtb\0"						\
+	\
+	"ubipart=ubi part $ubipartition\0"				\
+	"ubimount=ubifsmount $ubirfs\0"					\
+	\
+	"setbootargscommon=env set bootargs $bootargs "			\
+		"console=$console,$baudrate enable_wait_mode=off\0"	\
+	"setbootargsmtd=env set bootargs $bootargs $mtdparts\0"		\
+	"setbootargsdhcp=env set bootargs $bootargs ip=dhcp\0"		\
+	"setbootargsubirfs=env set bootargs $bootargs "			\
+		"ubi.mtd=$ubipartition root=$ubirfs rootfstype=ubifs\0" \
+	"setbootargsnfsrfs=env set bootargs $bootargs root=/dev/nfs "	\
+		"nfsroot=$serverip:$nfspath,v3,tcp\0"			\
+	"setbootargsmmcrfs=env set bootargs $bootargs "			\
+		"root=$mmcrootdev rootwait rw\0"			\
+	\
+	"bootnet=run settftpfilelinux settftpfiledtb setnfspath "	\
+		"setbootargscommon setbootargsmtd setbootargsdhcp "	\
+			"setbootargsnfsrfs;"				\
+			"run loadtftpkernel loadtftpdtb;"		\
+			"bootm $memaddrlinux - $memaddrdtb\0"		\
+	"bootnet_ubirfs=run settftpfilelinux settftpfiledtb;"		\
+			"run setubipartition setubirfs;"		\
+			"run setbootargscommon setbootargsmtd "		\
+				"setbootargsubirfs;"			\
+			"run loadtftpkernel loadtftpdtb;"		\
+			"bootm $memaddrlinux - $memaddrdtb\0"		\
+	"bootubi=run setubipartition setubirfs setubifilelinux "	\
+				"setubipfiledtb;"			\
+			"run setbootargscommon setbootargsmtd "		\
+				"setbootargsubirfs;"			\
+			"run ubipart ubimount loadubikernel loadubidtb;" \
+			"bootm $memaddrlinux - $memaddrdtb\0"		\
+	"bootubi_scr=run setubipartition setubirfs;"			\
+			"run ubipart ubimount;"				\
+			"if ubifsload ${memaddrsrc} boot/${boot_scr}; "	\
+			"then source ${memaddrsrc}; else run bootubi; fi\0" \
+	"bootmmc=run setmmcrootdev setmmcfilelinux setmmcfiledtb "	\
+			"setbootargscommon setbootargsmmcrfs;"		\
+			"run loadmmckernel loadmmcdtb;"			\
+			"bootm $memaddrlinux - $memaddrdtb\0"		\
+	\
+	"bootcmd="CONFIG_BOOTCOMMAND"\0"
+
+#define CONFIG_COMMON_ENV_SETTINGS			CONFIG_COMMON_ENV_MISC \
+							CONFIG_COMMON_ENV_UBI
+#endif /* __PLATINUM_CONFIG_H__ */
diff --git a/include/configs/platinum_picon.h b/include/configs/platinum_picon.h
new file mode 100644
index 0000000..4590df5
--- /dev/null
+++ b/include/configs/platinum_picon.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __PLATINUM_PICON_CONFIG_H__
+#define __PLATINUM_PICON_CONFIG_H__
+
+#define CONFIG_PLATINUM_PICON
+#define CONFIG_PLATINUM_BOARD			"Barco Picon"
+#define CONFIG_PLATINUM_PROJECT			"picon"
+#define CONFIG_PLATINUM_CPU			"imx6dl"
+
+#define CONFIG_MX6
+
+#include <configs/platinum.h>
+
+#define CONFIG_FEC_XCV_TYPE			RMII
+#define CONFIG_FEC_MXC_PHYADDR			0
+
+#define CONFIG_HOSTNAME				picon
+
+#define CONFIG_SYS_PROMPT			"picon > "
+
+#define CONFIG_PLATFORM_ENV_SETTINGS		"\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS		CONFIG_COMMON_ENV_SETTINGS \
+						CONFIG_PLATFORM_ENV_SETTINGS
+
+#endif /* __PLATINUM_PICON_CONFIG_H__ */
diff --git a/include/configs/platinum_titanium.h b/include/configs/platinum_titanium.h
new file mode 100644
index 0000000..6789655
--- /dev/null
+++ b/include/configs/platinum_titanium.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __PLATINUM_TITANIUM_CONFIG_H__
+#define __PLATINUM_TITANIUM_CONFIG_H__
+
+#define CONFIG_PLATINUM_TITANIUM
+#define CONFIG_PLATINUM_BOARD			"Barco Titanium"
+#define CONFIG_PLATINUM_PROJECT			"titanium"
+#define CONFIG_PLATINUM_CPU			"imx6q"
+
+#define CONFIG_MX6
+
+#define PHYS_SDRAM_SIZE				(512 << 20)
+#define CONFIG_SYS_NAND_MAX_CHIPS		1
+
+#include <configs/platinum.h>
+
+#define CONFIG_FEC_XCV_TYPE			RGMII
+#define CONFIG_FEC_MXC_PHYADDR			4
+
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_MICREL_KSZ9021
+#define CONFIG_PHY_RESET_DELAY			1000
+
+#define CONFIG_HOSTNAME				titanium
+
+#define CONFIG_SYS_PROMPT			"titanium > "
+
+#define CONFIG_PLATFORM_ENV_SETTINGS		"\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS		CONFIG_COMMON_ENV_SETTINGS \
+						CONFIG_PLATFORM_ENV_SETTINGS
+
+#endif /* __PLATINUM_TITANIUM_CONFIG_H__ */
diff --git a/include/configs/rpi-common.h b/include/configs/rpi-common.h
new file mode 100644
index 0000000..3121ac9
--- /dev/null
+++ b/include/configs/rpi-common.h
@@ -0,0 +1,186 @@
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _RPI_COMMON_H_
+#define _RPI_COMMON_H_
+
+#include <linux/sizes.h>
+
+/* Architecture, CPU, etc.*/
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_BCM2835
+#define CONFIG_ARCH_CPU_INIT
+#define CONFIG_SYS_DCACHE_OFF
+/*
+ * 2835 is a SKU in a series for which the 2708 is the first or primary SoC,
+ * so 2708 has historically been used rather than a dedicated 2835 ID.
+ *
+ * We don't define a machine type for bcm2709/bcm2836 since the RPi Foundation
+ * chose to use someone else's previously registered machine ID (3139, MX51_GGC)
+ * rather than obtaining a valid ID:-/
+ */
+#ifndef CONFIG_BCM2836
+#define CONFIG_MACH_TYPE		MACH_TYPE_BCM2708
+#endif
+
+/* Memory layout */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x00000000
+#define CONFIG_SYS_TEXT_BASE		0x00008000
+#define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_TEXT_BASE
+/*
+ * The board really has 256M. However, the VC (VideoCore co-processor) shares
+ * the RAM, and uses a configurable portion at the top. We tell U-Boot that a
+ * smaller amount of RAM is present in order to avoid stomping on the area
+ * the VC uses.
+ */
+#define CONFIG_SYS_SDRAM_SIZE		SZ_128M
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + \
+					 CONFIG_SYS_SDRAM_SIZE - \
+					 GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_MALLOC_LEN		SZ_4M
+#define CONFIG_SYS_MEMTEST_START	0x00100000
+#define CONFIG_SYS_MEMTEST_END		0x00200000
+#define CONFIG_LOADADDR			0x00200000
+
+/* Flash */
+#define CONFIG_SYS_NO_FLASH
+
+/* Devices */
+/* GPIO */
+#define CONFIG_BCM2835_GPIO
+/* LCD */
+#define CONFIG_LCD
+#define CONFIG_LCD_DT_SIMPLEFB
+#define LCD_BPP				LCD_COLOR16
+/*
+ * Prevent allocation of RAM for FB; the real FB address is queried
+ * dynamically from the VideoCore co-processor, and comes from RAM
+ * not owned by the ARM CPU.
+ */
+#define CONFIG_FB_ADDR			0
+#define CONFIG_VIDEO_BCM2835
+#define CONFIG_SYS_WHITE_ON_BLACK
+
+/* SD/MMC configuration */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_MMC_SDHCI_IO_ACCESSORS
+#define CONFIG_BCM2835_SDHCI
+
+#define CONFIG_CMD_USB
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_DWC2
+#ifdef CONFIG_BCM2836
+#define CONFIG_USB_DWC2_REG_ADDR 0x3f980000
+#else
+#define CONFIG_USB_DWC2_REG_ADDR 0x20980000
+#endif
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_MISC_INIT_R
+#endif
+
+/* Console UART */
+#define CONFIG_PL01X_SERIAL
+#define CONFIG_CONS_INDEX		0
+#define CONFIG_BAUDRATE			115200
+
+/* Console configuration */
+#define CONFIG_SYS_CBSIZE		1024
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE +		\
+					 sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/* Environment */
+#define CONFIG_ENV_SIZE			SZ_16K
+#define CONFIG_ENV_IS_IN_FAT
+#define FAT_ENV_INTERFACE		"mmc"
+#define FAT_ENV_DEVICE_AND_PART		"0:1"
+#define FAT_ENV_FILE			"uboot.env"
+#define CONFIG_FAT_WRITE
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
+#define CONFIG_SYS_LOAD_ADDR		0x1000000
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/* Shell */
+#define CONFIG_SYS_MAXARGS		8
+#define CONFIG_SYS_PROMPT		"U-Boot> "
+#define CONFIG_COMMAND_HISTORY
+
+/* Commands */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_MMC
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
+/* Device tree support */
+#define CONFIG_OF_BOARD_SETUP
+/* ATAGs support for bootm/bootz */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_INITRD_TAG
+
+#include <config_distro_defaults.h>
+
+/* Some things don't make sense on this HW or yet */
+#undef CONFIG_CMD_FPGA
+
+/* Environment */
+#define ENV_DEVICE_SETTINGS \
+	"stdin=serial,lcd\0" \
+	"stdout=serial,lcd\0" \
+	"stderr=serial,lcd\0"
+
+/*
+ * Memory layout for where various images get loaded by boot scripts:
+ *
+ * scriptaddr can be pretty much anywhere that doesn't conflict with something
+ *   else. Put it low in memory to avoid conflicts.
+ *
+ * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
+ *   something else. Put it low in memory to avoid conflicts.
+ *
+ * kernel_addr_r must be within the first 128M of RAM in order for the
+ *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
+ *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
+ *   should not overlap that area, or the kernel will have to copy itself
+ *   somewhere else before decompression. Similarly, the address of any other
+ *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
+ *   this up to 16M allows for a sizable kernel to be decompressed below the
+ *   compressed load address.
+ *
+ * fdt_addr_r simply shouldn't overlap anything else. Choosing 32M allows for
+ *   the compressed kernel to be up to 16M too.
+ *
+ * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
+ *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
+ */
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x00000000\0" \
+	"pxefile_addr_r=0x00100000\0" \
+	"kernel_addr_r=0x01000000\0" \
+	"fdt_addr_r=0x02000000\0" \
+	"ramdisk_addr_r=0x02100000\0" \
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(USB, usb, 0) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_DEVICE_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	BOOTENV
+
+#define CONFIG_BOOTDELAY 2
+
+#endif
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index c94f411..ab2f4db 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -1,193 +1,12 @@
 /*
- * (C) Copyright 2012 Stephen Warren
+ * (C) Copyright 2012,2015 Stephen Warren
  *
- * 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
- * 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.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#include <linux/sizes.h>
-
-/* Architecture, CPU, etc.*/
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_BCM2835
-#define CONFIG_ARCH_CPU_INIT
-#define CONFIG_SYS_DCACHE_OFF
-/*
- * 2835 is a SKU in a series for which the 2708 is the first or primary SoC,
- * so 2708 has historically been used rather than a dedicated 2835 ID.
- */
-#define CONFIG_MACH_TYPE		MACH_TYPE_BCM2708
-
-/* Enable driver model */
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
-
-/* Memory layout */
-#define CONFIG_NR_DRAM_BANKS		1
-#define CONFIG_SYS_SDRAM_BASE		0x00000000
-#define CONFIG_SYS_TEXT_BASE		0x00008000
-#define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_TEXT_BASE
-/*
- * The board really has 256M. However, the VC (VideoCore co-processor) shares
- * the RAM, and uses a configurable portion at the top. We tell U-Boot that a
- * smaller amount of RAM is present in order to avoid stomping on the area
- * the VC uses.
- */
-#define CONFIG_SYS_SDRAM_SIZE		SZ_128M
-#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + \
-					 CONFIG_SYS_SDRAM_SIZE - \
-					 GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_MALLOC_LEN		SZ_4M
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
-#define CONFIG_SYS_MEMTEST_START	0x00100000
-#define CONFIG_SYS_MEMTEST_END		0x00200000
-#define CONFIG_LOADADDR			0x00200000
-
-/* Flash */
-#define CONFIG_SYS_NO_FLASH
-
-/* Devices */
-/* GPIO */
-#define CONFIG_BCM2835_GPIO
-/* LCD */
-#define CONFIG_LCD
-#define CONFIG_LCD_DT_SIMPLEFB
-#define LCD_BPP				LCD_COLOR16
-/*
- * Prevent allocation of RAM for FB; the real FB address is queried
- * dynamically from the VideoCore co-processor, and comes from RAM
- * not owned by the ARM CPU.
- */
-#define CONFIG_FB_ADDR			0
-#define CONFIG_VIDEO_BCM2835
-#define CONFIG_SYS_WHITE_ON_BLACK
-
-/* SD/MMC configuration */
-#define CONFIG_GENERIC_MMC
-#define CONFIG_MMC
-#define CONFIG_SDHCI
-#define CONFIG_MMC_SDHCI_IO_ACCESSORS
-#define CONFIG_BCM2835_SDHCI
-
-#define CONFIG_CMD_USB
-#ifdef CONFIG_CMD_USB
-#define CONFIG_USB_DWC2
-#define CONFIG_USB_DWC2_REG_ADDR 0x20980000
-#define CONFIG_USB_STORAGE
-#define CONFIG_USB_HOST_ETHER
-#define CONFIG_USB_ETHER_SMSC95XX
-#define CONFIG_MISC_INIT_R
-#endif
-
-/* Console UART */
-#define CONFIG_PL01X_SERIAL
-#define CONFIG_CONS_INDEX		0
-#define CONFIG_BAUDRATE			115200
-
-/* Console configuration */
-#define CONFIG_SYS_CBSIZE		1024
-#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE +		\
-					 sizeof(CONFIG_SYS_PROMPT) + 16)
-
-/* Environment */
-#define CONFIG_ENV_SIZE			SZ_16K
-#define CONFIG_ENV_IS_IN_FAT
-#define FAT_ENV_INTERFACE		"mmc"
-#define FAT_ENV_DEVICE_AND_PART		"0:1"
-#define FAT_ENV_FILE			"uboot.env"
-#define CONFIG_FAT_WRITE
-#define CONFIG_ENV_VARS_UBOOT_CONFIG
-#define CONFIG_SYS_LOAD_ADDR		0x1000000
-#define CONFIG_CONSOLE_MUX
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV
-
-/* Shell */
-#define CONFIG_SYS_MAXARGS		8
-#define CONFIG_SYS_PROMPT		"U-Boot> "
-#define CONFIG_COMMAND_HISTORY
-
-/* Commands */
-#include <config_cmd_default.h>
-#define CONFIG_CMD_GPIO
-#define CONFIG_CMD_MMC
-#define CONFIG_PARTITION_UUIDS
-#define CONFIG_CMD_PART
-
-/* Device tree support */
-#define CONFIG_OF_BOARD_SETUP
-/* ATAGs support for bootm/bootz */
-#define CONFIG_SETUP_MEMORY_TAGS
-#define CONFIG_CMDLINE_TAG
-#define CONFIG_INITRD_TAG
-
-#include <config_distro_defaults.h>
-
-/* Some things don't make sense on this HW or yet */
-#undef CONFIG_CMD_FPGA
-
-/* Environment */
-#define ENV_DEVICE_SETTINGS \
-	"stdin=serial,lcd\0" \
-	"stdout=serial,lcd\0" \
-	"stderr=serial,lcd\0"
-
-/*
- * Memory layout for where various images get loaded by boot scripts:
- *
- * scriptaddr can be pretty much anywhere that doesn't conflict with something
- *   else. Put it low in memory to avoid conflicts.
- *
- * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
- *   something else. Put it low in memory to avoid conflicts.
- *
- * kernel_addr_r must be within the first 128M of RAM in order for the
- *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
- *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
- *   should not overlap that area, or the kernel will have to copy itself
- *   somewhere else before decompression. Similarly, the address of any other
- *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
- *   this up to 16M allows for a sizable kernel to be decompressed below the
- *   compressed load address.
- *
- * fdt_addr_r simply shouldn't overlap anything else. Choosing 32M allows for
- *   the compressed kernel to be up to 16M too.
- *
- * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
- *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
- */
-#define ENV_MEM_LAYOUT_SETTINGS \
-	"scriptaddr=0x00000000\0" \
-	"pxefile_addr_r=0x00100000\0" \
-	"kernel_addr_r=0x01000000\0" \
-	"fdt_addr_r=0x02000000\0" \
-	"ramdisk_addr_r=0x02100000\0" \
-
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
-	func(USB, usb, 0) \
-	func(PXE, pxe, na) \
-	func(DHCP, dhcp, na)
-#include <config_distro_bootcmd.h>
-
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	ENV_DEVICE_SETTINGS \
-	ENV_MEM_LAYOUT_SETTINGS \
-	BOOTENV
-
-#define CONFIG_BOOTDELAY 2
+#include "rpi-common.h"
 
 #endif
diff --git a/include/configs/rpi_2.h b/include/configs/rpi_2.h
new file mode 100644
index 0000000..2e7e74f
--- /dev/null
+++ b/include/configs/rpi_2.h
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2012,2015 Stephen Warren
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BCM2836
+
+#include "rpi-common.h"
+
+#endif
diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h
index dfa2e07..8fadc68 100644
--- a/include/configs/s5p_goni.h
+++ b/include/configs/s5p_goni.h
@@ -40,7 +40,6 @@
 #define CONFIG_CMDLINE_EDITING
 
 /* Size of malloc() pool before and after relocation */
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (80 << 20))
 
 /*
@@ -290,9 +289,5 @@
 #define CONFIG_OF_LIBFDT
 
 #define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/sama5d3_xplained.h b/include/configs/sama5d3_xplained.h
index 9458047..5dab61d 100644
--- a/include/configs/sama5d3_xplained.h
+++ b/include/configs/sama5d3_xplained.h
@@ -169,13 +169,14 @@
 				"bootz 0x22000000 - 0x21000000"
 #elif CONFIG_SYS_USE_MMC
 /* bootstrap + u-boot + env in sd card */
-#define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_ENV_OFFSET	0x2000
-#define CONFIG_ENV_SIZE		0x1000
+#define CONFIG_ENV_IS_IN_FAT
+#define FAT_ENV_INTERFACE	"mmc"
+#define FAT_ENV_FILE		"uboot.env"
+#define FAT_ENV_DEVICE_AND_PART	"0"
+#define CONFIG_ENV_SIZE		0x4000
 #define CONFIG_BOOTCOMMAND	"fatload mmc 0:1 0x21000000 at91-sama5d3_xplained.dtb; " \
 				"fatload mmc 0:1 0x22000000 zImage; " \
 				"bootz 0x22000000 - 0x21000000"
-#define CONFIG_SYS_MMC_ENV_DEV	0
 #else
 #define CONFIG_ENV_IS_NOWHERE
 #endif
@@ -226,7 +227,7 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl.lds
+#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/u-boot-spl.lds
 #define CONFIG_SPL_MMC_SUPPORT
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h
index f2849d7..bd288be 100644
--- a/include/configs/sama5d3xek.h
+++ b/include/configs/sama5d3xek.h
@@ -191,6 +191,7 @@
 
 #if defined(CONFIG_CMD_USB) || defined(CONFIG_CMD_MMC)
 #define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
 #endif
 
 #define CONFIG_SYS_LOAD_ADDR			0x22000000 /* load address */
@@ -215,13 +216,14 @@
 				"bootm 0x22000000 - 0x21000000"
 #elif CONFIG_SYS_USE_MMC
 /* bootstrap + u-boot + env in sd card */
-#define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_ENV_OFFSET	0x2000
-#define CONFIG_ENV_SIZE		0x1000
+#define CONFIG_ENV_IS_IN_FAT
+#define FAT_ENV_INTERFACE	"mmc"
+#define FAT_ENV_FILE		"uboot.env"
+#define FAT_ENV_DEVICE_AND_PART	"0"
+#define CONFIG_ENV_SIZE		0x4000
 #define CONFIG_BOOTCOMMAND	"fatload mmc 0:1 0x21000000 dtb; " \
 				"fatload mmc 0:1 0x22000000 uImage; " \
 				"bootm 0x22000000 - 0x21000000"
-#define CONFIG_SYS_MMC_ENV_DEV	0
 #else
 #define CONFIG_ENV_IS_NOWHERE
 #endif
@@ -272,7 +274,7 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl.lds
+#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/u-boot-spl.lds
 #define CONFIG_SPL_MMC_SUPPORT
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
diff --git a/include/configs/sama5d4_xplained.h b/include/configs/sama5d4_xplained.h
index 996973d..6493d56 100644
--- a/include/configs/sama5d4_xplained.h
+++ b/include/configs/sama5d4_xplained.h
@@ -20,7 +20,9 @@
 
 #define CONFIG_ARCH_CPU_INIT
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_DISPLAY_CPUINFO
 
@@ -66,8 +68,12 @@
 #define CONFIG_SYS_SDRAM_BASE           ATMEL_BASE_DDRCS
 #define CONFIG_SYS_SDRAM_SIZE		0x20000000
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_INIT_SP_ADDR		0x210000
+#else
 #define CONFIG_SYS_INIT_SP_ADDR \
 	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+#endif
 
 #define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
 
@@ -221,4 +227,54 @@
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(4 * 1024 * 1024)
 
+
+/* SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x200000
+#define CONFIG_SPL_MAX_SIZE		0x10000
+#define CONFIG_SPL_BSS_START_ADDR	0x20000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000
+#define CONFIG_SYS_SPL_MALLOC_START	0x20080000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x80000
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SYS_MONITOR_LEN		(512 << 10)
+
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl.lds
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+
+#elif CONFIG_SYS_USE_NANDFLASH
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_PMECC_CAP		8
+#define CONFIG_PMECC_SECTOR_SIZE	512
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x40000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_PAGE_SIZE	0x1000
+#define CONFIG_SYS_NAND_PAGE_COUNT	64
+#define CONFIG_SYS_NAND_OOBSIZE		224
+#define CONFIG_SYS_NAND_BLOCK_SIZE	0x40000
+#define CONFIG_SYS_NAND_BAD_BLOCK_POS	0x0
+#define CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
+
+#elif CONFIG_SYS_USE_SERIALFLASH
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+
+#endif
 #endif
diff --git a/include/configs/sama5d4ek.h b/include/configs/sama5d4ek.h
index 09ab4d7..9e1b86a 100644
--- a/include/configs/sama5d4ek.h
+++ b/include/configs/sama5d4ek.h
@@ -20,7 +20,9 @@
 
 #define CONFIG_ARCH_CPU_INIT
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
 #define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_DISPLAY_CPUINFO
 
@@ -66,8 +68,12 @@
 #define CONFIG_SYS_SDRAM_BASE           ATMEL_BASE_DDRCS
 #define CONFIG_SYS_SDRAM_SIZE		0x20000000
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_INIT_SP_ADDR		0x210000
+#else
 #define CONFIG_SYS_INIT_SP_ADDR \
 	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+#endif
 
 #define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
 
@@ -219,4 +225,54 @@
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(4 * 1024 * 1024)
 
+
+/* SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x200000
+#define CONFIG_SPL_MAX_SIZE		0x10000
+#define CONFIG_SPL_BSS_START_ADDR	0x20000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000
+#define CONFIG_SYS_SPL_MALLOC_START	0x20080000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x80000
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SYS_MONITOR_LEN		(512 << 10)
+
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_SPL_LDSCRIPT		arch/arm/cpu/at91-common/u-boot-spl.lds
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+
+#elif CONFIG_SYS_USE_NANDFLASH
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_PMECC_CAP		8
+#define CONFIG_PMECC_SECTOR_SIZE	512
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x40000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_PAGE_SIZE	0x1000
+#define CONFIG_SYS_NAND_PAGE_COUNT	64
+#define CONFIG_SYS_NAND_OOBSIZE		224
+#define CONFIG_SYS_NAND_BLOCK_SIZE	0x40000
+#define CONFIG_SYS_NAND_BAD_BLOCK_POS	0x0
+#define CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
+
+#elif CONFIG_SYS_USE_SERIALFLASH
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+
+#endif
 #endif
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 657f751..febbfb6 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -23,16 +23,6 @@
 
 #define CONFIG_BOOTSTAGE
 #define CONFIG_BOOTSTAGE_REPORT
-#define CONFIG_DM
-#define CONFIG_CMD_DEMO
-#define CONFIG_CMD_DM
-#define CONFIG_DM_DEMO
-#define CONFIG_DM_DEMO_SIMPLE
-#define CONFIG_DM_DEMO_SHAPE
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_TEST
-#define CONFIG_DM_SERIAL
-#define CONFIG_DM_CROS_EC
 
 #define CONFIG_SYS_STDIO_DEREGISTER
 
@@ -41,9 +31,6 @@
 
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
-#define CONFIG_FIT
-#define CONFIG_FIT_SIGNATURE
-#define CONFIG_RSA
 #define CONFIG_CMD_FDT
 #define CONFIG_ANDROID_BOOT_IMAGE
 
@@ -73,7 +60,6 @@
 /*
  * Size of malloc() pool, before and after relocation
  */
-#define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #define CONFIG_MALLOC_F_ADDR		0x0010000
 #define CONFIG_SYS_MALLOC_LEN		(32 << 20)	/* 32MB  */
 
@@ -100,8 +86,6 @@
 #define CONFIG_CMD_SF_TEST
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI_FLASH
-#define CONFIG_DM_SPI
-#define CONFIG_DM_SPI_FLASH
 #define CONFIG_SPI_FLASH_ATMEL
 #define CONFIG_SPI_FLASH_EON
 #define CONFIG_SPI_FLASH_GIGADEVICE
@@ -112,7 +96,6 @@
 #define CONFIG_SPI_FLASH_STMICRO
 #define CONFIG_SPI_FLASH_WINBOND
 
-#define CONFIG_DM_I2C
 #define CONFIG_CMD_I2C
 #define CONFIG_SYS_I2C_SANDBOX
 #define CONFIG_I2C_EDID
@@ -158,9 +141,6 @@
 
 #define CONFIG_BOOTARGS ""
 
-#define CONFIG_CROS_EC
-#define CONFIG_CMD_CROS_EC
-#define CONFIG_CROS_EC_SANDBOX
 #define CONFIG_ARCH_EARLY_INIT_R
 #define CONFIG_BOARD_LATE_INIT
 
@@ -183,7 +163,6 @@
 #define LCD_BPP			LCD_COLOR16
 #define CONFIG_LCD_BMP_RLE8
 
-#define CONFIG_CROS_EC_KEYB
 #define CONFIG_KEYBOARD
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial,cros-ec-keyb\0" \
diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h
index 21c8bda..84029cb 100644
--- a/include/configs/sheevaplug.h
+++ b/include/configs/sheevaplug.h
@@ -33,6 +33,11 @@
 #define CONFIG_LZO
 
 /*
+ * Enable device tree support
+ */
+#define CONFIG_OF_LIBFDT
+
+/*
  * Miscellaneous configurable options
  */
 #define CONFIG_SYS_HUSH_PARSER		/* use "hush" command parser */
@@ -51,6 +56,7 @@
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_USB
+
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
@@ -141,6 +147,5 @@
 #define CONFIG_MTD_DEVICE               /* needed for mtdparts commands */
 #define CONFIG_MTD_PARTITIONS
 #define CONFIG_CMD_MTDPARTS
-#define CONFIG_LZO
 
 #endif /* _CONFIG_SHEEVAPLUG_H */
diff --git a/include/configs/silk.h b/include/configs/silk.h
new file mode 100644
index 0000000..a4235e9
--- /dev/null
+++ b/include/configs/silk.h
@@ -0,0 +1,117 @@
+/*
+ * include/configs/silk.h
+ *     This file is silk board configuration.
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __SILK_H
+#define __SILK_H
+
+#undef DEBUG
+#define CONFIG_R8A7794
+#define CONFIG_RMOBILE_BOARD_STRING "Silk"
+
+#include "rcar-gen2-common.h"
+
+#if defined(CONFIG_RMOBILE_EXTRAM_BOOT)
+#define CONFIG_SYS_TEXT_BASE	0x70000000
+#else
+#define CONFIG_SYS_TEXT_BASE	0xE6304000
+#endif
+
+#if defined(CONFIG_RMOBILE_EXTRAM_BOOT)
+#define CONFIG_SYS_INIT_SP_ADDR		0x7003FFFC
+#else
+#define CONFIG_SYS_INIT_SP_ADDR		0xE633FFFC
+#endif
+#define STACK_AREA_SIZE			0xC000
+#define LOW_LEVEL_MERAM_STACK \
+		(CONFIG_SYS_INIT_SP_ADDR + STACK_AREA_SIZE - 4)
+
+/* MEMORY */
+#define RCAR_GEN2_SDRAM_BASE		0x40000000
+#define RCAR_GEN2_SDRAM_SIZE		(1024u * 1024 * 1024)
+#define RCAR_GEN2_UBOOT_SDRAM_SIZE	(512 * 1024 * 1024)
+
+/* SCIF */
+#define CONFIG_SCIF_CONSOLE
+#define CONFIG_CONS_SCIF2
+#define CONFIG_SCIF_USE_EXT_CLK
+
+/* FLASH */
+#define CONFIG_SPI
+#define CONFIG_SPI_FLASH_BAR
+#define CONFIG_SH_QSPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_SPI_FLASH_QUAD
+#define CONFIG_SYS_NO_FLASH
+
+/* SH Ether */
+#define	CONFIG_NET_MULTI
+#define CONFIG_SH_ETHER
+#define CONFIG_SH_ETHER_USE_PORT	0
+#define CONFIG_SH_ETHER_PHY_ADDR	0x1
+#define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
+#define CONFIG_SH_ETHER_CACHE_WRITEBACK
+#define CONFIG_SH_ETHER_CACHE_INVALIDATE
+#define CONFIG_SH_ETHER_ALIGNE_SIZE	64
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+#define CONFIG_BITBANGMII
+#define CONFIG_BITBANGMII_MULTI
+
+/* Board Clock */
+#define RMOBILE_XTAL_CLK	20000000u
+#define CONFIG_SYS_CLK_FREQ	RMOBILE_XTAL_CLK
+#define CONFIG_SH_TMU_CLK_FREQ	(CONFIG_SYS_CLK_FREQ / 2) /* EXT / 2 */
+#define CONFIG_PLL1_CLK_FREQ	(CONFIG_SYS_CLK_FREQ * 156 / 2)
+#define CONFIG_P_CLK_FREQ	(CONFIG_PLL1_CLK_FREQ / 24)
+#define CONFIG_SH_SCIF_CLK_FREQ	14745600 /* External Clock */
+
+#define CONFIG_SYS_TMU_CLK_DIV  4
+
+/* i2c */
+#define CONFIG_CMD_I2C
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_SH
+#define CONFIG_SYS_I2C_SLAVE		0x7F
+#define CONFIG_SYS_I2C_SH_NUM_CONTROLLERS	3
+#define CONFIG_SYS_I2C_SH_SPEED0	400000
+#define CONFIG_SYS_I2C_SH_SPEED1	400000
+#define CONFIG_SYS_I2C_SH_SPEED2	400000
+#define CONFIG_SH_I2C_DATA_HIGH		4
+#define CONFIG_SH_I2C_DATA_LOW		5
+#define CONFIG_SH_I2C_CLOCK		10000000
+
+#define CONFIG_SYS_I2C_POWERIC_ADDR	0x58 /* da9063 */
+
+/* USB */
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_RMOBILE
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	2
+
+/* MMCIF */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_SH_MMCIF
+#define CONFIG_SH_MMCIF_ADDR	0xee200000
+#define CONFIG_SH_MMCIF_CLK	48000000
+
+/* Module stop status bits */
+/* INTC-RT */
+#define CONFIG_SMSTP0_ENA	0x00400000
+/* MSIF */
+#define CONFIG_SMSTP2_ENA	0x00002000
+/* INTC-SYS, IRQC */
+#define CONFIG_SMSTP4_ENA	0x00000180
+/* SCIF2 */
+#define CONFIG_SMSTP7_ENA	0x00080000
+
+#endif /* __SILK_H */
diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h
index 8395372..3b06d30 100644
--- a/include/configs/smdk5250.h
+++ b/include/configs/smdk5250.h
@@ -18,6 +18,8 @@
 
 #include <configs/exynos5250-common.h>
 
+/* PMIC */
+#define CONFIG_POWER_MAX77686
 
 #define CONFIG_BOARD_COMMON
 #define CONFIG_ARCH_EARLY_INIT_R
diff --git a/include/configs/smdkc100.h b/include/configs/smdkc100.h
index 982d0dc..080fc3a 100644
--- a/include/configs/smdkc100.h
+++ b/include/configs/smdkc100.h
@@ -48,9 +48,6 @@
  */
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (1 << 20))
 
-/* Small malloc pool before relocation */
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
-
 /*
  * select serial console configuration
  */
@@ -224,9 +221,5 @@
 #define CONFIG_OF_LIBFDT
 
 #define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/snapper9260.h b/include/configs/snapper9260.h
index 9fa644f..6c68596 100644
--- a/include/configs/snapper9260.h
+++ b/include/configs/snapper9260.h
@@ -21,11 +21,6 @@
 #define CONFIG_SYS_AT91_MAIN_CLOCK	18432000 /* External Crystal, in Hz */
 #define CONFIG_SYS_AT91_SLOW_CLOCK	32768
 #define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 
 /* CPU */
 #define CONFIG_ARCH_CPU_INIT
diff --git a/include/configs/snow.h b/include/configs/snow.h
index 7eaa586..fe802f2 100644
--- a/include/configs/snow.h
+++ b/include/configs/snow.h
@@ -20,7 +20,6 @@
 #include <configs/exynos5-dt-common.h>
 
 
-#define CONFIG_CROS_EC_I2C		/* Support CROS_EC over I2C */
 #define CONFIG_POWER_TPS65090_I2C
 
 #define CONFIG_BOARD_COMMON
diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h
index 6b1f967..ee227fe 100644
--- a/include/configs/socfpga_common.h
+++ b/include/configs/socfpga_common.h
@@ -190,10 +190,6 @@
  * QSPI support
  */
 #ifdef CONFIG_OF_CONTROL	/* QSPI is controlled via DT */
-#define CONFIG_CMD_DM
-#define CONFIG_DM
-#define CONFIG_DM_SPI
-#define CONFIG_DM_SPI_FLASH
 #define CONFIG_CADENCE_QSPI
 /* Enable multiple SPI NOR flash manufacturers */
 #define CONFIG_SPI_FLASH		/* SPI flash subsystem */
@@ -210,9 +206,6 @@
 #endif
 
 #ifdef CONFIG_OF_CONTROL	/* DW SPI is controlled via DT */
-#define CONFIG_CMD_DM
-#define CONFIG_DM
-#define CONFIG_DM_SPI
 #define CONFIG_DESIGNWARE_SPI
 #define CONFIG_CMD_SPI
 #endif
diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h
index fd9bd63..156e0fa 100644
--- a/include/configs/stv0991.h
+++ b/include/configs/stv0991.h
@@ -28,21 +28,10 @@
 	(PHYS_SDRAM_1_SIZE - CONFIG_ENV_SIZE)
 #define CONFIG_SYS_MAXARGS			16
 #define CONFIG_SYS_MALLOC_LEN			(CONFIG_ENV_SIZE + 16 * 1024)
-#define CONFIG_SYS_MALLOC_F_LEN			0x2000
 
-#define CONFIG_DM
 /* serial port (PL011) configuration */
 #define CONFIG_BAUDRATE				115200
-#ifdef CONFIG_DM
-#define CONFIG_DM_SERIAL
 #define CONFIG_PL01X_SERIAL
-#else
-#define CONFIG_SYS_SERIAL0                     0x80406000
-#define CONFIG_CONS_INDEX			0
-#define CONFIG_PL011_SERIAL
-#define CONFIG_PL01x_PORTS                     {(void *)CONFIG_SYS_SERIAL0}
-#define CONFIG_PL011_CLOCK                     (2700 * 1000)
-#endif
 
 /* user interface */
 #define CONFIG_SYS_PROMPT			"STV0991> "
diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h
index 87d269b..1537e53 100644
--- a/include/configs/sun4i.h
+++ b/include/configs/sun4i.h
@@ -13,8 +13,6 @@
  */
 #define CONFIG_CLK_FULL_SPEED		1008000000
 
-#define CONFIG_MACH_TYPE		4104
-
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
@@ -25,4 +23,6 @@
  */
 #include <configs/sunxi-common.h>
 
+#define CONFIG_MACH_TYPE	(4104 | ((CONFIG_MACH_TYPE_COMPAT_REV) << 28))
+
 #endif /* __CONFIG_H */
diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h
index 52e3a6f..e755531 100644
--- a/include/configs/sun5i.h
+++ b/include/configs/sun5i.h
@@ -13,8 +13,6 @@
  */
 #define CONFIG_CLK_FULL_SPEED		1008000000
 
-#define CONFIG_MACH_TYPE		4138
-
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	1
@@ -25,4 +23,6 @@
  */
 #include <configs/sunxi-common.h>
 
+#define CONFIG_MACH_TYPE	(4138 | ((CONFIG_MACH_TYPE_COMPAT_REV) << 28))
+
 #endif /* __CONFIG_H */
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index 7cd7890..f817f73 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -14,8 +14,6 @@
  */
 #define CONFIG_CLK_FULL_SPEED		912000000
 
-#define CONFIG_MACH_TYPE		4283
-
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
@@ -31,4 +29,6 @@
  */
 #include <configs/sunxi-common.h>
 
+#define CONFIG_MACH_TYPE	(4283 | ((CONFIG_MACH_TYPE_COMPAT_REV) << 28))
+
 #endif /* __CONFIG_H */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 4a5cab2..bd7d049 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -13,26 +13,36 @@
 #ifndef _SUNXI_COMMON_CONFIG_H
 #define _SUNXI_COMMON_CONFIG_H
 
+#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT
+/*
+ * The U-Boot workarounds bugs in the outdated buggy sunxi-3.4 kernels at the
+ * expense of restricting some features, so the regular machine id values can
+ * be used.
+ */
+# define CONFIG_MACH_TYPE_COMPAT_REV	0
+#else
+/*
+ * A compatibility guard to prevent loading outdated buggy sunxi-3.4 kernels.
+ * Only sunxi-3.4 kernels with appropriate fixes applied are able to pass
+ * beyond the machine id check.
+ */
+# define CONFIG_MACH_TYPE_COMPAT_REV	1
+#endif
+
 /*
  * High Level Configuration Options
  */
 #define CONFIG_SUNXI		/* sunxi family */
 #ifdef CONFIG_SPL_BUILD
-#ifndef CONFIG_SPL_FEL
 #define CONFIG_SYS_THUMB_BUILD	/* Thumbs mode to save space in SPL */
 #endif
-#endif
 
 #include <asm/arch/cpu.h>	/* get chip and board defs */
 
 #define CONFIG_SYS_TEXT_BASE		0x4a000000
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_DM)
-# define CONFIG_CMD_DM
-# define CONFIG_DM_GPIO
-# define CONFIG_DM_SERIAL
 # define CONFIG_DW_SERIAL
-# define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #endif
 
 /*
@@ -146,10 +156,10 @@
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 
+#define CONFIG_SPL_BOARD_LOAD_IMAGE
+
 #ifdef CONFIG_SPL_FEL
 
-#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
-#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
 #define CONFIG_SPL_TEXT_BASE		0x2000
 #define CONFIG_SPL_MAX_SIZE		0x4000		/* 16 KiB */
 
@@ -181,11 +191,30 @@
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x00080000	/* 512 KiB */
 
 /* I2C */
+#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER
 #define CONFIG_SPL_I2C_SUPPORT
+#endif
+
 #define CONFIG_SYS_I2C
 #define CONFIG_SYS_I2C_MVTWSI
 #define CONFIG_SYS_I2C_SPEED		400000
 #define CONFIG_SYS_I2C_SLAVE		0x7f
+
+#if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
+#define CONFIG_SYS_I2C_SOFT
+#define CONFIG_SYS_I2C_SOFT_SPEED	50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE	0x00
+#define CONFIG_VIDEO_LCD_I2C_BUS	0 /* The lcd panel soft i2c is bus 0 */
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* And the axp209 i2c bus is bus 1 */
+/* We use pin names in Kconfig and sunxi_name_to_gpio() */
+#define CONFIG_SOFT_I2C_GPIO_SDA	soft_i2c_gpio_sda
+#define CONFIG_SOFT_I2C_GPIO_SCL	soft_i2c_gpio_scl
+#ifndef __ASSEMBLY__
+extern int soft_i2c_gpio_sda;
+extern int soft_i2c_gpio_scl;
+#endif
+#endif
+
 #define CONFIG_CMD_I2C
 
 /* PMU */
@@ -197,6 +226,20 @@
 #define CONFIG_CONS_INDEX              1       /* UART0 */
 #endif
 
+#if CONFIG_CONS_INDEX == 1
+#ifdef CONFIG_MACH_SUN9I
+#define OF_STDOUT_PATH		"/soc/serial@07000000:115200"
+#else
+#define OF_STDOUT_PATH		"/soc@01c00000/serial@01c28000:115200"
+#endif
+#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN5I)
+#define OF_STDOUT_PATH		"/soc@01c00000/serial@01c28400:115200"
+#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
+#define OF_STDOUT_PATH		"/soc@01c00000/serial@01f02800:115200"
+#else
+#error Unsupported console port nr. Please fix stdout-path in sunxi-common.h.
+#endif
+
 /* GPIO */
 #define CONFIG_SUNXI_GPIO
 #define CONFIG_SPL_GPIO_SUPPORT
@@ -204,10 +247,10 @@
 
 #ifdef CONFIG_VIDEO
 /*
- * The amount of RAM that is reserved for the FB. This will not show up as
- * RAM to the kernel, but will be reclaimed by a KMS driver in future.
+ * The amount of RAM to keep free at the top of RAM when relocating u-boot,
+ * to use as framebuffer. This must be a multiple of 4096.
  */
-#define CONFIG_SUNXI_FB_SIZE (9 << 20)
+#define CONFIG_SUNXI_MAX_FB_SIZE (9 << 20)
 
 /* Do we want to initialize a simple FB? */
 #define CONFIG_VIDEO_DT_SIMPLEFB
@@ -225,8 +268,6 @@
 /* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
 #define CONFIG_VGA_AS_SINGLE_DEVICE
 
-#define CONFIG_SYS_MEM_TOP_HIDE ((CONFIG_SUNXI_FB_SIZE + 0xFFF) & ~0xFFF)
-
 /* To be able to hook simplefb into dt */
 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
 #define CONFIG_OF_BOARD_SETUP
diff --git a/include/configs/taurus.h b/include/configs/taurus.h
index 65468ad..2cf4558 100644
--- a/include/configs/taurus.h
+++ b/include/configs/taurus.h
@@ -21,9 +21,6 @@
  */
 #include <asm/hardware.h>
 
-#define MACH_TYPE_TAURUS		2067
-#define MACH_TYPE_AXM			2068
-
 #define CONFIG_SYS_GENERIC_BOARD
 
 #if defined(CONFIG_SPL_BUILD)
@@ -121,6 +118,12 @@
 #define CONFIG_RMII
 #define CONFIG_AT91_WANTS_COMMON_PHY
 
+#define CONFIG_AT91SAM9_WATCHDOG
+#if !defined(CONFIG_SPL_BUILD)
+/* Enable the watchdog */
+#define CONFIG_HW_WATCHDOG
+#endif
+
 /* USB */
 #if defined(CONFIG_BOARD_TAURUS)
 #define CONFIG_USB_ATMEL
diff --git a/include/configs/tb100.h b/include/configs/tb100.h
index e9218f7..46df406 100644
--- a/include/configs/tb100.h
+++ b/include/configs/tb100.h
@@ -12,21 +12,11 @@
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER		3
-#define CONFIG_SYS_CACHELINE_SIZE	32
 #define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_CLK_FREQ
 
 /*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_ARCH_EARLY_INIT_R
-
-/*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE		0x84000000
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index 8f1e370..005fc6a 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -18,16 +18,6 @@
 
 #include <asm/arch/tegra.h>		/* get chip and board defs */
 
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#ifndef CONFIG_SPL_BUILD
-#define CONFIG_DM_SERIAL
-#endif
-#define CONFIG_DM_SPI
-#define CONFIG_DM_SPI_FLASH
-#define CONFIG_DM_I2C
-
 #define CONFIG_SYS_TIMER_RATE		1000000
 #define CONFIG_SYS_TIMER_COUNTER	NV_PA_TMRUS_BASE
 
@@ -47,7 +37,6 @@
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN		(4 << 20)	/* 4MB  */
-#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 
 #define CONFIG_SYS_NONCACHED_MEMORY	(1 << 20)       /* 1 MiB */
 
diff --git a/include/configs/ti_am335x_common.h b/include/configs/ti_am335x_common.h
index 5ed86d9..20a55f4 100644
--- a/include/configs/ti_am335x_common.h
+++ b/include/configs/ti_am335x_common.h
@@ -20,12 +20,7 @@
 #define CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC
 
 #ifndef CONFIG_SPL_BUILD
-# define CONFIG_DM
-# define CONFIG_CMD_DM
-# define CONFIG_DM_GPIO
-# define CONFIG_DM_SERIAL
 # define CONFIG_OMAP_SERIAL
-# define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #endif
 
 #include <asm/arch/omap.h>
diff --git a/include/configs/ti_omap3_common.h b/include/configs/ti_omap3_common.h
index 3c634ee..840e108 100644
--- a/include/configs/ti_omap3_common.h
+++ b/include/configs/ti_omap3_common.h
@@ -19,12 +19,7 @@
 #include <asm/arch/omap3.h>
 
 #ifndef CONFIG_SPL_BUILD
-# define CONFIG_DM
-# define CONFIG_CMD_DM
-# define CONFIG_DM_GPIO
-# define CONFIG_DM_SERIAL
 # define CONFIG_OMAP_SERIAL
-# define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
 #endif
 
 /* The chip has SDRC controller */
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index 5a53c50..3f738fb 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2012-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -43,6 +43,9 @@
 #define CONFIG_SDRAM1_SIZE	0x10000000
 #endif
 
+#define CONFIG_I2C_EEPROM
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  10
+
 /*
  * Support card address map
  */
@@ -77,8 +80,6 @@
 #define CONFIG_SMC911X_BASE		CONFIG_SUPPORT_CARD_ETHER_BASE
 #define CONFIG_SMC911X_32_BIT
 
-#define CONFIG_SYS_MALLOC_F_LEN  0x2000
-
 /*-----------------------------------------------------------------------
  * MMU and Cache Setting
  *----------------------------------------------------------------------*/
@@ -92,6 +93,8 @@
 
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_MISC_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_EARLY_INIT_R
 #define CONFIG_BOARD_LATE_INIT
 
@@ -187,8 +190,6 @@
 #define CONFIG_FAT_WRITE
 #define CONFIG_DOS_PARTITION
 
-#define CONFIG_CMD_DM
-
 /* memtest works on */
 #define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_SDRAM_BASE + 0x01000000)
@@ -232,11 +233,16 @@
 	"image_offset=0x00080000\0"		\
 	"image_size=0x00f00000\0"		\
 	"verify=n\0"				\
-	"norboot=run add_default_bootargs;"				\
+	"nandupdate=nand erase 0 0x100000 &&"				\
+		   "tftpboot u-boot-spl.bin &&"				\
+		   "nand write $loadaddr 0 0x10000 &&"			\
+		   "tftpboot u-boot-dtb.img &&"				\
+		   "nand write $loadaddr 0x10000 0xf0000\0"		\
+	"norboot=run add_default_bootargs &&"				\
 		"bootm $image_offset\0"					\
-	"nandboot=run add_default_bootargs;"				\
-		"nand read $loadaddr $image_offset $image_size;"	\
-		"bootm\0"						\
+	"nandboot=run add_default_bootargs &&"				\
+		 "nand read $loadaddr $image_offset $image_size &&"	\
+		 "bootm\0"						\
 	"add_default_bootargs=setenv bootargs $bootargs"		\
 		" console=ttyS0,$baudrate\0"				\
 
@@ -266,8 +272,6 @@
 #define CONFIG_SPL_TEXT_BASE		0x00100000
 #endif
 
-#define CONFIG_BOARD_POSTCLK_INIT
-
 #ifndef CONFIG_SPL_BUILD
 #define CONFIG_SKIP_LOWLEVEL_INIT
 #endif
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index 027d78b..7fb28a5 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -11,9 +11,9 @@
 /* We use generic board for v8 Versatile Express */
 #define CONFIG_SYS_GENERIC_BOARD
 
-#ifdef CONFIG_BASE_FVP
+#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP
 #ifndef CONFIG_SEMIHOSTING
-#error CONFIG_BASE_FVP requires CONFIG_SEMIHOSTING
+#error CONFIG_TARGET_VEXPRESS64_BASE_FVP requires CONFIG_SEMIHOSTING
 #endif
 #define CONFIG_BOARD_LATE_INIT
 #define CONFIG_ARMV8_SWITCH_TO_EL1
@@ -21,8 +21,9 @@
 
 #define CONFIG_REMAKE_ELF
 
-#ifndef CONFIG_BASE_FVP
-/* Base FVP not using GICv3 yet */
+#if !defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) && \
+    !defined(CONFIG_TARGET_VEXPRESS64_JUNO)
+/* Base FVP and Juno not using GICv3 yet */
 #define CONFIG_GICV3
 #endif
 
@@ -40,10 +41,13 @@
 #define CONFIG_BOOTP_VCI_STRING		"U-boot.armv8.vexpress_aemv8a"
 
 /* Link Definitions */
-#ifdef CONFIG_BASE_FVP
+#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP
 /* ATF loads u-boot here for BASE_FVP model */
 #define CONFIG_SYS_TEXT_BASE		0x88000000
 #define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + 0x03f00000)
+#elif CONFIG_TARGET_VEXPRESS64_JUNO
+#define CONFIG_SYS_TEXT_BASE		0xe0000000
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + 0x7fff0)
 #else
 #define CONFIG_SYS_TEXT_BASE		0x80000000
 #define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + 0x7fff0)
@@ -54,7 +58,7 @@
 
 
 /* SMP Spin Table Definitions */
-#ifdef CONFIG_BASE_FVP
+#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP
 #define CPU_RELEASE_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x03f00000)
 #else
 #define CPU_RELEASE_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x7fff0)
@@ -88,10 +92,15 @@
 #define V2M_KMI0			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(6))
 #define V2M_KMI1			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(7))
 
+#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
+#define V2M_UART0			0x7ff80000
+#define V2M_UART1			0x7ff70000
+#else /* Not Juno */
 #define V2M_UART0			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(9))
 #define V2M_UART1			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(10))
 #define V2M_UART2			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(11))
 #define V2M_UART3			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(12))
+#endif
 
 #define V2M_WDT				(V2M_PA_CS3 + V2M_PERIPH_OFFSET(15))
 
@@ -119,9 +128,12 @@
 #define GICR_BASE			(0x2f100000)
 #else
 
-#ifdef CONFIG_BASE_FVP
+#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP
 #define GICD_BASE			(0x2f000000)
 #define GICC_BASE			(0x2c000000)
+#elif CONFIG_TARGET_VEXPRESS64_JUNO
+#define GICD_BASE			(0x2C010000)
+#define GICC_BASE			(0x2C02f000)
 #else
 #define GICD_BASE			(0x2C001000)
 #define GICC_BASE			(0x2C002000)
@@ -140,7 +152,11 @@
 
 /* PL011 Serial Configuration */
 #define CONFIG_PL011_SERIAL
+#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
+#define CONFIG_PL011_CLOCK		7273800
+#else
 #define CONFIG_PL011_CLOCK		24000000
+#endif
 #define CONFIG_PL01x_PORTS		{(void *)CONFIG_SYS_SERIAL0, \
 					 (void *)CONFIG_SYS_SERIAL1}
 #define CONFIG_CONS_INDEX		0
@@ -161,6 +177,7 @@
 #define CONFIG_CMD_ENV
 #define CONFIG_CMD_FLASH
 #define CONFIG_CMD_IMI
+#define CONFIG_CMD_LOADB
 #define CONFIG_CMD_MEMORY
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NET
@@ -191,7 +208,7 @@
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
 
 /* Initial environment variables */
-#ifdef CONFIG_BASE_FVP
+#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP
 #define CONFIG_EXTRA_ENV_SETTINGS	\
 				"kernel_name=uImage\0"	\
 				"kernel_addr_r=0x80000000\0"	\
diff --git a/include/configs/vexpress_common.h b/include/configs/vexpress_common.h
index 7e78f8a..2dea921 100644
--- a/include/configs/vexpress_common.h
+++ b/include/configs/vexpress_common.h
@@ -122,7 +122,7 @@
 #define CONFIG_SETUP_MEMORY_TAGS	1
 #define CONFIG_SYS_L2CACHE_OFF		1
 #define CONFIG_INITRD_TAG		1
-
+#define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_OF_LIBFDT		1
 
 /* Size of malloc() pool */
diff --git a/include/configs/wandboard.h b/include/configs/wandboard.h
index 809017c..117d1f7 100644
--- a/include/configs/wandboard.h
+++ b/include/configs/wandboard.h
@@ -175,7 +175,7 @@
 		"if i2c probe 0x10; then " \
 			"setenv bootargs ${bootargs} " \
 				"video=mxcfb${nextcon}:dev=lcd,800x480@60," \
-					"if=RGB666; " \
+					"if=RGB666,bpp=32; " \
 			"if test 0 -eq ${nextcon}; then " \
 				"setenv fbmem fbmem=10M; " \
 			"else " \
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index ecedfc3..994874c 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -22,11 +22,6 @@
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 #define CONFIG_DISPLAY_CPUINFO
 
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
-
 #define CONFIG_LMB
 #define CONFIG_OF_LIBFDT
 
@@ -39,7 +34,6 @@
 /* SATA AHCI storage */
 
 #define CONFIG_SCSI_AHCI
-#define CONFIG_SATA_INTEL
 #ifdef CONFIG_SCSI_AHCI
 #define CONFIG_LIBATA
 #define CONFIG_SYS_64BIT_LBA
@@ -193,7 +187,6 @@
 #define CONFIG_SYS_STACK_SIZE			(32 * 1024)
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_MALLOC_LEN			0x200000
-#define CONFIG_SYS_MALLOC_F_LEN			(2 << 10)
 
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
@@ -245,6 +238,9 @@
 #define CONFIG_BOOTP_GATEWAY
 #define CONFIG_BOOTP_HOSTNAME
 
+#define CONFIG_BOOTSTAGE
+#define CONFIG_CMD_BOOTSTAGE
+
 #define CONFIG_CMD_USB
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 2d28e89..864528a 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -276,17 +276,11 @@
 #define CONFIG_OF_LIBFDT
 
 /* FIT support */
-#define CONFIG_FIT
-#define CONFIG_FIT_VERBOSE	1 /* enable fit_format_{error,warning}() */
 #define CONFIG_IMAGE_FORMAT_LEGACY /* enable also legacy image format */
 
 /* FDT support */
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 
-/* RSA support */
-#define CONFIG_FIT_SIGNATURE
-#define CONFIG_RSA
-
 /* Extend size of kernel image for uncompression */
 #define CONFIG_SYS_BOOTM_LEN	(60 * 1024 * 1024)
 
diff --git a/include/cros_ec.h b/include/cros_ec.h
index 9e13146..8457c80 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -13,6 +13,7 @@
 #include <ec_commands.h>
 #include <fdtdec.h>
 #include <cros_ec_message.h>
+#include <asm/gpio.h>
 
 #ifndef CONFIG_DM_CROS_EC
 /* Which interface is the device on? */
@@ -39,7 +40,7 @@
 	unsigned int bus_num;		/* Bus number (for I2C) */
 	unsigned int max_frequency;	/* Maximum interface frequency */
 #endif
-	struct fdt_gpio_state ec_int;	/* GPIO used as EC interrupt line */
+	struct gpio_desc ec_int;	/* GPIO used as EC interrupt line */
 	int protocol_version;           /* Protocol version to use */
 	int optimise_flash_write;	/* Don't write erased flash blocks */
 
diff --git a/include/debug_uart.h b/include/debug_uart.h
new file mode 100644
index 0000000..f56797b
--- /dev/null
+++ b/include/debug_uart.h
@@ -0,0 +1,139 @@
+/*
+ * Early debug UART support
+ *
+ * (C) Copyright 2014 Google, Inc
+ * Writte by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DEBUG_UART_H
+#define _DEBUG_UART_H
+
+#include <linux/linkage.h>
+
+/*
+ * The debug UART is intended for use very early in U-Boot to debug problems
+ * when an ICE or other debug mechanism is not available.
+ *
+ * To use it you should:
+ * - Make sure your UART supports this interface
+ * - Enable CONFIG_DEBUG_UART
+ * - Enable the CONFIG for your UART to tell it to provide this interface
+ *       (e.g. CONFIG_DEBUG_UART_NS16550)
+ * - Define the required settings as needed (see below)
+ * - Call debug_uart_init() before use
+ * - Call printch() to output a character
+ *
+ * Depending on your platform it may be possible to use this UART before a
+ * stack is available.
+ *
+ * If your UART does not support this interface you can probably add support
+ * quite easily. Remember that you cannot use driver model and it is preferred
+ * to use no stack.
+ *
+ * You must not use this UART once driver model is working and the serial
+ * drivers are up and running (done in serial_init()). Otherwise the drivers
+ * may conflict and you will get strange output.
+ *
+ *
+ * To enable the debug UART in your serial driver:
+ *
+ * - #include <debug_uart.h>
+ * - Define debug_uart_init(), trying to avoid using the stack
+ * - Define _debug_uart_putc() as static inline (avoiding stack usage)
+ * - Immediately afterwards, add DEBUG_UART_FUNCS to define the rest of the
+ *     functionality (printch(), etc.)
+ */
+
+/**
+ * debug_uart_init() - Set up the debug UART ready for use
+ *
+ * This sets up the UART with the correct baud rate, etc.
+ *
+ * Available CONFIG is:
+ *
+ *    - CONFIG_DEBUG_UART_BASE: Base address of UART
+ *    - CONFIG_BAUDRATE: Requested baud rate
+ *    - CONFIG_DEBUG_UART_CLOCK: Input clock for UART
+ */
+void debug_uart_init(void);
+
+/**
+ * printch() - Output a character to the debug UART
+ *
+ * @ch:		Character to output
+ */
+asmlinkage void printch(int ch);
+
+/**
+ * printascii() - Output an ASCII string to the debug UART
+ *
+ * @str:	String to output
+ */
+asmlinkage void printascii(const char *str);
+
+/**
+ * printhex2() - Output a 2-digit hex value
+ *
+ * @value:	Value to output
+ */
+asmlinkage void printhex2(uint value);
+
+/**
+ * printhex4() - Output a 4-digit hex value
+ *
+ * @value:	Value to output
+ */
+asmlinkage void printhex4(uint value);
+
+/**
+ * printhex8() - Output a 8-digit hex value
+ *
+ * @value:	Value to output
+ */
+asmlinkage void printhex8(uint value);
+
+/*
+ * Now define some functions - this should be inserted into the serial driver
+ */
+#define DEBUG_UART_FUNCS \
+	asmlinkage void printch(int ch) \
+	{ \
+		_debug_uart_putc(ch); \
+	} \
+\
+	asmlinkage void printascii(const char *str) \
+	{ \
+		while (*str) \
+			_debug_uart_putc(*str++); \
+	} \
+\
+	static inline void printhex1(uint digit) \
+	{ \
+		digit &= 0xf; \
+		_debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \
+	} \
+\
+	static inline void printhex(uint value, int digits) \
+	{ \
+		while (digits-- > 0) \
+			printhex1(value >> (4 * digits)); \
+	} \
+\
+	asmlinkage void printhex2(uint value) \
+	{ \
+		printhex(value, 2); \
+	} \
+\
+	asmlinkage void printhex4(uint value) \
+	{ \
+		printhex(value, 4); \
+	} \
+\
+	asmlinkage void printhex8(uint value) \
+	{ \
+		printhex(value, 8); \
+	}
+
+#endif
diff --git a/include/dm-demo.h b/include/dm-demo.h
index a24fec6..03722d0 100644
--- a/include/dm-demo.h
+++ b/include/dm-demo.h
@@ -25,10 +25,14 @@
 struct demo_ops {
 	int (*hello)(struct udevice *dev, int ch);
 	int (*status)(struct udevice *dev, int *status);
+	int (*set_light)(struct udevice *dev, int light);
+	int (*get_light)(struct udevice *dev);
 };
 
 int demo_hello(struct udevice *dev, int ch);
 int demo_status(struct udevice *dev, int *status);
+int demo_set_light(struct udevice *dev, int light);
+int demo_get_light(struct udevice *dev);
 int demo_list(void);
 
 int demo_parse_dt(struct udevice *dev);
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index f0cc794..e2418fe 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -101,7 +101,11 @@
  * @dev: Pointer to device to unbind
  * @return 0 if OK, -ve on error
  */
+#ifdef CONFIG_DM_DEVICE_REMOVE
 int device_unbind(struct udevice *dev);
+#else
+static inline int device_unbind(struct udevice *dev) { return 0; }
+#endif
 
 #ifdef CONFIG_DM_DEVICE_REMOVE
 void device_free(struct udevice *dev);
diff --git a/include/dm/device.h b/include/dm/device.h
index 13598a1..7a48eb8 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -12,6 +12,7 @@
 #define _DM_DEVICE_H
 
 #include <dm/uclass-id.h>
+#include <fdtdec.h>
 #include <linker_lists.h>
 #include <linux/list.h>
 
@@ -26,6 +27,9 @@
 /* DM should init this device prior to relocation */
 #define DM_FLAG_PRE_RELOC	(1 << 2)
 
+/* DM is responsible for allocating and freeing parent_platdata */
+#define DM_FLAG_ALLOC_PARENT_PDATA	(1 << 3)
+
 /**
  * struct udevice - An instance of a driver
  *
@@ -46,6 +50,7 @@
  * @driver: The driver used by this device
  * @name: Name of device, typically the FDT node name
  * @platdata: Configuration data for this device
+ * @parent_platdata: The parent bus's configuration data for this device
  * @of_offset: Device tree node offset for this device (- for none)
  * @of_id: Pointer to the udevice_id structure which created the device
  * @parent: Parent of this device, or NULL for the top level device
@@ -65,6 +70,7 @@
 	struct driver *driver;
 	const char *name;
 	void *platdata;
+	void *parent_platdata;
 	int of_offset;
 	const struct udevice_id *of_id;
 	struct udevice *parent;
@@ -127,6 +133,7 @@
  * @remove: Called to remove a device, i.e. de-activate it
  * @unbind: Called to unbind a device from its driver
  * @ofdata_to_platdata: Called before probe to decode device tree data
+ * @child_post_bind: Called after a new child has been bound
  * @child_pre_probe: Called before a child device is probed. The device has
  * memory allocated but it has not yet been probed.
  * @child_post_remove: Called after a child device is removed. The device
@@ -146,6 +153,9 @@
  * device_probe_child() pass it in. So far the use case for allocating it
  * is SPI, but I found that unsatisfactory. Since it is here I will leave it
  * until things are clearer.
+ * @per_child_platdata_auto_alloc_size: A bus likes to store information about
+ * its children. If non-zero this is the size of this data, to be allocated
+ * in the child's parent_platdata pointer.
  * @ops: Driver-specific operations. This is typically a list of function
  * pointers defined by the driver, to implement driver functions required by
  * the uclass.
@@ -160,11 +170,13 @@
 	int (*remove)(struct udevice *dev);
 	int (*unbind)(struct udevice *dev);
 	int (*ofdata_to_platdata)(struct udevice *dev);
+	int (*child_post_bind)(struct udevice *dev);
 	int (*child_pre_probe)(struct udevice *dev);
 	int (*child_post_remove)(struct udevice *dev);
 	int priv_auto_alloc_size;
 	int platdata_auto_alloc_size;
 	int per_child_auto_alloc_size;
+	int per_child_platdata_auto_alloc_size;
 	const void *ops;	/* driver-specific operations */
 	uint32_t flags;
 };
@@ -184,6 +196,16 @@
 void *dev_get_platdata(struct udevice *dev);
 
 /**
+ * dev_get_parent_platdata() - Get the parent platform data for a device
+ *
+ * This checks that dev is not NULL, but no other checks for now
+ *
+ * @dev		Device to check
+ * @return parent's platform data, or NULL if none
+ */
+void *dev_get_parent_platdata(struct udevice *dev);
+
+/**
  * dev_get_parentdata() - Get the parent data for a device
  *
  * The parent data is data stored in the device but owned by the parent.
@@ -224,6 +246,14 @@
  */
 ulong dev_get_of_data(struct udevice *dev);
 
+/*
+ * device_get_uclass_id() - return the uclass ID of a device
+ *
+ * @dev:	Device to check
+ * @return uclass ID for the device
+ */
+enum uclass_id device_get_uclass_id(struct udevice *dev);
+
 /**
  * device_get_child() - Get the child of a device by index
  *
@@ -322,4 +352,13 @@
  */
 int device_find_next_child(struct udevice **devp);
 
+/**
+ * dev_get_addr() - Get the reg property of a device
+ *
+ * @dev: Pointer to a device
+ *
+ * @return addr
+ */
+fdt_addr_t dev_get_addr(struct udevice *dev);
+
 #endif
diff --git a/include/dm/platform_data/serial_sh.h b/include/dm/platform_data/serial_sh.h
new file mode 100644
index 0000000..0271ad6
--- /dev/null
+++ b/include/dm/platform_data/serial_sh.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014  Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (c) 2014  Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __serial_sh_h
+#define __serial_sh_h
+
+enum sh_clk_mode {
+	INT_CLK,
+	EXT_CLK,
+};
+
+enum sh_serial_type {
+	PORT_SCI,
+	PORT_SCIF,
+	PORT_SCIFA,
+	PORT_SCIFB,
+};
+
+/*
+ * Information about SCIF port
+ *
+ * @base:	Register base address
+ * @clk:	Input clock rate, used for calculating the baud rate divisor
+ * @clk_mode:	Clock mode, set internal (INT) or external (EXT)
+ * @type:	Type of SCIF
+ */
+struct sh_serial_platdata {
+	unsigned long base;
+	unsigned int clk;
+	enum sh_clk_mode clk_mode;
+	enum sh_serial_type type;
+};
+#endif /* __serial_sh_h */
diff --git a/include/dm/test.h b/include/dm/test.h
index f08c05d..707c69e 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -67,6 +67,8 @@
 struct dm_test_priv {
 	int ping_total;
 	int op_count[DM_TEST_OP_COUNT];
+	int uclass_flag;
+	int uclass_total;
 };
 
 /**
@@ -88,6 +90,7 @@
  *
  * @sum: Test value used to check parent data works correctly
  * @flag: Used to track calling of parent operations
+ * @uclass_flag: Used to track calling of parent operations by uclass
  */
 struct dm_test_parent_data {
 	int sum;
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index f17c3c2..91bb90d 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -33,6 +33,7 @@
 	UCLASS_I2C,		/* I2C bus */
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
+	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index f718f37..f2f254a 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -44,6 +44,17 @@
 int uclass_unbind_device(struct udevice *dev);
 
 /**
+ * uclass_pre_probe_child() - Deal with a child that is about to be probed
+ *
+ * Perform any pre-processing that is needed by the uclass before it can be
+ * probed.
+ *
+ * @dev:	Pointer to the device
+ * #return 0 on success, -ve on error
+ */
+int uclass_pre_probe_child(struct udevice *dev);
+
+/**
  * uclass_post_probe_device() - Deal with a device that has just been probed
  *
  * Perform any post-processing of a probed device that is needed by the
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6ec6d7..d6c40c6 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -40,6 +40,9 @@
 
 struct udevice;
 
+/* Members of this uclass sequence themselves with aliases */
+#define DM_UC_FLAG_SEQ_ALIAS			(1 << 0)
+
 /**
  * struct uclass_driver - Driver for the uclass
  *
@@ -52,6 +55,7 @@
  * @pre_unbind: Called before a device is unbound from this uclass
  * @post_probe: Called after a new device is probed
  * @pre_remove: Called before a device is removed
+ * @child_post_bind: Called after a child is bound to a device in this uclass
  * @init: Called to set up the uclass
  * @destroy: Called to destroy the uclass
  * @priv_auto_alloc_size: If non-zero this is the size of the private data
@@ -60,8 +64,16 @@
  * @per_device_auto_alloc_size: Each device can hold private data owned
  * by the uclass. If required this will be automatically allocated if this
  * value is non-zero.
+ * @per_child_auto_alloc_size: Each child device (of a parent in this
+ * uclass) can hold parent data for the device/uclass. This value is only
+ * used as a falback if this member is 0 in the driver.
+ * @per_child_platdata_auto_alloc_size: A bus likes to store information about
+ * its children. If non-zero this is the size of this data, to be allocated
+ * in the child device's parent_platdata pointer. This value is only used as
+ * a falback if this member is 0 in the driver.
  * @ops: Uclass operations, providing the consistent interface to devices
  * within the uclass.
+ * @flags: Flags for this uclass (DM_UC_...)
  */
 struct uclass_driver {
 	const char *name;
@@ -70,11 +82,16 @@
 	int (*pre_unbind)(struct udevice *dev);
 	int (*post_probe)(struct udevice *dev);
 	int (*pre_remove)(struct udevice *dev);
+	int (*child_post_bind)(struct udevice *dev);
+	int (*child_pre_probe)(struct udevice *dev);
 	int (*init)(struct uclass *class);
 	int (*destroy)(struct uclass *class);
 	int priv_auto_alloc_size;
 	int per_device_auto_alloc_size;
+	int per_child_auto_alloc_size;
+	int per_child_platdata_auto_alloc_size;
 	const void *ops;
+	uint32_t flags;
 };
 
 /* Declare a new uclass_driver */
@@ -141,6 +158,8 @@
 /**
  * uclass_first_device() - Get the first device in a uclass
  *
+ * The device returned is probed if necessary, and ready for use
+ *
  * @id: Uclass ID to look up
  * @devp: Returns pointer to the first device in that uclass, or NULL if none
  * @return 0 if OK (found or not found), -1 on error
@@ -150,6 +169,8 @@
 /**
  * uclass_next_device() - Get the next device in a uclass
  *
+ * The device returned is probed if necessary, and ready for use
+ *
  * @devp: On entry, pointer to device to lookup. On exit, returns pointer
  * to the next device in the same uclass, or NULL if none
  * @return 0 if OK (found or not found), -1 on error
diff --git a/include/dt-bindings/mrc/quark.h b/include/dt-bindings/mrc/quark.h
new file mode 100644
index 0000000..e3ca8a2
--- /dev/null
+++ b/include/dt-bindings/mrc/quark.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Intel Quark MRC bindings include several properties
+ * as part of an Intel Quark MRC node. In most cases,
+ * the value of these properties uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_QRK_MRC_H_
+#define _DT_BINDINGS_QRK_MRC_H_
+
+/* MRC platform data flags */
+#define MRC_FLAG_ECC_EN		0x00000001
+#define MRC_FLAG_SCRAMBLE_EN	0x00000002
+#define MRC_FLAG_MEMTEST_EN	0x00000004
+/* 0b DDR "fly-by" topology else 1b DDR "tree" topology */
+#define MRC_FLAG_TOP_TREE_EN	0x00000008
+/* If set ODR signal is asserted to DRAM devices on writes */
+#define MRC_FLAG_WR_ODT_EN	0x00000010
+
+/* DRAM width */
+#define DRAM_WIDTH_X8		0
+#define DRAM_WIDTH_X16		1
+#define DRAM_WIDTH_X32		2
+
+/* DRAM speed */
+#define DRAM_FREQ_800		0
+#define DRAM_FREQ_1066		1
+
+/* DRAM type */
+#define DRAM_TYPE_DDR3		0
+#define DRAM_TYPE_DDR3L		1
+
+/* DRAM rank mask */
+#define DRAM_RANK(n)		(1 << (n))
+
+/* DRAM channel mask */
+#define DRAM_CHANNEL(n)		(1 << (n))
+
+/* DRAM channel width */
+#define DRAM_CHANNEL_WIDTH_X8	0
+#define DRAM_CHANNEL_WIDTH_X16	1
+#define DRAM_CHANNEL_WIDTH_X32	2
+
+/* DRAM address mode */
+#define DRAM_ADDR_MODE0		0
+#define DRAM_ADDR_MODE1		1
+#define DRAM_ADDR_MODE2		2
+
+/* DRAM refresh rate */
+#define DRAM_REFRESH_RATE_195US	1
+#define DRAM_REFRESH_RATE_39US	2
+#define DRAM_REFRESH_RATE_785US	3
+
+/* DRAM SR temprature range */
+#define DRAM_SRT_RANGE_NORMAL	0
+#define DRAM_SRT_RANGE_EXTENDED	1
+
+/* DRAM ron value */
+#define DRAM_RON_34OHM		0
+#define DRAM_RON_40OHM		1
+
+/* DRAM rtt nom value */
+#define DRAM_RTT_NOM_40OHM	0
+#define DRAM_RTT_NOM_60OHM	1
+#define DRAM_RTT_NOM_120OHM	2
+
+/* DRAM rd odt value */
+#define DRAM_RD_ODT_OFF		0
+#define DRAM_RD_ODT_60OHM	1
+#define DRAM_RD_ODT_120OHM	2
+#define DRAM_RD_ODT_180OHM	3
+
+/* DRAM density */
+#define DRAM_DENSITY_512M	0
+#define DRAM_DENSITY_1G		1
+#define DRAM_DENSITY_2G		2
+#define DRAM_DENSITY_4G		3
+
+#endif /* _DT_BINDINGS_QRK_MRC_H_ */
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 109f7c8..86a5491 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -141,9 +141,9 @@
 	int dev_index;
 	int dev_id;
 	int buswidth;
-	u32 clksel_val;
 	u32 fifoth_val;
 	struct mmc *mmc;
+	void *priv;
 
 	void (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
diff --git a/include/exports.h b/include/exports.h
index 41d5085..205affe 100644
--- a/include/exports.h
+++ b/include/exports.h
@@ -3,6 +3,8 @@
 
 #ifndef __ASSEMBLY__
 
+struct spi_slave;
+
 /* These are declarations of exported functions available in C code */
 unsigned long get_version(void);
 int  getc(void);
@@ -10,22 +12,23 @@
 void putc(const char);
 void puts(const char*);
 int printf(const char* fmt, ...);
-void install_hdlr(int, void (*interrupt_handler_t)(void *), void*);
+void install_hdlr(int, interrupt_handler_t, void*);
 void free_hdlr(int);
 void *malloc(size_t);
 void free(void*);
 void __udelay(unsigned long);
 unsigned long get_timer(unsigned long);
 int vprintf(const char *, va_list);
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base);
 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
 char *getenv (const char *name);
 int setenv (const char *varname, const char *varvalue);
-long simple_strtol(const char *cp,char **endp,unsigned int base);
-int strcmp(const char * cs,const char * ct);
+long simple_strtol(const char *cp, char **endp, unsigned int base);
+int strcmp(const char *cs, const char *ct);
 unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
 unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base);
-#if defined(CONFIG_CMD_I2C)
+#if defined(CONFIG_CMD_I2C) && \
+		(!defined(CONFIG_DM_I2C) || defined(CONFIG_DM_I2C_COMPAT))
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
 #endif
@@ -34,15 +37,14 @@
 
 #endif    /* ifndef __ASSEMBLY__ */
 
-enum {
-#define EXPORT_FUNC(x) XF_ ## x ,
+struct jt_funcs {
+#define EXPORT_FUNC(impl, res, func, ...) res(*func)(__VA_ARGS__);
 #include <_exports.h>
 #undef EXPORT_FUNC
-
-	XF_MAX
 };
 
-#define XF_VERSION	6
+
+#define XF_VERSION	7
 
 #if defined(CONFIG_X86)
 extern gd_t *global_data;
diff --git a/include/exynos_lcd.h b/include/exynos_lcd.h
new file mode 100644
index 0000000..cf389da
--- /dev/null
+++ b/include/exynos_lcd.h
@@ -0,0 +1,81 @@
+/*
+ * exynos_lcd.h - Exynos LCD Controller structures
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _EXYNOS_LCD_H_
+#define _EXYNOS_LCD_H_
+
+enum {
+	FIMD_RGB_INTERFACE = 1,
+	FIMD_CPU_INTERFACE = 2,
+};
+
+enum exynos_fb_rgb_mode_t {
+	MODE_RGB_P = 0,
+	MODE_BGR_P = 1,
+	MODE_RGB_S = 2,
+	MODE_BGR_S = 3,
+};
+
+typedef struct vidinfo {
+	ushort vl_col;		/* Number of columns (i.e. 640) */
+	ushort vl_row;		/* Number of rows (i.e. 480) */
+	ushort vl_width;	/* Width of display area in millimeters */
+	ushort vl_height;	/* Height of display area in millimeters */
+
+	/* LCD configuration register */
+	u_char vl_freq;		/* Frequency */
+	u_char vl_clkp;		/* Clock polarity */
+	u_char vl_oep;		/* Output Enable polarity */
+	u_char vl_hsp;		/* Horizontal Sync polarity */
+	u_char vl_vsp;		/* Vertical Sync polarity */
+	u_char vl_dp;		/* Data polarity */
+	u_char vl_bpix;		/* Bits per pixel */
+
+	/* Horizontal control register. Timing from data sheet */
+	u_char vl_hspw;		/* Horz sync pulse width */
+	u_char vl_hfpd;		/* Wait before of line */
+	u_char vl_hbpd;		/* Wait end of line */
+
+	/* Vertical control register. */
+	u_char	vl_vspw;	/* Vertical sync pulse width */
+	u_char	vl_vfpd;	/* Wait before of frame */
+	u_char	vl_vbpd;	/* Wait end of frame */
+	u_char  vl_cmd_allow_len; /* Wait end of frame */
+
+	unsigned int win_id;
+	unsigned int init_delay;
+	unsigned int power_on_delay;
+	unsigned int reset_delay;
+	unsigned int interface_mode;
+	unsigned int mipi_enabled;
+	unsigned int dp_enabled;
+	unsigned int cs_setup;
+	unsigned int wr_setup;
+	unsigned int wr_act;
+	unsigned int wr_hold;
+	unsigned int logo_on;
+	unsigned int logo_width;
+	unsigned int logo_height;
+	int logo_x_offset;
+	int logo_y_offset;
+	unsigned long logo_addr;
+	unsigned int rgb_mode;
+	unsigned int resolution;
+
+	/* parent clock name(MPLL, EPLL or VPLL) */
+	unsigned int pclk_name;
+	/* ratio value for source clock from parent clock. */
+	unsigned int sclk_div;
+
+	unsigned int dual_lcd_enabled;
+} vidinfo_t;
+
+void init_panel_info(vidinfo_t *vid);
+
+#endif
diff --git a/include/fdt_simplefb.h b/include/fdt_simplefb.h
new file mode 100644
index 0000000..8c89a19
--- /dev/null
+++ b/include/fdt_simplefb.h
@@ -0,0 +1,14 @@
+/*
+ * Simplefb device tree support
+ *
+ * (C) Copyright 2015
+ * Stephen Warren <swarren@wwwdotorg.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _FDT_SIMPLEFB_H_
+#define _FDT_SIMPLEFB_H_
+int lcd_dt_simplefb_add_node(void *blob);
+int lcd_dt_simplefb_enable_existing_node(void *blob);
+#endif
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 1f19fe4..ae5e8a3 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -100,7 +100,7 @@
  */
 int ft_system_setup(void *blob, bd_t *bd);
 
-void set_working_fdt_addr(void *addr);
+void set_working_fdt_addr(ulong addr);
 int fdt_shrink_to_minimum(void *blob);
 int fdt_increase_size(void *fdt, int add_len);
 
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 8c2bd21..1bc70db 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -115,9 +115,6 @@
 	COMPAT_NVIDIA_TEGRA20_USB,	/* Tegra20 USB port */
 	COMPAT_NVIDIA_TEGRA30_USB,	/* Tegra30 USB port */
 	COMPAT_NVIDIA_TEGRA114_USB,	/* Tegra114 USB port */
-	COMPAT_NVIDIA_TEGRA114_I2C,	/* Tegra114 I2C w/single clock source */
-	COMPAT_NVIDIA_TEGRA20_I2C,	/* Tegra20 i2c */
-	COMPAT_NVIDIA_TEGRA20_DVC,	/* Tegra20 dvc (really just i2c) */
 	COMPAT_NVIDIA_TEGRA20_EMC,	/* Tegra20 memory controller */
 	COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
 	COMPAT_NVIDIA_TEGRA20_KBC,	/* Tegra20 Keyboard */
@@ -127,9 +124,6 @@
 	COMPAT_NVIDIA_TEGRA124_SDMMC,	/* Tegra124 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA30_SDMMC,	/* Tegra30 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA20_SDMMC,	/* Tegra20 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
-	COMPAT_NVIDIA_TEGRA20_SLINK,	/* Tegra 2 SPI SLINK controller */
-	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */
 	COMPAT_NVIDIA_TEGRA124_PCIE,	/* Tegra 124 PCIe controller */
 	COMPAT_NVIDIA_TEGRA30_PCIE,	/* Tegra 30 PCIe controller */
 	COMPAT_NVIDIA_TEGRA20_PCIE,	/* Tegra 20 PCIe controller */
@@ -140,7 +134,6 @@
 	COMPAT_SAMSUNG_S3C2440_I2C,	/* Exynos I2C Controller */
 	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 */
@@ -174,42 +167,63 @@
 	COMPAT_INTEL_GMA,		/* Intel Graphics Media Accelerator */
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
+	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
 
 	COMPAT_COUNT,
 };
 
-/* GPIOs are numbered from 0 */
-enum {
-	FDT_GPIO_NONE = -1U,	/* an invalid GPIO used to end our list */
-
-	FDT_GPIO_ACTIVE_LOW = 1 << 0,	/* input is active low (else high) */
+#define MAX_PHANDLE_ARGS 16
+struct fdtdec_phandle_args {
+	int node;
+	int args_count;
+	uint32_t args[MAX_PHANDLE_ARGS];
 };
 
-/* This is the state of a GPIO pin as defined by the fdt */
-struct fdt_gpio_state {
-	const char *name;	/* name of the fdt property defining this */
-	uint gpio;		/* GPIO number, or FDT_GPIO_NONE if none */
-	u8 flags;		/* FDT_GPIO_... flags */
-};
-
-/* This tells us whether a fdt_gpio_state record is valid or not */
-#define fdt_gpio_isvalid(x) ((x)->gpio != FDT_GPIO_NONE)
-
 /**
- * Read the GPIO taking into account the polarity of the pin.
+ * fdtdec_parse_phandle_with_args() - Find a node pointed by phandle in a list
  *
- * @param gpio		pointer to the decoded gpio
- * @return value of the gpio if successful, < 0 if unsuccessful
- */
-int fdtdec_get_gpio(struct fdt_gpio_state *gpio);
-
-/**
- * Write the GPIO taking into account the polarity of the pin.
+ * This function is useful to parse lists of phandles and their arguments.
  *
- * @param gpio		pointer to the decoded gpio
- * @return 0 if successful
+ * Example:
+ *
+ * phandle1: node1 {
+ *	#list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ *	#list-cells = <1>;
+ * }
+ *
+ * node3 {
+ *	list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * fdtdec_parse_phandle_with_args(blob, node3, "list", "#list-cells", 0, 1,
+ *				  &args);
+ *
+ * (This function is a modified version of __of_parse_phandle_with_args() from
+ * Linux 3.18)
+ *
+ * @blob:	Pointer to device tree
+ * @src_node:	Offset of device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies the phandles' arguments count,
+ *		or NULL to use @cells_count
+ * @cells_count: Cell count to use if @cells_name is NULL
+ * @index:	index of a phandle to parse out
+ * @out_args:	optional pointer to output arguments structure (will be filled)
+ * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if
+ *	@list_name does not exist, a phandle was not found, @cells_name
+ *	could not be found, the arguments were truncated or there were too
+ *	many arguments.
+ *
  */
-int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val);
+int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
+				   const char *list_name,
+				   const char *cells_name,
+				   int cell_count, int index,
+				   struct fdtdec_phandle_args *out_args);
 
 /**
  * Find the next numbered alias for a peripheral. This is used to enumerate
@@ -592,50 +606,6 @@
 int fdtdec_get_bool(const void *blob, int node, const char *prop_name);
 
 /**
- * Decode a single GPIOs from an FDT.
- *
- * If the property is not found, then the GPIO structure will still be
- * initialised, with gpio set to FDT_GPIO_NONE. This makes it easy to
- * provide optional GPIOs.
- *
- * @param blob		FDT blob to use
- * @param node		Node to look at
- * @param prop_name	Node property name
- * @param gpio		gpio elements to fill from FDT
- * @return 0 if ok, -FDT_ERR_NOTFOUND if the property is missing.
- */
-int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
-		struct fdt_gpio_state *gpio);
-
-/**
- * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no
- * terminating item.
- *
- * @param blob         FDT blob to use
- * @param node         Node to look at
- * @param prop_name    Node property name
- * @param gpio         Array of gpio elements to fill from FDT. This will be
- *                     untouched if either 0 or an error is returned
- * @param max_count    Maximum number of elements allowed
- * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
- * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
- */
-int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
-		struct fdt_gpio_state *gpio, int max_count);
-
-/**
- * Set up a GPIO pin according to the provided gpio information. At present this
- * just requests the GPIO.
- *
- * If the gpio is FDT_GPIO_NONE, no action is taken. This makes it easy to
- * deal with optional GPIOs.
- *
- * @param gpio		GPIO info to use for set up
- * @return 0 if all ok or gpio was FDT_GPIO_NONE; -1 on error
- */
-int fdtdec_setup_gpio(struct fdt_gpio_state *gpio);
-
-/**
  * Look in the FDT for a config item with the given name and return its value
  * as a 32-bit integer. The property must have at least 4 bytes of data. The
  * value of the first cell is returned.
diff --git a/include/fs.h b/include/fs.h
index ffb6ce7..fd1e4ab 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -109,4 +109,10 @@
 int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 		int fstype);
 
+/*
+ * Determine the type of the specified filesystem and print it. Optionally it is
+ * possible to store the type directly in env.
+ */
+int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
 #endif /* _FS_H */
diff --git a/include/hash.h b/include/hash.h
index d8ec4f0..f4eb100 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -17,7 +17,6 @@
 	HASH_FLAG_ENV		= 1 << 1,	/* Allow env vars */
 };
 
-#ifndef USE_HOSTCC
 #if defined(CONFIG_SHA1SUM_VERIFY) || defined(CONFIG_CRC32_VERIFY)
 #define CONFIG_HASH_VERIFY
 #endif
@@ -77,6 +76,7 @@
 			   int size);
 };
 
+#ifndef USE_HOSTCC
 /**
  * hash_command: Process a hash command for a particular algorithm
  *
@@ -115,19 +115,6 @@
 	       uint8_t *output, int *output_size);
 
 /**
- * hash_lookup_algo() - Look up the hash_algo struct for an algorithm
- *
- * The function returns the pointer to the struct or -EPROTONOSUPPORT if the
- * algorithm is not available.
- *
- * @algo_name: Hash algorithm to look up
- * @algop: Pointer to the hash_algo struct if found
- *
- * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
- */
-int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
-
-/**
  * hash_show() - Print out a hash algorithm and value
  *
  * You will get a message like this (without a newline at the end):
@@ -141,5 +128,34 @@
  */
 void hash_show(struct hash_algo *algo, ulong addr, ulong len,
 	       uint8_t *output);
+
 #endif /* !USE_HOSTCC */
+
+/**
+ * hash_lookup_algo() - Look up the hash_algo struct for an algorithm
+ *
+ * The function returns the pointer to the struct or -EPROTONOSUPPORT if the
+ * algorithm is not available.
+ *
+ * @algo_name: Hash algorithm to look up
+ * @algop: Pointer to the hash_algo struct if found
+ *
+ * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
+ */
+int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
+
+/**
+ * hash_progressive_lookup_algo() - Look up hash_algo for prog. hash support
+ *
+ * The function returns the pointer to the struct or -EPROTONOSUPPORT if the
+ * algorithm is not available with progressive hash support.
+ *
+ * @algo_name: Hash algorithm to look up
+ * @algop: Pointer to the hash_algo struct if found
+ *
+ * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
+ */
+int hash_progressive_lookup_algo(const char *algo_name,
+				 struct hash_algo **algop);
+
 #endif
diff --git a/include/i2c.h b/include/i2c.h
index 9c6a60c..31b0389 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -25,22 +25,21 @@
  * enough as to be incompatible for compilation purposes.
  */
 
-#ifdef CONFIG_DM_I2C
-
 enum dm_i2c_chip_flags {
 	DM_I2C_CHIP_10BIT	= 1 << 0, /* Use 10-bit addressing */
 	DM_I2C_CHIP_RD_ADDRESS	= 1 << 1, /* Send address for each read byte */
 	DM_I2C_CHIP_WR_ADDRESS	= 1 << 2, /* Send address for each write byte */
 };
 
+struct udevice;
 /**
  * struct dm_i2c_chip - information about an i2c chip
  *
  * An I2C chip is a device on the I2C bus. It sits at a particular address
  * and normally supports 7-bit or 10-bit addressing.
  *
- * To obtain this structure, use dev_get_parentdata(dev) where dev is the
- * chip to examine.
+ * To obtain this structure, use dev_get_parent_platdata(dev) where dev is
+ * the chip to examine.
  *
  * @chip_addr:	Chip address on bus
  * @offset_len: Length of offset in bytes. A single byte offset can
@@ -75,7 +74,7 @@
 };
 
 /**
- * i2c_read() - read bytes from an I2C chip
+ * dm_i2c_read() - read bytes from an I2C chip
  *
  * To obtain an I2C device (called a 'chip') given the I2C bus address you
  * can use i2c_get_chip(). To obtain a bus by bus number use
@@ -91,13 +90,12 @@
  *
  * @return 0 on success, -ve on failure
  */
-int i2c_read(struct udevice *dev, uint offset, uint8_t *buffer,
-	     int len);
+int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len);
 
 /**
- * i2c_write() - write bytes to an I2C chip
+ * dm_i2c_write() - write bytes to an I2C chip
  *
- * See notes for i2c_read() above.
+ * See notes for dm_i2c_read() above.
  *
  * @dev:	Chip to write to
  * @offset:	Offset within chip to start writing
@@ -106,11 +104,11 @@
  *
  * @return 0 on success, -ve on failure
  */
-int i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
-	      int len);
+int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
+		 int len);
 
 /**
- * i2c_probe() - probe a particular chip address
+ * dm_i2c_probe() - probe a particular chip address
  *
  * This can be useful to check for the existence of a chip on the bus.
  * It is typically implemented by writing the chip address to the bus
@@ -122,25 +120,25 @@
  * @devp:	Returns the device found, or NULL if none
  * @return 0 if a chip was found at that address, -ve if not
  */
-int i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
-	      struct udevice **devp);
+int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
+		 struct udevice **devp);
 
 /**
- * i2c_set_bus_speed() - set the speed of a bus
+ * dm_i2c_set_bus_speed() - set the speed of a bus
  *
  * @bus:	Bus to adjust
  * @speed:	Requested speed in Hz
  * @return 0 if OK, -EINVAL for invalid values
  */
-int i2c_set_bus_speed(struct udevice *bus, unsigned int speed);
+int dm_i2c_set_bus_speed(struct udevice *bus, unsigned int speed);
 
 /**
- * i2c_get_bus_speed() - get the speed of a bus
+ * dm_i2c_get_bus_speed() - get the speed of a bus
  *
  * @bus:	Bus to check
  * @return speed of selected I2C bus in Hz, -ve on error
  */
-int i2c_get_bus_speed(struct udevice *bus);
+int dm_i2c_get_bus_speed(struct udevice *bus);
 
 /**
  * i2c_set_chip_flags() - set flags for a chip
@@ -185,6 +183,80 @@
  */
 int i2c_deblock(struct udevice *bus);
 
+#ifdef CONFIG_DM_I2C_COMPAT
+/**
+ * i2c_probe() - Compatibility function for driver model
+ *
+ * Calls dm_i2c_probe() on the current bus
+ */
+int i2c_probe(uint8_t chip_addr);
+
+/**
+ * i2c_read() - Compatibility function for driver model
+ *
+ * Calls dm_i2c_read() with the device corresponding to @chip_addr, and offset
+ * set to @addr. @alen must match the current setting for the device.
+ */
+int i2c_read(uint8_t chip_addr, unsigned int addr, int alen, uint8_t *buffer,
+	     int len);
+
+/**
+ * i2c_write() - Compatibility function for driver model
+ *
+ * Calls dm_i2c_write() with the device corresponding to @chip_addr, and offset
+ * set to @addr. @alen must match the current setting for the device.
+ */
+int i2c_write(uint8_t chip_addr, unsigned int addr, int alen, uint8_t *buffer,
+	      int len);
+
+/**
+ * i2c_get_bus_num_fdt() - Compatibility function for driver model
+ *
+ * @return the bus number associated with the given device tree node
+ */
+int i2c_get_bus_num_fdt(int node);
+
+/**
+ * i2c_get_bus_num() - Compatibility function for driver model
+ *
+ * @return the 'current' bus number
+ */
+unsigned int i2c_get_bus_num(void);
+
+/**
+ * i2c_set_bus_num() - Compatibility function for driver model
+ *
+ * Sets the 'current' bus
+ */
+int i2c_set_bus_num(unsigned int bus);
+
+static inline void I2C_SET_BUS(unsigned int bus)
+{
+	i2c_set_bus_num(bus);
+}
+
+static inline unsigned int I2C_GET_BUS(void)
+{
+	return i2c_get_bus_num();
+}
+
+/**
+ * i2c_init() - Compatibility function for driver model
+ *
+ * This function does nothing.
+ */
+void i2c_init(int speed, int slaveaddr);
+
+/**
+ * board_i2c_init() - Compatibility function for driver model
+ *
+ * @param blob  Device tree blbo
+ * @return the number of I2C bus
+ */
+void board_i2c_init(const void *blob);
+
+#endif
+
 /*
  * Not all of these flags are implemented in the U-Boot API
  */
@@ -330,10 +402,12 @@
  *
  * @bus:	Bus to examine
  * @chip_addr:	Chip address for the new device
+ * @offset_len:	Length of a register offset in bytes (normally 1)
  * @devp:	Returns pointer to new device if found or -ENODEV if not
  *		found
  */
-int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp);
+int i2c_get_chip(struct udevice *bus, uint chip_addr, uint offset_len,
+		 struct udevice **devp);
 
 /**
  * i2c_get_chip() - get a device to use to access a chip on a bus number
@@ -343,10 +417,12 @@
  *
  * @busnum:	Bus number to examine
  * @chip_addr:	Chip address for the new device
+ * @offset_len:	Length of a register offset in bytes (normally 1)
  * @devp:	Returns pointer to new device if found or -ENODEV if not
  *		found
  */
-int i2c_get_chip_for_busnum(int busnum, int chip_addr, struct udevice **devp);
+int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
+			    struct udevice **devp);
 
 /**
  * i2c_chip_ofdata_to_platdata() - Decode standard I2C platform data
@@ -362,8 +438,6 @@
 int i2c_chip_ofdata_to_platdata(const void *blob, int node,
 				struct dm_i2c_chip *chip);
 
-#endif
-
 #ifndef CONFIG_DM_I2C
 
 /*
diff --git a/include/image.h b/include/image.h
index ee3afe3..0e6af00 100644
--- a/include/image.h
+++ b/include/image.h
@@ -751,6 +751,7 @@
 int fit_parse_subimage(const char *spec, ulong addr_curr,
 		ulong *addr, const char **image_name);
 
+int fit_get_subimage_count(const void *fit, int images_noffset);
 void fit_print_contents(const void *fit);
 void fit_image_print(const void *fit, int noffset, const char *p);
 
@@ -927,8 +928,9 @@
 #if IMAGE_ENABLE_SIGN
 	const EVP_MD *(*calculate_sign)(void);
 #endif
-	void (*calculate)(const struct image_region region[],
-			  int region_count, uint8_t *checksum);
+	int (*calculate)(const char *name,
+			 const struct image_region region[],
+			 int region_count, uint8_t *checksum);
 	const uint8_t *rsa_padding;
 };
 
diff --git a/include/lcd.h b/include/lcd.h
index 160f940..f049fd3 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -13,21 +13,19 @@
 #ifndef _LCD_H_
 #define _LCD_H_
 #include <lcd_console.h>
+#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
+#include <bmp_layout.h>
+#include <asm/byteorder.h>
+#endif
 
 extern char lcd_is_enabled;
-
 extern int lcd_line_length;
-
 extern struct vidinfo panel_info;
 
 void lcd_ctrl_init(void *lcdbase);
 void lcd_enable(void);
-
-/* setcolreg used in 8bpp/16bpp; initcolregs used in monochrome */
 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue);
-void lcd_initcolregs(void);
 
-/* gunzip_bmp used if CONFIG_VIDEO_BMP_GZIP */
 struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
 			     void **alloc_addr);
 int bmp_display(ulong addr, int x, int y);
@@ -41,227 +39,38 @@
 void lcd_set_flush_dcache(int flush);
 
 #if defined CONFIG_MPC823
-/*
- * LCD controller stucture for MPC823 CPU
- */
-typedef struct vidinfo {
-	ushort	vl_col;		/* Number of columns (i.e. 640) */
-	ushort	vl_row;		/* Number of rows (i.e. 480) */
-	ushort	vl_width;	/* Width of display area in millimeters */
-	ushort	vl_height;	/* Height of display area in millimeters */
-
-	/* LCD configuration register */
-	u_char	vl_clkp;	/* Clock polarity */
-	u_char	vl_oep;		/* Output Enable polarity */
-	u_char	vl_hsp;		/* Horizontal Sync polarity */
-	u_char	vl_vsp;		/* Vertical Sync polarity */
-	u_char	vl_dp;		/* Data polarity */
-	u_char	vl_bpix;	/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
-	u_char	vl_lbw;		/* LCD Bus width, 0 = 4, 1 = 8 */
-	u_char	vl_splt;	/* Split display, 0 = single-scan, 1 = dual-scan */
-	u_char	vl_clor;	/* Color, 0 = mono, 1 = color */
-	u_char	vl_tft;		/* 0 = passive, 1 = TFT */
-
-	/* Horizontal control register. Timing from data sheet */
-	ushort	vl_wbl;		/* Wait between lines */
-
-	/* Vertical control register */
-	u_char	vl_vpw;		/* Vertical sync pulse width */
-	u_char	vl_lcdac;	/* LCD AC timing */
-	u_char	vl_wbf;		/* Wait between frames */
-} vidinfo_t;
-
+#include <mpc823_lcd.h>
 #elif defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
 	defined CONFIG_CPU_MONAHANS
-/*
- * PXA LCD DMA descriptor
- */
-struct pxafb_dma_descriptor {
-	u_long	fdadr;		/* Frame descriptor address register */
-	u_long	fsadr;		/* Frame source address register */
-	u_long	fidr;		/* Frame ID register */
-	u_long	ldcmd;		/* Command register */
-};
-
-/*
- * PXA LCD info
- */
-struct pxafb_info {
-
-	/* Misc registers */
-	u_long	reg_lccr3;
-	u_long	reg_lccr2;
-	u_long	reg_lccr1;
-	u_long	reg_lccr0;
-	u_long	fdadr0;
-	u_long	fdadr1;
-
-	/* DMA descriptors */
-	struct	pxafb_dma_descriptor *	dmadesc_fblow;
-	struct	pxafb_dma_descriptor *	dmadesc_fbhigh;
-	struct	pxafb_dma_descriptor *	dmadesc_palette;
-
-	u_long	screen;		/* physical address of frame buffer */
-	u_long	palette;	/* physical address of palette memory */
-	u_int	palette_size;
-};
-
-/*
- * LCD controller stucture for PXA CPU
- */
-typedef struct vidinfo {
-	ushort	vl_col;		/* Number of columns (i.e. 640) */
-	ushort	vl_row;		/* Number of rows (i.e. 480) */
-	ushort	vl_width;	/* Width of display area in millimeters */
-	ushort	vl_height;	/* Height of display area in millimeters */
-
-	/* LCD configuration register */
-	u_char	vl_clkp;	/* Clock polarity */
-	u_char	vl_oep;		/* Output Enable polarity */
-	u_char	vl_hsp;		/* Horizontal Sync polarity */
-	u_char	vl_vsp;		/* Vertical Sync polarity */
-	u_char	vl_dp;		/* Data polarity */
-	u_char	vl_bpix;	/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 = 16 */
-	u_char	vl_lbw;		/* LCD Bus width, 0 = 4, 1 = 8 */
-	u_char	vl_splt;	/* Split display, 0 = single-scan, 1 = dual-scan */
-	u_char	vl_clor;	/* Color, 0 = mono, 1 = color */
-	u_char	vl_tft;		/* 0 = passive, 1 = TFT */
-
-	/* Horizontal control register. Timing from data sheet */
-	ushort	vl_hpw;		/* Horz sync pulse width */
-	u_char	vl_blw;		/* Wait before of line */
-	u_char	vl_elw;		/* Wait end of line */
-
-	/* Vertical control register. */
-	u_char	vl_vpw;		/* Vertical sync pulse width */
-	u_char	vl_bfw;		/* Wait before of frame */
-	u_char	vl_efw;		/* Wait end of frame */
-
-	/* PXA LCD controller params */
-	struct	pxafb_info pxa;
-} vidinfo_t;
-
+#include <pxa_lcd.h>
 #elif defined(CONFIG_ATMEL_LCD) || defined(CONFIG_ATMEL_HLCD)
-
-typedef struct vidinfo {
-	ushort vl_col;		/* Number of columns (i.e. 640) */
-	ushort vl_row;		/* Number of rows (i.e. 480) */
-	u_long vl_clk;	/* pixel clock in ps    */
-
-	/* LCD configuration register */
-	u_long vl_sync;		/* Horizontal / vertical sync */
-	u_long vl_bpix;		/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 = 16 */
-	u_long vl_tft;		/* 0 = passive, 1 = TFT */
-	u_long vl_cont_pol_low;	/* contrast polarity is low */
-	u_long vl_clk_pol;	/* clock polarity */
-
-	/* Horizontal control register. */
-	u_long vl_hsync_len;	/* Length of horizontal sync */
-	u_long vl_left_margin;	/* Time from sync to picture */
-	u_long vl_right_margin;	/* Time from picture to sync */
-
-	/* Vertical control register. */
-	u_long vl_vsync_len;	/* Length of vertical sync */
-	u_long vl_upper_margin;	/* Time from sync to picture */
-	u_long vl_lower_margin;	/* Time from picture to sync */
-
-	u_long	mmio;		/* Memory mapped registers */
-} vidinfo_t;
-
+#include <atmel_lcd.h>
 #elif defined(CONFIG_EXYNOS_FB)
-
-enum {
-	FIMD_RGB_INTERFACE = 1,
-	FIMD_CPU_INTERFACE = 2,
-};
-
-enum exynos_fb_rgb_mode_t {
-	MODE_RGB_P = 0,
-	MODE_BGR_P = 1,
-	MODE_RGB_S = 2,
-	MODE_BGR_S = 3,
-};
-
-typedef struct vidinfo {
-	ushort vl_col;		/* Number of columns (i.e. 640) */
-	ushort vl_row;		/* Number of rows (i.e. 480) */
-	ushort vl_width;	/* Width of display area in millimeters */
-	ushort vl_height;	/* Height of display area in millimeters */
-
-	/* LCD configuration register */
-	u_char vl_freq;		/* Frequency */
-	u_char vl_clkp;		/* Clock polarity */
-	u_char vl_oep;		/* Output Enable polarity */
-	u_char vl_hsp;		/* Horizontal Sync polarity */
-	u_char vl_vsp;		/* Vertical Sync polarity */
-	u_char vl_dp;		/* Data polarity */
-	u_char vl_bpix;		/* Bits per pixel */
-
-	/* Horizontal control register. Timing from data sheet */
-	u_char vl_hspw;		/* Horz sync pulse width */
-	u_char vl_hfpd;		/* Wait before of line */
-	u_char vl_hbpd;		/* Wait end of line */
-
-	/* Vertical control register. */
-	u_char	vl_vspw;	/* Vertical sync pulse width */
-	u_char	vl_vfpd;	/* Wait before of frame */
-	u_char	vl_vbpd;	/* Wait end of frame */
-	u_char  vl_cmd_allow_len; /* Wait end of frame */
-
-	unsigned int win_id;
-	unsigned int init_delay;
-	unsigned int power_on_delay;
-	unsigned int reset_delay;
-	unsigned int interface_mode;
-	unsigned int mipi_enabled;
-	unsigned int dp_enabled;
-	unsigned int cs_setup;
-	unsigned int wr_setup;
-	unsigned int wr_act;
-	unsigned int wr_hold;
-	unsigned int logo_on;
-	unsigned int logo_width;
-	unsigned int logo_height;
-	int logo_x_offset;
-	int logo_y_offset;
-	unsigned long logo_addr;
-	unsigned int rgb_mode;
-	unsigned int resolution;
-
-	/* parent clock name(MPLL, EPLL or VPLL) */
-	unsigned int pclk_name;
-	/* ratio value for source clock from parent clock. */
-	unsigned int sclk_div;
-
-	unsigned int dual_lcd_enabled;
-} vidinfo_t;
-
-void init_panel_info(vidinfo_t *vid);
-
+#include <exynos_lcd.h>
 #else
-
 typedef struct vidinfo {
 	ushort	vl_col;		/* Number of columns (i.e. 160) */
 	ushort	vl_row;		/* Number of rows (i.e. 100) */
-
 	u_char	vl_bpix;	/* Bits per pixel, 0 = 1 */
-
 	ushort	*cmap;		/* Pointer to the colormap */
-
 	void	*priv;		/* Pointer to driver-specific data */
 } vidinfo_t;
 
-#endif /* CONFIG_MPC823, CONFIG_CPU_PXA25X, CONFIG_ATMEL_LCD */
+static __maybe_unused ushort *configuration_get_cmap(void)
+{
+	return panel_info.cmap;
+}
+#endif
+
+ushort *configuration_get_cmap(void);
 
 extern vidinfo_t panel_info;
 
-/* Video functions */
-
-void	lcd_putc(const char c);
-void	lcd_puts(const char *s);
-void	lcd_printf(const char *fmt, ...);
-void	lcd_clear(void);
-int	lcd_display_bitmap(ulong bmp_image, int x, int y);
+void lcd_putc(const char c);
+void lcd_puts(const char *s);
+void lcd_printf(const char *fmt, ...);
+void lcd_clear(void);
+int lcd_display_bitmap(ulong bmp_image, int x, int y);
 
 /**
  * Get the width of the LCD in pixels
@@ -319,20 +128,9 @@
 /* Return the size of the LCD frame buffer, and the line length */
 int lcd_get_size(int *line_length);
 
-int lcd_dt_simplefb_add_node(void *blob);
-int lcd_dt_simplefb_enable_existing_node(void *blob);
-
 /* Update the LCD / flush the cache */
 void lcd_sync(void);
 
-/************************************************************************/
-/* ** BITMAP DISPLAY SUPPORT						*/
-/************************************************************************/
-#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
-# include <bmp_layout.h>
-# include <asm/byteorder.h>
-#endif
-
 /*
  *  Information about displays we are using. This is for configuring
  *  the LCD controller and memory allocation. Someone has to know what
@@ -347,38 +145,32 @@
 #define LCD_COLOR8	3
 #define LCD_COLOR16	4
 #define LCD_COLOR32	5
-/*----------------------------------------------------------------------*/
+
 #if defined(CONFIG_LCD_INFO_BELOW_LOGO)
-# define LCD_INFO_X		0
-# define LCD_INFO_Y		(BMP_LOGO_HEIGHT + VIDEO_FONT_HEIGHT)
+#define LCD_INFO_X		0
+#define LCD_INFO_Y		(BMP_LOGO_HEIGHT + VIDEO_FONT_HEIGHT)
 #elif defined(CONFIG_LCD_LOGO)
-# define LCD_INFO_X		(BMP_LOGO_WIDTH + 4 * VIDEO_FONT_WIDTH)
-# define LCD_INFO_Y		VIDEO_FONT_HEIGHT
+#define LCD_INFO_X		(BMP_LOGO_WIDTH + 4 * VIDEO_FONT_WIDTH)
+#define LCD_INFO_Y		VIDEO_FONT_HEIGHT
 #else
-# define LCD_INFO_X		VIDEO_FONT_WIDTH
-# define LCD_INFO_Y		VIDEO_FONT_HEIGHT
+#define LCD_INFO_X		VIDEO_FONT_WIDTH
+#define LCD_INFO_Y		VIDEO_FONT_HEIGHT
 #endif
 
 /* Default to 8bpp if bit depth not specified */
 #ifndef LCD_BPP
-# define LCD_BPP			LCD_COLOR8
+#define LCD_BPP			LCD_COLOR8
 #endif
+
 #ifndef LCD_DF
-# define LCD_DF			1
+#define LCD_DF			1
 #endif
 
 /* Calculate nr. of bits per pixel  and nr. of colors */
 #define NBITS(bit_code)		(1 << (bit_code))
 #define NCOLORS(bit_code)	(1 << NBITS(bit_code))
 
-/************************************************************************/
-/* ** CONSOLE CONSTANTS							*/
-/************************************************************************/
 #if LCD_BPP == LCD_COLOR8
-
-/*
- * 8bpp color definitions
- */
 # define CONSOLE_COLOR_BLACK	0
 # define CONSOLE_COLOR_RED	1
 # define CONSOLE_COLOR_GREEN	2
@@ -387,38 +179,25 @@
 # define CONSOLE_COLOR_MAGENTA	5
 # define CONSOLE_COLOR_CYAN	6
 # define CONSOLE_COLOR_GREY	14
-# define CONSOLE_COLOR_WHITE	15	/* Must remain last / highest	*/
-
+# define CONSOLE_COLOR_WHITE	15		/* Must remain last / highest */
 #elif LCD_BPP == LCD_COLOR32
-/*
- * 32bpp color definitions
- */
-# define CONSOLE_COLOR_RED	0x00ff0000
-# define CONSOLE_COLOR_GREEN	0x0000ff00
-# define CONSOLE_COLOR_YELLOW	0x00ffff00
-# define CONSOLE_COLOR_BLUE	0x000000ff
-# define CONSOLE_COLOR_MAGENTA	0x00ff00ff
-# define CONSOLE_COLOR_CYAN	0x0000ffff
-# define CONSOLE_COLOR_GREY	0x00aaaaaa
-# define CONSOLE_COLOR_BLACK	0x00000000
-# define CONSOLE_COLOR_WHITE	0x00ffffff	/* Must remain last / highest*/
-# define NBYTES(bit_code)	(NBITS(bit_code) >> 3)
-
-#else
-
-/*
- * 16bpp color definitions
- */
-# define CONSOLE_COLOR_BLACK	0x0000
-# define CONSOLE_COLOR_WHITE	0xffff	/* Must remain last / highest	*/
-
+#define CONSOLE_COLOR_RED	0x00ff0000
+#define CONSOLE_COLOR_GREEN	0x0000ff00
+#define CONSOLE_COLOR_YELLOW	0x00ffff00
+#define CONSOLE_COLOR_BLUE	0x000000ff
+#define CONSOLE_COLOR_MAGENTA	0x00ff00ff
+#define CONSOLE_COLOR_CYAN	0x0000ffff
+#define CONSOLE_COLOR_GREY	0x00aaaaaa
+#define CONSOLE_COLOR_BLACK	0x00000000
+#define CONSOLE_COLOR_WHITE	0x00ffffff	/* Must remain last / highest */
+#define NBYTES(bit_code)	(NBITS(bit_code) >> 3)
+#else /* 16bpp color definitions */
+#define CONSOLE_COLOR_BLACK	0x0000
+#define CONSOLE_COLOR_WHITE	0xffff		/* Must remain last / highest */
 #endif /* color definitions */
 
-/************************************************************************/
 #ifndef PAGE_SIZE
-# define PAGE_SIZE	4096
+#define PAGE_SIZE	4096
 #endif
 
-/************************************************************************/
-
 #endif	/* _LCD_H_ */
diff --git a/include/linker_lists.h b/include/linker_lists.h
index d37fba4..940c871 100644
--- a/include/linker_lists.h
+++ b/include/linker_lists.h
@@ -23,7 +23,7 @@
 
 /**
  * A linker list is constructed by grouping together linker input
- * sections, each containning one entry of the list. Each input section
+ * sections, each containing one entry of the list. Each input section
  * contains a constant initialized variable which holds the entry's
  * content. Linker list input sections are constructed from the list
  * and entry names, plus a prefix which allows grouping all lists
@@ -39,7 +39,7 @@
  * This ensures uniqueness for both input section and C variable name.
  *
  * Note that the names differ only in the first character, "." for the
- * setion and "_" for the variable, so that the linker cannot confuse
+ * section and "_" for the variable, so that the linker cannot confuse
  * section and symbol names. From now on, both names will be referred
  * to as
  *
diff --git a/include/linux/compat.h b/include/linux/compat.h
index b40133c..6eac17f 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -262,7 +262,6 @@
 
 /* from include/linux/types.h */
 
-typedef int	atomic_t;
 /**
  * struct callback_head - callback structure for use with RCU and task_work
  * @next: next update requests in a list
diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h
new file mode 100644
index 0000000..c8c5659
--- /dev/null
+++ b/include/linux/compiler-gcc5.h
@@ -0,0 +1,65 @@
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead."
+#endif
+
+#define __used				__attribute__((__used__))
+#define __must_check			__attribute__((warn_unused_result))
+#define __compiler_offsetof(a, b)	__builtin_offsetof(a, b)
+
+/* Mark functions as cold. gcc will assume any path leading to a call
+   to them will be unlikely.  This means a lot of manual unlikely()s
+   are unnecessary now for any paths leading to the usual suspects
+   like BUG(), printk(), panic() etc. [but let's keep them for now for
+   older compilers]
+
+   Early snapshots of gcc 4.3 don't support this and we can't detect this
+   in the preprocessor, but we can live with this because they're unreleased.
+   Maketime probing would be overkill here.
+
+   gcc also has a __attribute__((__hot__)) to move hot functions into
+   a special section, but I don't see any sense in this right now in
+   the kernel context */
+#define __cold			__attribute__((__cold__))
+
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+#ifndef __CHECKER__
+# define __compiletime_warning(message) __attribute__((warning(message)))
+# define __compiletime_error(message) __attribute__((error(message)))
+#endif /* __CHECKER__ */
+
+/*
+ * Mark a position in code as unreachable.  This can be used to
+ * suppress control flow warnings after asm blocks that transfer
+ * control elsewhere.
+ *
+ * Early snapshots of gcc 4.5 don't support this and we can't detect
+ * this in the preprocessor, but we can live with this because they're
+ * unreleased.  Really, we need to have autoconf for the kernel.
+ */
+#define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone	__attribute__((__noclone__))
+
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#define asm_volatile_goto(x...)	do { asm goto(x); asm (""); } while (0)
+
+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
diff --git a/include/mmc.h b/include/mmc.h
index 09101e2..7d6feca 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -14,24 +14,41 @@
 #include <linux/compiler.h>
 #include <part.h>
 
-#define SD_VERSION_SD	0x20000
-#define SD_VERSION_3	(SD_VERSION_SD | 0x300)
-#define SD_VERSION_2	(SD_VERSION_SD | 0x200)
-#define SD_VERSION_1_0	(SD_VERSION_SD | 0x100)
-#define SD_VERSION_1_10	(SD_VERSION_SD | 0x10a)
-#define MMC_VERSION_MMC		0x10000
-#define MMC_VERSION_UNKNOWN	(MMC_VERSION_MMC)
-#define MMC_VERSION_1_2		(MMC_VERSION_MMC | 0x102)
-#define MMC_VERSION_1_4		(MMC_VERSION_MMC | 0x104)
-#define MMC_VERSION_2_2		(MMC_VERSION_MMC | 0x202)
-#define MMC_VERSION_3		(MMC_VERSION_MMC | 0x300)
-#define MMC_VERSION_4		(MMC_VERSION_MMC | 0x400)
-#define MMC_VERSION_4_1		(MMC_VERSION_MMC | 0x401)
-#define MMC_VERSION_4_2		(MMC_VERSION_MMC | 0x402)
-#define MMC_VERSION_4_3		(MMC_VERSION_MMC | 0x403)
-#define MMC_VERSION_4_41	(MMC_VERSION_MMC | 0x429)
-#define MMC_VERSION_4_5		(MMC_VERSION_MMC | 0x405)
-#define MMC_VERSION_5_0		(MMC_VERSION_MMC | 0x500)
+/* SD/MMC version bits; 8 flags, 8 major, 8 minor, 8 change */
+#define SD_VERSION_SD	(1U << 31)
+#define MMC_VERSION_MMC	(1U << 30)
+
+#define MAKE_SDMMC_VERSION(a, b, c)	\
+	((((u32)(a)) << 16) | ((u32)(b) << 8) | (u32)(c))
+#define MAKE_SD_VERSION(a, b, c)	\
+	(SD_VERSION_SD | MAKE_SDMMC_VERSION(a, b, c))
+#define MAKE_MMC_VERSION(a, b, c)	\
+	(MMC_VERSION_MMC | MAKE_SDMMC_VERSION(a, b, c))
+
+#define EXTRACT_SDMMC_MAJOR_VERSION(x)	\
+	(((u32)(x) >> 16) & 0xff)
+#define EXTRACT_SDMMC_MINOR_VERSION(x)	\
+	(((u32)(x) >> 8) & 0xff)
+#define EXTRACT_SDMMC_CHANGE_VERSION(x)	\
+	((u32)(x) & 0xff)
+
+#define SD_VERSION_3		MAKE_SD_VERSION(3, 0, 0)
+#define SD_VERSION_2		MAKE_SD_VERSION(2, 0, 0)
+#define SD_VERSION_1_0		MAKE_SD_VERSION(1, 0, 0)
+#define SD_VERSION_1_10		MAKE_SD_VERSION(1, 10, 0)
+
+#define MMC_VERSION_UNKNOWN	MAKE_MMC_VERSION(0, 0, 0)
+#define MMC_VERSION_1_2		MAKE_MMC_VERSION(1, 2, 0)
+#define MMC_VERSION_1_4		MAKE_MMC_VERSION(1, 4, 0)
+#define MMC_VERSION_2_2		MAKE_MMC_VERSION(2, 2, 0)
+#define MMC_VERSION_3		MAKE_MMC_VERSION(3, 0, 0)
+#define MMC_VERSION_4		MAKE_MMC_VERSION(4, 0, 0)
+#define MMC_VERSION_4_1		MAKE_MMC_VERSION(4, 1, 0)
+#define MMC_VERSION_4_2		MAKE_MMC_VERSION(4, 2, 0)
+#define MMC_VERSION_4_3		MAKE_MMC_VERSION(4, 3, 0)
+#define MMC_VERSION_4_41	MAKE_MMC_VERSION(4, 4, 1)
+#define MMC_VERSION_4_5		MAKE_MMC_VERSION(4, 5, 0)
+#define MMC_VERSION_5_0		MAKE_MMC_VERSION(5, 0, 0)
 
 #define MMC_MODE_HS		(1 << 0)
 #define MMC_MODE_HS_52MHz	(1 << 1)
@@ -43,7 +60,8 @@
 
 #define SD_DATA_4BIT	0x00040000
 
-#define IS_SD(x) (x->version & SD_VERSION_SD)
+#define IS_SD(x)	((x)->version & SD_VERSION_SD)
+#define IS_MMC(x)	((x)->version & SD_VERSION_MMC)
 
 #define MMC_DATA_READ		1
 #define MMC_DATA_WRITE		2
@@ -438,6 +456,20 @@
 int cpu_mmc_init(bd_t *bis);
 int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
 
+struct pci_device_id;
+
+/**
+ * pci_mmc_init() - set up PCI MMC devices
+ *
+ * This finds all the matching PCI IDs and sets them up as MMC devices.
+ *
+ * @name:		Name to use for devices
+ * @mmc_supported:	PCI IDs to search for
+ * @num_ids:		Number of elements in @mmc_supported
+ */
+int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported,
+		 int num_ids);
+
 /* Set block count limit because of 16 bit register limit on some hardware*/
 #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
 #define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
diff --git a/include/mpc823_lcd.h b/include/mpc823_lcd.h
new file mode 100644
index 0000000..7e210e3
--- /dev/null
+++ b/include/mpc823_lcd.h
@@ -0,0 +1,43 @@
+/*
+ * mpc823_lcd.h - MPC823 LCD Controller structures
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _MPC823_LCD_H_
+#define _MPC823_LCD_H_
+
+/*
+ * LCD controller stucture for MPC823 CPU
+ */
+typedef struct vidinfo {
+	ushort	vl_col;		/* Number of columns (i.e. 640) */
+	ushort	vl_row;		/* Number of rows (i.e. 480) */
+	ushort	vl_width;	/* Width of display area in millimeters */
+	ushort	vl_height;	/* Height of display area in millimeters */
+
+	/* LCD configuration register */
+	u_char	vl_clkp;	/* Clock polarity */
+	u_char	vl_oep;		/* Output Enable polarity */
+	u_char	vl_hsp;		/* Horizontal Sync polarity */
+	u_char	vl_vsp;		/* Vertical Sync polarity */
+	u_char	vl_dp;		/* Data polarity */
+	u_char	vl_bpix;	/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
+	u_char	vl_lbw;		/* LCD Bus width, 0 = 4, 1 = 8 */
+	u_char	vl_splt; /* Split display, 0 = single-scan, 1 = dual-scan */
+	u_char	vl_clor;	/* Color, 0 = mono, 1 = color */
+	u_char	vl_tft;		/* 0 = passive, 1 = TFT */
+
+	/* Horizontal control register. Timing from data sheet */
+	ushort	vl_wbl;		/* Wait between lines */
+
+	/* Vertical control register */
+	u_char	vl_vpw;		/* Vertical sync pulse width */
+	u_char	vl_lcdac;	/* LCD AC timing */
+	u_char	vl_wbf;		/* Wait between frames */
+} vidinfo_t;
+
+#endif
diff --git a/include/net.h b/include/net.h
index 73ea88b..43e3d28 100644
--- a/include/net.h
+++ b/include/net.h
@@ -512,10 +512,6 @@
  */
 int ip_checksum_ok(const void *addr, unsigned nbytes);
 
-/* Checksum */
-extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
-extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
-
 /* Callbacks */
 extern rxhand_f *net_get_udp_handler(void);	/* Get UDP RX packet handler */
 extern void net_set_udp_handler(rxhand_f *);	/* Set UDP RX packet handler */
diff --git a/include/pci.h b/include/pci.h
index 4fbb8f6..004a048 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -644,8 +644,7 @@
 
 extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index);
 extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index);
-extern pci_dev_t pci_find_class(int wanted_class, int wanted_sub_code,
-				int wanted_prog_if, int index);
+pci_dev_t pci_find_class(unsigned int find_class, int index);
 
 extern int pci_hose_config_device(struct pci_controller *hose,
 				  pci_dev_t dev,
diff --git a/include/pci_ids.h b/include/pci_ids.h
index 26f4748..dc2ca21 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -1346,6 +1346,7 @@
 
 #define PCI_VENDOR_ID_REALTEK		0x10ec
 #define PCI_DEVICE_ID_REALTEK_8139	0x8139
+#define PCI_DEVICE_ID_REALTEK_8168	0x8168
 
 #define PCI_VENDOR_ID_XILINX		0x10ee
 #define PCI_DEVICE_ID_RME_DIGI96	0x3fc0
@@ -2591,9 +2592,17 @@
 #define PCI_DEVICE_ID_INTEL_MFD_EMMC0	0x0823
 #define PCI_DEVICE_ID_INTEL_MFD_EMMC1	0x0824
 #define PCI_DEVICE_ID_INTEL_MRST_SD2	0x084F
+#define PCI_DEVICE_ID_INTEL_QRK_SDIO	0x08A7
+#define PCI_DEVICE_ID_INTEL_QRK_UART	0x0936
+#define PCI_DEVICE_ID_INTEL_QRK_EMAC	0x0937
+#define PCI_DEVICE_ID_INTEL_QRK_ILB	0x095E
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
 #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB	0x0c60
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO	0x0f15
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD	0x0f16
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC	0x0f1c
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA	0x0f23
 #define PCI_DEVICE_ID_INTEL_82541ER	0x1078
 #define PCI_DEVICE_ID_INTEL_82541GI_LF	0x107c
 #define PCI_DEVICE_ID_INTEL_82542	0x1000
diff --git a/include/pci_rom.h b/include/pci_rom.h
index 4ba36eb..2f1665d 100644
--- a/include/pci_rom.h
+++ b/include/pci_rom.h
@@ -33,14 +33,25 @@
 	uint16_t reserved_2;
 };
 
+/*
+ * Determines which execution method is used and whether we allow falling back
+ * to the other if the requested method is not available.
+ */
+enum pci_rom_emul {
+	PCI_ROM_EMULATE		= 0 << 0,
+	PCI_ROM_USE_NATIVE	= 1 << 0,
+	PCI_ROM_ALLOW_FALLBACK	= 1 << 1,
+};
+
  /**
  * pci_run_vga_bios() - Run the VGA BIOS in an x86 PC
  *
  * @dev:	Video device containing the BIOS
  * @int15_handler:	Function to call to handle int 0x15
- * @emulate:	true to use the x86 emulator, false to run native
+ * @exec_method:	flags from enum pci_rom_emul
  */
-int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate);
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void),
+		     int exec_method);
 
 /**
  * board_map_oprom_vendev() - map several PCI IDs to the one the ROM expects
diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
index 1118489..d304658 100644
--- a/include/power/pfuze100_pmic.h
+++ b/include/power/pfuze100_pmic.h
@@ -16,14 +16,34 @@
 
 	PFUZE100_SW1ABVOL	= 0x20,
 	PFUZE100_SW1ABSTBY	= 0x21,
+	PFUZE100_SW1ABOFF	= 0x22,
+	PFUZE100_SW1ABMODE	= 0x23,
 	PUZE_100_SW1ABCONF	= 0x24,
 	PFUZE100_SW1CVOL	= 0x2e,
 	PFUZE100_SW1CSTBY	= 0x2f,
+	PFUZE100_SW1COFF	= 0x30,
+	PFUZE100_SW1CMODE	= 0x31,
 	PFUZE100_SW1CCONF	= 0x32,
 	PFUZE100_SW2VOL		= 0x35,
+	PFUZE100_SW2STBY	= 0x36,
+	PFUZE100_SW2OFF		= 0x37,
+	PFUZE100_SW2MODE	= 0x38,
+	PFUZE100_SW2CONF	= 0x39,
 	PFUZE100_SW3AVOL	= 0x3c,
+	PFUZE100_SW3ASTBY	= 0x3D,
+	PFUZE100_SW3AOFF	= 0x3E,
+	PFUZE100_SW3AMODE	= 0x3F,
+	PFUZE100_SW3ACONF	= 0x40,
 	PFUZE100_SW3BVOL	= 0x43,
+	PFUZE100_SW3BSTBY	= 0x44,
+	PFUZE100_SW3BOFF	= 0x45,
+	PFUZE100_SW3BMODE	= 0x46,
+	PFUZE100_SW3BCONF	= 0x47,
 	PFUZE100_SW4VOL		= 0x4a,
+	PFUZE100_SW4STBY	= 0x4b,
+	PFUZE100_SW4OFF		= 0x4c,
+	PFUZE100_SW4MODE	= 0x4d,
+	PFUZE100_SW4CONF	= 0x4e,
 	PFUZE100_SWBSTCON1	= 0x66,
 	PFUZE100_VREFDDRCON	= 0x6a,
 	PFUZE100_VSNVSVOL	= 0x6b,
@@ -41,6 +61,8 @@
  * Buck Regulators
  */
 
+#define PFUZE100_SW1ABC_SETP(x)	((x - 3000) / 250)
+
 /* SW1A/B/C Output Voltage Configuration */
 #define SW1x_0_300V 0
 #define SW1x_0_325V 1
@@ -177,5 +199,38 @@
 #define SWBST_MODE_AUTO	(2 << 2)
 #define SWBST_MODE_APS	(2 << 3)
 
+/*
+ * Regulator Mode Control
+ *
+ * OFF: The regulator is switched off and the output voltage is discharged.
+ * PFM: In this mode, the regulator is always in PFM mode, which is useful
+ *      at light loads for optimized efficiency.
+ * PWM: In this mode, the regulator is always in PWM mode operation
+ *	regardless of load conditions.
+ * APS: In this mode, the regulator moves automatically between pulse
+ *	skipping mode and PWM mode depending on load conditions.
+ *
+ * SWxMODE[3:0]
+ * Normal Mode  |  Standby Mode	|      value
+ *   OFF		OFF		0x0
+ *   PWM		OFF		0x1
+ *   PFM		OFF		0x3
+ *   APS		OFF		0x4
+ *   PWM		PWM		0x5
+ *   PWM		APS		0x6
+ *   APS		APS		0x8
+ *   APS		PFM		0xc
+ *   PWM		PFM		0xd
+ */
+#define OFF_OFF		0x0
+#define PWM_OFF		0x1
+#define PFM_OFF		0x3
+#define APS_OFF		0x4
+#define PWM_PWM		0x5
+#define PWM_APS		0x6
+#define APS_APS		0x8
+#define APS_PFM		0xc
+#define PWM_PFM		0xd
+
 int power_pfuze100_init(unsigned char bus);
 #endif
diff --git a/include/pxa_lcd.h b/include/pxa_lcd.h
new file mode 100644
index 0000000..723f6ab
--- /dev/null
+++ b/include/pxa_lcd.h
@@ -0,0 +1,80 @@
+/*
+ * pxa_lcd.h - PXA LCD Controller structures
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _PXA_LCD_H_
+#define _PXA_LCD_H_
+
+/*
+ * PXA LCD DMA descriptor
+ */
+struct pxafb_dma_descriptor {
+	u_long	fdadr;		/* Frame descriptor address register */
+	u_long	fsadr;		/* Frame source address register */
+	u_long	fidr;		/* Frame ID register */
+	u_long	ldcmd;		/* Command register */
+};
+
+/*
+ * PXA LCD info
+ */
+struct pxafb_info {
+	/* Misc registers */
+	u_long	reg_lccr3;
+	u_long	reg_lccr2;
+	u_long	reg_lccr1;
+	u_long	reg_lccr0;
+	u_long	fdadr0;
+	u_long	fdadr1;
+
+	/* DMA descriptors */
+	struct	pxafb_dma_descriptor *dmadesc_fblow;
+	struct	pxafb_dma_descriptor *dmadesc_fbhigh;
+	struct	pxafb_dma_descriptor *dmadesc_palette;
+
+	u_long	screen;		/* physical address of frame buffer */
+	u_long	palette;	/* physical address of palette memory */
+	u_int	palette_size;
+};
+
+/*
+ * LCD controller stucture for PXA CPU
+ */
+typedef struct vidinfo {
+	ushort	vl_col;		/* Number of columns (i.e. 640) */
+	ushort	vl_row;		/* Number of rows (i.e. 480) */
+	ushort	vl_width;	/* Width of display area in millimeters */
+	ushort	vl_height;	/* Height of display area in millimeters */
+
+	/* LCD configuration register */
+	u_char	vl_clkp;	/* Clock polarity */
+	u_char	vl_oep;		/* Output Enable polarity */
+	u_char	vl_hsp;		/* Horizontal Sync polarity */
+	u_char	vl_vsp;		/* Vertical Sync polarity */
+	u_char	vl_dp;		/* Data polarity */
+	u_char	vl_bpix;/* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8, 4 = 16 */
+	u_char	vl_lbw;		/* LCD Bus width, 0 = 4, 1 = 8 */
+	u_char	vl_splt;/* Split display, 0 = single-scan, 1 = dual-scan */
+	u_char	vl_clor;	/* Color, 0 = mono, 1 = color */
+	u_char	vl_tft;		/* 0 = passive, 1 = TFT */
+
+	/* Horizontal control register. Timing from data sheet */
+	ushort	vl_hpw;		/* Horz sync pulse width */
+	u_char	vl_blw;		/* Wait before of line */
+	u_char	vl_elw;		/* Wait end of line */
+
+	/* Vertical control register. */
+	u_char	vl_vpw;		/* Vertical sync pulse width */
+	u_char	vl_bfw;		/* Wait before of frame */
+	u_char	vl_efw;		/* Wait end of frame */
+
+	/* PXA LCD controller params */
+	struct	pxafb_info pxa;
+} vidinfo_t;
+
+#endif
diff --git a/include/sdhci.h b/include/sdhci.h
index aa4a0e9..23893b5 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -12,7 +12,7 @@
 
 #include <asm/io.h>
 #include <mmc.h>
-#include <fdtdec.h>
+#include <asm/gpio.h>
 
 /*
  * Controller registers
@@ -246,8 +246,8 @@
 	int index;
 
 	int bus_width;
-	struct fdt_gpio_state pwr_gpio;	/* Power GPIO */
-	struct fdt_gpio_state cd_gpio;		/* Card Detect GPIO */
+	struct gpio_desc pwr_gpio;	/* Power GPIO */
+	struct gpio_desc cd_gpio;		/* Card Detect GPIO */
 
 	void (*set_control_reg)(struct sdhci_host *host);
 	void (*set_clock)(int dev_index, unsigned int div);
diff --git a/include/spi.h b/include/spi.h
index ec17bd0..c58e453 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -56,20 +56,42 @@
 #define SPI_DEFAULT_WORDLEN 8
 
 #ifdef CONFIG_DM_SPI
+/* TODO(sjg@chromium.org): Remove this and use max_hz from struct spi_slave */
 struct dm_spi_bus {
 	uint max_hz;
 };
 
+/**
+ * struct dm_spi_platdata - platform data for all SPI slaves
+ *
+ * This describes a SPI slave, a child device of the SPI bus. To obtain this
+ * struct from a spi_slave, use dev_get_parent_platdata(dev) or
+ * dev_get_parent_platdata(slave->dev).
+ *
+ * This data is immuatable. Each time the device is probed, @max_hz and @mode
+ * will be copied to struct spi_slave.
+ *
+ * @cs:		Chip select number (0..n-1)
+ * @max_hz:	Maximum bus speed that this slave can tolerate
+ * @mode:	SPI mode to use for this device (see SPI mode flags)
+ */
+struct dm_spi_slave_platdata {
+	unsigned int cs;
+	uint max_hz;
+	uint mode;
+};
+
 #endif /* CONFIG_DM_SPI */
 
 /**
  * struct spi_slave - Representation of a SPI slave
  *
  * For driver model this is the per-child data used by the SPI bus. It can
- * be accessed using dev_get_parentdata() on the slave device. Each SPI
- * driver should define this child data in its U_BOOT_DRIVER() definition:
- *
- *	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
+ * be accessed using dev_get_parentdata() on the slave device. The SPI uclass
+ * sets uip per_child_auto_alloc_size to sizeof(struct spi_slave), and the
+ * driver should not override it. Two platform data fields (max_hz and mode)
+ * are copied into this structure to provide an initial value. This allows
+ * them to be changed, since we should never change platform data in drivers.
  *
  * If not using driver model, drivers are expected to extend this with
  * controller-specific data.
@@ -97,8 +119,8 @@
 	uint mode;
 #else
 	unsigned int bus;
-#endif
 	unsigned int cs;
+#endif
 	u8 op_mode_rx;
 	u8 op_mode_tx;
 	unsigned int wordlen;
@@ -545,16 +567,16 @@
 int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp);
 
 /**
- * spi_ofdata_to_platdata() - decode standard SPI platform data
+ * spi_slave_ofdata_to_platdata() - decode standard SPI platform data
  *
- * This decodes the speed and mode from a device tree node and puts it into
- * the spi_slave structure.
+ * This decodes the speed and mode for a slave from a device tree node
  *
  * @blob:	Device tree blob
  * @node:	Node offset to read from
- * @spi:	Place to put the decoded information
+ * @plat:	Place to put the decoded information
  */
-int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
+int spi_slave_ofdata_to_platdata(const void *blob, int node,
+				 struct dm_spi_slave_platdata *plat);
 
 /**
  * spi_cs_info() - Check information on a chip select
diff --git a/include/splash.h b/include/splash.h
index 89ee7b2..7ae7a68 100644
--- a/include/splash.h
+++ b/include/splash.h
@@ -22,7 +22,20 @@
 #ifndef _SPLASH_H_
 #define _SPLASH_H_
 
+#include <errno.h>
 
+enum splash_storage {
+	SPLASH_STORAGE_NAND,
+	SPLASH_STORAGE_SF,
+};
+
+struct splash_location {
+	char *name;
+	enum splash_storage storage;
+	u32 offset;	/* offset from start of storage */
+};
+
+int splash_source_load(struct splash_location *locations, uint size);
 int splash_screen_prepare(void);
 
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
@@ -31,6 +44,15 @@
 static inline void splash_get_pos(int *x, int *y) { }
 #endif
 
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
+int lcd_splash(ulong addr);
+#else
+static inline int lcd_splash(ulong addr)
+{
+	return -ENOSYS;
+}
+#endif
+
 #define BMP_ALIGN_CENTER	0x7FFF
 
 #endif
diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h
index c996fb3..3c69d85 100644
--- a/include/u-boot/rsa-checksum.h
+++ b/include/u-boot/rsa-checksum.h
@@ -16,9 +16,18 @@
 extern const uint8_t padding_sha256_rsa2048[];
 extern const uint8_t padding_sha1_rsa2048[];
 
-void sha256_calculate(const struct image_region region[], int region_count,
-		      uint8_t *checksum);
-void sha1_calculate(const struct image_region region[], int region_count,
-		    uint8_t *checksum);
+/**
+ * hash_calculate() - Calculate hash over the data
+ *
+ * @name:  Name of algorithm to be used for hash calculation
+ * @region: Array having info of regions over which hash needs to be calculated
+ * @region_count: Number of regions in the region array
+ * @checksum: Buffer contanining the output hash
+ *
+ * @return 0 if OK, < 0 if error
+ */
+int hash_calculate(const char *name,
+		   const struct image_region region[], int region_count,
+		   uint8_t *checksum);
 
 #endif
diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h
new file mode 100644
index 0000000..fce445a
--- /dev/null
+++ b/include/u-boot/rsa-mod-exp.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Ruchika Gupta.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+*/
+
+#ifndef _RSA_MOD_EXP_H
+#define _RSA_MOD_EXP_H
+
+#include <errno.h>
+#include <image.h>
+
+/**
+ * struct key_prop - holder for a public key properties
+ *
+ * The struct has pointers to modulus (Typically called N),
+ * The inverse, R^2, exponent. These can be typecasted and
+ * used as byte arrays or converted to the required format
+ * as per requirement of RSA implementation.
+ */
+struct key_prop {
+	const void *rr;		/* R^2 can be treated as byte array */
+	const void *modulus;	/* modulus as byte array */
+	const void *public_exponent; /* public exponent as byte array */
+	uint32_t n0inv;		/* -1 / modulus[0] mod 2^32 */
+	int num_bits;		/* Key length in bits */
+	uint32_t exp_len;	/* Exponent length in number of uint8_t */
+};
+
+/**
+ * rsa_mod_exp_sw() - Perform RSA Modular Exponentiation in sw
+ *
+ * Operation: out[] = sig ^ exponent % modulus
+ *
+ * @sig:	RSA PKCS1.5 signature
+ * @sig_len:	Length of signature in number of bytes
+ * @node:	Node with RSA key elements like modulus, exponent, R^2, n0inv
+ * @out:	Result in form of byte array of len equal to sig_len
+ */
+int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *node, uint8_t *out);
+
+int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *node, uint8_t *out);
+
+/**
+ * struct struct mod_exp_ops - Driver model for RSA Modular Exponentiation
+ *				operations
+ *
+ * The uclass interface is implemented by all crypto devices which use
+ * driver model.
+ */
+struct mod_exp_ops {
+	/**
+	 * Perform Modular Exponentiation
+	 *
+	 * Operation: out[] = sig ^ exponent % modulus
+	 *
+	 * @dev:	RSA Device
+	 * @sig:	RSA PKCS1.5 signature
+	 * @sig_len:	Length of signature in number of bytes
+	 * @node:	Node with RSA key elements like modulus, exponent,
+	 *		R^2, n0inv
+	 * @out:	Result in form of byte array of len equal to sig_len
+	 *
+	 * This function computes exponentiation over the signature.
+	 * Returns: 0 if exponentiation is successful, or a negative value
+	 * if it wasn't.
+	 */
+	int (*mod_exp)(struct udevice *dev, const uint8_t *sig,
+			   uint32_t sig_len, struct key_prop *node,
+			   uint8_t *outp);
+};
+
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 8460439..a1f30a2 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -27,4 +27,6 @@
 	  get_timer() must operate in milliseconds and this option must be
 	  set to 1000.
 
+source lib/rsa/Kconfig
+
 endmenu
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index e989241..dd58bbb 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -11,8 +11,6 @@
 #include <fdtdec.h>
 #include <linux/ctype.h>
 
-#include <asm/gpio.h>
-
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -26,9 +24,6 @@
 	COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"),
 	COMPAT(NVIDIA_TEGRA30_USB, "nvidia,tegra30-ehci"),
 	COMPAT(NVIDIA_TEGRA114_USB, "nvidia,tegra114-ehci"),
-	COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"),
-	COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"),
-	COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"),
 	COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
 	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
 	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
@@ -38,9 +33,6 @@
 	COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
 	COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
 	COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
-	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
-	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
-	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
 	COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
 	COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
 	COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
@@ -50,7 +42,6 @@
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
 	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"),
@@ -84,6 +75,7 @@
 	COMPAT(INTEL_GMA, "intel,gma"),
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
+	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -679,99 +671,128 @@
 	return cell != NULL;
 }
 
-/**
- * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no
- * terminating item.
- *
- * @param blob		FDT blob to use
- * @param node		Node to look at
- * @param prop_name	Node property name
- * @param gpio		Array of gpio elements to fill from FDT. This will be
- *			untouched if either 0 or an error is returned
- * @param max_count	Maximum number of elements allowed
- * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
- * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
- */
-int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
-		struct fdt_gpio_state *gpio, int max_count)
+int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
+				   const char *list_name,
+				   const char *cells_name,
+				   int cell_count, int index,
+				   struct fdtdec_phandle_args *out_args)
 {
-	const struct fdt_property *prop;
-	const u32 *cell;
-	const char *name;
-	int len, i;
+	const __be32 *list, *list_end;
+	int rc = 0, size, cur_index = 0;
+	uint32_t count = 0;
+	int node = -1;
+	int phandle;
 
-	debug("%s: %s\n", __func__, prop_name);
-	assert(max_count > 0);
-	prop = fdt_get_property(blob, node, prop_name, &len);
-	if (!prop) {
-		debug("%s: property '%s' missing\n", __func__, prop_name);
-		return -FDT_ERR_NOTFOUND;
+	/* Retrieve the phandle list property */
+	list = fdt_getprop(blob, src_node, list_name, &size);
+	if (!list)
+		return -ENOENT;
+	list_end = list + size / sizeof(*list);
+
+	/* Loop over the phandles until all the requested entry is found */
+	while (list < list_end) {
+		rc = -EINVAL;
+		count = 0;
+
+		/*
+		 * If phandle is 0, then it is an empty entry with no
+		 * arguments.  Skip forward to the next entry.
+		 */
+		phandle = be32_to_cpup(list++);
+		if (phandle) {
+			/*
+			 * Find the provider node and parse the #*-cells
+			 * property to determine the argument length.
+			 *
+			 * This is not needed if the cell count is hard-coded
+			 * (i.e. cells_name not set, but cell_count is set),
+			 * except when we're going to return the found node
+			 * below.
+			 */
+			if (cells_name || cur_index == index) {
+				node = fdt_node_offset_by_phandle(blob,
+								  phandle);
+				if (!node) {
+					debug("%s: could not find phandle\n",
+					      fdt_get_name(blob, src_node,
+							   NULL));
+					goto err;
+				}
+			}
+
+			if (cells_name) {
+				count = fdtdec_get_int(blob, node, cells_name,
+						       -1);
+				if (count == -1) {
+					debug("%s: could not get %s for %s\n",
+					      fdt_get_name(blob, src_node,
+							   NULL),
+					      cells_name,
+					      fdt_get_name(blob, node,
+							   NULL));
+					goto err;
+				}
+			} else {
+				count = cell_count;
+			}
+
+			/*
+			 * Make sure that the arguments actually fit in the
+			 * remaining property data length
+			 */
+			if (list + count > list_end) {
+				debug("%s: arguments longer than property\n",
+				      fdt_get_name(blob, src_node, NULL));
+				goto err;
+			}
+		}
+
+		/*
+		 * All of the error cases above bail out of the loop, so at
+		 * this point, the parsing is successful. If the requested
+		 * index matches, then fill the out_args structure and return,
+		 * or return -ENOENT for an empty entry.
+		 */
+		rc = -ENOENT;
+		if (cur_index == index) {
+			if (!phandle)
+				goto err;
+
+			if (out_args) {
+				int i;
+
+				if (count > MAX_PHANDLE_ARGS) {
+					debug("%s: too many arguments %d\n",
+					      fdt_get_name(blob, src_node,
+							   NULL), count);
+					count = MAX_PHANDLE_ARGS;
+				}
+				out_args->node = node;
+				out_args->args_count = count;
+				for (i = 0; i < count; i++) {
+					out_args->args[i] =
+							be32_to_cpup(list++);
+				}
+			}
+
+			/* Found it! return success */
+			return 0;
+		}
+
+		node = -1;
+		list += count;
+		cur_index++;
 	}
 
-	/* We will use the name to tag the GPIO */
-	name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
-	cell = (u32 *)prop->data;
-	len /= sizeof(u32) * 3;		/* 3 cells per GPIO record */
-	if (len > max_count) {
-		debug(" %s: too many GPIOs / cells for "
-			"property '%s'\n", __func__, prop_name);
-		return -FDT_ERR_BADLAYOUT;
-	}
-
-	/* Read out the GPIO data from the cells */
-	for (i = 0; i < len; i++, cell += 3) {
-		gpio[i].gpio = fdt32_to_cpu(cell[1]);
-		gpio[i].flags = fdt32_to_cpu(cell[2]);
-		gpio[i].name = name;
-	}
-
-	return len;
-}
-
-int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
-		struct fdt_gpio_state *gpio)
-{
-	int err;
-
-	debug("%s: %s\n", __func__, prop_name);
-	gpio->gpio = FDT_GPIO_NONE;
-	gpio->name = NULL;
-	err = fdtdec_decode_gpios(blob, node, prop_name, gpio, 1);
-	return err == 1 ? 0 : err;
-}
-
-int fdtdec_get_gpio(struct fdt_gpio_state *gpio)
-{
-	int val;
-
-	if (!fdt_gpio_isvalid(gpio))
-		return -1;
-
-	val = gpio_get_value(gpio->gpio);
-	return gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
-}
-
-int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val)
-{
-	if (!fdt_gpio_isvalid(gpio))
-		return -1;
-
-	val = gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
-	return gpio_set_value(gpio->gpio, val);
-}
-
-int fdtdec_setup_gpio(struct fdt_gpio_state *gpio)
-{
 	/*
-	 * Return success if there is no GPIO defined. This is used for
-	 * optional GPIOs)
+	 * Result will be one of:
+	 * -ENOENT : index is for empty phandle
+	 * -EINVAL : parsing error on data
+	 * [1..n]  : Number of phandle (count mode; when index = -1)
 	 */
-	if (!fdt_gpio_isvalid(gpio))
-		return 0;
-
-	if (gpio_request(gpio->gpio, gpio->name))
-		return -1;
-	return 0;
+	rc = index < 0 ? cur_index : -ENOENT;
+ err:
+	return rc;
 }
 
 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig
new file mode 100644
index 0000000..1268a1b
--- /dev/null
+++ b/lib/rsa/Kconfig
@@ -0,0 +1,27 @@
+config RSA
+	bool "Use RSA Library"
+	select RSA_FREESCALE_EXP if FSL_CAAM
+	select RSA_SOFTWARE_EXP if !RSA_FREESCALE_EXP
+	help
+	  RSA support. This enables the RSA algorithm used for FIT image
+	  verification in U-Boot.
+	  See doc/uImage.FIT/signature.txt for more details.
+
+if RSA
+config RSA_SOFTWARE_EXP
+	bool "Enable driver for RSA Modular Exponentiation in software"
+	depends on DM && RSA
+	help
+	  Enables driver for modular exponentiation in software. This is a RSA
+	  algorithm used in FIT image verification. It required RSA Key as
+	  input.
+	  See doc/uImage.FIT/signature.txt for more details.
+
+config RSA_FREESCALE_EXP
+	bool "Enable RSA Modular Exponentiation with FSL crypto accelerator"
+	depends on DM && RSA && FSL_CAAM
+	help
+	Enables driver for RSA modular exponentiation using Freescale cryptographic
+	accelerator - CAAM.
+
+endif
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
index a5a96cb6..cc25b3c 100644
--- a/lib/rsa/Makefile
+++ b/lib/rsa/Makefile
@@ -7,4 +7,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
+obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o rsa-mod-exp.o
diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c
index 8d8b59f..68d9d65 100644
--- a/lib/rsa/rsa-checksum.c
+++ b/lib/rsa/rsa-checksum.c
@@ -10,12 +10,13 @@
 #include <asm/byteorder.h>
 #include <asm/errno.h>
 #include <asm/unaligned.h>
+#include <hash.h>
 #else
 #include "fdt_host.h"
-#endif
-#include <u-boot/rsa.h>
 #include <u-boot/sha1.h>
 #include <u-boot/sha256.h>
+#endif
+#include <u-boot/rsa.h>
 
 /* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
 
@@ -136,28 +137,37 @@
 	0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
 };
 
-void sha1_calculate(const struct image_region region[], int region_count,
-		    uint8_t *checksum)
+int hash_calculate(const char *name,
+		    const struct image_region region[],
+		    int region_count, uint8_t *checksum)
 {
-	sha1_context ctx;
+	struct hash_algo *algo;
+	int ret = 0;
+	void *ctx;
 	uint32_t i;
 	i = 0;
 
-	sha1_starts(&ctx);
-	for (i = 0; i < region_count; i++)
-		sha1_update(&ctx, region[i].data, region[i].size);
-	sha1_finish(&ctx, checksum);
-}
+	ret = hash_progressive_lookup_algo(name, &algo);
+	if (ret)
+		return ret;
 
-void sha256_calculate(const struct image_region region[], int region_count,
-		      uint8_t *checksum)
-{
-	sha256_context ctx;
-	uint32_t i;
-	i = 0;
+	ret = algo->hash_init(algo, &ctx);
+	if (ret)
+		return ret;
 
-	sha256_starts(&ctx);
-	for (i = 0; i < region_count; i++)
-		sha256_update(&ctx, region[i].data, region[i].size);
-	sha256_finish(&ctx, checksum);
+	for (i = 0; i < region_count - 1; i++) {
+		ret = algo->hash_update(algo, ctx, region[i].data,
+					region[i].size, 0);
+		if (ret)
+			return ret;
+	}
+
+	ret = algo->hash_update(algo, ctx, region[i].data, region[i].size, 1);
+	if (ret)
+		return ret;
+	ret = algo->hash_finish(algo, ctx, checksum, algo->digest_size);
+	if (ret)
+		return ret;
+
+	return 0;
 }
diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c
new file mode 100644
index 0000000..4a6de2b
--- /dev/null
+++ b/lib/rsa/rsa-mod-exp.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef USE_HOSTCC
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <asm/errno.h>
+#include <asm/types.h>
+#include <asm/unaligned.h>
+#else
+#include "fdt_host.h"
+#include "mkimage.h"
+#include <fdt_support.h>
+#endif
+#include <u-boot/rsa.h>
+#include <u-boot/rsa-mod-exp.h>
+
+#define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
+#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
+
+/* Default public exponent for backward compatibility */
+#define RSA_DEFAULT_PUBEXP	65537
+
+/**
+ * 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[])
+{
+	int i;
+
+	for (i = (int)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);
+}
+
+/**
+ * num_pub_exponent_bits() - Number of bits in the public exponent
+ *
+ * @key:	RSA key
+ * @num_bits:	Storage for the number of public exponent bits
+ */
+static int num_public_exponent_bits(const struct rsa_public_key *key,
+		int *num_bits)
+{
+	uint64_t exponent;
+	int exponent_bits;
+	const uint max_bits = (sizeof(exponent) * 8);
+
+	exponent = key->exponent;
+	exponent_bits = 0;
+
+	if (!exponent) {
+		*num_bits = exponent_bits;
+		return 0;
+	}
+
+	for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
+		if (!(exponent >>= 1)) {
+			*num_bits = exponent_bits;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+/**
+ * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
+ *
+ * @key:	RSA key
+ * @pos:	The bit position to check
+ */
+static int is_public_exponent_bit_set(const struct rsa_public_key *key,
+		int pos)
+{
+	return key->exponent & (1ULL << pos);
+}
+
+/**
+ * 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;
+	int j, k;
+
+	/* 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];
+	uint32_t a_scaled[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);
+
+	if (0 != num_public_exponent_bits(key, &k))
+		return -EINVAL;
+
+	if (k < 2) {
+		debug("Public exponent is too short (%d bits, minimum 2)\n",
+		      k);
+		return -EINVAL;
+	}
+
+	if (!is_public_exponent_bit_set(key, 0)) {
+		debug("LSB of RSA public exponent must be set.\n");
+		return -EINVAL;
+	}
+
+	/* the bit at e[k-1] is 1 by definition, so start with: C := M */
+	montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
+	/* retain scaled version for intermediate use */
+	memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
+
+	for (j = k - 2; j > 0; --j) {
+		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+
+		if (is_public_exponent_bit_set(key, j)) {
+			/* acc = tmp * val / R mod n */
+			montgomery_mul(key, acc, tmp, a_scaled);
+		} else {
+			/* e[j] == 0, copy tmp back to acc for next operation */
+			memcpy(acc, tmp, key->len * sizeof(acc[0]));
+		}
+	}
+
+	/* the bit at e[0] is always 1 */
+	montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+	montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
+	memcpy(result, acc, key->len * sizeof(result[0]));
+
+	/* 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 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]);
+}
+
+int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
+		struct key_prop *prop, uint8_t *out)
+{
+	struct rsa_public_key key;
+	int ret;
+
+	if (!prop) {
+		debug("%s: Skipping invalid prop", __func__);
+		return -EBADF;
+	}
+	key.n0inv = prop->n0inv;
+	key.len = prop->num_bits;
+
+	if (!prop->public_exponent)
+		key.exponent = RSA_DEFAULT_PUBEXP;
+	else
+		key.exponent =
+			fdt64_to_cpu(*((uint64_t *)(prop->public_exponent)));
+
+	if (!key.len || !prop->modulus || !prop->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, (uint32_t *)prop->modulus, key.len);
+	rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len);
+	if (!key.modulus || !key.rr) {
+		debug("%s: Out of memory", __func__);
+		return -ENOMEM;
+	}
+
+	uint32_t buf[sig_len / sizeof(uint32_t)];
+
+	memcpy(buf, sig, sig_len);
+
+	ret = pow_mod(&key, buf);
+	if (ret)
+		return ret;
+
+	memcpy(out, buf, sig_len);
+
+	return 0;
+}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 4ef19b6..60126d2 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -12,246 +12,46 @@
 #include <asm/errno.h>
 #include <asm/types.h>
 #include <asm/unaligned.h>
+#include <dm.h>
 #else
 #include "fdt_host.h"
 #include "mkimage.h"
 #include <fdt_support.h>
 #endif
+#include <u-boot/rsa-mod-exp.h>
 #include <u-boot/rsa.h>
-#include <u-boot/sha1.h>
-#include <u-boot/sha256.h>
-
-#define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
-
-#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
-#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
 
 /* Default public exponent for backward compatibility */
 #define RSA_DEFAULT_PUBEXP	65537
 
 /**
- * subtract_modulus() - subtract modulus from the given value
+ * rsa_verify_key() - Verify a signature against some data using RSA Key
  *
- * @key:	Key containing modulus to subtract
- * @num:	Number to subtract modulus from, as little endian word array
+ * Verify a RSA PKCS1.5 signature against an expected hash using
+ * the RSA Key properties in prop structure.
+ *
+ * @prop:	Specifies key
+ * @sig:	Signature
+ * @sig_len:	Number of bytes in signature
+ * @hash:	Pointer to the expected hash
+ * @algo:	Checksum algo structure having information on RSA padding etc.
+ * @return 0 if verified, -ve on error
  */
-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[])
-{
-	int i;
-
-	for (i = (int)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);
-}
-
-/**
- * num_pub_exponent_bits() - Number of bits in the public exponent
- *
- * @key:	RSA key
- * @num_bits:	Storage for the number of public exponent bits
- */
-static int num_public_exponent_bits(const struct rsa_public_key *key,
-		int *num_bits)
-{
-	uint64_t exponent;
-	int exponent_bits;
-	const uint max_bits = (sizeof(exponent) * 8);
-
-	exponent = key->exponent;
-	exponent_bits = 0;
-
-	if (!exponent) {
-		*num_bits = exponent_bits;
-		return 0;
-	}
-
-	for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
-		if (!(exponent >>= 1)) {
-			*num_bits = exponent_bits;
-			return 0;
-		}
-
-	return -EINVAL;
-}
-
-/**
- * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
- *
- * @key:	RSA key
- * @pos:	The bit position to check
- */
-static int is_public_exponent_bit_set(const struct rsa_public_key *key,
-		int pos)
-{
-	return key->exponent & (1ULL << pos);
-}
-
-/**
- * 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;
-	int j, k;
-
-	/* 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];
-	uint32_t a_scaled[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);
-
-	if (0 != num_public_exponent_bits(key, &k))
-		return -EINVAL;
-
-	if (k < 2) {
-		debug("Public exponent is too short (%d bits, minimum 2)\n",
-		      k);
-		return -EINVAL;
-	}
-
-	if (!is_public_exponent_bit_set(key, 0)) {
-		debug("LSB of RSA public exponent must be set.\n");
-		return -EINVAL;
-	}
-
-	/* the bit at e[k-1] is 1 by definition, so start with: C := M */
-	montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
-	/* retain scaled version for intermediate use */
-	memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
-
-	for (j = k - 2; j > 0; --j) {
-		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
-
-		if (is_public_exponent_bit_set(key, j)) {
-			/* acc = tmp * val / R mod n */
-			montgomery_mul(key, acc, tmp, a_scaled);
-		} else {
-			/* e[j] == 0, copy tmp back to acc for next operation */
-			memcpy(acc, tmp, key->len * sizeof(acc[0]));
-		}
-	}
-
-	/* the bit at e[0] is always 1 */
-	montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
-	montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
-	memcpy(result, acc, key->len * sizeof(result[0]));
-
-	/* 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,
+static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
 			  const uint32_t sig_len, const uint8_t *hash,
 			  struct checksum_algo *algo)
 {
 	const uint8_t *padding;
 	int pad_len;
 	int ret;
+#if !defined(USE_HOSTCC)
+	struct udevice *mod_exp_dev;
+#endif
 
-	if (!key || !sig || !hash || !algo)
+	if (!prop || !sig || !hash || !algo)
 		return -EIO;
 
-	if (sig_len != (key->len * sizeof(uint32_t))) {
+	if (sig_len != (prop->num_bits / 8)) {
 		debug("Signature is of incorrect length %d\n", sig_len);
 		return -EINVAL;
 	}
@@ -265,13 +65,23 @@
 		return -EINVAL;
 	}
 
-	uint32_t buf[sig_len / sizeof(uint32_t)];
+	uint8_t buf[sig_len];
 
-	memcpy(buf, sig, sig_len);
+#if !defined(USE_HOSTCC)
+	ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
+	if (ret) {
+		printf("RSA: Can't find Modular Exp implementation\n");
+		return -EINVAL;
+	}
 
-	ret = pow_mod(key, buf);
-	if (ret)
+	ret = rsa_mod_exp(mod_exp_dev, sig, sig_len, prop, buf);
+#else
+	ret = rsa_mod_exp_sw(sig, sig_len, prop, buf);
+#endif
+	if (ret) {
+		debug("Error in Modular exponentation\n");
 		return ret;
+	}
 
 	padding = algo->rsa_padding;
 	pad_len = algo->pad_len - algo->checksum_len;
@@ -291,72 +101,57 @@
 	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]);
-}
-
+/**
+ * rsa_verify_with_keynode() - Verify a signature against some data using
+ * information in node with prperties of RSA Key like modulus, exponent etc.
+ *
+ * Parse sign-node and fill a key_prop structure with properties of the
+ * key.  Verify a RSA PKCS1.5 signature against an expected hash using
+ * the properties parsed
+ *
+ * @info:	Specifies key and FIT information
+ * @hash:	Pointer to the expected hash
+ * @sig:	Signature
+ * @sig_len:	Number of bytes in signature
+ * @node:	Node having the RSA Key properties
+ * @return 0 if verified, -ve on error
+ */
 static int rsa_verify_with_keynode(struct image_sign_info *info,
-		const void *hash, uint8_t *sig, uint sig_len, int node)
+				   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;
-	const uint64_t *public_exponent;
+	struct key_prop prop;
 	int length;
-	int ret;
+	int ret = 0;
 
 	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);
-	public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
-	if (!public_exponent || length < sizeof(*public_exponent))
-		key.exponent = RSA_DEFAULT_PUBEXP;
-	else
-		key.exponent = fdt64_to_cpu(*public_exponent);
-	modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
-	rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
-	if (!key.len || !modulus || !rr) {
+
+	prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
+
+	prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+
+	prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
+	if (!prop.public_exponent || length < sizeof(uint64_t))
+		prop.public_exponent = NULL;
+
+	prop.exp_len = sizeof(uint64_t);
+
+	prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
+
+	prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
+
+	if (!prop.num_bits || !prop.modulus) {
 		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];
+	ret = rsa_verify_key(&prop, sig, sig_len, hash, info->algo->checksum);
 
-	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, info->algo->checksum);
-	if (ret) {
-		printf("%s: RSA failed to verify: %d\n", __func__, ret);
-		return ret;
-	}
-
-	return 0;
+	return ret;
 }
 
 int rsa_verify(struct image_sign_info *info,
@@ -389,7 +184,12 @@
 	}
 
 	/* Calculate checksum with checksum-algorithm */
-	info->algo->checksum->calculate(region, region_count, hash);
+	ret = info->algo->checksum->calculate(info->algo->checksum->name,
+					region, region_count, hash);
+	if (ret < 0) {
+		debug("%s: Error in checksum calculation\n", __func__);
+		return -EINVAL;
+	}
 
 	/* See if we must use a particular key */
 	if (info->required_keynode != -1) {
diff --git a/net/net.c b/net/net.c
index 2bea07b..b60ce62 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1086,7 +1086,7 @@
 		if ((ip->ip_hl_v & 0x0f) > 0x05)
 			return;
 		/* Check the Checksum of the header */
-		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE / 2)) {
+		if (!ip_checksum_ok((uchar *)ip, IP_HDR_SIZE)) {
 			debug("checksum bad\n");
 			return;
 		}
@@ -1291,27 +1291,6 @@
 /**********************************************************************/
 
 int
-NetCksumOk(uchar *ptr, int len)
-{
-	return !((NetCksum(ptr, len) + 1) & 0xfffe);
-}
-
-
-unsigned
-NetCksum(uchar *ptr, int len)
-{
-	ulong	xsum;
-	ushort *p = (ushort *)ptr;
-
-	xsum = 0;
-	while (len-- > 0)
-		xsum += *p++;
-	xsum = (xsum & 0xffff) + (xsum >> 16);
-	xsum = (xsum & 0xffff) + (xsum >> 16);
-	return xsum & 0xffff;
-}
-
-int
 NetEthHdrSize(void)
 {
 	ushort myvlanid;
@@ -1410,7 +1389,7 @@
 	net_set_ip_header(pkt, dest, NetOurIP);
 	ip->ip_len   = htons(IP_UDP_HDR_SIZE + len);
 	ip->ip_p     = IPPROTO_UDP;
-	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1);
+	ip->ip_sum   = compute_ip_checksum(ip, IP_HDR_SIZE);
 
 	ip->udp_src  = htons(sport);
 	ip->udp_dst  = htons(dport);
diff --git a/net/ping.c b/net/ping.c
index 2be56ed..366f518 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -29,14 +29,14 @@
 
 	ip->ip_len   = htons(IP_ICMP_HDR_SIZE);
 	ip->ip_p     = IPPROTO_ICMP;
-	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE >> 1);
+	ip->ip_sum   = compute_ip_checksum(ip, IP_HDR_SIZE);
 
 	icmp->type = ICMP_ECHO_REQUEST;
 	icmp->code = 0;
 	icmp->checksum = 0;
 	icmp->un.echo.id = 0;
 	icmp->un.echo.sequence = htons(PingSeqNo++);
-	icmp->checksum = ~NetCksum((uchar *)icmp, ICMP_HDR_SIZE	>> 1);
+	icmp->checksum = compute_ip_checksum(icmp, ICMP_HDR_SIZE);
 }
 
 static int ping_send(void)
@@ -101,13 +101,11 @@
 		ip->ip_off = 0;
 		NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
 		NetCopyIP((void *)&ip->ip_src, &NetOurIP);
-		ip->ip_sum = ~NetCksum((uchar *)ip,
-				       IP_HDR_SIZE >> 1);
+		ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE);
 
 		icmph->type = ICMP_ECHO_REPLY;
 		icmph->checksum = 0;
-		icmph->checksum = ~NetCksum((uchar *)icmph,
-			(len - IP_HDR_SIZE) >> 1);
+		icmph->checksum = compute_ip_checksum(icmph, len - IP_HDR_SIZE);
 		NetSendPacket((uchar *)et, eth_hdr_size + len);
 		return;
 /*	default:
diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
index 8e9d71f..58e1642 100644
--- a/scripts/Makefile.autoconf
+++ b/scripts/Makefile.autoconf
@@ -85,15 +85,26 @@
 	$(call filechk,config_h)
 
 # symbolic links
+# If arch/$(ARCH)/mach-$(SOC)/include/mach exists,
+# make a symbolic link to that directory.
+# Otherwise, create a symbolic link to arch/$(ARCH)/include/asm/arch-$(SOC).
 PHONY += create_symlink
 create_symlink:
 ifneq ($(KBUILD_SRC),)
 	$(Q)mkdir -p include/asm
-	$(Q)ln -fsn $(KBUILD_SRC)/arch/$(ARCH)/include/asm/arch-$(if $(SOC),$(SOC),$(CPU)) \
-		include/asm/arch
+	$(Q)if [ -d $(KBUILD_SRC)/arch/$(ARCH)/mach-$(SOC)/include/mach ]; then	\
+		dest=arch/$(ARCH)/mach-$(SOC)/include/mach;			\
+	else									\
+		dest=arch/$(ARCH)/include/asm/arch-$(if $(SOC),$(SOC),$(CPU));	\
+	fi;									\
+	ln -fsn $(KBUILD_SRC)/$$dest include/asm/arch
 else
-	$(Q)ln -fsn arch-$(if $(SOC),$(SOC),$(CPU)) \
-		arch/$(ARCH)/include/asm/arch
+	$(Q)if [ -d arch/$(ARCH)/mach-$(SOC)/include/mach ]; then	\
+		dest=../../mach-$(SOC)/include/mach;			\
+	else								\
+		dest=arch-$(if $(SOC),$(SOC),$(CPU));			\
+	fi;								\
+	ln -fsn $$dest arch/$(ARCH)/include/asm/arch
 endif
 
 PHONY += FORCE
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index ecf3037..cc189ad 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -57,6 +57,7 @@
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
 libs-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/
 libs-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += drivers/ddr/fsl/
+libs-$(CONFIG_SYS_MVEBU_DDR) += drivers/ddr/mvebu/
 libs-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/
 libs-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/
 libs-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/
@@ -153,10 +154,8 @@
 endif
 
 ifdef CONFIG_SUNXI
-ifndef CONFIG_SPL_FEL
 ALL-y	+= $(obj)/sunxi-spl.bin
 endif
-endif
 
 ifeq ($(CONFIG_SYS_SOC),"at91")
 ALL-y	+= boot.bin
diff --git a/test/Kconfig b/test/Kconfig
new file mode 100644
index 0000000..1fb1716
--- /dev/null
+++ b/test/Kconfig
@@ -0,0 +1 @@
+source "test/dm/Kconfig"
diff --git a/test/dm/Kconfig b/test/dm/Kconfig
new file mode 100644
index 0000000..a9d0298
--- /dev/null
+++ b/test/dm/Kconfig
@@ -0,0 +1,8 @@
+config DM_TEST
+	bool "Enable driver model test command"
+	depends on SANDBOX && CMD_DM
+	help
+	  This enables the 'dm test' command which runs a series of unit
+	  tests on the driver model code. Each subsystem (uclass) is tested.
+	  If all is well then all tests pass although there will be a few
+	  messages printed along the way.
diff --git a/test/dm/bus.c b/test/dm/bus.c
index abbaccf..faffe6a 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -9,11 +9,18 @@
 #include <dm/device-internal.h>
 #include <dm/root.h>
 #include <dm/test.h>
+#include <dm/uclass-internal.h>
 #include <dm/ut.h>
 #include <dm/util.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct dm_test_parent_platdata {
+	int count;
+	int bind_flag;
+	int uclass_bind_flag;
+};
+
 enum {
 	FLAG_CHILD_PROBED	= 10,
 	FLAG_CHILD_REMOVED	= -7,
@@ -26,6 +33,17 @@
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
+static int testbus_child_post_bind(struct udevice *dev)
+{
+	struct dm_test_parent_platdata *plat;
+
+	plat = dev_get_parent_platdata(dev);
+	plat->bind_flag = 1;
+	plat->uclass_bind_flag = 2;
+
+	return 0;
+}
+
 static int testbus_child_pre_probe(struct udevice *dev)
 {
 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
@@ -35,6 +53,15 @@
 	return 0;
 }
 
+static int testbus_child_pre_probe_uclass(struct udevice *dev)
+{
+	struct dm_test_priv *priv = dev_get_priv(dev);
+
+	priv->uclass_flag++;
+
+	return 0;
+}
+
 static int testbus_child_post_remove(struct udevice *dev)
 {
 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
@@ -59,9 +86,12 @@
 	.of_match	= testbus_ids,
 	.id	= UCLASS_TEST_BUS,
 	.probe	= testbus_drv_probe,
+	.child_post_bind = testbus_child_post_bind,
 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
 	.per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
+	.per_child_platdata_auto_alloc_size =
+			sizeof(struct dm_test_parent_platdata),
 	.child_pre_probe = testbus_child_pre_probe,
 	.child_post_remove = testbus_child_post_remove,
 };
@@ -69,12 +99,14 @@
 UCLASS_DRIVER(testbus) = {
 	.name		= "testbus",
 	.id		= UCLASS_TEST_BUS,
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.child_pre_probe = testbus_child_pre_probe_uclass,
 };
 
 /* Test that we can probe for children */
 static int dm_test_bus_children(struct dm_test_state *dms)
 {
-	int num_devices = 4;
+	int num_devices = 6;
 	struct udevice *bus;
 	struct uclass *uc;
 
@@ -172,7 +204,7 @@
 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
 /* Test that the bus can store data about each child */
-static int dm_test_bus_parent_data(struct dm_test_state *dms)
+static int test_bus_parent_data(struct dm_test_state *dms)
 {
 	struct dm_test_parent_data *parent_data;
 	struct udevice *bus, *dev;
@@ -231,9 +263,36 @@
 
 	return 0;
 }
-
+/* Test that the bus can store data about each child */
+static int dm_test_bus_parent_data(struct dm_test_state *dms)
+{
+	return test_bus_parent_data(dms);
+}
 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_data_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus;
+	int size;
+	int ret;
+
+	/* Set the driver size to 0 so that the uclass size is used */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	size = bus->driver->per_child_auto_alloc_size;
+	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
+	bus->driver->per_child_auto_alloc_size = 0;
+	ret = test_bus_parent_data(dms);
+	if (ret)
+		return ret;
+	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
+	bus->driver->per_child_auto_alloc_size = size;
+
+	return 0;
+}
+DM_TEST(dm_test_bus_parent_data_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that the bus ops are called when a child is probed/removed */
 static int dm_test_bus_parent_ops(struct dm_test_state *dms)
 {
@@ -271,3 +330,188 @@
 	return 0;
 }
 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int test_bus_parent_platdata(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	/* Check that the bus has no children */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	device_find_first_child(bus, &dev);
+	ut_asserteq_ptr(NULL, dev);
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+
+		/*
+		 * Check that it is not affected by the device being
+		 * probed/removed
+		 */
+		plat->count++;
+		ut_asserteq(1, plat->count);
+		device_probe(dev);
+		device_remove(dev);
+
+		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
+		ut_asserteq(1, plat->count);
+		ut_assertok(device_probe(dev));
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	/* Removing the bus should also have no effect (it is still bound) */
+	device_remove(bus);
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(1, plat->count);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	/* Unbind all the children */
+	do {
+		device_find_first_child(bus, &dev);
+		if (dev)
+			device_unbind(dev);
+	} while (dev);
+
+	/* Now the child platdata should be removed and re-added */
+	device_probe(bus);
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(0, plat->count);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+
+/* Test that the bus can store platform data about each child */
+static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+{
+	return test_bus_parent_platdata(dms);
+}
+DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_platdata_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus;
+	int size;
+	int ret;
+
+	/* Set the driver size to 0 so that the uclass size is used */
+	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+	size = bus->driver->per_child_platdata_auto_alloc_size;
+	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
+	bus->driver->per_child_platdata_auto_alloc_size = 0;
+	ret = test_bus_parent_platdata(dms);
+	if (ret)
+		return ret;
+	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
+	bus->driver->per_child_platdata_auto_alloc_size = size;
+
+	return 0;
+}
+DM_TEST(dm_test_bus_parent_platdata_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that the child post_bind method is called */
+static int dm_test_bus_child_post_bind(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(1, plat->bind_flag);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that the child post_bind method is called */
+static int dm_test_bus_child_post_bind_uclass(struct dm_test_state *dms)
+{
+	struct dm_test_parent_platdata *plat;
+	struct udevice *bus, *dev;
+	int child_count;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		/* Check that platform data is allocated */
+		plat = dev_get_parent_platdata(dev);
+		ut_assert(plat != NULL);
+		ut_asserteq(2, plat->uclass_bind_flag);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_post_bind_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/*
+ * Test that the bus' uclass' child_pre_probe() is called before the
+ * device's probe() method
+ */
+static int dm_test_bus_child_pre_probe_uclass(struct dm_test_state *dms)
+{
+	struct udevice *bus, *dev;
+	int child_count;
+
+	/*
+	 * See testfdt_drv_probe() which effectively checks that the uclass
+	 * flag is set before that method is called
+	 */
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	for (device_find_first_child(bus, &dev), child_count = 0;
+	     dev;
+	     device_find_next_child(&dev)) {
+		struct dm_test_priv *priv = dev_get_priv(dev);
+
+		/* Check that things happened in the right order */
+		ut_asserteq_ptr(NULL, priv);
+		ut_assertok(device_probe(dev));
+
+		priv = dev_get_priv(dev);
+		ut_assert(priv != NULL);
+		ut_asserteq(1, priv->uclass_flag);
+		ut_asserteq(1, priv->uclass_total);
+		child_count++;
+	}
+	ut_asserteq(3, child_count);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_child_pre_probe_uclass,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/core.c b/test/dm/core.c
index ff5c2a7..eccda09 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -598,3 +598,14 @@
 }
 
 DM_TEST(dm_test_uclass_before_ready, 0);
+
+static int dm_test_device_get_uclass_id(struct dm_test_state *dms)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST, 0, &dev));
+	ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_device_get_uclass_id, DM_TESTF_SCAN_PDATA);
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 94bd0d9..b29daf1 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -174,5 +174,72 @@
 
 	return 0;
 }
-
 DM_TEST(dm_test_gpio_leak, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that we can find GPIOs using phandles */
+static int dm_test_gpio_phandles(struct dm_test_state *dms)
+{
+	struct gpio_desc desc, desc_list[8], desc_list2[8];
+	struct udevice *dev, *gpio_a, *gpio_b;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio_a));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 2, &gpio_b));
+	ut_asserteq_str("base-gpios", gpio_a->name);
+	ut_asserteq(true, !!device_active(gpio_a));
+	ut_asserteq_ptr(gpio_a, desc.dev);
+	ut_asserteq(4, desc.offset);
+	/* GPIOF_INPUT is the sandbox GPIO driver default */
+	ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 4, NULL));
+	ut_assertok(dm_gpio_free(dev, &desc));
+
+	ut_asserteq(-ENOENT, gpio_request_by_name(dev, "test-gpios", 3, &desc,
+						  0));
+	ut_asserteq_ptr(NULL, desc.dev);
+	ut_asserteq(desc.offset, 0);
+	ut_asserteq(-ENOENT, gpio_request_by_name(dev, "test-gpios", 5, &desc,
+						  0));
+
+	/* Last GPIO is ignord as it comes after <0> */
+	ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc_list,
+						 ARRAY_SIZE(desc_list), 0));
+	ut_asserteq(-EBUSY, gpio_request_list_by_name(dev, "test-gpios",
+						      desc_list2,
+						      ARRAY_SIZE(desc_list2),
+						      0));
+	ut_assertok(gpio_free_list(dev, desc_list, 3));
+	ut_asserteq(3, gpio_request_list_by_name(dev,  "test-gpios", desc_list,
+						 ARRAY_SIZE(desc_list),
+						 GPIOD_IS_OUT |
+						 GPIOD_IS_OUT_ACTIVE));
+	ut_asserteq_ptr(gpio_a, desc_list[0].dev);
+	ut_asserteq(1, desc_list[0].offset);
+	ut_asserteq_ptr(gpio_a, desc_list[1].dev);
+	ut_asserteq(4, desc_list[1].offset);
+	ut_asserteq_ptr(gpio_b, desc_list[2].dev);
+	ut_asserteq(5, desc_list[2].offset);
+	ut_asserteq(1, dm_gpio_get_value(desc_list));
+	ut_assertok(gpio_free_list(dev, desc_list, 3));
+
+	ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list,
+						 ARRAY_SIZE(desc_list), 0));
+	/* This was set to output previously, so still will be */
+	ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 1, NULL));
+
+	/* Active low should invert the input value */
+	ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 6, NULL));
+	ut_asserteq(1, dm_gpio_get_value(&desc_list[2]));
+
+	ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 7, NULL));
+	ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 8, NULL));
+	ut_asserteq(0, dm_gpio_get_value(&desc_list[4]));
+	ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 9, NULL));
+	ut_asserteq(1, dm_gpio_get_value(&desc_list[5]));
+
+
+	return 0;
+}
+DM_TEST(dm_test_gpio_phandles, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
index a53e28d..541b73b 100644
--- a/test/dm/i2c.c
+++ b/test/dm/i2c.c
@@ -35,8 +35,8 @@
 	 * remove the emulation and the slave device.
 	 */
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_probe(bus, chip, 0, &dev));
-	ut_asserteq(-ENODEV, i2c_probe(bus, no_chip, 0, &dev));
+	ut_assertok(dm_i2c_probe(bus, chip, 0, &dev));
+	ut_asserteq(-ENODEV, dm_i2c_probe(bus, no_chip, 0, &dev));
 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus));
 
 	return 0;
@@ -49,11 +49,11 @@
 	uint8_t buf[5];
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_get_chip(bus, chip, &dev));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(i2c_get_chip(bus, chip, 1, &dev));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
-	ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0AB\0", sizeof(buf)));
 
 	return 0;
@@ -66,13 +66,13 @@
 	uint8_t buf[5];
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_get_chip(bus, chip, &dev));
-	ut_assertok(i2c_set_bus_speed(bus, 100000));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
-	ut_assertok(i2c_set_bus_speed(bus, 400000));
-	ut_asserteq(400000, i2c_get_bus_speed(bus));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
-	ut_asserteq(-EINVAL, i2c_write(dev, 0, buf, 5));
+	ut_assertok(i2c_get_chip(bus, chip, 1, &dev));
+	ut_assertok(dm_i2c_set_bus_speed(bus, 100000));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_set_bus_speed(bus, 400000));
+	ut_asserteq(400000, dm_i2c_get_bus_speed(bus));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
+	ut_asserteq(-EINVAL, dm_i2c_write(dev, 0, buf, 5));
 
 	return 0;
 }
@@ -84,9 +84,9 @@
 	uint8_t buf[5];
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_get_chip(bus, chip, &dev));
+	ut_assertok(i2c_get_chip(bus, chip, 1, &dev));
 	ut_assertok(i2c_set_chip_offset_len(dev, 1));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 
 	/* This is not supported by the uclass */
 	ut_asserteq(-EINVAL, i2c_set_chip_offset_len(dev, 5));
@@ -100,7 +100,7 @@
 	struct udevice *bus, *dev;
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev));
+	ut_assertok(dm_i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev));
 
 	return 0;
 }
@@ -113,8 +113,8 @@
 	uint8_t buf[5];
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
-	ut_assertok(i2c_get_chip(bus, chip, &dev));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(i2c_get_chip(bus, chip, 1, &dev));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
 
 	/* Tell the EEPROM to only read/write one register at a time */
@@ -123,34 +123,34 @@
 	sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_SINGLE_BYTE);
 
 	/* Now we only get the first byte - the rest will be 0xff */
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
 
 	/* If we do a separate transaction for each byte, it works */
 	ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
 
 	/* This will only write A */
 	ut_assertok(i2c_set_chip_flags(dev, 0));
-	ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
 
 	/* Check that the B was ignored */
 	ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0A\0\0\0", sizeof(buf)));
 
 	/* Now write it again with the new flags, it should work */
 	ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS));
-	ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
 
 	ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS |
 						DM_I2C_CHIP_RD_ADDRESS));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "\0\0AB\0\0", sizeof(buf)));
 
 	/* Restore defaults */
@@ -167,45 +167,45 @@
 	struct udevice *dev;
 	uint8_t buf[5];
 
-	ut_assertok(i2c_get_chip_for_busnum(busnum, chip, &dev));
+	ut_assertok(i2c_get_chip_for_busnum(busnum, chip, 1, &dev));
 
 	/* Do a transfer so we can find the emulator */
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom));
 
 	/* Offset length 0 */
 	sandbox_i2c_eeprom_set_offset_len(eeprom, 0);
 	ut_assertok(i2c_set_chip_offset_len(dev, 0));
-	ut_assertok(i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "AB\0\0\0\0", sizeof(buf)));
 
 	/* Offset length 1 */
 	sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
 	ut_assertok(i2c_set_chip_offset_len(dev, 1));
-	ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_assertok(memcmp(buf, "ABAB\0", sizeof(buf)));
 
 	/* Offset length 2 */
 	sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
 	ut_assertok(i2c_set_chip_offset_len(dev, 2));
-	ut_assertok(i2c_write(dev, 0x210, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0x210, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 0x210, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0x210, buf, 5));
 	ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
 
 	/* Offset length 3 */
 	sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
 	ut_assertok(i2c_set_chip_offset_len(dev, 2));
-	ut_assertok(i2c_write(dev, 0x410, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0x410, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 0x410, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0x410, buf, 5));
 	ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
 
 	/* Offset length 4 */
 	sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
 	ut_assertok(i2c_set_chip_offset_len(dev, 2));
-	ut_assertok(i2c_write(dev, 0x420, (uint8_t *)"AB", 2));
-	ut_assertok(i2c_read(dev, 0x420, buf, 5));
+	ut_assertok(dm_i2c_write(dev, 0x420, (uint8_t *)"AB", 2));
+	ut_assertok(dm_i2c_read(dev, 0x420, buf, 5));
 	ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
 
 	/* Restore defaults */
diff --git a/test/dm/spi.c b/test/dm/spi.c
index 61b5b25..c7ee652 100644
--- a/test/dm/spi.c
+++ b/test/dm/spi.c
@@ -36,7 +36,6 @@
 	ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
 	ut_assertok(spi_cs_info(bus, cs, &info));
 	of_offset = info.dev->of_offset;
-	sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
 	device_remove(info.dev);
 	device_unbind(info.dev);
 
@@ -45,7 +44,7 @@
 	 * reports that CS 0 is present
 	 */
 	ut_assertok(spi_cs_info(bus, cs, &info));
-	ut_asserteq_ptr(info.dev, NULL);
+	ut_asserteq_ptr(NULL, info.dev);
 
 	/* This finds nothing because we removed the device */
 	ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
@@ -62,8 +61,9 @@
 	ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode,
 						"spi_flash_std", "name", &bus,
 						&slave));
+	sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
 	ut_assertok(spi_cs_info(bus, cs, &info));
-	ut_asserteq_ptr(info.dev, NULL);
+	ut_asserteq_ptr(NULL, info.dev);
 
 	/* Add the emulation and try again */
 	ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, of_offset,
diff --git a/test/dm/test-dm.sh b/test/dm/test-dm.sh
index bb99677..8ebc392 100755
--- a/test/dm/test-dm.sh
+++ b/test/dm/test-dm.sh
@@ -1,9 +1,14 @@
 #!/bin/sh
 
+die() {
+	echo $1
+	exit 1
+}
+
 NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
 dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb
-make O=sandbox sandbox_config
-make O=sandbox -s -j${NUM_CPUS}
+make O=sandbox sandbox_config || die "Cannot configure U-Boot"
+make O=sandbox -s -j${NUM_CPUS} || die "Cannot build U-Boot"
 dd if=/dev/zero of=spi.bin bs=1M count=2
 ./sandbox/u-boot -d test/dm/test.dtb -c "dm test"
 rm spi.bin
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index cd2c389..b8ee959 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -51,6 +51,13 @@
 
 	priv->ping_total += DM_TEST_START_TOTAL;
 
+	/*
+	 * If this device is on a bus, the uclass_flag will be set before
+	 * calling this function. This is used by
+	 * dm_test_bus_child_pre_probe_uclass().
+	 */
+	priv->uclass_total += priv->uclass_flag;
+
 	return 0;
 }
 
@@ -89,6 +96,7 @@
 UCLASS_DRIVER(testfdt) = {
 	.name		= "testfdt",
 	.id		= UCLASS_TEST_FDT,
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 };
 
 int dm_check_devices(struct dm_test_state *dms, int num_devices)
@@ -128,7 +136,7 @@
 /* Test that FDT-based binding works correctly */
 static int dm_test_fdt(struct dm_test_state *dms)
 {
-	const int num_devices = 4;
+	const int num_devices = 6;
 	struct udevice *dev;
 	struct uclass *uc;
 	int ret;
@@ -143,12 +151,12 @@
 	/* These are num_devices compatible root-level device tree nodes */
 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
 
-	/* Each should have no platdata / priv */
+	/* Each should have platform data but no private data */
 	for (i = 0; i < num_devices; i++) {
 		ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
 		ut_assert(!ret);
 		ut_assert(!dev_get_priv(dev));
-		ut_assert(!dev->platdata);
+		ut_assert(dev->platdata);
 	}
 
 	ut_assertok(dm_check_devices(dms, num_devices));
@@ -184,7 +192,7 @@
 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev));
 	ut_asserteq_str("b-test", dev->name);
 
-	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 0, true, &dev));
+	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev));
 	ut_asserteq_str("a-test", dev->name);
 
 	ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5,
@@ -220,11 +228,11 @@
 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1,
 						      &dev));
 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
-	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 1, &dev));
+	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev));
 
 	/* But now that it is probed, we can find it */
 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev));
-	ut_asserteq_str("a-test", dev->name);
+	ut_asserteq_str("f-test", dev->name);
 
 	return 0;
 }
diff --git a/test/dm/test.dts b/test/dm/test.dts
index fb0272a..84024a4 100644
--- a/test/dm/test.dts
+++ b/test/dm/test.dts
@@ -8,7 +8,15 @@
 
 	aliases {
 		console = &uart0;
+		i2c0 = "/i2c@0";
+		spi0 = "/spi@0";
 		testfdt6 = "/e-test";
+		testbus3 = "/some-bus";
+		testfdt0 = "/some-bus/c-test@0";
+		testfdt1 = "/some-bus/c-test@1";
+		testfdt3 = "/b-test";
+		testfdt5 = "/some-bus/c-test@5";
+		testfdt8 = "/a-test";
 	};
 
 	uart0: serial {
@@ -22,6 +30,11 @@
 		ping-expect = <0>;
 		ping-add = <0>;
 		u-boot,dm-pre-reloc;
+		test-gpios = <&gpio_a 1>, <&gpio_a 4>, <&gpio_b 5 0 3 2 1>,
+			<0>, <&gpio_a 12>;
+		test2-gpios = <&gpio_a 1>, <&gpio_a 4>, <&gpio_b 6 1 3 2 1>,
+			<&gpio_b 7 2 3 2 1>, <&gpio_b 8 4 3 2 1>,
+			<&gpio_b 9 0xc 3 2 1>;
 	};
 
 	junk {
@@ -81,14 +94,26 @@
 		compatible = "google,another-fdt-test";
 	};
 
+	f-test {
+		compatible = "denx,u-boot-fdt-test";
+	};
+
+	g-test {
+		compatible = "denx,u-boot-fdt-test";
+	};
+
 	gpio_a: base-gpios {
 		compatible = "sandbox,gpio";
+		gpio-controller;
+		#gpio-cells = <1>;
 		gpio-bank-name = "a";
 		num-gpios = <20>;
 	};
 
-	extra-gpios {
+	gpio_b: extra-gpios {
 		compatible = "sandbox,gpio";
+		gpio-controller;
+		#gpio-cells = <5>;
 		gpio-bank-name = "b";
 		num-gpios = <10>;
 	};
diff --git a/test/image/test-imagetools.sh b/test/image/test-imagetools.sh
index 9e299e1..952f975 100755
--- a/test/image/test-imagetools.sh
+++ b/test/image/test-imagetools.sh
@@ -13,9 +13,11 @@
 # ./test/image/test-imagetools.sh
 
 BASEDIR=sandbox
-SRCDIR=sandbox/boot
+SRCDIR=${BASEDIR}/boot
 IMAGE_NAME="v1.0-test"
-IMAGE=linux.img
+IMAGE_MULTI=linux.img
+IMAGE_FIT_ITS=linux.its
+IMAGE_FIT_ITB=linux.itb
 DATAFILE0=vmlinuz
 DATAFILE1=initrd.img
 DATAFILE2=System.map
@@ -34,14 +36,17 @@
 	for file in ${DATAFILES}; do
 		rm -f ${file} ${SRCDIR}/${file}
 	done
-	rm -f ${IMAGE} ${DUMPIMAGE_LIST} ${MKIMAGE_LIST} ${TEST_OUT}
+	rm -f ${IMAGE_MULTI}
+	rm -f ${DUMPIMAGE_LIST}
+	rm -f ${MKIMAGE_LIST}
+	rm -f ${TEST_OUT}
 	rmdir ${SRCDIR}
 }
 
 # Check that two files are the same
 assert_equal()
 {
-	if ! diff $1 $2; then
+	if ! diff -u $1 $2; then
 		echo "Failed."
 		cleanup
 		exit 1
@@ -82,35 +87,103 @@
 	${cmd} >${redir}
 }
 
-# Write files into an image
-create_image()
+# Write files into an multi-file image
+create_multi_image()
 {
 	local files="${SRCDIR}/${DATAFILE0}:${SRCDIR}/${DATAFILE1}"
 	files+=":${SRCDIR}/${DATAFILE2}"
 
-	echo -e "\nBuilding image..."
+	echo -e "\nBuilding multi-file image..."
 	do_cmd ${MKIMAGE} -A x86 -O linux -T multi -n \"${IMAGE_NAME}\" \
-		-d ${files} ${IMAGE}
+		-d ${files} ${IMAGE_MULTI}
 	echo "done."
 }
 
-# Extract files from an image
-extract_image()
+# Extract files from an multi-file image
+extract_multi_image()
 {
-	echo -e "\nExtracting image contents..."
-	do_cmd ${DUMPIMAGE} -i ${IMAGE} -p 0 ${DATAFILE0}
-	do_cmd ${DUMPIMAGE} -i ${IMAGE} -p 1 ${DATAFILE1}
-	do_cmd ${DUMPIMAGE} -i ${IMAGE} -p 2 ${DATAFILE2}
-	do_cmd ${DUMPIMAGE} -i ${IMAGE} -p 2 ${DATAFILE2} -o ${TEST_OUT}
+	echo -e "\nExtracting multi-file image contents..."
+	do_cmd ${DUMPIMAGE} -T multi -i ${IMAGE_MULTI} -p 0 ${DATAFILE0}
+	do_cmd ${DUMPIMAGE} -T multi -i ${IMAGE_MULTI} -p 1 ${DATAFILE1}
+	do_cmd ${DUMPIMAGE} -T multi -i ${IMAGE_MULTI} -p 2 ${DATAFILE2}
+	do_cmd ${DUMPIMAGE} -T multi -i ${IMAGE_MULTI} -p 2 ${DATAFILE2} -o ${TEST_OUT}
+	echo "done."
+}
+
+# Write files into a FIT image
+create_fit_image()
+{
+	echo " \
+	/dts-v1/; \
+	/ { \
+	    description = \"FIT image\"; \
+	    #address-cells = <1>; \
+	\
+	    images { \
+	        kernel@1 { \
+	            description = \"kernel\"; \
+	            data = /incbin/(\"${DATAFILE0}\"); \
+	            type = \"kernel\"; \
+	            arch = \"sandbox\"; \
+	            os = \"linux\"; \
+	            compression = \"gzip\"; \
+	            load = <0x40000>; \
+	            entry = <0x8>; \
+	        }; \
+	        ramdisk@1 { \
+	            description = \"filesystem\"; \
+	            data = /incbin/(\"${DATAFILE1}\"); \
+	            type = \"ramdisk\"; \
+	            arch = \"sandbox\"; \
+	            os = \"linux\"; \
+	            compression = \"none\"; \
+	            load = <0x80000>; \
+	            entry = <0x16>; \
+	        }; \
+	        fdt@1 { \
+	            description = \"device tree\"; \
+	            data = /incbin/(\"${DATAFILE2}\"); \
+	            type = \"flat_dt\"; \
+	            arch = \"sandbox\"; \
+	            compression = \"none\"; \
+	        }; \
+	    }; \
+	    configurations { \
+	        default = \"conf@1\"; \
+	        conf@1 { \
+	            kernel = \"kernel@1\"; \
+	            fdt = \"fdt@1\"; \
+	        }; \
+	    }; \
+	}; \
+	" > ${IMAGE_FIT_ITS}
+
+	echo -e "\nBuilding FIT image..."
+	do_cmd ${MKIMAGE} -f ${IMAGE_FIT_ITS} ${IMAGE_FIT_ITB}
+	echo "done."
+}
+
+# Extract files from a FIT image
+extract_fit_image()
+{
+	echo -e "\nExtracting FIT image contents..."
+	do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 0 ${DATAFILE0}
+	do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 1 ${DATAFILE1}
+	do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 2 ${DATAFILE2}
+	do_cmd ${DUMPIMAGE} -T flat_dt -i ${IMAGE_FIT_ITB} -p 2 ${DATAFILE2} -o ${TEST_OUT}
 	echo "done."
 }
 
 # List the contents of a file
+# Args:
+#    image filename
 list_image()
 {
+	local image="$1"
+
 	echo -e "\nListing image contents..."
-	do_cmd_redir ${MKIMAGE_LIST} ${MKIMAGE} -l ${IMAGE}
-	do_cmd_redir ${DUMPIMAGE_LIST} ${DUMPIMAGE} -l ${IMAGE}
+	do_cmd_redir ${MKIMAGE_LIST} ${MKIMAGE} -l ${image}
+	do_cmd_redir ${DUMPIMAGE_LIST} ${DUMPIMAGE} -l ${image}
 	echo "done."
 }
 
@@ -120,16 +193,28 @@
 
 	create_files
 
-	# Compress and extract multifile images, compare the result
-	create_image
-	extract_image
+	# Compress and extract multi-file images, compare the result
+	create_multi_image
+	extract_multi_image
 	for file in ${DATAFILES}; do
 		assert_equal ${file} ${SRCDIR}/${file}
 	done
 	assert_equal ${TEST_OUT} ${DATAFILE2}
 
-	# List contents and compares output fro tools
-	list_image
+	# List contents of multi-file image and compares output from tools
+	list_image ${IMAGE_MULTI}
+	assert_equal ${DUMPIMAGE_LIST} ${MKIMAGE_LIST}
+
+	# Compress and extract FIT images, compare the result
+	create_fit_image
+	extract_fit_image
+	for file in ${DATAFILES}; do
+		assert_equal ${file} ${SRCDIR}/${file}
+	done
+	assert_equal ${TEST_OUT} ${DATAFILE2}
+
+	# List contents of FIT image and compares output from tools
+	list_image ${IMAGE_FIT_ITB}
 	assert_equal ${DUMPIMAGE_LIST} ${MKIMAGE_LIST}
 
 	# Remove files created
diff --git a/tools/Makefile b/tools/Makefile
index e549f8e..88770b0 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -60,7 +60,8 @@
 LIBFDT_OBJS := $(addprefix lib/libfdt/, \
 			fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o)
 RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
-					rsa-sign.o rsa-verify.o rsa-checksum.o)
+					rsa-sign.o rsa-verify.o rsa-checksum.o \
+					rsa-mod-exp.o)
 
 # common objs for dumpimage and mkimage
 dumpimage-mkimage-objs := aisimage.o \
@@ -90,6 +91,7 @@
 			socfpgaimage.o \
 			lib/sha1.o \
 			lib/sha256.o \
+			common/hash.o \
 			ublimage.o \
 			$(LIBFDT_OBJS) \
 			$(RSA_OBJS-y)
@@ -113,6 +115,10 @@
 HOST_EXTRACFLAGS	+= -DCONFIG_FIT_SIGNATURE
 endif
 
+ifdef CONFIG_SYS_SPI_U_BOOT_OFFS
+HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_SPI_U_BOOT_OFFS=$(CONFIG_SYS_SPI_U_BOOT_OFFS)
+endif
+
 # MXSImage needs LibSSL
 ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_FIT_SIGNATURE),)
 HOSTLOADLIBES_mkimage += -lssl -lcrypto
diff --git a/tools/aisimage.c b/tools/aisimage.c
index 8de370a..9338342 100644
--- a/tools/aisimage.c
+++ b/tools/aisimage.c
@@ -413,19 +413,17 @@
 /*
  * aisimage parameters
  */
-static struct image_type_params aisimage_params = {
-	.name		= "TI Davinci AIS Boot Image support",
-	.header_size	= 0,
-	.hdr		= NULL,
-	.check_image_type = aisimage_check_image_types,
-	.verify_header	= aisimage_verify_header,
-	.print_header	= aisimage_print_header,
-	.set_header	= aisimage_set_header,
-	.check_params	= aisimage_check_params,
-	.vrec_header	= aisimage_generate,
-};
-
-void init_ais_image_type(void)
-{
-	register_image_type(&aisimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	aisimage,
+	"TI Davinci AIS Boot Image support",
+	0,
+	NULL,
+	aisimage_check_params,
+	aisimage_verify_header,
+	aisimage_print_header,
+	aisimage_set_header,
+	NULL,
+	aisimage_check_image_types,
+	NULL,
+	aisimage_generate
+);
diff --git a/tools/atmelimage.c b/tools/atmelimage.c
index c8101d2..5b72ac5 100644
--- a/tools/atmelimage.c
+++ b/tools/atmelimage.c
@@ -324,19 +324,17 @@
 	return EXIT_SUCCESS;
 }
 
-static struct image_type_params atmelimage_params = {
-	.name		= "ATMEL ROM-Boot Image support",
-	.header_size	= 0,
-	.hdr		= NULL,
-	.check_image_type = atmel_check_image_type,
-	.verify_header	= atmel_verify_header,
-	.print_header	= atmel_print_header,
-	.set_header	= atmel_set_header,
-	.check_params	= atmel_check_params,
-	.vrec_header	= atmel_vrec_header,
-};
-
-void init_atmel_image_type(void)
-{
-	register_image_type(&atmelimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	atmelimage,
+	"ATMEL ROM-Boot Image support",
+	0,
+	NULL,
+	atmel_check_params,
+	atmel_verify_header,
+	atmel_print_header,
+	atmel_set_header,
+	NULL,
+	atmel_check_image_type,
+	NULL,
+	atmel_vrec_header
+);
diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py
index d4c5d4a..537797a 100644
--- a/tools/buildman/toolchain.py
+++ b/tools/buildman/toolchain.py
@@ -197,13 +197,14 @@
         Returns:
             Filename of C compiler if found, else None
         """
+        fnames = []
         for subdir in ['.', 'bin', 'usr/bin']:
             dirname = os.path.join(path, subdir)
             if verbose: print "      - looking in '%s'" % dirname
             for fname in glob.glob(dirname + '/*gcc'):
                 if verbose: print "         - found '%s'" % fname
-                return fname
-        return None
+                fnames.append(fname)
+        return fnames
 
 
     def Scan(self, verbose):
@@ -219,8 +220,8 @@
         if verbose: print 'Scanning for tool chains'
         for path in self.paths:
             if verbose: print "   - scanning path '%s'" % path
-            fname = self.ScanPath(path, verbose)
-            if fname:
+            fnames = self.ScanPath(path, verbose)
+            for fname in fnames:
                 self.Add(fname, True, verbose)
 
     def List(self):
diff --git a/tools/default_image.c b/tools/default_image.c
index 0a0792e..cf5c0d4 100644
--- a/tools/default_image.c
+++ b/tools/default_image.c
@@ -15,6 +15,8 @@
  */
 
 #include "imagetool.h"
+#include "mkimage.h"
+
 #include <image.h>
 #include <u-boot/crc.h>
 
@@ -53,9 +55,8 @@
 	memcpy(hdr, ptr, sizeof(image_header_t));
 
 	if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) {
-		fprintf(stderr,
-			"%s: Bad Magic Number: \"%s\" is no valid image\n",
-			params->cmdname, params->imagefile);
+		debug("%s: Bad Magic Number: \"%s\" is no valid image\n",
+		      params->cmdname, params->imagefile);
 		return -FDT_ERR_BADMAGIC;
 	}
 
@@ -66,9 +67,8 @@
 	hdr->ih_hcrc = cpu_to_be32(0);	/* clear for re-calculation */
 
 	if (crc32(0, data, len) != checksum) {
-		fprintf(stderr,
-			"%s: ERROR: \"%s\" has bad header checksum!\n",
-			params->cmdname, params->imagefile);
+		debug("%s: ERROR: \"%s\" has bad header checksum!\n",
+		      params->cmdname, params->imagefile);
 		return -FDT_ERR_BADSTATE;
 	}
 
@@ -77,9 +77,8 @@
 
 	checksum = be32_to_cpu(hdr->ih_dcrc);
 	if (crc32(0, data, len) != checksum) {
-		fprintf(stderr,
-			"%s: ERROR: \"%s\" has corrupted data!\n",
-			params->cmdname, params->imagefile);
+		debug("%s: ERROR: \"%s\" has corrupted data!\n",
+		      params->cmdname, params->imagefile);
 		return -FDT_ERR_BADSTRUCTURE;
 	}
 	return 0;
@@ -117,33 +116,7 @@
 	image_set_hcrc(hdr, checksum);
 }
 
-static int image_save_datafile(struct image_tool_params *params,
-			       ulong file_data, ulong file_len)
-{
-	int dfd;
-	const char *datafile = params->outfile;
-
-	dfd = open(datafile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
-		   S_IRUSR | S_IWUSR);
-	if (dfd < 0) {
-		fprintf(stderr, "%s: Can't open \"%s\": %s\n",
-			params->cmdname, datafile, strerror(errno));
-		return -1;
-	}
-
-	if (write(dfd, (void *)file_data, file_len) != (ssize_t)file_len) {
-		fprintf(stderr, "%s: Write error on \"%s\": %s\n",
-			params->cmdname, datafile, strerror(errno));
-		close(dfd);
-		return -1;
-	}
-
-	close(dfd);
-
-	return 0;
-}
-
-static int image_extract_datafile(void *ptr, struct image_tool_params *params)
+static int image_extract_subimage(void *ptr, struct image_tool_params *params)
 {
 	const image_header_t *hdr = (const image_header_t *)ptr;
 	ulong file_data;
@@ -170,25 +143,23 @@
 	}
 
 	/* save the "data file" into the file system */
-	return image_save_datafile(params, file_data, file_len);
+	return imagetool_save_subimage(params->outfile, file_data, file_len);
 }
 
 /*
  * Default image type parameters definition
  */
-static struct image_type_params defimage_params = {
-	.name = "Default Image support",
-	.header_size = sizeof(image_header_t),
-	.hdr = (void*)&header,
-	.check_image_type = image_check_image_types,
-	.verify_header = image_verify_header,
-	.print_header = image_print_contents,
-	.set_header = image_set_header,
-	.extract_datafile = image_extract_datafile,
-	.check_params = image_check_params,
-};
-
-void init_default_image_type(void)
-{
-	register_image_type(&defimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	defimage,
+	"Default Image support",
+	sizeof(image_header_t),
+	(void *)&header,
+	image_check_params,
+	image_verify_header,
+	image_print_contents,
+	image_set_header,
+	image_extract_subimage,
+	image_check_image_types,
+	NULL,
+	NULL
+);
diff --git a/tools/dumpimage.c b/tools/dumpimage.c
index 542ee28..75a5d47 100644
--- a/tools/dumpimage.c
+++ b/tools/dumpimage.c
@@ -12,112 +12,13 @@
 
 static void usage(void);
 
-/* image_type_params linked list to maintain registered image types supports */
-static struct image_type_params *dumpimage_tparams;
-
 /* parameters initialized by core will be used by the image type code */
 static struct image_tool_params params = {
 	.type = IH_TYPE_KERNEL,
 };
 
-/**
- * dumpimage_register() - register respective image generation/list support
- *
- * the input struct image_type_params is checked and appended to the link
- * list, if the input structure is already registered, issue an error
- *
- * @tparams: Image type parameters
- */
-static void dumpimage_register(struct image_type_params *tparams)
-{
-	struct image_type_params **tp;
-
-	if (!tparams) {
-		fprintf(stderr, "%s: %s: Null input\n", params.cmdname,
-			__func__);
-		exit(EXIT_FAILURE);
-	}
-
-	/* scan the linked list, check for registry and point the last one */
-	for (tp = &dumpimage_tparams; *tp != NULL; tp = &(*tp)->next) {
-		if (!strcmp((*tp)->name, tparams->name)) {
-			fprintf(stderr, "%s: %s already registered\n",
-				params.cmdname, tparams->name);
-			return;
-		}
-	}
-
-	/* add input struct entry at the end of link list */
-	*tp = tparams;
-	/* mark input entry as last entry in the link list */
-	tparams->next = NULL;
-
-	debug("Registered %s\n", tparams->name);
-}
-
-/**
- * dumpimage_get_type() - find the image type params for a given image type
- *
- * Scan all registered image types and check the input type_id for each
- * supported image type
- *
- * @return respective image_type_params pointer. If the input type is not
- * supported by any of registered image types, returns NULL
- */
-static struct image_type_params *dumpimage_get_type(int type)
-{
-	struct image_type_params *curr;
-
-	for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
-		if (curr->check_image_type) {
-			if (!curr->check_image_type(type))
-				return curr;
-		}
-	}
-	return NULL;
-}
-
 /*
- * dumpimage_verify_print_header() - verifies the image header
- *
- * Scan registered image types and verify the image_header for each
- * supported image type. If verification is successful, this prints
- * the respective header.
- *
- * @return 0 on success, negative if input image format does not match with
- * any of supported image types
- */
-static int dumpimage_verify_print_header(void *ptr, struct stat *sbuf)
-{
-	int retval = -1;
-	struct image_type_params *curr;
-
-	for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
-		if (curr->verify_header) {
-			retval = curr->verify_header((unsigned char *)ptr,
-						     sbuf->st_size, &params);
-			if (retval != 0)
-				continue;
-			/*
-			 * Print the image information  if verify is
-			 * successful
-			 */
-			if (curr->print_header) {
-				curr->print_header(ptr);
-			} else {
-				fprintf(stderr,
-					"%s: print_header undefined for %s\n",
-					params.cmdname, curr->name);
-			}
-			break;
-		}
-	}
-
-	return retval;
-}
-
-/*
- * dumpimage_extract_datafile -
+ * dumpimage_extract_subimage -
  *
  * It scans all registered image types,
  * verifies image_header for each supported image type
@@ -127,29 +28,27 @@
  * returns negative if input image format does not match with any of
  * supported image types
  */
-static int dumpimage_extract_datafile(void *ptr, struct stat *sbuf)
+static int dumpimage_extract_subimage(struct image_type_params *tparams,
+		void *ptr, struct stat *sbuf)
 {
 	int retval = -1;
-	struct image_type_params *curr;
 
-	for (curr = dumpimage_tparams; curr != NULL; curr = curr->next) {
-		if (curr->verify_header) {
-			retval = curr->verify_header((unsigned char *)ptr,
-						     sbuf->st_size, &params);
-			if (retval != 0)
-				continue;
-			/*
-			 * Extract the file from the image
-			 * if verify is successful
-			 */
-			if (curr->extract_datafile) {
-				curr->extract_datafile(ptr, &params);
-			} else {
-				fprintf(stderr,
-					"%s: extract_datafile undefined for %s\n",
-					params.cmdname, curr->name);
-			break;
-			}
+	if (tparams->verify_header) {
+		retval = tparams->verify_header((unsigned char *)ptr,
+				sbuf->st_size, &params);
+		if (retval != 0)
+			return -1;
+		/*
+		 * Extract the file from the image
+		 * if verify is successful
+		 */
+		if (tparams->extract_subimage) {
+			retval = tparams->extract_subimage(ptr, &params);
+		} else {
+			fprintf(stderr,
+				"%s: extract_subimage undefined for %s\n",
+				params.cmdname, tparams->name);
+			return -2;
 		}
 	}
 
@@ -165,12 +64,9 @@
 	int retval = 0;
 	struct image_type_params *tparams = NULL;
 
-	/* Init all image generation/list support */
-	register_image_tool(dumpimage_register);
-
 	params.cmdname = *argv;
 
-	while ((opt = getopt(argc, argv, "li:o:p:V")) != -1) {
+	while ((opt = getopt(argc, argv, "li:o:T:p:V")) != -1) {
 		switch (opt) {
 		case 'l':
 			params.lflag = 1;
@@ -182,6 +78,12 @@
 		case 'o':
 			params.outfile = optarg;
 			break;
+		case 'T':
+			params.type = genimg_get_type_id(optarg);
+			if (params.type < 0) {
+				usage();
+			}
+			break;
 		case 'p':
 			params.pflag = strtoul(optarg, &ptr, 10);
 			if (*ptr) {
@@ -196,6 +98,7 @@
 			exit(EXIT_SUCCESS);
 		default:
 			usage();
+			break;
 		}
 	}
 
@@ -203,9 +106,9 @@
 		usage();
 
 	/* set tparams as per input type_id */
-	tparams = dumpimage_get_type(params.type);
+	tparams = imagetool_get_type(params.type);
 	if (tparams == NULL) {
-		fprintf(stderr, "%s: unsupported type %s\n",
+		fprintf(stderr, "%s: unsupported type: %s\n",
 			params.cmdname, genimg_get_type_name(params.type));
 		exit(EXIT_FAILURE);
 	}
@@ -242,7 +145,7 @@
 			exit(EXIT_FAILURE);
 		}
 
-		if ((unsigned)sbuf.st_size < tparams->header_size) {
+		if ((uint32_t)sbuf.st_size < tparams->header_size) {
 			fprintf(stderr,
 				"%s: Bad size: \"%s\" is not valid image\n",
 				params.cmdname, params.imagefile);
@@ -267,13 +170,15 @@
 			 * Extract the data files from within the matched
 			 * image type. Returns the error code if not matched
 			 */
-			retval = dumpimage_extract_datafile(ptr, &sbuf);
+			retval = dumpimage_extract_subimage(tparams, ptr,
+					&sbuf);
 		} else {
 			/*
 			 * Print the image information for matched image type
 			 * Returns the error code if not matched
 			 */
-			retval = dumpimage_verify_print_header(ptr, &sbuf);
+			retval = imagetool_verify_print_header(ptr, &sbuf,
+					tparams, &params);
 		}
 
 		(void)munmap((void *)ptr, sbuf.st_size);
@@ -293,9 +198,10 @@
 		"          -l ==> list image header information\n",
 		params.cmdname);
 	fprintf(stderr,
-		"       %s -i image [-p position] [-o outfile] data_file\n"
-		"          -i ==> extract from the 'image' a specific 'data_file'"
-		", indexed by 'position' (starting at 0)\n",
+		"       %s -i image -T type [-p position] [-o outfile] data_file\n"
+		"          -i ==> extract from the 'image' a specific 'data_file'\n"
+		"          -T ==> set image type to 'type'\n"
+		"          -p ==> 'position' (starting at 0) of the 'data_file' inside the 'image'\n",
 		params.cmdname);
 	fprintf(stderr,
 		"       %s -V ==> print version information and exit\n",
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index c9b9f6a..6f216f9 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -20,3 +20,6 @@
 
 # Block device example
 #/dev/mmcblk0		0xc0000		0x20000
+
+# VFAT example
+#/boot/uboot.env	0x0000          0x4000
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 3ececf9..eb2a25e 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -155,6 +155,97 @@
 	return -1;
 }
 
+/**
+ * fit_image_extract - extract a FIT component image
+ * @fit: pointer to the FIT format image header
+ * @image_noffset: offset of the component image node
+ * @file_name: name of the file to store the FIT sub-image
+ *
+ * returns:
+ *     zero in case of success or a negative value if fail.
+ */
+static int fit_image_extract(
+	const void *fit,
+	int image_noffset,
+	const char *file_name)
+{
+	const void *file_data;
+	size_t file_size = 0;
+
+	/* get the "data" property of component at offset "image_noffset" */
+	fit_image_get_data(fit, image_noffset, &file_data, &file_size);
+
+	/* save the "file_data" into the file specified by "file_name" */
+	return imagetool_save_subimage(file_name, (ulong) file_data, file_size);
+}
+
+/**
+ * fit_extract_contents - retrieve a sub-image component from the FIT image
+ * @ptr: pointer to the FIT format image header
+ * @params: command line parameters
+ *
+ * returns:
+ *     zero in case of success or a negative value if fail.
+ */
+static int fit_extract_contents(void *ptr, struct image_tool_params *params)
+{
+	int images_noffset;
+	int noffset;
+	int ndepth;
+	const void *fit = ptr;
+	int count = 0;
+	const char *p;
+
+	/* Indent string is defined in header image.h */
+	p = IMAGE_INDENT_STRING;
+
+	if (!fit_check_format(fit)) {
+		printf("Bad FIT image format\n");
+		return -1;
+	}
+
+	/* Find images parent node offset */
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (images_noffset < 0) {
+		printf("Can't find images parent node '%s' (%s)\n",
+		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
+		return -1;
+	}
+
+	/* Avoid any overrun */
+	count = fit_get_subimage_count(fit, images_noffset);
+	if ((params->pflag < 0) || (count <= params->pflag)) {
+		printf("No such component at '%d'\n", params->pflag);
+		return -1;
+	}
+
+	/* Process its subnodes, extract the desired component from image */
+	for (ndepth = 0, count = 0,
+		noffset = fdt_next_node(fit, images_noffset, &ndepth);
+		(noffset >= 0) && (ndepth > 0);
+		noffset = fdt_next_node(fit, noffset, &ndepth)) {
+		if (ndepth == 1) {
+			/*
+			 * Direct child node of the images parent node,
+			 * i.e. component image node.
+			 */
+			if (params->pflag == count) {
+				printf("Extracted:\n%s Image %u (%s)\n", p,
+				       count, fit_get_name(fit, noffset, NULL));
+
+				fit_image_print(fit, noffset, p);
+
+				return fit_image_extract(fit, noffset,
+						params->outfile);
+			}
+
+			count++;
+		}
+	}
+
+	return 0;
+}
+
 static int fit_check_params(struct image_tool_params *params)
 {
 	return	((params->dflag && (params->fflag || params->lflag)) ||
@@ -162,19 +253,17 @@
 		(params->lflag && (params->dflag || params->fflag)));
 }
 
-static struct image_type_params fitimage_params = {
-	.name = "FIT Image support",
-	.header_size = sizeof(image_header_t),
-	.hdr = (void*)&header,
-	.verify_header = fit_verify_header,
-	.print_header = fit_print_contents,
-	.check_image_type = fit_check_image_types,
-	.fflag_handle = fit_handle_file,
-	.set_header = NULL,	/* FIT images use DTB header */
-	.check_params = fit_check_params,
-};
-
-void init_fit_image_type (void)
-{
-	register_image_type(&fitimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	fitimage,
+	"FIT Image support",
+	sizeof(image_header_t),
+	(void *)&header,
+	fit_check_params,
+	fit_verify_header,
+	fit_print_contents,
+	NULL,
+	fit_extract_contents,
+	fit_check_image_types,
+	fit_handle_file,
+	NULL /* FIT images use DTB header */
+);
diff --git a/tools/gpimage-common.c b/tools/gpimage-common.c
index b343a3a..5ad52be 100644
--- a/tools/gpimage-common.c
+++ b/tools/gpimage-common.c
@@ -32,7 +32,8 @@
 
 int gph_verify_header(struct gp_header *gph, int be)
 {
-	uint32_t gph_size = gph->size, gph_load_addr = gph->load_addr;
+	uint32_t gph_size = gph->size;
+	uint32_t gph_load_addr = gph->load_addr;
 
 	if (be)
 		to_be32(&gph_size, &gph_load_addr);
diff --git a/tools/gpimage.c b/tools/gpimage.c
index 1cabb5b..1adc55c 100644
--- a/tools/gpimage.c
+++ b/tools/gpimage.c
@@ -60,18 +60,17 @@
 /*
  * gpimage parameters
  */
-static struct image_type_params gpimage_params = {
-	.name		= "TI KeyStone GP Image support",
-	.header_size	= GPIMAGE_HDR_SIZE,
-	.hdr		= (void *)&gpimage_header,
-	.check_image_type = gpimage_check_image_types,
-	.verify_header	= gpimage_verify_header,
-	.print_header	= gpimage_print_header,
-	.set_header	= gpimage_set_header,
-	.check_params	= gpimage_check_params,
-};
-
-void init_gpimage_type(void)
-{
-	register_image_type(&gpimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	gpimage,
+	"TI KeyStone GP Image support",
+	GPIMAGE_HDR_SIZE,
+	(void *)&gpimage_header,
+	gpimage_check_params,
+	gpimage_verify_header,
+	gpimage_print_header,
+	gpimage_set_header,
+	NULL,
+	gpimage_check_image_types,
+	NULL,
+	NULL
+);
diff --git a/tools/imagetool.c b/tools/imagetool.c
index 98717bd..4b0b73d 100644
--- a/tools/imagetool.c
+++ b/tools/imagetool.c
@@ -8,57 +8,86 @@
 
 #include "imagetool.h"
 
-/*
- * Callback function to register a image type within a tool
- */
-static imagetool_register_t register_func;
+#include <image.h>
 
-/*
- * register_image_tool -
- *
- * The tool provides its own registration function in order to all image
- * types initialize themselves.
- */
-void register_image_tool(imagetool_register_t image_register)
+struct image_type_params *imagetool_get_type(int type)
 {
-	/*
-	 * Save the image tool callback function. It will be used to register
-	 * image types within that tool
-	 */
-	register_func = image_register;
+	struct image_type_params **curr;
+	INIT_SECTION(image_type);
 
-	/* Init ATMEL ROM Boot Image generation/list support */
-	init_atmel_image_type();
-	/* Init Freescale PBL Boot image generation/list support */
-	init_pbl_image_type();
-	/* Init Kirkwood Boot image generation/list support */
-	init_kwb_image_type();
-	/* Init Freescale imx Boot image generation/list support */
-	init_imx_image_type();
-	/* Init Freescale mxs Boot image generation/list support */
-	init_mxs_image_type();
-	/* Init FIT image generation/list support */
-	init_fit_image_type();
-	/* Init TI OMAP Boot image generation/list support */
-	init_omap_image_type();
-	/* Init Default image generation/list support */
-	init_default_image_type();
-	/* Init Davinci UBL support */
-	init_ubl_image_type();
-	/* Init Davinci AIS support */
-	init_ais_image_type();
-	/* Init Altera SOCFPGA support */
-	init_socfpga_image_type();
-	/* Init TI Keystone boot image generation/list support */
-	init_gpimage_type();
+	struct image_type_params **start = __start_image_type;
+	struct image_type_params **end = __stop_image_type;
+
+	for (curr = start; curr != end; curr++) {
+		if ((*curr)->check_image_type) {
+			if (!(*curr)->check_image_type(type))
+				return *curr;
+		}
+	}
+	return NULL;
 }
 
-/*
- * register_image_type -
- *
- * Register a image type within a tool
- */
-void register_image_type(struct image_type_params *tparams)
+int imagetool_verify_print_header(
+	void *ptr,
+	struct stat *sbuf,
+	struct image_type_params *tparams,
+	struct image_tool_params *params)
 {
-	register_func(tparams);
+	int retval = -1;
+	struct image_type_params **curr;
+	INIT_SECTION(image_type);
+
+	struct image_type_params **start = __start_image_type;
+	struct image_type_params **end = __stop_image_type;
+
+	for (curr = start; curr != end; curr++) {
+		if ((*curr)->verify_header) {
+			retval = (*curr)->verify_header((unsigned char *)ptr,
+						     sbuf->st_size, params);
+
+			if (retval == 0) {
+				/*
+				 * Print the image information  if verify is
+				 * successful
+				 */
+				if ((*curr)->print_header) {
+					(*curr)->print_header(ptr);
+				} else {
+					fprintf(stderr,
+						"%s: print_header undefined for %s\n",
+						params->cmdname, (*curr)->name);
+				}
+				break;
+			}
+		}
+	}
+
+	return retval;
+}
+
+int imagetool_save_subimage(
+	const char *file_name,
+	ulong file_data,
+	ulong file_len)
+{
+	int dfd;
+
+	dfd = open(file_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+		   S_IRUSR | S_IWUSR);
+	if (dfd < 0) {
+		fprintf(stderr, "Can't open \"%s\": %s\n",
+			file_name, strerror(errno));
+		return -1;
+	}
+
+	if (write(dfd, (void *)file_data, file_len) != (ssize_t)file_len) {
+		fprintf(stderr, "Write error on \"%s\": %s\n",
+			file_name, strerror(errno));
+		close(dfd);
+		return -1;
+	}
+
+	close(dfd);
+
+	return 0;
 }
diff --git a/tools/imagetool.h b/tools/imagetool.h
index 8bce059..3e15b4e 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -19,6 +19,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <u-boot/sha1.h>
+
 #include "fdt_host.h"
 
 #define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0]))
@@ -100,14 +101,15 @@
 	void (*set_header) (void *, struct stat *, int,
 					struct image_tool_params *);
 	/*
-	 * This function is used by the command to retrieve a data file from
-	 * the image (i.e. dumpimage -i <image> -p <position> <data_file>).
+	 * This function is used by the command to retrieve a component
+	 * (sub-image) from the image (i.e. dumpimage -i <image> -p <position>
+	 * <sub-image-name>).
 	 * Thus the code to extract a file from an image must be put here.
 	 *
 	 * Returns 0 if the file was successfully retrieved from the image,
 	 * or a negative value on error.
 	 */
-	int (*extract_datafile) (void *, struct image_tool_params *);
+	int (*extract_subimage)(void *, struct image_tool_params *);
 	/*
 	 * Some image generation support for ex (default image type) supports
 	 * more than one type_ids, this callback function is used to check
@@ -127,50 +129,131 @@
 	 */
 	int (*vrec_header) (struct image_tool_params *,
 		struct image_type_params *);
-	/* pointer to the next registered entry in linked list */
-	struct image_type_params *next;
 };
 
-/*
- * Tool registration function.
+/**
+ * imagetool_get_type() - find the image type params for a given image type
+ *
+ * It scans all registers image type supports
+ * checks the input type for each supported image type
+ *
+ * if successful,
+ *     returns respective image_type_params pointer if success
+ * if input type_id is not supported by any of image_type_support
+ *     returns NULL
  */
-typedef void (*imagetool_register_t)(struct image_type_params *);
+struct image_type_params *imagetool_get_type(int type);
 
 /*
- * Initializes all image types with the given registration callback
- * function.
- * An image tool uses this function to initialize all image types.
+ * imagetool_verify_print_header() - verifies the image header
+ *
+ * Scan registered image types and verify the image_header for each
+ * supported image type. If verification is successful, this prints
+ * the respective header.
+ *
+ * @return 0 on success, negative if input image format does not match with
+ * any of supported image types
  */
-void register_image_tool(imagetool_register_t image_register);
+int imagetool_verify_print_header(
+	void *ptr,
+	struct stat *sbuf,
+	struct image_type_params *tparams,
+	struct image_tool_params *params);
 
-/*
- * Register a image type within a tool.
- * An image type uses this function to register itself within
- * all tools.
+/**
+ * imagetool_save_subimage - store data into a file
+ * @file_name: name of the destination file
+ * @file_data: data to be written
+ * @file_len: the amount of data to store
+ *
+ * imagetool_save_subimage() store file_len bytes of data pointed by file_data
+ * into the file name by file_name.
+ *
+ * returns:
+ *     zero in case of success or a negative value if fail.
  */
-void register_image_type(struct image_type_params *tparams);
+int imagetool_save_subimage(
+	const char *file_name,
+	ulong file_data,
+	ulong file_len);
 
 /*
  * There is a c file associated with supported image type low level code
  * for ex. default_image.c, fit_image.c
- * init_xxx_type() is the only function referred by image tool core to avoid
- * a single lined header file, you can define them here
- *
- * Supported image types init functions
  */
-void init_default_image_type(void);
-void init_atmel_image_type(void);
-void init_pbl_image_type(void);
-void init_ais_image_type(void);
-void init_kwb_image_type(void);
-void init_imx_image_type(void);
-void init_mxs_image_type(void);
-void init_fit_image_type(void);
-void init_ubl_image_type(void);
-void init_omap_image_type(void);
-void init_socfpga_image_type(void);
-void init_gpimage_type(void);
+
 
 void pbl_load_uboot(int fd, struct image_tool_params *mparams);
 
+#define ___cat(a, b) a ## b
+#define __cat(a, b) ___cat(a, b)
+
+/* we need some special handling for this host tool running eventually on
+ * Darwin. The Mach-O section handling is a bit different than ELF section
+ * handling. The differnces in detail are:
+ *  a) we have segments which have sections
+ *  b) we need a API call to get the respective section symbols */
+#if defined(__MACH__)
+#include <mach-o/getsect.h>
+
+#define INIT_SECTION(name)  do {					\
+		unsigned long name ## _len;				\
+		char *__cat(pstart_, name) = getsectdata("__TEXT",	\
+			#name, &__cat(name, _len));			\
+		char *__cat(pstop_, name) = __cat(pstart_, name) +	\
+			__cat(name, _len);				\
+		__cat(__start_, name) = (void *)__cat(pstart_, name);	\
+		__cat(__stop_, name) = (void *)__cat(pstop_, name);	\
+	} while (0)
+#define SECTION(name)   __attribute__((section("__TEXT, " #name)))
+
+struct image_type_params **__start_image_type, **__stop_image_type;
+#else
+#define INIT_SECTION(name) /* no-op for ELF */
+#define SECTION(name)   __attribute__((section(#name)))
+
+/* We construct a table of pointers in an ELF section (pointers generally
+ * go unpadded by gcc).  ld creates boundary syms for us. */
+extern struct image_type_params *__start_image_type[], *__stop_image_type[];
+#endif /* __MACH__ */
+
+#if !defined(__used)
+# if __GNUC__ == 3 && __GNUC_MINOR__ < 3
+#  define __used			__attribute__((__unused__))
+# else
+#  define __used			__attribute__((__used__))
+# endif
+#endif
+
+#define U_BOOT_IMAGE_TYPE( \
+		_id, \
+		_name, \
+		_header_size, \
+		_header, \
+		_check_params, \
+		_verify_header, \
+		_print_header, \
+		_set_header, \
+		_extract_subimage, \
+		_check_image_type, \
+		_fflag_handle, \
+		_vrec_header \
+	) \
+	static struct image_type_params __cat(image_type_, _id) = \
+	{ \
+		.name = _name, \
+		.header_size = _header_size, \
+		.hdr = _header, \
+		.check_params = _check_params, \
+		.verify_header = _verify_header, \
+		.print_header = _print_header, \
+		.set_header = _set_header, \
+		.extract_subimage = _extract_subimage, \
+		.check_image_type = _check_image_type, \
+		.fflag_handle = _fflag_handle, \
+		.vrec_header = _vrec_header \
+	}; \
+	static struct image_type_params *SECTION(image_type) __used \
+		__cat(image_type_ptr_, _id) = &__cat(image_type_, _id)
+
 #endif /* _IMAGETOOL_H_ */
diff --git a/tools/imximage.c b/tools/imximage.c
index 526b7d4..6f469ae 100644
--- a/tools/imximage.c
+++ b/tools/imximage.c
@@ -38,6 +38,7 @@
 	{FLASH_OFFSET_SATA,	"sata",		"SATA Disk",	},
 	{FLASH_OFFSET_SD,	"sd",		"SD Card",	},
 	{FLASH_OFFSET_SPI,	"spi",		"SPI Flash",	},
+	{FLASH_OFFSET_QSPI,	"qspi",		"QSPI NOR Flash",},
 	{-1,			"",		"Invalid",	},
 };
 
@@ -52,6 +53,7 @@
 	{FLASH_LOADSIZE_SATA,		"sata",		"SATA Disk",	},
 	{FLASH_LOADSIZE_SD,		"sd",		"SD Card",	},
 	{FLASH_LOADSIZE_SPI,		"spi",		"SPI Flash",	},
+	{FLASH_LOADSIZE_QSPI,		"qspi",		"QSPI NOR Flash",},
 	{-1,				"",		"Invalid",	},
 };
 
@@ -694,19 +696,17 @@
 /*
  * imximage parameters
  */
-static struct image_type_params imximage_params = {
-	.name		= "Freescale i.MX Boot Image support",
-	.header_size	= 0,
-	.hdr		= NULL,
-	.check_image_type = imximage_check_image_types,
-	.verify_header	= imximage_verify_header,
-	.print_header	= imximage_print_header,
-	.set_header	= imximage_set_header,
-	.check_params	= imximage_check_params,
-	.vrec_header	= imximage_generate,
-};
-
-void init_imx_image_type(void)
-{
-	register_image_type(&imximage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	imximage,
+	"Freescale i.MX Boot Image support",
+	0,
+	NULL,
+	imximage_check_params,
+	imximage_verify_header,
+	imximage_print_header,
+	imximage_set_header,
+	NULL,
+	imximage_check_image_types,
+	NULL,
+	imximage_generate
+);
diff --git a/tools/imximage.h b/tools/imximage.h
index 5b5ad0e..36fe095 100644
--- a/tools/imximage.h
+++ b/tools/imximage.h
@@ -29,6 +29,7 @@
 #define FLASH_OFFSET_ONENAND	0x100
 #define FLASH_OFFSET_NOR	0x1000
 #define FLASH_OFFSET_SATA	FLASH_OFFSET_STANDARD
+#define FLASH_OFFSET_QSPI	0x1000
 
 /* Initial Load Region Size */
 #define FLASH_LOADSIZE_UNDEFINED	0xFFFFFFFF
@@ -39,6 +40,7 @@
 #define FLASH_LOADSIZE_ONENAND		0x400
 #define FLASH_LOADSIZE_NOR		0x0 /* entire image */
 #define FLASH_LOADSIZE_SATA		FLASH_LOADSIZE_STANDARD
+#define FLASH_LOADSIZE_QSPI		0x0 /* entire image */
 
 #define IVT_HEADER_TAG 0xD1
 #define IVT_VERSION 0x40
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 807d466..de5c808 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -868,6 +868,16 @@
 			sizeof(struct ext_hdr_v0);
 	} else {
 		alloc_len = image_headersz_v1(params, NULL);
+#if defined(CONFIG_SYS_SPI_U_BOOT_OFFS)
+		if (alloc_len > CONFIG_SYS_SPI_U_BOOT_OFFS) {
+			fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
+			fprintf(stderr, "header=0x%x CONFIG_SYS_SPI_U_BOOT_OFFS=0x%x!\n",
+				alloc_len, CONFIG_SYS_SPI_U_BOOT_OFFS);
+			fprintf(stderr, "Increase CONFIG_SYS_SPI_U_BOOT_OFFS!\n");
+		} else {
+			alloc_len = CONFIG_SYS_SPI_U_BOOT_OFFS;
+		}
+#endif
 	}
 
 	hdr = malloc(alloc_len);
@@ -905,19 +915,17 @@
 /*
  * kwbimage type parameters definition
  */
-static struct image_type_params kwbimage_params = {
-	.name		= "Marvell MVEBU Boot Image support",
-	.header_size	= 0,		/* no fixed header size */
-	.hdr		= NULL,
-	.vrec_header	= kwbimage_generate,
-	.check_image_type = kwbimage_check_image_types,
-	.verify_header	= kwbimage_verify_header,
-	.print_header	= kwbimage_print_header,
-	.set_header	= kwbimage_set_header,
-	.check_params	= kwbimage_check_params,
-};
-
-void init_kwb_image_type (void)
-{
-	register_image_type(&kwbimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	kwbimage,
+	"Marvell MVEBU Boot Image support",
+	0,
+	NULL,
+	kwbimage_check_params,
+	kwbimage_verify_header,
+	kwbimage_print_header,
+	kwbimage_set_header,
+	NULL,
+	kwbimage_check_image_types,
+	NULL,
+	kwbimage_generate
+);
diff --git a/tools/logos/compulab.bmp b/tools/logos/compulab.bmp
new file mode 100644
index 0000000..df5435c
--- /dev/null
+++ b/tools/logos/compulab.bmp
Binary files differ
diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py
index 003716d..71c2e91 100755
--- a/tools/microcode-tool.py
+++ b/tools/microcode-tool.py
@@ -76,6 +76,35 @@
         microcodes[name] = Microcode(name, data)
     return date, license_text, microcodes
 
+def ParseHeaderFiles(fname_list):
+    """Parse a list of header files and return the component parts
+
+    Args:
+        fname_list: List of files to parse
+    Returns:
+            date:         String containing date from the file's header
+            license_text: List of text lines for the license file
+            microcodes:   List of Microcode objects from the file
+    """
+    microcodes = {}
+    license_text = []
+    date = ''
+    name = None
+    for fname in fname_list:
+        name = os.path.basename(fname).lower()
+        name = os.path.splitext(name)[0]
+        data = []
+        with open(fname) as fd:
+            for line in fd:
+                line = line.rstrip()
+
+                # Omit anything after the last comma
+                words = line.split(',')[:-1]
+                data += [word + ',' for word in words]
+        microcodes[name] = Microcode(name, data)
+    return date, license_text, microcodes
+
+
 def List(date, microcodes, model):
     """List the available microcode chunks
 
@@ -129,13 +158,13 @@
             break
     return found, tried
 
-def CreateFile(date, license_text, mcode, outfile):
+def CreateFile(date, license_text, mcodes, outfile):
     """Create a microcode file in U-Boot's .dtsi format
 
     Args:
         date:       String containing date of original microcode file
         license:    List of text lines for the license file
-        mcode:      Microcode object to write
+        mcodes:      Microcode objects to write (normally only 1)
         outfile:    Filename to write to ('-' for stdout)
     """
     out = '''/*%s
@@ -159,15 +188,22 @@
 data = <%s
 \t>;'''
     words = ''
-    for i in range(len(mcode.words)):
-        if not (i & 3):
-            words += '\n'
-        val = mcode.words[i]
-        # Change each word so it will be little-endian in the FDT
-        # This data is needed before RAM is available on some platforms so we
-        # cannot do an endianness swap on boot.
-        val = struct.unpack("<I", struct.pack(">I", val))[0]
-        words += '\t%#010x' % val
+    add_comments = len(mcodes) > 1
+    for mcode in mcodes:
+        if add_comments:
+            words += '\n/* %s */' % mcode.name
+        for i in range(len(mcode.words)):
+            if not (i & 3):
+                words += '\n'
+            val = mcode.words[i]
+            # Change each word so it will be little-endian in the FDT
+            # This data is needed before RAM is available on some platforms so
+            # we cannot do an endianness swap on boot.
+            val = struct.unpack("<I", struct.pack(">I", val))[0]
+            words += '\t%#010x' % val
+
+    # Use the first microcode for the headers
+    mcode = mcodes[0]
 
     # Take care to avoid adding a space before a tab
     text = ''
@@ -187,8 +223,8 @@
                 print >> sys.stderr, "Creating directory '%s'" % MICROCODE_DIR
                 os.makedirs(MICROCODE_DIR)
             outfile = os.path.join(MICROCODE_DIR, mcode.name + '.dtsi')
-            print >> sys.stderr, "Writing microcode for '%s' to '%s'" % (
-                     mcode.name, outfile)
+        print >> sys.stderr, "Writing microcode for '%s' to '%s'" % (
+                ', '.join([mcode.name for mcode in mcodes]), outfile)
         with open(outfile, 'w') as fd:
             print >> fd, out % tuple(args)
 
@@ -198,8 +234,12 @@
     parser = OptionParser()
     parser.add_option('-d', '--mcfile', type='string', action='store',
                     help='Name of microcode.dat file')
+    parser.add_option('-H', '--headerfile', type='string', action='append',
+                    help='Name of .h file containing microcode')
     parser.add_option('-m', '--model', type='string', action='store',
-                    help='Model name to extract')
+                    help="Model name to extract ('all' for all)")
+    parser.add_option('-M', '--multiple', type='string', action='store',
+                    help="Allow output of multiple models")
     parser.add_option('-o', '--outfile', type='string', action='store',
                     help='Filename to use for output (- for stdout), default is'
                     ' %s/<name>.dtsi' % MICROCODE_DIR)
@@ -224,9 +264,14 @@
     if cmd not in commands:
         parser.error("Unknown command '%s'" % cmd)
 
-    if not options.mcfile:
-        parser.error('You must specify a microcode file')
-    date, license_text, microcodes = ParseFile(options.mcfile)
+    if (not not options.mcfile) != (not not options.mcfile):
+        parser.error("You must specify either header files or a microcode file, not both")
+    if options.headerfile:
+        date, license_text, microcodes = ParseHeaderFiles(options.headerfile)
+    elif options.mcfile:
+        date, license_text, microcodes = ParseFile(options.mcfile)
+    else:
+        parser.error('You must specify a microcode file (or header files)')
 
     if cmd == 'list':
         List(date, microcodes, options.model)
@@ -236,16 +281,21 @@
         if not options.model:
             parser.error('You must specify a model to create')
         model = options.model.lower()
-        mcode_list, tried = FindMicrocode(microcodes, model)
+        if options.model == 'all':
+            options.multiple = True
+            mcode_list = microcodes.values()
+            tried = []
+        else:
+            mcode_list, tried = FindMicrocode(microcodes, model)
         if not mcode_list:
             parser.error("Unknown model '%s' (%s) - try 'list' to list" %
                         (model, ', '.join(tried)))
-        if len(mcode_list) > 1:
+        if not options.multiple and len(mcode_list) > 1:
             parser.error("Ambiguous model '%s' (%s) matched %s - try 'list' "
                         "to list or specify a particular file" %
                         (model, ', '.join(tried),
                         ', '.join([m.name for m in mcode_list])))
-        CreateFile(date, license_text, mcode_list[0], options.outfile)
+        CreateFile(date, license_text, mcode_list, options.outfile)
     else:
         parser.error("Unknown command '%s'" % cmd)
 
diff --git a/tools/mkimage.c b/tools/mkimage.c
index c70408c..5ccd951 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -15,9 +15,6 @@
 static void copy_file(int, const char *, int);
 static void usage(void);
 
-/* image_type_params link list to maintain registered image type supports */
-struct image_type_params *mkimage_tparams = NULL;
-
 /* parameters initialized by core will be used by the image type code */
 struct image_tool_params params = {
 	.os = IH_OS_LINUX,
@@ -29,106 +26,6 @@
 	.imagename2 = "",
 };
 
-/*
- * mkimage_register -
- *
- * It is used to register respective image generation/list support to the
- * mkimage core
- *
- * the input struct image_type_params is checked and appended to the link
- * list, if the input structure is already registered, error
- */
-void mkimage_register (struct image_type_params *tparams)
-{
-	struct image_type_params **tp;
-
-	if (!tparams) {
-		fprintf (stderr, "%s: %s: Null input\n",
-			params.cmdname, __FUNCTION__);
-		exit (EXIT_FAILURE);
-	}
-
-	/* scan the linked list, check for registry and point the last one */
-	for (tp = &mkimage_tparams; *tp != NULL; tp = &(*tp)->next) {
-		if (!strcmp((*tp)->name, tparams->name)) {
-			fprintf (stderr, "%s: %s already registered\n",
-				params.cmdname, tparams->name);
-			return;
-		}
-	}
-
-	/* add input struct entry at the end of link list */
-	*tp = tparams;
-	/* mark input entry as last entry in the link list */
-	tparams->next = NULL;
-
-	debug ("Registered %s\n", tparams->name);
-}
-
-/*
- * mkimage_get_type -
- *
- * It scans all registers image type supports
- * checks the input type_id for each supported image type
- *
- * if successful,
- * 	returns respective image_type_params pointer if success
- * if input type_id is not supported by any of image_type_support
- * 	returns NULL
- */
-struct image_type_params *mkimage_get_type(int type)
-{
-	struct image_type_params *curr;
-
-	for (curr = mkimage_tparams; curr != NULL; curr = curr->next) {
-		if (curr->check_image_type) {
-			if (!curr->check_image_type (type))
-				return curr;
-		}
-	}
-	return NULL;
-}
-
-/*
- * mkimage_verify_print_header -
- *
- * It scans mkimage_tparams link list,
- * verifies image_header for each supported image type
- * if verification is successful, prints respective header
- *
- * returns negative if input image format does not match with any of
- * supported image types
- */
-int mkimage_verify_print_header (void *ptr, struct stat *sbuf)
-{
-	int retval = -1;
-	struct image_type_params *curr;
-
-	for (curr = mkimage_tparams; curr != NULL; curr = curr->next ) {
-		if (curr->verify_header) {
-			retval = curr->verify_header (
-				(unsigned char *)ptr, sbuf->st_size,
-				&params);
-
-			if (retval == 0) {
-				/*
-				 * Print the image information
-				 * if verify is successful
-				 */
-				if (curr->print_header)
-					curr->print_header (ptr);
-				else {
-					fprintf (stderr,
-					"%s: print_header undefined for %s\n",
-					params.cmdname, curr->name);
-				}
-				break;
-			}
-		}
-	}
-	return retval;
-}
-
 int
 main (int argc, char **argv)
 {
@@ -139,9 +36,6 @@
 	struct image_type_params *tparams = NULL;
 	int pad_len = 0;
 
-	/* Init all image generation/list support */
-	register_image_tool(mkimage_register);
-
 	params.cmdname = *argv;
 	params.addr = params.ep = 0;
 
@@ -279,7 +173,7 @@
 		usage ();
 
 	/* set tparams as per input type_id */
-	tparams = mkimage_get_type(params.type);
+	tparams = imagetool_get_type(params.type);
 	if (tparams == NULL) {
 		fprintf (stderr, "%s: unsupported type %s\n",
 			params.cmdname, genimg_get_type_name(params.type));
@@ -363,7 +257,8 @@
 		 * Print the image information for matched image type
 		 * Returns the error code if not matched
 		 */
-		retval = mkimage_verify_print_header (ptr, &sbuf);
+		retval = imagetool_verify_print_header(ptr, &sbuf,
+				tparams, &params);
 
 		(void) munmap((void *)ptr, sbuf.st_size);
 		(void) close (ifd);
@@ -529,7 +424,7 @@
 	uint8_t zeros[4096];
 	int offset = 0;
 	int size;
-	struct image_type_params *tparams = mkimage_get_type (params.type);
+	struct image_type_params *tparams = imagetool_get_type(params.type);
 
 	if (pad >= sizeof(zeros)) {
 		fprintf(stderr, "%s: Can't pad to %d\n",
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c
index 1f0fbae..0035f6e 100644
--- a/tools/mksunxiboot.c
+++ b/tools/mksunxiboot.c
@@ -43,19 +43,19 @@
 	uint32_t i;
 	uint32_t sum;
 
-	length = head_p->length;
+	length = le32_to_cpu(head_p->length);
 	if ((length & 0x3) != 0)	/* must 4-byte-aligned */
 		return -1;
 	buf = (uint32_t *)head_p;
-	head_p->check_sum = STAMP_VALUE;	/* fill stamp */
+	head_p->check_sum = cpu_to_le32(STAMP_VALUE);	/* fill stamp */
 	loop = length >> 2;
 
 	/* calculate the sum */
 	for (i = 0, sum = 0; i < loop; i++)
-		sum += buf[i];
+		sum += le32_to_cpu(buf[i]);
 
 	/* write back check sum */
-	head_p->check_sum = sum;
+	head_p->check_sum = cpu_to_le32(sum);
 
 	return 0;
 }
@@ -125,10 +125,12 @@
 	memcpy(img.header.magic, BOOT0_MAGIC, 8);	/* no '0' termination */
 	img.header.length =
 		ALIGN(file_size + sizeof(struct boot_file_head), BLOCK_SIZE);
+	img.header.b_instruction = cpu_to_le32(img.header.b_instruction);
+	img.header.length = cpu_to_le32(img.header.length);
 	gen_check_sum(&img.header);
 
-	count = write(fd_out, &img, img.header.length);
-	if (count != img.header.length) {
+	count = write(fd_out, &img, le32_to_cpu(img.header.length));
+	if (count != le32_to_cpu(img.header.length)) {
 		perror("Writing output");
 		return EXIT_FAILURE;
 	}
diff --git a/tools/mxsboot.c b/tools/mxsboot.c
index 90b2173..6d48cfb 100644
--- a/tools/mxsboot.c
+++ b/tools/mxsboot.c
@@ -142,6 +142,9 @@
 
 		if (page_oob_size == 218)
 			return 16;
+
+		if (page_oob_size == 224)
+			return 16;
 	}
 
 	return 0;
@@ -269,6 +272,9 @@
 		} else if (nand_oobsize == 218) {
 			fcb->ecc_block_n_ecc_type =	8;
 			fcb->ecc_block_0_ecc_type =	8;
+		} else if (nand_oobsize == 224) {
+			fcb->ecc_block_n_ecc_type =	8;
+			fcb->ecc_block_0_ecc_type =	8;
 		}
 	}
 
diff --git a/tools/mxsimage.c b/tools/mxsimage.c
index 04beefe..98fc644 100644
--- a/tools/mxsimage.c
+++ b/tools/mxsimage.c
@@ -2312,25 +2312,18 @@
 /*
  * mxsimage parameters
  */
-static struct image_type_params mxsimage_params = {
-	.name		= "Freescale MXS Boot Image support",
-	.header_size	= 0,
-	.hdr		= NULL,
-	.check_image_type = mxsimage_check_image_types,
-	.verify_header	= mxsimage_verify_header,
-	.print_header	= mxsimage_print_header,
-	.set_header	= mxsimage_set_header,
-	.check_params	= mxsimage_check_params,
-	.vrec_header	= mxsimage_generate,
-};
-
-void init_mxs_image_type(void)
-{
-	register_image_type(&mxsimage_params);
-}
-
-#else
-void init_mxs_image_type(void)
-{
-}
+U_BOOT_IMAGE_TYPE(
+	mxsimage,
+	"Freescale MXS Boot Image support",
+	0,
+	NULL,
+	mxsimage_check_params,
+	mxsimage_verify_header,
+	mxsimage_print_header,
+	mxsimage_set_header,
+	NULL,
+	mxsimage_check_image_types,
+	NULL,
+	mxsimage_generate
+);
 #endif
diff --git a/tools/omapimage.c b/tools/omapimage.c
index 1e0c164..7198b33 100644
--- a/tools/omapimage.c
+++ b/tools/omapimage.c
@@ -162,18 +162,17 @@
 /*
  * omapimage parameters
  */
-static struct image_type_params omapimage_params = {
-	.name		= "TI OMAP CH/GP Boot Image support",
-	.header_size	= OMAP_FILE_HDR_SIZE,
-	.hdr		= (void *)&omapimage_header,
-	.check_image_type = omapimage_check_image_types,
-	.verify_header	= omapimage_verify_header,
-	.print_header	= omapimage_print_header,
-	.set_header	= omapimage_set_header,
-	.check_params	= gpimage_check_params,
-};
-
-void init_omap_image_type(void)
-{
-	register_image_type(&omapimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	omapimage,
+	"TI OMAP CH/GP Boot Image support",
+	OMAP_FILE_HDR_SIZE,
+	(void *)&omapimage_header,
+	gpimage_check_params,
+	omapimage_verify_header,
+	omapimage_print_header,
+	omapimage_set_header,
+	NULL,
+	omapimage_check_image_types,
+	NULL,
+	NULL
+);
diff --git a/tools/patman/README b/tools/patman/README
index e466886..7d039e8 100644
--- a/tools/patman/README
+++ b/tools/patman/README
@@ -52,12 +52,15 @@
 How to configure it
 ===================
 
-For most cases of using patman for U-Boot development, patman will
-locate and use the file 'doc/git-mailrc' in your U-Boot directory.
-This contains most of the aliases you will need.
+For most cases of using patman for U-Boot development, patman can use the
+file 'doc/git-mailrc' in your U-Boot directory to supply the email aliases
+you need. To make this work, tell git where to find the file by typing
+this once:
 
-For Linux the 'scripts/get_maintainer.pl' handles figuring out where
-to send patches pretty well.
+    git config sendemail.aliasesfile doc/git-mailrc
+
+For both Linux and U-Boot the 'scripts/get_maintainer.pl' handles figuring
+out where to send patches pretty well.
 
 During the first run patman creates a config file for you by taking the default
 user name and email address from the global .gitconfig file.
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index cc5a55a..4c2c35b 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -129,7 +129,7 @@
         return upstream, msg
 
     if remote == '.':
-        return merge
+        return merge, None
     elif remote and merge:
         leaf = merge.split('/')[-1]
         return '%s/%s' % (remote, leaf), None
@@ -392,7 +392,8 @@
                    "Or do something like this\n"
                    "git config sendemail.to u-boot@lists.denx.de")
             return
-    cc = BuildEmailList(series.get('cc'), '--cc', alias, raise_on_error)
+    cc = BuildEmailList(list(set(series.get('cc')) - set(series.get('to'))),
+                        '--cc', alias, raise_on_error)
     if self_only:
         to = BuildEmailList([os.getenv('USER')], '--to', alias, raise_on_error)
         cc = []
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index da04883..8c3a0ec 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -139,6 +139,9 @@
         # Initially we have no output. Prepare the input line string
         out = []
         line = line.rstrip('\n')
+
+        commit_match = re_commit.match(line) if self.is_log else None
+
         if self.is_log:
             if line[:4] == '    ':
                 line = line[4:]
@@ -146,7 +149,6 @@
         # Handle state transition and skipping blank lines
         series_tag_match = re_series_tag.match(line)
         commit_tag_match = re_commit_tag.match(line)
-        commit_match = re_commit.match(line) if self.is_log else None
         cover_cc_match = re_cover_cc.match(line)
         signoff_match = re_signoff.match(line)
         tag_match = None
diff --git a/tools/patman/series.py b/tools/patman/series.py
index b67f870..60ebc76 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -94,6 +94,9 @@
             cmd: The git command we would have run
             process_tags: Process tags as if they were aliases
         """
+        to_set = set(gitutil.BuildEmailList(self.to));
+        cc_set = set(gitutil.BuildEmailList(self.cc));
+
         col = terminal.Color()
         print 'Dry run, so not doing much. But I would do this:'
         print
@@ -106,24 +109,16 @@
             commit = self.commits[upto]
             print col.Color(col.GREEN, '   %s' % args[upto])
             cc_list = list(self._generated_cc[commit.patch])
-
-            # Skip items in To list
-            if 'to' in self:
-                try:
-                    map(cc_list.remove, gitutil.BuildEmailList(self.to))
-                except ValueError:
-                    pass
-
-            for email in cc_list:
+            for email in set(cc_list) - to_set - cc_set:
                 if email == None:
                     email = col.Color(col.YELLOW, "<alias '%s' not found>"
                             % tag)
                 if email:
                     print '      Cc: ',email
         print
-        for item in gitutil.BuildEmailList(self.get('to', '<none>')):
+        for item in to_set:
             print 'To:\t ', item
-        for item in gitutil.BuildEmailList(self.cc):
+        for item in cc_set - to_set:
             print 'Cc:\t ', item
         print 'Version: ', self.get('version')
         print 'Prefix:\t ', self.get('prefix')
@@ -131,7 +126,7 @@
             print 'Cover: %d lines' % len(self.cover)
             cover_cc = gitutil.BuildEmailList(self.get('cover_cc', ''))
             all_ccs = itertools.chain(cover_cc, *self._generated_cc.values())
-            for email in set(all_ccs):
+            for email in set(all_ccs) - to_set - cc_set:
                     print '      Cc: ',email
         if cmd:
             print 'Git command: %s' % cmd
@@ -230,7 +225,7 @@
 	    if add_maintainers:
                 list += get_maintainer.GetMaintainer(commit.patch)
             all_ccs += list
-            print >>fd, commit.patch, ', '.join(list)
+            print >>fd, commit.patch, ', '.join(set(list))
             self._generated_cc[commit.patch] = list
 
         if cover_fname:
diff --git a/tools/patman/settings.py b/tools/patman/settings.py
index 122e8fd..ba2a68f 100644
--- a/tools/patman/settings.py
+++ b/tools/patman/settings.py
@@ -235,6 +235,31 @@
         else:
             print "WARNING: Unknown setting %s" % name
 
+def _ReadAliasFile(fname):
+    """Read in the U-Boot git alias file if it exists.
+
+    Args:
+        fname: Filename to read.
+    """
+    if os.path.exists(fname):
+        bad_line = None
+        with open(fname) as fd:
+            linenum = 0
+            for line in fd:
+                linenum += 1
+                line = line.strip()
+                if not line or line.startswith('#'):
+                    continue
+                words = line.split(' ', 2)
+                if len(words) < 3 or words[0] != 'alias':
+                    if not bad_line:
+                        bad_line = "%s:%d:Invalid line '%s'" % (fname, linenum,
+                                                                line)
+                    continue
+                alias[words[1]] = [s.strip() for s in words[2].split(',')]
+        if bad_line:
+            print bad_line
+
 def Setup(parser, project_name, config_fname=''):
     """Set up the settings module by reading config files.
 
@@ -244,6 +269,8 @@
             for sections named "project_section" as well.
         config_fname:   Config filename to read ('' for default)
     """
+    # First read the git alias file if available
+    _ReadAliasFile('doc/git-mailrc')
     config = _ProjectConfigParser(project_name)
     if config_fname == '':
         config_fname = '%s/.patman' % os.getenv('HOME')
diff --git a/tools/pblimage.c b/tools/pblimage.c
index 2a799ab..d74fde9 100644
--- a/tools/pblimage.c
+++ b/tools/pblimage.c
@@ -308,19 +308,17 @@
 };
 
 /* pblimage parameters */
-static struct image_type_params pblimage_params = {
-	.name		= "Freescale PBL Boot Image support",
-	.header_size	= sizeof(struct pbl_header),
-	.hdr		= (void *)&pblimage_header,
-	.check_image_type = pblimage_check_image_types,
-	.check_params	= pblimage_check_params,
-	.verify_header	= pblimage_verify_header,
-	.print_header	= pblimage_print_header,
-	.set_header	= pblimage_set_header,
-};
-
-void init_pbl_image_type(void)
-{
-	pbl_size = 0;
-	register_image_type(&pblimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	pblimage,
+	"Freescale PBL Boot Image support",
+	sizeof(struct pbl_header),
+	(void *)&pblimage_header,
+	pblimage_check_params,
+	pblimage_verify_header,
+	pblimage_print_header,
+	pblimage_set_header,
+	NULL,
+	pblimage_check_image_types,
+	NULL,
+	NULL
+);
diff --git a/tools/socfpgaimage.c b/tools/socfpgaimage.c
index 917873e..8fe91fe 100644
--- a/tools/socfpgaimage.c
+++ b/tools/socfpgaimage.c
@@ -33,6 +33,8 @@
 
 #include "pbl_crc32.h"
 #include "imagetool.h"
+#include "mkimage.h"
+
 #include <image.h>
 
 #define HEADER_OFFSET	0x40
@@ -133,12 +135,12 @@
 
 	len = verify_header(buf + HEADER_OFFSET);
 	if (len < 0) {
-		fprintf(stderr, "Invalid header\n");
+		debug("Invalid header\n");
 		return -1;
 	}
 
 	if (len < HEADER_OFFSET || len > PADDED_SIZE) {
-		fprintf(stderr, "Invalid header length (%i)\n", len);
+		debug("Invalid header length (%i)\n", len);
 		return -1;
 	}
 
@@ -241,19 +243,17 @@
 	sign_buffer(buf, 0, 0, data_size, 0);
 }
 
-static struct image_type_params socfpgaimage_params = {
-	.name		= "Altera SOCFPGA preloader support",
-	.vrec_header	= socfpgaimage_vrec_header,
-	.header_size	= 0, /* This will be modified by vrec_header() */
-	.hdr		= (void *)buffer,
-	.check_image_type = socfpgaimage_check_image_types,
-	.verify_header	= socfpgaimage_verify_header,
-	.print_header	= socfpgaimage_print_header,
-	.set_header	= socfpgaimage_set_header,
-	.check_params	= socfpgaimage_check_params,
-};
-
-void init_socfpga_image_type(void)
-{
-	register_image_type(&socfpgaimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	socfpgaimage,
+	"Altera SOCFPGA preloader support",
+	0, /* This will be modified by vrec_header() */
+	(void *)buffer,
+	socfpgaimage_check_params,
+	socfpgaimage_verify_header,
+	socfpgaimage_print_header,
+	socfpgaimage_set_header,
+	NULL,
+	socfpgaimage_check_image_types,
+	NULL,
+	socfpgaimage_vrec_header
+);
diff --git a/tools/ublimage.c b/tools/ublimage.c
index cbbbe20..6ed1eef 100644
--- a/tools/ublimage.c
+++ b/tools/ublimage.c
@@ -244,18 +244,17 @@
 /*
  * ublimage parameters
  */
-static struct image_type_params ublimage_params = {
-	.name		= "Davinci UBL boot support",
-	.header_size	= sizeof(struct ubl_header),
-	.hdr		= (void *)&ublimage_header,
-	.check_image_type = ublimage_check_image_types,
-	.verify_header	= ublimage_verify_header,
-	.print_header	= ublimage_print_header,
-	.set_header	= ublimage_set_header,
-	.check_params	= ublimage_check_params,
-};
-
-void init_ubl_image_type(void)
-{
-	register_image_type(&ublimage_params);
-}
+U_BOOT_IMAGE_TYPE(
+	ublimage,
+	"Davinci UBL boot support",
+	sizeof(struct ubl_header),
+	(void *)&ublimage_header,
+	ublimage_check_params,
+	ublimage_verify_header,
+	ublimage_print_header,
+	ublimage_set_header,
+	NULL,
+	ublimage_check_image_types,
+	NULL,
+	NULL
+);