Merge tag 'for-master-20181130' of git://git.denx.de/u-boot-rockchip

Improvements:
- RK3188 USB-UART functionality
- errors triggering a hard-stop in SPL on the RK3399 are reported
- Rockchip RV1108 (SoC) support
- MicroCrystal RV3029 (RTC) DM driver

Fixes:
- RK3188 early UART setup
- limit SD-card frequency to 40MHz on the RK3399-Q7
- MIPI fixes
- RK3399 CPUB clock initialisation
diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi
index 6e7e1e3..11ffcb7 100644
--- a/arch/arm/dts/rk3399-puma.dtsi
+++ b/arch/arm/dts/rk3399-puma.dtsi
@@ -503,7 +503,7 @@
 &sdmmc {
 	u-boot,dm-pre-reloc;
 	clock-frequency = <150000000>;
-	clock-freq-min-max = <100000 150000000>;
+	max-frequency = <40000000>;
 	supports-sd;
 	bus-width = <4>;
 	cap-mmc-highspeed;
diff --git a/arch/arm/dts/rv1108.dtsi b/arch/arm/dts/rv1108.dtsi
index acfd97e..215d885 100644
--- a/arch/arm/dts/rv1108.dtsi
+++ b/arch/arm/dts/rv1108.dtsi
@@ -121,8 +121,35 @@
 	};
 
 	grf: syscon@10300000 {
-		compatible = "rockchip,rv1108-grf", "syscon";
+		compatible = "rockchip,rv1108-grf", "syscon", "simple-mfd";
 		reg = <0x10300000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		u2phy: usb2-phy@100 {
+			compatible = "rockchip,rv1108-usb2phy";
+			reg = <0x100 0x0c>;
+			clocks = <&cru SCLK_USBPHY>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+			clock-output-names = "usbphy";
+			rockchip,usbgrf = <&usbgrf>;
+			status = "disabled";
+
+			u2phy_otg: otg-port {
+				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "otg-mux";
+				#phy-cells = <0>;
+				status = "disabled";
+			};
+
+			u2phy_host: host-port {
+				interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "linestate";
+				#phy-cells = <0>;
+				status = "disabled";
+			};
+		};
 	};
 
 	saradc: saradc@1038c000 {
@@ -141,6 +168,11 @@
 		reg = <0x20060000 0x1000>;
 	};
 
+	usbgrf: syscon@202a0000 {
+		compatible = "rockchip,rv1108-usbgrf", "syscon";
+		reg = <0x202a0000 0x1000>;
+	};
+
 	cru: clock-controller@20200000 {
 		compatible = "rockchip,rv1108-cru";
 		reg = <0x20200000 0x1000>;
@@ -200,12 +232,19 @@
 	};
 
 	usb20_otg: usb@30180000 {
-		compatible = "rockchip,rv1108-usb", "rockchip,rk3288-usb",
+		compatible = "rockchip,rv1108-usb", "rockchip,rk3066-usb",
 			     "snps,dwc2";
 		reg = <0x30180000 0x40000>;
 		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
-		hnp-srp-disable;
+		clocks = <&cru HCLK_OTG>;
+		clock-names = "otg";
 		dr_mode = "otg";
+		g-np-tx-fifo-size = <16>;
+		g-rx-fifo-size = <280>;
+		g-tx-fifo-size = <256 128 128 64 32 16>;
+		g-use-dma;
+		phys = <&u2phy_otg>;
+		phy-names = "usb2-phy";
 		status = "disabled";
 	};
 
@@ -427,6 +466,35 @@
 			};
 		};
 
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <2 RK_PB6 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <2 RK_PB4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+			};
+
+			emmc_pwren: emmc-pwren {
+				rockchip,pins = <2 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins = <2 RK_PA0 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins = <2 RK_PA0 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA1 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA2 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA3 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA5 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA6 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+						<2 RK_PA7 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+			};
+		};
+
 		sdmmc {
 			sdmmc_clk: sdmmc-clk {
 				rockchip,pins = <3 RK_PC4 RK_FUNC_1 &pcfg_pull_none_drv_4ma>;
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 1d5b3a0..0eb19ca 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -43,6 +43,12 @@
 	unsigned int glb_srst_snd_value;
 };
 
+struct softreset_reg {
+        void __iomem *base;
+        unsigned int sf_reset_offset;
+        unsigned int sf_reset_num;
+};
+
 /**
  * clk_get_divisor() - Calculate the required clock divisior
  *
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
index b18de9f..15eeb9c 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h
@@ -69,16 +69,21 @@
 #define MHz		1000000
 #define KHz		1000
 #define OSC_HZ		(24*MHz)
-#define APLL_HZ		(600*MHz)
+#define LPLL_HZ		(600*MHz)
+#define BPLL_HZ		(600*MHz)
 #define GPLL_HZ		(594*MHz)
 #define CPLL_HZ		(384*MHz)
 #define PPLL_HZ		(676*MHz)
 
 #define PMU_PCLK_HZ	(48*MHz)
 
-#define ACLKM_CORE_HZ	(300*MHz)
-#define ATCLK_CORE_HZ	(300*MHz)
-#define PCLK_DBG_HZ	(100*MHz)
+#define ACLKM_CORE_L_HZ	(300*MHz)
+#define ATCLK_CORE_L_HZ	(300*MHz)
+#define PCLK_DBG_L_HZ	(100*MHz)
+
+#define ACLKM_CORE_B_HZ	(300*MHz)
+#define ATCLK_CORE_B_HZ	(300*MHz)
+#define PCLK_DBG_B_HZ	(100*MHz)
 
 #define PERIHP_ACLK_HZ	(148500*KHz)
 #define PERIHP_HCLK_HZ	(148500*KHz)
@@ -98,4 +103,13 @@
 	APLL_L_600_MHZ,
 };
 
+enum apll_b_frequencies {
+	APLL_B_600_MHZ,
+};
+
+void rk3399_configure_cpu_l(struct rk3399_cru *cru,
+			    enum apll_l_frequencies apll_l_freq);
+void rk3399_configure_cpu_b(struct rk3399_cru *cru,
+			    enum apll_b_frequencies apll_b_freq);
+
 #endif	/* __ASM_ARCH_CRU_RK3399_H_ */
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
index 3cc2ed0..7697e96 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
@@ -11,7 +11,11 @@
 #define OSC_HZ		(24 * 1000 * 1000)
 
 #define APLL_HZ		(600 * 1000000)
-#define GPLL_HZ		(594 * 1000000)
+#define GPLL_HZ		(1188 * 1000000)
+#define ACLK_PERI_HZ	(148500000)
+#define HCLK_PERI_HZ	(148500000)
+#define PCLK_PERI_HZ	(74250000)
+#define ACLK_BUS_HZ	(148500000)
 
 struct rv1108_clk_priv {
 	struct rv1108_cru *cru;
@@ -80,6 +84,11 @@
 	WORK_MODE_NORMAL	= 1,
 	DSMPD_SHIFT             = 3,
 	DSMPD_MASK		= 1 << DSMPD_SHIFT,
+	INTEGER_MODE			= 1,
+	GLOBAL_POWER_DOWN_SHIFT		= 0,
+	GLOBAL_POWER_DOWN_MASK		= 1 << GLOBAL_POWER_DOWN_SHIFT,
+	GLOBAL_POWER_DOWN		= 1,
+	GLOBAL_POWER_UP			= 0,
 
 	/* CLKSEL0_CON */
 	CORE_PLL_SEL_SHIFT	= 8,
@@ -90,11 +99,77 @@
 	CORE_CLK_DIV_SHIFT	= 0,
 	CORE_CLK_DIV_MASK	= 0x1f << CORE_CLK_DIV_SHIFT,
 
+	/* CLKSEL_CON1 */
+	PCLK_DBG_DIV_CON_SHIFT		= 4,
+	PCLK_DBG_DIV_CON_MASK		= 0xf << PCLK_DBG_DIV_CON_SHIFT,
+	ACLK_CORE_DIV_CON_SHIFT		= 0,
+	ACLK_CORE_DIV_CON_MASK		= 7 << ACLK_CORE_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON2 */
+	ACLK_BUS_PLL_SEL_SHIFT		= 8,
+	ACLK_BUS_PLL_SEL_MASK		= 3 << ACLK_BUS_PLL_SEL_SHIFT,
+	ACLK_BUS_PLL_SEL_GPLL		= 0,
+	ACLK_BUS_PLL_SEL_APLL		= 1,
+	ACLK_BUS_PLL_SEL_DPLL		= 2,
+	ACLK_BUS_DIV_CON_SHIFT		= 0,
+	ACLK_BUS_DIV_CON_MASK		= 0x1f << ACLK_BUS_DIV_CON_SHIFT,
+	ACLK_BUS_DIV_CON_WIDTH		= 5,
+
+	/* CLKSEL_CON3 */
+	PCLK_BUS_DIV_CON_SHIFT		= 8,
+	PCLK_BUS_DIV_CON_MASK		= 0x1f << PCLK_BUS_DIV_CON_SHIFT,
+	HCLK_BUS_DIV_CON_SHIFT		= 0,
+	HCLK_BUS_DIV_CON_MASK		= 0x1f,
+
+	/* CLKSEL_CON4 */
+	CLK_DDR_PLL_SEL_SHIFT		= 8,
+	CLK_DDR_PLL_SEL_MASK		= 0x3 << CLK_DDR_PLL_SEL_SHIFT,
+	CLK_DDR_DIV_CON_SHIFT		= 0,
+	CLK_DDR_DIV_CON_MASK		= 0x3 << CLK_DDR_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON19 */
+	CLK_I2C1_PLL_SEL_SHIFT		= 15,
+	CLK_I2C1_PLL_SEL_MASK		= 1 << CLK_I2C1_PLL_SEL_SHIFT,
+	CLK_I2C1_PLL_SEL_DPLL		= 0,
+	CLK_I2C1_PLL_SEL_GPLL		= 1,
+	CLK_I2C1_DIV_CON_SHIFT		= 8,
+	CLK_I2C1_DIV_CON_MASK		= 0x7f << CLK_I2C1_DIV_CON_SHIFT,
+	CLK_I2C0_PLL_SEL_SHIFT		= 7,
+	CLK_I2C0_PLL_SEL_MASK		= 1 << CLK_I2C0_PLL_SEL_SHIFT,
+	CLK_I2C0_DIV_CON_SHIFT		= 0,
+	CLK_I2C0_DIV_CON_MASK		= 0x7f,
+	I2C_DIV_CON_WIDTH		= 7,
+
+	/* CLKSEL_CON20 */
+	CLK_I2C3_PLL_SEL_SHIFT		= 15,
+	CLK_I2C3_PLL_SEL_MASK		= 1 << CLK_I2C3_PLL_SEL_SHIFT,
+	CLK_I2C3_PLL_SEL_DPLL		= 0,
+	CLK_I2C3_PLL_SEL_GPLL		= 1,
+	CLK_I2C3_DIV_CON_SHIFT		= 8,
+	CLK_I2C3_DIV_CON_MASK		= 0x7f << CLK_I2C3_DIV_CON_SHIFT,
+	CLK_I2C2_PLL_SEL_SHIFT		= 7,
+	CLK_I2C2_PLL_SEL_MASK		= 1 << CLK_I2C2_PLL_SEL_SHIFT,
+	CLK_I2C2_DIV_CON_SHIFT		= 0,
+	CLK_I2C2_DIV_CON_MASK		= 0x7f,
+
 	/* CLKSEL_CON22 */
 	CLK_SARADC_DIV_CON_SHIFT= 0,
 	CLK_SARADC_DIV_CON_MASK	= GENMASK(9, 0),
 	CLK_SARADC_DIV_CON_WIDTH= 10,
 
+	/* CLKSEL_CON23 */
+	ACLK_PERI_PLL_SEL_SHIFT		= 15,
+	ACLK_PERI_PLL_SEL_MASK		= 1 << ACLK_PERI_PLL_SEL_SHIFT,
+	ACLK_PERI_PLL_SEL_GPLL		= 0,
+	ACLK_PERI_PLL_SEL_DPLL		= 1,
+	PCLK_PERI_DIV_CON_SHIFT		= 10,
+	PCLK_PERI_DIV_CON_MASK		= 0x1f << PCLK_PERI_DIV_CON_SHIFT,
+	HCLK_PERI_DIV_CON_SHIFT		= 5,
+	HCLK_PERI_DIV_CON_MASK		= 0x1f << HCLK_PERI_DIV_CON_SHIFT,
+	ACLK_PERI_DIV_CON_SHIFT		= 0,
+	ACLK_PERI_DIV_CON_MASK		= 0x1f,
+	PERI_DIV_CON_WIDTH		= 5,
+
 	/* CLKSEL24_CON */
 	MAC_PLL_SEL_SHIFT	= 12,
 	MAC_PLL_SEL_MASK	= 1 << MAC_PLL_SEL_SHIFT,
@@ -105,6 +180,17 @@
 	MAC_CLK_DIV_MASK	= 0x1f,
 	MAC_CLK_DIV_SHIFT	= 0,
 
+	/* CLKSEL25_CON */
+	EMMC_PLL_SEL_SHIFT	= 12,
+	EMMC_PLL_SEL_MASK	= 3 << EMMC_PLL_SEL_SHIFT,
+	EMMC_PLL_SEL_DPLL	= 0,
+	EMMC_PLL_SEL_GPLL,
+	EMMC_PLL_SEL_OSC,
+
+	/* CLKSEL26_CON */
+	EMMC_CLK_DIV_SHIFT	= 8,
+	EMMC_CLK_DIV_MASK	= 0xff << EMMC_CLK_DIV_SHIFT,
+
 	/* CLKSEL27_CON */
 	SFC_PLL_SEL_SHIFT	= 7,
 	SFC_PLL_SEL_MASK	= 1 << SFC_PLL_SEL_SHIFT,
@@ -112,5 +198,61 @@
 	SFC_PLL_SEL_GPLL	= 1,
 	SFC_CLK_DIV_SHIFT	= 0,
 	SFC_CLK_DIV_MASK	= 0x3f << SFC_CLK_DIV_SHIFT,
+
+	/* CLKSEL28_CON */
+	ACLK_VIO1_PLL_SEL_SHIFT		= 14,
+	ACLK_VIO1_PLL_SEL_MASK		= 3 << ACLK_VIO1_PLL_SEL_SHIFT,
+	VIO_PLL_SEL_DPLL		= 0,
+	VIO_PLL_SEL_GPLL		= 1,
+	ACLK_VIO1_CLK_DIV_SHIFT		= 8,
+	ACLK_VIO1_CLK_DIV_MASK		= 0x1f << ACLK_VIO1_CLK_DIV_SHIFT,
+	CLK_VIO_DIV_CON_WIDTH		= 5,
+	ACLK_VIO0_PLL_SEL_SHIFT		= 6,
+	ACLK_VIO0_PLL_SEL_MASK		= 3 << ACLK_VIO0_PLL_SEL_SHIFT,
+	ACLK_VIO0_CLK_DIV_SHIFT		= 0,
+	ACLK_VIO0_CLK_DIV_MASK		= 0x1f << ACLK_VIO0_CLK_DIV_SHIFT,
+
+	/* CLKSEL29_CON */
+	PCLK_VIO_CLK_DIV_SHIFT		= 8,
+	PCLK_VIO_CLK_DIV_MASK		= 0x1f << PCLK_VIO_CLK_DIV_SHIFT,
+	HCLK_VIO_CLK_DIV_SHIFT		= 0,
+	HCLK_VIO_CLK_DIV_MASK		= 0x1f << HCLK_VIO_CLK_DIV_SHIFT,
+
+	/* CLKSEL32_CON */
+	DCLK_VOP_SEL_SHIFT		= 7,
+	DCLK_VOP_SEL_MASK		= 1 << DCLK_VOP_SEL_SHIFT,
+	DCLK_VOP_SEL_HDMI		= 0,
+	DCLK_VOP_SEL_PLL		= 1,
+	DCLK_VOP_PLL_SEL_SHIFT		= 6,
+	DCLK_VOP_PLL_SEL_MASK		= 1 << DCLK_VOP_PLL_SEL_SHIFT,
+	DCLK_VOP_PLL_SEL_GPLL		= 0,
+	DCLK_VOP_PLL_SEL_DPLL		= 1,
+	DCLK_VOP_CLK_DIV_SHIFT		= 0,
+	DCLK_VOP_CLK_DIV_MASK		= 0x3f << DCLK_VOP_CLK_DIV_SHIFT,
+	DCLK_VOP_DIV_CON_WIDTH		= 6,
+
+	/* SOFTRST1_CON*/
+	DDRPHY_SRSTN_CLKDIV_REQ_SHIFT	= 0,
+	DDRPHY_SRSTN_CLKDIV_REQ		= 1,
+	DDRPHY_SRSTN_CLKDIV_DIS		= 0,
+	DDRPHY_SRSTN_CLKDIV_REQ_MASK	= 1 << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT,
+	DDRPHY_SRSTN_REQ_SHIFT		= 1,
+	DDRPHY_SRSTN_REQ		= 1,
+	DDRPHY_SRSTN_DIS		= 0,
+	DDRPHY_SRSTN_REQ_MASK		= 1 << DDRPHY_SRSTN_REQ_SHIFT,
+	DDRPHY_PSRSTN_REQ_SHIFT		= 2,
+	DDRPHY_PSRSTN_REQ		= 1,
+	DDRPHY_PSRSTN_DIS		= 0,
+	DDRPHY_PSRSTN_REQ_MASK		= 1 << DDRPHY_PSRSTN_REQ_SHIFT,
+
+	/* SOFTRST2_CON*/
+	DDRUPCTL_PSRSTN_REQ_SHIFT	= 0,
+	DDRUPCTL_PSRSTN_REQ		= 1,
+	DDRUPCTL_PSRSTN_DIS		= 0,
+	DDRUPCTL_PSRSTN_REQ_MASK	= 1 << DDRUPCTL_PSRSTN_REQ_SHIFT,
+	DDRUPCTL_NSRSTN_REQ_SHIFT	= 1,
+	DDRUPCTL_NSRSTN_REQ		= 1,
+	DDRUPCTL_NSRSTN_DIS		= 0,
+	DDRUPCTL_NSRSTN_REQ_MASK	= 1 << DDRUPCTL_NSRSTN_REQ_SHIFT,
 };
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3188.h b/arch/arm/include/asm/arch-rockchip/grf_rk3188.h
index 28a159c..d051976 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3188.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3188.h
@@ -205,4 +205,46 @@
 	ATO_AE_SHIFT		= 0,
 	ATO_AE_MASK		= 1,
 };
+
+/* GRF_UOC_CON0 */
+enum {
+	SIDDQ_SHIFT		= 13,
+	SIDDQ_MASK		= 1 << SIDDQ_SHIFT,
+
+	BYPASSSEL_SHIFT		= 9,
+	BYPASSSEL_MASK		= 1 << BYPASSSEL_SHIFT,
+
+	BYPASSDMEN_SHIFT	= 8,
+	BYPASSDMEN_MASK		= 1 << BYPASSDMEN_SHIFT,
+
+	UOC_DISABLE_SHIFT	= 4,
+	UOC_DISABLE_MASK	= 1 << UOC_DISABLE_SHIFT,
+
+	COMMON_ON_N_SHIFT	= 0,
+	COMMON_ON_N_MASK	= 1 << COMMON_ON_N_SHIFT,
+};
+
+/* GRF_UOC_CON2 */
+enum {
+	SOFT_CON_SEL_SHIFT	= 2,
+	SOFT_CON_SEL_MASK	= 1 << SOFT_CON_SEL_SHIFT,
+};
+
+/* GRF_UOC0_CON3 */
+enum {
+	TERMSEL_FULLSPEED_SHIFT	= 5,
+	TERMSEL_FULLSPEED_MASK	= 1 << TERMSEL_FULLSPEED_SHIFT,
+
+	XCVRSELECT_SHIFT	= 3,
+	XCVRSELECT_FSTRANSC	= 1,
+	XCVRSELECT_MASK		= 3 << XCVRSELECT_SHIFT,
+
+	OPMODE_SHIFT		= 1,
+	OPMODE_NODRIVING	= 1,
+	OPMODE_MASK		= 3 << OPMODE_SHIFT,
+
+	SUSPENDN_SHIFT		= 0,
+	SUSPENDN_MASK		= 1 << SUSPENDN_SHIFT,
+};
+
 #endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 145d96b..6dc8e3a 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -35,6 +35,7 @@
 	select SPL_RAM
 	select SPL_DRIVERS_MISC_SUPPORT
 	select SPL_ROCKCHIP_EARLYRETURN_TO_BROM
+	select DEBUG_UART_BOARD_INIT
 	select BOARD_LATE_INIT
 	select ROCKCHIP_BROM_HELPER
 	help
@@ -156,6 +157,14 @@
 	  The Rockchip RV1108 is a ARM-based SoC with a single-core Cortex-A7
 	  and a DSP.
 
+config ROCKCHIP_USB_UART
+	bool "Route uart output to usb pins"
+	help
+	  Rockchip SoCs have the ability to route the signals of the debug
+	  uart through the d+ and d- pins of a specific usb phy to enable
+	  some form of closed-case debugging. With this option supported
+	  SoCs will enable this routing as a debug measure.
+
 config SPL_ROCKCHIP_BACK_TO_BROM
 	bool "SPL returns to bootrom"
 	default y if ROCKCHIP_RK3036
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 05706c4..368302e 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -33,6 +33,7 @@
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board.o
+obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108-board.o
 endif
 
 obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o
diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
index 98ca971..3c6c3d3 100644
--- a/arch/arm/mach-rockchip/rk3188-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
@@ -16,6 +16,7 @@
 #include <asm/io.h>
 #include <asm/arch/bootrom.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3188.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/periph.h>
 #include <asm/arch/pmu_rk3188.h>
@@ -92,23 +93,38 @@
 	return ret;
 }
 
-void board_init_f(ulong dummy)
+void board_debug_uart_init(void)
 {
-	struct udevice *pinctrl, *dev;
-	int ret;
-
-	/* Example code showing how to enable the debug UART on RK3188 */
-#ifdef EARLY_UART
-#include <asm/arch/grf_rk3188.h>
 	/* Enable early UART on the RK3188 */
 #define GRF_BASE	0x20008000
 	struct rk3188_grf * const grf = (void *)GRF_BASE;
+	enum {
+		GPIO1B1_SHIFT		= 2,
+		GPIO1B1_MASK		= 3,
+		GPIO1B1_GPIO		= 0,
+		GPIO1B1_UART2_SOUT,
 
+		GPIO1B0_SHIFT		= 0,
+		GPIO1B0_MASK		= 3,
+		GPIO1B0_GPIO		= 0,
+		GPIO1B0_UART2_SIN,
+	};
+
+	/* Enable early UART on the RK3188 */
 	rk_clrsetreg(&grf->gpio1b_iomux,
 		     GPIO1B1_MASK << GPIO1B1_SHIFT |
 		     GPIO1B0_MASK << GPIO1B0_SHIFT,
 		     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
 		     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+}
+
+void board_init_f(ulong dummy)
+{
+	struct udevice *pinctrl, *dev;
+	int ret;
+
+#define EARLY_UART
+#ifdef EARLY_UART
 	/*
 	 * Debug UART can be used from here if required:
 	 *
@@ -124,6 +140,25 @@
 	printch('\n');
 #endif
 
+#ifdef CONFIG_ROCKCHIP_USB_UART
+	rk_clrsetreg(&grf->uoc0_con[0],
+		     SIDDQ_MASK | UOC_DISABLE_MASK | COMMON_ON_N_MASK,
+		     1 << SIDDQ_SHIFT | 1 << UOC_DISABLE_SHIFT |
+		     1 << COMMON_ON_N_SHIFT);
+	rk_clrsetreg(&grf->uoc0_con[2],
+		     SOFT_CON_SEL_MASK, 1 << SOFT_CON_SEL_SHIFT);
+	rk_clrsetreg(&grf->uoc0_con[3],
+		     OPMODE_MASK | XCVRSELECT_MASK |
+		     TERMSEL_FULLSPEED_MASK | SUSPENDN_MASK,
+		     OPMODE_NODRIVING << OPMODE_SHIFT |
+		     XCVRSELECT_FSTRANSC << XCVRSELECT_SHIFT |
+		     1 << TERMSEL_FULLSPEED_SHIFT |
+		     1 << SUSPENDN_SHIFT);
+	rk_clrsetreg(&grf->uoc0_con[0],
+		     BYPASSSEL_MASK | BYPASSDMEN_MASK,
+		     1 << BYPASSSEL_SHIFT | 1 << BYPASSDMEN_SHIFT);
+#endif
+
 	ret = spl_early_init();
 	if (ret) {
 		debug("spl_early_init() failed: %d\n", ret);
diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c
index 43350e3..0198c6c 100644
--- a/arch/arm/mach-rockchip/rk3399-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3399-board-spl.c
@@ -202,13 +202,13 @@
 
 	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
 	if (ret) {
-		debug("Pinctrl init failed: %d\n", ret);
+		pr_err("Pinctrl init failed: %d\n", ret);
 		return;
 	}
 
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
-		debug("DRAM init failed: %d\n", ret);
+		pr_err("DRAM init failed: %d\n", ret);
 		return;
 	}
 }
diff --git a/arch/arm/mach-rockchip/rv1108-board.c b/arch/arm/mach-rockchip/rv1108-board.c
new file mode 100644
index 0000000..3412f2c
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1108-board.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#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 rv1108_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)
+{
+	const void *blob = gd->fdt_blob;
+	bool matched = false;
+	int node, phy_node;
+	u32 grf_phy_offset;
+	const char *mode;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1, "rockchip,rk3066-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,rk3066-usb");
+	}
+
+	if (!matched) {
+		debug("usb_otg device not found\n");
+		return -ENODEV;
+	}
+
+	rv1108_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	node = fdtdec_lookup_phandle(blob, node, "phys");
+	if (node <= 0) {
+		debug("phys node not found\n");
+		return -ENODEV;
+	}
+
+	phy_node = fdt_parent_offset(blob, node);
+	if (phy_node <= 0) {
+		debug("usb phy node not found\n");
+		return -ENODEV;
+	}
+
+	rv1108_otg_data.phy_of_node = phy_node;
+	grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
+
+	/* find the grf node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "rockchip,rv1108-grf");
+	if (node <= 0) {
+		debug("grf node not found\n");
+		return -ENODEV;
+	}
+
+	rv1108_otg_data.regs_phy = grf_phy_offset + fdtdec_get_addr(blob, node,
+								    "reg");
+
+	return dwc2_udc_probe(&rv1108_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/configs/rock_defconfig b/configs/rock_defconfig
index 28dcd5b..0c41ac9 100644
--- a/configs/rock_defconfig
+++ b/configs/rock_defconfig
@@ -56,6 +56,5 @@
 CONFIG_USB=y
 CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_SPL_TINY_MEMSET=y
-CONFIG_TPL_TINY_MEMSET=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 26faf88..198914b 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -61,6 +61,11 @@
 	[APLL_L_600_MHZ] = &apll_l_600_cfg,
 };
 
+static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+static const struct pll_div *apll_b_cfgs[] = {
+	[APLL_B_600_MHZ] = &apll_b_600_cfg,
+};
+
 enum {
 	/* PLL_CON0 */
 	PLL_FBDIV_MASK			= 0xfff,
@@ -128,6 +133,24 @@
 	ATCLK_CORE_L_DIV_SHIFT		= 0,
 	ATCLK_CORE_L_DIV_MASK		= 0x1f << ATCLK_CORE_L_DIV_SHIFT,
 
+	/* CLKSEL_CON2 */
+	ACLKM_CORE_B_DIV_CON_SHIFT	= 8,
+	ACLKM_CORE_B_DIV_CON_MASK	= 0x1f << ACLKM_CORE_B_DIV_CON_SHIFT,
+	CLK_CORE_B_PLL_SEL_SHIFT	= 6,
+	CLK_CORE_B_PLL_SEL_MASK		= 3 << CLK_CORE_B_PLL_SEL_SHIFT,
+	CLK_CORE_B_PLL_SEL_ALPLL	= 0x0,
+	CLK_CORE_B_PLL_SEL_ABPLL	= 0x1,
+	CLK_CORE_B_PLL_SEL_DPLL		= 0x10,
+	CLK_CORE_B_PLL_SEL_GPLL		= 0x11,
+	CLK_CORE_B_DIV_MASK		= 0x1f,
+	CLK_CORE_B_DIV_SHIFT		= 0,
+
+	/* CLKSEL_CON3 */
+	PCLK_DBG_B_DIV_SHIFT		= 0x8,
+	PCLK_DBG_B_DIV_MASK		= 0x1f << PCLK_DBG_B_DIV_SHIFT,
+	ATCLK_CORE_B_DIV_SHIFT		= 0,
+	ATCLK_CORE_B_DIV_MASK		= 0x1f << ATCLK_CORE_B_DIV_SHIFT,
+
 	/* CLKSEL_CON14 */
 	PCLK_PERIHP_DIV_CON_SHIFT	= 12,
 	PCLK_PERIHP_DIV_CON_MASK	= 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
@@ -395,25 +418,26 @@
 	return 0;
 }
 
-void rk3399_configure_cpu(struct rk3399_cru *cru,
-			  enum apll_l_frequencies apll_l_freq)
+void rk3399_configure_cpu_l(struct rk3399_cru *cru,
+			    enum apll_l_frequencies apll_l_freq)
 {
 	u32 aclkm_div;
 	u32 pclk_dbg_div;
 	u32 atclk_div;
 
+	/* Setup cluster L */
 	rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
 
-	aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
-	assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
+	aclkm_div = LPLL_HZ / ACLKM_CORE_L_HZ - 1;
+	assert((aclkm_div + 1) * ACLKM_CORE_L_HZ == LPLL_HZ &&
 	       aclkm_div < 0x1f);
 
-	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
-	assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
+	pclk_dbg_div = LPLL_HZ / PCLK_DBG_L_HZ - 1;
+	assert((pclk_dbg_div + 1) * PCLK_DBG_L_HZ == LPLL_HZ &&
 	       pclk_dbg_div < 0x1f);
 
-	atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
-	assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
+	atclk_div = LPLL_HZ / ATCLK_CORE_L_HZ - 1;
+	assert((atclk_div + 1) * ATCLK_CORE_L_HZ == LPLL_HZ &&
 	       atclk_div < 0x1f);
 
 	rk_clrsetreg(&cru->clksel_con[0],
@@ -428,6 +452,42 @@
 		     pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
 		     atclk_div << ATCLK_CORE_L_DIV_SHIFT);
 }
+
+void rk3399_configure_cpu_b(struct rk3399_cru *cru,
+			    enum apll_b_frequencies apll_b_freq)
+{
+	u32 aclkm_div;
+	u32 pclk_dbg_div;
+	u32 atclk_div;
+
+	/* Setup cluster B */
+	rkclk_set_pll(&cru->apll_b_con[0], apll_b_cfgs[apll_b_freq]);
+
+	aclkm_div = BPLL_HZ / ACLKM_CORE_B_HZ - 1;
+	assert((aclkm_div + 1) * ACLKM_CORE_B_HZ == BPLL_HZ &&
+	       aclkm_div < 0x1f);
+
+	pclk_dbg_div = BPLL_HZ / PCLK_DBG_B_HZ - 1;
+	assert((pclk_dbg_div + 1) * PCLK_DBG_B_HZ == BPLL_HZ &&
+	       pclk_dbg_div < 0x1f);
+
+	atclk_div = BPLL_HZ / ATCLK_CORE_B_HZ - 1;
+	assert((atclk_div + 1) * ATCLK_CORE_B_HZ == BPLL_HZ &&
+	       atclk_div < 0x1f);
+
+	rk_clrsetreg(&cru->clksel_con[2],
+		     ACLKM_CORE_B_DIV_CON_MASK | CLK_CORE_B_PLL_SEL_MASK |
+		     CLK_CORE_B_DIV_MASK,
+		     aclkm_div << ACLKM_CORE_B_DIV_CON_SHIFT |
+		     CLK_CORE_B_PLL_SEL_ABPLL << CLK_CORE_B_PLL_SEL_SHIFT |
+		     0 << CLK_CORE_B_DIV_SHIFT);
+
+	rk_clrsetreg(&cru->clksel_con[3],
+		     PCLK_DBG_B_DIV_MASK | ATCLK_CORE_B_DIV_MASK,
+		     pclk_dbg_div << PCLK_DBG_B_DIV_SHIFT |
+		     atclk_div << ATCLK_CORE_B_DIV_SHIFT);
+}
+
 #define I2C_CLK_REG_MASK(bus) \
 			(I2C_DIV_CON_MASK << \
 			CLK_I2C ##bus## _DIV_CON_SHIFT | \
@@ -1026,7 +1086,8 @@
 	u32 hclk_div;
 	u32 pclk_div;
 
-	rk3399_configure_cpu(cru, APLL_L_600_MHZ);
+	rk3399_configure_cpu_l(cru, APLL_L_600_MHZ);
+	rk3399_configure_cpu_b(cru, APLL_B_600_MHZ);
 	/*
 	 * some cru registers changed by bootrom, we'd better reset them to
 	 * reset/default values described in TRM to avoid confusion in kernel.
diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c
index 1f9f534..914e2f4 100644
--- a/drivers/clk/rockchip/clk_rv1108.c
+++ b/drivers/clk/rockchip/clk_rv1108.c
@@ -17,6 +17,8 @@
 #include <dm/lists.h>
 #include <dt-bindings/clock/rv1108-cru.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 enum {
 	VCO_MAX_HZ	= 2400U * 1000000,
 	VCO_MIN_HZ	= 600 * 1000000,
@@ -35,6 +37,9 @@
 			 #hz "Hz cannot be hit with PLL "\
 			 "divisors on line " __stringify(__LINE__));
 
+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);
+
 /* use integer mode */
 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
 {
@@ -57,6 +62,58 @@
 	return id;
 }
 
+static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
+			 const struct pll_div *div)
+{
+	int pll_id = rv1108_pll_id(clk_id);
+	struct rv1108_pll *pll = &cru->pll[pll_id];
+
+	/* All PLLs have same VCO and output frequency range restrictions. */
+	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
+	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
+
+	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
+	      pll, div->fbdiv, div->refdiv, div->postdiv1,
+	      div->postdiv2, vco_hz, output_hz);
+	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
+
+	/*
+	 * When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
+		     WORK_MODE_SLOW << WORK_MODE_SHIFT);
+
+	/* use integer mode */
+	rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
+	/* Power down */
+	rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
+
+	rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
+	rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
+		     (div->postdiv1 << POSTDIV1_SHIFT |
+		     div->postdiv2 << POSTDIV2_SHIFT |
+		     div->refdiv << REFDIV_SHIFT));
+	rk_clrsetreg(&pll->con2, FRACDIV_MASK,
+		     (div->refdiv << REFDIV_SHIFT));
+
+	/* Power Up */
+	rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
+
+	/* waiting for pll lock */
+	while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
+		udelay(1);
+
+	/*
+	 * set PLL into normal mode.
+	 */
+	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
+		     WORK_MODE_NORMAL << WORK_MODE_SHIFT);
+
+	return 0;
+}
+
 static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
 				   enum rk_clk_id clk_id)
 {
@@ -74,7 +131,7 @@
 		fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
 		postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
 		postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
-		refdiv = (con1 & REFDIV_MASK) >> REFDIV_SHIFT;
+		refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
 		freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
 	} else {
 		freq = OSC_HZ;
@@ -154,6 +211,326 @@
 	return rv1108_saradc_get_clk(cru);
 }
 
+static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[28]);
+	div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
+			       CLK_VIO_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[28],
+		     ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
+		     (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_vio1_get_clk(cru);
+}
+
+static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[28]);
+	div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
+			       CLK_VIO_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[28],
+		     ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
+		     (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
+
+	/*HCLK_VIO default div = 4*/
+	rk_clrsetreg(&cru->clksel_con[29],
+		     HCLK_VIO_CLK_DIV_MASK,
+		     3 << HCLK_VIO_CLK_DIV_SHIFT);
+	/*PCLK_VIO default div = 4*/
+	rk_clrsetreg(&cru->clksel_con[29],
+		     PCLK_VIO_CLK_DIV_MASK,
+		     3 << PCLK_VIO_CLK_DIV_SHIFT);
+
+	return rv1108_aclk_vio0_get_clk(cru);
+}
+
+static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[32]);
+	div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
+			       DCLK_VOP_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 64);
+
+	rk_clrsetreg(&cru->clksel_con[32],
+		     DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
+		     DCLK_VOP_SEL_SHIFT,
+		     (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
+		     (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
+		     (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
+
+	return rv1108_dclk_vop_get_clk(cru);
+}
+
+static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[2]);
+	div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
+			       ACLK_BUS_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[2],
+		     ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
+		     (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_bus_get_clk(cru);
+}
+
+static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
+		     (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     HCLK_PERI_DIV_CON_MASK,
+		     (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
+
+	return rv1108_hclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     PCLK_PERI_DIV_CON_MASK,
+		     (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
+
+	return rv1108_pclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
+{
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_I2C0_PMU:
+		con = readl(&cru->clksel_con[19]);
+		div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C1:
+		con = readl(&cru->clksel_con[19]);
+		div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C2:
+		con = readl(&cru->clksel_con[20]);
+		div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C3:
+		con = readl(&cru->clksel_con[20]);
+		div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
+{
+	int src_clk_div;
+
+	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
+	src_clk_div = GPLL_HZ / hz;
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk_id) {
+	case SCLK_I2C0_PMU:
+		rk_clrsetreg(&cru->clksel_con[19],
+			     CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
+			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C1:
+		rk_clrsetreg(&cru->clksel_con[19],
+			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
+			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C2:
+		rk_clrsetreg(&cru->clksel_con[20],
+			     CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
+			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C3:
+		rk_clrsetreg(&cru->clksel_con[20],
+			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
+			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return rv1108_i2c_get_clk(cru, clk_id);
+}
+
+static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, con;
+	ulong mmc_clk;
+
+	con = readl(&cru->clksel_con[26]);
+	div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
+
+	con = readl(&cru->clksel_con[25]);
+
+	if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
+		mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
+	else
+		mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
+
+	debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
+	return mmc_clk;
+}
+
+static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
+{
+	int div;
+	u32 pll_rate;
+
+	div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
+
+	if (div < 127) {
+		debug("%s source gpll\n", __func__);
+		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
+			    (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
+		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+	} else {
+		debug("%s source 24m\n", __func__);
+		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
+			    (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
+		pll_rate = OSC_HZ;
+	}
+
+	div = DIV_ROUND_UP(pll_rate / 2, rate);
+	rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
+		    ((div - 1) << EMMC_CLK_DIV_SHIFT));
+
+	debug("%s set_rate %ld div %d\n", __func__,  rate, div);
+
+	return DIV_TO_RATE(pll_rate, div);
+}
+
 static ulong rv1108_clk_get_rate(struct clk *clk)
 {
 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
@@ -163,6 +540,29 @@
 		return rkclk_pll_get_rate(priv->cru, clk->id);
 	case SCLK_SARADC:
 		return rv1108_saradc_get_clk(priv->cru);
+	case ACLK_VIO0:
+		return rv1108_aclk_vio0_get_clk(priv->cru);
+	case ACLK_VIO1:
+		return rv1108_aclk_vio1_get_clk(priv->cru);
+	case DCLK_VOP:
+		return rv1108_dclk_vop_get_clk(priv->cru);
+	case ACLK_PRE:
+		return rv1108_aclk_bus_get_clk(priv->cru);
+	case ACLK_PERI:
+		return rv1108_aclk_peri_get_clk(priv->cru);
+	case HCLK_PERI:
+		return rv1108_hclk_peri_get_clk(priv->cru);
+	case PCLK_PERI:
+		return rv1108_pclk_peri_get_clk(priv->cru);
+	case SCLK_I2C0_PMU:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		return rv1108_i2c_get_clk(priv->cru, clk->id);
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		return rv1108_mmc_get_clk(priv->cru);
 	default:
 		return -ENOENT;
 	}
@@ -183,6 +583,37 @@
 	case SCLK_SARADC:
 		new_rate = rv1108_saradc_set_clk(priv->cru, rate);
 		break;
+	case ACLK_VIO0:
+		new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
+		break;
+	case ACLK_VIO1:
+		new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
+		break;
+	case DCLK_VOP:
+		new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
+		break;
+	case ACLK_PRE:
+		new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
+		break;
+	case ACLK_PERI:
+		new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
+		break;
+	case HCLK_PERI:
+		new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
+		break;
+	case PCLK_PERI:
+		new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
+		break;
+	case SCLK_I2C0_PMU:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
+		break;
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+		new_rate = rv1108_mmc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -197,14 +628,34 @@
 
 static void rkclk_init(struct rv1108_cru *cru)
 {
-	unsigned int apll = rkclk_pll_get_rate(cru, CLK_ARM);
-	unsigned int dpll = rkclk_pll_get_rate(cru, CLK_DDR);
-	unsigned int gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
+	unsigned int apll, dpll, gpll;
+	unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
+
+	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
+	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
+	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
+	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
+	rv1108_aclk_vio0_set_clk(cru, 297000000);
+	rv1108_aclk_vio1_set_clk(cru, 297000000);
+
+	/* configure apll */
+	rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
+	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
+	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
+	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
+	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
+	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
+
+	apll = rkclk_pll_get_rate(cru, CLK_ARM);
+	dpll = rkclk_pll_get_rate(cru, CLK_DDR);
+	gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
 
 	rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
 		     0 << MAC_CLK_DIV_SHIFT);
 
 	printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
+	printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
+	       aclk_bus, aclk_peri, hclk_peri, pclk_peri);
 }
 
 static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
@@ -228,8 +679,9 @@
 static int rv1108_clk_bind(struct udevice *dev)
 {
 	int ret;
-	struct udevice *sys_child;
+	struct udevice *sys_child, *sf_child;
 	struct sysreset_reg *priv;
+	struct softreset_reg *sf_priv;
 
 	/* The reset driver does not have a device node, so bind it here */
 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
@@ -251,6 +703,17 @@
 	if (ret)
 		debug("Warning: software reset driver bind faile\n");
 #endif
+	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
+					 dev_ofnode(dev), &sf_child);
+	if (ret) {
+		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
+	} else {
+		sf_priv = malloc(sizeof(struct softreset_reg));
+		sf_priv->sf_reset_offset = offsetof(struct rv1108_cru,
+						    softrst_con[0]);
+		sf_priv->sf_reset_num = 13;
+		sf_child->priv = sf_priv;
+	}
 
 	return 0;
 }
@@ -265,8 +728,8 @@
 	.id		= UCLASS_CLK,
 	.of_match	= rv1108_clk_ids,
 	.priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
-	.ofdata_to_platdata = rv1108_clk_ofdata_to_platdata,
 	.ops		= &rv1108_clk_ops,
 	.bind		= rv1108_clk_bind,
+	.ofdata_to_platdata	= rv1108_clk_ofdata_to_platdata,
 	.probe		= rv1108_clk_probe,
 };
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index bcc01b1..6038b43 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -60,6 +60,16 @@
 	  This driver supports reading and writing the RTC/calendar and detects
 	  total power failures.
 
+config RTC_RV3029
+	bool "Enable RV3029 driver"
+	depends on DM_RTC
+	help
+	  The MicroCrystal RV3029 is a I2C Real Time Clock (RTC) with 8-byte
+	  battery-backed SRAM.
+
+	  This driver supports reading and writing the RTC/calendar and the
+	  battery-baced SRAM section.
+
 config RTC_RX8010SJ
 	bool "Enable RX8010SJ driver"
 	depends on DM_RTC
diff --git a/drivers/rtc/rv3029.c b/drivers/rtc/rv3029.c
index dd4d060..38acb9c 100644
--- a/drivers/rtc/rv3029.c
+++ b/drivers/rtc/rv3029.c
@@ -1,189 +1,495 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * (C) Copyright 2010
- * Heiko Schocher, DENX Software Engineering, hs@denx.de
+ * (C) Copyright 2018 Theobroma Systems Design und Consulting GmbH
+ *
+ * Based on a the Linux rtc-rv3029c2.c driver written by:
+ *   Gregory Hermant <gregory.hermant@calao-systems.com>
+ *   Michael Buesch <m@bues.ch>
  */
+
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <i2c.h>
 #include <rtc.h>
 
-#define RTC_RV3029_CTRL1	0x00
-#define RTC_RV3029_CTRL1_EERE	(1 << 3)
-
-#define RTC_RV3029_CTRL_STATUS	0x03
-#define RTC_RV3029_CTRLS_EEBUSY	(1 << 7)
+#define RTC_RV3029_PAGE_LEN             7
 
-#define RTC_RV3029_CTRL_RESET	0x04
-#define RTC_RV3029_CTRL_SYS_R	(1 << 4)
+/* control section */
+#define RV3029_ONOFF_CTRL		0x00
+#define RV3029_ONOFF_CTRL_WE		BIT(0)
+#define RV3029_ONOFF_CTRL_TE		BIT(1)
+#define RV3029_ONOFF_CTRL_TAR		BIT(2)
+#define RV3029_ONOFF_CTRL_EERE		BIT(3)
+#define RV3029_ONOFF_CTRL_SRON		BIT(4)
+#define RV3029_ONOFF_CTRL_TD0		BIT(5)
+#define RV3029_ONOFF_CTRL_TD1		BIT(6)
+#define RV3029_ONOFF_CTRL_CLKINT	BIT(7)
+#define RV3029_IRQ_CTRL			0x01
+#define RV3029_IRQ_CTRL_AIE		BIT(0)
+#define RV3029_IRQ_CTRL_TIE		BIT(1)
+#define RV3029_IRQ_CTRL_V1IE		BIT(2)
+#define RV3029_IRQ_CTRL_V2IE		BIT(3)
+#define RV3029_IRQ_CTRL_SRIE		BIT(4)
+#define RV3029_IRQ_FLAGS		0x02
+#define RV3029_IRQ_FLAGS_AF		BIT(0)
+#define RV3029_IRQ_FLAGS_TF		BIT(1)
+#define RV3029_IRQ_FLAGS_V1IF		BIT(2)
+#define RV3029_IRQ_FLAGS_V2IF		BIT(3)
+#define RV3029_IRQ_FLAGS_SRF		BIT(4)
+#define RV3029_STATUS			0x03
+#define RV3029_STATUS_VLOW1		BIT(2)
+#define RV3029_STATUS_VLOW2		BIT(3)
+#define RV3029_STATUS_SR		BIT(4)
+#define RV3029_STATUS_PON		BIT(5)
+#define RV3029_STATUS_EEBUSY		BIT(7)
+#define RV3029_RST_CTRL			0x04
+#define RV3029_RST_CTRL_SYSR		BIT(4)
+#define RV3029_CONTROL_SECTION_LEN	0x05
 
-#define RTC_RV3029_CLOCK_PAGE	0x08
-#define RTC_RV3029_PAGE_LEN	7
+/* watch section */
+#define RV3029_W_SEC			0x08
+#define RV3029_W_MINUTES		0x09
+#define RV3029_W_HOURS			0x0A
+#define RV3029_REG_HR_12_24		BIT(6) /* 24h/12h mode */
+#define RV3029_REG_HR_PM		BIT(5) /* PM/AM bit in 12h mode */
+#define RV3029_W_DATE			0x0B
+#define RV3029_W_DAYS			0x0C
+#define RV3029_W_MONTHS			0x0D
+#define RV3029_W_YEARS			0x0E
 
-#define RV3029C2_W_SECONDS	0x00
-#define RV3029C2_W_MINUTES	0x01
-#define RV3029C2_W_HOURS	0x02
-#define RV3029C2_W_DATE		0x03
-#define RV3029C2_W_DAYS		0x04
-#define RV3029C2_W_MONTHS	0x05
-#define RV3029C2_W_YEARS	0x06
+/* eeprom control section */
+#define RV3029_CONTROL_E2P_EECTRL	0x30
+#define RV3029_TRICKLE_1K		BIT(4) /* 1.5K resistance */
+#define RV3029_TRICKLE_5K		BIT(5) /* 5K   resistance */
+#define RV3029_TRICKLE_20K		BIT(6) /* 20K  resistance */
+#define RV3029_TRICKLE_80K		BIT(7) /* 80K  resistance */
+#define RV3029_TRICKLE_MASK		(RV3029_TRICKLE_1K |\
+					 RV3029_TRICKLE_5K |\
+					 RV3029_TRICKLE_20K |\
+					 RV3029_TRICKLE_80K)
+#define RV3029_TRICKLE_SHIFT		4
 
-#define RV3029C2_REG_HR_12_24          (1 << 6)  /* 24h/12h mode */
-#define RV3029C2_REG_HR_PM             (1 << 5)  /* PM/AM bit in 12h mode */
 
-#define RTC_RV3029_EEPROM_CTRL	0x30
-#define RTC_RV3029_TRICKLE_1K	(1 << 4)
-#define RTC_RV3029_TRICKLE_5K	(1 << 5)
-#define RTC_RV3029_TRICKLE_20K	(1 << 6)
-#define RTC_RV3029_TRICKLE_80K	(1 << 7)
-
-int rtc_get( struct rtc_time *tmp )
+static int rv3029_rtc_get(struct udevice *dev, struct rtc_time *tm)
 {
-	int	ret;
-	unsigned char buf[RTC_RV3029_PAGE_LEN];
+	u8 regs[RTC_RV3029_PAGE_LEN];
+	int ret;
 
-	ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1, buf, \
-			RTC_RV3029_PAGE_LEN);
-	if (ret) {
+	ret = dm_i2c_read(dev, RV3029_W_SEC, regs, sizeof(regs));
+	if (ret < 0) {
 		printf("%s: error reading RTC: %x\n", __func__, ret);
-		return -1;
+		return -EIO;
+	}
+
+	tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
+	tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);
+
+	/* HR field has a more complex interpretation */
+	{
+		const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC];
+
+		if (_hr & RV3029_REG_HR_12_24) {
+			/* 12h format */
+			tm->tm_hour = bcd2bin(_hr & 0x1f);
+			if (_hr & RV3029_REG_HR_PM)	/* PM flag set */
+				tm->tm_hour += 12;
+		} else {
+			/* 24h format */
+			tm->tm_hour = bcd2bin(_hr & 0x3f);
+		}
 	}
-	tmp->tm_sec  = bcd2bin( buf[RV3029C2_W_SECONDS] & 0x7f);
-	tmp->tm_min  = bcd2bin( buf[RV3029C2_W_MINUTES] & 0x7f);
-	if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_12_24) {
-		/* 12h format */
-		tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x1f);
-		if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_PM)
-			/* PM flag set */
-			tmp->tm_hour += 12;
-	} else
-		tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x3f);
 
-	tmp->tm_mday = bcd2bin( buf[RV3029C2_W_DATE] & 0x3F );
-	tmp->tm_mon  = bcd2bin( buf[RV3029C2_W_MONTHS] & 0x1F );
-	tmp->tm_wday = bcd2bin( buf[RV3029C2_W_DAYS] & 0x07 );
+	tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]);
+	tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1;
 	/* RTC supports only years > 1999 */
-	tmp->tm_year = bcd2bin( buf[RV3029C2_W_YEARS]) + 2000;
-	tmp->tm_yday = 0;
-	tmp->tm_isdst = 0;
+	tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 2000;
+	tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1;
 
-	debug( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
-		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
-		tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
+	tm->tm_yday = 0;
+	tm->tm_isdst = 0;
+
+	debug("%s: %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
+	      __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+	      tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
 
 	return 0;
 }
 
-int rtc_set( struct rtc_time *tmp )
+static int rv3029_rtc_set(struct udevice *dev, const struct rtc_time *tm)
 {
-	int	ret;
-	unsigned char buf[RTC_RV3029_PAGE_LEN];
+	u8 regs[RTC_RV3029_PAGE_LEN];
 
-	debug( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
-		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
-		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+	debug("%s: %4d-%02d-%02d (wday=%d( %2d:%02d:%02d\n",
+	      __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+	      tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
 
-	if (tmp->tm_year < 2000) {
-		printf("RTC: year %d < 2000 not possible\n", tmp->tm_year);
-		return -1;
+
+	if (tm->tm_year < 2000) {
+		printf("%s: year %d (before 2000) not supported\n",
+		       __func__, tm->tm_year);
+		return -EINVAL;
 	}
-	buf[RV3029C2_W_SECONDS] = bin2bcd(tmp->tm_sec);
-	buf[RV3029C2_W_MINUTES] = bin2bcd(tmp->tm_min);
-	buf[RV3029C2_W_HOURS] = bin2bcd(tmp->tm_hour);
-	/* set 24h format */
-	buf[RV3029C2_W_HOURS] &= ~RV3029C2_REG_HR_12_24;
-	buf[RV3029C2_W_DATE] = bin2bcd(tmp->tm_mday);
-	buf[RV3029C2_W_DAYS] = bin2bcd(tmp->tm_wday);
-	buf[RV3029C2_W_MONTHS] = bin2bcd(tmp->tm_mon);
-	tmp->tm_year -= 2000;
-	buf[RV3029C2_W_YEARS] = bin2bcd(tmp->tm_year);
-	ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1,
-			buf, RTC_RV3029_PAGE_LEN);
 
-	/* give the RTC some time to update */
-	udelay(1000);
-	return ret;
+	regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
+	regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
+	regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
+	regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
+	regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
+	regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7;
+	regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 2000);
+
+	return dm_i2c_write(dev, RV3029_W_SEC, regs, sizeof(regs));
 }
 
-/* sets EERE-Bit  (automatic EEPROM refresh) */
-static void set_eere_bit(int state)
+static int rv3029_rtc_reset(struct udevice *dev)
 {
-	unsigned char reg_ctrl1;
+	u8 ctrl = RV3029_RST_CTRL_SYSR;
+	unsigned long start;
+	const unsigned long timeout_ms = 10000;
+	int ret;
+
+	/* trigger the system-reset */
+	ret = dm_i2c_write(dev, RV3029_RST_CTRL, &ctrl, 1);
+	if (ret < 0)
+		return -EIO;
+
+	/* wait for the system-reset to complete */
+	start = get_timer(0);
+	do {
+		if (get_timer(start) > timeout_ms)
+			return -ETIMEDOUT;
+
+		ret = dm_i2c_read(dev, RV3029_RST_CTRL, &ctrl, 1);
+		if (ret < 0)
+			return -EIO;
+	} while (ctrl & RV3029_RST_CTRL_SYSR);
+
+	return 0;
+}
+
+static int rv3029_rtc_read8(struct udevice *dev, unsigned int reg)
+{
+	u8 data;
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, &data, sizeof(data));
+	return ret < 0 ? ret : data;
+}
+
+static int rv3029_rtc_write8(struct udevice *dev, unsigned int reg, int val)
+{
+	u8 data = val;
+
+	return dm_i2c_write(dev, reg, &data, 1);
+}
 
-	(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL1, 1,
-			&reg_ctrl1, 1);
+#if defined(OF_CONTROL)
+static int rv3029_get_sr(struct udevice *dev, u8 *buf)
+{
+	int ret = dm_i2c_read(dev, RV3029_STATUS, buf, 1);
 
-	if (state)
-		reg_ctrl1 |= RTC_RV3029_CTRL1_EERE;
-	else
-		reg_ctrl1 &= (~RTC_RV3029_CTRL1_EERE);
+	if (ret < 0)
+		return -EIO;
 
-	(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL1, 1,
-		&reg_ctrl1, 1);
+	dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
+	return 0;
 }
 
-/* waits until EEPROM page is no longer busy (times out after 10ms*loops) */
-static int wait_eebusy(int loops)
+static int rv3029_set_sr(struct udevice *dev, u8 val)
 {
-	int i;
-	unsigned char ctrl_status;
+	int ret;
 
-	for (i = 0; i < loops; i++) {
-		(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL_STATUS,
-			1, &ctrl_status, 1);
+	ret = dm_i2c_read(dev, RV3029_STATUS, &val, 1);
+	if (ret < 0)
+		return -EIO;
+
+	dev_dbg(dev, "status = 0x%.2x (%d)\n", val, val);
+	return 0;
+}
+
+static int rv3029_eeprom_busywait(struct udevice *dev)
+{
+	int i, ret;
+	u8 sr;
 
-		if ((ctrl_status & RTC_RV3029_CTRLS_EEBUSY) == 0)
+	for (i = 100; i > 0; i--) {
+		ret = rv3029_get_sr(dev, &sr);
+		if (ret < 0)
+			break;
+		if (!(sr & RV3029_STATUS_EEBUSY))
 			break;
 		udelay(10000);
 	}
-	return i;
+	if (i <= 0) {
+		dev_err(dev, "EEPROM busy wait timeout.\n");
+		return -ETIMEDOUT;
+	}
+
+	return ret;
 }
 
-void rtc_reset (void)
+static int rv3029_update_bits(struct udevice *dev, u8 reg, u8 mask, u8 set)
 {
-	unsigned char buf[RTC_RV3029_PAGE_LEN];
+	u8 buf;
+	int ret;
 
-	buf[0] = RTC_RV3029_CTRL_SYS_R;
-	(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL_RESET, 1,
-			buf, 1);
+	ret = dm_i2c_read(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
 
-#if defined(CONFIG_SYS_RV3029_TCR)
-	/*
-	 * because EEPROM_CTRL register is in EEPROM page it is necessary to
-	 * disable automatic EEPROM refresh and check if EEPROM is busy
-	 * before EEPORM_CTRL register may be accessed
-	 */
-	set_eere_bit(0);
-	wait_eebusy(100);
-	/* read current trickle charger setting */
-	(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_EEPROM_CTRL,
-			1, buf, 1);
-	/* enable automatic EEPROM refresh again */
-	set_eere_bit(1);
+	if ((buf & mask) == (set && mask))
+		return 0;
 
-	/*
-	 * to minimize EEPROM access write trickle charger setting only if it
-	 * differs from current value
-	 */
-	if ((buf[0] & 0xF0) != CONFIG_SYS_RV3029_TCR) {
-		buf[0] = (buf[0] & 0x0F) | CONFIG_SYS_RV3029_TCR;
-		/*
-		 * write trickle charger setting (disable autom. EEPROM
-		 * refresh and wait until EEPROM is idle)
-		 */
-		set_eere_bit(0);
-		wait_eebusy(100);
-		(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR,
-				RTC_RV3029_EEPROM_CTRL, 1, buf, 1);
-		/*
-		 * it is necessary to wait 10ms before EEBUSY-Bit may be read
-		 * (this is not documented in the data sheet yet, but the
-		 * manufacturer recommends it)
+	buf = (buf & ~mask) | (set & mask);
+	ret = dm_i2c_read(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rv3029_eeprom_exit(struct udevice *dev)
+{
+	/* Re-enable eeprom refresh */
+	return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
+				  RV3029_ONOFF_CTRL_EERE,
+				  RV3029_ONOFF_CTRL_EERE);
+}
+
+static int rv3029_eeprom_enter(struct udevice *dev)
+{
+	int ret;
+	u8 sr;
+
+	/* Check whether we are in the allowed voltage range. */
+	ret = rv3029_get_sr(dev, &sr);
+	if (ret < 0)
+		return ret;
+	if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+		/* We clear the bits and retry once just in case
+		 * we had a brown out in early startup.
 		 */
+		sr &= ~RV3029_STATUS_VLOW1;
+		sr &= ~RV3029_STATUS_VLOW2;
+		ret = rv3029_set_sr(dev, sr);
+		if (ret < 0)
+			return ret;
 		udelay(10000);
-		/* wait until EEPROM write access is finished */
-		wait_eebusy(100);
-		set_eere_bit(1);
+		ret = rv3029_get_sr(dev, &sr);
+		if (ret < 0)
+			return ret;
+		if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+			dev_err(dev, "Supply voltage is too low to safely access the EEPROM.\n");
+			return -ENODEV;
+		}
 	}
+
+	/* Disable eeprom refresh. */
+	ret = rv3029_update_bits(dev,
+				 RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for any previous eeprom accesses to finish. */
+	ret = rv3029_eeprom_busywait(dev);
+	if (ret < 0)
+		rv3029_eeprom_exit(dev);
+
+	return ret;
+}
+
+static int rv3029_eeprom_read(struct udevice *dev, u8 reg,
+			      u8 buf[], size_t len)
+{
+	int ret, err;
+
+	err = rv3029_eeprom_enter(dev);
+	if (err < 0)
+		return err;
+
+	ret = dm_i2c_read(dev, reg, buf, len);
+
+	err = rv3029_eeprom_exit(dev);
+	if (err < 0)
+		return err;
+
+	return ret;
+}
+
+static int rv3029_eeprom_write(struct udevice *dev, u8 reg,
+			       u8 const buf[], size_t len)
+{
+	int ret;
+	size_t i;
+	u8 tmp;
+
+	ret = rv3029_eeprom_enter(dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < len; i++, reg++) {
+		ret = dm_i2c_read(dev, reg, &tmp, 1);
+		if (ret < 0)
+			break;
+		if (tmp != buf[i]) {
+			ret = dm_i2c_write(dev, reg, &buf[i], 1);
+			if (ret < 0)
+				break;
+		}
+		ret = rv3029_eeprom_busywait(dev);
+		if (ret < 0)
+			break;
+	}
+
+	ret = rv3029_eeprom_exit(dev);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rv3029_eeprom_update_bits(struct udevice *dev,
+				     u8 reg, u8 mask, u8 set)
+{
+	u8 buf;
+	int ret;
+
+	ret = rv3029_eeprom_read(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * If the EEPROM already reads the correct bitpattern, we don't need
+	 * to update it.
+	 */
+	if ((buf & mask) == (set & mask))
+		return 0;
+
+	buf = (buf & ~mask) | (set & mask);
+	ret = rv3029_eeprom_write(dev, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void rv3029_trickle_config(struct udevice *dev)
+{
+	static const struct rv3029_trickle_tab_elem {
+		u32 r;		/* resistance in ohms */
+		u8 conf;	/* trickle config bits */
+	} rv3029_trickle_tab[] = {
+		{
+			.r	= 1076,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+				  RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+		}, {
+			.r	= 1091,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+				  RV3029_TRICKLE_20K,
+		}, {
+			.r	= 1137,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+				  RV3029_TRICKLE_80K,
+		}, {
+			.r	= 1154,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
+		}, {
+			.r	= 1371,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
+				  RV3029_TRICKLE_80K,
+		}, {
+			.r	= 1395,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
+		}, {
+			.r	= 1472,
+			.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
+		}, {
+			.r	= 1500,
+			.conf	= RV3029_TRICKLE_1K,
+		}, {
+			.r	= 3810,
+			.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
+				  RV3029_TRICKLE_80K,
+		}, {
+			.r	= 4000,
+			.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
+		}, {
+			.r	= 4706,
+			.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
+		}, {
+			.r	= 5000,
+			.conf	= RV3029_TRICKLE_5K,
+		}, {
+			.r	= 16000,
+			.conf	= RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+		}, {
+			.r	= 20000,
+			.conf	= RV3029_TRICKLE_20K,
+		}, {
+			.r	= 80000,
+			.conf	= RV3029_TRICKLE_80K,
+		},
+	};
+	int err;
+	u32 ohms;
+	u8 trickle_set_bits = 0;
+
+	/* Configure the trickle charger. */
+	err = dev_read_u32(dev, "trickle-resistor-ohms", &ohms);
+
+	if (!err) {
+		/* Find trickle-charger config */
+		for (int i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++)
+			if (rv3029_trickle_tab[i].r >= ohms) {
+				dev_dbg(dev, "trickle charger at %d ohms\n",
+					rv3029_trickle_tab[i].r);
+				trickle_set_bits = rv3029_trickle_tab[i].conf;
+				break;
+			}
+	}
+
+	dev_dbg(dev, "trickle charger config 0x%x\n", trickle_set_bits);
+	err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
+					RV3029_TRICKLE_MASK,
+					trickle_set_bits);
+	if (err < 0)
+		dev_dbg(dev, "failed to update trickle charger\n");
+}
+#else
+static inline void rv3029_trickle_config(struct udevice *dev)
+{
+}
 #endif
+
+static int rv3029_probe(struct udevice *dev)
+{
+	i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
+				DM_I2C_CHIP_WR_ADDRESS);
+
+	rv3029_trickle_config(dev);
+	return 0;
 }
+
+static const struct rtc_ops rv3029_rtc_ops = {
+	.get = rv3029_rtc_get,
+	.set = rv3029_rtc_set,
+	.read8 = rv3029_rtc_read8,
+	.write8 = rv3029_rtc_write8,
+	.reset = rv3029_rtc_reset,
+};
+
+static const struct udevice_id rv3029_rtc_ids[] = {
+	{ .compatible = "mc,rv3029" },
+	{ .compatible = "mc,rv3029c2" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_rv3029) = {
+	.name	= "rtc-rv3029",
+	.id	= UCLASS_RTC,
+	.probe	= rv3029_probe,
+	.of_match = rv3029_rtc_ids,
+	.ops	= &rv3029_rtc_ops,
+};
diff --git a/drivers/video/rockchip/rk_mipi.c b/drivers/video/rockchip/rk_mipi.c
index 4fe8f47..4f1a0f3 100644
--- a/drivers/video/rockchip/rk_mipi.c
+++ b/drivers/video/rockchip/rk_mipi.c
@@ -106,7 +106,7 @@
 	rk_mipi_dsi_write(regs, VSYNC_ACTIVE_LOW, val);
 
 	val = (timing->flags & DISPLAY_FLAGS_DE_LOW) ? 1 : 0;
-	rk_mipi_dsi_write(regs, DISPLAY_FLAGS_DE_LOW, val);
+	rk_mipi_dsi_write(regs, DATAEN_ACTIVE_LOW, val);
 
 	val = (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) ? 1 : 0;
 	rk_mipi_dsi_write(regs, COLORM_ACTIVE_LOW, val);
@@ -241,7 +241,7 @@
 
 	/* select the suitable value for fsfreqrang reg */
 	for (i = 0; i < ARRAY_SIZE(freq_rang); i++) {
-		if (ddr_clk / (MHz) >= freq_rang[i][0])
+		if (ddr_clk / (MHz) <= freq_rang[i][0])
 			break;
 	}
 	if (i == ARRAY_SIZE(freq_rang)) {
diff --git a/include/configs/evb_rv1108.h b/include/configs/evb_rv1108.h
index 34739c7..b742d98 100644
--- a/include/configs/evb_rv1108.h
+++ b/include/configs/evb_rv1108.h
@@ -11,11 +11,14 @@
 /*
  * Default environment settings
  */
+#undef CONFIG_EXTRA_ENV_SETTINGS
 #define CONFIG_EXTRA_ENV_SETTINGS                                       \
 	"netdev=eth0\0"                                                 \
 	"ipaddr=172.16.12.50\0"                                         \
 	"serverip=172.16.12.69\0"					\
 	""
+
+#undef CONFIG_BOOTCOMMAND
 #define CONFIG_BOOTCOMMAND						\
 	"sf probe;"							\
 	"sf read 0x62000000 0x140800 0x500000;"				\
diff --git a/include/configs/rv1108_common.h b/include/configs/rv1108_common.h
index 2ab3b85..16d4e2e 100644
--- a/include/configs/rv1108_common.h
+++ b/include/configs/rv1108_common.h
@@ -17,6 +17,9 @@
 #define CONFIG_SYS_TIMER_BASE		0x10350020
 #define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
 
+/* MMC/SD IP block */
+#define CONFIG_BOUNCE_BUFFER
+
 #define CONFIG_SYS_SDRAM_BASE		0x60000000
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + 0x100000)
 #define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x2000000)
@@ -25,3 +28,18 @@
 #define CONFIG_USB_OHCI_NEW
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	1
 #endif
+
+#ifndef CONFIG_SPL_BUILD
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x60000000\0" \
+	"fdt_addr_r=0x61f00000\0" \
+	"kernel_addr_r=0x62000000\0" \
+	"ramdisk_addr_r=0x64000000\0"
+
+#include <config_distro_bootcmd.h>
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
+	"partitions=" PARTS_DEFAULT \
+	BOOTENV
+#endif
diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h
index 9219a50..10ed9d1 100644
--- a/include/dt-bindings/clock/rv1108-cru.h
+++ b/include/dt-bindings/clock/rv1108-cru.h
@@ -14,7 +14,6 @@
 #define ARMCLK				3
 
 /* sclk gates (special clocks) */
-#define SCLK_MAC			64
 #define SCLK_SPI0			65
 #define SCLK_NANDC			67
 #define SCLK_SDMMC			68
@@ -35,20 +34,77 @@
 #define SCLK_SDMMC_SAMPLE		84
 #define SCLK_SDIO_SAMPLE		85
 #define SCLK_EMMC_SAMPLE		86
-#define SCLK_MAC_RX			87
-#define SCLK_MAC_TX			88
-#define SCLK_MACREF			89
-#define SCLK_MACREF_OUT			90
-#define SCLK_SARADC			91
+#define SCLK_VENC_CORE			87
+#define SCLK_HEVC_CORE			88
+#define SCLK_HEVC_CABAC			89
+#define SCLK_PWM0_PMU			90
+#define SCLK_I2C0_PMU			91
+#define SCLK_WIFI			92
+#define SCLK_CIFOUT			93
+#define SCLK_MIPI_CSI_OUT		94
+#define SCLK_CIF0			95
+#define SCLK_CIF1			96
+#define SCLK_CIF2			97
+#define SCLK_CIF3			98
+#define SCLK_DSP			99
+#define SCLK_DSP_IOP			100
+#define SCLK_DSP_EPP			101
+#define SCLK_DSP_EDP			102
+#define SCLK_DSP_EDAP			103
+#define SCLK_CVBS_HOST			104
+#define SCLK_HDMI_SFR			105
+#define SCLK_HDMI_CEC			106
+#define SCLK_CRYPTO			107
+#define SCLK_SPI			108
+#define SCLK_SARADC			109
+#define SCLK_TSADC			110
+#define SCLK_MAC_PRE			111
+#define SCLK_MAC			112
+#define SCLK_MAC_RX			113
+#define SCLK_MAC_REF			114
+#define SCLK_MAC_REFOUT			115
+#define SCLK_DSP_PFM			116
+#define SCLK_RGA			117
+#define SCLK_I2C1			118
+#define SCLK_I2C2			119
+#define SCLK_I2C3			120
+#define SCLK_PWM			121
+#define SCLK_ISP			122
+#define SCLK_USBPHY			123
+#define SCLK_I2S0_SRC			124
+#define SCLK_I2S1_SRC			125
+#define SCLK_I2S2_SRC			126
+#define SCLK_UART0_SRC			127
+#define SCLK_UART1_SRC			128
+#define SCLK_UART2_SRC			129
+#define SCLK_MAC_TX			130
+#define SCLK_MACREF			131
+#define SCLK_MACREF_OUT			132
 
+#define DCLK_VOP_SRC			185
+#define DCLK_HDMIPHY			186
+#define DCLK_VOP			187
 
 /* aclk gates */
 #define ACLK_DMAC			192
 #define ACLK_PRE			193
 #define ACLK_CORE			194
 #define ACLK_ENMCORE			195
-#define ACLK_GMAC			196
-
+#define ACLK_RKVENC			196
+#define ACLK_RKVDEC			197
+#define ACLK_VPU			198
+#define ACLK_CIF0			199
+#define ACLK_VIO0			200
+#define ACLK_VIO1			201
+#define ACLK_VOP			202
+#define ACLK_IEP			203
+#define ACLK_RGA			204
+#define ACLK_ISP			205
+#define ACLK_CIF1			206
+#define ACLK_CIF2			207
+#define ACLK_CIF3			208
+#define ACLK_PERI			209
+#define ACLK_GMAC			210
 
 /* pclk gates */
 #define PCLK_GPIO1			256
@@ -67,12 +123,24 @@
 #define PCLK_PWM			269
 #define PCLK_TIMER			270
 #define PCLK_PERI			271
-#define PCLK_GMAC			272
-#define PCLK_SARADC			273
+#define PCLK_GPIO0_PMU			272
+#define PCLK_I2C0_PMU			273
+#define PCLK_PWM0_PMU			274
+#define PCLK_ISP			275
+#define PCLK_VIO			276
+#define PCLK_MIPI_DSI			277
+#define PCLK_HDMI_CTRL			278
+#define PCLK_SARADC			279
+#define PCLK_DSP_CFG			280
+#define PCLK_BUS			281
+#define PCLK_EFUSE0			282
+#define PCLK_EFUSE1			283
+#define PCLK_WDT			284
+#define PCLK_GMAC			285
 
 /* hclk gates */
 #define HCLK_I2S0_8CH			320
-#define HCLK_I2S1_8CH			321
+#define HCLK_I2S1_2CH			321
 #define HCLK_I2S2_2CH			322
 #define HCLK_NANDC			323
 #define HCLK_SDMMC			324
@@ -80,20 +148,37 @@
 #define HCLK_EMMC			326
 #define HCLK_PERI			327
 #define HCLK_SFC			328
+#define HCLK_RKVENC			329
+#define HCLK_RKVDEC			330
+#define HCLK_CIF0			331
+#define HCLK_VIO			332
+#define HCLK_VOP			333
+#define HCLK_IEP			334
+#define HCLK_RGA			335
+#define HCLK_ISP			336
+#define HCLK_CRYPTO_MST			337
+#define HCLK_CRYPTO_SLV			338
+#define HCLK_HOST0			339
+#define HCLK_OTG			340
+#define HCLK_CIF1			341
+#define HCLK_CIF2			342
+#define HCLK_CIF3			343
+#define HCLK_BUS			344
+#define HCLK_VPU			345
 
-#define CLK_NR_CLKS			(HCLK_SFC + 1)
+#define CLK_NR_CLKS			(HCLK_VPU + 1)
 
 /* reset id */
-#define SRST_CORE_PO_AD		0
+#define SRST_CORE_PO_AD			0
 #define SRST_CORE_AD			1
 #define SRST_L2_AD			2
-#define SRST_CPU_NIU_AD		3
+#define SRST_CPU_NIU_AD			3
 #define SRST_CORE_PO			4
 #define SRST_CORE			5
-#define SRST_L2			6
+#define SRST_L2				6
 #define SRST_CORE_DBG			8
 #define PRST_DBG			9
-#define RST_DAP			10
+#define RST_DAP				10
 #define PRST_DBG_NIU			11
 #define ARST_STRC_SYS_AD		15
 
@@ -160,9 +245,9 @@
 #define HRST_SYSBUS			75
 #define PRST_USBGRF			76
 
-#define ARST_PERIPH_NIU		80
-#define HRST_PERIPH_NIU		81
-#define PRST_PERIPH_NIU		82
+#define ARST_PERIPH_NIU			80
+#define HRST_PERIPH_NIU			81
+#define PRST_PERIPH_NIU			82
 #define HRST_PERIPH			83
 #define HRST_SDMMC			84
 #define HRST_SDIO			85
@@ -180,7 +265,7 @@
 #define HRST_HOST0_AUX			96
 #define HRST_HOST0_ARB			97
 #define SRST_HOST0_EHCIPHY		98
-#define SRST_HOST0_UTMI		99
+#define SRST_HOST0_UTMI			99
 #define SRST_USBPOR			100
 #define SRST_UTMI0			101
 #define SRST_UTMI1			102
@@ -227,21 +312,21 @@
 #define HRST_VPU_NIU			141
 #define ARST_VPU			142
 #define HRST_VPU			143
-#define ARST_RKVDEC_NIU		144
-#define HRST_RKVDEC_NIU		145
+#define ARST_RKVDEC_NIU			144
+#define HRST_RKVDEC_NIU			145
 #define ARST_RKVDEC			146
 #define HRST_RKVDEC			147
 #define SRST_RKVDEC_CABAC		148
 #define SRST_RKVDEC_CORE		149
-#define ARST_RKVENC_NIU		150
-#define HRST_RKVENC_NIU		151
+#define ARST_RKVENC_NIU			150
+#define HRST_RKVENC_NIU			151
 #define ARST_RKVENC			152
 #define HRST_RKVENC			153
 #define SRST_RKVENC_CORE		154
 
 #define SRST_DSP_CORE			156
 #define SRST_DSP_SYS			157
-#define SRST_DSP_GLOBAL		158
+#define SRST_DSP_GLOBAL			158
 #define SRST_DSP_OECM			159
 #define PRST_DSP_IOP_NIU		160
 #define ARST_DSP_EPP_NIU		161
@@ -259,7 +344,7 @@
 #define SRST_PMU_I2C0			173
 #define PRST_PMU_I2C0			174
 #define PRST_PMU_GPIO0			175
-#define PRST_PMU_INTMEM		176
+#define PRST_PMU_INTMEM			176
 #define PRST_PMU_PWM0			177
 #define SRST_PMU_PWM0			178
 #define PRST_PMU_GRF			179
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 69bef5e..b3f525f 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -4054,7 +4054,6 @@
 CONFIG_SYS_RTC_OSCILLATOR
 CONFIG_SYS_RTC_REG_BASE_ADDR
 CONFIG_SYS_RTC_SETUP
-CONFIG_SYS_RV3029_TCR
 CONFIG_SYS_RX_ETH_BUFFER
 CONFIG_SYS_SATA
 CONFIG_SYS_SATA1