diff --git a/Kconfig b/Kconfig
index 286d1c7afcfaf07ef3e99534f480508c84bcf259..14740b49f1ddbd00530292b13f7d0ad027039949 100644
--- a/Kconfig
+++ b/Kconfig
@@ -96,7 +96,17 @@ config SYS_MALLOC_F_LEN
 	  initial serial device and any others that are needed.
 
 config SPL_SYS_MALLOC_F_LEN
-        hex "Size of malloc() pool in spl before relocation"
+        hex "Size of malloc() pool in SPL before relocation"
+        depends on SYS_MALLOC_F
+        default SYS_MALLOC_F_LEN
+        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 TPL_SYS_MALLOC_F_LEN
+        hex "Size of malloc() pool in TPL before relocation"
         depends on SYS_MALLOC_F
         default SYS_MALLOC_F_LEN
         help
diff --git a/Makefile b/Makefile
index 50a002e72f1c7756d86a8236243611787feb2758..e1b0b13456bf95acca992065f5c5cbafb9ce15e3 100644
--- a/Makefile
+++ b/Makefile
@@ -1400,7 +1400,8 @@ u-boot.lds: $(LDSCRIPT) prepare FORCE
 spl/u-boot-spl.bin: spl/u-boot-spl
 	@:
 spl/u-boot-spl: tools prepare \
-		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb)
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \
+		$(if $(CONFIG_OF_SEPARATE)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
 	$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
 
 spl/sunxi-spl.bin: spl/u-boot-spl
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 61d8d31ee2e3e7c4002b8b2f1e029a6f15766827..39b001fd531fb21f9cdbdce838fdb6ec13ac5bfc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -618,6 +618,11 @@ config ARCH_MX6
 	select SYS_FSL_SEC_LE
 	select SYS_THUMB_BUILD if SPL
 
+if ARCH_MX6
+config SPL_LDSCRIPT
+        default "arch/arm/mach-omap2/u-boot-spl.lds"
+endif
+
 config ARCH_MX5
 	bool "Freescale MX5"
 	select CPU_V7
@@ -1233,3 +1238,10 @@ source "board/zipitz2/Kconfig"
 source "arch/arm/Kconfig.debug"
 
 endmenu
+
+config SPL_LDSCRIPT
+        default "arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds" if TARGET_APX4DEVKIT || TARGET_BG0900 || TARGET_M28EVK || TARGET_MX23_OLINUXINO || TARGET_MX23EVK || TARGET_MX28EVK || TARGET_SANSA_FUZE_PLUS || TARGET_SC_SPS_1 || TARGET_TS4600 || TARGET_XFI3
+        default "arch/arm/cpu/arm1136/u-boot-spl.lds" if CPU_ARM1136
+	default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64
+
+
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index c447085fe4317cbedcbd853db2673b4a85ef5d2c..12495474360b6508584a606475e49392803c521c 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -8,7 +8,9 @@
 extra-y	:= start.o
 
 obj-y	+= cpu.o
+ifndef CONFIG_$(SPL_TPL_)TIMER
 obj-y	+= generic_timer.o
+endif
 obj-y	+= cache_v8.o
 obj-y	+= exceptions.o
 obj-y	+= cache.o
diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index 7cba308ee7a2806cfe2fa3a88a3cafa12ba7e405..ea845d1809e0944d30620756d792a8c73ed3a014 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -22,6 +22,7 @@
  * x1: 0 clean & invalidate, 1 invalidate only
  * x2~x9: clobbered
  */
+.pushsection .text.__asm_dcache_level, "ax"
 ENTRY(__asm_dcache_level)
 	lsl	x12, x0, #1
 	msr	csselr_el1, x12		/* select cache level */
@@ -58,6 +59,7 @@ loop_way:
 
 	ret
 ENDPROC(__asm_dcache_level)
+.popsection
 
 /*
  * void __asm_flush_dcache_all(int invalidate_only)
@@ -66,6 +68,7 @@ ENDPROC(__asm_dcache_level)
  *
  * flush or invalidate all data cache by SET/WAY.
  */
+.pushsection .text.__asm_dcache_all, "ax"
 ENTRY(__asm_dcache_all)
 	mov	x1, x0
 	dsb	sy
@@ -102,16 +105,21 @@ skip:
 finished:
 	ret
 ENDPROC(__asm_dcache_all)
+.popsection
 
+.pushsection .text.__asm_flush_dcache_all, "ax"
 ENTRY(__asm_flush_dcache_all)
 	mov	x0, #0
 	b	__asm_dcache_all
 ENDPROC(__asm_flush_dcache_all)
+.popsection
 
+.pushsection .text.__asm_invalidate_dcache_all, "ax"
 ENTRY(__asm_invalidate_dcache_all)
 	mov	x0, #0x1
 	b	__asm_dcache_all
 ENDPROC(__asm_invalidate_dcache_all)
+.popsection
 
 /*
  * void __asm_flush_dcache_range(start, end)
@@ -121,6 +129,7 @@ ENDPROC(__asm_invalidate_dcache_all)
  * x0: start address
  * x1: end address
  */
+.pushsection .text.__asm_flush_dcache_range, "ax"
 ENTRY(__asm_flush_dcache_range)
 	mrs	x3, ctr_el0
 	lsr	x3, x3, #16
@@ -138,6 +147,7 @@ ENTRY(__asm_flush_dcache_range)
 	dsb	sy
 	ret
 ENDPROC(__asm_flush_dcache_range)
+.popsection
 /*
  * void __asm_invalidate_dcache_range(start, end)
  *
@@ -146,6 +156,7 @@ ENDPROC(__asm_flush_dcache_range)
  * x0: start address
  * x1: end address
  */
+.pushsection .text.__asm_invalidate_dcache_range, "ax"
 ENTRY(__asm_invalidate_dcache_range)
 	mrs	x3, ctr_el0
 	ubfm	x3, x3, #16, #19
@@ -162,41 +173,51 @@ ENTRY(__asm_invalidate_dcache_range)
 	dsb	sy
 	ret
 ENDPROC(__asm_invalidate_dcache_range)
+.popsection
 
 /*
  * void __asm_invalidate_icache_all(void)
  *
  * invalidate all tlb entries.
  */
+.pushsection .text.__asm_invalidate_icache_all, "ax"
 ENTRY(__asm_invalidate_icache_all)
 	ic	ialluis
 	isb	sy
 	ret
 ENDPROC(__asm_invalidate_icache_all)
+.popsection
 
+.pushsection .text.__asm_invalidate_l3_dcache, "ax"
 ENTRY(__asm_invalidate_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
 ENDPROC(__asm_invalidate_l3_dcache)
 	.weak	__asm_invalidate_l3_dcache
+.popsection
 
+.pushsection .text.__asm_flush_l3_dcache, "ax"
 ENTRY(__asm_flush_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
 ENDPROC(__asm_flush_l3_dcache)
 	.weak	__asm_flush_l3_dcache
+.popsection
 
+.pushsection .text.__asm_invalidate_l3_icache, "ax"
 ENTRY(__asm_invalidate_l3_icache)
 	mov	x0, #0			/* return status as success */
 	ret
 ENDPROC(__asm_invalidate_l3_icache)
 	.weak	__asm_invalidate_l3_icache
+.popsection
 
 /*
  * void __asm_switch_ttbr(ulong new_ttbr)
  *
  * Safely switches to a new page table.
  */
+.pushsection .text.__asm_switch_ttbr, "ax"
 ENTRY(__asm_switch_ttbr)
 	/* x2 = SCTLR (alive throghout the function) */
 	switch_el x4, 3f, 2f, 1f
@@ -244,3 +265,4 @@ ENTRY(__asm_switch_ttbr)
 
 	ret	x3
 ENDPROC(__asm_switch_ttbr)
+.popsection
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 1b98f5a95513a860c2d6d654934a69df0522e79a..cdeef26fe5d4fd27f4ab55bd81070f1ea96232ae 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -393,3 +393,6 @@ config SYS_MC_RSV_MEM_ALIGN
 	help
 	  Reserved memory needs to be aligned for MC to use. Default value
 	  is 512MB.
+
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A
diff --git a/arch/arm/cpu/armv8/tlb.S b/arch/arm/cpu/armv8/tlb.S
index 945445bc3742bb03249b0e759b8a2f2ac0c45bee..6743111b6a1085245f3df70deaea95eb6bfcd3da 100644
--- a/arch/arm/cpu/armv8/tlb.S
+++ b/arch/arm/cpu/armv8/tlb.S
@@ -14,7 +14,8 @@
  * void __asm_invalidate_tlb_all(void)
  *
  * invalidate all tlb entries.
- */
+*/
+.pushsection .text.__asm_invalidate_tlb_all, "ax"
 ENTRY(__asm_invalidate_tlb_all)
 	switch_el x9, 3f, 2f, 1f
 3:	tlbi	alle3
@@ -31,3 +32,4 @@ ENTRY(__asm_invalidate_tlb_all)
 0:
 	ret
 ENDPROC(__asm_invalidate_tlb_all)
+.popsection
diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S
index ca074653769eb2e634d74a70e93a3a76f93624c0..7aa6935318c6a95e8cf9cee28467af432c2fb6e6 100644
--- a/arch/arm/cpu/armv8/transition.S
+++ b/arch/arm/cpu/armv8/transition.S
@@ -10,6 +10,7 @@
 #include <linux/linkage.h>
 #include <asm/macro.h>
 
+.pushsection .text.armv8_switch_to_el2, "ax"
 ENTRY(armv8_switch_to_el2)
 	switch_el x6, 1f, 0f, 0f
 0:
@@ -30,7 +31,9 @@ ENTRY(armv8_switch_to_el2)
 	br x4
 1:	armv8_switch_to_el2_m x4, x5, x6
 ENDPROC(armv8_switch_to_el2)
+.popsection
 
+.pushsection .text.armv8_switch_to_el1, "ax"
 ENTRY(armv8_switch_to_el1)
 	switch_el x6, 0f, 1f, 0f
 0:
@@ -40,7 +43,10 @@ ENTRY(armv8_switch_to_el1)
 	br x4
 1:	armv8_switch_to_el1_m x4, x5, x6
 ENDPROC(armv8_switch_to_el1)
+.popsection
 
+.pushsection .text.armv8_el2_to_aarch32, "ax"
 WEAK(armv8_el2_to_aarch32)
 	ret
 ENDPROC(armv8_el2_to_aarch32)
+.popsection
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index c2dc240edf687a51523ef4e1f21f5824e923486d..2cbdb17ca54b7d6604877dbea2681bb602a6cef9 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -42,6 +42,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3288-veyron-mickey.dtb \
 	rk3288-veyron-minnie.dtb \
 	rk3328-evb.dtb \
+	rk3368-lion.dtb \
 	rk3368-sheep.dtb \
 	rk3368-geekbox.dtb \
 	rk3368-px5-evb.dtb \
diff --git a/arch/arm/dts/rk3229-evb.dts b/arch/arm/dts/rk3229-evb.dts
index 37137c2e520bfdce2c961c64c5a701c7663bcc71..64f1c2d7dac2b854ef870cfbb99676e6a41bea7e 100644
--- a/arch/arm/dts/rk3229-evb.dts
+++ b/arch/arm/dts/rk3229-evb.dts
@@ -72,6 +72,17 @@
 	status = "okay";
 };
 
+&sdmmc {
+	status = "okay";
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;
+	num-slots = <1>;
+	supports-sd;
+};
+
 &uart2 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/rk322x.dtsi b/arch/arm/dts/rk322x.dtsi
index 4f2a1f6a157f620c472fdf3baebd8ee8a3ccec33..22324f97b3d9412c82224a7aa9208af03bed0868 100644
--- a/arch/arm/dts/rk322x.dtsi
+++ b/arch/arm/dts/rk322x.dtsi
@@ -21,6 +21,8 @@
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
+		mmc0 = &emmc;
+		mmc1 = &sdmmc;
 	};
 
 	cpus {
@@ -383,12 +385,38 @@
 		status = "disabled";
 	};
 
+	sdmmc: dwmmc@30000000 {
+		compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x30000000 0x4000>;
+		max-frequency = <150000000>;
+		interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+		fifo-depth = <0x100>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
+		status = "disabled";
+	};
+
+	sdio: dwmmc@30010000 {
+		compatible = "rockchip,rk3228-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x30010000 0x4000>;
+		interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+		fifo-depth = <0x100>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>;
+		status = "disabled";
+	};
+
 	emmc: dwmmc@30020000 {
 		compatible = "rockchip,rk3288-dw-mshc";
 		reg = <0x30020000 0x4000>;
+		max-frequency = <150000000>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
-		clock-frequency = <37500000>;
-		max-frequency = <37500000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
@@ -520,6 +548,40 @@
 			drive-strength = <12>;
 		};
 
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins = <1 15 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<1 19 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<1 20 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<1 21 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+		};
+
+		sdio {
+			sdio_clk: sdio-clk {
+				rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+
+			sdio_cmd: sdio-cmd {
+				rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+
+			sdio_bus4: sdio-bus4 {
+				rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<3 3 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<3 4 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
+						<3 5 RK_FUNC_1 &pcfg_pull_none_drv_12ma>;
+			};
+		};
+
 		emmc {
 			emmc_clk: emmc-clk {
 				rockchip,pins = <2 RK_PA7 RK_FUNC_2 &pcfg_pull_none>;
diff --git a/arch/arm/dts/rk3368-geekbox-u-boot.dtsi b/arch/arm/dts/rk3368-geekbox-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..764b3e4cb4fbbab54aae1afea473d5db2aee89f8
--- /dev/null
+++ b/arch/arm/dts/rk3368-geekbox-u-boot.dtsi
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+	X11
+ */
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&service_msch {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3368-lion-u-boot.dtsi b/arch/arm/dts/rk3368-lion-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..6052e8a8d38926ed2ccf92a3b04c5e1792134a87
--- /dev/null
+++ b/arch/arm/dts/rk3368-lion-u-boot.dtsi
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+	X11
+ */
+
+/ {
+	config {
+		u-boot,spl-payload-offset = <0x40000>; /* @ 256KB */
+		u-boot,mmc-env-offset = <0x4000>;      /* @  16KB */
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+		u-boot,spl-boot-order = &emmc, &sdmmc;
+	};
+
+};
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&service_msch {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+
+	/*
+	 * Validation of throughput using SPEC2000 shows the following
+	 * relative performance for the different memory schedules:
+	 *  - CBDR: 30.1
+	 *  - CBRD: 29.8
+	 *  - CRBD: 29.9
+	 * Note that the best performance for any given application workload
+	 * may vary from the default configured here (e.g. 164.gzip is fastest
+	 * with CBRD, whereas 252.eon and 186.crafty are fastest with CRBD).
+	 *
+	 * See doc/device-tree-bindings/clock/rockchip,rk3368-dmc.txt for
+	 * details on the 'rockchip,memory-schedule' property and how it
+	 * affects the physical-address to device-address mapping.
+	 */
+	rockchip,memory-schedule = <DMC_MSCH_CBDR>;
+	rockchip,ddr-frequency = <800000000>;
+	rockchip,ddr-speed-bin = <DDR3_1600K>;
+
+	status = "okay";
+};
+
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&sgrf {
+        u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
+
+&spi1 {
+	u-boot,dm-pre-reloc;
+
+	spiflash: w25q32dw@0 {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&timer0 {
+	u-boot,dm-pre-reloc;
+	clock-frequency = <24000000>;
+};
+
+
diff --git a/arch/arm/dts/rk3368-lion.dts b/arch/arm/dts/rk3368-lion.dts
new file mode 100644
index 0000000000000000000000000000000000000000..850db500e4e4be623499b5b420898ec3bb1aab33
--- /dev/null
+++ b/arch/arm/dts/rk3368-lion.dts
@@ -0,0 +1,195 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+	X11
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+#include "rk3368-lion-u-boot.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Theobroma Systems RK3368-uQ7 SoM";
+	compatible = "tsd,rk3368-uq7", "tsd,lion", "rockchip,rk3368";
+
+	aliases {
+		mmc0 = &emmc;
+		mmc1 = &sdmmc;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	ext_gmac: gmac-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+		#clock-cells = <0>;
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&emmc {
+	status = "okay";
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	clock-frequency = <150000000>;
+	disable-wp;
+	keep-power-in-suspend;
+	non-removable;
+	num-slots = <1>;
+	vmmc-supply = <&vcc33_io>;
+	vqmmc-supply = <&vcc18_io>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
+};
+
+&sdmmc {
+	status = "okay";
+};
+
+&gmac {
+	status = "okay";
+	phy-supply = <&vcc33_io>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	snps,reset-gpio = <&gpio3 11 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <2 10000 50000>;
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x10>;
+	rx_delay = <0x10>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		rockchip,system-power-controller;
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_sys>;
+		vcc9-supply = <&vcc_sys>;
+		vcc10-supply = <&vcc_sys>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_sys>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		#clock-cells = <1>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_cpu";
+			};
+
+			vdd_log: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_log";
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+			};
+
+			vcc33_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc33_io";
+			};
+
+			vcc33_video: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc33_video";
+			};
+
+			vdd10_pll: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_pll";
+			};
+
+			vcc18_io: LDO_REG4 {
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_io";
+			};
+
+			vdd10_video: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_video";
+			};
+
+			vcc18_video: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_video";
+			};
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	spiflash: w25q32dw@0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <49500000>;
+		spi-cpol;
+		spi-cpha;
+	};
+};
diff --git a/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..3a5e30ea55128068af61aca56ae90ffc3afa9822
--- /dev/null
+++ b/arch/arm/dts/rk3368-px5-evb-u-boot.dtsi
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+	X11
+ */
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&service_msch {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&uart4 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3368-sheep-u-boot.dtsi b/arch/arm/dts/rk3368-sheep-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..764b3e4cb4fbbab54aae1afea473d5db2aee89f8
--- /dev/null
+++ b/arch/arm/dts/rk3368-sheep-u-boot.dtsi
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+	X11
+ */
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
+&service_msch {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3368.dtsi b/arch/arm/dts/rk3368.dtsi
index 9daf76543067babfeed299dcd07ff7d43d71db6c..b4f4f6139dba2d81c8b104a38726ee0db504ff48 100644
--- a/arch/arm/dts/rk3368.dtsi
+++ b/arch/arm/dts/rk3368.dtsi
@@ -46,6 +46,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/memory/rk3368-dmc.h>
 
 / {
 	compatible = "rockchip,rk3368";
@@ -227,6 +228,21 @@
 		#clock-cells = <0>;
 	};
 
+	dmc: dmc@ff610000 {
+		compatible = "rockchip,rk3368-dmc", "syscon";
+		rockchip,cru = <&cru>;
+		rockchip,grf = <&grf>;
+		rockchip,msch = <&service_msch>;
+		reg = <0 0xff610000 0 0x400
+		       0 0xff620000 0 0x400>;
+	};
+
+	service_msch: syscon@ffac0000 {
+		compatible = "rockchip,rk3368-msch", "syscon";
+		reg = <0x0 0xffac0000 0x0 0x2000>;
+		status = "okay";
+	};
+
 	sdmmc: dwmmc@ff0c0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0c0000 0x0 0x4000>;
@@ -546,12 +562,6 @@
 		status = "disabled";
 	};
 
-	dmc: dmc@ff610000 {
-		u-boot,dm-pre-reloc;
-		compatible = "rockchip,rk3368-dmc", "syscon";
-		reg = <0x0 0xff610000 0x0 0x1000>;
-	};
-
 	i2c0: i2c@ff650000 {
 		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
 		reg = <0x0 0xff650000 0x0 0x1000>;
@@ -647,11 +657,15 @@
 	};
 
 	pmugrf: syscon@ff738000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3368-pmugrf", "syscon";
 		reg = <0x0 0xff738000 0x0 0x1000>;
 	};
 
+	sgrf: syscon@ff740000 {
+	        compatible = "rockchip,rk3368-sgrf", "syscon";
+		reg = <0x0 0xff740000 0x0 0x1000>;
+	};
+
 	cru: clock-controller@ff760000 {
 		compatible = "rockchip,rk3368-cru";
 		reg = <0x0 0xff760000 0x0 0x1000>;
@@ -673,7 +687,7 @@
 		status = "disabled";
 	};
 
-	timer@ff810000 {
+	timer0: timer@ff810000 {
 		compatible = "rockchip,rk3368-timer", "rockchip,rk3288-timer";
 		reg = <0x0 0xff810000 0x0 0x20>;
 		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index cb0a935edce711ecc421e0c2de77f6043ebf4ded..c7e21bd605efdde1c395756df188dfc61888260e 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
@@ -85,7 +85,7 @@ enum {
 	EMMC_PLL_SELECT_24MHZ,
 
 	EMMC_DIV_SHIFT		= 8,
-	EMMC_DIV_MASK		= 0x3f < EMMC_DIV_SHIFT,
+	EMMC_DIV_MASK		= 0x3f << EMMC_DIV_SHIFT,
 
 	SDIO0_PLL_SHIFT		= 6,
 	SDIO0_PLL_MASK		= 3 << SDIO0_PLL_SHIFT,
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
index 24a9cc052517c0f78fdd39e9b4d7b5a24f0ea284..2b1197fd4665a5686247f8e1d637ccab740b95a8 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
@@ -89,19 +89,26 @@ enum {
 	MCU_CLK_DIV_SHIFT		= 0,
 	MCU_CLK_DIV_MASK		= GENMASK(4, 0),
 
+	/* CLKSEL43_CON */
+	GMAC_MUX_SEL_EXTCLK             = BIT(8),
+
 	/* CLKSEL51_CON */
 	MMC_PLL_SEL_SHIFT		= 8,
 	MMC_PLL_SEL_MASK		= GENMASK(9, 8),
-	MMC_PLL_SEL_CPLL		= 0,
-	MMC_PLL_SEL_GPLL,
-	MMC_PLL_SEL_USBPHY_480M,
-	MMC_PLL_SEL_24M,
+	MMC_PLL_SEL_CPLL		= (0 << MMC_PLL_SEL_SHIFT),
+	MMC_PLL_SEL_GPLL                = (1 << MMC_PLL_SEL_SHIFT),
+	MMC_PLL_SEL_USBPHY_480M         = (2 << MMC_PLL_SEL_SHIFT),
+	MMC_PLL_SEL_24M                 = (3 << MMC_PLL_SEL_SHIFT),
 	MMC_CLK_DIV_SHIFT		= 0,
 	MMC_CLK_DIV_MASK		= GENMASK(6, 0),
 
 	/* SOFTRST1_CON */
 	MCU_PO_SRST_MASK		= BIT(13),
 	MCU_SYS_SRST_MASK		= BIT(12),
+	DMA1_SRST_REQ                   = BIT(2),
+
+	/* SOFTRST4_CON */
+	DMA2_SRST_REQ                   = BIT(0),
 
 	/* GLB_RST_CON */
 	PMU_GLB_SRST_CTRL_SHIFT		= 2,
diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3368.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3368.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e2b2337f22b045a40227adb9ea47af2a36edaf8
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3368.h
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ASM_ARCH_DDR_RK3368_H__
+#define __ASM_ARCH_DDR_RK3368_H__
+
+/*
+ * The RK3368 DDR PCTL differs from the incarnation in the RK3288 only
+ * in a few details. Most notably, it has an additional field to track
+ * tREFI in controller cycles (i.e. trefi_mem_ddr3).
+ */
+struct rk3368_ddr_pctl {
+	u32 scfg;
+	u32 sctl;
+	u32 stat;
+	u32 intrstat;
+	u32 reserved0[12];
+	u32 mcmd;
+	u32 powctl;
+	u32 powstat;
+	u32 cmdtstat;
+	u32 cmdtstaten;
+	u32 reserved1[3];
+	u32 mrrcfg0;
+	u32 mrrstat0;
+	u32 mrrstat1;
+	u32 reserved2[4];
+	u32 mcfg1;
+	u32 mcfg;
+	u32 ppcfg;
+	u32 mstat;
+	u32 lpddr2zqcfg;
+	u32 reserved3;
+	u32 dtupdes;
+	u32 dtuna;
+	u32 dtune;
+	u32 dtuprd0;
+	u32 dtuprd1;
+	u32 dtuprd2;
+	u32 dtuprd3;
+	u32 dtuawdt;
+	u32 reserved4[3];
+	u32 togcnt1u;
+	u32 tinit;
+	u32 trsth;
+	u32 togcnt100n;
+	u32 trefi;
+	u32 tmrd;
+	u32 trfc;
+	u32 trp;
+	u32 trtw;
+	u32 tal;
+	u32 tcl;
+	u32 tcwl;
+	u32 tras;
+	u32 trc;
+	u32 trcd;
+	u32 trrd;
+	u32 trtp;
+	u32 twr;
+	u32 twtr;
+	u32 texsr;
+	u32 txp;
+	u32 txpdll;
+	u32 tzqcs;
+	u32 tzqcsi;
+	u32 tdqs;
+	u32 tcksre;
+	u32 tcksrx;
+	u32 tcke;
+	u32 tmod;
+	u32 trstl;
+	u32 tzqcl;
+	u32 tmrr;
+	u32 tckesr;
+	u32 tdpd;
+	u32 trefi_mem_ddr3;
+	u32 reserved5[45];
+	u32 dtuwactl;
+	u32 dturactl;
+	u32 dtucfg;
+	u32 dtuectl;
+	u32 dtuwd0;
+	u32 dtuwd1;
+	u32 dtuwd2;
+	u32 dtuwd3;
+	u32 dtuwdm;
+	u32 dturd0;
+	u32 dturd1;
+	u32 dturd2;
+	u32 dturd3;
+	u32 dtulfsrwd;
+	u32 dtulfsrrd;
+	u32 dtueaf;
+	u32 dfitctrldelay;
+	u32 dfiodtcfg;
+	u32 dfiodtcfg1;
+	u32 dfiodtrankmap;
+	u32 dfitphywrdata;
+	u32 dfitphywrlat;
+	u32 reserved7[2];
+	u32 dfitrddataen;
+	u32 dfitphyrdlat;
+	u32 reserved8[2];
+	u32 dfitphyupdtype0;
+	u32 dfitphyupdtype1;
+	u32 dfitphyupdtype2;
+	u32 dfitphyupdtype3;
+	u32 dfitctrlupdmin;
+	u32 dfitctrlupdmax;
+	u32 dfitctrlupddly;
+	u32 reserved9;
+	u32 dfiupdcfg;
+	u32 dfitrefmski;
+	u32 dfitctrlupdi;
+	u32 reserved10[4];
+	u32 dfitrcfg0;
+	u32 dfitrstat0;
+	u32 dfitrwrlvlen;
+	u32 dfitrrdlvlen;
+	u32 dfitrrdlvlgateen;
+	u32 dfiststat0;
+	u32 dfistcfg0;
+	u32 dfistcfg1;
+	u32 reserved11;
+	u32 dfitdramclken;
+	u32 dfitdramclkdis;
+	u32 dfistcfg2;
+	u32 dfistparclr;
+	u32 dfistparlog;
+	u32 reserved12[3];
+	u32 dfilpcfg0;
+	u32 reserved13[3];
+	u32 dfitrwrlvlresp0;
+	u32 dfitrwrlvlresp1;
+	u32 dfitrwrlvlresp2;
+	u32 dfitrrdlvlresp0;
+	u32 dfitrrdlvlresp1;
+	u32 dfitrrdlvlresp2;
+	u32 dfitrwrlvldelay0;
+	u32 dfitrwrlvldelay1;
+	u32 dfitrwrlvldelay2;
+	u32 dfitrrdlvldelay0;
+	u32 dfitrrdlvldelay1;
+	u32 dfitrrdlvldelay2;
+	u32 dfitrrdlvlgatedelay0;
+	u32 dfitrrdlvlgatedelay1;
+	u32 dfitrrdlvlgatedelay2;
+	u32 dfitrcmd;
+	u32 reserved14[46];
+	u32 ipvr;
+	u32 iptr;
+};
+check_member(rk3368_ddr_pctl, iptr, 0x03fc);
+
+struct rk3368_ddrphy {
+	u32 reg[0x100];
+};
+check_member(rk3368_ddrphy, reg[0xff], 0x03fc);
+
+struct rk3368_msch {
+	u32 coreid;
+	u32 revisionid;
+	u32 ddrconf;
+	u32 ddrtiming;
+	u32 ddrmode;
+	u32 readlatency;
+	u32 reserved1[8];
+	u32 activate;
+	u32 devtodev;
+};
+check_member(rk3368_msch, devtodev, 0x003c);
+
+/* GRF_SOC_CON0 */
+enum {
+	NOC_RSP_ERR_STALL = BIT(9),
+	MOBILE_DDR_SEL = BIT(4),
+	DDR0_16BIT_EN = BIT(3),
+	MSCH0_MAINDDR3_DDR3 = BIT(2),
+	MSCH0_MAINPARTIALPOP = BIT(1),
+	UPCTL_C_ACTIVE = BIT(0),
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3368.h b/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
index 93c4e7d4e13ceccd9dc6ee5af44c2398b39beee5..6b6651acab4b676c21b7ea8aff7204a07fd673b1 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
@@ -1,4 +1,6 @@
-/* (C) Copyright 2016 Rockchip Electronics Co., Ltd
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
@@ -74,8 +76,11 @@ struct rk3368_grf {
 	u32 soc_con15;
 	u32 soc_con16;
 	u32 soc_con17;
+	u32 reserved5[0x6e];
+	u32 ddrc0_con0;
 };
 check_member(rk3368_grf, soc_con17, 0x444);
+check_member(rk3368_grf, ddrc0_con0, 0x600);
 
 struct rk3368_pmu_grf {
 	u32 gpio0a_iomux;
@@ -92,323 +97,11 @@ struct rk3368_pmu_grf {
 	u32 gpio0d_drv;
 	u32 gpio0l_sr;
 	u32 gpio0h_sr;
-	u32 reserved[(0x200 - 0x34) / 4 - 1];
+	u32 reserved[0x72];
 	u32 os_reg[4];
 };
-check_member(rk3368_pmu_grf, os_reg[3], 0x20c);
-
-/*GRF_GPIO0C_IOMUX*/
-enum {
-	GPIO0C7_SHIFT		= 14,
-	GPIO0C7_MASK		= 3 << GPIO0C7_SHIFT,
-	GPIO0C7_GPIO		= 0,
-	GPIO0C7_LCDC_D19,
-	GPIO0C7_TRACE_D9,
-	GPIO0C7_UART1_RTSN,
-
-	GPIO0C6_SHIFT           = 12,
-	GPIO0C6_MASK            = 3 << GPIO0C6_SHIFT,
-	GPIO0C6_GPIO            = 0,
-	GPIO0C6_LCDC_D18,
-	GPIO0C6_TRACE_D8,
-	GPIO0C6_UART1_CTSN,
-
-	GPIO0C5_SHIFT           = 10,
-	GPIO0C5_MASK            = 3 << GPIO0C5_SHIFT,
-	GPIO0C5_GPIO            = 0,
-	GPIO0C5_LCDC_D17,
-	GPIO0C5_TRACE_D7,
-	GPIO0C5_UART1_SOUT,
-
-	GPIO0C4_SHIFT           = 8,
-	GPIO0C4_MASK            = 3 << GPIO0C4_SHIFT,
-	GPIO0C4_GPIO            = 0,
-	GPIO0C4_LCDC_D16,
-	GPIO0C4_TRACE_D6,
-	GPIO0C4_UART1_SIN,
-
-	GPIO0C3_SHIFT           = 6,
-	GPIO0C3_MASK            = 3 << GPIO0C3_SHIFT,
-	GPIO0C3_GPIO            = 0,
-	GPIO0C3_LCDC_D15,
-	GPIO0C3_TRACE_D5,
-	GPIO0C3_MCU_JTAG_TDO,
-
-	GPIO0C2_SHIFT           = 4,
-	GPIO0C2_MASK            = 3 << GPIO0C2_SHIFT,
-	GPIO0C2_GPIO            = 0,
-	GPIO0C2_LCDC_D14,
-	GPIO0C2_TRACE_D4,
-	GPIO0C2_MCU_JTAG_TDI,
-
-	GPIO0C1_SHIFT           = 2,
-	GPIO0C1_MASK            = 3 << GPIO0C1_SHIFT,
-	GPIO0C1_GPIO            = 0,
-	GPIO0C1_LCDC_D13,
-	GPIO0C1_TRACE_D3,
-	GPIO0C1_MCU_JTAG_TRTSN,
-
-	GPIO0C0_SHIFT           = 0,
-	GPIO0C0_MASK            = 3 << GPIO0C0_SHIFT,
-	GPIO0C0_GPIO            = 0,
-	GPIO0C0_LCDC_D12,
-	GPIO0C0_TRACE_D2,
-	GPIO0C0_MCU_JTAG_TDO,
-};
-
-/*GRF_GPIO0D_IOMUX*/
-enum {
-	GPIO0D7_SHIFT           = 14,
-	GPIO0D7_MASK            = 3 << GPIO0D7_SHIFT,
-	GPIO0D7_GPIO            = 0,
-	GPIO0D7_LCDC_DCLK,
-	GPIO0D7_TRACE_CTL,
-	GPIO0D7_PMU_DEBUG5,
-
-	GPIO0D6_SHIFT           = 12,
-	GPIO0D6_MASK            = 3 << GPIO0D6_SHIFT,
-	GPIO0D6_GPIO            = 0,
-	GPIO0D6_LCDC_DEN,
-	GPIO0D6_TRACE_CLK,
-	GPIO0D6_PMU_DEBUG4,
-
-	GPIO0D5_SHIFT           = 10,
-	GPIO0D5_MASK            = 3 << GPIO0D5_SHIFT,
-	GPIO0D5_GPIO            = 0,
-	GPIO0D5_LCDC_VSYNC,
-	GPIO0D5_TRACE_D15,
-	GPIO0D5_PMU_DEBUG3,
-
-	GPIO0D4_SHIFT           = 8,
-	GPIO0D4_MASK            = 3 << GPIO0D4_SHIFT,
-	GPIO0D4_GPIO            = 0,
-	GPIO0D4_LCDC_HSYNC,
-	GPIO0D4_TRACE_D14,
-	GPIO0D4_PMU_DEBUG2,
-
-	GPIO0D3_SHIFT           = 6,
-	GPIO0D3_MASK            = 3 << GPIO0D3_SHIFT,
-	GPIO0D3_GPIO            = 0,
-	GPIO0D3_LCDC_D23,
-	GPIO0D3_TRACE_D13,
-	GPIO0D3_UART4_SIN,
-
-	GPIO0D2_SHIFT           = 4,
-	GPIO0D2_MASK            = 3 << GPIO0D2_SHIFT,
-	GPIO0D2_GPIO            = 0,
-	GPIO0D2_LCDC_D22,
-	GPIO0D2_TRACE_D12,
-	GPIO0D2_UART4_SOUT,
-
-	GPIO0D1_SHIFT           = 2,
-	GPIO0D1_MASK            = 3 << GPIO0D1_SHIFT,
-	GPIO0D1_GPIO            = 0,
-	GPIO0D1_LCDC_D21,
-	GPIO0D1_TRACE_D11,
-	GPIO0D1_UART4_RTSN,
-
-	GPIO0D0_SHIFT           = 0,
-	GPIO0D0_MASK            = 3 << GPIO0D0_SHIFT,
-	GPIO0D0_GPIO            = 0,
-	GPIO0D0_LCDC_D20,
-	GPIO0D0_TRACE_D10,
-	GPIO0D0_UART4_CTSN,
-};
-
-/*GRF_GPIO2A_IOMUX*/
-enum {
-	GPIO2A7_SHIFT           = 14,
-	GPIO2A7_MASK            = 3 << GPIO2A7_SHIFT,
-	GPIO2A7_GPIO            = 0,
-	GPIO2A7_SDMMC0_D2,
-	GPIO2A7_JTAG_TCK,
-
-	GPIO2A6_SHIFT           = 12,
-	GPIO2A6_MASK            = 3 << GPIO2A6_SHIFT,
-	GPIO2A6_GPIO            = 0,
-	GPIO2A6_SDMMC0_D1,
-	GPIO2A6_UART2_SIN,
-
-	GPIO2A5_SHIFT           = 10,
-	GPIO2A5_MASK            = 3 << GPIO2A5_SHIFT,
-	GPIO2A5_GPIO            = 0,
-	GPIO2A5_SDMMC0_D0,
-	GPIO2A5_UART2_SOUT,
-
-	GPIO2A4_SHIFT           = 8,
-	GPIO2A4_MASK            = 3 << GPIO2A4_SHIFT,
-	GPIO2A4_GPIO            = 0,
-	GPIO2A4_FLASH_DQS,
-	GPIO2A4_EMMC_CLKO,
-
-	GPIO2A3_SHIFT           = 6,
-	GPIO2A3_MASK            = 3 << GPIO2A3_SHIFT,
-	GPIO2A3_GPIO            = 0,
-	GPIO2A3_FLASH_CSN3,
-	GPIO2A3_EMMC_RSTNO,
-
-	GPIO2A2_SHIFT           = 4,
-	GPIO2A2_MASK            = 3 << GPIO2A2_SHIFT,
-	GPIO2A2_GPIO           = 0,
-	GPIO2A2_FLASH_CSN2,
-
-	GPIO2A1_SHIFT           = 2,
-	GPIO2A1_MASK            = 3 << GPIO2A1_SHIFT,
-	GPIO2A1_GPIO            = 0,
-	GPIO2A1_FLASH_CSN1,
-
-	GPIO2A0_SHIFT           = 0,
-	GPIO2A0_MASK            = 3 << GPIO2A0_SHIFT,
-	GPIO2A0_GPIO            = 0,
-	GPIO2A0_FLASH_CSN0,
-};
-
-/*GRF_GPIO2D_IOMUX*/
-enum {
-	GPIO2D7_SHIFT           = 14,
-	GPIO2D7_MASK            = 3 << GPIO2D7_SHIFT,
-	GPIO2D7_GPIO            = 0,
-	GPIO2D7_SDIO0_D3,
-
-	GPIO2D6_SHIFT           = 12,
-	GPIO2D6_MASK            = 3 << GPIO2D6_SHIFT,
-	GPIO2D6_GPIO            = 0,
-	GPIO2D6_SDIO0_D2,
-
-	GPIO2D5_SHIFT           = 10,
-	GPIO2D5_MASK            = 3 << GPIO2D5_SHIFT,
-	GPIO2D5_GPIO            = 0,
-	GPIO2D5_SDIO0_D1,
-
-	GPIO2D4_SHIFT           = 8,
-	GPIO2D4_MASK            = 3 << GPIO2D4_SHIFT,
-	GPIO2D4_GPIO            = 0,
-	GPIO2D4_SDIO0_D0,
-
-	GPIO2D3_SHIFT           = 6,
-	GPIO2D3_MASK            = 3 << GPIO2D3_SHIFT,
-	GPIO2D3_GPIO            = 0,
-	GPIO2D3_UART0_RTS0,
-
-	GPIO2D2_SHIFT           = 4,
-	GPIO2D2_MASK            = 3 << GPIO2D2_SHIFT,
-	GPIO2D2_GPIO            = 0,
-	GPIO2D2_UART0_CTS0,
-
-	GPIO2D1_SHIFT           = 2,
-	GPIO2D1_MASK            = 3 << GPIO2D1_SHIFT,
-	GPIO2D1_GPIO            = 0,
-	GPIO2D1_UART0_SOUT,
-
-	GPIO2D0_SHIFT           = 0,
-	GPIO2D0_MASK            = 3 << GPIO2D0_SHIFT,
-	GPIO2D0_GPIO            = 0,
-	GPIO2D0_UART0_SIN,
-};
-
-/*GRF_GPIO3C_IOMUX*/
-enum {
-	GPIO3C7_SHIFT           = 14,
-	GPIO3C7_MASK            = 3 << GPIO3C7_SHIFT,
-	GPIO3C7_GPIO            = 0,
-	GPIO3C7_EDPHDMI_CECINOUT,
-	GPIO3C7_ISP_FLASHTRIGIN,
-
-	GPIO3C6_SHIFT           = 12,
-	GPIO3C6_MASK            = 3 << GPIO3C6_SHIFT,
-	GPIO3C6_GPIO            = 0,
-	GPIO3C6_MAC_CLK,
-	GPIO3C6_ISP_SHUTTERTRIG,
-
-	GPIO3C5_SHIFT           = 10,
-	GPIO3C5_MASK            = 3 << GPIO3C5_SHIFT,
-	GPIO3C5_GPIO            = 0,
-	GPIO3C5_MAC_RXER,
-	GPIO3C5_ISP_PRELIGHTTRIG,
-
-	GPIO3C4_SHIFT           = 8,
-	GPIO3C4_MASK            = 3 << GPIO3C4_SHIFT,
-	GPIO3C4_GPIO            = 0,
-	GPIO3C4_MAC_RXDV,
-	GPIO3C4_ISP_FLASHTRIGOUT,
-
-	GPIO3C3_SHIFT           = 6,
-	GPIO3C3_MASK            = 3 << GPIO3C3_SHIFT,
-	GPIO3C3_GPIO            = 0,
-	GPIO3C3_MAC_RXDV,
-	GPIO3C3_EMMC_RSTNO,
-
-	GPIO3C2_SHIFT           = 4,
-	GPIO3C2_MASK            = 3 << GPIO3C2_SHIFT,
-	GPIO3C2_MAC_MDC            = 0,
-	GPIO3C2_ISP_SHUTTEREN,
-
-	GPIO3C1_SHIFT           = 2,
-	GPIO3C1_MASK            = 3 << GPIO3C1_SHIFT,
-	GPIO3C1_GPIO            = 0,
-	GPIO3C1_MAC_RXD2,
-	GPIO3C1_UART3_RTSN,
-
-	GPIO3C0_SHIFT           = 0,
-	GPIO3C0_MASK            = 3 << GPIO3C0_SHIFT,
-	GPIO3C0_GPIO            = 0,
-	GPIO3C0_MAC_RXD1,
-	GPIO3C0_UART3_CTSN,
-	GPIO3C0_GPS_RFCLK,
-};
-
-/*GRF_GPIO3D_IOMUX*/
-enum {
-	GPIO3D7_SHIFT           = 14,
-	GPIO3D7_MASK            = 3 << GPIO3D7_SHIFT,
-	GPIO3D7_GPIO            = 0,
-	GPIO3D7_SC_VCC18V,
-	GPIO3D7_I2C2_SDA,
-	GPIO3D7_GPUJTAG_TCK,
-
-	GPIO3D6_SHIFT           = 12,
-	GPIO3D6_MASK            = 3 << GPIO3D6_SHIFT,
-	GPIO3D6_GPIO            = 0,
-	GPIO3D6_IR_TX,
-	GPIO3D6_UART3_SOUT,
-	GPIO3D6_PWM3,
-
-	GPIO3D5_SHIFT           = 10,
-	GPIO3D5_MASK            = 3 << GPIO3D5_SHIFT,
-	GPIO3D5_GPIO            = 0,
-	GPIO3D5_IR_RX,
-	GPIO3D5_UART3_SIN,
-
-	GPIO3D4_SHIFT           = 8,
-	GPIO3D4_MASK            = 3 << GPIO3D4_SHIFT,
-	GPIO3D4_GPIO            = 0,
-	GPIO3D4_MAC_TXCLKOUT,
-	GPIO3D4_SPI1_CSN1,
-
-	GPIO3D3_SHIFT           = 6,
-	GPIO3D3_MASK            = 3 << GPIO3D3_SHIFT,
-	GPIO3D3_GPIO            = 0,
-	GPIO3D3_HDMII2C_SCL,
-	GPIO3D3_I2C5_SCL,
-
-	GPIO3D2_SHIFT           = 4,
-	GPIO3D2_MASK            = 3 << GPIO3D2_SHIFT,
-	GPIO3D2_GPIO            = 0,
-	GPIO3D2_HDMII2C_SDA,
-	GPIO3D2_I2C5_SDA,
-
-	GPIO3D1_SHIFT           = 2,
-	GPIO3D1_MASK            = 3 << GPIO3D1_SHIFT,
-	GPIO3D1_GPIO            = 0,
-	GPIO3D1_MAC_RXCLKIN,
-	GPIO3D1_I2C4_SCL,
-
-	GPIO3D0_SHIFT           = 0,
-	GPIO3D0_MASK            = 3 << GPIO3D0_SHIFT,
-	GPIO3D0_GPIO            = 0,
-	GPIO3D0_MAC_MDIO,
-	GPIO3D0_I2C4_SDA,
-};
+check_member(rk3368_pmu_grf, gpio0h_sr, 0x34);
+check_member(rk3368_pmu_grf, os_reg[0], 0x200);
 
 /*GRF_SOC_CON11/12/13*/
 enum {
@@ -439,4 +132,5 @@ enum {
 	MCU_CODE_BASE_BIT31_BIT28_SHIFT		= 0,
 	MCU_CODE_BASE_BIT31_BIT28_MASK		= GENMASK(3, 0),
 };
+
 #endif
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 0e674704ab6d020a260b78f548bbc07838a038ab..df45511699099c759ada76f2e26f0e5d34f9dac9 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -30,6 +30,7 @@ enum {
 	BOOT_DEVICE_BOARD,
 	BOOT_DEVICE_DFU,
 	BOOT_DEVICE_XIP,
+	BOOT_DEVICE_BOOTROM,
 	BOOT_DEVICE_NONE
 };
 #endif
diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S
index 57e728f9f2a36be2781442b4a9f4da3204fad1c1..62fad452b2127b0f07c416ab085005246f18c424 100644
--- a/arch/arm/lib/crt0_64.S
+++ b/arch/arm/lib/crt0_64.S
@@ -69,7 +69,9 @@ ENTRY(_main)
 /*
  * Set up initial C runtime environment and call board_init_f(0).
  */
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
+#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK)
+	ldr	x0, =(CONFIG_TPL_STACK)
+#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
 	ldr	x0, =(CONFIG_SPL_STACK)
 #else
 	ldr	x0, =(CONFIG_SYS_INIT_SP_ADDR)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 23ddc6296d896ab4cd827f23ff923ad8ccf24a33..20f7eeaf0913285c8a5d44a03631d20996f5a727 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -199,4 +199,8 @@ source "board/siemens/corvus/Kconfig"
 source "board/siemens/taurus/Kconfig"
 source "board/siemens/smartweb/Kconfig"
 
+config SPL_LDSCRIPT
+	default "arch/arm/mach-at91/arm926ejs/u-boot-spl.lds" if CPU_ARM926EJS
+	default "arch/arm/mach-at91/armv7/u-boot-spl.lds" if CPU_V7
+
 endif
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 4757f2496dfc836c65c5c7283bc796e21f20e9cb..35e4e9bcea927319e9ef9502f4a6e3a6d854ae55 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -53,4 +53,8 @@ source "board/davinci/ea20/Kconfig"
 source "board/omicron/calimain/Kconfig"
 source "board/lego/ev3/Kconfig"
 
+config SPL_LDSCRIPT
+	default "board/$(BOARDDIR)/u-boot-spl-ipam390.lds" if TARGET_IPAM390
+	default "board/$(BOARDDIR)/u-boot-spl-da850evm.lds"
+
 endif
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index d1aa68db20def848a092d37c7ee779694867de84..8b1389f30f23a204b99e57cabdf94c847a67bbe9 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -161,4 +161,7 @@ source "board/samsung/smdk5250/Kconfig"
 source "board/samsung/smdk5420/Kconfig"
 source "board/samsung/espresso7420/Kconfig"
 
+config SPL_LDSCRIPT
+	default "board/samsung/common/exynos-uboot-spl.lds" if ARCH_EXYNOS5 || ARCH_EXYNOS4
+
 endif
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 89c91d1b7782796d3cb221cc9dd06019acc20904..72832ad09944440c040d3d1649042b1ef5dac306 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -170,4 +170,7 @@ source "board/ti/am335x/Kconfig"
 source "board/compulab/cm_t335/Kconfig"
 source "board/compulab/cm_t43/Kconfig"
 
+config SPL_LDSCRIPT
+        default "arch/arm/mach-omap2/u-boot-spl.lds"
+
 endif
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index 7644b8dc854b3ac5086bfc7cce41c8f95b6528ca..2984a3edda21cea233362dc8b5b95aeb08dc4f6e 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -15,4 +15,7 @@ config SYS_SOC
 
 source "board/LaCie/edminiv2/Kconfig"
 
+config SPL_LDSCRIPT
+	default "$(CPUDIR)/orion5x/u-boot-spl.lds" if ORION5X
+
 endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index c9246132e097250fbeb4d9b078d4432313b12780..d9b25d5de4e66647799569df0d4c35089949afde 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -67,14 +67,42 @@ config ROCKCHIP_RK3328
 config ROCKCHIP_RK3368
 	bool "Support Rockchip RK3368"
 	select ARM64
+	select SUPPORT_SPL
+	select SUPPORT_TPL
+	select TPL_NEEDS_SEPARATE_TEXT_BASE if SPL
+	select TPL_NEEDS_SEPARATE_STACK if TPL
+	imply SPL_SEPARATE_BSS
+	imply SPL_SERIAL_SUPPORT
+	imply TPL_SERIAL_SUPPORT
+	select ENABLE_ARM_SOC_BOOT0_HOOK
+	select DEBUG_UART_BOARD_INIT
 	select SYS_NS16550
 	help
-	  The Rockchip RK3328 is a ARM-based SoC with a octa-core Cortex-A53.
-	  including NEON and GPU, 512KB L2 cache for big cluster and 256 KB
-	  L2 cache for little cluser, PowerVR G6110 based graphics, one video
-	  output processor supporting LVDS、HDMI、eDP, several DDR3 options
-	  and video codec support. Peripherals include Gigabit Ethernet,
-	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
+	  The Rockchip RK3368 is a ARM-based SoC with a octa-core (organised
+	  into a big and little cluster with 4 cores each) Cortex-A53 including
+	  AdvSIMD, 512KB L2 cache (for the big cluster) and 256 KB L2 cache
+	  (for the little cluster), PowerVR G6110 based graphics, one video
+	  output processor supporting LVDS/HDMI/eDP, several DDR3 options and
+	  video codec support.
+
+	  On-chip peripherals include Gigabit Ethernet, USB2 host and OTG, SDIO,
+	  I2S, UARTs, SPI, I2C and PWMs.
+
+if ROCKCHIP_RK3368
+
+config TPL_LDSCRIPT
+	default "arch/arm/mach-rockchip/rk3368/u-boot-tpl.lds"
+
+config TPL_TEXT_BASE
+        default 0xff8c1000
+
+config TPL_MAX_SIZE
+        default 28672
+
+config TPL_STACK
+        default 0xff8cffff
+
+endif
 
 config ROCKCHIP_RK3399
 	bool "Support Rockchip RK3399"
@@ -101,10 +129,21 @@ config ROCKCHIP_RV1108
 	  The Rockchip RV1108 is a ARM-based SoC with a single-core Cortex-A7
 	  and a DSP.
 
-config ROCKCHIP_SPL_BACK_TO_BROM
+config SPL_ROCKCHIP_BACK_TO_BROM
 	bool "SPL returns to bootrom"
 	default y if ROCKCHIP_RK3036
 	select ROCKCHIP_BROM_HELPER
+	depends on SPL
+	help
+	  Rockchip SoCs have ability to load SPL & U-Boot binary. If enabled,
+          SPL will return to the boot rom, which will then load the U-Boot
+          binary to keep going on.
+
+config TPL_ROCKCHIP_BACK_TO_BROM
+	bool "TPL returns to bootrom"
+	default y if ROCKCHIP_RK3368
+	select ROCKCHIP_BROM_HELPER
+	depends on TPL
 	help
 	  Rockchip SoCs have ability to load SPL & U-Boot binary. If enabled,
           SPL will return to the boot rom, which will then load the U-Boot
@@ -122,7 +161,7 @@ config ROCKCHIP_BROM_HELPER
 	bool
 
 config SPL_MMC_SUPPORT
-	default y if !ROCKCHIP_SPL_BACK_TO_BROM
+	default y if !SPL_ROCKCHIP_BACK_TO_BROM
 
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
 source "arch/arm/mach-rockchip/rk3188/Kconfig"
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index cb8d3efe4b3f27dcf44f5868481e719fc5d88252..79e9704a2c5fa58a7ec2d849ce564cf639bb9cd3 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -4,39 +4,50 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
-
-ifdef CONFIG_TPL_BUILD
-obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
-obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
-else ifdef CONFIG_SPL_BUILD
-obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
-obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
-obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-spl.o
-obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
-obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o
-obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
-else
+# We don't want the bootrom-helper present in a full U-Boot build, as
+# this may have entered from ATF with the stack-pointer pointing to
+# inaccessible/protected memory (and the bootrom-helper assumes that
+# the stack-pointer is valid before switching to the U-Boot stack).
+obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
+obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
+
+obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
+obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
+
+obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-spl.o spl-boot-order.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o
+
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
-ifdef CONFIG_RAM
-obj-y += sdram_common.o
-endif
 endif
+
+obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o
+
 ifndef CONFIG_ARM64
 obj-y += rk_timer.o
 endif
-obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
 
+obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
 ifndef CONFIG_TPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
 endif
-
 obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x/
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
 obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328/
 obj-$(CONFIG_ROCKCHIP_RK3368) += rk3368/
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
 obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108/
+
+# Clear out SPL objects, in case this is a TPL build
+obj-spl-$(CONFIG_TPL_BUILD) =
+
+# Now add SPL/TPL objects back into the main build
+obj-$(CONFIG_SPL_BUILD) += $(obj-spl-y)
+obj-$(CONFIG_TPL_BUILD) += $(obj-tpl-y)
diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c
index 4ca996231015a38cd0a5c05e288d28be73c4b284..8380e4e00613b8c2cd8e4fc587226b51d6dba2e1 100644
--- a/arch/arm/mach-rockchip/bootrom.c
+++ b/arch/arm/mach-rockchip/bootrom.c
@@ -9,8 +9,8 @@
 
 void back_to_bootrom(void)
 {
-#if defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && !defined(CONFIG_TPL_BUILD)
-	puts("Returning to boot ROM...");
+#if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT)
+	puts("Returning to boot ROM...\n");
 #endif
 	_back_to_bootrom_s();
 }
diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
index c3e174db9eae3b8a0f4651a413c8d12c47b64b0f..d3866bf029a53c993efeaf78416abab659ab07b4 100644
--- a/arch/arm/mach-rockchip/rk3188-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
@@ -167,8 +167,7 @@ void board_init_f(ulong dummy)
 	}
 
 	setup_arm_clock();
-
-#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
 	back_to_bootrom();
 #endif
 }
@@ -229,7 +228,7 @@ void spl_board_init(void)
 	}
 
 	preloader_console_init();
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 	back_to_bootrom();
 #endif
 	return;
diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c
index 3e76100ad1e541a436330f30b331a6b172a8e9bf..622e046dc0a754444aea5441b52a20e33e059162 100644
--- a/arch/arm/mach-rockchip/rk3188-board.c
+++ b/arch/arm/mach-rockchip/rk3188-board.c
@@ -39,7 +39,7 @@ int board_late_init(void)
 
 int board_init(void)
 {
-#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM)
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 	struct udevice *pinctrl;
 	int ret;
 
diff --git a/arch/arm/mach-rockchip/rk3188/Kconfig b/arch/arm/mach-rockchip/rk3188/Kconfig
index d129fcda99dced1fbb53042cd32444814c480130..2bb35662d19e52374cd32c7f605e5f4db9626823 100644
--- a/arch/arm/mach-rockchip/rk3188/Kconfig
+++ b/arch/arm/mach-rockchip/rk3188/Kconfig
@@ -30,9 +30,6 @@ config TPL_LIBCOMMON_SUPPORT
 config TPL_LIBGENERIC_SUPPORT
 	default y
 
-config TPL_SERIAL_SUPPORT
-	default y
-
 source "board/radxa/rock/Kconfig"
 
 endif
diff --git a/arch/arm/mach-rockchip/rk322x-board-spl.c b/arch/arm/mach-rockchip/rk322x-board-spl.c
index 15216c74b06fc14a40f061b510b60fc5aedede7b..4ddb8ba065f86828992783fdc5e31bb9e8505038 100644
--- a/arch/arm/mach-rockchip/rk322x-board-spl.c
+++ b/arch/arm/mach-rockchip/rk322x-board-spl.c
@@ -41,6 +41,8 @@ static struct rk322x_grf * const grf = (void *)GRF_BASE;
 		     CON_IOMUX_UART2SEL_MASK,
 		     CON_IOMUX_UART2SEL_21 << CON_IOMUX_UART2SEL_SHIFT);
 }
+
+#define SGRF_DDR_CON0 0x10150000
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;
@@ -71,6 +73,8 @@ void board_init_f(ulong dummy)
 		return;
 	}
 
+	/* Disable the ddr secure region setting to make it non-secure */
+	rk_clrreg(SGRF_DDR_CON0, 0x4000);
 #if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
 	back_to_bootrom();
 #endif
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index 5668fd28a00097ab7e6afc1fd5e72026140bd470..6b7bf85d8d3347aaa3f2363935f971978f1830c0 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -249,7 +249,7 @@ void board_init_f(ulong dummy)
 		debug("DRAM init failed: %d\n", ret);
 		return;
 	}
-#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
 	back_to_bootrom();
 #endif
 }
@@ -316,7 +316,7 @@ void spl_board_init(void)
 	}
 
 	preloader_console_init();
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 	back_to_bootrom();
 #endif
 	return;
diff --git a/arch/arm/mach-rockchip/rk3288-board.c b/arch/arm/mach-rockchip/rk3288-board.c
index 613967c307700bf3cb359051fcf5e055a226c779..d5f568c7932fe0501153361796a0e081ad1fd31e 100644
--- a/arch/arm/mach-rockchip/rk3288-board.c
+++ b/arch/arm/mach-rockchip/rk3288-board.c
@@ -78,7 +78,7 @@ int board_late_init(void)
 	return rk_board_late_init();
 }
 
-#ifndef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if !CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 static int veyron_init(void)
 {
 	struct udevice *dev;
@@ -115,7 +115,7 @@ static int veyron_init(void)
 
 int board_init(void)
 {
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 	struct udevice *pinctrl;
 	int ret;
 
diff --git a/arch/arm/mach-rockchip/rk3368-board-spl.c b/arch/arm/mach-rockchip/rk3368-board-spl.c
new file mode 100644
index 0000000000000000000000000000000000000000..cabf34448643ef232288833321a0bbe218a803f6
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3368-board-spl.c
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cru_rk3368.h>
+#include <asm/arch/grf_rk3368.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_debug_uart_init(void)
+{
+}
+
+void board_init_f(ulong dummy)
+{
+	struct udevice *pinctrl;
+	struct udevice *dev;
+	int ret;
+
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	/* Set up our preloader console */
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		error("%s: pinctrl init failed: %d\n", __func__, ret);
+		hang();
+	}
+
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART0);
+	if (ret) {
+		error("%s: failed to set up console UART\n", __func__);
+		hang();
+	}
+
+	preloader_console_init();
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+u32 spl_boot_mode(const u32 boot_device)
+{
+	return MMCSD_MODE_RAW;
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_MMC1;
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3368-board-tpl.c b/arch/arm/mach-rockchip/rk3368-board-tpl.c
new file mode 100644
index 0000000000000000000000000000000000000000..b3e6ffa781b0e92a3ec304bd9a8e09a797c7980d
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3368-board-tpl.c
@@ -0,0 +1,157 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom.h>
+#include <asm/arch/cru_rk3368.h>
+#include <asm/arch/grf_rk3368.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/timer.h>
+#include <syscon.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * The SPL (and also the full U-Boot stage on the RK3368) will run in
+ * secure mode (i.e. EL3) and an ATF will eventually be booted before
+ * starting up the operating system... so we can initialize the SGRF
+ * here and rely on the ATF installing the final (secure) policy
+ * later.
+ */
+static inline uintptr_t sgrf_soc_con_addr(unsigned no)
+{
+	const uintptr_t SGRF_BASE =
+		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
+
+	return SGRF_BASE + sizeof(u32) * no;
+}
+
+static inline uintptr_t sgrf_busdmac_addr(unsigned no)
+{
+	const uintptr_t SGRF_BASE =
+		(uintptr_t)syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
+	const uintptr_t SGRF_BUSDMAC_OFFSET = 0x100;
+	const uintptr_t SGRF_BUSDMAC_BASE = SGRF_BASE + SGRF_BUSDMAC_OFFSET;
+
+	return SGRF_BUSDMAC_BASE + sizeof(u32) * no;
+}
+
+static void sgrf_init(void)
+{
+	struct rk3368_cru * const cru =
+		(struct rk3368_cru * const)rockchip_get_cru();
+	const u16 SGRF_SOC_CON_SEC = GENMASK(15, 0);
+	const u16 SGRF_BUSDMAC_CON0_SEC = BIT(2);
+	const u16 SGRF_BUSDMAC_CON1_SEC = GENMASK(15, 12);
+
+	/* Set all configurable IP to 'non secure'-mode */
+	rk_setreg(sgrf_soc_con_addr(5), SGRF_SOC_CON_SEC);
+	rk_setreg(sgrf_soc_con_addr(6), SGRF_SOC_CON_SEC);
+	rk_setreg(sgrf_soc_con_addr(7), SGRF_SOC_CON_SEC);
+
+	/*
+	 * From rockchip-uboot/arch/arm/cpu/armv8/rk33xx/cpu.c
+	 * Original comment: "ddr space set no secure mode"
+	 */
+	rk_clrreg(sgrf_soc_con_addr(8), SGRF_SOC_CON_SEC);
+	rk_clrreg(sgrf_soc_con_addr(9), SGRF_SOC_CON_SEC);
+	rk_clrreg(sgrf_soc_con_addr(10), SGRF_SOC_CON_SEC);
+
+	/* Set 'secure dma' to 'non secure'-mode */
+	rk_setreg(sgrf_busdmac_addr(0), SGRF_BUSDMAC_CON0_SEC);
+	rk_setreg(sgrf_busdmac_addr(1), SGRF_BUSDMAC_CON1_SEC);
+
+	dsb();  /* barrier */
+
+	rk_setreg(&cru->softrst_con[1], DMA1_SRST_REQ);
+	rk_setreg(&cru->softrst_con[4], DMA2_SRST_REQ);
+
+	dsb();  /* barrier */
+	udelay(10);
+
+	rk_clrreg(&cru->softrst_con[1], DMA1_SRST_REQ);
+	rk_clrreg(&cru->softrst_con[4], DMA2_SRST_REQ);
+}
+
+void board_debug_uart_init(void)
+{
+	/*
+	 * N.B.: This is called before the device-model has been
+	 *       initialised. For this reason, we can not access
+	 *       the GRF address range using the syscon API.
+	 */
+	struct rk3368_grf * const grf =
+		(struct rk3368_grf * const)0xff770000;
+
+	enum {
+		GPIO2D1_MASK            = GENMASK(3, 2),
+		GPIO2D1_GPIO            = 0,
+		GPIO2D1_UART0_SOUT      = (1 << 2),
+
+		GPIO2D0_MASK            = GENMASK(1, 0),
+		GPIO2D0_GPIO            = 0,
+		GPIO2D0_UART0_SIN       = (1 << 0),
+	};
+
+#if defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff180000)
+	/* Enable early UART0 on the RK3368 */
+	rk_clrsetreg(&grf->gpio2d_iomux,
+		     GPIO2D0_MASK, GPIO2D0_UART0_SIN);
+	rk_clrsetreg(&grf->gpio2d_iomux,
+		     GPIO2D1_MASK, GPIO2D1_UART0_SOUT);
+#endif
+}
+
+void board_init_f(ulong dummy)
+{
+	struct udevice *dev;
+	int ret;
+
+#define EARLY_UART
+#ifdef EARLY_UART
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+	printascii("U-Boot TPL board init\n");
+#endif
+
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	/* Reset security, so we can use DMA in the MMC drivers */
+	sgrf_init();
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+void board_return_to_bootrom(void)
+{
+	back_to_bootrom();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_BOOTROM;
+}
diff --git a/arch/arm/mach-rockchip/rk3368/Kconfig b/arch/arm/mach-rockchip/rk3368/Kconfig
index 6d320689206978c8aa4927d2b6a120686f171748..7c9b722b002309fd82a77c0a80197492f871ebdd 100644
--- a/arch/arm/mach-rockchip/rk3368/Kconfig
+++ b/arch/arm/mach-rockchip/rk3368/Kconfig
@@ -3,6 +3,26 @@ if ROCKCHIP_RK3368
 choice
 	prompt "RK3368 board"
 
+config TARGET_LION_RK3368
+        bool "Theobroma Systems RK3368-uQ7 (Lion) module"
+	help
+	  The RK3368-uQ7 is a micro-Qseven form-factor (40mm x 70mm,
+	  MXM-230 connector) system-on-module designed by Theobroma
+	  Systems for industrial applications.
+
+	  It provides the following features:
+	   - 8x Cortex-A53 (in 2 clusters of 4 cores each)
+	   - (on-module) up to 4GB of DDR3 memory
+	   - (on-module) SPI-NOR flash
+	   - (on-module) eMMC
+	   - Gigabit Ethernet (with an on-module KSZ9031 PHY)
+	   - USB
+	   - HDMI
+	   - MIPI-DSI/single-channel LVDS (muxed on the 'LVDS-A' pin-group)
+	   - various 'slow' interfaces (e.g. UART, SPI, I2C, I2S, ...)
+	   - on-module STM32 providing CAN, RTC and fan-control
+	   - (optional on-module) EAL4+-certified security module
+
 config TARGET_SHEEP
 	bool "Sheep board"
 	help
@@ -25,8 +45,12 @@ endchoice
 config SYS_SOC
 	default "rockchip"
 
+source "board/theobroma-systems/lion_rk3368/Kconfig"
 source "board/rockchip/sheep_rk3368/Kconfig"
 source "board/geekbuying/geekbox/Kconfig"
 source "board/rockchip/evb_px5/Kconfig"
 
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/armv8/u-boot-spl.lds"
+
 endif
diff --git a/arch/arm/mach-rockchip/rk3368/Makefile b/arch/arm/mach-rockchip/rk3368/Makefile
index 0390716410bd07468aa5f5b121d1c0056966d494..46798c2e936b0573f05f9cc4e74a22c735baa2d8 100644
--- a/arch/arm/mach-rockchip/rk3368/Makefile
+++ b/arch/arm/mach-rockchip/rk3368/Makefile
@@ -5,5 +5,4 @@
 #
 obj-y		+= clk_rk3368.o
 obj-y		+= rk3368.o
-obj-y 		+= sdram_rk3368.o
 obj-y 		+= syscon_rk3368.o
diff --git a/arch/arm/mach-rockchip/rk3368/sdram_rk3368.c b/arch/arm/mach-rockchip/rk3368/sdram_rk3368.c
deleted file mode 100644
index d0d090087b3c9546dc71baf4fad98f6946a91711..0000000000000000000000000000000000000000
--- a/arch/arm/mach-rockchip/rk3368/sdram_rk3368.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * (C) Copyright 2016 Rockchip Electronics Co., Ltd.
- *
- * SPDX-License-Identifier:     GPL-2.0
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ram.h>
-#include <syscon.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/grf_rk3368.h>
-#include <asm/arch/sdram_common.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-struct dram_info {
-	struct ram_info info;
-	struct rk3368_pmu_grf *pmugrf;
-};
-
-static int rk3368_dmc_probe(struct udevice *dev)
-{
-	struct dram_info *priv = dev_get_priv(dev);
-
-	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
-	debug("%s: grf=%p\n", __func__, priv->pmugrf);
-	priv->info.base = CONFIG_SYS_SDRAM_BASE;
-	priv->info.size = rockchip_sdram_size(
-			(phys_addr_t)&priv->pmugrf->os_reg[2]);
-
-	return 0;
-}
-
-static int rk3368_dmc_get_info(struct udevice *dev, struct ram_info *info)
-{
-	struct dram_info *priv = dev_get_priv(dev);
-
-	*info = priv->info;
-
-	return 0;
-}
-
-static struct ram_ops rk3368_dmc_ops = {
-	.get_info = rk3368_dmc_get_info,
-};
-
-
-static const struct udevice_id rk3368_dmc_ids[] = {
-	{ .compatible = "rockchip,rk3368-dmc" },
-	{ }
-};
-
-U_BOOT_DRIVER(dmc_rk3368) = {
-	.name = "rockchip_rk3368_dmc",
-	.id = UCLASS_RAM,
-	.of_match = rk3368_dmc_ids,
-	.ops = &rk3368_dmc_ops,
-	.probe = rk3368_dmc_probe,
-	.priv_auto_alloc_size = sizeof(struct dram_info),
-};
diff --git a/arch/arm/mach-rockchip/rk3368/syscon_rk3368.c b/arch/arm/mach-rockchip/rk3368/syscon_rk3368.c
index 03e97eb6292f21554091887b0d782e5ea8a9b0ad..99d51f0edc0ff431c65860fe6616f30b3f79ea4b 100644
--- a/arch/arm/mach-rockchip/rk3368/syscon_rk3368.c
+++ b/arch/arm/mach-rockchip/rk3368/syscon_rk3368.c
@@ -1,6 +1,8 @@
 /*
  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
  * Author: Andy Yan <andy.yan@rock-chips.com>
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -14,6 +16,10 @@ static const struct udevice_id rk3368_syscon_ids[] = {
 	  .data = ROCKCHIP_SYSCON_GRF },
 	{ .compatible = "rockchip,rk3368-pmugrf",
 	  .data = ROCKCHIP_SYSCON_PMUGRF },
+	{ .compatible = "rockchip,rk3368-msch",
+	  .data = ROCKCHIP_SYSCON_MSCH },
+	{ .compatible = "rockchip,rk3368-sgrf",
+	  .data = ROCKCHIP_SYSCON_SGRF },
 	{ }
 };
 
@@ -22,3 +28,41 @@ U_BOOT_DRIVER(syscon_rk3368) = {
 	.id = UCLASS_SYSCON,
 	.of_match = rk3368_syscon_ids,
 };
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rk3368_syscon_bind_of_platdata(struct udevice *dev)
+{
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(rockchip_rk3368_grf) = {
+	.name = "rockchip_rk3368_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3368_syscon_ids,
+	.bind = rk3368_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3368_pmugrf) = {
+	.name = "rockchip_rk3368_pmugrf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3368_syscon_ids + 1,
+	.bind = rk3368_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3368_msch) = {
+	.name = "rockchip_rk3368_msch",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3368_syscon_ids + 2,
+	.bind = rk3368_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3368_sgrf) = {
+	.name = "rockchip_rk3368_sgrf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3368_syscon_ids + 3,
+	.bind = rk3368_syscon_bind_of_platdata,
+};
+#endif
diff --git a/arch/arm/mach-rockchip/rk3368/u-boot-tpl.lds b/arch/arm/mach-rockchip/rk3368/u-boot-tpl.lds
new file mode 100644
index 0000000000000000000000000000000000000000..cc59844735be642f81cb0f7a78de6c5b8a050be7
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3368/u-boot-tpl.lds
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#undef CONFIG_SPL_TEXT_BASE
+#define CONFIG_SPL_TEXT_BASE CONFIG_TPL_TEXT_BASE
+
+#undef CONFIG_SPL_MAX_SIZE
+#define CONFIG_SPL_MAX_SIZE CONFIG_TPL_MAX_SIZE
+
+#include "../../cpu/armv8/u-boot-spl.lds"
diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c
index e050affac06ca3c185cc6c92cb096174a3d8434e..a13b717bbd003f5913af3082664297a2bdbf3145 100644
--- a/arch/arm/mach-rockchip/rk3399-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3399-board-spl.c
@@ -8,9 +8,6 @@
 #include <debug_uart.h>
 #include <dm.h>
 #include <fdtdec.h>
-#include <led.h>
-#include <malloc.h>
-#include <mmc.h>
 #include <ram.h>
 #include <spl.h>
 #include <asm/gpio.h>
@@ -21,111 +18,10 @@
 #include <asm/arch/sdram.h>
 #include <asm/arch/timer.h>
 #include <dm/pinctrl.h>
-#include <dm/root.h>
-#include <dm/test.h>
-#include <dm/util.h>
 #include <power/regulator.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OF_CONTROL)
-static int spl_node_to_boot_device(int node)
-{
-	struct udevice *parent;
-
-	/*
-	 * This should eventually move into the SPL code, once SPL becomes
-	 * aware of the block-device layer.  Until then (and to avoid unneeded
-	 * delays in getting this feature out, it lives at the board-level).
-	 */
-	if (!uclass_get_device_by_of_offset(UCLASS_MMC, node, &parent)) {
-		struct udevice *dev;
-		struct blk_desc *desc = NULL;
-
-		for (device_find_first_child(parent, &dev);
-		     dev;
-		     device_find_next_child(&dev)) {
-			if (device_get_uclass_id(dev) == UCLASS_BLK) {
-				desc = dev_get_uclass_platdata(dev);
-				break;
-			}
-		}
-
-		if (!desc)
-			return -ENOENT;
-
-		switch (desc->devnum) {
-		case 0:
-			return BOOT_DEVICE_MMC1;
-		case 1:
-			return BOOT_DEVICE_MMC2;
-		default:
-			return -ENOSYS;
-		}
-	}
-
-	/*
-	 * SPL doesn't differentiate SPI flashes, so we keep the detection
-	 * brief and inaccurate... hopefully, the common SPL layer can be
-	 * extended with awareness of the BLK layer (and matching OF_CONTROL)
-	 * soon.
-	 */
-	if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent))
-		return BOOT_DEVICE_SPI;
-
-	return -1;
-}
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	const void *blob = gd->fdt_blob;
-	int chosen_node = fdt_path_offset(blob, "/chosen");
-	int idx = 0;
-	int elem;
-	int boot_device;
-	int node;
-	const char *conf;
-
-	if (chosen_node < 0) {
-		debug("%s: /chosen not found, using spl_boot_device()\n",
-		      __func__);
-		spl_boot_list[0] = spl_boot_device();
-		return;
-	}
-
-	for (elem = 0;
-	     (conf = fdt_stringlist_get(blob, chosen_node,
-					"u-boot,spl-boot-order", elem, NULL));
-	     elem++) {
-		/* First check if the list element is an alias */
-		const char *alias = fdt_get_alias(blob, conf);
-		if (alias)
-			conf = alias;
-
-		/* Try to resolve the config item (or alias) as a path */
-		node = fdt_path_offset(blob, conf);
-		if (node < 0) {
-			debug("%s: could not find %s in FDT", __func__, conf);
-			continue;
-		}
-
-		/* Try to map this back onto SPL boot devices */
-		boot_device = spl_node_to_boot_device(node);
-		if (boot_device < 0) {
-			debug("%s: could not map node @%x to a boot-device\n",
-			      __func__, node);
-			continue;
-		}
-
-		spl_boot_list[idx++] = boot_device;
-	}
-
-	/* If we had no matches, fall back to spl_boot_device */
-	if (idx == 0)
-		spl_boot_list[0] = spl_boot_device();
-}
-#endif
-
 u32 spl_boot_device(void)
 {
 	return BOOT_DEVICE_MMC1;
@@ -263,7 +159,7 @@ void spl_board_init(void)
 	}
 
 	preloader_console_init();
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 	back_to_bootrom();
 #endif
 
diff --git a/arch/arm/mach-rockchip/save_boot_param.S b/arch/arm/mach-rockchip/save_boot_param.S
index 5e6c8dba13e787d41b2b82257c6ac54bd8c65483..50fce207a534947dc368147a5c31db647df106b8 100644
--- a/arch/arm/mach-rockchip/save_boot_param.S
+++ b/arch/arm/mach-rockchip/save_boot_param.S
@@ -1,11 +1,47 @@
 /*
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <linux/linkage.h>
 
+#if defined(CONFIG_ARM64)
+.globl	SAVE_SP_ADDR
+SAVE_SP_ADDR:
+	.quad 0
+
+ENTRY(save_boot_params)
+	sub	sp, sp, #0x60
+	stp	x29, x30, [sp, #0x50]
+	stp	x27, x28, [sp, #0x40]
+	stp	x25, x26, [sp, #0x30]
+	stp	x23, x24, [sp, #0x20]
+	stp	x21, x22, [sp, #0x10]
+	stp	x19, x20, [sp, #0]
+	ldr	x8, =SAVE_SP_ADDR
+	mov	x9, sp
+	str	x9, [x8]
+	b	save_boot_params_ret  /* back to my caller */
+ENDPROC(save_boot_params)
+
+.globl _back_to_bootrom_s
+ENTRY(_back_to_bootrom_s)
+	ldr	x0, =SAVE_SP_ADDR
+	ldr	x0, [x0]
+	mov	sp, x0
+	ldp	x29, x30, [sp, #0x50]
+	ldp	x27, x28, [sp, #0x40]
+	ldp	x25, x26, [sp, #0x30]
+	ldp	x23, x24, [sp, #0x20]
+	ldp	x21, x22, [sp, #0x10]
+	ldp	x19, x20, [sp]
+	add	sp, sp, #0x60
+	mov	x0, xzr
+	ret
+ENDPROC(_back_to_bootrom_s)
+#else
 .globl	SAVE_SP_ADDR
 SAVE_SP_ADDR:
 	.word 0
@@ -30,3 +66,4 @@ ENTRY(_back_to_bootrom_s)
 	mov	r0, #0
 	pop	{r1-r12, pc}
 ENDPROC(_back_to_bootrom_s)
+#endif
diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f78c72720948e9adc77ae1c3437d096d5c5dca9
--- /dev/null
+++ b/arch/arm/mach-rockchip/spl-boot-order.c
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mmc.h>
+#include <spl.h>
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int spl_node_to_boot_device(int node)
+{
+	struct udevice *parent;
+
+	/*
+	 * This should eventually move into the SPL code, once SPL becomes
+	 * aware of the block-device layer.  Until then (and to avoid unneeded
+	 * delays in getting this feature out, it lives at the board-level).
+	 */
+	if (!uclass_get_device_by_of_offset(UCLASS_MMC, node, &parent)) {
+		struct udevice *dev;
+		struct blk_desc *desc = NULL;
+
+		for (device_find_first_child(parent, &dev);
+		     dev;
+		     device_find_next_child(&dev)) {
+			if (device_get_uclass_id(dev) == UCLASS_BLK) {
+				desc = dev_get_uclass_platdata(dev);
+				break;
+			}
+		}
+
+		if (!desc)
+			return -ENOENT;
+
+		switch (desc->devnum) {
+		case 0:
+			return BOOT_DEVICE_MMC1;
+		case 1:
+			return BOOT_DEVICE_MMC2;
+		default:
+			return -ENOSYS;
+		}
+	}
+
+	/*
+	 * SPL doesn't differentiate SPI flashes, so we keep the detection
+	 * brief and inaccurate... hopefully, the common SPL layer can be
+	 * extended with awareness of the BLK layer (and matching OF_CONTROL)
+	 * soon.
+	 */
+	if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent))
+		return BOOT_DEVICE_SPI;
+
+	return -1;
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	const void *blob = gd->fdt_blob;
+	int chosen_node = fdt_path_offset(blob, "/chosen");
+	int idx = 0;
+	int elem;
+	int boot_device;
+	int node;
+	const char *conf;
+
+	if (chosen_node < 0) {
+		debug("%s: /chosen not found, using spl_boot_device()\n",
+		      __func__);
+		spl_boot_list[0] = spl_boot_device();
+		return;
+	}
+
+	for (elem = 0;
+	     (conf = fdt_stringlist_get(blob, chosen_node,
+					"u-boot,spl-boot-order", elem, NULL));
+	     elem++) {
+		/* First check if the list element is an alias */
+		const char *alias = fdt_get_alias(blob, conf);
+		if (alias)
+			conf = alias;
+
+		/* Try to resolve the config item (or alias) as a path */
+		node = fdt_path_offset(blob, conf);
+		if (node < 0) {
+			debug("%s: could not find %s in FDT", __func__, conf);
+			continue;
+		}
+
+		/* Try to map this back onto SPL boot devices */
+		boot_device = spl_node_to_boot_device(node);
+		if (boot_device < 0) {
+			debug("%s: could not map node @%x to a boot-device\n",
+			      __func__, node);
+			continue;
+		}
+
+		spl_boot_list[idx++] = boot_device;
+	}
+
+	/* If we had no matches, fall back to spl_boot_device */
+	if (idx == 0)
+		spl_boot_list[0] = spl_boot_device();
+}
+#endif
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 94412bac0c1df717216e1412c1f286391257cd80..386befb4e7b893ee8920973f31395f853c24b55d 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1,5 +1,8 @@
 if ARCH_SUNXI
 
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64
+
 config IDENT_STRING
 	default " Allwinner Technology"
 
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index c428ce5cc70b35d738060e14350ad63b7713c957..b9cd45ba095f311a73f1bbf329698bda9be92d9b 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -1,5 +1,8 @@
 if ARCH_ZYNQ
 
+config SPL_LDSCRIPT
+	default "arch/arm/mach-zynq/u-boot-spl.lds"
+
 config SPL_FAT_SUPPORT
 	default y
 
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 20fa25b5ccb2a3ccc07db03f5a1f0496d00aeab5..f791c0081eab3e12aba3d6b30b9fc6b23e1b9635 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -21,4 +21,7 @@ endchoice
 
 source "board/xilinx/microblaze-generic/Kconfig"
 
+config SPL_LDSCRIPT
+	default "arch/microblaze/cpu/u-boot-spl.lds"
+
 endmenu
diff --git a/board/armadeus/apf27/Kconfig b/board/armadeus/apf27/Kconfig
index 65544a844834eb7288213a5e3ee66aef4177e296..a342d2e05ec51fcf4772e84665d48080eca85f20 100644
--- a/board/armadeus/apf27/Kconfig
+++ b/board/armadeus/apf27/Kconfig
@@ -1,5 +1,8 @@
 if TARGET_APF27
 
+config SPL_LDSCRIPT
+	default "arch/$(ARCH)/cpu/u-boot-spl.lds"
+
 config SYS_BOARD
 	default "apf27"
 
diff --git a/board/freescale/mx31pdk/Kconfig b/board/freescale/mx31pdk/Kconfig
index 055545c93063c5641ab7bd8fd283981b9bf808a3..b9fc2d51778628ef5de6996572a8a0086a8a9406 100644
--- a/board/freescale/mx31pdk/Kconfig
+++ b/board/freescale/mx31pdk/Kconfig
@@ -1,5 +1,8 @@
 if TARGET_MX31PDK
 
+config SPL_LDSCRIPT
+	default "arch/$(ARCH)/cpu/u-boot-spl.lds"
+
 config SYS_BOARD
 	default "mx31pdk"
 
diff --git a/board/rockchip/evb_px5/evb-px5.c b/board/rockchip/evb_px5/evb-px5.c
index 6dca1fc74b92b32c3bd87377347f76c639693700..6a47642b575f4db188614d3dec5c472036bab0fa 100644
--- a/board/rockchip/evb_px5/evb-px5.c
+++ b/board/rockchip/evb_px5/evb-px5.c
@@ -4,30 +4,6 @@
  * SPDX-License-Identifier:     GPL-2.0+
  */
 #include <common.h>
-#include <asm/io.h>
-#include <fdtdec.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/grf_rk3368.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-int mach_cpu_init(void)
-{
-	struct rk3368_pmu_grf *pmugrf;
-	int node;
-
-	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "rockchip,rk3368-pmugrf");
-	pmugrf = (struct rk3368_pmu_grf *)fdtdec_get_addr(gd->fdt_blob, node, "reg");
-
-	rk_clrsetreg(&pmugrf->gpio0d_iomux,
-		     GPIO0D0_MASK | GPIO0D1_MASK |
-		     GPIO0D2_MASK | GPIO0D3_MASK,
-		     GPIO0D0_GPIO << GPIO0D0_SHIFT |
-		     GPIO0D1_GPIO << GPIO0D1_SHIFT |
-		     GPIO0D2_UART4_SOUT << GPIO0D2_SHIFT |
-		     GPIO0D3_UART4_SIN << GPIO0D3_SHIFT);
-	return 0;
-}
 
 int board_init(void)
 {
diff --git a/board/spear/x600/Kconfig b/board/spear/x600/Kconfig
index 6a1c5c7b40143f49d8191b046eda13364fd25ed9..59f2b1ef561578c888b5baab4e68e701ff56b978 100644
--- a/board/spear/x600/Kconfig
+++ b/board/spear/x600/Kconfig
@@ -1,5 +1,8 @@
 if TARGET_X600
 
+config SPL_LDSCRIPT
+	default "arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds"
+
 config SYS_BOARD
 	default "x600"
 
diff --git a/board/theobroma-systems/lion_rk3368/Kconfig b/board/theobroma-systems/lion_rk3368/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..d7aa487abd4f86c166c2e3e62a4ecfa013c5a9bb
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LION_RK3368
+
+config SYS_BOARD
+	default "lion_rk3368"
+
+config SYS_VENDOR
+	default "theobroma-systems"
+
+config SYS_CONFIG_NAME
+	default "lion_rk3368"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/theobroma-systems/lion_rk3368/MAINTAINERS b/board/theobroma-systems/lion_rk3368/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..857f784d21b73b06a855e500e9f54d1f01c8f062
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/MAINTAINERS
@@ -0,0 +1,10 @@
+LION-RK3368 (RK3368-uQ7 system-on-module)
+M:	Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+M:	Klaus Goger <klaus.goger@theobroma-systems.com>
+S:	Maintained
+F:	board/theobroma-systems/lion_rk3368
+F:	include/configs/lion_rk3368.h
+F:	arch/arm/dts/rk3368-lion.dts
+F:	configs/lion-rk3368_defconfig
+W:	https://www.theobroma-systems.com/rk3368-uq7/tech-specs
+T:	git git://git.theobroma-systems.com/lion-u-boot.git
diff --git a/board/theobroma-systems/lion_rk3368/Makefile b/board/theobroma-systems/lion_rk3368/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f13a20b21e990d60456dd532b8c1c92af6f5455a
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += lion_rk3368.o
diff --git a/board/theobroma-systems/lion_rk3368/README b/board/theobroma-systems/lion_rk3368/README
new file mode 100644
index 0000000000000000000000000000000000000000..47304fcba6b872195cdcfd332ccc8c70136962ac
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/README
@@ -0,0 +1,60 @@
+Here is the step-by-step to boot to U-Boot on RK3368-uQ7
+
+Get the Source and build ATF
+============================
+
+  > git clone git://git.theobroma-systems.com/arm-trusted-firmware.git
+  > cd arm-trusted-firmware
+  > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3368 bl31
+  > cp build/rk3368/release/bl31.bin ../u-boot/bl31-rk3368.bin
+
+Configure U-Boot
+================
+
+  > cd ../u-boot
+  > make lion-rk3368_defconfig
+
+Build the TPL/SPL stage
+=======================
+
+  > make CROSS_COMPILE=aarch64-unknown-elf- ARCH=arm
+  > tools/mkimage -n rk3368 -T rksd -d tpl/u-boot-tpl.bin spl-3368.img
+  > cat spl/u-boot-spl-dtb.bin >> spl-3368.img
+
+Build the full U-Boot and a FIT image including the ATF
+=======================================================
+
+  > make CROSS_COMPILE=aarch64-unknown-elf- ARCH=arm u-boot.itb
+
+Write to a SD-card
+==================
+
+  > dd if=spl-3368.img of=/dev/sdb seek=64
+  > dd if=u-boot.itb of=/dev/sdb seek=512
+
+
+If everything went according to plan, you should see the following
+output on UART0:
+
+<debug_uart> U-Boot TPL board init
+Trying to boot from BOOTROM
+Returning to boot ROM...
+Trying to boot from MMC1
+NOTICE:  BL31: v1.3(release):v1.2-1320-gbf43a443
+NOTICE:  BL31: Built : 18:04:47, Jul  5 2017
+
+
+U-Boot 2017.07-00158-g2395e99858 (Jul 18 2017 - 21:03:31 +0200)
+
+Model: Theobroma Systems RK3368-uQ7 SoM
+DRAM:  2 GiB
+MMC:   dwmmc@ff0c0000: 1, dwmmc@ff0f0000: 0
+Using default environment
+
+In:    serial@ff180000
+Out:   serial@ff180000
+Err:   serial@ff180000
+Net:
+Warning: ethernet@ff290000 (eth0) using random MAC address - d2:69:35:7e:d0:1e
+eth0: ethernet@ff290000
+Hit any key to stop autoboot:  2
diff --git a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its
new file mode 100644
index 0000000000000000000000000000000000000000..405750f3517b5588428626a9b136044b736d3868
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * Minimal dts for a SPL FIT image payload.
+ *
+ * SPDX-License-Identifier: GPL-2.0+  X11
+ */
+
+/dts-v1/;
+
+/ {
+	description = "FIT image with U-Boot proper, ATF bl31, DTB";
+	#address-cells = <1>;
+
+	images {
+		uboot {
+			description = "U-Boot (64-bit)";
+			data = /incbin/("../../../u-boot-nodtb.bin");
+			type = "standalone";
+			arch = "arm64";
+			compression = "none";
+			load = <0x00200000>;
+		};
+		atf {
+			description = "ARM Trusted Firmware";
+			data = /incbin/("../../../bl31-rk3368.bin");
+			type = "firmware";
+			arch = "arm64";
+			compression = "none";
+			load = <0x00010000>;
+			entry = <0x00010000>;
+		};
+
+		fdt {
+			description = "RK3368-uQ7 (Lion) flat device-tree";
+			data = /incbin/("../../../u-boot.dtb");
+			type = "flat_dt";
+			compression = "none";
+		};
+	};
+
+	configurations {
+		default = "conf";
+		conf {
+			description = "Theobroma Systems RK3368-uQ7 (Puma) SoM";
+			firmware = "uboot";
+			loadables = "atf";
+			fdt = "fdt";
+		};
+	};
+};
diff --git a/board/theobroma-systems/lion_rk3368/lion_rk3368.c b/board/theobroma-systems/lion_rk3368/lion_rk3368.c
new file mode 100644
index 0000000000000000000000000000000000000000..73b14883c3178eb9f3ad2e2bf45d66f437e85b44
--- /dev/null
+++ b/board/theobroma-systems/lion_rk3368/lion_rk3368.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3368.h>
+#include <asm/arch/timer.h>
+#include <syscon.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int mach_cpu_init(void)
+{
+	return 0;
+}
+
+int board_init(void)
+{
+	return 0;
+}
diff --git a/board/theobroma-systems/puma_rk3399/README b/board/theobroma-systems/puma_rk3399/README
index 250e3459a3a6e4ac37356ee4a8a110bb16ce9e2a..214281a32990e25c573c8d39ba79f1100f5e8972 100644
--- a/board/theobroma-systems/puma_rk3399/README
+++ b/board/theobroma-systems/puma_rk3399/README
@@ -37,7 +37,7 @@ Compile the ATF
 
   > cd arm-trusted-firmware
   > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl31
-  > cp build/rk3399/release/bl31.bin ../u-boot
+  > cp build/rk3399/release/bl31.bin ../u-boot/bl31-rk3399.bin
 
 Compile the M0 firmware
 =======================
diff --git a/board/theobroma-systems/puma_rk3399/fit_spl_atf.its b/board/theobroma-systems/puma_rk3399/fit_spl_atf.its
index f93c2519272d4987784c256c1e6615cd4e7eff89..520f846d66a51bc56b0bcbc0f990e5415d306db8 100644
--- a/board/theobroma-systems/puma_rk3399/fit_spl_atf.its
+++ b/board/theobroma-systems/puma_rk3399/fit_spl_atf.its
@@ -13,7 +13,7 @@
 	#address-cells = <1>;
 
 	images {
-		uboot@1 {
+		uboot {
 			description = "U-Boot (64-bit)";
 			data = /incbin/("../../../u-boot-nodtb.bin");
 			type = "standalone";
@@ -21,23 +21,23 @@
 			compression = "none";
 			load = <0x00200000>;
 		};
-		atf@1 {
+		atf {
 			description = "ARM Trusted Firmware";
-			data = /incbin/("../../../bl31.bin");
+			data = /incbin/("../../../bl31-rk3399.bin");
 			type = "firmware";
 			arch = "arm64";
 			compression = "none";
 			load = <0x00001000>;
 			entry = <0x00001000>;
 		};
-		pmu@1 {
+		pmu {
 		        description = "Cortex-M0 firmware";
 			data = /incbin/("../../../rk3399m0.bin");
 			type = "pmu-firmware";
 			compression = "none";
 			load = <0xff8c0000>;
                 };
-		fdt@1 {
+		fdt {
 			description = "RK3399-Q7 (Puma) flat device-tree";
 			data = /incbin/("../../../u-boot.dtb");
 			type = "flat_dt";
@@ -46,12 +46,12 @@
 	};
 
 	configurations {
-		default = "conf@1";
-		conf@1 {
+		default = "conf";
+		conf {
 			description = "Theobroma Systems RK3399-Q7 (Puma) SoM";
-			firmware = "uboot@1";
-			loadables = "atf@1";
-			fdt = "fdt@1";
+			firmware = "uboot";
+			loadables = "atf";
+			fdt = "fdt";
 		};
 	};
 };
diff --git a/common/Makefile b/common/Makefile
index 60681c845cc205d870fcd3238c3853eb37e38389..3ee7a6b18b9d08d2611d99f9204d8567a1c4f3f5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -53,7 +53,7 @@ obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
 obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
 
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
-obj-$(CONFIG_$(SPL_)OF_LIBFDT) += fdt_support.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
 
 obj-$(CONFIG_MII) += miiphyutil.o
 obj-$(CONFIG_CMD_MII) += miiphyutil.o
@@ -96,7 +96,7 @@ obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
 obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
 obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
-obj-$(CONFIG_SPL_OF_LIBFDT) += fdt_support.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
 ifdef CONFIG_SPL_USB_HOST_SUPPORT
 obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o
 obj-$(CONFIG_USB_STORAGE) += usb_storage.o
@@ -146,10 +146,10 @@ endif
 endif
 obj-y += image.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
-obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o
-obj-$(CONFIG_$(SPL_)FIT) += image-fit.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
+obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
 obj-$(CONFIG_FIT_EMBED) += boot_fit.o common_fit.o
-obj-$(CONFIG_$(SPL_)FIT_SIGNATURE) += image-sig.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o
 obj-$(CONFIG_IO_TRACE) += iotrace.o
 obj-y += memsize.o
 obj-y += stdio.o
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 4de81392b0260464e30bcb67265ed6b598e7c279..51768575064dbc0ed4a8033c0b4bc581368d1017 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -18,6 +18,16 @@ config SPL
 
 if SPL
 
+config SPL_LDSCRIPT
+	string "Linker script for the SPL stage"
+	default "arch/$(ARCH)/cpu/u-boot-spl.lds"
+	depends on SPL
+	help
+	  The SPL stage will usually require a different linker-script
+	  (as it runs from a different memory region) than the regular
+	  U-Boot stage.	 Set this to the path of the linker-script to
+	  be used for SPL.
+
 config SPL_BOARD_INIT
 	bool "Call board-specific initialization in SPL"
 	help
@@ -25,6 +35,17 @@ config SPL_BOARD_INIT
 	  spl_board_init() from board_init_r(). This function should be
 	  provided by the board.
 
+config SPL_BOOTROM_SUPPORT
+        bool "Support returning to the BOOTROM"
+	help
+	  Some platforms (e.g. the Rockchip RK3368) provide support in their
+	  ROM for loading the next boot-stage after performing basic setup
+	  from the SPL stage.
+
+	  Enable this option, to return to the BOOTROM through the
+	  BOOT_DEVICE_BOOTROM (or fall-through to the next boot device in the
+	  boot device list, if not implemented for a given board)
+
 config SPL_RAW_IMAGE_SUPPORT
 	bool "Support SPL loading and booting of RAW images"
 	default n if (ARCH_MX6 && (SPL_MMC_SUPPORT || SPL_SATA_SUPPORT))
@@ -51,6 +72,15 @@ config SPL_SYS_MALLOC_SIMPLE
 	  this will make the SPL binary smaller at the cost of more heap
 	  usage as the *_simple malloc functions do not re-use free-ed mem.
 
+config TPL_SYS_MALLOC_SIMPLE
+	bool
+	prompt "Only use malloc_simple functions in the TPL"
+	help
+	  Say Y here to only use the *_simple malloc functions from
+	  malloc_simple.c, rather then using the versions from dlmalloc.c;
+	  this will make the TPL binary smaller at the cost of more heap
+	  usage as the *_simple malloc functions do not re-use free-ed mem.
+
 config SPL_STACK_R
 	bool "Enable SDRAM location for SPL stack"
 	help
@@ -573,14 +603,6 @@ config SPL_SPI_SUPPORT
 	  enable SPI drivers that are needed for other purposes also, such
 	  as a SPI PMIC.
 
-config SPL_TIMER_SUPPORT
-	bool "Support timer drivers"
-	help
-	  Enable support for timer drivers in SPL. These can be used to get
-	  a timer value when in SPL, or perhaps for implementing a delay
-	  function. This enables the drivers in drivers/timer as part of an
-	  SPL build.
-
 config SPL_USB_HOST_SUPPORT
 	bool "Support USB host drivers"
 	help
@@ -687,6 +709,74 @@ config TPL
 
 if TPL
 
+config TPL_LDSCRIPT
+        string "Linker script for the TPL stage"
+	depends on TPL
+	help
+	  The TPL stage will usually require a different linker-script
+	  (as it runs from a different memory region) than the regular
+	  U-Boot stage.  Set this to the path of the linker-script to
+	  be used for TPL.
+
+	  May be left empty to trigger the Makefile infrastructure to
+	  fall back to the linker-script used for the SPL stage.
+
+config TPL_NEEDS_SEPARATE_TEXT_BASE
+        bool "TPL needs a separate text-base"
+	default n
+	depends on TPL
+	help
+	  Enable, if the TPL stage should not inherit its text-base
+	  from the SPL stage.  When enabled, a base address for the
+	  .text sections of the TPL stage has to be set below.
+
+config TPL_NEEDS_SEPARATE_STACK
+        bool "TPL needs a separate initial stack-pointer"
+	default n
+	depends on TPL
+	help
+	  Enable, if the TPL stage should not inherit its initial
+	  stack-pointer from the settings for the SPL stage.
+
+config TPL_TEXT_BASE
+        hex "Base address for the .text section of the TPL stage"
+	depends on TPL_NEEDS_SEPARATE_TEXT_BASE
+	help
+	  The base address for the .text section of the TPL stage.
+
+config TPL_MAX_SIZE
+        int "Maximum size (in bytes) for the TPL stage"
+	default 0
+	depends on TPL
+	help
+	  The maximum size (in bytes) of the TPL stage.
+
+config TPL_STACK
+        hex "Address of the initial stack-pointer for the TPL stage"
+	depends on TPL_NEEDS_SEPARATE_STACK
+	help
+	  The address of the initial stack-pointer for the TPL stage.
+	  Usually this will be the (aligned) top-of-stack.
+
+config TPL_BOOTROM_SUPPORT
+        bool "Support returning to the BOOTROM (from TPL)"
+	help
+	  Some platforms (e.g. the Rockchip RK3368) provide support in their
+	  ROM for loading the next boot-stage after performing basic setup
+	  from the TPL stage.
+
+	  Enable this option, to return to the BOOTROM through the
+	  BOOT_DEVICE_BOOTROM (or fall-through to the next boot device in the
+	  boot device list, if not implemented for a given board)
+
+config TPL_DRIVERS_MISC_SUPPORT
+	bool "Support misc drivers in TPL"
+	help
+	  Enable miscellaneous drivers in TPL. These drivers perform various
+	  tasks that don't fall nicely into other categories, Enable this
+	  option to build the drivers in drivers/misc as part of an TPL
+	  build, for those that support building in TPL (not all drivers do).
+
 config TPL_ENV_SUPPORT
 	bool "Support an environment"
 	help
@@ -695,7 +785,7 @@ config TPL_ENV_SUPPORT
 config TPL_I2C_SUPPORT
 	bool "Support I2C"
 	help
-	  Enable support for the I2C bus in SPL. See SPL_I2C_SUPPORT for
+	  Enable support for the I2C bus in TPL. See SPL_I2C_SUPPORT for
 	  details.
 
 config TPL_LIBCOMMON_SUPPORT
@@ -725,24 +815,24 @@ config TPL_MMC_SUPPORT
 config TPL_NAND_SUPPORT
 	bool "Support NAND flash"
 	help
-	  Enable support for NAND in SPL. See SPL_NAND_SUPPORT for details.
+	  Enable support for NAND in TPL. See SPL_NAND_SUPPORT for details.
 
 config TPL_SERIAL_SUPPORT
 	bool "Support serial"
 	help
-	  Enable support for serial in SPL. See SPL_SERIAL_SUPPORT for
+	  Enable support for serial in TPL. See SPL_SERIAL_SUPPORT for
 	  details.
 
 config TPL_SPI_FLASH_SUPPORT
 	bool "Support SPI flash drivers"
 	help
-	  Enable support for using SPI flash in SPL. See SPL_SPI_FLASH_SUPPORT
+	  Enable support for using SPI flash in TPL. See SPL_SPI_FLASH_SUPPORT
 	  for details.
 
 config TPL_SPI_SUPPORT
 	bool "Support SPI drivers"
 	help
-	  Enable support for using SPI in SPL. See SPL_SPI_SUPPORT for
+	  Enable support for using SPI in TPL. See SPL_SPI_SUPPORT for
 	  details.
 
 endif # TPL
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 47a64dd7d0cdaca517e108eaa8cf4b4e82f27341..112b3e6022f12590e48be0e97d89278a727a5133 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -10,23 +10,24 @@
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
-obj-$(CONFIG_SPL_LOAD_FIT) += spl_fit.o
-obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o
-obj-$(CONFIG_SPL_XIP_SUPPORT) += spl_xip.o
-obj-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTROM_SUPPORT) += spl_bootrom.o
+obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit.o
+obj-$(CONFIG_$(SPL_TPL_)SPL_NOR_SUPPORT) += spl_nor.o
+obj-$(CONFIG_$(SPL_TPL_)SPL_XIP_SUPPORT) += spl_xip.o
+obj-$(CONFIG_$(SPL_TPL_)SPL_YMODEM_SUPPORT) += spl_ymodem.o
 ifndef CONFIG_SPL_UBI
-obj-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o
-obj-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o
+obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += spl_nand.o
+obj-$(CONFIG_$(SPL_TPL_)ONENAND_SUPPORT) += spl_onenand.o
 endif
-obj-$(CONFIG_SPL_UBI) += spl_ubi.o
-obj-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o
-obj-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o
-obj-$(CONFIG_SPL_ATF_SUPPORT) += spl_atf.o
-obj-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o
-obj-$(CONFIG_SPL_FAT_SUPPORT) += spl_fat.o
-obj-$(CONFIG_SPL_EXT_SUPPORT) += spl_ext.o
-obj-$(CONFIG_SPL_SATA_SUPPORT) += spl_sata.o
-obj-$(CONFIG_SPL_DFU_SUPPORT) += spl_dfu.o
-obj-$(CONFIG_SPL_SPI_LOAD) += spl_spi.o
-obj-$(CONFIG_SPL_RAM_SUPPORT) += spl_ram.o
+obj-$(CONFIG_$(SPL_TPL_)UBI) += spl_ubi.o
+obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o
+obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o
+obj-$(CONFIG_$(SPL_TPL_)ATF_SUPPORT) += spl_atf.o
+obj-$(CONFIG_$(SPL_TPL_)USB_SUPPORT) += spl_usb.o
+obj-$(CONFIG_$(SPL_TPL_)FAT_SUPPORT) += spl_fat.o
+obj-$(CONFIG_$(SPL_TPL_)EXT_SUPPORT) += spl_ext.o
+obj-$(CONFIG_$(SPL_TPL_)SATA_SUPPORT) += spl_sata.o
+obj-$(CONFIG_$(SPL_TPL_)DFU_SUPPORT) += spl_dfu.o
+obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o
+obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o
 endif
diff --git a/common/spl/spl.c b/common/spl/spl.c
index c56cc6f0ec330ba444c604f6e148be2f8922c955..d245cfc0d14d905586dd37fd1ac969dd5d6853fa 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -6,6 +6,7 @@
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
 #include <spl.h>
@@ -243,7 +244,7 @@ static int spl_common_init(bool setup_malloc)
 			return ret;
 		}
 	}
-	if (IS_ENABLED(CONFIG_SPL_DM)) {
+	if (CONFIG_IS_ENABLED(DM)) {
 		bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, "dm_spl");
 		/* With CONFIG_SPL_OF_PLATDATA, bring in all devices */
 		ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
@@ -424,7 +425,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 	      gd->malloc_ptr / 1024);
 #endif
 
-	if (IS_ENABLED(CONFIG_SPL_ATF_SUPPORT)) {
+	if (CONFIG_IS_ENABLED(ATF_SUPPORT)) {
 		debug("loaded - jumping to U-Boot via ATF BL31.\n");
 		bl31_entry();
 	}
@@ -486,7 +487,7 @@ ulong spl_relocate_stack_gd(void)
 	gd_t *new_gd;
 	ulong ptr = CONFIG_SPL_STACK_R_ADDR;
 
-#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_SPL_SYS_MALLOC_F_LEN
+#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_VAL(SYS_MALLOC_F_LEN)
 	if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
 		ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
 		gd->malloc_base = ptr;
diff --git a/common/spl/spl_bootrom.c b/common/spl/spl_bootrom.c
new file mode 100644
index 0000000000000000000000000000000000000000..6804246d03fd85a8a1dac308c88300cb3feadc4c
--- /dev/null
+++ b/common/spl/spl_bootrom.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Theobroma Systems Design und Consulting GmH
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+
+__weak void board_return_to_bootrom(void)
+{
+}
+
+static int spl_return_to_bootrom(struct spl_image_info *spl_image,
+				 struct spl_boot_device *bootdev)
+{
+	/*
+	 * If the board implements a way to return to its ROM (with
+	 * the expectation that the next stage of will be booted by
+	 * the ROM), it will implement board_return_to_bootrom() and
+	 * should not return from it.
+	 */
+	board_return_to_bootrom();
+	return false;
+}
+
+SPL_LOAD_IMAGE_METHOD("BOOTROM", 0, BOOT_DEVICE_BOOTROM, spl_return_to_bootrom);
diff --git a/configs/C29XPCIE_NAND_defconfig b/configs/C29XPCIE_NAND_defconfig
index a4651dee06b7f314016e6325ab1e71f6a6555a6d..316dbdab88831d4c96a6460f6eddb16f8447bebf 100644
--- a/configs/C29XPCIE_NAND_defconfig
+++ b/configs/C29XPCIE_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_EEPROM=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1010RDB-PA_36BIT_NAND_defconfig b/configs/P1010RDB-PA_36BIT_NAND_defconfig
index be98bdce6e4b2ed8b761b3938e6d01f18c4a78ec..db6259147cdd0a5ab5fdf296f3858c2f52d01dbb 100644
--- a/configs/P1010RDB-PA_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
@@ -18,9 +17,12 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_TPL=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1010RDB-PA_NAND_defconfig b/configs/P1010RDB-PA_NAND_defconfig
index cf8acd6aa6ae9d65ab4a0c91de6050bff8c1aa95..6f4fcda0be7f1bbe49f673af0db12ef511119b42 100644
--- a/configs/P1010RDB-PA_NAND_defconfig
+++ b/configs/P1010RDB-PA_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
@@ -17,9 +16,12 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_TPL=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1010RDB-PB_36BIT_NAND_defconfig b/configs/P1010RDB-PB_36BIT_NAND_defconfig
index 23c76ec3c2fb4112013fd1ea1e6182fc527a1548..c051563d11f72381e856c62c0770b35b37cd5b77 100644
--- a/configs/P1010RDB-PB_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
@@ -18,9 +17,12 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_TPL=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1010RDB-PB_NAND_defconfig b/configs/P1010RDB-PB_NAND_defconfig
index ef3adbdd9ee1702b995c5e7a4c158bc51a267b2b..99b2562a9767bd1a7997a539df3e3eedc3920a5d 100644
--- a/configs/P1010RDB-PB_NAND_defconfig
+++ b/configs/P1010RDB-PB_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
@@ -17,10 +16,12 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_TPL=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
 CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1020RDB-PC_36BIT_NAND_defconfig b/configs/P1020RDB-PC_36BIT_NAND_defconfig
index decf3197da4f9d87262c85f9779f67222c80887c..97b77a26caa9a6ae87a8a73cbea77c36a5e4fe5a 100644
--- a/configs/P1020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P1020RDB-PC_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -20,6 +19,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1020RDB-PC_NAND_defconfig b/configs/P1020RDB-PC_NAND_defconfig
index bb7c27c59682e604df4886dd568f34bd06fc7413..4f3a8f0cf7248a15f5d45eb5d7a8c154949842ba 100644
--- a/configs/P1020RDB-PC_NAND_defconfig
+++ b/configs/P1020RDB-PC_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1020RDB-PD_NAND_defconfig b/configs/P1020RDB-PD_NAND_defconfig
index db7b8707cfe781f43c3bffe20d53479909f27eb5..c2c01771071ea21f478c7555a441427b3e16d5a1 100644
--- a/configs/P1020RDB-PD_NAND_defconfig
+++ b/configs/P1020RDB-PD_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1021RDB-PC_36BIT_NAND_defconfig b/configs/P1021RDB-PC_36BIT_NAND_defconfig
index 4e62ac933a4510d9663ae3aeb20494e9e1bde02a..fa68c788a8184eaccf45fc7ae57c0abc4682e83b 100644
--- a/configs/P1021RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P1021RDB-PC_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -20,6 +19,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1021RDB-PC_NAND_defconfig b/configs/P1021RDB-PC_NAND_defconfig
index 3e1ed5214adf6503a33112fb8b9e28d8293af95c..feaf1c4e64596cb22ae4a2b4a34a813a9cb5208b 100644
--- a/configs/P1021RDB-PC_NAND_defconfig
+++ b/configs/P1021RDB-PC_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1022DS_36BIT_NAND_defconfig b/configs/P1022DS_36BIT_NAND_defconfig
index a8c5d825fe783f2ab1804bc1452e5ff35153600b..7e5358cfc7b722fada39160f88717236df1be739 100644
--- a/configs/P1022DS_36BIT_NAND_defconfig
+++ b/configs/P1022DS_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_REGINFO=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1022DS_NAND_defconfig b/configs/P1022DS_NAND_defconfig
index 6ae4068881f124d6ffb49de2435b1e277a337032..90d9fc632a2d1b5d6b9e25dc10dad9eac7e14922 100644
--- a/configs/P1022DS_NAND_defconfig
+++ b/configs/P1022DS_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_P1022DS=y
@@ -19,6 +18,7 @@ CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
 CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_REGINFO=y
 CONFIG_CMD_MMC=y
diff --git a/configs/P1024RDB_NAND_defconfig b/configs/P1024RDB_NAND_defconfig
index 70fc4565d891c1153462b36c0cad8ef3652b023e..070de7d77fa4289a0b75122a54db919f5877f058 100644
--- a/configs/P1024RDB_NAND_defconfig
+++ b/configs/P1024RDB_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P1025RDB_NAND_defconfig b/configs/P1025RDB_NAND_defconfig
index 7fd641482be8db29b89ea9eb1c027477379644c8..a3e00de171260c92d8c24ed6ca7f17644cf8f617 100644
--- a/configs/P1025RDB_NAND_defconfig
+++ b/configs/P1025RDB_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -20,6 +19,7 @@ CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
 CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
diff --git a/configs/P2020RDB-PC_36BIT_NAND_defconfig b/configs/P2020RDB-PC_36BIT_NAND_defconfig
index dd1027e9d8a1e7fa516198b77a7b7c7b64858cfa..192e5102d7e96a89b7f67d4bc09b088788a9aced 100644
--- a/configs/P2020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P2020RDB-PC_36BIT_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -21,6 +20,7 @@ CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
 CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/P2020RDB-PC_NAND_defconfig b/configs/P2020RDB-PC_NAND_defconfig
index 9d94662cee6b457a16a7fd69cbd76075ac7f17f7..b9510975ed3918c8c221d9f297346c810d06dbfc 100644
--- a/configs/P2020RDB-PC_NAND_defconfig
+++ b/configs/P2020RDB-PC_NAND_defconfig
@@ -2,7 +2,6 @@ CONFIG_PPC=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_TPL_LIBCOMMON_SUPPORT=y
 CONFIG_TPL_LIBGENERIC_SUPPORT=y
-CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_MPC85xx=y
 # CONFIG_CMD_ERRATA is not set
@@ -19,6 +18,8 @@ CONFIG_TPL=y
 CONFIG_TPL_ENV_SUPPORT=y
 CONFIG_TPL_I2C_SUPPORT=y
 CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT=y
+CONFIG_TPL_NAND_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig
index 34b9a56ee6cf1472dc68b758c4c588f0c5c98f99..f01b98da4d40f3b20994eee0fa0f887796ec4b12 100644
--- a/configs/chromebook_link64_defconfig
+++ b/configs/chromebook_link64_defconfig
@@ -27,7 +27,7 @@ CONFIG_SPL_NET_SUPPORT=y
 CONFIG_SPL_PCI_SUPPORT=y
 CONFIG_SPL_PCH_SUPPORT=y
 CONFIG_SPL_RTC_SUPPORT=y
-CONFIG_SPL_TIMER_SUPPORT=y
+CONFIG_SPL_TIMER=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_CPU=y
 # CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set
diff --git a/configs/evb-px5_defconfig b/configs/evb-px5_defconfig
index dae5094443a389c19e6fdb214d46b2b01daba90c..72e492faaa5886abc0907a5a17f8339db7961746 100644
--- a/configs/evb-px5_defconfig
+++ b/configs/evb-px5_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_TARGET_EVB_PX5=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3368-px5-evb"
diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig
index 8b9a288258b07b0ecdeff9a01b9afda7aed6c741..f4ad4c2c65eeaf5a4397ba13b41f9341f3b1ed1f 100644
--- a/configs/evb-rk3229_defconfig
+++ b/configs/evb-rk3229_defconfig
@@ -4,7 +4,7 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x800
 CONFIG_ROCKCHIP_RK322X=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_EVB_RK3229=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3229-evb"
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index fa3884c922edd2f7546c4b3c2c76679606f4bfdf..88a70cdcc67b16de029bc18d7ff498346ce8221e 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_EVB_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-evb"
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index 9d2b3199bc38b0e9b7147036f27e6a428e751cd1..2d6824284196cab2cc819bb12efd32237c50da3e 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_FENNEC_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-fennec"
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index 99a3f63b3e4c3d041989273617e00076b459e7be..b5408052efa1f10b5bfe543d4516038655fe1167 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_FIREFLY_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-firefly"
diff --git a/configs/geekbox_defconfig b/configs/geekbox_defconfig
index a1944b4ccf31ee32789073f56451e026fe2d2e45..0fd89d23e494cf9ade88d5ccc74fe10d5bd27439 100644
--- a/configs/geekbox_defconfig
+++ b/configs/geekbox_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_TARGET_GEEKBOX=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3368-geekbox"
diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..407bd440ffeb49fc3865502f98bb25e5d7cfbe1b
--- /dev/null
+++ b/configs/lion-rk3368_defconfig
@@ -0,0 +1,95 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3368=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0
+CONFIG_TPL_LIBCOMMON_SUPPORT=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_DEFAULT_DEVICE_TREE="rk3368-lion"
+CONFIG_SMBIOS_PRODUCT_NAME="sheep_rk3368"
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_SOURCE="board/theobroma-systems/lion_rk3368/fit_spl_atf.its"
+CONFIG_ENV_IS_IN_MMC=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_ARCH_EARLY_INIT_R=y
+CONFIG_SPL=y
+CONFIG_SPL_BOOTROM_SUPPORT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SPL_ATF_SUPPORT=y
+CONFIG_SPL_ATF_TEXT_BASE=0x10000
+CONFIG_TPL=y
+CONFIG_TPL_BOOTROM_SUPPORT=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_FASTBOOT=y
+CONFIG_ANDROID_BOOT_IMAGE=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent"
+CONFIG_TPL_OF_PLATDATA=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_TPL_DM=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_TPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ9031=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_RGMII=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_ROCKCHIP_RK3368=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+CONFIG_DEBUG_UART_BASE=0xFF180000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_SKIP_INIT=y
+CONFIG_ROCKCHIP_SPI=y
+CONFIG_SYSRESET=y
+CONFIG_TIMER=y
+CONFIG_SPL_TIMER=y
+CONFIG_TPL_TIMER=y
+CONFIG_ROCKCHIP_TIMER=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
+CONFIG_SMBIOS_MANUFACTURER="rockchip"
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index a7c796d062deeb0f16e0b9a5999e02f4a2cd90e9..3dd18726107f1f843830003adeb619b33e086c63 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_MIQI_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-miqi"
diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig
index 618d9839fdf4d6ea51cd5d4f69977eae36eee4f0..d09c92f7660e5885b63692ef177ac0ba14bb4b3b 100644
--- a/configs/phycore-rk3288_defconfig
+++ b/configs/phycore-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_PHYCORE_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-phycore-rdk"
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index cfa2205e8cf1926a32534f756db4ec926029a403..f68f988c16b5d8d4418e6c450692b472e2a17b7c 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_POPMETAL_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-popmetal"
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 0c40788e3fc0634ef8562de4e5e839bb14a9f978..44a15368ce3d5299222e8f489aba4b9d462338d6 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -26,7 +26,7 @@ CONFIG_SPL_NET_SUPPORT=y
 CONFIG_SPL_PCI_SUPPORT=y
 CONFIG_SPL_PCH_SUPPORT=y
 CONFIG_SPL_RTC_SUPPORT=y
-CONFIG_SPL_TIMER_SUPPORT=y
+CONFIG_SPL_TIMER=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_CPU=y
 # CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index cca855cfdf6788e1d51daabb697ac41b62f347be..570ff3153b5b956fcf40c07afed2efe6039e18be 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_ROCK2=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-rock2-square"
diff --git a/configs/rock_defconfig b/configs/rock_defconfig
index 2ad6a6c521dad44e7a576d8ec98e48fa80901805..eae284ca188c42aed32a7ae406a99ac744986c09 100644
--- a/configs/rock_defconfig
+++ b/configs/rock_defconfig
@@ -4,7 +4,8 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3188=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
+CONFIG_TPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_ROCK=y
 CONFIG_SPL_STACK_R_ADDR=0x60080000
 CONFIG_DEFAULT_DEVICE_TREE="rk3188-radxarock"
@@ -49,5 +50,6 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/sheep-rk3368_defconfig b/configs/sheep-rk3368_defconfig
index be00fade7e0a041f00904c95c15920cb521fdbd2..da6b93a28c25224564913dc701a18f2e14d4f9d1 100644
--- a/configs/sheep-rk3368_defconfig
+++ b/configs/sheep-rk3368_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x1000
 CONFIG_ROCKCHIP_RK3368=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3368-sheep"
 CONFIG_DEBUG_UART=y
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index be937998e62ad9faf0fa955623c261d0e1b215e8..7dde8ab9f542deb8dd325eea7aeab1f1e865d563 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -2,7 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
-CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_SPL_ROCKCHIP_BACK_TO_BROM=y
 CONFIG_TARGET_TINKER_RK3288=y
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-tinker"
diff --git a/doc/README.rockchip b/doc/README.rockchip
index dbeb8be6c09646fceaca9cb21e768bfcceb4eaca..12fec38139c827a2d4511b97a1694984d473ce15 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -130,7 +130,7 @@ load a second-level bootloader(ie. U-BOOT) as soon as it returns to bootrom.
 Therefore RK3288 has another loading sequence like RK3036. The option of
 U-Boot is controlled with this setting in U-Boot:
 
-	#define CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	#define CONFIG_SPL_ROCKCHIP_BACK_TO_BROM
 
 You can create the image via the following operations:
 
diff --git a/doc/device-tree-bindings/clock/rockchip,rk3368-dmc.txt b/doc/device-tree-bindings/clock/rockchip,rk3368-dmc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8e7357d53d3e25ba067f473429f98ae1aca10c44
--- /dev/null
+++ b/doc/device-tree-bindings/clock/rockchip,rk3368-dmc.txt
@@ -0,0 +1,67 @@
+RK3368 dynamic memory controller driver
+=======================================
+
+The RK3368 DMC (dynamic memory controller) driver supports setup/initialisation
+during TPL using configuration data from the DTS (i.e. OF_PLATDATA), based on
+the following key configuration data:
+  (a) a target-frequency (i.e. operating point) for the memory operation
+  (b) a speed-bin (as defined in JESD-79) for the DDR3 used in hardware
+  (c) a memory-schedule (i.e. mapping from physical addresses to the address
+      pins of the memory bus)
+
+Required properties
+-------------------
+
+- compatible: "rockchip,rk3368-dmc"
+- reg
+    protocol controller (PCTL) address and PHY controller (DDRPHY) address
+- rockchip,ddr-speed-bin
+    the DDR3 device's speed-bin (as specified according to JESD-79)
+        DDR3_800D (5-5-5)
+        DDR3_800E (6-6-6)
+        DDR3_1066E (6-6-6)
+        DDR3_1066F (7-7-7)
+        DDR3_1066G (8-8-8)
+        DDR3_1333F (7-7-7)
+        DDR3_1333G (8-8-8)
+        DDR3_1333H (9-9-9)
+        DDR3_1333J (10-10-10)
+        DDR3_1600G (8-8-8)
+        DDR3_1600H (9-9-9)
+        DDR3_1600J (10-10-10)
+        DDR3_1600K (11-11-11)
+        DDR3_1866J (10-10-10)
+        DDR3_1866K (11-11-11)
+        DDR3_1866L (12-12-12)
+        DDR3_1866M (13-13-13)
+        DDR3_2133K (11-11-11)
+        DDR3_2133L (12-12-12)
+        DDR3_2133M (13-13-13)
+        DDR3_2133N (14-14-14)
+- rockchip,ddr-frequency:
+    target DDR clock frequency in Hz (not all frequencies may be supported,
+    as there's some cooperation from the clock-driver required)
+- rockchip,memory-schedule:
+    controls the decoding of physical addresses to DRAM addressing (i.e. how
+    the physical address maps onto the address pins/chip-select of the device)
+	DMC_MSCH_CBDR: column -> bank -> device -> row
+	DMC_MSCH_CBRD: column -> band -> row -> device
+	DMC_MSCH_CRBD: column -> row -> band -> device
+
+Example (for DDR3-1600K and 800MHz)
+-----------------------------------
+
+	#include <dt-bindings/memory/rk3368-dmc.h>
+
+	dmc: dmc@ff610000 {
+	        u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3368-dmc";
+		reg = <0 0xff610000 0 0x400
+		       0 0xff620000 0 0x400>;
+	};
+
+	&dmc {
+		rockchip,ddr-speed-bin = <DDR3_1600K>;
+		rockchip,ddr-frequency = <800000000>;
+		rockchip,memory-schedule = <DMC_MSCH_CBRD>;
+	};
diff --git a/drivers/Makefile b/drivers/Makefile
index 0cbfa5d07b80af653476f487c4e87cf2edc2d75e..dab5c182c2c9d6d253a80e0045de96b2f9de75c1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -2,33 +2,35 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_$(SPL_TPL_)DM)	+= core/
-obj-$(CONFIG_$(SPL_)CLK)	+= clk/
-obj-$(CONFIG_$(SPL_)LED)	+= led/
-obj-$(CONFIG_$(SPL_)PHY)	+= phy/
-obj-$(CONFIG_$(SPL_)PINCTRL)	+= pinctrl/
-obj-$(CONFIG_$(SPL_)RAM)	+= ram/
+obj-$(CONFIG_$(SPL_TPL_)CLK) += clk/
+obj-$(CONFIG_$(SPL_TPL_)DM) += core/
+obj-$(CONFIG_$(SPL_TPL_)DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
+obj-$(CONFIG_$(SPL_TPL_)I2C_SUPPORT) += i2c/
+obj-$(CONFIG_$(SPL_TPL_)LED) += led/
+obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
+obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/
+obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL) += pinctrl/
+obj-$(CONFIG_$(SPL_TPL_)RAM) += ram/
+obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
+obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
+obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
+obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
 
+ifndef CONFIG_TPL_BUILD
 ifdef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
 obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
-obj-$(CONFIG_SPL_I2C_SUPPORT) += i2c/
 obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
-obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc/
 obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
 obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
 obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
 obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/
-obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/
-obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
 obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
-obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
 obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/
-obj-$(CONFIG_SPL_NAND_SUPPORT) += mtd/nand/
 obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/
-obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/
 obj-$(CONFIG_SPL_UBI) += mtd/ubispl/
 obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/
 obj-$(CONFIG_SPL_ETH_SUPPORT) += net/
@@ -37,7 +39,6 @@ obj-$(CONFIG_SPL_USBETH_SUPPORT) += net/phy/
 obj-$(CONFIG_SPL_PCI_SUPPORT) += pci/
 obj-$(CONFIG_SPL_PCH_SUPPORT) += pch/
 obj-$(CONFIG_SPL_RTC_SUPPORT) += rtc/
-obj-$(CONFIG_SPL_TIMER_SUPPORT) += timer/
 obj-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += usb/musb-new/
 obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
 obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
@@ -49,18 +50,13 @@ obj-$(CONFIG_SPL_SATA_SUPPORT) += ata/ scsi/
 obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
 obj-$(CONFIG_SPL_MMC_SUPPORT) += block/
 obj-$(CONFIG_SPL_FPGA_SUPPORT) += fpga/
+
+endif
 endif
 
 ifdef CONFIG_TPL_BUILD
 
-obj-$(CONFIG_TPL_I2C_SUPPORT) += i2c/
-obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
-obj-$(CONFIG_TPL_MMC_SUPPORT) += mmc/
 obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
-obj-$(CONFIG_TPL_NAND_SUPPORT) += mtd/nand/
-obj-$(CONFIG_TPL_SERIAL_SUPPORT) += serial/
-obj-$(CONFIG_TPL_SPI_FLASH_SUPPORT) += mtd/spi/
-obj-$(CONFIG_TPL_SPI_SUPPORT) += spi/
 
 endif
 
@@ -88,7 +84,6 @@ obj-y += scsi/
 obj-y += sound/
 obj-y += spmi/
 obj-y += sysreset/
-obj-y += timer/
 obj-y += tpm/
 obj-y += video/
 obj-y += watchdog/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 60bd706fa2bdb5edf3b3918c1d810a22e13ade17..7765148876d9613f6de1546da13d621aed26315a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -12,7 +12,7 @@ config CLK
 
 config SPL_CLK
 	bool "Enable clock support in SPL"
-	depends on CLK
+	depends on CLK && SPL_DM
 	help
 	  The clock subsystem adds a small amount of overhead to the image.
 	  If this is acceptable and you have a need to use clock drivers in
@@ -20,6 +20,16 @@ config SPL_CLK
 	  setting up clocks within SPL, and allows the same drivers to be
 	  used as U-Boot proper.
 
+config TPL_CLK
+	bool "Enable clock support in TPL"
+	depends on CLK && TPL_DM
+	help
+	  The clock subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use clock drivers in
+	  SPL, enable this option. It might provide a cleaner interface to
+	  setting up clocks within TPL, and allows the same drivers to be
+	  used as U-Boot proper.
+
 config CLK_BCM6345
 	bool "Clock controller driver for BCM6345"
 	depends on CLK && ARCH_BMIPS
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 159f285f9a2e76dabb2d63b0c60737f32f7f8048..b7735933be5c952fbfb5b91c4ede202663f853da 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -5,7 +5,7 @@
 # SPDX-License-Identifier:      GPL-2.0+
 #
 
-obj-$(CONFIG_CLK) += clk-uclass.o clk_fixed_rate.o
+obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index 5ecf5129d81c41c6a9b9f198f480a7ca16536799..83f4ae6ca394f5dad546c9037573f617b614d642 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -235,7 +235,7 @@ static ulong rockchip_mmc_get_clk(struct rk3036_cru *cru, uint clk_general_rate,
 	}
 
 	src_rate = mux == EMMC_SEL_24M ? OSC_HZ : clk_general_rate;
-	return DIV_TO_RATE(src_rate, div);
+	return DIV_TO_RATE(src_rate, div) / 2;
 }
 
 static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
@@ -247,10 +247,11 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate,
 	debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate);
 
 	/* mmc clock auto divide 2 in internal */
-	src_clk_div = (clk_general_rate / 2 + freq - 1) / freq;
+	src_clk_div = DIV_ROUND_UP(clk_general_rate / 2, freq);
 
-	if (src_clk_div > 0x7f) {
-		src_clk_div = (OSC_HZ / 2 + freq - 1) / freq;
+	if (src_clk_div > 128) {
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq);
+		assert(src_clk_div - 1 < 128);
 		mux = EMMC_SEL_24M;
 	} else {
 		mux = EMMC_SEL_GPLL;
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
index 6f3033287839d7f3f6f90ba506b51570a0dc8ba8..8c2c9bc1d87ca0350977f8e50863a3105d2efdaa 100644
--- a/drivers/clk/rockchip/clk_rk3188.c
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -71,9 +71,6 @@ enum {
 	SOCSTS_GPLL_LOCK	= 1 << 8,
 };
 
-#define RATE_TO_DIV(input_rate, output_rate) \
-	((input_rate) / (output_rate) - 1);
-
 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _nr, _no) {\
@@ -287,7 +284,7 @@ static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate,
 		return -EINVAL;
 	}
 
-	return DIV_TO_RATE(gclk_rate, div);
+	return DIV_TO_RATE(gclk_rate, div) / 2;
 }
 
 static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
@@ -296,7 +293,8 @@ static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
 	int src_clk_div;
 
 	debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
-	src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+	/* mmc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1;
 	assert(src_clk_div <= 0x3f);
 
 	switch (periph) {
@@ -350,8 +348,9 @@ static ulong rockchip_spi_get_clk(struct rk3188_cru *cru, uint gclk_rate,
 static ulong rockchip_spi_set_clk(struct rk3188_cru *cru, uint gclk_rate,
 				  int periph, uint freq)
 {
-	int src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+	int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
 
+	assert(src_clk_div < 128);
 	switch (periph) {
 	case SCLK_SPI0:
 		assert(src_clk_div <= SPI0_DIV_MASK);
@@ -400,8 +399,8 @@ static void rkclk_init(struct rk3188_cru *cru, struct rk3188_grf *grf,
 	 * reparent aclk_cpu_pre from apll to gpll
 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
 	 */
-	aclk_div = RATE_TO_DIV(GPLL_HZ, CPU_ACLK_HZ);
-	assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+	aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1;
+	assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
 
 	rk_clrsetreg(&cru->cru_clksel_con[0],
 		     CPU_ACLK_PLL_MASK << CPU_ACLK_PLL_SHIFT |
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index fdeb816e2316bb1d90a89d6a134875641151cd2b..d7f6a3c313e6c86143dc3931fc00196981d8b534 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -26,9 +26,6 @@ enum {
 	OUTPUT_MIN_HZ	= 24 * 1000000,
 };
 
-#define RATE_TO_DIV(input_rate, output_rate) \
-	((input_rate) / (output_rate) - 1);
-
 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
@@ -239,7 +236,7 @@ static ulong rockchip_mmc_get_clk(struct rk322x_cru *cru, uint clk_general_rate,
 	}
 
 	src_rate = mux == EMMC_SEL_24M ? OSC_HZ : clk_general_rate;
-	return DIV_TO_RATE(src_rate, div);
+	return DIV_TO_RATE(src_rate, div) / 2;
 }
 
 static ulong rockchip_mmc_set_clk(struct rk322x_cru *cru, uint clk_general_rate,
@@ -250,11 +247,12 @@ static ulong rockchip_mmc_set_clk(struct rk322x_cru *cru, uint clk_general_rate,
 
 	debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate);
 
-	/* mmc clock auto divide 2 in internal */
-	src_clk_div = (clk_general_rate / 2 + freq - 1) / freq;
+	/* mmc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(clk_general_rate / 2, freq);
 
-	if (src_clk_div > 0x7f) {
-		src_clk_div = (OSC_HZ / 2 + freq - 1) / freq;
+	if (src_clk_div > 128) {
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq);
+		assert(src_clk_div - 1 < 128);
 		mux = EMMC_SEL_24M;
 	} else {
 		mux = EMMC_SEL_GPLL;
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 792ee76509f068223ff1de75850714583a0f7696..478195b10b0eb6175b86a8a0b599c1011af3671e 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -118,9 +118,6 @@ enum {
 	SOCSTS_NPLL_LOCK	= 1 << 9,
 };
 
-#define RATE_TO_DIV(input_rate, output_rate) \
-	((input_rate) / (output_rate) - 1);
-
 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _nr, _no) {\
@@ -530,10 +527,12 @@ static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint gclk_rate,
 	int mux;
 
 	debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
-	src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+	/* mmc clock default div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq);
 
 	if (src_clk_div > 0x3f) {
-		src_clk_div = RATE_TO_DIV(OSC_HZ, freq);
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, freq);
+		assert(src_clk_div < 0x40);
 		mux = EMMC_PLL_SELECT_24MHZ;
 		assert((int)EMMC_PLL_SELECT_24MHZ ==
 		       (int)MMC0_PLL_SELECT_24MHZ);
@@ -607,7 +606,8 @@ static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint gclk_rate,
 	int src_clk_div;
 
 	debug("%s: clk_general_rate=%u\n", __func__, gclk_rate);
-	src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+	src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
+	assert(src_clk_div < 128);
 	switch (periph) {
 	case SCLK_SPI0:
 		rk_clrsetreg(&cru->cru_clksel_con[25],
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 2065a8a65b9f2a6679bca027b7d157988b088818..c3a6650de0328d563bf869582b596c043d75d862 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -412,9 +412,9 @@ static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
 
 	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
 	    == CLK_EMMC_PLL_SEL_24M)
-		return DIV_TO_RATE(OSC_HZ, div);
+		return DIV_TO_RATE(OSC_HZ, div) / 2;
 	else
-		return DIV_TO_RATE(GPLL_HZ, div);
+		return DIV_TO_RATE(GPLL_HZ, div) / 2;
 }
 
 static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
@@ -436,11 +436,12 @@ static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
 		return -EINVAL;
 	}
 	/* Select clk_sdmmc/emmc source from GPLL by default */
-	src_clk_div = GPLL_HZ / set_rate;
+	/* mmc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
 
 	if (src_clk_div > 127) {
 		/* use 24MHz source for 400KHz clock */
-		src_clk_div = OSC_HZ / set_rate;
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
 		rk_clrsetreg(&cru->clksel_con[con_id],
 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 			     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c
index e1d9aeb8e54db9ef3254482230b76bc318788f7c..2be1f572d7212a166cf96680fb26b71464d360ba 100644
--- a/drivers/clk/rockchip/clk_rk3368.c
+++ b/drivers/clk/rockchip/clk_rk3368.c
@@ -1,13 +1,16 @@
 /*
  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
  * Author: Andy Yan <andy.yan@rock-chips.com>
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  * SPDX-License-Identifier:	GPL-2.0
  */
 
 #include <common.h>
 #include <clk-uclass.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <errno.h>
+#include <mapmem.h>
 #include <syscon.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cru_rk3368.h>
@@ -18,6 +21,12 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+struct rk3368_clk_plat {
+	struct dtd_rockchip_rk3368_cru dtd;
+};
+#endif
+
 struct pll_div {
 	u32 nr;
 	u32 nf;
@@ -30,9 +39,6 @@ struct pll_div {
 #define GPLL_HZ		(576 * 1000 * 1000)
 #define CPLL_HZ		(400 * 1000 * 1000)
 
-#define RATE_TO_DIV(input_rate, output_rate) \
-		((input_rate) / (output_rate) - 1);
-
 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _nr, _no) { \
@@ -41,10 +47,16 @@ struct pll_div {
 		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \
 		       "divisors on line " __stringify(__LINE__));
 
+#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
 static const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2);
 static const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2);
+#if !defined(CONFIG_TPL_BUILD)
 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2);
 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6);
+#endif
+#endif
+
+static ulong rk3368_clk_get_rate(struct clk *clk);
 
 /* Get pll rate by id */
 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru,
@@ -73,8 +85,9 @@ static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru,
 	}
 }
 
+#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
 static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id,
-			 const struct pll_div *div, bool has_bwadj)
+			 const struct pll_div *div)
 {
 	struct rk3368_pll *pll = &cru->pll[pll_id];
 	/* All PLLs have same VCO and output frequency range restrictions*/
@@ -92,6 +105,12 @@ static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id,
 		     ((div->nr - 1) << PLL_NR_SHIFT) |
 		     ((div->no - 1) << PLL_OD_SHIFT));
 	writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1);
+	/*
+	 * BWADJ should be set to NF / 2 to ensure the nominal bandwidth.
+	 * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment".
+	 */
+	clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
+
 	udelay(10);
 
 	/* return from reset */
@@ -106,15 +125,23 @@ static int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id,
 
 	return 0;
 }
+#endif
 
+#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
 static void rkclk_init(struct rk3368_cru *cru)
 {
 	u32 apllb, aplll, dpll, cpll, gpll;
 
-	rkclk_set_pll(cru, APLLB, &apll_b_init_cfg, false);
-	rkclk_set_pll(cru, APLLL, &apll_l_init_cfg, false);
-	rkclk_set_pll(cru, GPLL, &gpll_init_cfg, false);
-	rkclk_set_pll(cru, CPLL, &cpll_init_cfg, false);
+	rkclk_set_pll(cru, APLLB, &apll_b_init_cfg);
+	rkclk_set_pll(cru, APLLL, &apll_l_init_cfg);
+#if !defined(CONFIG_TPL_BUILD)
+	/*
+	 * If we plan to return to the boot ROM, we can't increase the
+	 * GPLL rate from the SPL stage.
+	 */
+	rkclk_set_pll(cru, GPLL, &gpll_init_cfg);
+	rkclk_set_pll(cru, CPLL, &cpll_init_cfg);
+#endif
 
 	apllb = rkclk_pll_get_rate(cru, APLLB);
 	aplll = rkclk_pll_get_rate(cru, APLLL);
@@ -125,17 +152,19 @@ static void rkclk_init(struct rk3368_cru *cru)
 	debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n",
 	       __func__, apllb, aplll, dpll, cpll, gpll);
 }
+#endif
 
+#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
 static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
 {
 	u32 div, con, con_id, rate;
 	u32 pll_rate;
 
 	switch (clk_id) {
-	case SCLK_SDMMC:
+	case HCLK_SDMMC:
 		con_id = 50;
 		break;
-	case SCLK_EMMC:
+	case HCLK_EMMC:
 		con_id = 51;
 		break;
 	case SCLK_SDIO0:
@@ -146,7 +175,7 @@ static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
 	}
 
 	con = readl(&cru->clksel_con[con_id]);
-	switch ((con & MMC_PLL_SEL_MASK) >> MMC_PLL_SEL_SHIFT) {
+	switch (con & MMC_PLL_SEL_MASK) {
 	case MMC_PLL_SEL_GPLL:
 		pll_rate = rkclk_pll_get_rate(cru, GPLL);
 		break;
@@ -154,6 +183,8 @@ static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
 		pll_rate = OSC_HZ;
 		break;
 	case MMC_PLL_SEL_CPLL:
+		pll_rate = rkclk_pll_get_rate(cru, CPLL);
+		break;
 	case MMC_PLL_SEL_USBPHY_480M:
 	default:
 		return -EINVAL;
@@ -161,23 +192,76 @@ static ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id)
 	div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT;
 	rate = DIV_TO_RATE(pll_rate, div);
 
+	debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate);
 	return rate >> 1;
 }
 
-static ulong rk3368_mmc_set_clk(struct rk3368_cru *cru,
-				ulong clk_id, ulong rate)
+static ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk,
+						  ulong rate,
+						  u32 *best_mux,
+						  u32 *best_div)
+{
+	int i;
+	ulong best_rate = 0;
+	const ulong MHz = 1000000;
+	const struct {
+		u32 mux;
+		ulong rate;
+	} parents[] = {
+		{ .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ },
+		{ .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ },
+		{ .mux = MMC_PLL_SEL_24M,  .rate = 24 * MHz }
+	};
+
+	debug("%s: target rate %ld\n", __func__, rate);
+	for (i = 0; i < ARRAY_SIZE(parents); ++i) {
+		/*
+		 * Find the largest rate no larger than the target-rate for
+		 * the current parent.
+		 */
+		ulong parent_rate = parents[i].rate;
+		u32 div = DIV_ROUND_UP(parent_rate, rate);
+		u32 adj_div = div;
+		ulong new_rate = parent_rate / adj_div;
+
+		debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n",
+		      __func__, rate, parents[i].mux, parents[i].rate, div);
+
+		/* Skip, if not representable */
+		if ((div - 1) > MMC_CLK_DIV_MASK)
+			continue;
+
+		/* Skip, if we already have a better (or equal) solution */
+		if (new_rate <= best_rate)
+			continue;
+
+		/* This is our new best rate. */
+		best_rate = new_rate;
+		*best_mux = parents[i].mux;
+		*best_div = div - 1;
+	}
+
+	debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n",
+	      __func__, *best_mux, *best_div, best_rate);
+
+	return best_rate;
+}
+
+static ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate)
 {
-	u32 div;
-	u32 con_id;
-	u32 gpll_rate = rkclk_pll_get_rate(cru, GPLL);
+	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3368_cru *cru = priv->cru;
+	ulong clk_id = clk->id;
+	u32 con_id, mux = 0, div = 0;
 
-	div = RATE_TO_DIV(gpll_rate, rate << 1);
+	/* Find the best parent and rate */
+	rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div);
 
 	switch (clk_id) {
-	case SCLK_SDMMC:
+	case HCLK_SDMMC:
 		con_id = 50;
 		break;
-	case SCLK_EMMC:
+	case HCLK_EMMC:
 		con_id = 51;
 		break;
 	case SCLK_SDIO0:
@@ -187,33 +271,154 @@ static ulong rk3368_mmc_set_clk(struct rk3368_cru *cru,
 		return -EINVAL;
 	}
 
-	if (div > 0x3f) {
-		div = RATE_TO_DIV(OSC_HZ, rate);
-		rk_clrsetreg(&cru->clksel_con[con_id],
-			     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
-			     (MMC_PLL_SEL_24M << MMC_PLL_SEL_SHIFT) |
-			     (div << MMC_CLK_DIV_SHIFT));
-	} else {
-		rk_clrsetreg(&cru->clksel_con[con_id],
-			     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
-			     (MMC_PLL_SEL_GPLL << MMC_PLL_SEL_SHIFT) |
-			     div << MMC_CLK_DIV_SHIFT);
-	}
+	rk_clrsetreg(&cru->clksel_con[con_id],
+		     MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK,
+		     mux | div);
 
 	return rk3368_mmc_get_clk(cru, clk_id);
 }
+#endif
+
+#if IS_ENABLED(CONFIG_TPL_BUILD)
+static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate)
+{
+	const struct pll_div *dpll_cfg = NULL;
+	const ulong MHz = 1000000;
+
+	/* Fout = ((Fin /NR) * NF )/ NO */
+	static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1);
+	static const struct pll_div dpll_1332 =	PLL_DIVISORS(1332 * MHz, 2, 1);
+	static const struct pll_div dpll_1600 =	PLL_DIVISORS(1600 * MHz, 3, 2);
+
+	switch (set_rate) {
+	case 1200*MHz:
+		dpll_cfg = &dpll_1200;
+		break;
+	case 1332*MHz:
+		dpll_cfg = &dpll_1332;
+		break;
+	case 1600*MHz:
+		dpll_cfg = &dpll_1600;
+		break;
+	default:
+		error("Unsupported SDRAM frequency!,%ld\n", set_rate);
+	}
+	rkclk_set_pll(cru, DPLL, dpll_cfg);
+
+	return set_rate;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
+static ulong rk3368_gmac_set_clk(struct rk3368_cru *cru,
+				 ulong clk_id, ulong set_rate)
+{
+	/*
+	 * This models the 'assigned-clock-parents = <&ext_gmac>' from
+	 * the DTS and switches to the 'ext_gmac' clock parent.
+	 */
+	rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK);
+	return set_rate;
+}
+#endif
+
+/*
+ * RK3368 SPI clocks have a common divider-width (7 bits) and a single bit
+ * to select either CPLL or GPLL as the clock-parent. The location within
+ * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
+ */
+
+struct spi_clkreg {
+	uint8_t reg;  /* CLKSEL_CON[reg] register in CRU */
+	uint8_t div_shift;
+	uint8_t sel_shift;
+};
+
+/*
+ * The entries are numbered relative to their offset from SCLK_SPI0.
+ */
+static const struct spi_clkreg spi_clkregs[] = {
+	[0] = { .reg = 45, .div_shift = 0, .sel_shift = 7, },
+	[1] = { .reg = 45, .div_shift = 8, .sel_shift = 15, },
+	[2] = { .reg = 46, .div_shift = 8, .sel_shift = 15, },
+};
+
+static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
+{
+	return (val >> shift) & ((1 << width) - 1);
+}
+
+static ulong rk3368_spi_get_clk(struct rk3368_cru *cru, ulong clk_id)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	u32 div, val;
+
+	switch (clk_id) {
+	case SCLK_SPI0 ... SCLK_SPI2:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	val = readl(&cru->clksel_con[spiclk->reg]);
+	div = extract_bits(val, 7, spiclk->div_shift);
+
+	debug("%s: div 0x%x\n", __func__, div);
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+	assert(src_clk_div < 127);
+
+	switch (clk_id) {
+	case SCLK_SPI0 ... SCLK_SPI2:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[spiclk->reg],
+		     ((0x7f << spiclk->div_shift) |
+		      (0x1 << spiclk->sel_shift)),
+		     ((src_clk_div << spiclk->div_shift) |
+		      (1 << spiclk->sel_shift)));
+
+	return rk3368_spi_get_clk(cru, clk_id);
+}
 
 static ulong rk3368_clk_get_rate(struct clk *clk)
 {
 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
 	ulong rate = 0;
 
-	debug("%s id:%ld\n", __func__, clk->id);
+	debug("%s: id %ld\n", __func__, clk->id);
 	switch (clk->id) {
+	case PLL_CPLL:
+		rate = rkclk_pll_get_rate(priv->cru, CPLL);
+		break;
+	case PLL_GPLL:
+		rate = rkclk_pll_get_rate(priv->cru, GPLL);
+		break;
+	case SCLK_SPI0 ... SCLK_SPI2:
+		rate = rk3368_spi_get_clk(priv->cru, clk->id);
+		break;
+#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
 	case HCLK_SDMMC:
 	case HCLK_EMMC:
 		rate = rk3368_mmc_get_clk(priv->cru, clk->id);
 		break;
+#endif
 	default:
 		return -ENOENT;
 	}
@@ -223,15 +428,31 @@ static ulong rk3368_clk_get_rate(struct clk *clk)
 
 static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
 {
-	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
+	__maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
 	ulong ret = 0;
 
 	debug("%s id:%ld rate:%ld\n", __func__, clk->id, rate);
 	switch (clk->id) {
-	case SCLK_SDMMC:
-	case SCLK_EMMC:
-		ret = rk3368_mmc_set_clk(priv->cru, clk->id, rate);
+	case SCLK_SPI0 ... SCLK_SPI2:
+		ret = rk3368_spi_set_clk(priv->cru, clk->id, rate);
 		break;
+#if IS_ENABLED(CONFIG_TPL_BUILD)
+	case CLK_DDR:
+		ret = rk3368_ddr_set_clk(priv->cru, rate);
+		break;
+#endif
+#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC_SUPPORT)
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+		ret = rk3368_mmc_set_clk(clk, rate);
+		break;
+#endif
+#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
+	case SCLK_MAC:
+		/* select the external clock */
+		ret = rk3368_gmac_set_clk(priv->cru, clk->id, rate);
+		break;
+#endif
 	default:
 		return -ENOENT;
 	}
@@ -246,18 +467,26 @@ static struct clk_ops rk3368_clk_ops = {
 
 static int rk3368_clk_probe(struct udevice *dev)
 {
-	struct rk3368_clk_priv *priv = dev_get_priv(dev);
+	struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3368_clk_plat *plat = dev_get_platdata(dev);
 
+	priv->cru = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
+#endif
+#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD)
 	rkclk_init(priv->cru);
+#endif
 
 	return 0;
 }
 
 static int rk3368_clk_ofdata_to_platdata(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3368_clk_priv *priv = dev_get_priv(dev);
 
 	priv->cru = (struct rk3368_cru *)devfdt_get_addr(dev);
+#endif
 
 	return 0;
 }
@@ -284,6 +513,9 @@ U_BOOT_DRIVER(rockchip_rk3368_cru) = {
 	.id		= UCLASS_CLK,
 	.of_match	= rk3368_clk_ids,
 	.priv_auto_alloc_size = sizeof(struct rk3368_clk_priv),
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	.platdata_auto_alloc_size = sizeof(struct rk3368_clk_plat),
+#endif
 	.ofdata_to_platdata = rk3368_clk_ofdata_to_platdata,
 	.ops		= &rk3368_clk_ops,
 	.bind		= rk3368_clk_bind,
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 53d2a3f85dad63e43ce17446d326809305bb1e04..3edafea140073a5f7c53df3af07a956cb195ae8f 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -676,8 +676,8 @@ static ulong rk3399_spi_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
 	const struct spi_clkreg *spiclk = NULL;
 	int src_clk_div;
 
-	src_clk_div = RATE_TO_DIV(GPLL_HZ, hz);
-	assert(src_clk_div < 127);
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 128);
 
 	switch (clk_id) {
 	case SCLK_SPI1 ... SCLK_SPI5:
@@ -750,18 +750,21 @@ static ulong rk3399_mmc_get_clk(struct rk3399_cru *cru, uint clk_id)
 	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 		con = readl(&cru->clksel_con[16]);
+		/* dwmmc controller have internal div 2 */
+		div = 2;
 		break;
 	case SCLK_EMMC:
 		con = readl(&cru->clksel_con[21]);
+		div = 1;
 		break;
 	default:
 		return -EINVAL;
 	}
-	div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
 
+	div *= (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
 	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
 			== CLK_EMMC_PLL_SEL_24M)
-		return DIV_TO_RATE(24*1000*1000, div);
+		return DIV_TO_RATE(OSC_HZ, div);
 	else
 		return DIV_TO_RATE(GPLL_HZ, div);
 }
@@ -776,11 +779,13 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
 	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 		/* Select clk_sdmmc source from GPLL by default */
-		src_clk_div = GPLL_HZ / set_rate;
+		/* mmc clock defaulg div 2 internal, provide double in cru */
+		src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
 
-		if (src_clk_div > 127) {
+		if (src_clk_div > 128) {
 			/* use 24MHz source for 400KHz clock */
-			src_clk_div = 24*1000*1000 / set_rate;
+			src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+			assert(src_clk_div - 1 < 128);
 			rk_clrsetreg(&cru->clksel_con[16],
 				     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
 				     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
@@ -794,8 +799,8 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
 		break;
 	case SCLK_EMMC:
 		/* Select aclk_emmc source from GPLL */
-		src_clk_div = GPLL_HZ / aclk_emmc;
-		assert(src_clk_div - 1 < 31);
+		src_clk_div = DIV_ROUND_UP(GPLL_HZ , aclk_emmc);
+		assert(src_clk_div - 1 < 32);
 
 		rk_clrsetreg(&cru->clksel_con[21],
 			     ACLK_EMMC_PLL_SEL_MASK | ACLK_EMMC_DIV_CON_MASK,
@@ -803,8 +808,8 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
 			     (src_clk_div - 1) << ACLK_EMMC_DIV_CON_SHIFT);
 
 		/* Select clk_emmc source from GPLL too */
-		src_clk_div = GPLL_HZ / set_rate;
-		assert(src_clk_div - 1 < 127);
+		src_clk_div = DIV_ROUND_UP(GPLL_HZ, set_rate);
+		assert(src_clk_div - 1 < 128);
 
 		rk_clrsetreg(&cru->clksel_con[22],
 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c
index 818293dfe87ad178aaed0ab2fd0fbb9f4c95516a..cf966bbdc339924eba4ac8e73b630f41da53d5e2 100644
--- a/drivers/clk/rockchip/clk_rv1108.c
+++ b/drivers/clk/rockchip/clk_rv1108.c
@@ -25,9 +25,6 @@ enum {
 	OUTPUT_MIN_HZ	= 24 * 1000000,
 };
 
-#define RATE_TO_DIV(input_rate, output_rate) \
-	((input_rate) / (output_rate) - 1);
-
 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
 
 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index f8b19a48cc0aeea8f1393f9de38ee1b9b6a67e35..7afef1f9a3f6f273894ca9207d7de4a274ba0fa6 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -97,7 +97,17 @@ config REGMAP
 
 config SPL_REGMAP
 	bool "Support register maps in SPL"
-	depends on DM
+	depends on SPL_DM
+	help
+	  Hardware peripherals tend to have one or more sets of registers
+	  which can be accessed to control the hardware. A register map
+	  models this with a simple read/write interface. It can in principle
+	  support any bus type (I2C, SPI) but so far this only supports
+	  direct memory access.
+
+config TPL_REGMAP
+	bool "Support register maps in TPL"
+	depends on TPL_DM
 	help
 	  Hardware peripherals tend to have one or more sets of registers
 	  which can be accessed to control the hardware. A register map
@@ -116,7 +126,16 @@ config SYSCON
 
 config SPL_SYSCON
 	bool "Support system controllers in SPL"
-	depends on REGMAP
+	depends on SPL_REGMAP
+	help
+	  Many SoCs have a number of system controllers which are dealt with
+	  as a group by a single driver. Some common functionality is provided
+	  by this uclass, including accessing registers via regmap and
+	  assigning a unique number to each.
+
+config TPL_SYSCON
+	bool "Support system controllers in TPL"
+	depends on TPL_REGMAP
 	help
 	  Many SoCs have a number of system controllers which are dealt with
 	  as a group by a single driver. Some common functionality is provided
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index fd2d4de0c832d6a83006a454c0277c296ccaad99..3d68c70b57c5e6549e5d1f2f6f4ba5b81a060707 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -9,8 +9,8 @@ obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE)	+= device-remove.o
 obj-$(CONFIG_$(SPL_)SIMPLE_BUS)	+= simple-bus.o
 obj-$(CONFIG_DM)	+= dump.o
-obj-$(CONFIG_$(SPL_)REGMAP)	+= regmap.o
-obj-$(CONFIG_$(SPL_)SYSCON)	+= syscon-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)REGMAP)	+= regmap.o
+obj-$(CONFIG_$(SPL_TPL_)SYSCON)	+= syscon-uclass.o
 obj-$(CONFIG_OF_LIVE) += of_access.o of_addr.o
 ifndef CONFIG_DM_DEV_READ_INLINE
 obj-$(CONFIG_OF_CONTROL) += read.o
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index c9f9e839bad7ac276491f08d810f68c81683e24c..586ccbff0a76462efde19bb85c27b05fba6f4acb 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -16,6 +16,7 @@
 #include <asm/arch/clock.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/grf_rk3288.h>
+#include <asm/arch/grf_rk3368.h>
 #include <asm/arch/grf_rk3399.h>
 #include <dm/pinctrl.h>
 #include <dt-bindings/clock/rk3288-cru.h>
@@ -83,6 +84,38 @@ static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
+static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+{
+	struct rk3368_grf *grf;
+	int clk;
+	enum {
+		RK3368_GMAC_CLK_SEL_2_5M = 2 << 4,
+		RK3368_GMAC_CLK_SEL_25M = 3 << 4,
+		RK3368_GMAC_CLK_SEL_125M = 0 << 4,
+		RK3368_GMAC_CLK_SEL_MASK = GENMASK(5, 4),
+	};
+
+	switch (priv->phydev->speed) {
+	case 10:
+		clk = RK3368_GMAC_CLK_SEL_2_5M;
+		break;
+	case 100:
+		clk = RK3368_GMAC_CLK_SEL_25M;
+		break;
+	case 1000:
+		clk = RK3368_GMAC_CLK_SEL_125M;
+		break;
+	default:
+		debug("Unknown phy speed: %d\n", priv->phydev->speed);
+		return -EINVAL;
+	}
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	rk_clrsetreg(&grf->soc_con15, RK3368_GMAC_CLK_SEL_MASK, clk);
+
+	return 0;
+}
+
 static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 {
 	struct rk3399_grf_regs *grf;
@@ -129,6 +162,44 @@ static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
 		     pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT);
 }
 
+static void rk3368_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
+{
+	struct rk3368_grf *grf;
+	enum {
+		RK3368_GMAC_PHY_INTF_SEL_RGMII = 1 << 9,
+		RK3368_GMAC_PHY_INTF_SEL_MASK = GENMASK(11, 9),
+		RK3368_RMII_MODE_MASK  = BIT(6),
+		RK3368_RMII_MODE       = BIT(6),
+	};
+	enum {
+		RK3368_RXCLK_DLY_ENA_GMAC_MASK = BIT(15),
+		RK3368_RXCLK_DLY_ENA_GMAC_DISABLE = 0,
+		RK3368_RXCLK_DLY_ENA_GMAC_ENABLE = BIT(15),
+		RK3368_TXCLK_DLY_ENA_GMAC_MASK = BIT(7),
+		RK3368_TXCLK_DLY_ENA_GMAC_DISABLE = 0,
+		RK3368_TXCLK_DLY_ENA_GMAC_ENABLE = BIT(7),
+		RK3368_CLK_RX_DL_CFG_GMAC_SHIFT = 8,
+		RK3368_CLK_RX_DL_CFG_GMAC_MASK = GENMASK(14, 8),
+		RK3368_CLK_TX_DL_CFG_GMAC_SHIFT = 0,
+		RK3368_CLK_TX_DL_CFG_GMAC_MASK = GENMASK(6, 0),
+	};
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	rk_clrsetreg(&grf->soc_con15,
+		     RK3368_RMII_MODE_MASK | RK3368_GMAC_PHY_INTF_SEL_MASK,
+		     RK3368_GMAC_PHY_INTF_SEL_RGMII);
+
+	rk_clrsetreg(&grf->soc_con16,
+		     RK3368_RXCLK_DLY_ENA_GMAC_MASK |
+		     RK3368_TXCLK_DLY_ENA_GMAC_MASK |
+		     RK3368_CLK_RX_DL_CFG_GMAC_MASK |
+		     RK3368_CLK_TX_DL_CFG_GMAC_MASK,
+		     RK3368_RXCLK_DLY_ENA_GMAC_ENABLE |
+		     RK3368_TXCLK_DLY_ENA_GMAC_ENABLE |
+		     pdata->rx_delay << RK3368_CLK_RX_DL_CFG_GMAC_SHIFT |
+		     pdata->tx_delay << RK3368_CLK_TX_DL_CFG_GMAC_SHIFT);
+}
+
 static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
 {
 	struct rk3399_grf_regs *grf;
@@ -208,6 +279,11 @@ const struct rk_gmac_ops rk3288_gmac_ops = {
 	.set_to_rgmii = rk3288_gmac_set_to_rgmii,
 };
 
+const struct rk_gmac_ops rk3368_gmac_ops = {
+	.fix_mac_speed = rk3368_gmac_fix_mac_speed,
+	.set_to_rgmii = rk3368_gmac_set_to_rgmii,
+};
+
 const struct rk_gmac_ops rk3399_gmac_ops = {
 	.fix_mac_speed = rk3399_gmac_fix_mac_speed,
 	.set_to_rgmii = rk3399_gmac_set_to_rgmii,
@@ -216,6 +292,8 @@ const struct rk_gmac_ops rk3399_gmac_ops = {
 static const struct udevice_id rockchip_gmac_ids[] = {
 	{ .compatible = "rockchip,rk3288-gmac",
 	  .data = (ulong)&rk3288_gmac_ops },
+	{ .compatible = "rockchip,rk3368-gmac",
+	  .data = (ulong)&rk3368_gmac_ops },
 	{ .compatible = "rockchip,rk3399-gmac",
 	  .data = (ulong)&rk3399_gmac_ops },
 	{ }
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3368.c b/drivers/pinctrl/rockchip/pinctrl_rk3368.c
index bdf0758c0ccdaada20a54deea05eece3fb9694c2..81ce2e31a7f6ac727caded3b3d6258fa3cd5f1c1 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3368.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3368.c
@@ -1,8 +1,11 @@
 /*
  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
  * Author: Andy Yan <andy.yan@rock-chips.com>
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -16,6 +19,428 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* PMUGRF_GPIO0B_IOMUX */
+enum {
+	GPIO0B5_SHIFT           = 10,
+	GPIO0B5_MASK            = GENMASK(GPIO0B5_SHIFT + 1, GPIO0B5_SHIFT),
+	GPIO0B5_GPIO            = 0,
+	GPIO0B5_SPI2_CSN0       = (2 << GPIO0B5_SHIFT),
+
+	GPIO0B4_SHIFT           = 8,
+	GPIO0B4_MASK            = GENMASK(GPIO0B4_SHIFT + 1, GPIO0B4_SHIFT),
+	GPIO0B4_GPIO            = 0,
+	GPIO0B4_SPI2_CLK        = (2 << GPIO0B4_SHIFT),
+
+	GPIO0B3_SHIFT           = 6,
+	GPIO0B3_MASK            = GENMASK(GPIO0B3_SHIFT + 1, GPIO0B3_SHIFT),
+	GPIO0B3_GPIO            = 0,
+	GPIO0B3_SPI2_TXD        = (2 << GPIO0B3_SHIFT),
+
+	GPIO0B2_SHIFT           = 4,
+	GPIO0B2_MASK            = GENMASK(GPIO0B2_SHIFT + 1, GPIO0B2_SHIFT),
+	GPIO0B2_GPIO            = 0,
+	GPIO0B2_SPI2_RXD        = (2 << GPIO0B2_SHIFT),
+};
+
+/*GRF_GPIO0C_IOMUX*/
+enum {
+	GPIO0C7_SHIFT           = 14,
+	GPIO0C7_MASK	        = GENMASK(GPIO0C7_SHIFT + 1, GPIO0C7_SHIFT),
+	GPIO0C7_GPIO	        = 0,
+	GPIO0C7_LCDC_D19        = (1 << GPIO0C7_SHIFT),
+	GPIO0C7_TRACE_D9        = (2 << GPIO0C7_SHIFT),
+	GPIO0C7_UART1_RTSN      = (3 << GPIO0C7_SHIFT),
+
+	GPIO0C6_SHIFT           = 12,
+	GPIO0C6_MASK            = GENMASK(GPIO0C6_SHIFT + 1, GPIO0C6_SHIFT),
+	GPIO0C6_GPIO            = 0,
+	GPIO0C6_LCDC_D18        = (1 << GPIO0C6_SHIFT),
+	GPIO0C6_TRACE_D8        = (2 << GPIO0C6_SHIFT),
+	GPIO0C6_UART1_CTSN      = (3 << GPIO0C6_SHIFT),
+
+	GPIO0C5_SHIFT           = 10,
+	GPIO0C5_MASK            = GENMASK(GPIO0C5_SHIFT + 1, GPIO0C5_SHIFT),
+	GPIO0C5_GPIO            = 0,
+	GPIO0C5_LCDC_D17        = (1 << GPIO0C5_SHIFT),
+	GPIO0C5_TRACE_D7        = (2 << GPIO0C5_SHIFT),
+	GPIO0C5_UART1_SOUT      = (3 << GPIO0C5_SHIFT),
+
+	GPIO0C4_SHIFT           = 8,
+	GPIO0C4_MASK            = GENMASK(GPIO0C4_SHIFT + 1, GPIO0C4_SHIFT),
+	GPIO0C4_GPIO            = 0,
+	GPIO0C4_LCDC_D16        = (1 << GPIO0C4_SHIFT),
+	GPIO0C4_TRACE_D6        = (2 << GPIO0C4_SHIFT),
+	GPIO0C4_UART1_SIN       = (3 << GPIO0C4_SHIFT),
+
+	GPIO0C3_SHIFT           = 6,
+	GPIO0C3_MASK            = GENMASK(GPIO0C3_SHIFT + 1, GPIO0C3_SHIFT),
+	GPIO0C3_GPIO            = 0,
+	GPIO0C3_LCDC_D15        = (1 << GPIO0C3_SHIFT),
+	GPIO0C3_TRACE_D5        = (2 << GPIO0C3_SHIFT),
+	GPIO0C3_MCU_JTAG_TDO    = (3 << GPIO0C3_SHIFT),
+
+	GPIO0C2_SHIFT           = 4,
+	GPIO0C2_MASK            = GENMASK(GPIO0C2_SHIFT + 1, GPIO0C2_SHIFT),
+	GPIO0C2_GPIO            = 0,
+	GPIO0C2_LCDC_D14        = (1 << GPIO0C2_SHIFT),
+	GPIO0C2_TRACE_D4        = (2 << GPIO0C2_SHIFT),
+	GPIO0C2_MCU_JTAG_TDI    = (3 << GPIO0C2_SHIFT),
+
+	GPIO0C1_SHIFT           = 2,
+	GPIO0C1_MASK            = GENMASK(GPIO0C1_SHIFT + 1, GPIO0C1_SHIFT),
+	GPIO0C1_GPIO            = 0,
+	GPIO0C1_LCDC_D13        = (1 << GPIO0C1_SHIFT),
+	GPIO0C1_TRACE_D3        = (2 << GPIO0C1_SHIFT),
+	GPIO0C1_MCU_JTAG_TRTSN  = (3 << GPIO0C1_SHIFT),
+
+	GPIO0C0_SHIFT           = 0,
+	GPIO0C0_MASK            = GENMASK(GPIO0C0_SHIFT + 1, GPIO0C0_SHIFT),
+	GPIO0C0_GPIO            = 0,
+	GPIO0C0_LCDC_D12        = (1 << GPIO0C0_SHIFT),
+	GPIO0C0_TRACE_D2        = (2 << GPIO0C0_SHIFT),
+	GPIO0C0_MCU_JTAG_TDO    = (3 << GPIO0C0_SHIFT),
+};
+
+/*GRF_GPIO0D_IOMUX*/
+enum {
+	GPIO0D7_SHIFT           = 14,
+	GPIO0D7_MASK            = GENMASK(GPIO0D7_SHIFT + 1, GPIO0D7_SHIFT),
+	GPIO0D7_GPIO            = 0,
+	GPIO0D7_LCDC_DCLK       = (1 << GPIO0D7_SHIFT),
+	GPIO0D7_TRACE_CTL       = (2 << GPIO0D7_SHIFT),
+	GPIO0D7_PMU_DEBUG5      = (3 << GPIO0D7_SHIFT),
+
+	GPIO0D6_SHIFT           = 12,
+	GPIO0D6_MASK            = GENMASK(GPIO0D6_SHIFT + 1, GPIO0D6_SHIFT),
+	GPIO0D6_GPIO            = 0,
+	GPIO0D6_LCDC_DEN        = (1 << GPIO0D6_SHIFT),
+	GPIO0D6_TRACE_CLK       = (2 << GPIO0D6_SHIFT),
+	GPIO0D6_PMU_DEBUG4      = (3 << GPIO0D6_SHIFT),
+
+	GPIO0D5_SHIFT           = 10,
+	GPIO0D5_MASK            = GENMASK(GPIO0D5_SHIFT + 1, GPIO0D5_SHIFT),
+	GPIO0D5_GPIO            = 0,
+	GPIO0D5_LCDC_VSYNC      = (1 << GPIO0D5_SHIFT),
+	GPIO0D5_TRACE_D15       = (2 << GPIO0D5_SHIFT),
+	GPIO0D5_PMU_DEBUG3      = (3 << GPIO0D5_SHIFT),
+
+	GPIO0D4_SHIFT           = 8,
+	GPIO0D4_MASK            = GENMASK(GPIO0D4_SHIFT + 1, GPIO0D4_SHIFT),
+	GPIO0D4_GPIO            = 0,
+	GPIO0D4_LCDC_HSYNC      = (1 << GPIO0D4_SHIFT),
+	GPIO0D4_TRACE_D14       = (2 << GPIO0D4_SHIFT),
+	GPIO0D4_PMU_DEBUG2      = (3 << GPIO0D4_SHIFT),
+
+	GPIO0D3_SHIFT           = 6,
+	GPIO0D3_MASK            = GENMASK(GPIO0D3_SHIFT + 1, GPIO0D3_SHIFT),
+	GPIO0D3_GPIO            = 0,
+	GPIO0D3_LCDC_D23        = (1 << GPIO0D3_SHIFT),
+	GPIO0D3_TRACE_D13       = (2 << GPIO0D3_SHIFT),
+	GPIO0D3_UART4_SIN       = (3 << GPIO0D3_SHIFT),
+
+	GPIO0D2_SHIFT           = 4,
+	GPIO0D2_MASK            = GENMASK(GPIO0D2_SHIFT + 1, GPIO0D2_SHIFT),
+	GPIO0D2_GPIO            = 0,
+	GPIO0D2_LCDC_D22        = (1 << GPIO0D2_SHIFT),
+	GPIO0D2_TRACE_D12       = (2 << GPIO0D2_SHIFT),
+	GPIO0D2_UART4_SOUT      = (3 << GPIO0D2_SHIFT),
+
+	GPIO0D1_SHIFT           = 2,
+	GPIO0D1_MASK            = GENMASK(GPIO0D1_SHIFT + 1, GPIO0D1_SHIFT),
+	GPIO0D1_GPIO            = 0,
+	GPIO0D1_LCDC_D21        = (1 << GPIO0D1_SHIFT),
+	GPIO0D1_TRACE_D11       = (2 << GPIO0D1_SHIFT),
+	GPIO0D1_UART4_RTSN      = (3 << GPIO0D1_SHIFT),
+
+	GPIO0D0_SHIFT           = 0,
+	GPIO0D0_MASK            = GENMASK(GPIO0D0_SHIFT + 1, GPIO0D0_SHIFT),
+	GPIO0D0_GPIO            = 0,
+	GPIO0D0_LCDC_D20        = (1 << GPIO0D0_SHIFT),
+	GPIO0D0_TRACE_D10       = (2 << GPIO0D0_SHIFT),
+	GPIO0D0_UART4_CTSN      = (3 << GPIO0D0_SHIFT),
+};
+
+/*GRF_GPIO2A_IOMUX*/
+enum {
+	GPIO2A7_SHIFT           = 14,
+	GPIO2A7_MASK            = GENMASK(GPIO2A7_SHIFT + 1, GPIO2A7_SHIFT),
+	GPIO2A7_GPIO            = 0,
+	GPIO2A7_SDMMC0_D2       = (1 << GPIO2A7_SHIFT),
+	GPIO2A7_JTAG_TCK        = (2 << GPIO2A7_SHIFT),
+
+	GPIO2A6_SHIFT           = 12,
+	GPIO2A6_MASK            = GENMASK(GPIO2A6_SHIFT + 1, GPIO2A6_SHIFT),
+	GPIO2A6_GPIO            = 0,
+	GPIO2A6_SDMMC0_D1       = (1 << GPIO2A6_SHIFT),
+	GPIO2A6_UART2_SIN       = (2 << GPIO2A6_SHIFT),
+
+	GPIO2A5_SHIFT           = 10,
+	GPIO2A5_MASK            = GENMASK(GPIO2A5_SHIFT + 1, GPIO2A5_SHIFT),
+	GPIO2A5_GPIO            = 0,
+	GPIO2A5_SDMMC0_D0       = (1 << GPIO2A5_SHIFT),
+	GPIO2A5_UART2_SOUT      = (2 << GPIO2A5_SHIFT),
+
+	GPIO2A4_SHIFT           = 8,
+	GPIO2A4_MASK            = GENMASK(GPIO2A4_SHIFT + 1, GPIO2A4_SHIFT),
+	GPIO2A4_GPIO            = 0,
+	GPIO2A4_FLASH_DQS       = (1 << GPIO2A4_SHIFT),
+	GPIO2A4_EMMC_CLKOUT     = (2 << GPIO2A4_SHIFT),
+
+	GPIO2A3_SHIFT           = 6,
+	GPIO2A3_MASK            = GENMASK(GPIO2A3_SHIFT + 1, GPIO2A3_SHIFT),
+	GPIO2A3_GPIO            = 0,
+	GPIO2A3_FLASH_CSN3      = (1 << GPIO2A3_SHIFT),
+	GPIO2A3_EMMC_RSTNOUT    = (2 << GPIO2A3_SHIFT),
+
+	GPIO2A2_SHIFT           = 4,
+	GPIO2A2_MASK            = GENMASK(GPIO2A2_SHIFT + 1, GPIO2A2_SHIFT),
+	GPIO2A2_GPIO            = 0,
+	GPIO2A2_FLASH_CSN2      = (1 << GPIO2A2_SHIFT),
+
+	GPIO2A1_SHIFT           = 2,
+	GPIO2A1_MASK            = GENMASK(GPIO2A1_SHIFT + 1, GPIO2A1_SHIFT),
+	GPIO2A1_GPIO            = 0,
+	GPIO2A1_FLASH_CSN1      = (1 << GPIO2A1_SHIFT),
+
+	GPIO2A0_SHIFT           = 0,
+	GPIO2A0_MASK            = GENMASK(GPIO2A0_SHIFT + 1, GPIO2A0_SHIFT),
+	GPIO2A0_GPIO            = 0,
+	GPIO2A0_FLASH_CSN0      = (1 << GPIO2A0_SHIFT),
+};
+
+/*GRF_GPIO2D_IOMUX*/
+enum {
+	GPIO2D7_SHIFT           = 14,
+	GPIO2D7_MASK            = GENMASK(GPIO2D7_SHIFT + 1, GPIO2D7_SHIFT),
+	GPIO2D7_GPIO            = 0,
+	GPIO2D7_SDIO0_D3        = (1 << GPIO2D7_SHIFT),
+
+	GPIO2D6_SHIFT           = 12,
+	GPIO2D6_MASK            = GENMASK(GPIO2D6_SHIFT + 1, GPIO2D6_SHIFT),
+	GPIO2D6_GPIO            = 0,
+	GPIO2D6_SDIO0_D2        = (1 << GPIO2D6_SHIFT),
+
+	GPIO2D5_SHIFT           = 10,
+	GPIO2D5_MASK            = GENMASK(GPIO2D5_SHIFT + 1, GPIO2D5_SHIFT),
+	GPIO2D5_GPIO            = 0,
+	GPIO2D5_SDIO0_D1        = (1 << GPIO2D5_SHIFT),
+
+	GPIO2D4_SHIFT           = 8,
+	GPIO2D4_MASK            = GENMASK(GPIO2D4_SHIFT + 1, GPIO2D4_SHIFT),
+	GPIO2D4_GPIO            = 0,
+	GPIO2D4_SDIO0_D0        = (1 << GPIO2D4_SHIFT),
+
+	GPIO2D3_SHIFT           = 6,
+	GPIO2D3_MASK            = GENMASK(GPIO2D3_SHIFT + 1, GPIO2D3_SHIFT),
+	GPIO2D3_GPIO            = 0,
+	GPIO2D3_UART0_RTS0      = (1 << GPIO2D3_SHIFT),
+
+	GPIO2D2_SHIFT           = 4,
+	GPIO2D2_MASK            = GENMASK(GPIO2D2_SHIFT + 1, GPIO2D2_SHIFT),
+	GPIO2D2_GPIO            = 0,
+	GPIO2D2_UART0_CTS0      = (1 << GPIO2D2_SHIFT),
+
+	GPIO2D1_SHIFT           = 2,
+	GPIO2D1_MASK            = GENMASK(GPIO2D1_SHIFT + 1, GPIO2D1_SHIFT),
+	GPIO2D1_GPIO            = 0,
+	GPIO2D1_UART0_SOUT      = (1 << GPIO2D1_SHIFT),
+
+	GPIO2D0_SHIFT           = 0,
+	GPIO2D0_MASK            = GENMASK(GPIO2D0_SHIFT + 1, GPIO2D0_SHIFT),
+	GPIO2D0_GPIO            = 0,
+	GPIO2D0_UART0_SIN       = (1 << GPIO2D0_SHIFT),
+};
+
+/* GRF_GPIO1B_IOMUX */
+enum {
+	GPIO1B7_SHIFT           = 14,
+	GPIO1B7_MASK            = GENMASK(GPIO1B7_SHIFT + 1, GPIO1B7_SHIFT),
+	GPIO1B7_GPIO            = 0,
+	GPIO1B7_SPI1_CSN0       = (2 << GPIO1B7_SHIFT),
+
+	GPIO1B6_SHIFT           = 12,
+	GPIO1B6_MASK            = GENMASK(GPIO1B6_SHIFT + 1, GPIO1B6_SHIFT),
+	GPIO1B6_GPIO            = 0,
+	GPIO1B6_SPI1_CLK        = (2 << GPIO1B6_SHIFT),
+};
+
+/* GRF_GPIO1C_IOMUX */
+enum {
+	GPIO1C7_SHIFT           = 14,
+	GPIO1C7_MASK            = GENMASK(GPIO1C7_SHIFT + 1, GPIO1C7_SHIFT),
+	GPIO1C7_GPIO            = 0,
+	GPIO1C7_EMMC_DATA5      = (2 << GPIO1C7_SHIFT),
+	GPIO1C7_SPI0_TXD        = (3 << GPIO1C7_SHIFT),
+
+	GPIO1C6_SHIFT           = 12,
+	GPIO1C6_MASK            = GENMASK(GPIO1C6_SHIFT + 1, GPIO1C6_SHIFT),
+	GPIO1C6_GPIO            = 0,
+	GPIO1C6_EMMC_DATA4      = (2 << GPIO1C6_SHIFT),
+	GPIO1C6_SPI0_RXD        = (3 << GPIO1C6_SHIFT),
+
+	GPIO1C5_SHIFT           = 10,
+	GPIO1C5_MASK            = GENMASK(GPIO1C5_SHIFT + 1, GPIO1C5_SHIFT),
+	GPIO1C5_GPIO            = 0,
+	GPIO1C5_EMMC_DATA3      = (2 << GPIO1C5_SHIFT),
+
+	GPIO1C4_SHIFT           = 8,
+	GPIO1C4_MASK            = GENMASK(GPIO1C4_SHIFT + 1, GPIO1C4_SHIFT),
+	GPIO1C4_GPIO            = 0,
+	GPIO1C4_EMMC_DATA2      = (2 << GPIO1C4_SHIFT),
+
+	GPIO1C3_SHIFT           = 6,
+	GPIO1C3_MASK            = GENMASK(GPIO1C3_SHIFT + 1, GPIO1C3_SHIFT),
+	GPIO1C3_GPIO            = 0,
+	GPIO1C3_EMMC_DATA1      = (2 << GPIO1C3_SHIFT),
+
+	GPIO1C2_SHIFT           = 4,
+	GPIO1C2_MASK            = GENMASK(GPIO1C2_SHIFT + 1, GPIO1C2_SHIFT),
+	GPIO1C2_GPIO            = 0,
+	GPIO1C2_EMMC_DATA0      = (2 << GPIO1C2_SHIFT),
+
+	GPIO1C1_SHIFT           = 2,
+	GPIO1C1_MASK            = GENMASK(GPIO1C1_SHIFT + 1, GPIO1C1_SHIFT),
+	GPIO1C1_GPIO            = 0,
+	GPIO1C1_SPI1_RXD        = (2 << GPIO1C1_SHIFT),
+
+	GPIO1C0_SHIFT           = 0,
+	GPIO1C0_MASK            = GENMASK(GPIO1C0_SHIFT + 1, GPIO1C0_SHIFT),
+	GPIO1C0_GPIO            = 0,
+	GPIO1C0_SPI1_TXD        = (2 << GPIO1C0_SHIFT),
+};
+
+/* GRF_GPIO1D_IOMUX*/
+enum {
+	GPIO1D5_SHIFT           = 10,
+	GPIO1D5_MASK            = GENMASK(GPIO1D5_SHIFT + 1, GPIO1D5_SHIFT),
+	GPIO1D5_GPIO            = 0,
+	GPIO1D5_SPI0_CLK        = (2 << GPIO1D5_SHIFT),
+
+	GPIO1D3_SHIFT           = 6,
+	GPIO1D3_MASK            = GENMASK(GPIO1D3_SHIFT + 1, GPIO1D3_SHIFT),
+	GPIO1D3_GPIO            = 0,
+	GPIO1D3_EMMC_PWREN      = (2 << GPIO1D3_SHIFT),
+
+	GPIO1D2_SHIFT           = 4,
+	GPIO1D2_MASK            = GENMASK(GPIO1D2_SHIFT + 1, GPIO1D2_SHIFT),
+	GPIO1D2_GPIO            = 0,
+	GPIO1D2_EMMC_CMD        = (2 << GPIO1D2_SHIFT),
+
+	GPIO1D1_SHIFT           = 2,
+	GPIO1D1_MASK            = GENMASK(GPIO1D1_SHIFT + 1, GPIO1D1_SHIFT),
+	GPIO1D1_GPIO            = 0,
+	GPIO1D1_EMMC_DATA7      = (2 << GPIO1D1_SHIFT),
+	GPIO1D1_SPI0_CSN1       = (3 << GPIO1D1_SHIFT),
+
+	GPIO1D0_SHIFT           = 0,
+	GPIO1D0_MASK            = GENMASK(GPIO1D0_SHIFT + 1, GPIO1D0_SHIFT),
+	GPIO1D0_GPIO            = 0,
+	GPIO1D0_EMMC_DATA6      = (2 << GPIO1D0_SHIFT),
+	GPIO1D0_SPI0_CSN0       = (3 << GPIO1D0_SHIFT),
+};
+
+
+/*GRF_GPIO3B_IOMUX*/
+enum {
+	GPIO3B7_SHIFT           = 14,
+	GPIO3B7_MASK            = GENMASK(GPIO3B7_SHIFT + 1, GPIO3B7_SHIFT),
+	GPIO3B7_GPIO            = 0,
+	GPIO3B7_MAC_RXD0        = (1 << GPIO3B7_SHIFT),
+
+	GPIO3B6_SHIFT           = 12,
+	GPIO3B6_MASK            = GENMASK(GPIO3B6_SHIFT + 1, GPIO3B6_SHIFT),
+	GPIO3B6_GPIO            = 0,
+	GPIO3B6_MAC_TXD3        = (1 << GPIO3B6_SHIFT),
+
+	GPIO3B5_SHIFT           = 10,
+	GPIO3B5_MASK            = GENMASK(GPIO3B5_SHIFT + 1, GPIO3B5_SHIFT),
+	GPIO3B5_GPIO            = 0,
+	GPIO3B5_MAC_TXEN        = (1 << GPIO3B5_SHIFT),
+
+	GPIO3B4_SHIFT           = 8,
+	GPIO3B4_MASK            = GENMASK(GPIO3B4_SHIFT + 1, GPIO3B4_SHIFT),
+	GPIO3B4_GPIO            = 0,
+	GPIO3B4_MAC_COL         = (1 << GPIO3B4_SHIFT),
+
+	GPIO3B3_SHIFT           = 6,
+	GPIO3B3_MASK            = GENMASK(GPIO3B3_SHIFT + 1, GPIO3B3_SHIFT),
+	GPIO3B3_GPIO            = 0,
+	GPIO3B3_MAC_CRS         = (1 << GPIO3B3_SHIFT),
+
+	GPIO3B2_SHIFT           = 4,
+	GPIO3B2_MASK            = GENMASK(GPIO3B2_SHIFT + 1, GPIO3B2_SHIFT),
+	GPIO3B2_GPIO            = 0,
+	GPIO3B2_MAC_TXD2        = (1 << GPIO3B2_SHIFT),
+
+	GPIO3B1_SHIFT           = 2,
+	GPIO3B1_MASK            = GENMASK(GPIO3B1_SHIFT + 1, GPIO3B1_SHIFT),
+	GPIO3B1_GPIO            = 0,
+	GPIO3B1_MAC_TXD1        = (1 << GPIO3B1_SHIFT),
+
+	GPIO3B0_SHIFT           = 0,
+	GPIO3B0_MASK            = GENMASK(GPIO3B0_SHIFT + 1, GPIO3B0_SHIFT),
+	GPIO3B0_GPIO            = 0,
+	GPIO3B0_MAC_TXD0        = (1 << GPIO3B0_SHIFT),
+	GPIO3B0_PWM0            = (2 << GPIO3B0_SHIFT),
+};
+
+/*GRF_GPIO3C_IOMUX*/
+enum {
+	GPIO3C6_SHIFT           = 12,
+	GPIO3C6_MASK            = GENMASK(GPIO3C6_SHIFT + 1, GPIO3C6_SHIFT),
+	GPIO3C6_GPIO            = 0,
+	GPIO3C6_MAC_CLK         = (1 << GPIO3C6_SHIFT),
+
+	GPIO3C5_SHIFT           = 10,
+	GPIO3C5_MASK            = GENMASK(GPIO3C5_SHIFT + 1, GPIO3C5_SHIFT),
+	GPIO3C5_GPIO            = 0,
+	GPIO3C5_MAC_RXEN        = (1 << GPIO3C5_SHIFT),
+
+	GPIO3C4_SHIFT           = 8,
+	GPIO3C4_MASK            = GENMASK(GPIO3C4_SHIFT + 1, GPIO3C4_SHIFT),
+	GPIO3C4_GPIO            = 0,
+	GPIO3C4_MAC_RXDV        = (1 << GPIO3C4_SHIFT),
+
+	GPIO3C3_SHIFT           = 6,
+	GPIO3C3_MASK            = GENMASK(GPIO3C3_SHIFT + 1, GPIO3C3_SHIFT),
+	GPIO3C3_GPIO            = 0,
+	GPIO3C3_MAC_MDC         = (1 << GPIO3C3_SHIFT),
+
+	GPIO3C2_SHIFT           = 4,
+	GPIO3C2_MASK            = GENMASK(GPIO3C2_SHIFT + 1, GPIO3C2_SHIFT),
+	GPIO3C2_GPIO            = 0,
+	GPIO3C2_MAC_RXD3        = (1 << GPIO3C2_SHIFT),
+
+	GPIO3C1_SHIFT           = 2,
+	GPIO3C1_MASK            = GENMASK(GPIO3C1_SHIFT + 1, GPIO3C1_SHIFT),
+	GPIO3C1_GPIO            = 0,
+	GPIO3C1_MAC_RXD2        = (1 << GPIO3C1_SHIFT),
+
+	GPIO3C0_SHIFT           = 0,
+	GPIO3C0_MASK            = GENMASK(GPIO3C0_SHIFT + 1, GPIO3C0_SHIFT),
+	GPIO3C0_GPIO            = 0,
+	GPIO3C0_MAC_RXD1        = (1 << GPIO3C0_SHIFT),
+};
+
+/*GRF_GPIO3D_IOMUX*/
+enum {
+	GPIO3D4_SHIFT           = 8,
+	GPIO3D4_MASK            = GENMASK(GPIO3D4_SHIFT + 1, GPIO3D4_SHIFT),
+	GPIO3D4_GPIO            = 0,
+	GPIO3D4_MAC_TXCLK       = (1 << GPIO3D4_SHIFT),
+	GPIO3D4_SPI1_CNS1       = (2 << GPIO3D4_SHIFT),
+
+	GPIO3D1_SHIFT           = 2,
+	GPIO3D1_MASK            = GENMASK(GPIO3D1_SHIFT + 1, GPIO3D1_SHIFT),
+	GPIO3D1_GPIO            = 0,
+	GPIO3D1_MAC_RXCLK       = (1 << GPIO3D1_SHIFT),
+
+	GPIO3D0_SHIFT           = 0,
+	GPIO3D0_MASK            = GENMASK(GPIO3D0_SHIFT + 1, GPIO3D0_SHIFT),
+	GPIO3D0_GPIO            = 0,
+	GPIO3D0_MAC_MDIO        = (1 << GPIO3D0_SHIFT),
+};
+
 struct rk3368_pinctrl_priv {
 	struct rk3368_grf *grf;
 	struct rk3368_pmu_grf *pmugrf;
@@ -31,8 +456,7 @@ static void pinctrl_rk3368_uart_config(struct rk3368_pinctrl_priv *priv,
 	case PERIPH_ID_UART2:
 		rk_clrsetreg(&grf->gpio2a_iomux,
 			     GPIO2A6_MASK | GPIO2A5_MASK,
-			     GPIO2A6_UART2_SIN << GPIO2A6_SHIFT |
-			     GPIO2A5_UART2_SOUT << GPIO2A5_SHIFT);
+			     GPIO2A6_UART2_SIN | GPIO2A5_UART2_SOUT);
 		break;
 	case PERIPH_ID_UART0:
 		break;
@@ -44,10 +468,8 @@ static void pinctrl_rk3368_uart_config(struct rk3368_pinctrl_priv *priv,
 		rk_clrsetreg(&pmugrf->gpio0d_iomux,
 			     GPIO0D0_MASK | GPIO0D1_MASK |
 			     GPIO0D2_MASK | GPIO0D3_MASK,
-			     GPIO0D0_GPIO << GPIO0D0_SHIFT |
-			     GPIO0D1_GPIO << GPIO0D1_SHIFT |
-			     GPIO0D2_UART4_SOUT << GPIO0D2_SHIFT |
-			     GPIO0D3_UART4_SIN << GPIO0D3_SHIFT);
+			     GPIO0D0_GPIO | GPIO0D1_GPIO |
+			     GPIO0D2_UART4_SOUT | GPIO0D3_UART4_SIN);
 		break;
 	default:
 		debug("uart id = %d iomux error!\n", uart_id);
@@ -55,6 +477,121 @@ static void pinctrl_rk3368_uart_config(struct rk3368_pinctrl_priv *priv,
 	}
 }
 
+static void pinctrl_rk3368_spi_config(struct rk3368_pinctrl_priv *priv,
+				      int spi_id)
+{
+	struct rk3368_grf *grf = priv->grf;
+	struct rk3368_pmu_grf *pmugrf = priv->pmugrf;
+
+	switch (spi_id) {
+	case PERIPH_ID_SPI0:
+		/*
+		 * eMMC can only be connected with 4 bits, when SPI0 is used.
+		 * This is all-or-nothing, so we assume that if someone asks us
+		 * to configure SPI0, that their eMMC interface is unused or
+		 * configured appropriately.
+		 */
+		rk_clrsetreg(&grf->gpio1d_iomux,
+			     GPIO1D0_MASK | GPIO1D1_MASK |
+			     GPIO1D5_MASK,
+			     GPIO1D0_SPI0_CSN0 | GPIO1D1_SPI0_CSN1 |
+			     GPIO1D5_SPI0_CLK);
+		rk_clrsetreg(&grf->gpio1c_iomux,
+			     GPIO1C6_MASK | GPIO1C7_MASK,
+			     GPIO1C6_SPI0_RXD | GPIO1C7_SPI0_TXD);
+		break;
+	case PERIPH_ID_SPI1:
+		/*
+		 * We don't implement support for configuring SPI1_CSN#1, as it
+		 * conflicts with the GMAC (MAC TX clk-out).
+		 */
+		rk_clrsetreg(&grf->gpio1b_iomux,
+			     GPIO1B6_MASK | GPIO1B7_MASK,
+			     GPIO1B6_SPI1_CLK | GPIO1B7_SPI1_CSN0);
+		rk_clrsetreg(&grf->gpio1c_iomux,
+			     GPIO1C0_MASK | GPIO1C1_MASK,
+			     GPIO1C0_SPI1_TXD | GPIO1C1_SPI1_RXD);
+		break;
+	case PERIPH_ID_SPI2:
+		rk_clrsetreg(&pmugrf->gpio0b_iomux,
+			     GPIO0B2_MASK | GPIO0B3_MASK |
+			     GPIO0B4_MASK | GPIO0B5_MASK,
+			     GPIO0B2_SPI2_RXD | GPIO0B3_SPI2_TXD |
+			     GPIO0B4_SPI2_CLK | GPIO0B5_SPI2_CSN0);
+		break;
+	default:
+		debug("%s: spi id = %d iomux error!\n", __func__, spi_id);
+		break;
+	}
+}
+
+#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
+static void pinctrl_rk3368_gmac_config(struct rk3368_grf *grf, int gmac_id)
+{
+	rk_clrsetreg(&grf->gpio3b_iomux,
+		     GPIO3B0_MASK | GPIO3B1_MASK |
+		     GPIO3B2_MASK | GPIO3B5_MASK |
+		     GPIO3B6_MASK | GPIO3B7_MASK,
+		     GPIO3B0_MAC_TXD0 | GPIO3B1_MAC_TXD1 |
+		     GPIO3B2_MAC_TXD2 | GPIO3B5_MAC_TXEN |
+		     GPIO3B6_MAC_TXD3 | GPIO3B7_MAC_RXD0);
+	rk_clrsetreg(&grf->gpio3c_iomux,
+		     GPIO3C0_MASK | GPIO3C1_MASK |
+		     GPIO3C2_MASK | GPIO3C3_MASK |
+		     GPIO3C4_MASK | GPIO3C5_MASK |
+		     GPIO3C6_MASK,
+		     GPIO3C0_MAC_RXD1 | GPIO3C1_MAC_RXD2 |
+		     GPIO3C2_MAC_RXD3 | GPIO3C3_MAC_MDC |
+		     GPIO3C4_MAC_RXDV | GPIO3C5_MAC_RXEN |
+		     GPIO3C6_MAC_CLK);
+	rk_clrsetreg(&grf->gpio3d_iomux,
+		     GPIO3D0_MASK | GPIO3D1_MASK |
+		     GPIO3D4_MASK,
+		     GPIO3D0_MAC_MDIO | GPIO3D1_MAC_RXCLK |
+		     GPIO3D4_MAC_TXCLK);
+}
+#endif
+
+static void pinctrl_rk3368_sdmmc_config(struct rk3368_grf *grf, int mmc_id)
+{
+	switch (mmc_id) {
+	case PERIPH_ID_EMMC:
+		debug("mmc id = %d setting registers!\n", mmc_id);
+		rk_clrsetreg(&grf->gpio1c_iomux,
+			     GPIO1C2_MASK | GPIO1C3_MASK |
+			     GPIO1C4_MASK | GPIO1C5_MASK |
+			     GPIO1C6_MASK | GPIO1C7_MASK,
+			     GPIO1C2_EMMC_DATA0 |
+			     GPIO1C3_EMMC_DATA1 |
+			     GPIO1C4_EMMC_DATA2 |
+			     GPIO1C5_EMMC_DATA3 |
+			     GPIO1C6_EMMC_DATA4 |
+			     GPIO1C7_EMMC_DATA5);
+		rk_clrsetreg(&grf->gpio1d_iomux,
+			     GPIO1D0_MASK | GPIO1D1_MASK |
+			     GPIO1D2_MASK | GPIO1D3_MASK,
+			     GPIO1D0_EMMC_DATA6 |
+			     GPIO1D1_EMMC_DATA7 |
+			     GPIO1D2_EMMC_CMD |
+			     GPIO1D3_EMMC_PWREN);
+		rk_clrsetreg(&grf->gpio2a_iomux,
+			     GPIO2A3_MASK | GPIO2A4_MASK,
+			     GPIO2A3_EMMC_RSTNOUT |
+			     GPIO2A4_EMMC_CLKOUT);
+		break;
+	case PERIPH_ID_SDCARD:
+		/*
+		 * We assume that the BROM has already set this up
+		 * correctly for us and that there's nothing to do
+		 * here.
+		 */
+		break;
+	default:
+		debug("mmc id = %d iomux error!\n", mmc_id);
+		break;
+	}
+}
+
 static int rk3368_pinctrl_request(struct udevice *dev, int func, int flags)
 {
 	struct rk3368_pinctrl_priv *priv = dev_get_priv(dev);
@@ -68,6 +605,20 @@ static int rk3368_pinctrl_request(struct udevice *dev, int func, int flags)
 	case PERIPH_ID_UART4:
 		pinctrl_rk3368_uart_config(priv, func);
 		break;
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+	case PERIPH_ID_SPI2:
+		pinctrl_rk3368_spi_config(priv, func);
+		break;
+	case PERIPH_ID_EMMC:
+	case PERIPH_ID_SDCARD:
+		pinctrl_rk3368_sdmmc_config(priv->grf, func);
+		break;
+#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
+	case PERIPH_ID_GMAC:
+		pinctrl_rk3368_gmac_config(priv->grf, func);
+		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -97,6 +648,20 @@ static int rk3368_pinctrl_get_periph_id(struct udevice *dev,
 		return PERIPH_ID_UART1;
 	case 55:
 		return PERIPH_ID_UART0;
+	case 44:
+		return PERIPH_ID_SPI0;
+	case 45:
+		return PERIPH_ID_SPI1;
+	case 41:
+		return PERIPH_ID_SPI2;
+	case 35:
+		return PERIPH_ID_EMMC;
+	case 32:
+		return PERIPH_ID_SDCARD;
+#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
+	case 27:
+		return PERIPH_ID_GMAC;
+#endif
 	}
 
 	return -ENOENT;
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index 61afd7a92a4814111ee0b12ee912ee12825f8a4c..836be25507b58e062dc47e50e8ca478f8d321035 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -10,13 +10,22 @@ config RAM
 
 config SPL_RAM
 	bool "Enable RAM support in SPL"
-	depends on RAM
+	depends on RAM && SPL_DM
 	help
 	  The RAM subsystem adds a small amount of overhead to the image.
 	  If this is acceptable and you have a need to use RAM drivers in
 	  SPL, enable this option. It might provide a cleaner interface to
 	  setting up RAM (e.g. SDRAM / DDR) within SPL.
 
+config TPL_RAM
+	bool "Enable RAM support in SPL"
+	depends on RAM && TPL_DM
+	help
+	  The RAM subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use RAM drivers in
+	  TPL, enable this option. It might provide a cleaner interface to
+	  setting up RAM (e.g. SDRAM / DDR) within TPL.
+
 config STM32_SDRAM
 	bool "Enable STM32 SDRAM support"
 	depends on RAM
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index c409c480fc779e95b3199cf6a76e2f7c3325b57e..51ae6be655083fedfbdf2dc1078772e33afda358 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -8,3 +8,5 @@ obj-$(CONFIG_RAM) += ram-uclass.o
 obj-$(CONFIG_SANDBOX) += sandbox_ram.o
 obj-$(CONFIG_STM32_SDRAM) += stm32_sdram.o
 obj-$(CONFIG_ARCH_BMIPS) += bmips_ram.o
+
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b09d03c2c9d09bfbdf44d0f7afdebfd5c9139333
--- /dev/null
+++ b/drivers/ram/rockchip/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca7b1ff0c841517cb84e2417055938ab5fbc1cc1
--- /dev/null
+++ b/drivers/ram/rockchip/dmc-rk3368.c
@@ -0,0 +1,1007 @@
+/*
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-bindings/memory/rk3368-dmc.h>
+#include <dt-structs.h>
+#include <ram.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3368.h>
+#include <asm/arch/grf_rk3368.h>
+#include <asm/arch/ddr_rk3368.h>
+#include <asm/arch/sdram.h>
+#include <asm/arch/sdram_common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct dram_info {
+	struct ram_info info;
+	struct clk ddr_clk;
+	struct rk3368_cru *cru;
+	struct rk3368_grf *grf;
+	struct rk3368_ddr_pctl *pctl;
+	struct rk3368_ddrphy *phy;
+	struct rk3368_pmu_grf *pmugrf;
+	struct rk3368_msch *msch;
+};
+
+struct rk3368_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3368_dmc of_plat;
+#endif
+	struct rk3288_sdram_pctl_timing pctl_timing;
+	u32 trefi_mem_ddr3;
+	struct rk3288_sdram_channel chan;
+	struct regmap *map;
+	u32 ddr_freq;
+	u32 memory_schedule;
+	u32 ddr_speed_bin;
+	u32 tfaw_mult;
+};
+
+/* PTCL bits */
+enum {
+	/* PCTL_DFISTCFG0 */
+	DFI_INIT_START = BIT(0),
+	DFI_DATA_BYTE_DISABLE_EN = BIT(2),
+
+	/* PCTL_DFISTCFG1 */
+	DFI_DRAM_CLK_SR_EN = BIT(0),
+	DFI_DRAM_CLK_DPD_EN = BIT(1),
+	ODT_LEN_BL8_W_SHIFT = 16,
+
+	/* PCTL_DFISTCFG2 */
+	DFI_PARITY_INTR_EN = BIT(0),
+	DFI_PARITY_EN = BIT(1),
+
+	/* PCTL_DFILPCFG0 */
+	TLP_RESP_TIME_SHIFT = 16,
+	LP_SR_EN = BIT(8),
+	LP_PD_EN = BIT(0),
+
+	/* PCTL_DFIODTCFG */
+	RANK0_ODT_WRITE_SEL = BIT(3),
+	RANK1_ODT_WRITE_SEL = BIT(11),
+
+	/* PCTL_SCFG */
+	HW_LOW_POWER_EN = BIT(0),
+
+	/* PCTL_MCMD */
+	START_CMD = BIT(31),
+	MCMD_RANK0 = BIT(20),
+	MCMD_RANK1 = BIT(21),
+	DESELECT_CMD = 0,
+	PREA_CMD,
+	REF_CMD,
+	MRS_CMD,
+	ZQCS_CMD,
+	ZQCL_CMD,
+	RSTL_CMD,
+	MRR_CMD	= 8,
+	DPDE_CMD,
+
+	/* PCTL_POWCTL */
+	POWER_UP_START = BIT(0),
+
+	/* PCTL_POWSTAT */
+	POWER_UP_DONE = BIT(0),
+
+	/* PCTL_SCTL */
+	INIT_STATE = 0,
+	CFG_STATE,
+	GO_STATE,
+	SLEEP_STATE,
+	WAKEUP_STATE,
+
+	/* PCTL_STAT */
+	LP_TRIG_SHIFT = 4,
+	LP_TRIG_MASK = 7,
+	PCTL_STAT_MSK = 7,
+	INIT_MEM = 0,
+	CONFIG,
+	CONFIG_REQ,
+	ACCESS,
+	ACCESS_REQ,
+	LOW_POWER,
+	LOW_POWER_ENTRY_REQ,
+	LOW_POWER_EXIT_REQ,
+
+	/* PCTL_MCFG */
+	DDR2_DDR3_BL_8 = BIT(0),
+	DDR3_EN = BIT(5),
+	TFAW_TRRD_MULT4 = (0 << 18),
+	TFAW_TRRD_MULT5 = (1 << 18),
+	TFAW_TRRD_MULT6 = (2 << 18),
+};
+
+#define DDR3_MR0_WR(n) \
+	((n <= 8) ? ((n - 4) << 9) : (((n >> 1) & 0x7) << 9))
+#define DDR3_MR0_CL(n) \
+	((((n - 4) & 0x7) << 4) | (((n - 4) & 0x8) >> 2))
+#define DDR3_MR0_BL8 \
+	(0 << 0)
+#define DDR3_MR0_DLL_RESET \
+	(1 << 8)
+#define DDR3_MR1_RTT120OHM \
+	((0 << 9) | (1 << 6) | (0 << 2))
+#define DDR3_MR2_TWL(n) \
+	(((n - 5) & 0x7) << 3)
+
+
+#ifdef CONFIG_TPL_BUILD
+
+static void ddr_set_noc_spr_err_stall(struct rk3368_grf *grf, bool enable)
+{
+	if (enable)
+		rk_setreg(&grf->ddrc0_con0, NOC_RSP_ERR_STALL);
+	else
+		rk_clrreg(&grf->ddrc0_con0, NOC_RSP_ERR_STALL);
+}
+
+static void ddr_set_ddr3_mode(struct rk3368_grf *grf, bool ddr3_mode)
+{
+	if (ddr3_mode)
+		rk_setreg(&grf->ddrc0_con0, MSCH0_MAINDDR3_DDR3);
+	else
+		rk_clrreg(&grf->ddrc0_con0, MSCH0_MAINDDR3_DDR3);
+}
+
+static void ddrphy_config(struct rk3368_ddrphy *phy,
+			  u32 tcl, u32 tal, u32 tcwl)
+{
+	int i;
+
+	/* Set to DDR3 mode */
+	clrsetbits_le32(&phy->reg[1], 0x3, 0x0);
+
+	/* DDRPHY_REGB: CL, AL */
+	clrsetbits_le32(&phy->reg[0xb], 0xff, tcl << 4 | tal);
+	/* DDRPHY_REGC: CWL */
+	clrsetbits_le32(&phy->reg[0xc], 0x0f, tcwl);
+
+	/* Update drive-strength */
+	writel(0xcc, &phy->reg[0x11]);
+	writel(0xaa, &phy->reg[0x16]);
+	/*
+	 * Update NRCOMP/PRCOMP for all 4 channels (for details of all
+	 * affected registers refer to the documentation of DDRPHY_REG20
+	 * and DDRPHY_REG21 in the RK3368 TRM.
+	 */
+	for (i = 0; i < 4; ++i) {
+		writel(0xcc, &phy->reg[0x20 + i * 0x10]);
+		writel(0x44, &phy->reg[0x21 + i * 0x10]);
+	}
+
+	/* Enable write-leveling calibration bypass */
+	setbits_le32(&phy->reg[2], BIT(3));
+}
+
+static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+	int i;
+
+	for (i = 0; i < n / sizeof(u32); i++)
+		writel(*src++, dest++);
+}
+
+static void send_command(struct rk3368_ddr_pctl *pctl, u32 rank, u32 cmd)
+{
+	u32 mcmd = START_CMD | cmd | rank;
+
+	debug("%s: writing %x to MCMD\n", __func__, mcmd);
+	writel(mcmd, &pctl->mcmd);
+	while (readl(&pctl->mcmd) & START_CMD)
+		/* spin */;
+}
+
+static void send_mrs(struct rk3368_ddr_pctl *pctl,
+			    u32 rank, u32 mr_num, u32 mr_data)
+{
+	u32 mcmd = START_CMD | MRS_CMD | rank | (mr_num << 17) | (mr_data << 4);
+
+	debug("%s: writing %x to MCMD\n", __func__, mcmd);
+	writel(mcmd, &pctl->mcmd);
+	while (readl(&pctl->mcmd) & START_CMD)
+		/* spin */;
+}
+
+static int memory_init(struct rk3368_ddr_pctl *pctl,
+		       struct rk3368_sdram_params *params)
+{
+	u32 mr[4];
+	const ulong timeout_ms = 500;
+	ulong tmp;
+
+	/*
+	 * Power up DRAM by DDR_PCTL_POWCTL[0] register of PCTL and
+	 * wait power up DRAM finish with DDR_PCTL_POWSTAT[0] register
+	 * of PCTL.
+	 */
+	writel(POWER_UP_START, &pctl->powctl);
+
+	tmp = get_timer(0);
+	do {
+		if (get_timer(tmp) > timeout_ms) {
+			error("%s: POWER_UP_START did not complete in %ld ms\n",
+			      __func__, timeout_ms);
+			return -ETIME;
+		}
+	} while (!(readl(&pctl->powstat) & POWER_UP_DONE));
+
+	/* Configure MR0 through MR3 */
+	mr[0] = DDR3_MR0_WR(params->pctl_timing.twr) |
+		DDR3_MR0_CL(params->pctl_timing.tcl) |
+		DDR3_MR0_DLL_RESET;
+	mr[1] = DDR3_MR1_RTT120OHM;
+	mr[2] = DDR3_MR2_TWL(params->pctl_timing.tcwl);
+	mr[3] = 0;
+
+	/*
+	 * Also see RK3368 Technical Reference Manual:
+	 *   "16.6.2 Initialization (DDR3 Initialization Sequence)"
+	 */
+	send_command(pctl, MCMD_RANK0 | MCMD_RANK1, DESELECT_CMD);
+	udelay(1);
+	send_command(pctl, MCMD_RANK0 | MCMD_RANK1, PREA_CMD);
+	send_mrs(pctl, MCMD_RANK0 | MCMD_RANK1, 2, mr[2]);
+	send_mrs(pctl, MCMD_RANK0 | MCMD_RANK1, 3, mr[3]);
+	send_mrs(pctl, MCMD_RANK0 | MCMD_RANK1, 1, mr[1]);
+	send_mrs(pctl, MCMD_RANK0 | MCMD_RANK1, 0, mr[0]);
+	send_command(pctl, MCMD_RANK0 | MCMD_RANK1, ZQCL_CMD);
+
+	return 0;
+}
+
+static void move_to_config_state(struct rk3368_ddr_pctl *pctl)
+{
+	/*
+	 * Also see RK3368 Technical Reference Manual:
+	 *   "16.6.1 State transition of PCTL (Moving to Config State)"
+	 */
+	u32 state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+	switch (state) {
+	case LOW_POWER:
+		writel(WAKEUP_STATE, &pctl->sctl);
+		while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS)
+			/* spin */;
+
+		/* fall-through */
+	case ACCESS:
+	case INIT_MEM:
+		writel(CFG_STATE, &pctl->sctl);
+		while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+			/* spin */;
+		break;
+
+	case CONFIG:
+		return;
+
+	default:
+		break;
+	}
+}
+
+static void move_to_access_state(struct rk3368_ddr_pctl *pctl)
+{
+	/*
+	 * Also see RK3368 Technical Reference Manual:
+	 *   "16.6.1 State transition of PCTL (Moving to Access State)"
+	 */
+	u32 state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+	switch (state) {
+	case LOW_POWER:
+		if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) &
+		     LP_TRIG_MASK) == 1)
+			return;
+
+		writel(WAKEUP_STATE, &pctl->sctl);
+		while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS)
+			/* spin */;
+
+		/* fall-through */
+	case INIT_MEM:
+		writel(CFG_STATE, &pctl->sctl);
+		while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+			/* spin */;
+
+		/* fall-through */
+	case CONFIG:
+		writel(GO_STATE, &pctl->sctl);
+		while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG)
+			/* spin */;
+		break;
+
+	case ACCESS:
+		return;
+
+	default:
+		break;
+	}
+}
+
+static void ddrctl_reset(struct rk3368_cru *cru)
+{
+	const u32 ctl_reset = BIT(3) | BIT(2);
+	const u32 phy_reset = BIT(1) | BIT(0);
+
+	/*
+	 * The PHY reset should be released before the PCTL reset.
+	 *
+	 * Note that the following sequence (including the number of
+	 * us to delay between releasing the PHY and PCTL reset) has
+	 * been adapted per feedback received from Rockchips, so do
+	 * not try to optimise.
+	 */
+	rk_setreg(&cru->softrst_con[10], ctl_reset | phy_reset);
+	udelay(1);
+	rk_clrreg(&cru->softrst_con[10], phy_reset);
+	udelay(5);
+	rk_clrreg(&cru->softrst_con[10], ctl_reset);
+}
+
+static void ddrphy_reset(struct rk3368_ddrphy *ddrphy)
+{
+	/*
+	 * The analog part of the PHY should be release at least 1000
+	 * DRAM cycles before the digital part of the PHY (waiting for
+	 * 5us will ensure this for a DRAM clock as low as 200MHz).
+	 */
+	clrbits_le32(&ddrphy->reg[0], BIT(3) | BIT(2));
+	udelay(1);
+	setbits_le32(&ddrphy->reg[0], BIT(2));
+	udelay(5);
+	setbits_le32(&ddrphy->reg[0], BIT(3));
+}
+
+static void ddrphy_config_delays(struct rk3368_ddrphy *ddrphy, u32 freq)
+{
+	u32 dqs_dll_delay;
+
+	setbits_le32(&ddrphy->reg[0x13], BIT(4));
+	clrbits_le32(&ddrphy->reg[0x14], BIT(3));
+
+	setbits_le32(&ddrphy->reg[0x26], BIT(4));
+	clrbits_le32(&ddrphy->reg[0x27], BIT(3));
+
+	setbits_le32(&ddrphy->reg[0x36], BIT(4));
+	clrbits_le32(&ddrphy->reg[0x37], BIT(3));
+
+	setbits_le32(&ddrphy->reg[0x46], BIT(4));
+	clrbits_le32(&ddrphy->reg[0x47], BIT(3));
+
+	setbits_le32(&ddrphy->reg[0x56], BIT(4));
+	clrbits_le32(&ddrphy->reg[0x57], BIT(3));
+
+	if (freq <= 400000000)
+		setbits_le32(&ddrphy->reg[0xa4], 0x1f);
+	else
+		clrbits_le32(&ddrphy->reg[0xa4], 0x1f);
+
+	if (freq < 681000000)
+		dqs_dll_delay = 3; /* 67.5 degree delay */
+	else
+		dqs_dll_delay = 2; /* 45 degree delay */
+
+	writel(dqs_dll_delay, &ddrphy->reg[0x28]);
+	writel(dqs_dll_delay, &ddrphy->reg[0x38]);
+	writel(dqs_dll_delay, &ddrphy->reg[0x48]);
+	writel(dqs_dll_delay, &ddrphy->reg[0x58]);
+}
+
+static int dfi_cfg(struct rk3368_ddr_pctl *pctl)
+{
+	const ulong timeout_ms = 200;
+	ulong tmp;
+
+	writel(DFI_DATA_BYTE_DISABLE_EN, &pctl->dfistcfg0);
+
+	writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN,
+	       &pctl->dfistcfg1);
+	writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
+	writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN,
+	       &pctl->dfilpcfg0);
+
+	writel(1, &pctl->dfitphyupdtype0);
+
+	writel(0x1f, &pctl->dfitphyrdlat);
+	writel(0, &pctl->dfitphywrdata);
+	writel(0, &pctl->dfiupdcfg);  /* phyupd and ctrlupd disabled */
+
+	setbits_le32(&pctl->dfistcfg0, DFI_INIT_START);
+
+	tmp = get_timer(0);
+	do {
+		if (get_timer(tmp) > timeout_ms) {
+			error("%s: DFI init did not complete within %ld ms\n",
+			      __func__, timeout_ms);
+			return -ETIME;
+		}
+	} while ((readl(&pctl->dfiststat0) & 1) == 0);
+
+	return 0;
+}
+
+static inline u32 ps_to_tCK(const u32 ps, const ulong freq)
+{
+	const ulong MHz = 1000000;
+	return DIV_ROUND_UP(ps * freq, 1000000 * MHz);
+}
+
+static inline u32 ns_to_tCK(const u32 ns, const ulong freq)
+{
+	return ps_to_tCK(ns * 1000, freq);
+}
+
+static inline u32 tCK_to_ps(const ulong tCK, const ulong freq)
+{
+	const ulong MHz = 1000000;
+	return DIV_ROUND_UP(tCK * 1000000 * MHz, freq);
+}
+
+static int pctl_calc_timings(struct rk3368_sdram_params *params,
+			      ulong freq)
+{
+	struct rk3288_sdram_pctl_timing *pctl_timing = &params->pctl_timing;
+	const ulong MHz = 1000000;
+	u32 tccd;
+	u32 tfaw_as_ps;
+
+	if (params->ddr_speed_bin != DDR3_1600K) {
+		error("%s: unimplemented DDR3 speed bin %d\n",
+		      __func__, params->ddr_speed_bin);
+		return -1;
+	}
+
+	/* PCTL is clocked at 1/2 the DRAM clock; err on the side of caution */
+	pctl_timing->togcnt1u = DIV_ROUND_UP(freq, 2 * MHz);
+	pctl_timing->togcnt100n = DIV_ROUND_UP(freq / 10, 2 * MHz);
+
+	pctl_timing->tinit = 200;                 /* 200 usec                */
+	pctl_timing->trsth = 500;                 /* 500 usec                */
+	pctl_timing->trefi = 78;                  /* 7.8usec = 78 * 100ns    */
+	params->trefi_mem_ddr3 = ns_to_tCK(pctl_timing->trefi * 100, freq);
+
+	if (freq <= (400 * MHz)) {
+		pctl_timing->tcl = 6;
+		pctl_timing->tcwl = 10;
+	} else if (freq <= (533 * MHz)) {
+		pctl_timing->tcl = 8;
+		pctl_timing->tcwl = 6;
+	} else if (freq <= (666 * MHz)) {
+		pctl_timing->tcl = 10;
+		pctl_timing->tcwl = 7;
+	} else {
+		pctl_timing->tcl = 11;
+		pctl_timing->tcwl = 8;
+	}
+
+	pctl_timing->tmrd = 4;                    /* 4 tCK (all speed bins)  */
+	pctl_timing->trfc = ns_to_tCK(350, freq); /* tRFC: 350 (max) @ 8GBit */
+	pctl_timing->trp = max(4u, ps_to_tCK(13750, freq));
+	/*
+	 * JESD-79:
+	 *   READ to WRITE Command Delay = RL + tCCD / 2 + 2tCK - WL
+	 */
+	tccd = 4;
+	pctl_timing->trtw = pctl_timing->tcl + tccd/2 + 2 - pctl_timing->tcwl;
+	pctl_timing->tal = 0;
+	pctl_timing->tras = ps_to_tCK(35000, freq);
+	pctl_timing->trc = ps_to_tCK(48750, freq);
+	pctl_timing->trcd = ps_to_tCK(13750, freq);
+	pctl_timing->trrd = max(4u, ps_to_tCK(7500, freq));
+	pctl_timing->trtp = max(4u, ps_to_tCK(7500, freq));
+	pctl_timing->twr = ps_to_tCK(15000, freq);
+	/* The DDR3 mode-register does only support even values for tWR > 8. */
+	if (pctl_timing->twr > 8)
+		pctl_timing->twr = (pctl_timing->twr + 1) & ~1;
+	pctl_timing->twtr = max(4u, ps_to_tCK(7500, freq));
+	pctl_timing->texsr = 512;                 /* tEXSR(max) is tDLLLK    */
+	pctl_timing->txp = max(3u, ps_to_tCK(6000, freq));
+	pctl_timing->txpdll = max(10u, ps_to_tCK(24000, freq));
+	pctl_timing->tzqcs = max(64u, ps_to_tCK(80000, freq));
+	pctl_timing->tzqcsi = 10000;               /* as used by Rockchip    */
+	pctl_timing->tdqs = 1;                     /* fixed for DDR3         */
+	pctl_timing->tcksre = max(5u, ps_to_tCK(10000, freq));
+	pctl_timing->tcksrx = max(5u, ps_to_tCK(10000, freq));
+	pctl_timing->tcke = max(3u, ps_to_tCK(5000, freq));
+	pctl_timing->tmod = max(12u, ps_to_tCK(15000, freq));
+	pctl_timing->trstl = ns_to_tCK(100, freq);
+	pctl_timing->tzqcl = max(256u, ps_to_tCK(320000, freq));   /* tZQoper */
+	pctl_timing->tmrr = 0;
+	pctl_timing->tckesr = pctl_timing->tcke + 1;  /* JESD-79: tCKE + 1tCK */
+	pctl_timing->tdpd = 0;    /* RK3368 TRM: "allowed values for DDR3: 0" */
+
+
+	/*
+	 * The controller can represent tFAW as 4x, 5x or 6x tRRD only.
+	 * We want to use the smallest multiplier that satisfies the tFAW
+	 * requirements of the given speed-bin.  If necessary, we stretch out
+	 * tRRD to allow us to operate on a 6x multiplier for tFAW.
+	 */
+	tfaw_as_ps = 40000;      /* 40ns: tFAW for DDR3-1600K, 2KB page-size */
+	if (tCK_to_ps(pctl_timing->trrd * 6, freq) < tfaw_as_ps) {
+		/* If tFAW is > 6 x tRRD, we need to stretch tRRD */
+		pctl_timing->trrd = ps_to_tCK(DIV_ROUND_UP(40000, 6), freq);
+		params->tfaw_mult = TFAW_TRRD_MULT6;
+	} else if (tCK_to_ps(pctl_timing->trrd * 5, freq) < tfaw_as_ps) {
+		params->tfaw_mult = TFAW_TRRD_MULT6;
+	} else if (tCK_to_ps(pctl_timing->trrd * 4, freq) < tfaw_as_ps) {
+		params->tfaw_mult = TFAW_TRRD_MULT5;
+	} else {
+		params->tfaw_mult = TFAW_TRRD_MULT4;
+	}
+
+	return 0;
+}
+
+static void pctl_cfg(struct rk3368_ddr_pctl *pctl,
+		     struct rk3368_sdram_params *params,
+		     struct rk3368_grf *grf)
+{
+	/* Configure PCTL timing registers */
+	params->pctl_timing.trefi |= BIT(31);   /* see PCTL_TREFI */
+	copy_to_reg(&pctl->togcnt1u, &params->pctl_timing.togcnt1u,
+		    sizeof(params->pctl_timing));
+	writel(params->trefi_mem_ddr3, &pctl->trefi_mem_ddr3);
+
+	/* Set up ODT write selector and ODT write length */
+	writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), &pctl->dfiodtcfg);
+	writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1);
+
+	/* Set up the CL/CWL-dependent timings of DFI */
+	writel((params->pctl_timing.tcl - 1) / 2 - 1, &pctl->dfitrddataen);
+	writel((params->pctl_timing.tcwl - 1) / 2 - 1, &pctl->dfitphywrlat);
+
+	/* DDR3 */
+	writel(params->tfaw_mult | DDR3_EN | DDR2_DDR3_BL_8, &pctl->mcfg);
+	writel(0x001c0004, &grf->ddrc0_con0);
+
+	setbits_le32(&pctl->scfg, HW_LOW_POWER_EN);
+}
+
+static int ddrphy_data_training(struct rk3368_ddr_pctl *pctl,
+				struct rk3368_ddrphy *ddrphy)
+{
+	const u32 trefi = readl(&pctl->trefi);
+	const ulong timeout_ms = 500;
+	ulong tmp;
+
+	/* disable auto-refresh */
+	writel(0 | BIT(31), &pctl->trefi);
+
+	clrsetbits_le32(&ddrphy->reg[2], 0x33, 0x20);
+	clrsetbits_le32(&ddrphy->reg[2], 0x33, 0x21);
+
+	tmp = get_timer(0);
+	do {
+		if (get_timer(tmp) > timeout_ms) {
+			error("%s: did not complete within %ld ms\n",
+			      __func__, timeout_ms);
+			return -ETIME;
+		}
+	} while ((readl(&ddrphy->reg[0xff]) & 0xf) != 0xf);
+
+	send_command(pctl, MCMD_RANK0 | MCMD_RANK1, PREA_CMD);
+	clrsetbits_le32(&ddrphy->reg[2], 0x33, 0x20);
+	/* resume auto-refresh */
+	writel(trefi | BIT(31), &pctl->trefi);
+
+	return 0;
+}
+
+static int sdram_col_row_detect(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rk3368_sdram_params *params = dev_get_platdata(dev);
+	struct rk3368_ddr_pctl *pctl = priv->pctl;
+	struct rk3368_msch *msch = priv->msch;
+	const u32 test_pattern = 0x5aa5f00f;
+	int row, col;
+	uintptr_t addr;
+
+	move_to_config_state(pctl);
+	writel(6, &msch->ddrconf);
+	move_to_access_state(pctl);
+
+	/* Detect col */
+	for (col = 11; col >= 9; col--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE +
+			(1 << (col + params->chan.bw - 1));
+		writel(test_pattern, addr);
+		if ((readl(addr) == test_pattern) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+
+	if (col == 8) {
+		error("%s: col detect error\n", __func__);
+		return -EINVAL;
+	}
+
+	move_to_config_state(pctl);
+	writel(15, &msch->ddrconf);
+	move_to_access_state(pctl);
+
+	/* Detect row*/
+	for (row = 16; row >= 12; row--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1));
+		writel(test_pattern, addr);
+		if ((readl(addr) == test_pattern) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+
+	if (row == 11) {
+		error("%s: row detect error\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Record results */
+	debug("%s: col %d, row %d\n", __func__, col, row);
+	params->chan.col = col;
+	params->chan.cs0_row = row;
+	params->chan.cs1_row = row;
+	params->chan.row_3_4 = 0;
+
+	return 0;
+}
+
+static int msch_niu_config(struct rk3368_msch *msch,
+			   struct rk3368_sdram_params *params)
+{
+	int i;
+	const u8 cols =	params->chan.col - ((params->chan.bw == 2) ? 0 : 1);
+	const u8 rows = params->chan.cs0_row;
+
+	/*
+	 * The DDR address-translation table always assumes a 32bit
+	 * bus and the comparison below takes care of adjusting for
+	 * a 16bit bus (i.e. one column-address is consumed).
+	 */
+	const struct {
+		u8 rows;
+		u8 columns;
+		u8 type;
+	} ddrconf_table[] = {
+		/*
+		 * C-B-R-D patterns are first. For these we require an
+		 * exact match for the columns and rows (as there's
+		 * one entry per possible configuration).
+		 */
+		[0] =  { .rows = 13, .columns = 10, .type = DMC_MSCH_CBRD },
+		[1] =  { .rows = 14, .columns = 10, .type = DMC_MSCH_CBRD },
+		[2] =  { .rows = 15, .columns = 10, .type = DMC_MSCH_CBRD },
+		[3] =  { .rows = 16, .columns = 10, .type = DMC_MSCH_CBRD },
+		[4] =  { .rows = 14, .columns = 11, .type = DMC_MSCH_CBRD },
+		[5] =  { .rows = 15, .columns = 11, .type = DMC_MSCH_CBRD },
+		[6] =  { .rows = 16, .columns = 11, .type = DMC_MSCH_CBRD },
+		[7] =  { .rows = 13, .columns = 9, .type = DMC_MSCH_CBRD },
+		[8] =  { .rows = 14, .columns = 9, .type = DMC_MSCH_CBRD },
+		[9] =  { .rows = 15, .columns = 9, .type = DMC_MSCH_CBRD },
+		[10] = { .rows = 16, .columns = 9, .type = DMC_MSCH_CBRD },
+		/*
+		 * 11 through 13 are C-R-B-D patterns. These are
+		 * matched for an exact number of columns and to
+		 * ensure that the hardware uses at least as many rows
+		 * as the pattern requires (i.e. we make sure that
+		 * there's no gaps up until we hit the device/chip-select;
+		 * however, these patterns can accept up to 16 rows,
+		 * as the row-address continues right after the CS
+		 * switching)
+		 */
+		[11] = { .rows = 15, .columns = 10, .type = DMC_MSCH_CRBD },
+		[12] = { .rows = 14, .columns = 11, .type = DMC_MSCH_CRBD },
+		[13] = { .rows = 13, .columns = 10, .type = DMC_MSCH_CRBD },
+		/*
+		 * 14 and 15 are catch-all variants using a C-B-D-R
+		 * scheme (i.e. alternating the chip-select every time
+		 * C-B overflows) and stuffing the remaining C-bits
+		 * into the top. Matching needs to make sure that the
+		 * number of columns is either an exact match (i.e. we
+		 * can use less the the maximum number of rows) -or-
+		 * that the columns exceed what is given in this table
+		 * and the rows are an exact match (in which case the
+		 * remaining C-bits will be stuffed onto the top after
+		 * the device/chip-select switches).
+		 */
+		[14] = { .rows = 16, .columns = 10, .type = DMC_MSCH_CBDR },
+		[15] = { .rows = 16, .columns = 9, .type = DMC_MSCH_CBDR },
+	};
+
+	/*
+	 * For C-B-R-D, we need an exact match (i.e. both for the number of
+	 * columns and rows), while for C-B-D-R, only the the number of
+	 * columns needs to match.
+	 */
+	for (i = 0; i < ARRAY_SIZE(ddrconf_table); i++) {
+		bool match = false;
+
+		/* If this entry if for a different matcher, then skip it */
+		if (ddrconf_table[i].type != params->memory_schedule)
+			continue;
+
+		/*
+		 * Match according to the rules (exact/inexact/at-least)
+		 * documented in the ddrconf_table above.
+		 */
+		switch (params->memory_schedule) {
+		case DMC_MSCH_CBRD:
+			match = (ddrconf_table[i].columns == cols) &&
+				(ddrconf_table[i].rows == rows);
+			break;
+
+		case DMC_MSCH_CRBD:
+			match = (ddrconf_table[i].columns == cols) &&
+				(ddrconf_table[i].rows <= rows);
+			break;
+
+		case DMC_MSCH_CBDR:
+			match = (ddrconf_table[i].columns == cols) ||
+				((ddrconf_table[i].columns <= cols) &&
+				 (ddrconf_table[i].rows == rows));
+			break;
+
+		default:
+			break;
+		}
+
+		if (match) {
+			debug("%s: setting ddrconf 0x%x\n", __func__, i);
+			writel(i, &msch->ddrconf);
+			return 0;
+		}
+	}
+
+	error("%s: ddrconf (NIU config) not found\n", __func__);
+	return -EINVAL;
+}
+
+static void dram_all_config(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rk3368_pmu_grf *pmugrf = priv->pmugrf;
+	struct rk3368_sdram_params *params = dev_get_platdata(dev);
+	const struct rk3288_sdram_channel *info = &params->chan;
+	u32 sys_reg = 0;
+	const int chan = 0;
+
+	sys_reg |= DDR3 << SYS_REG_DDRTYPE_SHIFT;
+	sys_reg |= 0 << SYS_REG_NUM_CH_SHIFT;
+
+	sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan);
+	sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan);
+	sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan);
+	sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan);
+	sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan);
+	sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan);
+	sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan);
+	sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan);
+	sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan);
+
+	writel(sys_reg, &pmugrf->os_reg[2]);
+}
+
+static int setup_sdram(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rk3368_sdram_params *params = dev_get_platdata(dev);
+
+	struct rk3368_ddr_pctl *pctl = priv->pctl;
+	struct rk3368_ddrphy *ddrphy = priv->phy;
+	struct rk3368_cru *cru = priv->cru;
+	struct rk3368_grf *grf = priv->grf;
+	struct rk3368_msch *msch = priv->msch;
+
+	int ret;
+
+	/* The input clock (i.e. DPLL) needs to be 2x the DRAM frequency */
+	ret = clk_set_rate(&priv->ddr_clk, 2 * params->ddr_freq);
+	if (ret < 0) {
+		debug("%s: could not set DDR clock: %d\n", __func__, ret);
+		return ret;
+	}
+
+	/* Update the read-latency for the RK3368 */
+	writel(0x32, &msch->readlatency);
+
+	/* Initialise the DDR PCTL and DDR PHY */
+	ddrctl_reset(cru);
+	ddrphy_reset(ddrphy);
+	ddrphy_config_delays(ddrphy, params->ddr_freq);
+	dfi_cfg(pctl);
+	/* Configure relative system information of grf_ddrc0_con0 register */
+	ddr_set_ddr3_mode(grf, true);
+	ddr_set_noc_spr_err_stall(grf, true);
+	/* Calculate timings */
+	pctl_calc_timings(params, params->ddr_freq);
+	/* Initialise the device timings in protocol controller */
+	pctl_cfg(pctl, params, grf);
+	/* Configure AL, CL ... information of PHY registers */
+	ddrphy_config(ddrphy,
+		      params->pctl_timing.tcl,
+		      params->pctl_timing.tal,
+		      params->pctl_timing.tcwl);
+
+	/* Initialize DRAM and configure with mode-register values */
+	ret = memory_init(pctl, params);
+	if (ret)
+		goto error;
+
+	move_to_config_state(pctl);
+	/* Perform data-training */
+	ddrphy_data_training(pctl, ddrphy);
+	move_to_access_state(pctl);
+
+	/* TODO(prt): could detect rank in training... */
+	params->chan.rank = 2;
+	/* TODO(prt): bus width is not auto-detected (yet)... */
+	params->chan.bw = 2;  /* 32bit wide bus */
+	params->chan.dbw = params->chan.dbw;  /* 32bit wide bus */
+
+	/* DDR3 is always 8 bank */
+	params->chan.bk = 3;
+	/* Detect col and row number */
+	ret = sdram_col_row_detect(dev);
+	if (ret)
+		goto error;
+
+	/* Configure NIU DDR configuration */
+	ret = msch_niu_config(msch, params);
+	if (ret)
+		goto error;
+
+	/* set up OS_REG to communicate w/ next stage and OS */
+	dram_all_config(dev);
+
+	return 0;
+
+error:
+	printf("DRAM init failed!\n");
+	hang();
+}
+#endif
+
+static int rk3368_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+	int ret = 0;
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3368_sdram_params *plat = dev_get_platdata(dev);
+
+	ret = regmap_init_mem(dev, &plat->map);
+	if (ret)
+		return ret;
+#endif
+
+	return ret;
+}
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rk3368_sdram_params *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3368_dmc *of_plat = &plat->of_plat;
+	int ret;
+
+	plat->ddr_freq = of_plat->rockchip_ddr_frequency;
+	plat->ddr_speed_bin = of_plat->rockchip_ddr_speed_bin;
+	plat->memory_schedule = of_plat->rockchip_memory_schedule;
+
+	ret = regmap_init_mem_platdata(dev, of_plat->reg,
+				       ARRAY_SIZE(of_plat->reg) / 2,
+				       &plat->map);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static int rk3368_dmc_probe(struct udevice *dev)
+{
+#ifdef CONFIG_TPL_BUILD
+	struct rk3368_sdram_params *plat = dev_get_platdata(dev);
+	struct rk3368_ddr_pctl *pctl;
+	struct rk3368_ddrphy *ddrphy;
+	struct rk3368_cru *cru;
+	struct rk3368_grf *grf;
+	struct rk3368_msch *msch;
+	int ret;
+	struct udevice *dev_clk;
+#endif
+	struct dram_info *priv = dev_get_priv(dev);
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	ret = conv_of_platdata(dev);
+	if (ret)
+		return ret;
+#endif
+
+	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
+
+#ifdef CONFIG_TPL_BUILD
+	pctl = regmap_get_range(plat->map, 0);
+	ddrphy = regmap_get_range(plat->map, 1);
+	msch = syscon_get_first_range(ROCKCHIP_SYSCON_MSCH);
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+	priv->pctl = pctl;
+	priv->phy = ddrphy;
+	priv->msch = msch;
+	priv->grf = grf;
+
+	ret = rockchip_get_clk(&dev_clk);
+	if (ret)
+		return ret;
+	priv->ddr_clk.id = CLK_DDR;
+	ret = clk_request(dev_clk, &priv->ddr_clk);
+	if (ret)
+		return ret;
+
+	cru = rockchip_get_cru();
+	priv->cru = cru;
+	if (IS_ERR(priv->cru))
+		return PTR_ERR(priv->cru);
+
+	ret = setup_sdram(dev);
+	if (ret)
+		return ret;
+#endif
+
+	priv->info.base = 0;
+	priv->info.size =
+		rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg[2]);
+
+	/*
+	* we use the 0x00000000~0xfdffffff space since 0xff000000~0xffffffff
+	* is SoC register space (i.e. reserved), and 0xfe000000~0xfeffffff is
+	* inaccessible for some IP controller.
+	*/
+	priv->info.size = min(priv->info.size, (size_t)0xfe000000);
+
+	return 0;
+}
+
+static int rk3368_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	*info = priv->info;
+	return 0;
+}
+
+static struct ram_ops rk3368_dmc_ops = {
+	.get_info = rk3368_dmc_get_info,
+};
+
+
+static const struct udevice_id rk3368_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3368-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk3368) = {
+	.name = "rockchip_rk3368_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk3368_dmc_ids,
+	.ops = &rk3368_dmc_ops,
+	.probe = rk3368_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+	.ofdata_to_platdata = rk3368_dmc_ofdata_to_platdata,
+	.probe = rk3368_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+	.platdata_auto_alloc_size = sizeof(struct rk3368_sdram_params),
+};
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 7921ea0d7542762bf9663d1b14ddff32fcf26994..c70d63627704cfded3d481128a555d88f7f4ed49 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -210,6 +210,14 @@ static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
 
 static int rockchip_spi_calc_modclk(ulong max_freq)
 {
+	/*
+	 * While this is not strictly correct for the RK3368, as the
+	 * GPLL will be 576MHz, things will still work, as the
+	 * clk_set_rate(...) implementation in our clock-driver will
+	 * chose the next closest rate not exceeding what we request
+	 * based on the output of this function.
+	 */
+
 	unsigned div;
 	const unsigned long gpll_hz = 594000000UL;
 
@@ -443,6 +451,7 @@ static const struct dm_spi_ops rockchip_spi_ops = {
 
 static const struct udevice_id rockchip_spi_ids[] = {
 	{ .compatible = "rockchip,rk3288-spi" },
+	{ .compatible = "rockchip,rk3368-spi" },
 	{ .compatible = "rockchip,rk3399-spi" },
 	{ }
 };
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index c666303331165dcf2e100adcf3fea41a0db660c1..13f122350b2f86086555230c21e2e32bb0eba4ed 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -9,6 +9,24 @@ config TIMER
 	  will be used. The timer is usually a 32 bits free-running up
 	  counter. There may be no real tick, and no timer interrupt.
 
+config SPL_TIMER
+	bool "Enable driver model for timer drivers in SPL"
+	depends on TIMER && SPL
+	help
+	  Enable support for timer drivers in SPL. These can be used to get
+	  a timer value when in SPL, or perhaps for implementing a delay
+	  function. This enables the drivers in drivers/timer as part of an
+	  SPL build.
+
+config TPL_TIMER
+	bool "Enable driver model for timer drivers in TPL"
+	depends on TIMER && TPL
+	help
+	  Enable support for timer drivers in TPL. These can be used to get
+	  a timer value when in TPL, or perhaps for implementing a delay
+	  function. This enables the drivers in drivers/timer as part of an
+	  TPL build.
+
 config TIMER_EARLY
 	bool "Allow timer to be used early in U-Boot"
 	depends on TIMER
@@ -85,4 +103,11 @@ config AE3XX_TIMER
 	help
 	  Select this to enable a timer for AE3XX devices.
 
+config ROCKCHIP_TIMER
+        bool "Rockchip timer support"
+	depends on TIMER
+	help
+	  Select this to enable support for the timer found on
+	  Rockchip devices.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index ced7bd66bd30407d692bd71257461fb1b129eb8e..fa7ce7c835838eb07dc0d4c95cf1e1bf2bd7ab41 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -4,7 +4,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_TIMER)		+= timer-uclass.o
+obj-y += timer-uclass.o
 obj-$(CONFIG_ALTERA_TIMER)	+= altera_timer.o
 obj-$(CONFIG_SANDBOX_TIMER)	+= sandbox_timer.o
 obj-$(CONFIG_X86_TSC_TIMER)	+= tsc_timer.o
@@ -14,3 +14,4 @@ obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
 obj-$(CONFIG_ARC_TIMER)	+= arc_timer.o
 obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o
 obj-$(CONFIG_AE3XX_TIMER) += ae3xx_timer.o
+obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..0848033c66257630b987ed14b0411280cb08662b
--- /dev/null
+++ b/drivers/timer/rockchip_timer.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <asm/arch/timer.h>
+#include <dt-structs.h>
+#include <timer.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+struct rockchip_timer_plat {
+	struct dtd_rockchip_rk3368_timer dtd;
+};
+#endif
+
+/* Driver private data. Contains timer id. Could be either 0 or 1. */
+struct rockchip_timer_priv {
+	struct rk_timer *timer;
+};
+
+static int rockchip_timer_get_count(struct udevice *dev, u64 *count)
+{
+	struct rockchip_timer_priv *priv = dev_get_priv(dev);
+	uint64_t timebase_h, timebase_l;
+	uint64_t cntr;
+
+	timebase_l = readl(&priv->timer->timer_curr_value0);
+	timebase_h = readl(&priv->timer->timer_curr_value1);
+
+	/* timers are down-counting */
+	cntr = timebase_h << 32 | timebase_l;
+	*count = ~0ull - cntr;
+	return 0;
+}
+
+static int rockchip_clk_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rockchip_timer_priv *priv = dev_get_priv(dev);
+
+	priv->timer = (struct rk_timer *)devfdt_get_addr(dev);
+#endif
+
+	return 0;
+}
+
+static int rockchip_timer_start(struct udevice *dev)
+{
+	struct rockchip_timer_priv *priv = dev_get_priv(dev);
+	const uint64_t reload_val = ~0uLL;
+	const uint32_t reload_val_l = reload_val & 0xffffffff;
+	const uint32_t reload_val_h = reload_val >> 32;
+
+	/* disable timer and reset all control */
+	writel(0, &priv->timer->timer_ctrl_reg);
+	/* write reload value */
+	writel(reload_val_l, &priv->timer->timer_load_count0);
+	writel(reload_val_h, &priv->timer->timer_load_count1);
+	/* enable timer */
+	writel(1, &priv->timer->timer_ctrl_reg);
+
+	return 0;
+}
+
+static int rockchip_timer_probe(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct rockchip_timer_priv *priv = dev_get_priv(dev);
+	struct rockchip_timer_plat *plat = dev_get_platdata(dev);
+
+	priv->timer = map_sysmem(plat->dtd.reg[1], plat->dtd.reg[3]);
+	uc_priv->clock_rate = plat->dtd.clock_frequency;
+#endif
+
+	return rockchip_timer_start(dev);
+}
+
+static const struct timer_ops rockchip_timer_ops = {
+	.get_count = rockchip_timer_get_count,
+};
+
+static const struct udevice_id rockchip_timer_ids[] = {
+	{ .compatible = "rockchip,rk3368-timer" },
+	{}
+};
+
+U_BOOT_DRIVER(arc_timer) = {
+	.name	= "rockchip_rk3368_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = rockchip_timer_ids,
+	.probe = rockchip_timer_probe,
+	.ops	= &rockchip_timer_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size = sizeof(struct rockchip_timer_priv),
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	.platdata_auto_alloc_size = sizeof(struct rockchip_timer_plat),
+#endif
+	.ofdata_to_platdata = rockchip_clk_ofdata_to_platdata,
+};
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
index ec10b282882f1681eab70b6f78169bcb942fd19f..a84755f4c5a4e6263c9f1ebadeedd76a3961380e 100644
--- a/drivers/timer/timer-uclass.c
+++ b/drivers/timer/timer-uclass.c
@@ -42,6 +42,7 @@ unsigned long notrace timer_get_rate(struct udevice *dev)
 
 static int timer_pre_probe(struct udevice *dev)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct clk timer_clk;
 	int err;
@@ -56,6 +57,7 @@ static int timer_pre_probe(struct udevice *dev)
 	} else
 		uc_priv->clock_rate = fdtdec_get_int(gd->fdt_blob,
 				dev_of_offset(dev),	"clock-frequency", 0);
+#endif
 
 	return 0;
 }
@@ -81,16 +83,18 @@ u64 timer_conv_64(u32 count)
 
 int notrace dm_timer_init(void)
 {
-	const void *blob = gd->fdt_blob;
+	__maybe_unused const void *blob = gd->fdt_blob;
 	struct udevice *dev = NULL;
-	int node;
+	int node = -ENOENT;
 	int ret;
 
 	if (gd->timer)
 		return 0;
 
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	/* Check for a chosen timer to be used for tick */
 	node = fdtdec_get_chosen_node(blob, "tick-timer");
+#endif
 	if (node < 0) {
 		/* No chosen timer, trying first available timer */
 		ret = uclass_first_device_err(UCLASS_TIMER, &dev);
diff --git a/dts/Kconfig b/dts/Kconfig
index 1bc9656faee6565563bac204a29e6efac2320ac1..b4b7ddc1444a0b0b16e275fa0365322f5c05b1c0 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -32,6 +32,14 @@ config SPL_OF_CONTROL
 	  which is not enough to support device tree. Enable this option to
 	  allow such boards to be supported by U-Boot SPL.
 
+config TPL_OF_CONTROL
+	bool "Enable run-time configuration via Device Tree in TPL"
+	depends on TPL && OF_CONTROL
+	help
+	  Some boards use device tree in U-Boot but only have 4KB of SRAM
+	  which is not enough to support device tree. Enable this option to
+	  allow such boards to be supported by U-Boot TPL.
+
 config OF_LIVE
 	bool "Enable use of a live tree"
 	depends on OF_CONTROL
@@ -136,4 +144,25 @@ config SPL_OF_PLATDATA
 	  declarations for each node. See README.platdata for more
 	  information.
 
+config TPL_OF_PLATDATA
+	bool "Generate platform data for use in TPL"
+	depends on TPL_OF_CONTROL
+	help
+	  For very constrained SPL environments the overhead of decoding
+	  device tree nodes and converting their contents into platform data
+	  is too large. This overhead includes libfdt code as well as the
+	  device tree contents itself. The latter is fairly compact, but the
+	  former can add 3KB or more to a Thumb 2 Image.
+
+	  This option enables generation of platform data from the device
+	  tree as C code. This code creates devices using U_BOOT_DEVICE()
+	  declarations. The benefit is that it allows driver code to access
+	  the platform data directly in C structures, avoidin the libfdt
+	  overhead.
+
+	  This option works by generating C structure declarations for each
+	  compatible string, then adding platform data and U_BOOT_DEVICE
+	  declarations for each node. See README.platdata for more
+	  information.
+
 endmenu
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 9c419dee415f3c199e3f655b4fcb6d646d3ab335..c9420b2d739cd5d10f7fe6467a7f77b03e87f281 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -191,8 +191,6 @@
 #define CONFIG_SYS_BOOTCOUNT_BE
 
 /* USB gadget RNDIS */
-
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 #endif
 
 #ifdef CONFIG_NAND
diff --git a/include/configs/am335x_igep003x.h b/include/configs/am335x_igep003x.h
index d9f05eb55d2b1b402ceb06bb614750c6fc973b37..9b14603918c34d3e19254569e9a02882dcd7f37f 100644
--- a/include/configs/am335x_igep003x.h
+++ b/include/configs/am335x_igep003x.h
@@ -123,7 +123,6 @@
 #define MTDPARTS_DEFAULT		"mtdparts=omap2-nand.0:512k(SPL),-(UBI)"
 
 /* SPL */
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /* UBI configuration */
 #define CONFIG_SPL_UBI			1
diff --git a/include/configs/am335x_shc.h b/include/configs/am335x_shc.h
index b1e44bbbb40741266c7711c57bb8fe5798ea8659..62ab2d7227e0a92b76105e203d554284a5b43220 100644
--- a/include/configs/am335x_shc.h
+++ b/include/configs/am335x_shc.h
@@ -246,8 +246,6 @@
 
 /* SPL */
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #ifndef CONFIG_SPL_USBETH_SUPPORT
 #define CONFIG_FASTBOOT_FLASH_MMC_DEV   1
 #endif
diff --git a/include/configs/am335x_sl50.h b/include/configs/am335x_sl50.h
index 13ff2b277aebc76825c63b8dea00b0148c3c92fe..62af3fa9ff49abf9a26e67dbe2f8c35f419caada 100644
--- a/include/configs/am335x_sl50.h
+++ b/include/configs/am335x_sl50.h
@@ -78,8 +78,6 @@
 #define CONFIG_BOOTCOUNT_AM33XX
 #define CONFIG_SYS_BOOTCOUNT_BE
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #ifndef CONFIG_SPL_USBETH_SUPPORT
 #define CONFIG_FASTBOOT_FLASH_MMC_DEV   1
 #endif
diff --git a/include/configs/am3517_crane.h b/include/configs/am3517_crane.h
index aeba61ea59ebdd886ed645d957a1b01859703aa7..0502b567e6582fb92bd039a189da9d5f00b7be7f 100644
--- a/include/configs/am3517_crane.h
+++ b/include/configs/am3517_crane.h
@@ -257,7 +257,6 @@
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /* NAND boot config */
 #define CONFIG_SYS_NAND_BUSWIDTH_16BIT
diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h
index 60460c8105eced60eb17f5e9ccef715d3585a264..e957a28b6bfbfbdd256dffc1fd7137fbdeb777c5 100644
--- a/include/configs/am3517_evm.h
+++ b/include/configs/am3517_evm.h
@@ -305,6 +305,5 @@
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 6a35a0884f4c06767e4aa27c47de0cc5b2d5d736..b84f6e3480cb118d9fbb14f9de249341c9d186b4 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -71,8 +71,6 @@
 /* NS16550 Configuration */
 #define CONFIG_SYS_NS16550_COM1		0x44e09000	/* Base EVM has UART0 */
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 /* SPL USB Support */
 
 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
diff --git a/include/configs/apf27.h b/include/configs/apf27.h
index 29cbbabd1e0bc1ca12bb32c5d27b7b043f04fe40..5c5d223e84837cedbc5c1c14e77b2fc25cd6e3a0 100644
--- a/include/configs/apf27.h
+++ b/include/configs/apf27.h
@@ -27,7 +27,6 @@
  * SPL
  */
 #define CONFIG_SPL_TARGET	"u-boot-with-spl.bin"
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 #define CONFIG_SPL_MAX_SIZE	2048
 #define CONFIG_SPL_TEXT_BASE    0xA0000000
 
diff --git a/include/configs/at91sam9m10g45ek.h b/include/configs/at91sam9m10g45ek.h
index 019006a84abcf1eca5ff704a74ebae509ea10a47..ee6ab4163179c40c71daf5813786cb643669e5ae 100644
--- a/include/configs/at91sam9m10g45ek.h
+++ b/include/configs/at91sam9m10g45ek.h
@@ -136,7 +136,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START	0x70080000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x00080000
 
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/at91sam9n12ek.h b/include/configs/at91sam9n12ek.h
index db046627994386d6d0408c4523ca0b36c187d23e..089b865ac2427e254d795e9ce0dce32d9a301e42 100644
--- a/include/configs/at91sam9n12ek.h
+++ b/include/configs/at91sam9n12ek.h
@@ -189,7 +189,6 @@
 #define CONFIG_SYS_MCKR_CSS		0x1302
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/at91sam9x5ek.h b/include/configs/at91sam9x5ek.h
index 608be149a0ed050a1813361364c763017f931101..0cb8985982d185fa12220abf6b730032958a73db 100644
--- a/include/configs/at91sam9x5ek.h
+++ b/include/configs/at91sam9x5ek.h
@@ -180,7 +180,6 @@
 #define CONFIG_SYS_MCKR_CSS		0x1302
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/baltos.h b/include/configs/baltos.h
index dbd933f30aca16a048b17492e0b7bacf49a2dbd5..185c749d78681542dc5d34a581428479fba78d20 100644
--- a/include/configs/baltos.h
+++ b/include/configs/baltos.h
@@ -241,8 +241,6 @@
 /* General network SPL, both CPSW and USB gadget RNDIS */
 #define CONFIG_SPL_NET_VCI_STRING	"AM335x U-Boot SPL"*/
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #ifdef CONFIG_NAND
 #define CONFIG_NAND_OMAP_GPMC
 #define CONFIG_NAND_OMAP_GPMC_PREFETCH
diff --git a/include/configs/bav335x.h b/include/configs/bav335x.h
index 59530beeda9518145c223a7b2013d3a1a3b23ca5..c824ebde27e6873b8ab9be398c4c975406187769 100644
--- a/include/configs/bav335x.h
+++ b/include/configs/bav335x.h
@@ -344,8 +344,6 @@ DEFAULT_LINUX_BOOT_ENV \
 #define CONFIG_SYS_BOOTCOUNT_BE
 
 /* USB gadget RNDIS */
-
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 #endif
 
 #ifdef CONFIG_NAND
diff --git a/include/configs/bur_am335x_common.h b/include/configs/bur_am335x_common.h
index f545a56d8272f00884ee8b7fdd78f098b8d8a3b2..15c481d421de97878469dce09578d270d7e36ada 100644
--- a/include/configs/bur_am335x_common.h
+++ b/include/configs/bur_am335x_common.h
@@ -102,6 +102,5 @@
 #define CONFIG_SYS_SPL_MALLOC_SIZE	CONFIG_SYS_MALLOC_LEN
 
 /* General parts of the framework, required. */
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 #endif	/* ! __BUR_AM335X_COMMON_H__ */
diff --git a/include/configs/chiliboard.h b/include/configs/chiliboard.h
index d7606c7f99aa4bf66abffa90059a3b823860b15a..fb3e67466ee0b34fb2d95d6bbc4cd494c7ffe818 100644
--- a/include/configs/chiliboard.h
+++ b/include/configs/chiliboard.h
@@ -127,8 +127,6 @@
 #define CONFIG_BOOTCOUNT_AM33XX
 #define CONFIG_SYS_BOOTCOUNT_BE
 
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/mach-omap2/u-boot-spl.lds"
-
 /* NAND: device related configs */
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 #define CONFIG_SYS_NAND_PAGE_COUNT	(CONFIG_SYS_NAND_BLOCK_SIZE / \
diff --git a/include/configs/cm_t335.h b/include/configs/cm_t335.h
index df81f7d78e7f217a735b2097b0ca78e3e31ccfc1..2287d5b6e455ec2bd8a6c5d067de362bd584a65d 100644
--- a/include/configs/cm_t335.h
+++ b/include/configs/cm_t335.h
@@ -97,7 +97,6 @@
 #define CONFIG_SYS_I2C_EEPROM_BUS	0
 
 /* SPL */
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /* Network. */
 #define CONFIG_PHY_ATHEROS
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h
index 52b713d5035662fdb250b23760506db57d345a8f..a94d55fa3abe5e11eecc90923cd25f24fde332a9 100644
--- a/include/configs/cm_t35.h
+++ b/include/configs/cm_t35.h
@@ -259,7 +259,6 @@
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
 #define CONFIG_SPL_OMAP3_ID_NAND
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /* NAND boot config */
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h
index d43d90610bd5b9bcafac29e25aeee194a0d8829d..bbc455a2440a9037324cc622616fa37fa34f2a8f 100644
--- a/include/configs/cm_t43.h
+++ b/include/configs/cm_t43.h
@@ -97,8 +97,6 @@
 #define CONFIG_ENV_OFFSET		(768 * 1024)
 #define CONFIG_ENV_SPI_MAX_HZ           48000000
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=0x80200000\0" \
 	"fdtaddr=0x81200000\0" \
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index 675e7a649e1ce080bd09d406be91d27181507648..c1f92edfa4a5168b681a5cf670de515b6cda2e11 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -291,7 +291,6 @@
 						CONFIG_SYS_MALLOC_LEN)
 #define CONFIG_SYS_SPL_MALLOC_SIZE	CONFIG_SYS_MALLOC_LEN
 #define CONFIG_SPL_SPI_LOAD
-#define CONFIG_SPL_LDSCRIPT	"board/$(BOARDDIR)/u-boot-spl-da850evm.lds"
 #define CONFIG_SPL_STACK	0x8001ff00
 #define CONFIG_SPL_TEXT_BASE	0x80000000
 #define CONFIG_SPL_MAX_FOOTPRINT	32768
diff --git a/include/configs/edminiv2.h b/include/configs/edminiv2.h
index 31364c25335c1c3276d814fe5021dd90b43107e5..235b7461f503b3bc12975fc4e9684df68f0bf465 100644
--- a/include/configs/edminiv2.h
+++ b/include/configs/edminiv2.h
@@ -24,7 +24,6 @@
 #define CONFIG_SPL_BSS_MAX_SIZE		0x0001ffff
 #define CONFIG_SYS_SPL_MALLOC_START	0x00040000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x0001ffff
-#define CONFIG_SPL_LDSCRIPT            "$(CPUDIR)/orion5x/u-boot-spl.lds"
 #define CONFIG_SYS_UBOOT_BASE		0xfff90000
 #define CONFIG_SYS_UBOOT_START		0x00800000
 #define CONFIG_SYS_TEXT_BASE 		0x00800000
diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h
index 9c9681e8ac9a85d87e33ded6bcda01c543626dc6..c90cc329ac73ae7b749dbf0e197b3cdfaa94e9e6 100644
--- a/include/configs/exynos5-common.h
+++ b/include/configs/exynos5-common.h
@@ -48,7 +48,6 @@
 #define CONFIG_SUPPORT_EMMC_BOOT
 
 /* specific .lds file */
-#define CONFIG_SPL_LDSCRIPT	"board/samsung/common/exynos-uboot-spl.lds"
 
 /* Boot Argument Buffer Size */
 /* memtest works on */
diff --git a/include/configs/imx6_spl.h b/include/configs/imx6_spl.h
index 953711269379078010b4bbe6dab08ed67edf82ad..cdb3a374bc049b197804194df58396c1ad0c1176 100644
--- a/include/configs/imx6_spl.h
+++ b/include/configs/imx6_spl.h
@@ -24,7 +24,6 @@
  *    and some padding thus 'our' max size is really 0x00908000 - 0x00918000
  *    or 64KB
  */
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/mach-omap2/u-boot-spl.lds"
 #define CONFIG_SPL_TEXT_BASE		0x00908000
 #define CONFIG_SPL_MAX_SIZE		0x10000
 #define CONFIG_SPL_STACK		0x0091FFB8
diff --git a/include/configs/ipam390.h b/include/configs/ipam390.h
index be91dc27cd8ae46e799e277eca23a543fb9e50f7..d2fc81bfe0b810bd62c436ad5c75e9dc1abbc121 100644
--- a/include/configs/ipam390.h
+++ b/include/configs/ipam390.h
@@ -261,7 +261,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SYS_TEXT_BASE - \
 						CONFIG_SYS_MALLOC_LEN)
 #define CONFIG_SYS_SPL_MALLOC_SIZE	CONFIG_SYS_MALLOC_LEN
-#define CONFIG_SPL_LDSCRIPT	"board/$(BOARDDIR)/u-boot-spl-ipam390.lds"
 #define CONFIG_SPL_STACK	0x8001ff00
 #define CONFIG_SPL_TEXT_BASE	0x80000000
 #define CONFIG_SPL_MAX_SIZE	0x20000
diff --git a/include/configs/kc1.h b/include/configs/kc1.h
index 38c5862b7212832ad04411db4134b8bc2f35dc64..36c01c0e0577f0ca545a184dffc6318ab6f28bdc 100644
--- a/include/configs/kc1.h
+++ b/include/configs/kc1.h
@@ -88,8 +88,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START	0x80208000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	(1024 * 1024)
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 /*
  * Console
  */
diff --git a/include/configs/lion_rk3368.h b/include/configs/lion_rk3368.h
new file mode 100644
index 0000000000000000000000000000000000000000..4118ffd65b41d16742524f4aed3d31387710df6d
--- /dev/null
+++ b/include/configs/lion_rk3368.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIGS_LION_RK3368_H
+#define __CONFIGS_LION_RK3368_H
+
+#include <configs/rk3368_common.h>
+
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define KERNEL_LOAD_ADDR		0x280000
+#define DTB_LOAD_ADDR			0x5600000
+#define INITRD_LOAD_ADDR		0x5bf0000
+#define CONFIG_ENV_SIZE			0x2000
+
+#endif
diff --git a/include/configs/ls1021aiot.h b/include/configs/ls1021aiot.h
index 33b62cdca236d555b070220f5ae5e0649a3cfbaf..6ef7d632959ca348afd4bb44f1629f3f765e3d51 100644
--- a/include/configs/ls1021aiot.h
+++ b/include/configs/ls1021aiot.h
@@ -76,7 +76,6 @@
 #define CONFIG_SYS_FSL_PBL_RCW	\
 	board/freescale/ls1021aiot/ls102xa_rcw_sd.cfg
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 #define CONFIG_SPL_ENV_SUPPORT
diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h
index 7c651e4efd8794b3a1c5fd8c3b6628a2007e52c6..b934d10b472ffd3674f0e7d3237b7e80267c2163 100644
--- a/include/configs/ls1021aqds.h
+++ b/include/configs/ls1021aqds.h
@@ -52,7 +52,6 @@ unsigned long get_board_ddr_clk(void);
 	board/freescale/ls1021aqds/ls102xa_rcw_sd_ifc.cfg
 #endif
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 
 #define CONFIG_SPL_TEXT_BASE		0x10000000
 #define CONFIG_SPL_MAX_SIZE		0x1a000
@@ -75,7 +74,6 @@ unsigned long get_board_ddr_clk(void);
 #ifdef CONFIG_NAND_BOOT
 #define CONFIG_SYS_FSL_PBL_RCW	board/freescale/ls1021aqds/ls102xa_rcw_nand.cfg
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 
 #define CONFIG_SPL_TEXT_BASE		0x10000000
 #define CONFIG_SPL_MAX_SIZE		0x1a000
diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h
index 0e5b00486881b0e353022bb5f93fa0bc5ecc67a6..f5c3947e3037ef99016f9510a49b751cd925c84d 100644
--- a/include/configs/ls1021atwr.h
+++ b/include/configs/ls1021atwr.h
@@ -95,7 +95,6 @@
 	board/freescale/ls1021atwr/ls102xa_rcw_sd_ifc.cfg
 #endif
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 
 #ifdef CONFIG_SECURE_BOOT
 /*
diff --git a/include/configs/ls1043a_common.h b/include/configs/ls1043a_common.h
index f064d5c24ae89d8f70a542a44b02287099399ea7..6c74afac9fc2fa760af5f294e3a1beb95f879957 100644
--- a/include/configs/ls1043a_common.h
+++ b/include/configs/ls1043a_common.h
@@ -66,7 +66,6 @@
 /* SD boot SPL */
 #ifdef CONFIG_SD_BOOT
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
 #define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
 
 #define CONFIG_SPL_TEXT_BASE		0x10000000
@@ -98,7 +97,6 @@
 #ifdef CONFIG_NAND_BOOT
 #define CONFIG_SPL_PBL_PAD
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
 #define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
 #define CONFIG_SPL_TEXT_BASE		0x10000000
 #define CONFIG_SPL_MAX_SIZE		0x1a000
diff --git a/include/configs/ls1046a_common.h b/include/configs/ls1046a_common.h
index e5159d8f1a6fb8bcef26f119357de0d58c22bfb2..4cab7d98164745205c3b3428f12e68140c8ae0f0 100644
--- a/include/configs/ls1046a_common.h
+++ b/include/configs/ls1046a_common.h
@@ -64,7 +64,6 @@
 /* SD boot SPL */
 #ifdef CONFIG_SD_BOOT
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
 #define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
@@ -104,7 +103,6 @@
 #ifdef CONFIG_NAND_BOOT
 #define CONFIG_SPL_PBL_PAD
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
 #define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
diff --git a/include/configs/ls2080a_common.h b/include/configs/ls2080a_common.h
index 1ec6cb2cdecfe0a828472c922d8b935671ff15ba..393112f50df47a2c3283b153bef8d9c22f521b3e 100644
--- a/include/configs/ls2080a_common.h
+++ b/include/configs/ls2080a_common.h
@@ -233,7 +233,6 @@ unsigned long long get_qixis_addr(void);
 #define CONFIG_SPL_BSS_START_ADDR	0x80100000
 #define CONFIG_SPL_BSS_MAX_SIZE		0x00100000
 #define CONFIG_SPL_FRAMEWORK
-#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv8/u-boot-spl.lds"
 #define CONFIG_SPL_MAX_SIZE		0x16000
 #define CONFIG_SPL_STACK		(CONFIG_SYS_FSL_OCRAM_BASE + 0x9ff0)
 #define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
diff --git a/include/configs/ma5d4evk.h b/include/configs/ma5d4evk.h
index 7c28a94d92d6f77b1cc70d3b8a0af7dab24dd72e..0d6977c7071f3160bfefa95112a1af905346a6d7 100644
--- a/include/configs/ma5d4evk.h
+++ b/include/configs/ma5d4evk.h
@@ -214,7 +214,6 @@
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x10000
 
 #define CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SPL_MMC_SUPPORT
 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
diff --git a/include/configs/mcx.h b/include/configs/mcx.h
index 49b9c8b32aafea714c7d9fa83ff71869f7b011d0..7047e3f5457c48b2f8b3c2af962e8de28fc25885 100644
--- a/include/configs/mcx.h
+++ b/include/configs/mcx.h
@@ -284,7 +284,6 @@
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 #define CONFIG_SPL_TEXT_BASE		0x40200000 /*CONFIG_SYS_SRAM_START*/
 #define CONFIG_SPL_MAX_SIZE		(54 * 1024)	/* 8 KB for stack */
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index 926a8f65261164a3fe0bcc6b1626cf02051463b1..75baccc770e6c0c83e260d3673ed9d9f02bd92dd 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -235,8 +235,6 @@
 /* SPL part */
 #define CONFIG_SPL_FRAMEWORK
 
-#define CONFIG_SPL_LDSCRIPT	"arch/microblaze/cpu/u-boot-spl.lds"
-
 #ifdef CONFIG_SYS_FLASH_BASE
 # define CONFIG_SYS_UBOOT_BASE		CONFIG_SYS_FLASH_BASE
 #endif
diff --git a/include/configs/mx31pdk.h b/include/configs/mx31pdk.h
index 3b776b1d9f16c9144b83ca7c0e326691a58c8f3f..2bb24a1545e396e855354c06780ff2f4a93ecd07 100644
--- a/include/configs/mx31pdk.h
+++ b/include/configs/mx31pdk.h
@@ -26,7 +26,6 @@
 #define CONFIG_MACH_TYPE	MACH_TYPE_MX31_3DS
 
 #define CONFIG_SPL_TARGET	"u-boot-with-spl.bin"
-#define CONFIG_SPL_LDSCRIPT	"arch/$(ARCH)/cpu/u-boot-spl.lds"
 #define CONFIG_SPL_MAX_SIZE	2048
 
 #define CONFIG_SPL_TEXT_BASE	0x87dc0000
diff --git a/include/configs/mxs.h b/include/configs/mxs.h
index 041dcde38e76766bd5a02cd3106e91c2fdf8a676..804b9e199c727a90465430e9696b65e53b6ecc7c 100644
--- a/include/configs/mxs.h
+++ b/include/configs/mxs.h
@@ -46,7 +46,6 @@
 /* SPL */
 #define CONFIG_SPL_NO_CPU_SUPPORT_CODE
 #define CONFIG_SPL_START_S_PATH	"arch/arm/cpu/arm926ejs/mxs"
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
 
 /* Memory sizes */
 #define CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h
index 6ea2b5e7f3687d97a2dc98704519e26ae74abb49..0085559ef9f049292723c8c28dc267ca501a0b25 100644
--- a/include/configs/omapl138_lcdk.h
+++ b/include/configs/omapl138_lcdk.h
@@ -307,7 +307,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SYS_TEXT_BASE - \
 						CONFIG_SYS_MALLOC_LEN)
 #define CONFIG_SYS_SPL_MALLOC_SIZE	CONFIG_SYS_MALLOC_LEN
-#define CONFIG_SPL_LDSCRIPT	"board/$(BOARDDIR)/u-boot-spl-da850evm.lds"
 #define CONFIG_SPL_STACK	0x8001ff00
 #define CONFIG_SPL_TEXT_BASE	0x80000000
 #define CONFIG_SPL_MAX_FOOTPRINT	32768
diff --git a/include/configs/origen.h b/include/configs/origen.h
index c36365353776b033b308da050e0021a8215963ee..69f6930c54476b8ccce71860c790a86813f573c3 100644
--- a/include/configs/origen.h
+++ b/include/configs/origen.h
@@ -95,7 +95,6 @@
 #define BL1_SIZE			(16 << 10) /*16 K reserved for BL1*/
 #define CONFIG_ENV_OFFSET		(RESERVE_BLOCK_SIZE + BL1_SIZE)
 
-#define CONFIG_SPL_LDSCRIPT	"board/samsung/common/exynos-uboot-spl.lds"
 #define CONFIG_SPL_MAX_FOOTPRINT	(14 * 1024)
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x02040000
diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h
index 112f9b8285cc58aebed8ac8ee6e71e5c5651a5a9..f678b2944dd09f41a8bffc71c9a3ad99ca4eddaa 100644
--- a/include/configs/pcm051.h
+++ b/include/configs/pcm051.h
@@ -117,8 +117,6 @@
 
 /* CPU */
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #ifdef CONFIG_SPI_BOOT
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
diff --git a/include/configs/pengwyn.h b/include/configs/pengwyn.h
index 4eecca16150a09a525fac47c9ec066cd7612171d..242a13912bb07f82c89d0f0b464cd8fa549403f4 100644
--- a/include/configs/pengwyn.h
+++ b/include/configs/pengwyn.h
@@ -194,6 +194,4 @@
 
 /* CPSW support */
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #endif	/* ! __CONFIG_PENGWYN_H */
diff --git a/include/configs/pepper.h b/include/configs/pepper.h
index 1a6981a52e57ca1466b0736f788e5e7f34219903..7ef25294c115ccc247e28206f0fc7bb1bc736e32 100644
--- a/include/configs/pepper.h
+++ b/include/configs/pepper.h
@@ -81,6 +81,5 @@
 #define CONFIG_PHY_RESET_DELAY 1000
 
 /* SPL */
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 #endif /* __CONFIG_PEPPER_H */
diff --git a/include/configs/picosam9g45.h b/include/configs/picosam9g45.h
index 4e64eac4221ba86e36c8de49471ba3f3f6d8b11b..c8ab54210528dac864279ed714085749d2257b80 100644
--- a/include/configs/picosam9g45.h
+++ b/include/configs/picosam9g45.h
@@ -141,7 +141,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START	0x20080000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x00080000
 
-#define CONFIG_SPL_LDSCRIPT	arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h
index 3ee9abd38d5034ede1fed0f0c527251ddae3d265..8a019361be7438d2884380fdffd06e88247a8bd6 100644
--- a/include/configs/rk3188_common.h
+++ b/include/configs/rk3188_common.h
@@ -26,7 +26,7 @@
 
 #define CONFIG_SYS_NS16550_MEM32
 
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#ifdef CONFIG_SPL_ROCKCHIP_BACK_TO_BROM
 /* Bootrom will load u-boot binary to 0x60000000 once return from SPL */
 #define CONFIG_SYS_TEXT_BASE		0x60000000
 #else
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index 488d67924a0afe6c123967afa429bc1dbcd38150..ade6caf624d9492ebfe5dcfe2b94abea4e642542 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -24,7 +24,7 @@
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SYS_NS16550_MEM32
 
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#ifdef CONFIG_SPL_ROCKCHIP_BACK_TO_BROM
 /* Bootrom will load u-boot binary to 0x0 once return from SPL */
 #define CONFIG_SYS_TEXT_BASE		0x00000000
 #else
diff --git a/include/configs/rk3368_common.h b/include/configs/rk3368_common.h
index b0c858c693cecb18f13e28b42fd59c11414d9916..a89c69a72b5158cc0aa74625b5ac9e4cb2955533 100644
--- a/include/configs/rk3368_common.h
+++ b/include/configs/rk3368_common.h
@@ -21,12 +21,20 @@
 #define CONFIG_SYS_CBSIZE		1024
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
+#define COUNTER_FREQUENCY               24000000
+
+#define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SYS_NS16550_MEM32
 
 #define CONFIG_SYS_TEXT_BASE		0x00200000
 #define CONFIG_SYS_INIT_SP_ADDR		0x00300000
 #define CONFIG_SYS_LOAD_ADDR		0x00280000
 
+#define CONFIG_SPL_TEXT_BASE            0x00000000
+#define CONFIG_SPL_MAX_SIZE             0x40000
+#define CONFIG_SPL_BSS_START_ADDR       0x400000
+#define CONFIG_SPL_BSS_MAX_SIZE         0x20000
+
 #define CONFIG_BOUNCE_BUFFER
 
 #ifndef CONFIG_SPL_BUILD
diff --git a/include/configs/rock.h b/include/configs/rock.h
index e998ec5f03cff94088b22d6468629ef21389fd50..6b0788be9db5f1b25e8b53703c6b6b22791a2a34 100644
--- a/include/configs/rock.h
+++ b/include/configs/rock.h
@@ -12,7 +12,7 @@
 
 #define CONFIG_SYS_MMC_ENV_DEV 0
 
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if defined(ROCKCHIP_BACK_TO_BROM)
 /* SPL @ 32k for 34k
  * u-boot directly after @ 68k for 400k or so
  * ENV @ 992k
diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h
index 29a492dc5529ca4c17e3031ac0668fbc281e35d6..b3986c28af43886cc42271bd762f27b7f2735ed3 100644
--- a/include/configs/rockchip-common.h
+++ b/include/configs/rockchip-common.h
@@ -46,7 +46,7 @@
 
 #endif
 
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
 /* SPL @ 32k for 34k
  * u-boot directly after @ 68k for 400k or so
  * ENV @ 992k
diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h
index 13d454f18a0f5284e0f1b667373a164ed8113cdf..72beb25304026a362a047817573b505c7a278fcf 100644
--- a/include/configs/sama5d2_xplained.h
+++ b/include/configs/sama5d2_xplained.h
@@ -77,7 +77,6 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/sama5d3_xplained.h b/include/configs/sama5d3_xplained.h
index cc12521577bb8d3aac097bcfe84aa95823116ddb..05600c81ff21f5bde286f0bdbd003b80b0591ee8 100644
--- a/include/configs/sama5d3_xplained.h
+++ b/include/configs/sama5d3_xplained.h
@@ -87,7 +87,6 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
 
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h
index d10dc3e2cb0c83c98b3d04618d621d99d9e46a33..29b7e8b50a0ec0ba79bf6e7d75f7d4e611cd37d0 100644
--- a/include/configs/sama5d3xek.h
+++ b/include/configs/sama5d3xek.h
@@ -118,7 +118,6 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
 
diff --git a/include/configs/sama5d4_xplained.h b/include/configs/sama5d4_xplained.h
index f0c80260d0d370c0a94f4082ec82d327f7204aa6..c8462b0b6485e7ce9b6bfb4976e49b133488cd50 100644
--- a/include/configs/sama5d4_xplained.h
+++ b/include/configs/sama5d4_xplained.h
@@ -76,7 +76,6 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/sama5d4ek.h b/include/configs/sama5d4ek.h
index ab858cecfab292499b5f595a2243cf39882ecd76..fc16ed0420cadd2ffffea9fc7aba2d5b5f7bcdbb 100644
--- a/include/configs/sama5d4ek.h
+++ b/include/configs/sama5d4ek.h
@@ -74,7 +74,6 @@
 #define CONFIG_SYS_MONITOR_LEN		(512 << 10)
 
 #ifdef CONFIG_SYS_USE_MMC
-#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
 
diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h
index 58b72812ed33b69af4cabfafcc20cd18c07ccfdf..5ed46588dd8cfd655743bfbb3b6b309557870d47 100644
--- a/include/configs/siemens-am33x-common.h
+++ b/include/configs/siemens-am33x-common.h
@@ -119,8 +119,6 @@
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #define CONFIG_SPL_NAND_AM33XX_BCH
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
diff --git a/include/configs/smartweb.h b/include/configs/smartweb.h
index 5b5046873ba5429556a71dcfb3079fa1608916c4..fe24b3a16088d03a36508fb10f508fe1cbcc3ae5 100644
--- a/include/configs/smartweb.h
+++ b/include/configs/smartweb.h
@@ -219,7 +219,6 @@
 #define CONFIG_SYS_SPL_MALLOC_START     (CONFIG_SPL_BSS_START_ADDR + \
 					CONFIG_SPL_BSS_MAX_SIZE)
 #define CONFIG_SYS_SPL_MALLOC_SIZE      CONFIG_SYS_MALLOC_LEN
-#define CONFIG_SPL_LDSCRIPT	arch/arm/mach-at91/arm926ejs/u-boot-spl.lds
 
 #define CONFIG_SYS_NAND_ENABLE_PIN_SPL	(2*32 + 14)
 #define CONFIG_SYS_USE_NANDFLASH	1
diff --git a/include/configs/smdkv310.h b/include/configs/smdkv310.h
index 96048f5d40b26fff2a28a6602c910d15b1ce77d4..978fb24f39598f75e45b1de1645530492663c6b6 100644
--- a/include/configs/smdkv310.h
+++ b/include/configs/smdkv310.h
@@ -78,7 +78,6 @@
 #define BL1_SIZE			(16 << 10) /*16 K reserved for BL1*/
 #define CONFIG_ENV_OFFSET		(RESERVE_BLOCK_SIZE + BL1_SIZE)
 
-#define CONFIG_SPL_LDSCRIPT	"board/samsung/common/exynos-uboot-spl.lds"
 #define CONFIG_SPL_MAX_FOOTPRINT	(14 * 1024)
 
 #define CONFIG_SYS_INIT_SP_ADDR		0x02040000
diff --git a/include/configs/sniper.h b/include/configs/sniper.h
index 34f6d8ad72bf278313794104da57b7fde83a7e1d..2306e7cdb96770a985bbd8c5a2826e08a2457954 100644
--- a/include/configs/sniper.h
+++ b/include/configs/sniper.h
@@ -85,8 +85,6 @@
 #define CONFIG_SYS_SPL_MALLOC_SIZE	(1024 * 1024)
 #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
 
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
-
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION		1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME			"u-boot.img"
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 07c7ffd7f204d855b720a0bbb4416c03888392a4..212862acd1cb630eb33b2f9e9270e82533ee628b 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -202,10 +202,6 @@
 
 #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
 
-#ifndef CONFIG_ARM64
-#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds"
-#endif
-
 #define CONFIG_SPL_PAD_TO		32768		/* decimal for 'dd' */
 
 
diff --git a/include/configs/tam3517-common.h b/include/configs/tam3517-common.h
index 419f683277a2f10eadc5493c5b37d0f309813d38..54223c475adca04aa943bf178be0068847dd2484 100644
--- a/include/configs/tam3517-common.h
+++ b/include/configs/tam3517-common.h
@@ -170,7 +170,6 @@
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 #define CONFIG_SPL_TEXT_BASE		0x40200000 /*CONFIG_SYS_SRAM_START*/
 #define CONFIG_SPL_MAX_SIZE		(SRAM_SCRATCH_SPACE_ADDR - \
diff --git a/include/configs/tao3530.h b/include/configs/tao3530.h
index 253270e1769c87fe75ea8c75e2cad3b936e5d260..d47dc8bba909bc1c137e247599986e4e611da853 100644
--- a/include/configs/tao3530.h
+++ b/include/configs/tao3530.h
@@ -240,7 +240,6 @@
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
 #define CONFIG_SPL_OMAP3_ID_NAND
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /* NAND boot config */
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
diff --git a/include/configs/ti814x_evm.h b/include/configs/ti814x_evm.h
index 4d9ec790fd94a64dab4d6ea69d723e044efbe6c8..129ae4c4665658fb1c9aa2549f8b970ee8784409 100644
--- a/include/configs/ti814x_evm.h
+++ b/include/configs/ti814x_evm.h
@@ -149,7 +149,6 @@
 
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
 #define CONFIG_SYS_SPI_U_BOOT_SIZE	0x40000
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
 /*
  * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM
diff --git a/include/configs/ti816x_evm.h b/include/configs/ti816x_evm.h
index bba10ec00108786b44eebe419e14742855f79d2b..3da774f9c567bbc6a18e06bfeda823aa0d6b2ebe 100644
--- a/include/configs/ti816x_evm.h
+++ b/include/configs/ti816x_evm.h
@@ -118,8 +118,6 @@
 #define CONFIG_SPL_MAX_SIZE		(SRAM_SCRATCH_SPACE_ADDR - \
 					 CONFIG_SPL_TEXT_BASE)
 
-#define CONFIG_SPL_LDSCRIPT     "arch/arm/mach-omap2/u-boot-spl.lds"
-
 #define CONFIG_SYS_TEXT_BASE        0x80800000
 
 #define CONFIG_DRIVER_TI_EMAC
diff --git a/include/configs/ti_omap3_common.h b/include/configs/ti_omap3_common.h
index 393d867a73360870539ae78a6b9ad5a70b81ede9..938136c94629fa6fc34bfc8709f7d489b0d6241b 100644
--- a/include/configs/ti_omap3_common.h
+++ b/include/configs/ti_omap3_common.h
@@ -60,7 +60,6 @@
 
 /* SPL */
 #define CONFIG_SPL_TEXT_BASE		0x40200800
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 #define CONFIG_SYS_SPL_ARGS_ADDR	(CONFIG_SYS_SDRAM_BASE + \
 					 (64 << 20))
 
diff --git a/include/configs/ti_omap4_common.h b/include/configs/ti_omap4_common.h
index acfac24ebe1406c60e607b4fae44c4cd32a5d368..018e4c2512827cbdeb3416f15392848be4ca7c77 100644
--- a/include/configs/ti_omap4_common.h
+++ b/include/configs/ti_omap4_common.h
@@ -139,7 +139,6 @@
  * So moving TEXT_BASE down to non-HS limit.
  */
 #define CONFIG_SPL_TEXT_BASE		0x40300000
-#define CONFIG_SPL_LDSCRIPT "arch/arm/mach-omap2/u-boot-spl.lds"
 #define CONFIG_SYS_SPL_ARGS_ADDR	(CONFIG_SYS_SDRAM_BASE + \
 					 (128 << 20))
 
diff --git a/include/configs/ti_omap5_common.h b/include/configs/ti_omap5_common.h
index 4c3a2766ecbd73777118811eb73f8f0c42c8ba1b..73c1d8f66ead792d1dfc3164714499d854c0f18a 100644
--- a/include/configs/ti_omap5_common.h
+++ b/include/configs/ti_omap5_common.h
@@ -100,7 +100,6 @@
 #define CONFIG_SPL_TEXT_BASE	0x40300000
 #endif
 
-#define CONFIG_SPL_LDSCRIPT "arch/arm/mach-omap2/u-boot-spl.lds"
 #define CONFIG_SYS_SPL_ARGS_ADDR	(CONFIG_SYS_SDRAM_BASE + \
 					 (128 << 20))
 
diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index fbdd43ac728e27cc41e56b7cac824d348dc4fb00..77f8cbde27fb12baa561fd92a8b3f565ebafefa7 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -259,7 +259,6 @@
 #define CONFIG_SPL_NAND_BASE
 #define CONFIG_SPL_NAND_DRIVERS
 #define CONFIG_SPL_NAND_ECC
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME        "u-boot.img"
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION     1
 
diff --git a/include/configs/woodburn_sd.h b/include/configs/woodburn_sd.h
index bab7fdf93caadaf2c2f78b63ab816fc2ca0fa858..fb7385649e20827b34520206458032012c87480e 100644
--- a/include/configs/woodburn_sd.h
+++ b/include/configs/woodburn_sd.h
@@ -21,7 +21,6 @@
  * SPL
  */
 #define CONFIG_SPL_FRAMEWORK
-#define	CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm1136/u-boot-spl.lds"
 
 #define CONFIG_SPL_TEXT_BASE		0x10002300
 #define CONFIG_SPL_MAX_SIZE		(64 * 1024)	/* 8 KB for stack */
diff --git a/include/configs/x600.h b/include/configs/x600.h
index 677882539704cf1592fda4d4b123f117585e8f65..1255edd5bd6974d16b9c99759806809afb1e32dd 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -237,7 +237,6 @@
 #define CONFIG_SPL_TEXT_BASE		0xd2800b00
 #define CONFIG_SPL_MAX_SIZE		(CONFIG_SRAM_SIZE - 0xb00)
 #define	CONFIG_SPL_START_S_PATH	"arch/arm/cpu/arm926ejs/spear"
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds"
 
 #define CONFIG_SPL_FRAMEWORK
 
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 66bc508b9de5f14b99704d06f27c19c529d309bf..6359587738dd774a58a725f17b63aa634841d26a 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -319,8 +319,6 @@
 /* SPL part */
 #define CONFIG_SPL_FRAMEWORK
 
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/mach-zynq/u-boot-spl.lds"
-
 /* MMC support */
 #ifdef CONFIG_MMC_SDHCI_ZYNQ
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION     1
diff --git a/include/dt-bindings/memory/rk3368-dmc.h b/include/dt-bindings/memory/rk3368-dmc.h
new file mode 100644
index 0000000000000000000000000000000000000000..b06ffde7186903137c25e5e9f238a27c311f887f
--- /dev/null
+++ b/include/dt-bindings/memory/rk3368-dmc.h
@@ -0,0 +1,30 @@
+#ifndef DT_BINDINGS_RK3368_DMC_H
+#define DT_BINDINGS_RK3368_DMC_H
+
+#define DMC_MSCH_CBDR       0x0
+#define DMC_MSCH_CBRD       0x1
+#define DMC_MSCH_CRBD       0x2
+
+#define DDR3_800D 0
+#define DDR3_800E 1
+#define DDR3_1066E 2
+#define DDR3_1066F 3
+#define DDR3_1066G 4
+#define DDR3_1333F 5
+#define DDR3_1333G 6
+#define DDR3_1333H 7
+#define DDR3_1333J 8
+#define DDR3_1600G 9
+#define DDR3_1600H 10
+#define DDR3_1600J 11
+#define DDR3_1600K 12
+#define DDR3_1866J 13
+#define DDR3_1866K 14
+#define DDR3_1866L 15
+#define DDR3_1866M 16
+#define DDR3_2133K 17
+#define DDR3_2133L 18
+#define DDR3_2133M 19
+#define DDR3_2133N 20
+
+#endif
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index 486fb94c577bd2d757009239d2e1a36ec50b4868..fbfc7188b8f646972303b37e9fd829736dfc35ba 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -51,12 +51,25 @@
 #define _IS_SPL 1
 #endif
 
+#ifdef CONFIG_TPL_BUILD
+#define _IS_TPL 1
+#endif
+
+#if defined(CONFIG_TPL_BUILD)
+#define config_val(cfg) _config_val(_IS_TPL, cfg)
+#define _config_val(x, cfg) __config_val(x, cfg)
+#define __config_val(x, cfg) ___config_val(__ARG_PLACEHOLDER_##x, cfg)
+#define ___config_val(arg1_or_junk, cfg)  \
+	____config_val(arg1_or_junk CONFIG_TPL_##cfg, CONFIG_##cfg)
+#define ____config_val(__ignored, val, ...) val
+#else
 #define config_val(cfg) _config_val(_IS_SPL, cfg)
 #define _config_val(x, cfg) __config_val(x, cfg)
 #define __config_val(x, cfg) ___config_val(__ARG_PLACEHOLDER_##x, cfg)
 #define ___config_val(arg1_or_junk, cfg)  \
 	____config_val(arg1_or_junk CONFIG_SPL_##cfg, CONFIG_##cfg)
 #define ____config_val(__ignored, val, ...) val
+#endif
 
 /*
  * CONFIG_VAL(FOO) evaluates to the value of
diff --git a/include/spl.h b/include/spl.h
index ffadce93c7be28ac6b409f28ff7eeaed3a37da71..ce4cf0abbebb6e599d7b8727afbf65fe80bfe348 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -268,4 +268,14 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
 		       struct spl_boot_device *bootdev);
 
 void bl31_entry(void);
+
+/**
+ * board_return_to_bootrom - allow for boards to continue with the boot ROM
+ *
+ * If a board (e.g. the Rockchip RK3368 boards) provide some
+ * supporting functionality for SPL in their boot ROM and the SPL
+ * stage wants to return to the ROM code to continue booting, boards
+ * can implement 'board_return_to_bootrom'.
+ */
+void board_return_to_bootrom(void);
 #endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 2f5a210ad42f7df51d93d36fff8db0222bdc5540..81636172bce44996cea9ac4db7bb146623de0903 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -61,6 +61,15 @@ config SPL_TINY_MEMSET
 	  size-constrained envrionments even this may be too big. Enable this
 	  option to reduce code size slightly at the cost of some speed.
 
+config TPL_TINY_MEMSET
+	bool "Use a very small memset() in TPL"
+	help
+	  The faster memset() is the arch-specific one (if available) enabled
+	  by CONFIG_USE_ARCH_MEMSET. If that is not enabled, we can still get
+	  better performance by writing a word at a time. But in very
+	  size-constrained envrionments even this may be too big. Enable this
+	  option to reduce code size slightly at the cost of some speed.
+
 config RBTREE
 	bool
 
diff --git a/lib/Makefile b/lib/Makefile
index eacc7d64857dc9a497a444650c5bbbd6f8252ec3..2eef1eb80e65231948b5fb708e8cccf7ed45a23b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,11 +49,11 @@ obj-$(CONFIG_RSA) += rsa/
 obj-$(CONFIG_SHA1) += sha1.o
 obj-$(CONFIG_SHA256) += sha256.o
 
-obj-$(CONFIG_SPL_SAVEENV) += qsort.o
-obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/
-ifneq ($(CONFIG_SPL_BUILD)$(CONFIG_SPL_OF_PLATDATA),yy)
-obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec_common.o
-obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec.o
+obj-$(CONFIG_$(SPL_TPL_)SAVEENV) += qsort.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
+ifneq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
+obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec_common.o
+obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index ac3c2c7f1342dedf6e72d674481350fc8a42d0ac..167b2d9d2977c0259f4b11671343167a713352e6 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -98,15 +98,22 @@ endif
 
 u-boot-spl-init := $(head-y)
 u-boot-spl-main := $(libs-y)
-ifdef CONFIG_SPL_OF_PLATDATA
+ifdef CONFIG_$(SPL_TPL_)OF_PLATDATA
 u-boot-spl-platdata := $(obj)/dts/dt-platdata.o
 endif
 
 # Linker Script
-ifdef CONFIG_SPL_LDSCRIPT
+# First test whether there's a linker-script for the specific stage defined...
+ifneq ($(CONFIG_$(SPL_TPL_)LDSCRIPT),)
+# need to strip off double quotes
+LDSCRIPT := $(addprefix $(srctree)/,$(CONFIG_$(SPL_TPL_)LDSCRIPT:"%"=%))
+else
+# ...then fall back to the generic SPL linker-script
+ifneq ($(CONFIG_SPL_LDSCRIPT),)
 # need to strip off double quotes
 LDSCRIPT := $(addprefix $(srctree)/,$(CONFIG_SPL_LDSCRIPT:"%"=%))
 endif
+endif
 
 ifeq ($(wildcard $(LDSCRIPT)),)
 	LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot-spl.lds
@@ -202,7 +209,7 @@ cmd_cat = cat $(filter-out $(PHONY), $^) > $@
 quiet_cmd_copy = COPY    $@
       cmd_copy = cp $< $@
 
-ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy)
+ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
 $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
 		$(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
 		$(obj)/$(SPL_BIN).dtb FORCE
@@ -293,9 +300,15 @@ LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
 # Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
 LDFLAGS_$(SPL_BIN) += $(call ld-option, --no-dynamic-linker)
 
+# First try the best-match (i.e. SPL_TEXT_BASE for SPL, TPL_TEXT_BASE for TPL)
+ifneq ($(CONFIG_$(SPL_TPL_)TEXT_BASE),)
+LDFLAGS_$(SPL_BIN) += -Ttext $(CONFIG_$(SPL_TPL_)TEXT_BASE)
+else
+# And then fall back to just testing for SPL_TEXT_BASE, even if in TPL mode
 ifneq ($(CONFIG_SPL_TEXT_BASE),)
 LDFLAGS_$(SPL_BIN) += -Ttext $(CONFIG_SPL_TEXT_BASE)
 endif
+endif
 
 MKIMAGEFLAGS_$(SPL_BIN).sfp = -T socfpgaimage
 $(obj)/$(SPL_BIN).sfp: $(obj)/$(SPL_BIN).bin FORCE
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index f509984d77566e19ef3f8b51b059bb38e672ff45..d9aeb62a024abb9f59ddca6f277a5a6b2d48c542 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -2207,7 +2207,6 @@ CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
 CONFIG_SPL_INIT_MINIMAL
 CONFIG_SPL_JR0_LIODN_NS
 CONFIG_SPL_JR0_LIODN_S
-CONFIG_SPL_LDSCRIPT
 CONFIG_SPL_LOAD_FIT_ADDRESS
 CONFIG_SPL_MAX_FOOTPRINT
 CONFIG_SPL_MAX_PEB_SIZE
@@ -4909,7 +4908,6 @@ CONFIG_TI_KEYSTONE_SERDES
 CONFIG_TI_KSNAV
 CONFIG_TI_SPI_MMAP
 CONFIG_TMU_TIMER
-CONFIG_TPL_DRIVERS_MISC_SUPPORT
 CONFIG_TPL_PAD_TO
 CONFIG_TPM_TIS_BASE_ADDRESS
 CONFIG_TPS6586X_POWER
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 63d91e22ed7ccd18a0cd77852af647112ed216bb..8564bedd1a7cf31c9b3d3f71b5c328de690bf182 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -141,7 +141,11 @@ if $scm_only; then
 fi
 
 if test -e include/config/auto.conf; then
-	. include/config/auto.conf
+	# We are interested only in CONFIG_LOCALVERSION and
+        # CONFIG_LOCALVERSION_AUTO, so extract these in a safe
+        # way (i.e. w/o sourcing auto.conf)
+	CONFIG_LOCALVERSION=`cat include/config/auto.conf | awk -F '=' '/^CONFIG_LOCALVERSION=/ {print $2}'`
+	CONFIG_LOCALVERSION_AUTO=`cat include/config/auto.conf | awk -F '=' '/^CONFIG_LOCALVERSION_AUTO=/ {print $2}'`
 else
 	echo "Error: kernelrelease not valid - run 'make prepare' to update it"
 	exit 1
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 25b034028b48c96f8001c743f21e97742d2d97b8..04e8272fd5b63b870186bd73a31e4256ee38352f 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -77,6 +77,7 @@ static struct spl_info spl_infos[] = {
 	{ "rk322x", "RK32", 0x8000 - 0x1000, false, false },
 	{ "rk3288", "RK32", 0x8000, false, false },
 	{ "rk3328", "RK32", 0x8000 - 0x1000, false, false },
+	{ "rk3368", "RK33", 0x8000 - 0x1000, false, true },
 	{ "rk3399", "RK33", 0x30000 - 0x2000, false, true },
 	{ "rv1108", "RK11", 0x1800, false, false},
 };