Merge git://git.denx.de/u-boot-rockchip
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 634bc48..f55d5b2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -851,6 +851,8 @@
 	select DM_SPI
 	select DM_SPI_FLASH
 	select DM_USB if USB
+	select DM_PWM
+	select DM_REGULATOR
 
 config TARGET_THUNDERX_88XX
 	bool "Support ThunderX 88xx"
diff --git a/arch/arm/dts/rk3288-miniarm.dtsi b/arch/arm/dts/rk3288-miniarm.dtsi
index b889875..ceb4e2b 100644
--- a/arch/arm/dts/rk3288-miniarm.dtsi
+++ b/arch/arm/dts/rk3288-miniarm.dtsi
@@ -116,18 +116,6 @@
 	cpu0-supply = <&vdd_cpu>;
 };
 
-&emmc {
-	broken-cd;
-	bus-width = <8>;
-	cap-mmc-highspeed;
-	disable-wp;
-	non-removable;
-	num-slots = <1>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
-	status = "okay";
-};
-
 &sdmmc {
 	bus-width = <4>;
 	cap-mmc-highspeed;
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
index bd7801b..fa60e19 100644
--- a/arch/arm/dts/rk3399-evb.dts
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -23,6 +23,7 @@
 		regulator-name = "vdd_center";
 		regulator-min-microvolt = <800000>;
 		regulator-max-microvolt = <1400000>;
+		regulator-init-microvolt = <950000>;
 		regulator-always-on;
 		regulator-boot-on;
 		status = "okay";
diff --git a/arch/arm/include/asm/arch-rockchip/boot_mode.h b/arch/arm/include/asm/arch-rockchip/boot_mode.h
new file mode 100644
index 0000000..bd65f60
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/boot_mode.h
@@ -0,0 +1,19 @@
+#ifndef __REBOOT_MODE_H
+#define __REBOOT_MODE_H
+
+/* high 24 bits is tag, low 8 bits is type */
+#define REBOOT_FLAG		0x5242C300
+/* normal boot */
+#define BOOT_NORMAL		(REBOOT_FLAG + 0)
+/* enter loader rockusb mode */
+#define BOOT_LOADER		(REBOOT_FLAG + 1)
+/* enter recovery */
+#define BOOT_RECOVERY		(REBOOT_FLAG + 3)
+/* enter fastboot mode */
+#define BOOT_FASTBOOT		(REBOOT_FLAG + 9)
+/* enter charging mode */
+#define BOOT_CHARGING		(REBOOT_FLAG + 11)
+/* enter usb mass storage mode */
+#define BOOT_UMS		(REBOOT_FLAG + 12)
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
index c919f47..6776e48 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
@@ -64,9 +64,9 @@
 #define APLL_HZ		(600*MHz)
 #define GPLL_HZ		(594*MHz)
 #define CPLL_HZ		(384*MHz)
-#define PPLL_HZ		(594*MHz)
+#define PPLL_HZ		(676*MHz)
 
-#define PMU_PCLK_HZ	(99*MHz)
+#define PMU_PCLK_HZ	(48*MHz)
 
 #define ACLKM_CORE_HZ	(300*MHz)
 #define ATCLK_CORE_HZ	(300*MHz)
diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h b/arch/arm/include/asm/arch-rockchip/pwm.h
index 08ff945..5d9a178 100644
--- a/arch/arm/include/asm/arch-rockchip/pwm.h
+++ b/arch/arm/include/asm/arch-rockchip/pwm.h
@@ -10,8 +10,8 @@
 
 struct rk3288_pwm {
 	u32 cnt;
-	u32 period_hpr;
 	u32 duty_lpr;
+	u32 period_hpr;
 	u32 ctrl;
 };
 check_member(rk3288_pwm, ctrl, 0xc);
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1aac3c8..8a5d62a 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -42,6 +42,9 @@
           SPL will return to the boot rom, which will then load the U-Boot
           binary to keep going on.
 
+config SPL_MMC_SUPPORT
+	default y if !ROCKCHIP_SPL_BACK_TO_BROM
+
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
 source "arch/arm/mach-rockchip/rk3288/Kconfig"
 source "arch/arm/mach-rockchip/rk3399/Kconfig"
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 157d42f..6e79fed 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -9,7 +9,8 @@
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
 obj-$(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) += save_boot_param.o
 else
-obj-$(CONFIG_ROCKCHIP_RK3288) += board.o
+obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
+obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
 endif
 ifndef CONFIG_ARM64
 obj-y += rk_timer.o
diff --git a/arch/arm/mach-rockchip/rk3036-board.c b/arch/arm/mach-rockchip/rk3036-board.c
new file mode 100644
index 0000000..bf2b268
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3036-board.c
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2015 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/grf_rk3036.h>
+#include <asm/arch/boot_mode.h>
+#include <asm/arch/sdram_rk3036.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GRF_BASE	0x20008000
+
+static void setup_boot_mode(void)
+{
+	struct rk3036_grf *const grf = (void *)GRF_BASE;
+	int boot_mode = readl(&grf->os_reg[4]);
+
+	debug("boot mode %x.\n", boot_mode);
+
+	/* Clear boot mode */
+	writel(BOOT_NORMAL, &grf->os_reg[4]);
+
+	switch (boot_mode) {
+	case BOOT_FASTBOOT:
+		printf("enter fastboot!\n");
+		setenv("preboot", "setenv preboot; fastboot usb0");
+		break;
+	case BOOT_UMS:
+		printf("enter UMS!\n");
+		setenv("preboot", "setenv preboot; ums mmc 0");
+		break;
+	}
+}
+
+__weak int rk_board_late_init(void)
+{
+	return 0;
+}
+
+int board_late_init(void)
+{
+	setup_boot_mode();
+
+	return rk_board_late_init();
+}
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = sdram_size();
+
+	return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
+
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3036_otg_data = {
+	.rx_fifo_sz	= 512,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 128,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int node;
+	const char *mode;
+	bool matched = false;
+	const void *blob = gd->fdt_blob;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3288-usb");
+
+	while (node > 0) {
+		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+		if (mode && strcmp(mode, "otg") == 0) {
+			matched = true;
+			break;
+		}
+
+		node = fdt_node_offset_by_compatible(blob, node,
+					"rockchip,rk3288-usb");
+	}
+	if (!matched) {
+		debug("Not found usb_otg device\n");
+		return -ENODEV;
+	}
+	rk3036_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	return dwc2_udc_probe(&rk3036_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index ae509ff..0f40351 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -206,7 +206,7 @@
 		debug("DRAM init failed: %d\n", ret);
 		return;
 	}
-#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
 	back_to_bootrom();
 #endif
 }
@@ -273,6 +273,9 @@
 	}
 
 	preloader_console_init();
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	back_to_bootrom();
+#endif
 	return;
 err:
 	printf("spl_board_init: Error %d\n", ret);
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/rk3288-board.c
similarity index 80%
rename from arch/arm/mach-rockchip/board.c
rename to arch/arm/mach-rockchip/rk3288-board.c
index 6c36bf9..baf9522 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/rk3288-board.c
@@ -8,25 +8,65 @@
 #include <clk.h>
 #include <dm.h>
 #include <ram.h>
+#include <syscon.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <asm/arch/boot_mode.h>
 #include <asm/gpio.h>
 #include <dm/pinctrl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define PMU_BASE	0xff730000
+
+static void setup_boot_mode(void)
+{
+	struct rk3288_pmu *const pmu = (void *)PMU_BASE;
+	int boot_mode = readl(&pmu->sys_reg[0]);
+
+	debug("boot mode %x.\n", boot_mode);
+
+	/* Clear boot mode */
+	writel(BOOT_NORMAL, &pmu->sys_reg[0]);
+
+	switch (boot_mode) {
+	case BOOT_FASTBOOT:
+		printf("enter fastboot!\n");
+		setenv("preboot", "setenv preboot; fastboot usb0");
+		break;
+	case BOOT_UMS:
+		printf("enter UMS!\n");
+		setenv("preboot", "setenv preboot; if mmc dev 0;"
+		       "then ums mmc 0; else ums mmc 1;fi");
+		break;
+	}
+}
+
+__weak int rk_board_late_init(void)
+{
+	return 0;
+}
+
+int board_late_init(void)
+{
+	setup_boot_mode();
+
+	return rk_board_late_init();
+}
+
 int board_init(void)
 {
 #ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
 	struct udevice *pinctrl;
 	int ret;
 
-    /*
-     * We need to implement sdcard iomux here for the further
-     * initlization, otherwise, it'll hit sdcard command sending
-     * timeout exception.
-     */
+	/*
+	 * We need to implement sdcard iomux here for the further
+	 * initlization, otherwise, it'll hit sdcard command sending
+	 * timeout exception.
+	 */
 	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
 	if (ret) {
 		debug("%s: Cannot find pinctrl device\n", __func__);
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index cf9ef2e..8020e9c 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -755,10 +755,11 @@
 	}
 
 	/*
-	* we use the 0x00000000~0xfeffffff space since 0xff000000~0xffffffff
-	* is SoC register space (i.e. reserved)
+	* 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.
 	*/
-	size_mb = min(size_mb, 0xff000000 >> 20);
+	size_mb = min(size_mb, 0xfe000000 >> 20);
 
 	return size_mb;
 }
diff --git a/board/rockchip/evb_rk3036/evb_rk3036.c b/board/rockchip/evb_rk3036/evb_rk3036.c
index e5582b4..288370a 100644
--- a/board/rockchip/evb_rk3036/evb_rk3036.c
+++ b/board/rockchip/evb_rk3036/evb_rk3036.c
@@ -27,69 +27,3 @@
 	/* 16bit bw */
 	config->bw = 1;
 }
-
-int board_init(void)
-{
-	return 0;
-}
-
-int dram_init(void)
-{
-	gd->ram_size = sdram_size();
-
-	return 0;
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
-	/* Enable D-cache. I-cache is already enabled in start.S */
-	dcache_enable();
-}
-#endif
-
-#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
-#include <usb.h>
-#include <usb/dwc2_udc.h>
-
-static struct dwc2_plat_otg_data rk3036_otg_data = {
-	.rx_fifo_sz	= 512,
-	.np_tx_fifo_sz	= 16,
-	.tx_fifo_sz	= 128,
-};
-
-int board_usb_init(int index, enum usb_init_type init)
-{
-	int node;
-	const char *mode;
-	bool matched = false;
-	const void *blob = gd->fdt_blob;
-
-	/* find the usb_otg node */
-	node = fdt_node_offset_by_compatible(blob, -1,
-					"rockchip,rk3288-usb");
-
-	while (node > 0) {
-		mode = fdt_getprop(blob, node, "dr_mode", NULL);
-		if (mode && strcmp(mode, "otg") == 0) {
-			matched = true;
-			break;
-		}
-
-		node = fdt_node_offset_by_compatible(blob, node,
-					"rockchip,rk3288-usb");
-	}
-	if (!matched) {
-		debug("Not found usb_otg device\n");
-		return -ENODEV;
-	}
-	rk3036_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
-
-	return dwc2_udc_probe(&rk3036_otg_data);
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-	return 0;
-}
-#endif
diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c
index 2580b38..c6e6cd3 100644
--- a/board/rockchip/evb_rk3399/evb-rk3399.c
+++ b/board/rockchip/evb_rk3399/evb-rk3399.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <dm.h>
 #include <dm/pinctrl.h>
+#include <dm/uclass-internal.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
 
@@ -39,6 +40,11 @@
 		goto out;
 	}
 
+	/* rk3399 need init vdd_center to get correct output voltage */
+	ret = regulator_get_by_platname("vdd_center", &regulator);
+	if (ret)
+		debug("%s: Cannot get vdd_center regulator\n", __func__);
+
 	ret = regulator_get_by_platname("vcc5v0_host", &regulator);
 	if (ret) {
 		debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret);
diff --git a/board/rockchip/kylin_rk3036/kylin_rk3036.c b/board/rockchip/kylin_rk3036/kylin_rk3036.c
index 5ade695..7e2edf4 100644
--- a/board/rockchip/kylin_rk3036/kylin_rk3036.c
+++ b/board/rockchip/kylin_rk3036/kylin_rk3036.c
@@ -8,14 +8,11 @@
 #include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/uart.h>
-#include <asm/arch-rockchip/grf_rk3036.h>
 #include <asm/arch/sdram_rk3036.h>
 #include <asm/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define GRF_BASE	0x20008000
-
 void get_ddr_config(struct rk3036_ddr_config *config)
 {
 	/* K4B4G1646Q config */
@@ -43,85 +40,12 @@
 
 #define ROCKCHIP_BOOT_MODE_FASTBOOT	0x5242C309
 
-int board_late_init(void)
+int rk_board_late_init(void)
 {
-	struct rk3036_grf * const grf = (void *)GRF_BASE;
-	int boot_mode = readl(&grf->os_reg[4]);
-
-	/* Clear boot mode */
-	writel(0, &grf->os_reg[4]);
-
-	if (boot_mode == ROCKCHIP_BOOT_MODE_FASTBOOT ||
-	    fastboot_key_pressed()) {
+	if (fastboot_key_pressed()) {
 		printf("enter fastboot!\n");
 		setenv("preboot", "setenv preboot; fastboot usb0");
 	}
 
 	return 0;
 }
-
-int board_init(void)
-{
-	return 0;
-}
-
-int dram_init(void)
-{
-	gd->ram_size = sdram_size();
-
-	return 0;
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
-	/* Enable D-cache. I-cache is already enabled in start.S */
-	dcache_enable();
-}
-#endif
-
-#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
-#include <usb.h>
-#include <usb/dwc2_udc.h>
-
-static struct dwc2_plat_otg_data rk3036_otg_data = {
-	.rx_fifo_sz	= 512,
-	.np_tx_fifo_sz	= 16,
-	.tx_fifo_sz	= 128,
-};
-
-int board_usb_init(int index, enum usb_init_type init)
-{
-	int node;
-	const char *mode;
-	bool matched = false;
-	const void *blob = gd->fdt_blob;
-
-	/* find the usb_otg node */
-	node = fdt_node_offset_by_compatible(blob, -1,
-					"rockchip,rk3288-usb");
-
-	while (node > 0) {
-		mode = fdt_getprop(blob, node, "dr_mode", NULL);
-		if (mode && strcmp(mode, "otg") == 0) {
-			matched = true;
-			break;
-		}
-
-		node = fdt_node_offset_by_compatible(blob, node,
-					"rockchip,rk3288-usb");
-	}
-	if (!matched) {
-		debug("Not found usb_otg device\n");
-		return -ENODEV;
-	}
-	rk3036_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
-
-	return dwc2_udc_probe(&rk3036_otg_data);
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-	return 0;
-}
-#endif
diff --git a/board/rockchip/miniarm_rk3288/miniarm-rk3288.c b/board/rockchip/miniarm_rk3288/miniarm-rk3288.c
index aad74ef..79541a3 100644
--- a/board/rockchip/miniarm_rk3288/miniarm-rk3288.c
+++ b/board/rockchip/miniarm_rk3288/miniarm-rk3288.c
@@ -5,11 +5,3 @@
  */
 
 #include <common.h>
-#include <spl.h>
-
-void board_boot_order(u32 *spl_boot_list)
-{
-	/* eMMC prior to sdcard */
-	spl_boot_list[0] = BOOT_DEVICE_MMC2;
-	spl_boot_list[1] = BOOT_DEVICE_MMC1;
-}
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index 25e8939..97f2966 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -23,6 +23,7 @@
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_PINCTRL=y
 CONFIG_ROCKCHIP_RK3399_PINCTRL=y
+CONFIG_REGULATOR_PWM=y
 CONFIG_RAM=y
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_BASE=0xFF1A0000
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index fc9ff78..0361256 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -7,6 +7,8 @@
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-rock2-square"
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+# CONFIG_SPL_MMC_SUPPORT is not set
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 17f22dd..c7e88c0 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -42,6 +42,16 @@
 	features for REGULATOR PFUZE100. The driver implements get/set api for:
 	value, enable and mode.
 
+config REGULATOR_PWM
+	bool "Enable driver for PWM regulators"
+	depends on DM_REGULATOR
+	---help---
+	Enable support for the PWM regulator functions which voltage are
+	controlled by PWM duty ratio. Some of Rockchip board using this kind
+	of regulator. The driver implements get/set api for the various BUCKS.
+	This driver is controlled by a device tree node
+	which includes voltage limits.
+
 config DM_REGULATOR_MAX77686
 	bool "Enable Driver Model for REGULATOR MAX77686"
 	depends on DM_REGULATOR && DM_PMIC_MAX77686
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 1590d85..ab461ec 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
 obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
+obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_REGULATOR_RK808) += rk808.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c
new file mode 100644
index 0000000..b0a4c5d
--- /dev/null
+++ b/drivers/power/regulator/pwm_regulator.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd
+ *
+ * Based on kernel drivers/regulator/pwm-regulator.c
+ * Copyright (C) 2014 - STMicroelectronics Inc.
+ * Author: Lee Jones <lee.jones@linaro.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <pwm.h>
+#include <power/regulator.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pwm_regulator_info {
+	/* pwm id corresponding to the PWM driver */
+	int pwm_id;
+	/* the period of one PWM cycle */
+	int period_ns;
+	struct udevice *pwm;
+	/* initialize voltage of regulator */
+	unsigned int init_voltage;
+	/* the maximum voltage of regulator */
+	unsigned int max_voltage;
+	/* the minimum voltage of regulator */
+	unsigned int min_voltage;
+	/* the current voltage of regulator */
+	unsigned int volt_uV;
+};
+
+static int pwm_regulator_enable(struct udevice *dev, bool enable)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+
+	return pwm_set_enable(priv->pwm, priv->pwm_id, enable);
+}
+
+static int pwm_voltage_to_duty_cycle_percentage(struct udevice *dev, int req_uV)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+	int min_uV = priv->min_voltage;
+	int max_uV = priv->max_voltage;
+	int diff = max_uV - min_uV;
+
+	return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
+}
+
+static int pwm_regulator_get_voltage(struct udevice *dev)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+
+	return priv->volt_uV;
+}
+
+static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+	int duty_cycle;
+	int ret = 0;
+
+	duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt);
+
+	ret = pwm_set_config(priv->pwm, priv->pwm_id,
+			(priv->period_ns / 100) * duty_cycle, priv->period_ns);
+	if (ret) {
+		dev_err(dev, "Failed to configure PWM\n");
+		return ret;
+	}
+
+	ret = pwm_set_enable(priv->pwm, priv->pwm_id, true);
+	if (ret) {
+		dev_err(dev, "Failed to enable PWM\n");
+		return ret;
+	}
+	priv->volt_uV = uvolt;
+	return ret;
+}
+
+static int pwm_regulator_ofdata_to_platdata(struct udevice *dev)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+	struct fdtdec_phandle_args args;
+	const void *blob = gd->fdt_blob;
+	int node = dev->of_offset;
+	int ret;
+
+	ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells",
+					     0, 0, &args);
+	if (ret) {
+		debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
+		return ret;
+	}
+	/* TODO: pwm_id here from device tree if needed */
+
+	priv->period_ns = args.args[1];
+
+	priv->init_voltage = fdtdec_get_int(blob, node,
+			"regulator-init-microvolt", -1);
+	if (priv->init_voltage < 0) {
+		printf("Cannot find regulator pwm init_voltage\n");
+		return -EINVAL;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm);
+	if (ret) {
+		debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pwm_regulator_probe(struct udevice *dev)
+{
+	struct pwm_regulator_info *priv = dev_get_priv(dev);
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_BUCK;
+	uc_pdata->mode_count = 0;
+	priv->max_voltage = uc_pdata->max_uV;
+	priv->min_voltage = uc_pdata->min_uV;
+
+	if (priv->init_voltage)
+		pwm_regulator_set_voltage(dev, priv->init_voltage);
+
+	pwm_regulator_enable(dev, 1);
+
+	return 0;
+}
+
+static const struct dm_regulator_ops pwm_regulator_ops = {
+	.get_value  = pwm_regulator_get_voltage,
+	.set_value  = pwm_regulator_set_voltage,
+	.set_enable = pwm_regulator_enable,
+};
+
+static const struct udevice_id pwm_regulator_ids[] = {
+	{ .compatible = "pwm-regulator" },
+	{ }
+};
+
+U_BOOT_DRIVER(pwm_regulator) = {
+	.name = "pwm_regulator",
+	.id = UCLASS_REGULATOR,
+	.ops = &pwm_regulator_ops,
+	.probe = pwm_regulator_probe,
+	.of_match = pwm_regulator_ids,
+	.ofdata_to_platdata	= pwm_regulator_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct pwm_regulator_info),
+};
diff --git a/include/configs/kylin_rk3036.h b/include/configs/kylin_rk3036.h
index e8ca76d..4f0bd84 100644
--- a/include/configs/kylin_rk3036.h
+++ b/include/configs/kylin_rk3036.h
@@ -23,33 +23,6 @@
 #define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
 #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
 
-/* Enable gpt partition table */
-#define CONFIG_CMD_GPT
-#define CONFIG_RANDOM_UUID
-#define PARTS_DEFAULT \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=loader,start=32K,size=4000K,uuid=${uuid_gpt_loader};" \
-	"name=reserved,size=64K,uuid=${uuid_gpt_reserved};" \
-	"name=misc,size=4M,uuid=${uuid_gpt_misc};" \
-	"name=recovery,size=32M,uuid=${uuid_gpt_recovery};" \
-	"name=boot_a,size=32M,uuid=${uuid_gpt_boot_a};" \
-	"name=boot_b,size=32M,uuid=${uuid_gpt_boot_b};" \
-	"name=system_a,size=818M,uuid=${uuid_gpt_system_a};" \
-	"name=system_b,size=818M,uuid=${uuid_gpt_system_b};" \
-	"name=vendor_a,size=50M,uuid=${uuid_gpt_vendor_a};" \
-	"name=vendor_b,size=50M,uuid=${uuid_gpt_vendor_b};" \
-	"name=cache,size=100M,uuid=${uuid_gpt_cache};" \
-	"name=metadata,size=16M,uuid=${uuid_gpt_metadata};" \
-	"name=persist,size=4M,uuid=${uuid_gpt_persist};" \
-	"name=userdata,size=-,uuid=${uuid_gpt_userdata};\0" \
-
-#undef CONFIG_EXTRA_ENV_SETTINGS
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	"partitions=" PARTS_DEFAULT \
-
 #endif
 
-#define CONFIG_BOARD_LATE_INIT
-#define CONFIG_PREBOOT
-
 #endif
diff --git a/include/configs/miniarm_rk3288.h b/include/configs/miniarm_rk3288.h
index 390c243..aa259db 100644
--- a/include/configs/miniarm_rk3288.h
+++ b/include/configs/miniarm_rk3288.h
@@ -10,8 +10,13 @@
 #define ROCKCHIP_DEVICE_SETTINGS
 #include <configs/rk3288_common.h>
 
+#undef BOOT_TARGET_DEVICES
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0)
+
 #define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_SYS_MMC_ENV_DEV 1
+#define CONFIG_SYS_MMC_ENV_DEV 0
 /* SPL @ 32k for ~36k
  * ENV @ 96k
  * u-boot @ 128K
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index 4b26662..73830e4 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -70,11 +70,18 @@
 #define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE	0x08000000
 
+/* usb mass storage */
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+#define CONFIG_CMD_USB_MASS_STORAGE
+
 #define CONFIG_USB_GADGET_DOWNLOAD
 #define CONFIG_G_DNL_MANUFACTURER	"Rockchip"
 #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 \
@@ -84,6 +91,12 @@
 	"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) \
@@ -95,8 +108,12 @@
  * so limit the fdt reallocation to that */
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"fdt_high=0x7fffffff\0" \
+	"partitions=" PARTS_DEFAULT \
 	ENV_MEM_LAYOUT_SETTINGS \
 	BOOTENV
 #endif
 
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_PREBOOT
+
 #endif
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index e8bf987..9ddfe1d 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -132,4 +132,7 @@
 	BOOTENV
 #endif
 
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_PREBOOT
+
 #endif
diff --git a/include/configs/rock2.h b/include/configs/rock2.h
index ee924c3..99d6915 100644
--- a/include/configs/rock2.h
+++ b/include/configs/rock2.h
@@ -16,11 +16,20 @@
 
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV 0
+
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+/* SPL @ 32k for 34k
+ * u-boot directly after @ 68k for 400k or so
+ * ENV @ 992k
+ */
+#define CONFIG_ENV_OFFSET ((1024-32) * 1024)
+#else
 /* SPL @ 32k for ~36k
  * ENV @ 96k
  * u-boot @ 128K
  */
 #define CONFIG_ENV_OFFSET (96 * 1024)
+#endif
 
 #define CONFIG_SYS_WHITE_ON_BLACK
 #define CONFIG_CONSOLE_SCROLL_LINES		10