diff --git a/arch/arm/dts/rk3288-evb.dts b/arch/arm/dts/rk3288-evb.dts
index 3e1ee58a5ee1279ae7241fb25e095db023862616..3f03e1326cb369002771ef472201c53a1f9e0dad 100644
--- a/arch/arm/dts/rk3288-evb.dts
+++ b/arch/arm/dts/rk3288-evb.dts
@@ -17,7 +17,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
 		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
 		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
@@ -25,8 +24,6 @@
 		0x8 0x1f4>;
 	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
 		0x0 0xc3 0x6 0x2>;
-	/* Add a dummy value to cause of-platdata think this is bytes */
-	rockchip,sdram-channel = /bits/ 8 <0x2 0xa 0x3 0x2 0x2 0x0 0xe 0xe 0xff>;
 	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
 };
 
diff --git a/arch/arm/dts/rk3288-fennec.dts b/arch/arm/dts/rk3288-fennec.dts
index 36e9f3dac5644a35b4823da667355161c8ddc378..66ddf8d655bed9132584957c75cfb1a16ea9dcc5 100644
--- a/arch/arm/dts/rk3288-fennec.dts
+++ b/arch/arm/dts/rk3288-fennec.dts
@@ -17,7 +17,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
 		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
 		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
@@ -25,8 +24,6 @@
 		0x8 0x1f4>;
 	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
 		0x0 0xc3 0x6 0x2>;
-	/* Add a dummy value to cause of-platdata think this is bytes */
-	rockchip,sdram-channel = /bits/ 8 <0x2 0xa 0x3 0x2 0x2 0x0 0xe 0xe 0xff>;
 	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
 };
 
diff --git a/arch/arm/dts/rk3288-firefly.dts b/arch/arm/dts/rk3288-firefly.dts
index 3176d5046b2a4a622bb700b2ab189575204ec2c0..97568a36ee2fe627520e0126a5c9bb776a4cf03e 100644
--- a/arch/arm/dts/rk3288-firefly.dts
+++ b/arch/arm/dts/rk3288-firefly.dts
@@ -22,7 +22,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
@@ -31,7 +30,6 @@
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
 	/* Add a dummy value to cause of-platdata think this is bytes */
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-miniarm.dts b/arch/arm/dts/rk3288-miniarm.dts
index c7410821d366170949640b452f9b12727e8d2391..9083028579f1068a8ca7fd7c609448332126209f 100644
--- a/arch/arm/dts/rk3288-miniarm.dts
+++ b/arch/arm/dts/rk3288-miniarm.dts
@@ -17,7 +17,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
@@ -25,8 +24,6 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	/* Add a dummy value to cause of-platdata think this is bytes */
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-popmetal.dts b/arch/arm/dts/rk3288-popmetal.dts
index 3f61a61f97cd5d0ac356f315ed4a630cd4c722ee..284d5eda7bc6a24f96b69f608b0ba299af43c36c 100644
--- a/arch/arm/dts/rk3288-popmetal.dts
+++ b/arch/arm/dts/rk3288-popmetal.dts
@@ -17,7 +17,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
@@ -25,8 +24,6 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	/* Add a dummy value to cause of-platdata think this is bytes */
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-rock2-square.dts b/arch/arm/dts/rk3288-rock2-square.dts
index 2c30355f06bf285eb5a9169fb41d49b83519a721..11c580a0b56a34f9f19ded998d542fd671b22241 100644
--- a/arch/arm/dts/rk3288-rock2-square.dts
+++ b/arch/arm/dts/rk3288-rock2-square.dts
@@ -184,7 +184,6 @@
 };
 
 &dmc {
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
@@ -192,7 +191,6 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index d9d51879f03b09ae9505523ff7517f4217773019..2ffe39cbf710331a699232249fbb2a860a071077 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -245,7 +245,6 @@
 		533000 1150000
 		666000 1200000
 	>;
-	rockchip,num-channels = <2>;
 	rockchip,pctl-timing = <0x29a 0xc8 0x1f4 0x42 0x4e 0x4 0xea 0xa
 		0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
 		0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
@@ -253,7 +252,6 @@
 		0x5 0x0>;
 	rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
 		0xa60 0x40 0x10 0x0>;
-	rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
 	rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
 };
 
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3036.h b/arch/arm/include/asm/arch-rockchip/cru_rk3036.h
index 7ecc8ee71c7ac74fbe091fd1fe75193955d4eb37..aaef4b9d734181e1f805ef26dfb503d30caffc29 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3036.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3036.h
@@ -24,6 +24,12 @@
 #define PERI_HCLK_HZ	148500000
 #define PERI_PCLK_HZ	74250000
 
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rk3036_clk_priv {
+	struct rk3036_cru *cru;
+	ulong rate;
+};
+
 struct rk3036_cru {
 	struct rk3036_pll {
 		unsigned int con0;
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index 8a8ca9c9aad9e6d026eec291222ad1fd6a85f9f1..d575f4a16396012d3fbb3e1faad21018b8d3271e 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
@@ -25,6 +25,13 @@
 #define PERI_HCLK_HZ	148500000
 #define PERI_PCLK_HZ	74250000
 
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rk3288_clk_priv {
+	struct rk3288_grf *grf;
+	struct rk3288_cru *cru;
+	ulong rate;
+};
+
 struct rk3288_cru {
 	struct rk3288_pll {
 		u32 con0;
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
index 6776e484b737ff6a1f6242ffd73f3bf78c04a65e..98fba2bd7556a16f2d686d46f290902dfcf2be82 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
@@ -9,6 +9,12 @@
 
 #include <common.h>
 
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rk3399_clk_priv {
+	struct rk3399_cru *cru;
+	ulong rate;
+};
+
 struct rk3399_pmucru {
 	u32 ppll_con[6];
 	u32 reserved[0x1a];
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
index 82c3d07cbbd800f88b2d56b0d1e2b937eeaad64f..d7d67baa6895e1c38434cbca1485ce6c5f376cf6 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram.h
@@ -16,6 +16,11 @@ enum {
 };
 
 struct rk3288_sdram_channel {
+	/*
+	 * bit width in address, eg:
+	 * 8 banks using 3 bit to address,
+	 * 2 cs using 1 bit to address.
+	 */
 	u8 rank;
 	u8 col;
 	u8 bk;
@@ -87,6 +92,16 @@ struct rk3288_base_params {
 	u32 ddrconfig;
 	u32 ddr_freq;
 	u32 dramtype;
+	/*
+	 * DDR Stride is address mapping for DRAM space
+	 * Stride	Ch 0 range	Ch1 range	Total
+	 * 0x00		0-256MB		256MB-512MB	512MB
+	 * 0x05		0-1GB		0-1GB		1GB
+	 * 0x09		0-2GB		0-2GB		2GB
+	 * 0x0d		0-4GB		0-4GB		4GB
+	 * 0x17		N/A		0-4GB		4GB
+	 * 0x1a		0-4GB		4GB-8GB		8GB
+	 */
 	u32 stride;
 	u32 odt;
 };
diff --git a/arch/arm/mach-rockchip/rk3036/Makefile b/arch/arm/mach-rockchip/rk3036/Makefile
index 916a7a43784cdc854d4ab1c54cbe40a025c38799..20d28f7c21c182d1e5e2e470b2c28c58c33389b4 100644
--- a/arch/arm/mach-rockchip/rk3036/Makefile
+++ b/arch/arm/mach-rockchip/rk3036/Makefile
@@ -4,6 +4,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-y += clk_rk3036.o
+
 ifndef CONFIG_SPL_BUILD
 obj-y += syscon_rk3036.o
 endif
diff --git a/arch/arm/mach-rockchip/rk3036/clk_rk3036.c b/arch/arm/mach-rockchip/rk3036/clk_rk3036.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a06afb103ba11ad0e00da86672cb7c44645430f
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3036/clk_rk3036.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3036.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3036_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rk3036_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index 94863a925e32fcb0462885a1069ac3b46d153052..c53d2e203377a1e2fa812cd572fbbb78c9ec3466 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -81,9 +81,6 @@ config SPL_LIBCOMMON_SUPPORT
 config SPL_LIBGENERIC_SUPPORT
 	default y
 
-config SPL_MMC_SUPPORT
-	default y
-
 config SPL_SERIAL_SUPPORT
 	default y
 
diff --git a/arch/arm/mach-rockchip/rk3288/clk_rk3288.c b/arch/arm/mach-rockchip/rk3288/clk_rk3288.c
index 2099e349c16f723996d528894bd4662b6240932e..a45b923a2c72229485b15a9c3a7167284df04090 100644
--- a/arch/arm/mach-rockchip/rk3288/clk_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/clk_rk3288.c
@@ -9,9 +9,25 @@
 #include <dm.h>
 #include <syscon.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
 
 int rockchip_get_clk(struct udevice **devp)
 {
 	return uclass_get_device_by_driver(UCLASS_CLK,
 			DM_GET_DRIVER(rockchip_rk3288_cru), devp);
 }
+
+void *rockchip_get_cru(void)
+{
+	struct rk3288_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c
index 92f34bbbcb73a9936c3cc38d7928410909fe4307..acc3b7932a3c02e020641538003674cbe169f74f 100644
--- a/arch/arm/mach-rockchip/rk3288/rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/rk3288.c
@@ -6,7 +6,7 @@
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
 
-#define GRF_SOC_CON2 0x24c
+#define GRF_SOC_CON2 0xff77024c
 
 int arch_cpu_init(void)
 {
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 8020e9c6e2fb0a4572fda97002d4e1de8523e3d6..be3d7132020f3999f83ec3dbcd3ec2c236fbec2b 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -57,6 +57,10 @@ struct rk3288_sdram_params {
 	struct regmap *map;
 };
 
+#define TEST_PATTEN	0x5aa5f00f
+#define DQS_GATE_TRAINING_ERROR_RANK0	(1 << 4)
+#define DQS_GATE_TRAINING_ERROR_RANK1	(2 << 4)
+
 #ifdef CONFIG_SPL_BUILD
 static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
 {
@@ -214,7 +218,7 @@ static void ddr_set_en_bst_odt(struct rk3288_grf *grf, uint channel,
 }
 
 static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
-		     const struct rk3288_sdram_params *sdram_params,
+		     struct rk3288_sdram_params *sdram_params,
 		     struct rk3288_grf *grf)
 {
 	unsigned int burstlen;
@@ -264,7 +268,7 @@ static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
 }
 
 static void phy_cfg(const struct chan_info *chan, u32 channel,
-		    const struct rk3288_sdram_params *sdram_params)
+		    struct rk3288_sdram_params *sdram_params)
 {
 	struct rk3288_ddr_publ *publ = chan->publ;
 	struct rk3288_msch *msch = chan->msch;
@@ -446,7 +450,7 @@ static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
 }
 
 static int data_training(const struct chan_info *chan, u32 channel,
-			 const struct rk3288_sdram_params *sdram_params)
+			 struct rk3288_sdram_params *sdram_params)
 {
 	unsigned int j;
 	int ret = 0;
@@ -549,7 +553,7 @@ static void move_to_access_state(const struct chan_info *chan)
 }
 
 static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
-			 const struct rk3288_sdram_params *sdram_params)
+			 struct rk3288_sdram_params *sdram_params)
 {
 	struct rk3288_ddr_publ *publ = chan->publ;
 
@@ -563,7 +567,7 @@ static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
 }
 
 static void dram_all_config(const struct dram_info *dram,
-			    const struct rk3288_sdram_params *sdram_params)
+			    struct rk3288_sdram_params *sdram_params)
 {
 	unsigned int chan;
 	u32 sys_reg = 0;
@@ -589,9 +593,191 @@ static void dram_all_config(const struct dram_info *dram,
 	writel(sys_reg, &dram->pmu->sys_reg[2]);
 	rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, sdram_params->base.stride);
 }
+const int ddrconf_table[] = {
+	/* row	    col,bw */
+	0,
+	((1 << 4) | 1),
+	((2 << 4) | 1),
+	((3 << 4) | 1),
+	((4 << 4) | 1),
+	((1 << 4) | 2),
+	((2 << 4) | 2),
+	((3 << 4) | 2),
+	((1 << 4) | 0),
+	((2 << 4) | 0),
+	((3 << 4) | 0),
+	0,
+	0,
+	0,
+	0,
+	((4 << 4) | 2),
+};
+
+static int sdram_rank_bw_detect(struct dram_info *dram, int channel,
+		struct rk3288_sdram_params *sdram_params)
+{
+	int reg;
+	int need_trainig = 0;
+	const struct chan_info *chan = &dram->chan[channel];
+	struct rk3288_ddr_publ *publ = chan->publ;
+
+	if (-1 == data_training(chan, channel, sdram_params)) {
+		reg = readl(&publ->datx8[0].dxgsr[0]);
+		/* Check the result for rank 0 */
+		if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) {
+			debug("data training fail!\n");
+				return -EIO;
+		} else if ((channel == 1) &&
+			   (reg & DQS_GATE_TRAINING_ERROR_RANK0)) {
+			sdram_params->num_channels = 1;
+		}
+
+		/* Check the result for rank 1 */
+		if (reg & DQS_GATE_TRAINING_ERROR_RANK1) {
+			sdram_params->ch[channel].rank = 1;
+			clrsetbits_le32(&publ->pgcr, 0xF << 18,
+					sdram_params->ch[channel].rank << 18);
+			need_trainig = 1;
+		}
+		reg = readl(&publ->datx8[2].dxgsr[0]);
+		if (reg & (1 << 4)) {
+			sdram_params->ch[channel].bw = 1;
+			set_bandwidth_ratio(chan, channel,
+					    sdram_params->ch[channel].bw,
+					    dram->grf);
+			need_trainig = 1;
+		}
+	}
+	/* Assume the Die bit width are the same with the chip bit width */
+	sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw;
+
+	if (need_trainig &&
+	    (-1 == data_training(chan, channel, sdram_params))) {
+		if (sdram_params->base.dramtype == LPDDR3) {
+			ddr_phy_ctl_reset(dram->cru, channel, 1);
+			udelay(10);
+			ddr_phy_ctl_reset(dram->cru, channel, 0);
+			udelay(10);
+		}
+		debug("2nd data training failed!");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int sdram_col_row_detect(struct dram_info *dram, int channel,
+		struct rk3288_sdram_params *sdram_params)
+{
+	int row, col;
+	unsigned int addr;
+	const struct chan_info *chan = &dram->chan[channel];
+	struct rk3288_ddr_pctl *pctl = chan->pctl;
+	struct rk3288_ddr_publ *publ = chan->publ;
+	int ret = 0;
+
+	/* Detect col */
+	for (col = 11; col >= 9; col--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE +
+			(1 << (col + sdram_params->ch[channel].bw - 1));
+		writel(TEST_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (col == 8) {
+		printf("Col detect error\n");
+		ret = -EINVAL;
+		goto out;
+	} else {
+		sdram_params->ch[channel].col = col;
+	}
+
+	move_to_config_state(publ, pctl);
+	writel(4, &chan->msch->ddrconf);
+	move_to_access_state(chan);
+	/* 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_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (row == 11) {
+		printf("Row detect error\n");
+		ret = -EINVAL;
+	} else {
+		sdram_params->ch[channel].cs1_row = row;
+		sdram_params->ch[channel].row_3_4 = 0;
+		debug("chn %d col %d, row %d\n", channel, col, row);
+		sdram_params->ch[channel].cs0_row = row;
+	}
+
+out:
+	return ret;
+}
+
+static int sdram_get_niu_config(struct rk3288_sdram_params *sdram_params)
+{
+	int i, tmp, size, ret = 0;
+
+	tmp = sdram_params->ch[0].col - 9;
+	tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1;
+	tmp |= ((sdram_params->ch[0].cs0_row - 12) << 4);
+	size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]);
+	for (i = 0; i < size; i++)
+		if (tmp == ddrconf_table[i])
+			break;
+	if (i >= size) {
+		printf("niu config not found\n");
+		ret = -EINVAL;
+	} else {
+		sdram_params->base.ddrconfig = i;
+	}
+
+	return ret;
+}
+
+static int sdram_get_stride(struct rk3288_sdram_params *sdram_params)
+{
+	int stride = -1;
+	int ret = 0;
+	long cap = sdram_params->num_channels * (1u <<
+			(sdram_params->ch[0].cs0_row +
+			 sdram_params->ch[0].col +
+			 (sdram_params->ch[0].rank - 1) +
+			 sdram_params->ch[0].bw +
+			 3 - 20));
+
+	switch (cap) {
+	case 512:
+		stride = 0;
+		break;
+	case 1024:
+		stride = 5;
+		break;
+	case 2048:
+		stride = 9;
+		break;
+	case 4096:
+		stride = 0xd;
+		break;
+	default:
+		stride = -1;
+		printf("could not find correct stride, cap error!\n");
+		ret = -EINVAL;
+		break;
+	}
+	sdram_params->base.stride = stride;
+
+	return ret;
+}
 
 static int sdram_init(struct dram_info *dram,
-		      const struct rk3288_sdram_params *sdram_params)
+		      struct rk3288_sdram_params *sdram_params)
 {
 	int channel;
 	int zqcr;
@@ -619,12 +805,14 @@ static int sdram_init(struct dram_info *dram,
 		struct rk3288_ddr_pctl *pctl = chan->pctl;
 		struct rk3288_ddr_publ *publ = chan->publ;
 
+		/* map all the 4GB space to the current channel */
+		if (channel)
+			rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, 0x17);
+		else
+			rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, 0x1a);
 		phy_pctrl_reset(dram->cru, publ, channel);
 		phy_dll_bypass_set(publ, sdram_params->base.ddr_freq);
 
-		if (channel >= sdram_params->num_channels)
-			continue;
-
 		dfi_cfg(pctl, sdram_params->base.dramtype);
 
 		pctl_cfg(channel, pctl, sdram_params, dram->grf);
@@ -658,16 +846,20 @@ static int sdram_init(struct dram_info *dram,
 			udelay(1);
 		}
 
+		/* Using 32bit bus width for detect */
+		sdram_params->ch[channel].bw = 2;
 		set_bandwidth_ratio(chan, channel,
 				    sdram_params->ch[channel].bw, dram->grf);
 		/*
-		 * set cs
+		 * set cs, using n=3 for detect
 		 * CS0, n=1
 		 * CS1, n=2
 		 * CS0 & CS1, n = 3
 		 */
+		sdram_params->ch[channel].rank = 2,
 		clrsetbits_le32(&publ->pgcr, 0xF << 18,
 				(sdram_params->ch[channel].rank | 1) << 18);
+
 		/* DS=40ohm,ODT=155ohm */
 		zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT |
 			2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT |
@@ -693,16 +885,8 @@ static int sdram_init(struct dram_info *dram,
 			}
 		}
 
-		if (-1 == data_training(chan, channel, sdram_params)) {
-			if (sdram_params->base.dramtype == LPDDR3) {
-				ddr_phy_ctl_reset(dram->cru, channel, 1);
-				udelay(10);
-				ddr_phy_ctl_reset(dram->cru, channel, 0);
-				udelay(10);
-			}
-			debug("failed!");
-			return -EIO;
-		}
+		/* Detect the rank and bit-width with data-training */
+		sdram_rank_bw_detect(dram, channel, sdram_params);
 
 		if (sdram_params->base.dramtype == LPDDR3) {
 			u32 i;
@@ -710,12 +894,31 @@ static int sdram_init(struct dram_info *dram,
 			for (i = 0; i < 17; i++)
 				send_command_op(pctl, 1, MRR_CMD, i, 0);
 		}
+		writel(15, &chan->msch->ddrconf);
 		move_to_access_state(chan);
+		/* DDR3 and LPDDR3 are always 8 bank, no need detect */
+		sdram_params->ch[channel].bk = 3;
+		/* Detect Col and Row number*/
+		ret = sdram_col_row_detect(dram, channel, sdram_params);
+		if (ret)
+			goto error;
 	}
+	/* Find NIU DDR configuration */
+	ret = sdram_get_niu_config(sdram_params);
+	if (ret)
+		goto error;
+	/* Find stride setting */
+	ret = sdram_get_stride(sdram_params);
+	if (ret)
+		goto error;
+
 	dram_all_config(dram, sdram_params);
 	debug("%s done\n", __func__);
 
 	return 0;
+error:
+	printf("DRAM init failed!\n");
+	hang();
 }
 #endif /* CONFIG_SPL_BUILD */
 
@@ -743,7 +946,6 @@ size_t sdram_size_mb(struct rk3288_pmu *pmu)
 			SYS_REG_BW_MASK));
 		row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
 			SYS_REG_ROW_3_4_MASK;
-
 		chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
 
 		if (rank > 1)
@@ -815,21 +1017,10 @@ static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev)
 	struct rk3288_sdram_params *params = dev_get_platdata(dev);
 	const void *blob = gd->fdt_blob;
 	int node = dev->of_offset;
-	int i, ret;
-
-	params->num_channels = fdtdec_get_int(blob, node,
-					      "rockchip,num-channels", 1);
-	for (i = 0; i < params->num_channels; i++) {
-		ret = fdtdec_get_byte_array(blob, node,
-					    "rockchip,sdram-channel",
-					    (u8 *)&params->ch[i],
-					    sizeof(params->ch[i]));
-		if (ret) {
-			debug("%s: Cannot read rockchip,sdram-channel\n",
-			      __func__);
-			return -EINVAL;
-		}
-	}
+	int ret;
+
+	/* Rk3288 supports dual-channel, set default channel num to 2 */
+	params->num_channels = 2;
 	ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
 				   (u32 *)&params->pctl_timing,
 				   sizeof(params->pctl_timing) / sizeof(u32));
@@ -870,18 +1061,15 @@ static int conv_of_platdata(struct udevice *dev)
 {
 	struct rk3288_sdram_params *plat = dev_get_platdata(dev);
 	struct dtd_rockchip_rk3288_dmc *of_plat = &plat->of_plat;
-	int i, ret;
+	int ret;
 
-	for (i = 0; i < 2; i++) {
-		memcpy(&plat->ch[i], of_plat->rockchip_sdram_channel,
-		       sizeof(plat->ch[i]));
-	}
 	memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
 	       sizeof(plat->pctl_timing));
 	memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
 	       sizeof(plat->phy_timing));
 	memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
-	plat->num_channels = of_plat->rockchip_num_channels;
+	/* Rk3288 supports dual-channel, set default channel num to 2 */
+	plat->num_channels = 2;
 	ret = regmap_init_mem_platdata(dev, of_plat->reg,
 				       ARRAY_SIZE(of_plat->reg) / 2,
 				       &plat->map);
diff --git a/arch/arm/mach-rockchip/rk3399/Makefile b/arch/arm/mach-rockchip/rk3399/Makefile
index 607f9c96129844c61d888f39908040f30cba8f66..98ebeac340d8ccdebaafa003b3a8127ad21b3ce1 100644
--- a/arch/arm/mach-rockchip/rk3399/Makefile
+++ b/arch/arm/mach-rockchip/rk3399/Makefile
@@ -4,5 +4,6 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-y += clk_rk3399.o
 obj-y += rk3399.o
 obj-y += syscon_rk3399.o
diff --git a/arch/arm/mach-rockchip/rk3399/clk_rk3399.c b/arch/arm/mach-rockchip/rk3399/clk_rk3399.c
new file mode 100644
index 0000000000000000000000000000000000000000..7663591154c62c28d6b1ab4af99999178a6c98c8
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3399/clk_rk3399.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3399.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3399_pmuclk), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rk3399_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rk3399/rk3399.c b/arch/arm/mach-rockchip/rk3399/rk3399.c
index b9d7629407809f75967841ba9522c8e353981fd6..8bb950ebd1145c8da3a63f3303b8db662c19e180 100644
--- a/arch/arm/mach-rockchip/rk3399/rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/rk3399.c
@@ -6,6 +6,10 @@
 
 #include <common.h>
 #include <asm/armv8/mmu.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#define GRF_EMMCCORE_CON11 0xff77f02c
 
 static struct mm_region rk3399_mem_map[] = {
 	{
@@ -28,3 +32,13 @@ static struct mm_region rk3399_mem_map[] = {
 };
 
 struct mm_region *mem_map = rk3399_mem_map;
+
+int arch_cpu_init(void)
+{
+	/* We do some SoC one time setting here. */
+
+	/* Emmc clock generator: disable the clock multipilier */
+	rk_clrreg(GRF_EMMCCORE_CON11, 0x0ff);
+
+	return 0;
+}
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index fd8afe752bcbf45cfe519c5a7869fcbe243bb26a..8db9041a13dd6fe40f382f9ecb70bc63deaec06c 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -64,3 +64,4 @@ CONFIG_SYSRESET=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index 5b4d0f14d12b6e05f3dfb8325befd746cb3c5d7c..d5452004b71adac666ae3946e0bfc98f2adf2b0c 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -63,3 +63,4 @@ CONFIG_SYSRESET=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
diff --git a/configs/miniarm-rk3288_defconfig b/configs/miniarm-rk3288_defconfig
index 394e4aa20efd8166f0bdb8795b4266bd3b049335..888563bee128fe3802c800a730d3ba6e511e2402 100644
--- a/configs/miniarm-rk3288_defconfig
+++ b/configs/miniarm-rk3288_defconfig
@@ -62,3 +62,4 @@ CONFIG_SYSRESET=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index ff6a153d2c047fd379a53b1e0de1e88c259542a2..1e70ae03908e29481d75c05bc4274fff879aa835 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -62,3 +62,4 @@ CONFIG_SYSRESET=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
diff --git a/doc/README.rockchip b/doc/README.rockchip
index 69b926c52d56fb3cc616917898e5505b1534c839..06ec80e523684c546c8f283eb3ba55e0854eaabc 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -149,7 +149,6 @@ Note: rk3036 SDMMC and debug uart use the same iomux, so if you boot from SD, th
 
 Using fastboot on rk3288
 ========================
-- Define GPT partition layout like kylin_rk3036(see include/configs/kylin_rk3036.h)
 - Write GPT partition layout to mmc device which fastboot want to use it to
 store the image
 
@@ -212,7 +211,6 @@ When booting you should see something like:
    Err:   serial@ff690000
    =>
 
-
 Future work
 ===========
 
@@ -298,6 +296,15 @@ overhead and in SPL with a 32KB size limit some shortcuts have been taken.
 In general all Rockchip drivers should use these features, with SPL-specific
 modifications where required.
 
+GPT partition layout
+----------------------------
+
+Rockchip use a unified GPT partition layout  in open source support.
+With this GPT partition layout, uboot can be compatilbe with other components,
+like miniloader, trusted-os, arm-trust-firmware.
+
+There are some documents about partitions in the links below.
+http://rockchip.wikidot.com/partitions
 
 --
 Simon Glass <sjg@chromium.org>
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index 8899b0c62db779947963a17d12136808490f40d9..7e3bf9694400769aa75df9ca2c6e225bdd603208 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -19,11 +19,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct rk3036_clk_priv {
-	struct rk3036_cru *cru;
-	ulong rate;
-};
-
 enum {
 	VCO_MAX_HZ	= 2400U * 1000000,
 	VCO_MIN_HZ	= 600 * 1000000,
@@ -49,23 +44,6 @@ enum {
 static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
 
-void *rockchip_get_cru(void)
-{
-	struct udevice *dev;
-	fdt_addr_t addr;
-	int ret;
-
-	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	addr = dev_get_addr(dev);
-	if (addr == FDT_ADDR_T_NONE)
-		return ERR_PTR(-EINVAL);
-
-	return (void *)addr;
-}
-
 static int rkclk_set_pll(struct rk3036_cru *cru, enum rk_clk_id clk_id,
 			 const struct pll_div *div)
 {
@@ -371,7 +349,7 @@ static const struct udevice_id rk3036_clk_ids[] = {
 	{ }
 };
 
-U_BOOT_DRIVER(clk_rk3036) = {
+U_BOOT_DRIVER(rockchip_rk3036_cru) = {
 	.name		= "clk_rk3036",
 	.id		= UCLASS_CLK,
 	.of_match	= rk3036_clk_ids,
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index bd71a969278894f3b46c74a4e0db8fb9d984f45d..ed97e87a959bfbdc936d438e7dd3d9c2336389e5 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -30,12 +30,6 @@ struct rk3288_clk_plat {
 #endif
 };
 
-struct rk3288_clk_priv {
-	struct rk3288_grf *grf;
-	struct rk3288_cru *cru;
-	ulong rate;
-};
-
 struct pll_div {
 	u32 nr;
 	u32 nf;
@@ -140,21 +134,6 @@ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1);
 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
 
-void *rockchip_get_cru(void)
-{
-	struct rk3288_clk_priv *priv;
-	struct udevice *dev;
-	int ret;
-
-	ret = rockchip_get_clk(&dev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	priv = dev_get_priv(dev);
-
-	return priv->cru;
-}
-
 static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id,
 			 const struct pll_div *div)
 {
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index ea0ce2aab101ec67e86ee064ce7997f543883ea6..2e87e4b62d596d423f0cd7b5d2def4e14e83f627 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -18,11 +18,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct rk3399_clk_priv {
-	struct rk3399_cru *cru;
-	ulong rate;
-};
-
 struct rk3399_pmuclk_priv {
 	struct rk3399_pmucru *pmucru;
 };
@@ -780,23 +775,6 @@ static struct clk_ops rk3399_clk_ops = {
 	.set_rate = rk3399_clk_set_rate,
 };
 
-void *rockchip_get_cru(void)
-{
-	struct udevice *dev;
-	fdt_addr_t *addr;
-	int ret;
-
-	ret = uclass_get_device_by_name(UCLASS_CLK, "clk_rk3399", &dev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	addr = dev_get_addr_ptr(dev);
-	if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
-		return ERR_PTR(-EINVAL);
-
-	return addr;
-}
-
 static int rk3399_clk_probe(struct udevice *dev)
 {
 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
@@ -990,7 +968,7 @@ static const struct udevice_id rk3399_pmuclk_ids[] = {
 	{ }
 };
 
-U_BOOT_DRIVER(pmuclk_rk3399) = {
+U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
 	.name		= "pmuclk_rk3399",
 	.id		= UCLASS_CLK,
 	.of_match	= rk3399_pmuclk_ids,
diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h
index f4536405eb45fe41d84c26a322e70664d620e6c5..8fdefa29c7298711f7c3cf2016a991685fc75a0e 100644
--- a/include/configs/evb_rk3399.h
+++ b/include/configs/evb_rk3399.h
@@ -10,7 +10,7 @@
 #include <configs/rk3399_common.h>
 
 #define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_SYS_MMC_ENV_DEV 1
 /*
  * SPL @ 32k for ~36k
  * ENV @ 96k
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index 724a3f40ded987a312f1179e0aea3ef579e318df..4eef3f8cc6e8ac11eb03e05a9dd4ced960208840 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -7,6 +7,7 @@
 #define __CONFIG_RK3036_COMMON_H
 
 #include <asm/arch/hardware.h>
+#include "rockchip-common.h"
 
 #define CONFIG_SYS_NO_FLASH
 #define CONFIG_NR_DRAM_BANKS		1
@@ -78,11 +79,6 @@
 #define CONFIG_G_DNL_VENDOR_NUM		0x2207
 #define CONFIG_G_DNL_PRODUCT_NUM	0x310a
 
-/* Enable gpt partition table */
-#define CONFIG_CMD_GPT
-
-#include <config_distro_defaults.h>
-
 #define ENV_MEM_LAYOUT_SETTINGS \
 	"scriptaddr=0x60000000\0" \
 	"pxefile_addr_r=0x60100000\0" \
@@ -90,17 +86,6 @@
 	"kernel_addr_r=0x62000000\0" \
 	"ramdisk_addr_r=0x64000000\0"
 
-#define CONFIG_RANDOM_UUID
-#define PARTS_DEFAULT \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=boot,start=8M,size=64M,bootable,uuid=${uuid_gpt_boot};" \
-	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
-
-/* First try to boot from SD (index 0), then eMMC (index 1 */
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
-	func(MMC, mmc, 1)
-
 #include <config_distro_bootcmd.h>
 
 /* Linux fails to load the fdt if it's loaded above 512M on a evb-rk3036 board,
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index cf6f3557f08b4e401cb9ebe467b2f2d157327e4b..0868612c136c5f5f6c25bb1e56908e2b5d94a545 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -8,6 +8,7 @@
 #define __CONFIG_RK3288_COMMON_H
 
 #include <asm/arch/hardware.h>
+#include "rockchip-common.h"
 
 #define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
 #define CONFIG_SYS_NO_FLASH
@@ -89,11 +90,6 @@
 #define CONFIG_G_DNL_VENDOR_NUM		0x2207
 #define CONFIG_G_DNL_PRODUCT_NUM	0x320a
 
-/* Enable gpt partition table */
-#define CONFIG_CMD_GPT
-
-#include <config_distro_defaults.h>
-
 #define ENV_MEM_LAYOUT_SETTINGS \
 	"scriptaddr=0x00000000\0" \
 	"pxefile_addr_r=0x00100000\0" \
@@ -101,24 +97,13 @@
 	"kernel_addr_r=0x02000000\0" \
 	"ramdisk_addr_r=0x04000000\0"
 
-#define CONFIG_RANDOM_UUID
-#define PARTS_DEFAULT \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=boot,start=8M,size=64M,bootable,uuid=${uuid_gpt_boot};" \
-	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
-
-/* First try to boot from SD (index 0), then eMMC (index 1 */
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
-	func(MMC, mmc, 1)
-
 #include <config_distro_bootcmd.h>
 
-/* Linux fails to load the fdt if it's loaded above 512M on a Rock 2 board, so
+/* Linux fails to load the fdt if it's loaded above 256M on a Rock 2 board, so
  * limit the fdt reallocation to that */
 #define CONFIG_EXTRA_ENV_SETTINGS \
-	"fdt_high=0x1fffffff\0" \
-	"initrd_high=0x1fffffff\0" \
+	"fdt_high=0x0fffffff\0" \
+	"initrd_high=0x0fffffff\0" \
 	"partitions=" PARTS_DEFAULT \
 	ENV_MEM_LAYOUT_SETTINGS \
 	ROCKCHIP_DEVICE_SETTINGS \
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index bec004a6d86244ba15860711434818a6192d3abd..d75feadab7c881d56e5ac03f4e605c152ce348ea 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -7,6 +7,8 @@
 #ifndef __CONFIG_RK3399_COMMON_H
 #define __CONFIG_RK3399_COMMON_H
 
+#include "rockchip-common.h"
+
 #define CONFIG_SYS_NO_FLASH
 #define CONFIG_NR_DRAM_BANKS		1
 #define CONFIG_ENV_SIZE			0x2000
@@ -52,7 +54,6 @@
 #define CONFIG_SF_DEFAULT_SPEED 20000000
 
 #ifndef CONFIG_SPL_BUILD
-#include <config_distro_defaults.h>
 
 #define ENV_MEM_LAYOUT_SETTINGS \
 	"scriptaddr=0x00000000\0" \
@@ -61,19 +62,6 @@
 	"kernel_addr_r=0x02000000\0" \
 	"ramdisk_addr_r=0x04000000\0"
 
-#define CONFIG_CMD_GPT
-#define CONFIG_RANDOM_UUID
-#define CONFIG_PARTITION_UUIDS
-#define PARTS_DEFAULT \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=boot,start=16M,size=32M,bootable;" \
-	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
-
-/* First try to boot from SD (index 0), then eMMC (index 1) */
-#define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
-	func(MMC, mmc, 1)
-
 #include <config_distro_bootcmd.h>
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	ENV_MEM_LAYOUT_SETTINGS \
diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ca1696a1630ad288d5f1ecc3fe1233be99015ef
--- /dev/null
+++ b/include/configs/rockchip-common.h
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ROCKCHIP_COMMON_H_
+#define _ROCKCHIP_COMMON_H_
+#include <linux/sizes.h>
+
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+
+/* First try to boot from SD (index 0), then eMMC (index 1 */
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(MMC, mmc, 1)
+
+ /* Enable gpt partition table */
+#define CONFIG_CMD_GPT
+#define CONFIG_RANDOM_UUID
+#define CONFIG_PARTITION_UUIDS
+#define PARTS_DEFAULT \
+	"uuid_disk=${uuid_gpt_disk};" \
+	"name=loader1,start=32K,size=4000K,uuid=${uuid_gpt_loader1};" \
+	"name=reserved1,size=64K,uuid=${uuid_gpt_reserved1};" \
+	"name=reserved2,size=4M,uuid=${uuid_gpt_reserved2};" \
+	"name=loader2,size=4MB,uuid=${uuid_gpt_loader2};" \
+	"name=atf,size=4M,uuid=${uuid_gpt_atf};" \
+	"name=boot,size=128M,bootable,uuid=${uuid_gpt_boot};" \
+	"name=rootfs,size=-,uuid=${uuid_gpt_rootfs};\0" \
+
+#endif
+
+#endif /* _ROCKCHIP_COMMON_H_ */