Merge git://git.denx.de/u-boot-rockchip

This adds a new firefly-rk3399 board, MIPI support for rk3399 and
rk3288, rk818 pmic support, mkimage improvements for rockchip and a few
other things.
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 5ccd63d..a985c5d 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -42,6 +42,7 @@
 	rk3288-veyron-minnie.dtb \
 	rk3328-evb.dtb \
 	rk3399-evb.dtb \
+	rk3399-firefly.dtb \
 	rk3399-puma.dtb
 dtb-$(CONFIG_ARCH_MESON) += \
 	meson-gxbb-odroidc2.dtb
diff --git a/arch/arm/dts/rk3288-evb.dtsi b/arch/arm/dts/rk3288-evb.dtsi
index 4960f33..a84156f 100644
--- a/arch/arm/dts/rk3288-evb.dtsi
+++ b/arch/arm/dts/rk3288-evb.dtsi
@@ -85,6 +85,59 @@
 		regulator-always-on;
 		vin-supply = <&vcc_5v>;
 	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		power-supply = <&vcc_sys>;
+		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <50>;
+		pwms = <&pwm0 0 25000 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		pwm-delay-us = <10000>;
+		status = "disabled";
+	};
+
+	panel: panel {
+		compatible = "simple-panel";
+		power-supply = <&vcc_io>;
+		backlight = <&backlight>;
+		enable-gpios = <&gpio7 3 GPIO_ACTIVE_HIGH>;
+		status = "disabled";
+	};
 };
 
 &cpu0 {
@@ -318,6 +371,10 @@
 	};
 };
 
+&pwm0 {
+	status = "okay";
+};
+
 &saradc {
 	vref-supply = <&vcc_18>;
 	status = "okay";
@@ -396,6 +453,29 @@
 	status = "okay";
 };
 
+&mipi_dsi0 {
+	status = "disabled";
+	rockchip,panel = <&panel>;
+	display-timings {
+		timing0 {
+		bits-per-pixel = <24>;
+		clock-frequency = <160000000>;
+		hfront-porch = <120>;
+		hsync-len = <20>;
+		hback-porch = <21>;
+		hactive = <1200>;
+		vfront-porch = <21>;
+		vsync-len = <3>;
+		vback-porch = <18>;
+		vactive = <1920>;
+		hsync-active = <0>;
+		vsync-active = <0>;
+		de-active = <1>;
+		pixelclk-active = <0>;
+		};
+	};
+};
+
 &wdt {
 	status = "okay";
 };
diff --git a/arch/arm/dts/rk3288-tinker.dts b/arch/arm/dts/rk3288-tinker.dts
index 22881cb..ea2f715 100644
--- a/arch/arm/dts/rk3288-tinker.dts
+++ b/arch/arm/dts/rk3288-tinker.dts
@@ -67,3 +67,10 @@
 &gpio8 {
 	u-boot,dm-pre-reloc;
 };
+
+&i2c2 {
+    m24c08@50 {
+        compatible = "at,24c08", "i2c-eeprom";
+        reg = <0x50>;
+    };
+};
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index bcf051a..64aa07d 100644
--- a/arch/arm/dts/rk3288.dtsi
+++ b/arch/arm/dts/rk3288.dtsi
@@ -664,6 +664,7 @@
 	};
 
 	vopb: vop@ff930000 {
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3288-vop";
 		reg = <0xff930000 0x19c>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
@@ -689,6 +690,11 @@
 				reg = <2>;
 				remote-endpoint = <&lvds_in_vopb>;
 			};
+			vopb_out_mipi: endpoint@3 {
+				reg = <3>;
+				remote-endpoint = <&mipi_in_vopb>;
+			};
+
 		};
 	};
 
@@ -729,6 +735,11 @@
 				reg = <2>;
 				remote-endpoint = <&lvds_in_vopl>;
 			};
+			vopl_out_mipi: endpoint@3 {
+				reg = <3>;
+				remote-endpoint = <&mipi_in_vopl>;
+			};
+
 		};
 	};
 
@@ -823,6 +834,36 @@
 		};
 	};
 
+	mipi_dsi0: mipi@ff960000 {
+		compatible = "rockchip,rk3288_mipi_dsi";
+		reg = <0xff960000 0x4000>;
+		clocks = <&cru PCLK_MIPI_DSI0>;
+		clock-names = "pclk_mipi";
+		/*pinctrl-names = "default";
+		pinctrl-0 = <&lcdc0_ctl>;*/
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			mipi_in: port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				mipi_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_mipi>;
+				};
+				mipi_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_mipi>;
+				};
+			};
+		};
+	};
+
 	hdmi_audio: hdmi_audio {
 		compatible = "rockchip,rk3288-hdmi-audio";
 		i2s-controller = <&i2s>;
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
index e1f867b..f5af75b 100644
--- a/arch/arm/dts/rk3399-evb.dts
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -6,6 +6,7 @@
 
 /dts-v1/;
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/pinctrl/rockchip.h>
 #include "rk3399.dtsi"
 #include "rk3399-sdram-lpddr3-4GB-1600.dtsi"
 
@@ -20,7 +21,7 @@
 
 	vdd_center: vdd-center {
 		compatible = "pwm-regulator";
-		pwms = <&pwm3 0 25000 0>;
+		pwms = <&pwm3 0 25000 1>;
 		regulator-name = "vdd_center";
 		regulator-min-microvolt = <800000>;
 		regulator-max-microvolt = <1400000>;
@@ -59,6 +60,65 @@
 		gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>;
 	};
 
+	clkin_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "clkin_gmac";
+		#clock-cells = <0>;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		power-supply = <&vccsys>;
+		enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <200>;
+		pwms = <&pwm0 0 25000 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		pwm-delay-us = <10000>;
+		status = "disabled";
+	};
+
+	panel:panel {
+		compatible = "simple-panel";
+		power-supply = <&vcc33_lcd>;
+		backlight = <&backlight>;
+		/*enable-gpios = <&gpio4 18 GPIO_ACTIVE_HIGH>;*/
+		status = "disabled";
+	};
 };
 
 &emmc_phy {
@@ -141,6 +201,7 @@
 		status = "okay";
 
 		vcc12-supply = <&vcc3v3_sys>;
+
 		regulators {
 			vcc33_lcd: SWITCH_REG2 {
 				regulator-always-on;
@@ -151,6 +212,29 @@
 	};
 };
 
+&mipi_dsi {
+	status = "disabled";
+	rockchip,panel = <&panel>;
+	display-timings {
+		timing0 {
+		bits-per-pixel = <24>;
+		clock-frequency = <160000000>;
+		hfront-porch = <120>;
+		hsync-len = <20>;
+		hback-porch = <21>;
+		hactive = <1200>;
+		vfront-porch = <21>;
+		vsync-len = <3>;
+		vback-porch = <18>;
+		vactive = <1920>;
+		hsync-active = <0>;
+		vsync-active = <0>;
+		de-active = <1>;
+		pixelclk-active = <0>;
+		};
+	};
+};
+
 &pinctrl {
 	pmic {
 		pmic_int_l: pmic-int-l {
@@ -164,3 +248,35 @@
 		};
 	};
 };
+
+&gmac {
+        phy-supply = <&vcc_phy>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+	assigned-clocks = <&cru SCLK_RMII_SRC>;
+	assigned-clock-parents = <&clkin_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x10>;
+	rx_delay = <0x10>;
+	status = "okay";
+};
+
+&gmac {
+        phy-supply = <&vcc_phy>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+	assigned-clocks = <&cru SCLK_RMII_SRC>;
+	assigned-clock-parents = <&clkin_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x10>;
+	rx_delay = <0x10>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-firefly.dts b/arch/arm/dts/rk3399-firefly.dts
new file mode 100644
index 0000000..edf48fb
--- /dev/null
+++ b/arch/arm/dts/rk3399-firefly.dts
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/dts-v1/;
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3399.dtsi"
+#include "rk3399-sdram-ddr3-1333.dtsi"
+
+/ {
+	model = "Firefly-RK3399 Board";
+	compatible = "firefly,firefly-rk3399", "rockchip,rk3399";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm0 0 25000 0>;
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <200>;
+	};
+
+	clkin_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "clkin_gmac";
+		#clock-cells = <0>;
+	};
+
+	rt5640-sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "rockchip,rt5640-codec";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,mclk-fs = <256>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Mic Jack", "MICBIAS1",
+			"IN1P", "Mic Jack",
+			"Headphone Jack", "HPOL",
+			"Headphone Jack", "HPOR";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s1>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&rt5640>;
+		};
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&rk808 1>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_enable_h>;
+
+		/*
+		 * On the module itself this is one of these (depending
+		 * on the actual card populated):
+		 * - SDIO_RESET_L_WL_REG_ON
+		 * - PDN (power down when low)
+		 */
+		reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc3v3_pcie: vcc3v3-pcie-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pcie_drv>;
+		regulator-name = "vcc3v3_pcie";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vcc3v3_sys: vcc3v3-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc5v0_host: vcc5v0-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc5v0_host";
+		regulator-always-on;
+	};
+
+	vcc5v0_sys: vcc5v0-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc5v0_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vcc_phy: vcc-phy-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_phy";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_log: vdd-log {
+		compatible = "pwm-regulator";
+		pwms = <&pwm2 0 25000 1>;
+		regulator-name = "vdd_log";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1400000>;
+	};
+
+	vccadc_ref: vccadc-ref {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc1v8_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+};
+
+&cpu_l0 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+	cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+	cpu-supply = <&vdd_cpu_b>;
+};
+
+&emmc_phy {
+	status = "okay";
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_RMII_SRC>;
+	assigned-clock-parents = <&clkin_gmac>;
+	clock_in_out = "input";
+	phy-supply = <&vcc_phy>;
+	phy-mode = "rgmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+	tx_delay = <0x28>;
+	rx_delay = <0x11>;
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <400000>;
+	i2c-scl-rising-time-ns = <168>;
+	i2c-scl-falling-time-ns = <4>;
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int_l>;
+		rockchip,system-power-controller;
+		wakeup-source;
+
+		vcc1-supply = <&vcc3v3_sys>;
+		vcc2-supply = <&vcc3v3_sys>;
+		vcc3-supply = <&vcc3v3_sys>;
+		vcc4-supply = <&vcc3v3_sys>;
+		vcc6-supply = <&vcc3v3_sys>;
+		vcc7-supply = <&vcc3v3_sys>;
+		vcc8-supply = <&vcc3v3_sys>;
+		vcc9-supply = <&vcc3v3_sys>;
+		vcc10-supply = <&vcc3v3_sys>;
+		vcc11-supply = <&vcc3v3_sys>;
+		vcc12-supply = <&vcc3v3_sys>;
+		vddio-supply = <&vcc1v8_pmu>;
+
+		regulators {
+			vdd_center: DCDC_REG1 {
+				regulator-name = "vdd_center";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_cpu_l: DCDC_REG2 {
+				regulator-name = "vdd_cpu_l";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-name = "vcc_ddr";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_1v8: DCDC_REG4 {
+				regulator-name = "vcc_1v8";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc1v8_dvp: LDO_REG1 {
+				regulator-name = "vcc1v8_dvp";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc3v0_tp: LDO_REG2 {
+				regulator-name = "vcc3v0_tp";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc1v8_pmu: LDO_REG3 {
+				regulator-name = "vcc1v8_pmu";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc_sd: LDO_REG4 {
+				regulator-name = "vcc_sd";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcca3v0_codec: LDO_REG5 {
+				regulator-name = "vcca3v0_codec";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_1v5: LDO_REG6 {
+				regulator-name = "vcc_1v5";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1500000>;
+				};
+			};
+
+			vcca1v8_codec: LDO_REG7 {
+				regulator-name = "vcca1v8_codec";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_3v0: LDO_REG8 {
+				regulator-name = "vcc_3v0";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3000000>;
+				};
+			};
+
+			vcc3v3_s3: SWITCH_REG1 {
+				regulator-name = "vcc3v3_s3";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc3v3_s0: SWITCH_REG2 {
+				regulator-name = "vcc3v3_s0";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+		};
+	};
+
+	vdd_cpu_b: regulator@40 {
+		compatible = "silergy,syr827";
+		reg = <0x40>;
+		fcs,suspend-voltage-selector = <0>;
+		regulator-name = "vdd_cpu_b";
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <1000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc5v0_sys>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+
+	vdd_gpu: regulator@41 {
+		compatible = "silergy,syr828";
+		reg = <0x41>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-name = "vdd_gpu";
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <1000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc5v0_sys>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+};
+
+&i2c1 {
+	i2c-scl-rising-time-ns = <300>;
+	i2c-scl-falling-time-ns = <15>;
+	status = "okay";
+
+	rt5640: rt5640@1c {
+		compatible = "realtek,rt5640";
+		reg = <0x1c>;
+		clocks = <&cru SCLK_I2S_8CH_OUT>;
+		clock-names = "mclk";
+		realtek,in1-differential;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&rt5640_hpcon>;
+	};
+};
+
+&i2c3 {
+	i2c-scl-rising-time-ns = <450>;
+	i2c-scl-falling-time-ns = <15>;
+	status = "okay";
+};
+
+&i2c4 {
+	i2c-scl-rising-time-ns = <600>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+
+	accelerometer@68 {
+		compatible = "invensense,mpu6500";
+		reg = <0x68>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <RK_PC6 IRQ_TYPE_EDGE_RISING>;
+	};
+};
+
+&i2s0 {
+	rockchip,playback-channels = <8>;
+	rockchip,capture-channels = <8>;
+	#sound-dai-cells = <0>;
+	status = "okay";
+};
+
+&i2s1 {
+	rockchip,playback-channels = <2>;
+	rockchip,capture-channels = <2>;
+	#sound-dai-cells = <0>;
+	status = "okay";
+};
+
+&i2s2 {
+	#sound-dai-cells = <0>;
+	status = "okay";
+};
+
+&io_domains {
+	status = "okay";
+
+	bt656-supply = <&vcc1v8_dvp>;
+	audio-supply = <&vcca1v8_codec>;
+	sdmmc-supply = <&vcc_sd>;
+	gpio1830-supply = <&vcc_3v0>;
+};
+
+&pcie_phy {
+	status = "okay";
+};
+
+&pcie0 {
+	ep-gpios = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
+	num-lanes = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_clkreqn>;
+	status = "okay";
+};
+
+&pmu_io_domains {
+	pmu1830-supply = <&vcc_3v0>;
+	status = "okay";
+};
+
+&pinctrl {
+	buttons {
+		pwrbtn: pwrbtn {
+			rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	lcd-panel {
+		lcd_panel_reset: lcd-panel-reset {
+			rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	pcie {
+		pcie_drv: pcie-drv {
+			rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		pcie_3g_drv: pcie-3g-drv {
+			rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	pmic {
+		vsel1_gpio: vsel1-gpio {
+			rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+
+		vsel2_gpio: vsel2-gpio {
+			rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+
+	sdio-pwrseq {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	rt5640 {
+		rt5640_hpcon: rt5640-hpcon {
+			rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_int_l: pmic-int-l {
+			rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	usb2 {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&saradc {
+	vref-supply = <&vccadc_ref>;
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	keep-power-in-suspend;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
+&tsadc {
+	/* tshut mode 0:CRU 1:GPIO */
+	rockchip,hw-tshut-mode = <1>;
+	/* tshut polarity 0:LOW 1:HIGH */
+	rockchip,hw-tshut-polarity = <1>;
+	status = "okay";
+};
+
+&u2phy0 {
+	status = "okay";
+
+	u2phy0_otg: otg-port {
+		status = "okay";
+	};
+
+	u2phy0_host: host-port {
+		phy-supply = <&vcc5v0_host>;
+		status = "okay";
+	};
+};
+
+&u2phy1 {
+	status = "okay";
+
+	u2phy1_otg: otg-port {
+		status = "okay";
+	};
+
+	u2phy1_host: host-port {
+		phy-supply = <&vcc5v0_host>;
+		status = "okay";
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer &uart0_cts>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&usb_host1_ehci {
+	status = "okay";
+};
+
+&usb_host1_ohci {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-puma.dts b/arch/arm/dts/rk3399-puma.dts
index 50e43c7..a234db8 100644
--- a/arch/arm/dts/rk3399-puma.dts
+++ b/arch/arm/dts/rk3399-puma.dts
@@ -7,12 +7,16 @@
 /dts-v1/;
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3399.dtsi"
-#include "rk3399-sdram-ddr3-1333.dtsi"
+#include "rk3399-sdram-ddr3-1600.dtsi"
 
 / {
 	model = "Theobroma Systems RK3399-Q7 SoM";
 	compatible = "tsd,puma", "rockchip,rk3399";
 
+	config {
+	        u-boot,spl-payload-offset = <204800>;
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 		u-boot,spl-boot-order = &spiflash, &sdhci, &sdmmc;
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
index bed236d..f032eec 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
@@ -39,22 +39,22 @@
 		666
 		3
 		2
-/*		13 */ 9
+		9
 		1
 		0x00000600
 		0x00000000
 		0x00000000
 		0x00000000
 		0x00000000
-/*		0xaae60 */ 7
+		0x00000007
 		0x00000000
 		0x00000000
 		0x00000000
-/* 		0xaae60 */ 7
+		0x00000007
 		0x00000000
 		0x00000000
 		0x00000000
-/*		0xaae60 */ 7
+		0x00000007
 		0x00000000
 		0x00000000
 		0x01000000
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
new file mode 100644
index 0000000..d54ea82
--- /dev/null
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
@@ -0,0 +1,1536 @@
+/*
+ * (C) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+&dmc {
+        rockchip,sdram-params = <
+		0x1
+		0xa
+		0x3
+		0x2
+		0x1
+		0x0
+		0xf
+		0xf
+		1
+		0x80151015
+		0x14040902
+		0x00000002
+		0x00006346
+		0x0000004c
+		0x00000000
+		0x1
+		0xa
+		0x3
+		0x2
+		0x1
+		0x0
+		0xf
+		0xf
+		1
+		0x80151015
+		0x14040902
+		0x00000002
+		0x00006346
+		0x0000004c
+		0x00000000
+		800
+		3
+		2
+		9
+		1
+		0x00000600
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000008
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000008
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000008
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000000
+		0x00000101
+		0x00020100
+		0x00027100
+		0x00061a80
+		0x02000200
+		0x08160200
+		0x00081600
+		0x04000816
+		0x26050004
+		0x1c0b061c
+		0x1c260500
+		0x001c0b06
+		0x061c2605
+		0x06001c0b
+		0x00000c04
+		0x0400db60
+		0x0c040605
+		0x0400db60
+		0x0c040605
+		0x0400db60
+		0x02030005
+		0x0b0c0b00
+		0x000c0b0c
+		0x14000a0a
+		0x00000a0a
+		0x00010000
+		0x03171717
+		0x000b0b0b
+		0x00000000
+		0x03010000
+		0x18580118
+		0x18580118
+		0x18580118
+		0x00000000
+		0x00050005
+		0x00140005
+		0x00140014
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02000000
+		0x02000120
+		0x02000120
+		0x00000120
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000301
+		0x00000001
+		0x00000000
+		0x00000000
+		0x01000000
+		0x80104002
+		0x00040003
+		0x00040005
+		0x00030000
+		0x00050004
+		0x00000004
+		0x00040003
+		0x00040005
+		0x61600000
+		0x000030b0
+		0x30b06160
+		0x61600000
+		0x000030b0
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x08080800
+		0x00080808
+		0x00030200
+		0x00040700
+		0x00000302
+		0x02000407
+		0x00000003
+		0x00030f04
+		0x00070004
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x00010000
+		0x20040020
+		0x00200400
+		0x01000400
+		0x00000b80
+		0x00000000
+		0x00000001
+		0x00000002
+		0x0000000e
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00a00000
+		0x00c80050
+		0x00c80000
+		0x005000a0
+		0x000000c8
+		0x00a000c8
+		0x00c80050
+		0x00c80000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00420c70
+		0x0c700018
+		0x00180042
+		0x00420c70
+		0x00000018
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00420c70
+		0x0c700018
+		0x00180042
+		0x00420c70
+		0x00000018
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000000
+		0x00000000
+		0x18151100
+		0x0000000c
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00020003
+		0x00400100
+		0x00000000
+		0x01000200
+		0x00000040
+		0x00020000
+		0x00400100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01010100
+		0x00000202
+		0x0a000001
+		0x01000f0f
+		0x00000000
+		0x00000000
+		0x00010003
+		0x00000c03
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00010000
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010000
+		0x07070702
+		0x01010606
+		0x00000001
+		0x03030300
+		0x03080808
+		0x03050303
+		0x03050303
+		0x00050303
+		0x00020202
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0d000001
+		0x00010028
+		0x00010000
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010100
+		0x01000000
+		0x00000001
+		0x00000303
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x000556aa
+		0x000aaaaa
+		0x000aa955
+		0x00055555
+		0x000b3133
+		0x0004cd33
+		0x0004cecc
+		0x000b32cc
+		0x00010300
+		0x03000100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00ffff00
+		0x15150000
+		0x08000015
+		0x000030b0
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x000030b0
+		0x0001e6e0
+		0x30b00709
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x000030b0
+		0x0001e6e0
+		0x30b00709
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x000030b0
+		0x0001e6e0
+		0x02020709
+		0x03030202
+		0x00000014
+		0x00000000
+		0x00000000
+		0x00001403
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030000
+		0x00060018
+		0x00060018
+		0x00060018
+		0x00000000
+		0x00000000
+		0x01000000
+		0x02060206
+		0x00050206
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000100
+		0x01010101
+		0x01000101
+		0x01000100
+		0x00010001
+		0x00010002
+		0x00020100
+		0x00000002
+		0x00000600
+		0x00000000
+		0x00006160
+		0x000030b0
+		0x00006160
+		0x000030b0
+		0x00006160
+		0x30b030b0
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x000030b0
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x000030b0
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00000200
+		0x00010000
+		0x00000007
+		0x110f0001
+		0x3c020000
+		0x3fffffff
+		0x3c030000
+		0x1dc0ffff
+		0x3c010000
+		0x1dc0ffff
+		0x3c000000
+		0x1dc0ffff
+		0x3c300400
+		0x1dc7ffff
+		0x3c000000
+		0x00000000
+		0x3c000000
+		0x00000000
+		0x3c000000
+		0x00000000
+		0x03000101
+		0x00242424
+		0x08160008
+		0x00081600
+		0x00000016
+		0x18580118
+		0x18580118
+		0x18580118
+		0x00000500
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04040000
+		0x0d000004
+		0x00000128
+		0x00000000
+		0x00030003
+		0x00000014
+		0x00000000
+		0x00000000
+		0x07060002
+		0x07010701
+		0x00060601
+		0x00020001
+		0x00080004
+		0x00000000
+		0x00000000
+		0x03030300
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00030300
+		0x00000014
+		0x00000000
+		0x01010300
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00000101
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x55555a5a
+		0x09090001
+		0x07070009
+		0x02020007
+		0x00000102
+		0x00030000
+		0x17030000
+		0x00060018
+		0x00060018
+		0x00060018
+		0x00000000
+		0x00000000
+		0x00000000
+		0x140a0000
+		0x000a000a
+		0x00000a00
+		0x010a000a
+		0x00000100
+		0x01000000
+		0x00000000
+		0x00000100
+		0x1e1a0000
+		0x10010204
+		0x07070705
+		0x20000202
+		0x00201000
+		0x00201000
+		0x04041000
+		0x10100100
+		0x00010110
+		0x004b004a
+		0x1a030000
+		0x0102041e
+		0x34000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00004200
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0000424d
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0000424d
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0042004d
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0000424d
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0000424d
+		0x00000018
+		0x004d4d00
+		0x00180042
+		0x4d000000
+		0x0000004d
+		0x00c800c8
+		0x060400c8
+		0x0c060b0b
+		0x1c00d92e
+		0x08042000
+		0x0b0b060c
+		0x00000c06
+		0x1c00d92e
+		0x08042000
+		0x0b0b060c
+		0x00000c06
+		0x1c00d92e
+		0x08042000
+		0x0200020c
+		0x02000200
+		0x02000200
+		0x02000200
+		0x02000200
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000300
+		0x0030b000
+		0x0001e6e0
+		0x000030b0
+		0x0001e6e0
+		0x000030b0
+		0x0001e6e0
+		0x08000000
+		0x00000100
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000001
+		0x76543210
+		0x0004c008
+		0x00000099
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000001
+		0x001700c0
+		0x00cc0001
+		0x00000066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x08000000
+		0x0c00c007
+		0x00000100
+		0x00000100
+		0x55555555
+		0xaaaaaaaa
+		0x55555555
+		0xaaaaaaaa
+		0x00005555
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00990080
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51313152
+		0x80013130
+		0x02000080
+		0x00100001
+		0x07054208
+		0x000f0c0f
+		0x01000140
+		0x00000c20
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004c008
+		0x00000099
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000001
+		0x001700c0
+		0x00cc0001
+		0x00000066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x08000000
+		0x0c00c007
+		0x00000100
+		0x00000100
+		0x55555555
+		0xaaaaaaaa
+		0x55555555
+		0xaaaaaaaa
+		0x00005555
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00990080
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51313152
+		0x80013130
+		0x02000080
+		0x00100001
+		0x07054208
+		0x000f0c0f
+		0x01000140
+		0x00000c20
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004c008
+		0x00000099
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000001
+		0x001700c0
+		0x00cc0001
+		0x00000066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x08000000
+		0x0c00c007
+		0x00000100
+		0x00000100
+		0x55555555
+		0xaaaaaaaa
+		0x55555555
+		0xaaaaaaaa
+		0x00005555
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00990080
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51313152
+		0x80013130
+		0x02000080
+		0x00100001
+		0x07054208
+		0x000f0c0f
+		0x01000140
+		0x00000c20
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x76543210
+		0x0004c008
+		0x00000099
+		0x00000000
+		0x00000000
+		0x00010000
+		0x01665555
+		0x00665555
+		0x00010f00
+		0x05010200
+		0x00000001
+		0x001700c0
+		0x00cc0001
+		0x00000066
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04080000
+		0x04080400
+		0x08000000
+		0x0c00c007
+		0x00000100
+		0x00000100
+		0x55555555
+		0xaaaaaaaa
+		0x55555555
+		0xaaaaaaaa
+		0x00005555
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00200000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x02800280
+		0x02800280
+		0x02800280
+		0x02800280
+		0x00000280
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00800080
+		0x00990080
+		0x00000001
+		0x00000000
+		0x00000000
+		0x00000200
+		0x00000000
+		0x51313152
+		0x80013130
+		0x02000080
+		0x00100001
+		0x07054208
+		0x000f0c0f
+		0x01000140
+		0x00000c20
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00dcba98
+		0x00000000
+		0x00dcba98
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x0a418820
+		0x103f0000
+		0x0000003f
+		0x00030055
+		0x03000300
+		0x03000300
+		0x00000300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x16a4a0e6
+		0x103f0000
+		0x0000003f
+		0x00030055
+		0x03000300
+		0x03000300
+		0x00000300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00800000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00400320
+		0x00000040
+		0x00000000
+		0x00000000
+		0x00000000
+		0x01000000
+		0x00020003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x0000002a
+		0x00000015
+		0x00000015
+		0x0000002a
+		0x00000033
+		0x0000000c
+		0x0000000c
+		0x00000033
+		0x1ee6b16a
+		0x103f0000
+		0x0000003f
+		0x00030055
+		0x03000300
+		0x03000300
+		0x00000300
+		0x42080010
+		0x00000003
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000001
+		0x00000000
+		0x01000005
+		0x04000f00
+		0x00020040
+		0x00020055
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00010100
+		0x00000601
+		0x00000000
+		0x00006400
+		0x01221102
+		0x00000000
+		0x00031f00
+		0x031f031f
+		0x031f031f
+		0x00030003
+		0x03000300
+		0x00000300
+		0x01221102
+		0x00000000
+		0x00000000
+		0x03020000
+		0x00000001
+		0x00008011
+		0x00000011
+		0x00000440
+		0x00000040
+		0x00004011
+		0x00004011
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004410
+		0x00004011
+		0x00004410
+		0x00004011
+		0x00004410
+		0x00004011
+		0x00004410
+		0x00000000
+		0x00000000
+		0x00000000
+		0x04000000
+		0x00000000
+		0x00000000
+		0x00000508
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0x00000000
+		0xe4000000
+		0x00000000
+		0x00000000
+		0x01010000
+		0x00000000
+	>;
+};
diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi
index d94d780..f3d3f53 100644
--- a/arch/arm/dts/rk3399.dtsi
+++ b/arch/arm/dts/rk3399.dtsi
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,6 +9,8 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/power/rk3399-power.h>
+#include <dt-bindings/thermal/thermal.h>
 #define USB_CLASS_HUB			9
 
 / {
@@ -19,6 +21,15 @@
 	#size-cells = <2>;
 
 	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+		i2c8 = &i2c8;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
@@ -26,7 +37,6 @@
 		serial4 = &uart4;
 		mmc0 = &sdhci;
 		mmc1 = &sdmmc;
-		i2c0 = &i2c0;
 	};
 
 	cpus {
@@ -110,6 +120,16 @@
 		};
 	};
 
+	pmu_a53 {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>;
+	};
+
+	pmu_a72 {
+		compatible = "arm,cortex-a72-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>;
+	};
+
 	psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
@@ -117,10 +137,11 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
-			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
-			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
-			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
+		arm,no-tick-in-suspend;
 	};
 
 	xin24m: xin24m {
@@ -139,8 +160,8 @@
 		dmac_bus: dma-controller@ff6d0000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x0 0xff6d0000 0x0 0x4000>;
-			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>;
 			#dma-cells = <1>;
 			clocks = <&cru ACLK_DMAC0_PERILP>;
 			clock-names = "apb_pclk";
@@ -149,24 +170,92 @@
 		dmac_peri: dma-controller@ff6e0000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x0 0xff6e0000 0x0 0x4000>;
-			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH 0>,
+				     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>;
 			#dma-cells = <1>;
 			clocks = <&cru ACLK_DMAC1_PERILP>;
 			clock-names = "apb_pclk";
 		};
 	};
 
+	pcie0: pcie@f8000000 {
+		compatible = "rockchip,rk3399-pcie";
+		reg = <0x0 0xf8000000 0x0 0x2000000>,
+		      <0x0 0xfd000000 0x0 0x1000000>;
+		reg-names = "axi-base", "apb-base";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		aspm-no-l0s;
+		bus-range = <0x0 0x1>;
+		clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
+			 <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
+		clock-names = "aclk", "aclk-perf",
+			      "hclk", "pm";
+		interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
+		interrupt-names = "sys", "legacy", "client";
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>,
+				<0 0 0 2 &pcie0_intc 1>,
+				<0 0 0 3 &pcie0_intc 2>,
+				<0 0 0 4 &pcie0_intc 3>;
+		linux,pci-domain = <0>;
+		max-link-speed = <1>;
+		msi-map = <0x0 &its 0x0 0x1000>;
+		phys = <&pcie_phy>;
+		phy-names = "pcie-phy";
+		ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000
+			  0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>;
+		resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
+			 <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
+			 <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>,
+			 <&cru SRST_A_PCIE>;
+		reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
+			      "pm", "pclk", "aclk";
+		status = "disabled";
+
+		pcie0_intc: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+	};
+
+	gmac: ethernet@fe300000 {
+		compatible = "rockchip,rk3399-gmac";
+		reg = <0x0 0xfe300000 0x0 0x10000>;
+		interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>;
+		interrupt-names = "macirq";
+		clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>,
+			 <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>,
+			 <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>,
+			 <&cru PCLK_GMAC>;
+		clock-names = "stmmaceth", "mac_clk_rx",
+			      "mac_clk_tx", "clk_mac_ref",
+			      "clk_mac_refout", "aclk_mac",
+			      "pclk_mac";
+		power-domains = <&power RK3399_PD_GMAC>;
+		resets = <&cru SRST_A_GMAC>;
+		reset-names = "stmmaceth";
+		rockchip,grf = <&grf>;
+		status = "disabled";
+	};
+
 	sdio0: dwmmc@fe310000 {
 		compatible = "rockchip,rk3399-dw-mshc",
 			     "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xfe310000 0x0 0x4000>;
-		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-		clock-freq-min-max = <400000 150000000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH 0>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
 			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
+		power-domains = <&power RK3399_PD_SDIOAUDIO>;
+		resets = <&cru SRST_SDIO0>;
+		reset-names = "reset";
 		status = "disabled";
 	};
 
@@ -174,14 +263,15 @@
 		compatible = "rockchip,rk3399-dw-mshc",
 			     "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xfe320000 0x0 0x4000>;
-		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-		clock-freq-min-max = <400000 150000000>;
-		clocks = <&cru SCLK_SDMMC>, <&cru HCLK_SDMMC>,
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
+		max-frequency = <150000000>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-		clock-names = "ciu", "biu", "ciu-drive", "ciu-sample";
-		pinctrl-names = "default";
-		pinctrl-0 = <&sdmmc_clk>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
+		power-domains = <&power RK3399_PD_SD>;
+		resets = <&cru SRST_SDMMC>;
+		reset-names = "reset";
 		status = "disabled";
 	};
 
@@ -189,50 +279,74 @@
 		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
 		reg = <0x0 0xfe330000 0x0 0x10000>;
-		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>;
+		arasan,soc-ctl-syscon = <&grf>;
 		assigned-clocks = <&cru SCLK_EMMC>;
 		assigned-clock-rates = <200000000>;
 		max-frequency = <200000000>;
 		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
 		clock-names = "clk_xin", "clk_ahb";
+		clock-output-names = "emmc_cardclock";
+		#clock-cells = <0>;
 		phys = <&emmc_phy>;
 		phy-names = "phy_arasan";
+		power-domains = <&power RK3399_PD_EMMC>;
 		status = "disabled";
 	};
 
 	usb_host0_ehci: usb@fe380000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe380000 0x0 0x20000>;
-		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
-		clock-names = "hclk_host0", "hclk_host0_arb";
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
+			 <&u2phy0>;
+		clock-names = "usbhost", "arbiter",
+			      "utmi";
+		phys = <&u2phy0_host>;
+		phy-names = "usb";
+		power-domains = <&power RK3399_PD_PERIHP>;
 		status = "disabled";
 	};
 
 	usb_host0_ohci: usb@fe3a0000 {
 		compatible = "generic-ohci";
 		reg = <0x0 0xfe3a0000 0x0 0x20000>;
-		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
-		clock-names = "hclk_host0", "hclk_host0_arb";
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
+			 <&u2phy0>;
+		clock-names = "usbhost", "arbiter",
+			      "utmi";
+		phys = <&u2phy0_host>;
+		phy-names = "usb";
+		power-domains = <&power RK3399_PD_PERIHP>;
 		status = "disabled";
 	};
 
 	usb_host1_ehci: usb@fe3c0000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe3c0000 0x0 0x20000>;
-		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
-		clock-names = "hclk_host1", "hclk_host1_arb";
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
+			 <&u2phy1>;
+		clock-names = "usbhost", "arbiter",
+			      "utmi";
+		phys = <&u2phy1_host>;
+		phy-names = "usb";
+		power-domains = <&power RK3399_PD_PERIHP>;
 		status = "disabled";
 	};
 
 	usb_host1_ohci: usb@fe3e0000 {
 		compatible = "generic-ohci";
 		reg = <0x0 0xfe3e0000 0x0 0x20000>;
-		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
-		clock-names = "hclk_host1", "hclk_host1_arb";
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
+			 <&u2phy1>;
+		clock-names = "usbhost", "arbiter",
+			      "utmi";
+		phys = <&u2phy1_host>;
+		phy-names = "usb";
+		power-domains = <&power RK3399_PD_PERIHP>;
 		status = "disabled";
 	};
 
@@ -280,7 +394,7 @@
 
 	gic: interrupt-controller@fee00000 {
 		compatible = "arm,gic-v3";
-		#interrupt-cells = <3>;
+		#interrupt-cells = <4>;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -291,20 +405,132 @@
 		      <0x0 0xfff00000 0 0x10000>, /* GICC */
 		      <0x0 0xfff10000 0 0x10000>, /* GICH */
 		      <0x0 0xfff20000 0 0x10000>; /* GICV */
-		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
 		its: interrupt-controller@fee20000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
 			reg = <0x0 0xfee20000 0x0 0x20000>;
 		};
+
+		ppi-partitions {
+			ppi_cluster0: interrupt-partition-0 {
+				affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>;
+			};
+
+			ppi_cluster1: interrupt-partition-1 {
+				affinity = <&cpu_b0 &cpu_b1>;
+			};
+		};
+	};
+
+	saradc: saradc@ff100000 {
+		compatible = "rockchip,rk3399-saradc";
+		reg = <0x0 0xff100000 0x0 0x100>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH 0>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_P_SARADC>;
+		reset-names = "saradc-apb";
+		status = "disabled";
+	};
+
+	i2c1: i2c@ff110000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff110000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C1>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@ff120000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff120000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C2>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@ff130000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff130000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C3>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c5: i2c@ff140000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C5>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
 	};
 
+	i2c6: i2c@ff150000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff150000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C6>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c6_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c7: i2c@ff160000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff160000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C7>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c7_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	uart0: serial@ff180000 {
 		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
 		reg = <0x0 0xff180000 0x0 0x100>;
 		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
 		clock-names = "baudclk", "apb_pclk";
-		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		pinctrl-names = "default";
@@ -317,7 +543,7 @@
 		reg = <0x0 0xff190000 0x0 0x100>;
 		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
 		clock-names = "baudclk", "apb_pclk";
-		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		pinctrl-names = "default";
@@ -330,7 +556,7 @@
 		reg = <0x0 0xff1a0000 0x0 0x100>;
 		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
 		clock-names = "baudclk", "apb_pclk";
-		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>;
 		clock-frequency = <24000000>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
@@ -344,7 +570,7 @@
 		reg = <0x0 0xff1b0000 0x0 0x100>;
 		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
 		clock-names = "baudclk", "apb_pclk";
-		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		pinctrl-names = "default";
@@ -357,7 +583,7 @@
 		reg = <0x0 0xff1c0000 0x0 0x1000>;
 		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
 		#address-cells = <1>;
@@ -370,7 +596,7 @@
 		reg = <0x0 0xff1d0000 0x0 0x1000>;
 		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
 		#address-cells = <1>;
@@ -383,7 +609,7 @@
 		reg = <0x0 0xff1e0000 0x0 0x1000>;
 		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
 		#address-cells = <1>;
@@ -396,7 +622,7 @@
 		reg = <0x0 0xff1f0000 0x0 0x1000>;
 		clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>;
 		#address-cells = <1>;
@@ -409,7 +635,7 @@
 		reg = <0x0 0xff200000 0x0 0x1000>;
 		clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>;
 		#address-cells = <1>;
@@ -417,6 +643,375 @@
 		status = "disabled";
 	};
 
+	thermal_zones: thermal-zones {
+		cpu_thermal: cpu {
+			polling-delay-passive = <100>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <70000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <95000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+						<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu_thermal: gpu {
+			polling-delay-passive = <100>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				gpu_alert0: gpu_alert0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				gpu_crit: gpu_crit {
+					temperature = <95000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
+	tsadc: tsadc@ff260000 {
+		compatible = "rockchip,rk3399-tsadc";
+		reg = <0x0 0xff260000 0x0 0x100>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>;
+		assigned-clocks = <&cru SCLK_TSADC>;
+		assigned-clock-rates = <750000>;
+		clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+		clock-names = "tsadc", "apb_pclk";
+		resets = <&cru SRST_TSADC>;
+		reset-names = "tsadc-apb";
+		rockchip,grf = <&grf>;
+		rockchip,hw-tshut-temp = <95000>;
+		pinctrl-names = "init", "default", "sleep";
+		pinctrl-0 = <&otp_gpio>;
+		pinctrl-1 = <&otp_out>;
+		pinctrl-2 = <&otp_gpio>;
+		#thermal-sensor-cells = <1>;
+		status = "disabled";
+	};
+
+	qos_emmc: qos@ffa58000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa58000 0x0 0x20>;
+	};
+
+	qos_gmac: qos@ffa5c000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa5c000 0x0 0x20>;
+	};
+
+	qos_pcie: qos@ffa60080 {
+		compatible = "syscon";
+		reg = <0x0 0xffa60080 0x0 0x20>;
+	};
+
+	qos_usb_host0: qos@ffa60100 {
+		compatible = "syscon";
+		reg = <0x0 0xffa60100 0x0 0x20>;
+	};
+
+	qos_usb_host1: qos@ffa60180 {
+		compatible = "syscon";
+		reg = <0x0 0xffa60180 0x0 0x20>;
+	};
+
+	qos_usb_otg0: qos@ffa70000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa70000 0x0 0x20>;
+	};
+
+	qos_usb_otg1: qos@ffa70080 {
+		compatible = "syscon";
+		reg = <0x0 0xffa70080 0x0 0x20>;
+	};
+
+	qos_sd: qos@ffa74000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa74000 0x0 0x20>;
+	};
+
+	qos_sdioaudio: qos@ffa76000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa76000 0x0 0x20>;
+	};
+
+	qos_hdcp: qos@ffa90000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa90000 0x0 0x20>;
+	};
+
+	qos_iep: qos@ffa98000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa98000 0x0 0x20>;
+	};
+
+	qos_isp0_m0: qos@ffaa0000 {
+		compatible = "syscon";
+		reg = <0x0 0xffaa0000 0x0 0x20>;
+	};
+
+	qos_isp0_m1: qos@ffaa0080 {
+		compatible = "syscon";
+		reg = <0x0 0xffaa0080 0x0 0x20>;
+	};
+
+	qos_isp1_m0: qos@ffaa8000 {
+		compatible = "syscon";
+		reg = <0x0 0xffaa8000 0x0 0x20>;
+	};
+
+	qos_isp1_m1: qos@ffaa8080 {
+		compatible = "syscon";
+		reg = <0x0 0xffaa8080 0x0 0x20>;
+	};
+
+	qos_rga_r: qos@ffab0000 {
+		compatible = "syscon";
+		reg = <0x0 0xffab0000 0x0 0x20>;
+	};
+
+	qos_rga_w: qos@ffab0080 {
+		compatible = "syscon";
+		reg = <0x0 0xffab0080 0x0 0x20>;
+	};
+
+	qos_video_m0: qos@ffab8000 {
+		compatible = "syscon";
+		reg = <0x0 0xffab8000 0x0 0x20>;
+	};
+
+	qos_video_m1_r: qos@ffac0000 {
+		compatible = "syscon";
+		reg = <0x0 0xffac0000 0x0 0x20>;
+	};
+
+	qos_video_m1_w: qos@ffac0080 {
+		compatible = "syscon";
+		reg = <0x0 0xffac0080 0x0 0x20>;
+	};
+
+	qos_vop_big_r: qos@ffac8000 {
+		compatible = "syscon";
+		reg = <0x0 0xffac8000 0x0 0x20>;
+	};
+
+	qos_vop_big_w: qos@ffac8080 {
+		compatible = "syscon";
+		reg = <0x0 0xffac8080 0x0 0x20>;
+	};
+
+	qos_vop_little: qos@ffad0000 {
+		compatible = "syscon";
+		reg = <0x0 0xffad0000 0x0 0x20>;
+	};
+
+	qos_perihp: qos@ffad8080 {
+		compatible = "syscon";
+		reg = <0x0 0xffad8080 0x0 0x20>;
+	};
+
+	qos_gpu: qos@ffae0000 {
+		compatible = "syscon";
+		reg = <0x0 0xffae0000 0x0 0x20>;
+	};
+
+	pmu: power-management@ff310000 {
+		compatible = "rockchip,rk3399-pmu", "syscon", "simple-mfd";
+		reg = <0x0 0xff310000 0x0 0x1000>;
+
+		/*
+		 * Note: RK3399 supports 6 voltage domains including VD_CORE_L,
+		 * VD_CORE_B, VD_CENTER, VD_GPU, VD_LOGIC and VD_PMU.
+		 * Some of the power domains are grouped together for every
+		 * voltage domain.
+		 * The detail contents as below.
+		 */
+		power: power-controller {
+			compatible = "rockchip,rk3399-power-controller";
+			#power-domain-cells = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* These power domains are grouped by VD_CENTER */
+			pd_iep@RK3399_PD_IEP {
+				reg = <RK3399_PD_IEP>;
+				clocks = <&cru ACLK_IEP>,
+					 <&cru HCLK_IEP>;
+				pm_qos = <&qos_iep>;
+			};
+			pd_rga@RK3399_PD_RGA {
+				reg = <RK3399_PD_RGA>;
+				clocks = <&cru ACLK_RGA>,
+					 <&cru HCLK_RGA>;
+				pm_qos = <&qos_rga_r>,
+					 <&qos_rga_w>;
+			};
+			pd_vcodec@RK3399_PD_VCODEC {
+				reg = <RK3399_PD_VCODEC>;
+				clocks = <&cru ACLK_VCODEC>,
+					 <&cru HCLK_VCODEC>;
+				pm_qos = <&qos_video_m0>;
+			};
+			pd_vdu@RK3399_PD_VDU {
+				reg = <RK3399_PD_VDU>;
+				clocks = <&cru ACLK_VDU>,
+					 <&cru HCLK_VDU>;
+				pm_qos = <&qos_video_m1_r>,
+					 <&qos_video_m1_w>;
+			};
+
+			/* These power domains are grouped by VD_GPU */
+			pd_gpu@RK3399_PD_GPU {
+				reg = <RK3399_PD_GPU>;
+				clocks = <&cru ACLK_GPU>;
+				pm_qos = <&qos_gpu>;
+			};
+
+			/* These power domains are grouped by VD_LOGIC */
+			pd_edp@RK3399_PD_EDP {
+				reg = <RK3399_PD_EDP>;
+				clocks = <&cru PCLK_EDP_CTRL>;
+			};
+			pd_emmc@RK3399_PD_EMMC {
+				reg = <RK3399_PD_EMMC>;
+				clocks = <&cru ACLK_EMMC>;
+				pm_qos = <&qos_emmc>;
+			};
+			pd_gmac@RK3399_PD_GMAC {
+				reg = <RK3399_PD_GMAC>;
+				clocks = <&cru ACLK_GMAC>,
+					 <&cru PCLK_GMAC>;
+				pm_qos = <&qos_gmac>;
+			};
+			pd_perihp@RK3399_PD_PERIHP {
+				reg = <RK3399_PD_PERIHP>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&cru ACLK_PERIHP>;
+				pm_qos = <&qos_perihp>,
+					 <&qos_pcie>,
+					 <&qos_usb_host0>,
+					 <&qos_usb_host1>;
+
+				pd_sd@RK3399_PD_SD {
+					reg = <RK3399_PD_SD>;
+					clocks = <&cru HCLK_SDMMC>,
+						 <&cru SCLK_SDMMC>;
+					pm_qos = <&qos_sd>;
+				};
+			};
+			pd_sdioaudio@RK3399_PD_SDIOAUDIO {
+				reg = <RK3399_PD_SDIOAUDIO>;
+				clocks = <&cru HCLK_SDIO>;
+				pm_qos = <&qos_sdioaudio>;
+			};
+			pd_usb3@RK3399_PD_USB3 {
+				reg = <RK3399_PD_USB3>;
+				clocks = <&cru ACLK_USB3>;
+				pm_qos = <&qos_usb_otg0>,
+					 <&qos_usb_otg1>;
+			};
+			pd_vio@RK3399_PD_VIO {
+				reg = <RK3399_PD_VIO>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pd_hdcp@RK3399_PD_HDCP {
+					reg = <RK3399_PD_HDCP>;
+					clocks = <&cru ACLK_HDCP>,
+						 <&cru HCLK_HDCP>,
+						 <&cru PCLK_HDCP>;
+					pm_qos = <&qos_hdcp>;
+				};
+				pd_isp0@RK3399_PD_ISP0 {
+					reg = <RK3399_PD_ISP0>;
+					clocks = <&cru ACLK_ISP0>,
+						 <&cru HCLK_ISP0>;
+					pm_qos = <&qos_isp0_m0>,
+						 <&qos_isp0_m1>;
+				};
+				pd_isp1@RK3399_PD_ISP1 {
+					reg = <RK3399_PD_ISP1>;
+					clocks = <&cru ACLK_ISP1>,
+						 <&cru HCLK_ISP1>;
+					pm_qos = <&qos_isp1_m0>,
+						 <&qos_isp1_m1>;
+				};
+				pd_tcpc0@RK3399_PD_TCPC0 {
+					reg = <RK3399_PD_TCPD0>;
+					clocks = <&cru SCLK_UPHY0_TCPDCORE>,
+						 <&cru SCLK_UPHY0_TCPDPHY_REF>;
+				};
+				pd_tcpc1@RK3399_PD_TCPC1 {
+					reg = <RK3399_PD_TCPD1>;
+					clocks = <&cru SCLK_UPHY1_TCPDCORE>,
+						 <&cru SCLK_UPHY1_TCPDPHY_REF>;
+				};
+				pd_vo@RK3399_PD_VO {
+					reg = <RK3399_PD_VO>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					pd_vopb@RK3399_PD_VOPB {
+						reg = <RK3399_PD_VOPB>;
+						clocks = <&cru ACLK_VOP0>,
+							 <&cru HCLK_VOP0>;
+						pm_qos = <&qos_vop_big_r>,
+							 <&qos_vop_big_w>;
+					};
+					pd_vopl@RK3399_PD_VOPL {
+						reg = <RK3399_PD_VOPL>;
+						clocks = <&cru ACLK_VOP1>,
+							 <&cru HCLK_VOP1>;
+						pm_qos = <&qos_vop_little>;
+					};
+				};
+			};
+		};
+	};
+
 	pmugrf: syscon@ff320000 {
 		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd";
@@ -441,7 +1036,7 @@
 		reg = <0x0 0xff350000 0x0 0x1000>;
 		clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>;
 		clock-names = "spiclk", "apb_pclk";
-		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH 0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>;
 		#address-cells = <1>;
@@ -454,7 +1049,7 @@
 		reg = <0x0 0xff370000 0x0 0x100>;
 		clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>;
 		clock-names = "baudclk", "apb_pclk";
-		interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>;
 		reg-shift = <2>;
 		reg-io-width = <4>;
 		pinctrl-names = "default";
@@ -462,6 +1057,36 @@
 		status = "disabled";
 	};
 
+	i2c4: i2c@ff3d0000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff3d0000 0x0 0x1000>;
+		assigned-clocks = <&pmucru SCLK_I2C4_PMU>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c8: i2c@ff3e0000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff3e0000 0x0 0x1000>;
+		assigned-clocks = <&pmucru SCLK_I2C8_PMU>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c8_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	pwm0: pwm@ff420000 {
 		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
 		reg = <0x0 0xff420000 0x0 0x10>;
@@ -538,10 +1163,43 @@
 		       0x0 0xffa8c000 0x0 0x1000>;
 	};
 
+	efuse0: efuse@ff690000 {
+		compatible = "rockchip,rk3399-efuse";
+		reg = <0x0 0xff690000 0x0 0x80>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		clocks = <&cru PCLK_EFUSE1024NS>;
+		clock-names = "pclk_efuse";
+
+		/* Data cells */
+		cpu_id: cpu-id@7 {
+			reg = <0x07 0x10>;
+		};
+		cpub_leakage: cpu-leakage@17 {
+			reg = <0x17 0x1>;
+		};
+		gpu_leakage: gpu-leakage@18 {
+			reg = <0x18 0x1>;
+		};
+		center_leakage: center-leakage@19 {
+			reg = <0x19 0x1>;
+		};
+		cpul_leakage: cpu-leakage@1a {
+			reg = <0x1a 0x1>;
+		};
+		logic_leakage: logic-leakage@1b {
+			reg = <0x1b 0x1>;
+		};
+		wafer_info: wafer-info@1c {
+			reg = <0x1c 0x1>;
+		};
+	};
+
 	pmucru: pmu-clock-controller@ff750000 {
 		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmucru";
 		reg = <0x0 0xff750000 0x0 0x1000>;
+		rockchip,grf = <&pmugrf>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
 		assigned-clocks = <&pmucru PLL_PPLL>;
@@ -552,6 +1210,7 @@
 		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-cru";
 		reg = <0x0 0xff760000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
 		assigned-clocks =
@@ -560,7 +1219,7 @@
 			<&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>,
 			<&cru PCLK_PERIHP>,
 			<&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
-			<&cru PCLK_PERILP0>,
+			<&cru PCLK_PERILP0>, <&cru ACLK_CCI>,
 			<&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>;
 		assigned-clock-rates =
 			 <594000000>,  <800000000>,
@@ -568,7 +1227,7 @@
 			 <150000000>,   <75000000>,
 			  <37500000>,
 			 <100000000>,  <100000000>,
-			  <50000000>,
+			  <50000000>, <600000000>,
 			 <100000000>,   <50000000>;
 	};
 
@@ -584,50 +1243,106 @@
 			status = "disabled";
 		};
 
+		u2phy0: usb2-phy@e450 {
+			compatible = "rockchip,rk3399-usb2phy";
+			reg = <0xe450 0x10>;
+			clocks = <&cru SCLK_USB2PHY0_REF>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+			clock-output-names = "clk_usbphy0_480m";
+			status = "disabled";
+
+			u2phy0_host: host-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "linestate";
+				status = "disabled";
+			};
+
+			u2phy0_otg: otg-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "otg-bvalid", "otg-id",
+						  "linestate";
+				status = "disabled";
+			};
+		};
+
+		u2phy1: usb2-phy@e460 {
+			compatible = "rockchip,rk3399-usb2phy";
+			reg = <0xe460 0x10>;
+			clocks = <&cru SCLK_USB2PHY1_REF>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+			clock-output-names = "clk_usbphy1_480m";
+			status = "disabled";
+
+			u2phy1_host: host-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "linestate";
+				status = "disabled";
+			};
+
+			u2phy1_otg: otg-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "otg-bvalid", "otg-id",
+						  "linestate";
+				status = "disabled";
+			};
+		};
+
 		emmc_phy: phy@f780 {
 			compatible = "rockchip,rk3399-emmc-phy";
 			reg = <0xf780 0x24>;
+			clocks = <&sdhci>;
+			clock-names = "emmcclk";
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		pcie_phy: pcie-phy {
+			compatible = "rockchip,rk3399-pcie-phy";
+			clocks = <&cru SCLK_PCIEPHY_REF>;
+			clock-names = "refclk";
 			#phy-cells = <0>;
+			resets = <&cru SRST_PCIEPHY>;
+			reset-names = "phy";
 			status = "disabled";
 		};
 	};
 
-	watchdog@ff840000 {
+	watchdog@ff848000 {
 		compatible = "snps,dw-wdt";
-		reg = <0x0 0xff840000 0x0 0x100>;
+		reg = <0x0 0xff848000 0x0 0x100>;
 		clocks = <&cru PCLK_WDT>;
-		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>;
 	};
 
-        gmac: eth@fe300000 {
-                compatible = "rockchip,rk3399-gmac";
-                reg = <0x0 0xfe300000 0x0 0x10000>;
-                rockchip,grf = <&grf>;
-                interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>;
-                interrupt-names = "macirq";
-                clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>,
-                         <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>,
-                         <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>,
-                         <&cru PCLK_GMAC>;
-                clock-names = "stmmaceth", "mac_clk_rx",
-                              "mac_clk_tx", "clk_mac_ref",
-                              "clk_mac_refout", "aclk_mac",
-                              "pclk_mac";
-                resets = <&cru SRST_A_GMAC>;
-                reset-names = "stmmaceth";
-                status = "disabled";
-        };
+	rktimer: rktimer@ff850000 {
+		compatible = "rockchip,rk3399-timer";
+		reg = <0x0 0xff850000 0x0 0x1000>;
+		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>;
+		clock-names = "pclk", "timer";
+	};
 
 	spdif: spdif@ff870000 {
 		compatible = "rockchip,rk3399-spdif";
 		reg = <0x0 0xff870000 0x0 0x1000>;
-		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>;
 		dmas = <&dmac_bus 7>;
 		dma-names = "tx";
 		clock-names = "mclk", "hclk";
 		clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spdif_bus>;
+		power-domains = <&power RK3399_PD_SDIOAUDIO>;
 		status = "disabled";
 	};
 
@@ -635,37 +1350,40 @@
 		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
 		reg = <0x0 0xff880000 0x0 0x1000>;
 		rockchip,grf = <&grf>;
-		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH 0>;
 		dmas = <&dmac_bus 0>, <&dmac_bus 1>;
 		dma-names = "tx", "rx";
 		clock-names = "i2s_clk", "i2s_hclk";
 		clocks = <&cru SCLK_I2S0_8CH>, <&cru HCLK_I2S0_8CH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&i2s0_8ch_bus>;
+		power-domains = <&power RK3399_PD_SDIOAUDIO>;
 		status = "disabled";
 	};
 
 	i2s1: i2s@ff890000 {
 		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
 		reg = <0x0 0xff890000 0x0 0x1000>;
-		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH 0>;
 		dmas = <&dmac_bus 2>, <&dmac_bus 3>;
 		dma-names = "tx", "rx";
 		clock-names = "i2s_clk", "i2s_hclk";
 		clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&i2s1_2ch_bus>;
+		power-domains = <&power RK3399_PD_SDIOAUDIO>;
 		status = "disabled";
 	};
 
 	i2s2: i2s@ff8a0000 {
 		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
 		reg = <0x0 0xff8a0000 0x0 0x1000>;
-		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH 0>;
 		dmas = <&dmac_bus 4>, <&dmac_bus 5>;
 		dma-names = "tx", "rx";
 		clock-names = "i2s_clk", "i2s_hclk";
 		clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>;
+		power-domains = <&power RK3399_PD_SDIOAUDIO>;
 		status = "disabled";
 	};
 
@@ -682,8 +1400,79 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
+	};
+
+	vopl: vop@ff8f0000 {
+		u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3399-vop-lit";
+		reg = <0x0 0xff8f0000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>;
+		reset-names = "axi", "ahb", "dclk";
+		status = "disabled";
+		vopl_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			vopl_out_mipi: endpoint@0 {
+				reg = <3>;
+				remote-endpoint = <&mipi_in_vopl>;
+			};
+		};
+	};
+
+	vopb: vop@ff900000 {
+		u-boot,dm-pre-reloc;
+		compatible = "rockchip,rk3399-vop-big";
+		reg = <0x0 0xff900000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
+		#clock-cells = <0>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;
+		reset-names = "axi", "ahb", "dclk";
+		status = "disabled";
+		vopb_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			vopb_out_mipi: endpoint@0 {
+				reg = <3>;
+				remote-endpoint = <&mipi_in_vopb>;
+			};
+		};
 	};
 
+	mipi_dsi: mipi@ff960000 {
+		compatible = "rockchip,rk3399_mipi_dsi";
+		reg = <0x0 0xff960000 0x0 0x8000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru SCLK_MIPIDPHY_REF>, <&cru PCLK_MIPI_DSI0>,
+		         <&cru SCLK_DPHY_TX0_CFG>;
+		clock-names = "ref", "pclk", "phy_cfg";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			mipi_in: port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				mipi_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_mipi>;
+				};
+				mipi_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_mipi>;
+				};
+			};
+		};
+	};
+
 	pinctrl: pinctrl {
 		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pinctrl";
@@ -697,7 +1486,7 @@
 			compatible = "rockchip,gpio-bank";
 			reg = <0x0 0xff720000 0x0 0x100>;
 			clocks = <&pmucru PCLK_GPIO0_PMU>;
-			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>;
 
 			gpio-controller;
 			#gpio-cells = <0x2>;
@@ -710,7 +1499,7 @@
 			compatible = "rockchip,gpio-bank";
 			reg = <0x0 0xff730000 0x0 0x100>;
 			clocks = <&pmucru PCLK_GPIO1_PMU>;
-			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH 0>;
 
 			gpio-controller;
 			#gpio-cells = <0x2>;
@@ -723,7 +1512,7 @@
 			compatible = "rockchip,gpio-bank";
 			reg = <0x0 0xff780000 0x0 0x100>;
 			clocks = <&cru PCLK_GPIO2>;
-			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH 0>;
 
 			gpio-controller;
 			#gpio-cells = <0x2>;
@@ -736,7 +1525,7 @@
 			compatible = "rockchip,gpio-bank";
 			reg = <0x0 0xff788000 0x0 0x100>;
 			clocks = <&cru PCLK_GPIO3>;
-			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>;
 
 			gpio-controller;
 			#gpio-cells = <0x2>;
@@ -749,7 +1538,7 @@
 			compatible = "rockchip,gpio-bank";
 			reg = <0x0 0xff790000 0x0 0x100>;
 			clocks = <&cru PCLK_GPIO4>;
-			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>;
 
 			gpio-controller;
 			#gpio-cells = <0x2>;
@@ -800,427 +1589,575 @@
 			drive-strength = <13>;
 		};
 
+		clock {
+			clk_32k: clk-32k {
+				rockchip,pins = <0 RK_PA0 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		edp {
+			edp_hpd: edp-hpd {
+				rockchip,pins =
+					<4 RK_PC7 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		gmac {
+			rgmii_pins: rgmii-pins {
+				rockchip,pins =
+					/* mac_txclk */
+					<3 RK_PC1 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_rxclk */
+					<3 RK_PB6 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_mdio */
+					<3 RK_PB5 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_txen */
+					<3 RK_PB4 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_clk */
+					<3 RK_PB3 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxdv */
+					<3 RK_PB1 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_mdc */
+					<3 RK_PB0 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxd1 */
+					<3 RK_PA7 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxd0 */
+					<3 RK_PA6 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_txd1 */
+					<3 RK_PA5 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_txd0 */
+					<3 RK_PA4 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_rxd3 */
+					<3 RK_PA3 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxd2 */
+					<3 RK_PA2 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_txd3 */
+					<3 RK_PA1 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_txd2 */
+					<3 RK_PA0 RK_FUNC_1 &pcfg_pull_none_13ma>;
+			};
+
+			rmii_pins: rmii-pins {
+				rockchip,pins =
+					/* mac_mdio */
+					<3 RK_PB5 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_txen */
+					<3 RK_PB4 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_clk */
+					<3 RK_PB3 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxer */
+					<3 RK_PB2 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxdv */
+					<3 RK_PB1 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_mdc */
+					<3 RK_PB0 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxd1 */
+					<3 RK_PA7 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_rxd0 */
+					<3 RK_PA6 RK_FUNC_1 &pcfg_pull_none>,
+					/* mac_txd1 */
+					<3 RK_PA5 RK_FUNC_1 &pcfg_pull_none_13ma>,
+					/* mac_txd0 */
+					<3 RK_PA4 RK_FUNC_1 &pcfg_pull_none_13ma>;
+			};
+		};
+
 		i2c0 {
 			i2c0_xfer: i2c0-xfer {
 				rockchip,pins =
-					<1 15 RK_FUNC_2 &pcfg_pull_none>,
-					<1 16 RK_FUNC_2 &pcfg_pull_none>;
+					<1 RK_PB7 RK_FUNC_2 &pcfg_pull_none>,
+					<1 RK_PC0 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c1 {
 			i2c1_xfer: i2c1-xfer {
 				rockchip,pins =
-					<4 2 RK_FUNC_1 &pcfg_pull_none>,
-					<4 1 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PA2 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA1 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c2 {
 			i2c2_xfer: i2c2-xfer {
 				rockchip,pins =
-					<2 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
-					<2 0 RK_FUNC_2 &pcfg_pull_none_12ma>;
+					<2 RK_PA1 RK_FUNC_2 &pcfg_pull_none_12ma>,
+					<2 RK_PA0 RK_FUNC_2 &pcfg_pull_none_12ma>;
 			};
 		};
 
 		i2c3 {
 			i2c3_xfer: i2c3-xfer {
 				rockchip,pins =
-					<4 17 RK_FUNC_1 &pcfg_pull_none>,
-					<4 16 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC1 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PC0 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c4 {
 			i2c4_xfer: i2c4-xfer {
 				rockchip,pins =
-					<1 12 RK_FUNC_1 &pcfg_pull_none>,
-					<1 11 RK_FUNC_1 &pcfg_pull_none>;
+					<1 RK_PB4 RK_FUNC_1 &pcfg_pull_none>,
+					<1 RK_PB3 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		i2c5 {
 			i2c5_xfer: i2c5-xfer {
 				rockchip,pins =
-					<3 11 RK_FUNC_2 &pcfg_pull_none>,
-					<3 10 RK_FUNC_2 &pcfg_pull_none>;
+					<3 RK_PB3 RK_FUNC_2 &pcfg_pull_none>,
+					<3 RK_PB2 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c6 {
 			i2c6_xfer: i2c6-xfer {
 				rockchip,pins =
-					<2 10 RK_FUNC_2 &pcfg_pull_none>,
-					<2 9 RK_FUNC_2 &pcfg_pull_none>;
+					<2 RK_PB2 RK_FUNC_2 &pcfg_pull_none>,
+					<2 RK_PB1 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c7 {
 			i2c7_xfer: i2c7-xfer {
 				rockchip,pins =
-					<2 8 RK_FUNC_2 &pcfg_pull_none>,
-					<2 7 RK_FUNC_2 &pcfg_pull_none>;
+					<2 RK_PB0 RK_FUNC_2 &pcfg_pull_none>,
+					<2 RK_PA7 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		i2c8 {
 			i2c8_xfer: i2c8-xfer {
 				rockchip,pins =
-					<1 21 RK_FUNC_1 &pcfg_pull_none>,
-					<1 20 RK_FUNC_1 &pcfg_pull_none>;
+					<1 RK_PC5 RK_FUNC_1 &pcfg_pull_none>,
+					<1 RK_PC4 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		i2s0 {
 			i2s0_8ch_bus: i2s0-8ch-bus {
 				rockchip,pins =
-					<3 24 RK_FUNC_1 &pcfg_pull_none>,
-					<3 25 RK_FUNC_1 &pcfg_pull_none>,
-					<3 26 RK_FUNC_1 &pcfg_pull_none>,
-					<3 27 RK_FUNC_1 &pcfg_pull_none>,
-					<3 28 RK_FUNC_1 &pcfg_pull_none>,
-					<3 29 RK_FUNC_1 &pcfg_pull_none>,
-					<3 30 RK_FUNC_1 &pcfg_pull_none>,
-					<3 31 RK_FUNC_1 &pcfg_pull_none>,
-					<4 0 RK_FUNC_1 &pcfg_pull_none>;
+					<3 RK_PD0 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD1 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD2 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD3 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD4 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD5 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD6 RK_FUNC_1 &pcfg_pull_none>,
+					<3 RK_PD7 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA0 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		i2s1 {
 			i2s1_2ch_bus: i2s1-2ch-bus {
 				rockchip,pins =
-					<4 3 RK_FUNC_1 &pcfg_pull_none>,
-					<4 4 RK_FUNC_1 &pcfg_pull_none>,
-					<4 5 RK_FUNC_1 &pcfg_pull_none>,
-					<4 6 RK_FUNC_1 &pcfg_pull_none>,
-					<4 7 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PA3 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA4 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA5 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA6 RK_FUNC_1 &pcfg_pull_none>,
+					<4 RK_PA7 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
-		gmac {
-			rgmii_pins: rgmii-pins {
+		sdio0 {
+			sdio0_bus1: sdio0-bus1 {
 				rockchip,pins =
-					/* mac_txclk */
-					<3 17 RK_FUNC_1 &pcfg_pull_none_13ma>,
-					/* mac_rxclk */
-					<3 14 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_mdio */
-					<3 13 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_txen */
-					<3 12 RK_FUNC_1 &pcfg_pull_none_13ma>,
-					/* mac_clk */
-					<3 11 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_rxdv */
-					<3 9 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_mdc */
-					<3 8 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_rxd1 */
-					<3 7 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_rxd0 */
-					<3 6 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_txd1 */
-					<3 5 RK_FUNC_1 &pcfg_pull_none_13ma>,
-					/* mac_txd0 */
-					<3 4 RK_FUNC_1 &pcfg_pull_none_13ma>,
-					/* mac_rxd3 */
-					<3 3 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_rxd2 */
-					<3 2 RK_FUNC_1 &pcfg_pull_none>,
-					/* mac_txd3 */
-					<3 1 RK_FUNC_1 &pcfg_pull_none_13ma>,
-					/* mac_txd2 */
-					<3 0 RK_FUNC_1 &pcfg_pull_none_13ma>;
+					<2 RK_PC4 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bus4: sdio0-bus4 {
+				rockchip,pins =
+					<2 RK_PC4 RK_FUNC_1 &pcfg_pull_up>,
+					<2 RK_PC5 RK_FUNC_1 &pcfg_pull_up>,
+					<2 RK_PC6 RK_FUNC_1 &pcfg_pull_up>,
+					<2 RK_PC7 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_cmd: sdio0-cmd {
+				rockchip,pins =
+					<2 RK_PD0 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_clk: sdio0-clk {
+				rockchip,pins =
+					<2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdio0_cd: sdio0-cd {
+				rockchip,pins =
+					<2 RK_PD2 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_pwr: sdio0-pwr {
+				rockchip,pins =
+					<2 RK_PD3 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bkpwr: sdio0-bkpwr {
+				rockchip,pins =
+					<2 RK_PD4 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_wp: sdio0-wp {
+				rockchip,pins =
+					<0 RK_PA3 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_int: sdio0-int {
+				rockchip,pins =
+					<0 RK_PA4 RK_FUNC_1 &pcfg_pull_up>;
 			};
 		};
 
 		sdmmc {
 			sdmmc_bus1: sdmmc-bus1 {
 				rockchip,pins =
-					<4 8 RK_FUNC_1 &pcfg_pull_up>;
+					<4 RK_PB0 RK_FUNC_1 &pcfg_pull_up>;
 			};
 
 			sdmmc_bus4: sdmmc-bus4 {
 				rockchip,pins =
-					<4 8 RK_FUNC_1 &pcfg_pull_up>,
-					<4 9 RK_FUNC_1 &pcfg_pull_up>,
-					<4 10 RK_FUNC_1 &pcfg_pull_up>,
-					<4 11 RK_FUNC_1 &pcfg_pull_up>;
+					<4 RK_PB0 RK_FUNC_1 &pcfg_pull_up>,
+					<4 RK_PB1 RK_FUNC_1 &pcfg_pull_up>,
+					<4 RK_PB2 RK_FUNC_1 &pcfg_pull_up>,
+					<4 RK_PB3 RK_FUNC_1 &pcfg_pull_up>;
 			};
 
 			sdmmc_clk: sdmmc-clk {
 				rockchip,pins =
-					<4 12 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PB4 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
 			sdmmc_cmd: sdmmc-cmd {
 				rockchip,pins =
-					<4 13 RK_FUNC_1 &pcfg_pull_up>;
+					<4 RK_PB5 RK_FUNC_1 &pcfg_pull_up>;
 			};
 
 			sdmmc_cd: sdmcc-cd {
 				rockchip,pins =
-					<0 7 RK_FUNC_1 &pcfg_pull_up>;
+					<0 RK_PA7 RK_FUNC_1 &pcfg_pull_up>;
 			};
 
 			sdmmc_wp: sdmmc-wp {
 				rockchip,pins =
-					<0 8 RK_FUNC_1 &pcfg_pull_up>;
+					<0 RK_PB0 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		sleep {
+			ap_pwroff: ap-pwroff {
+				rockchip,pins = <1 RK_PA5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			ddrio_pwroff: ddrio-pwroff {
+				rockchip,pins = <0 RK_PA1 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		spdif {
 			spdif_bus: spdif-bus {
 				rockchip,pins =
-					<4 21 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			spdif_bus_1: spdif-bus-1 {
+				rockchip,pins =
+					<3 RK_PC0 RK_FUNC_3 &pcfg_pull_none>;
 			};
 		};
 
 		spi0 {
 			spi0_clk: spi0-clk {
 				rockchip,pins =
-					<3 6 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA6 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi0_cs0: spi0-cs0 {
 				rockchip,pins =
-					<3 7 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA7 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi0_cs1: spi0-cs1 {
 				rockchip,pins =
-					<3 8 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PB0 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi0_tx: spi0-tx {
 				rockchip,pins =
-					<3 5 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA5 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi0_rx: spi0-rx {
 				rockchip,pins =
-					<3 4 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA4 RK_FUNC_2 &pcfg_pull_up>;
 			};
 		};
 
 		spi1 {
 			spi1_clk: spi1-clk {
 				rockchip,pins =
-					<1 9 RK_FUNC_2 &pcfg_pull_up>;
+					<1 RK_PB1 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi1_cs0: spi1-cs0 {
 				rockchip,pins =
-					<1 10 RK_FUNC_2 &pcfg_pull_up>;
+					<1 RK_PB2 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi1_rx: spi1-rx {
 				rockchip,pins =
-					<1 7 RK_FUNC_2 &pcfg_pull_up>;
+					<1 RK_PA7 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi1_tx: spi1-tx {
 				rockchip,pins =
-					<1 8 RK_FUNC_2 &pcfg_pull_up>;
+					<1 RK_PB0 RK_FUNC_2 &pcfg_pull_up>;
 			};
 		};
 
 		spi2 {
 			spi2_clk: spi2-clk {
 				rockchip,pins =
-					<2 11 RK_FUNC_1 &pcfg_pull_up>;
+					<2 RK_PB3 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi2_cs0: spi2-cs0 {
 				rockchip,pins =
-					<2 12 RK_FUNC_1 &pcfg_pull_up>;
+					<2 RK_PB4 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi2_rx: spi2-rx {
 				rockchip,pins =
-					<2 9 RK_FUNC_1 &pcfg_pull_up>;
+					<2 RK_PB1 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi2_tx: spi2-tx {
 				rockchip,pins =
-					<2 10 RK_FUNC_1 &pcfg_pull_up>;
+					<2 RK_PB2 RK_FUNC_1 &pcfg_pull_up>;
 			};
 		};
 
 		spi3 {
 			spi3_clk: spi3-clk {
 				rockchip,pins =
-					<1 17 RK_FUNC_1 &pcfg_pull_up>;
+					<1 RK_PC1 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi3_cs0: spi3-cs0 {
 				rockchip,pins =
-					<1 18 RK_FUNC_1 &pcfg_pull_up>;
+					<1 RK_PC2 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi3_rx: spi3-rx {
 				rockchip,pins =
-					<1 15 RK_FUNC_1 &pcfg_pull_up>;
+					<1 RK_PB7 RK_FUNC_1 &pcfg_pull_up>;
 			};
 			spi3_tx: spi3-tx {
 				rockchip,pins =
-					<1 16 RK_FUNC_1 &pcfg_pull_up>;
+					<1 RK_PC0 RK_FUNC_1 &pcfg_pull_up>;
 			};
 		};
 
 		spi4 {
 			spi4_clk: spi4-clk {
 				rockchip,pins =
-					<3 2 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA2 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi4_cs0: spi4-cs0 {
 				rockchip,pins =
-					<3 3 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA3 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi4_rx: spi4-rx {
 				rockchip,pins =
-					<3 0 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA0 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi4_tx: spi4-tx {
 				rockchip,pins =
-					<3 1 RK_FUNC_2 &pcfg_pull_up>;
+					<3 RK_PA1 RK_FUNC_2 &pcfg_pull_up>;
 			};
 		};
 
 		spi5 {
 			spi5_clk: spi5-clk {
 				rockchip,pins =
-					<2 22 RK_FUNC_2 &pcfg_pull_up>;
+					<2 RK_PC6 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi5_cs0: spi5-cs0 {
 				rockchip,pins =
-					<2 23 RK_FUNC_2 &pcfg_pull_up>;
+					<2 RK_PC7 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi5_rx: spi5-rx {
 				rockchip,pins =
-					<2 20 RK_FUNC_2 &pcfg_pull_up>;
+					<2 RK_PC4 RK_FUNC_2 &pcfg_pull_up>;
 			};
 			spi5_tx: spi5-tx {
 				rockchip,pins =
-					<2 21 RK_FUNC_2 &pcfg_pull_up>;
+					<2 RK_PC5 RK_FUNC_2 &pcfg_pull_up>;
 			};
 		};
 
+		tsadc {
+			otp_gpio: otp-gpio {
+				rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			otp_out: otp-out {
+				rockchip,pins = <1 RK_PA6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
 		uart0 {
 			uart0_xfer: uart0-xfer {
 				rockchip,pins =
-					<2 16 RK_FUNC_1 &pcfg_pull_up>,
-					<2 17 RK_FUNC_1 &pcfg_pull_none>;
+					<2 RK_PC0 RK_FUNC_1 &pcfg_pull_up>,
+					<2 RK_PC1 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
 			uart0_cts: uart0-cts {
 				rockchip,pins =
-					<2 18 RK_FUNC_1 &pcfg_pull_none>;
+					<2 RK_PC2 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
 			uart0_rts: uart0-rts {
 				rockchip,pins =
-					<2 19 RK_FUNC_1 &pcfg_pull_none>;
+					<2 RK_PC3 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		uart1 {
 			uart1_xfer: uart1-xfer {
 				rockchip,pins =
-					<3 12 RK_FUNC_2 &pcfg_pull_up>,
-					<3 13 RK_FUNC_2 &pcfg_pull_none>;
+					<3 RK_PB4 RK_FUNC_2 &pcfg_pull_up>,
+					<3 RK_PB5 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		uart2a {
 			uart2a_xfer: uart2a-xfer {
 				rockchip,pins =
-					<4 8 RK_FUNC_2 &pcfg_pull_up>,
-					<4 9 RK_FUNC_2 &pcfg_pull_none>;
+					<4 RK_PB0 RK_FUNC_2 &pcfg_pull_up>,
+					<4 RK_PB1 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		uart2b {
 			uart2b_xfer: uart2b-xfer {
 				rockchip,pins =
-					<4 16 RK_FUNC_2 &pcfg_pull_up>,
-					<4 17 RK_FUNC_2 &pcfg_pull_none>;
+					<4 RK_PC0 RK_FUNC_2 &pcfg_pull_up>,
+					<4 RK_PC1 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		uart2c {
 			uart2c_xfer: uart2c-xfer {
 				rockchip,pins =
-					<4 19 RK_FUNC_1 &pcfg_pull_up>,
-					<4 20 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC3 RK_FUNC_1 &pcfg_pull_up>,
+					<4 RK_PC4 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		uart3 {
 			uart3_xfer: uart3-xfer {
 				rockchip,pins =
-					<3 14 RK_FUNC_2 &pcfg_pull_up>,
-					<3 15 RK_FUNC_2 &pcfg_pull_none>;
+					<3 RK_PB6 RK_FUNC_2 &pcfg_pull_up>,
+					<3 RK_PB7 RK_FUNC_2 &pcfg_pull_none>;
 			};
 
 			uart3_cts: uart3-cts {
 				rockchip,pins =
-					<3 18 RK_FUNC_2 &pcfg_pull_none>;
+					<3 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
 			};
 
 			uart3_rts: uart3-rts {
 				rockchip,pins =
-					<3 19 RK_FUNC_2 &pcfg_pull_none>;
+					<3 RK_PC3 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		uart4 {
 			uart4_xfer: uart4-xfer {
 				rockchip,pins =
-					<1 7 RK_FUNC_1 &pcfg_pull_up>,
-					<1 8 RK_FUNC_1 &pcfg_pull_none>;
+					<1 RK_PA7 RK_FUNC_1 &pcfg_pull_up>,
+					<1 RK_PB0 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		uarthdcp {
 			uarthdcp_xfer: uarthdcp-xfer {
 				rockchip,pins =
-					<4 21 RK_FUNC_2 &pcfg_pull_up>,
-					<4 22 RK_FUNC_2 &pcfg_pull_none>;
+					<4 RK_PC5 RK_FUNC_2 &pcfg_pull_up>,
+					<4 RK_PC6 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		pwm0 {
 			pwm0_pin: pwm0-pin {
 				rockchip,pins =
-					<4 18 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC2 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
 			vop0_pwm_pin: vop0-pwm-pin {
 				rockchip,pins =
-					<4 18 RK_FUNC_2 &pcfg_pull_none>;
+					<4 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
 			};
 		};
 
 		pwm1 {
 			pwm1_pin: pwm1-pin {
 				rockchip,pins =
-					<4 22 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC6 RK_FUNC_1 &pcfg_pull_none>;
 			};
 
 			vop1_pwm_pin: vop1-pwm-pin {
 				rockchip,pins =
-					<4 18 RK_FUNC_3 &pcfg_pull_none>;
+					<4 RK_PC2 RK_FUNC_3 &pcfg_pull_none>;
 			};
 		};
 
 		pwm2 {
 			pwm2_pin: pwm2-pin {
 				rockchip,pins =
-					<1 19 RK_FUNC_1 &pcfg_pull_none>;
+					<1 RK_PC3 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		pwm3a {
 			pwm3a_pin: pwm3a-pin {
 				rockchip,pins =
-					<0 6 RK_FUNC_1 &pcfg_pull_none>;
+					<0 RK_PA6 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
 		pwm3b {
 			pwm3b_pin: pwm3b-pin {
 				rockchip,pins =
+					<1 RK_PB6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		hdmi {
+			hdmi_i2c_xfer: hdmi-i2c-xfer {
+				rockchip,pins =
-					<1 14 RK_FUNC_1 &pcfg_pull_none>;
+					<4 RK_PC1 RK_FUNC_3 &pcfg_pull_none>,
+					<4 RK_PC0 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			hdmi_cec: hdmi-cec {
+				rockchip,pins =
+					<4 RK_PC7 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
+
+		pcie {
+			pcie_clkreqn: pci-clkreqn {
+				rockchip,pins =
+					<2 RK_PD2 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			pcie_clkreqnb: pci-clkreqnb {
+				rockchip,pins =
+					<4 RK_PD0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			pcie_clkreqn_cpm: pci-clkreqn-cpm {
+				rockchip,pins =
+					<2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			pcie_clkreqnb_cpm: pci-clkreqnb-cpm {
+				rockchip,pins =
+					<4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+		};
+
 	};
 };
diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h
index 8d7bc9a..7346876 100644
--- a/arch/arm/include/asm/arch-rockchip/boot0.h
+++ b/arch/arm/include/asm/arch-rockchip/boot0.h
@@ -16,3 +16,7 @@
 	.space 0x4         /* space for the 'RK33' */
 #endif
 	b reset
+
+#if defined(CONFIG_ROCKCHIP_RK3399) && defined(CONFIG_SPL_BUILD)
+	.space CONFIG_ROCKCHIP_SPL_RESERVE_IRAM	/* space for the ATF data */
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3288.h b/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
index 1a7c819..7d56b8c 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
@@ -824,4 +824,66 @@
 		(0x7f << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT),
 };
 
+/* GRF_SOC_CON6 */
+enum GRF_SOC_CON6 {
+	RK3288_HDMI_EDP_SEL_SHIFT = 0xf,
+	RK3288_HDMI_EDP_SEL_MASK =
+		1 << RK3288_HDMI_EDP_SEL_SHIFT,
+	RK3288_HDMI_EDP_SEL_EDP = 0,
+	RK3288_HDMI_EDP_SEL_HDMI,
+
+	RK3288_DSI0_DPICOLORM_SHIFT = 0x8,
+	RK3288_DSI0_DPICOLORM_MASK =
+		1 << RK3288_DSI0_DPICOLORM_SHIFT,
+
+	RK3288_DSI0_DPISHUTDN_SHIFT = 0x7,
+	RK3288_DSI0_DPISHUTDN_MASK =
+		1 << RK3288_DSI0_DPISHUTDN_SHIFT,
+
+	RK3288_DSI0_LCDC_SEL_SHIFT = 0x6,
+	RK3288_DSI0_LCDC_SEL_MASK =
+		1 << RK3288_DSI0_LCDC_SEL_SHIFT,
+	RK3288_DSI0_LCDC_SEL_BIG = 0,
+	RK3288_DSI0_LCDC_SEL_LIT = 1,
+
+	RK3288_EDP_LCDC_SEL_SHIFT = 0x5,
+	RK3288_EDP_LCDC_SEL_MASK =
+		1 << RK3288_EDP_LCDC_SEL_SHIFT,
+	RK3288_EDP_LCDC_SEL_BIG = 0,
+	RK3288_EDP_LCDC_SEL_LIT = 1,
+
+	RK3288_HDMI_LCDC_SEL_SHIFT = 0x4,
+	RK3288_HDMI_LCDC_SEL_MASK =
+		1 << RK3288_HDMI_LCDC_SEL_SHIFT,
+	RK3288_HDMI_LCDC_SEL_BIG = 0,
+	RK3288_HDMI_LCDC_SEL_LIT = 1,
+
+	RK3288_LVDS_LCDC_SEL_SHIFT = 0x3,
+	RK3288_LVDS_LCDC_SEL_MASK =
+		1 << RK3288_LVDS_LCDC_SEL_SHIFT,
+	RK3288_LVDS_LCDC_SEL_BIG = 0,
+	RK3288_LVDS_LCDC_SEL_LIT = 1,
+};
+
+/* RK3288_SOC_CON8 */
+enum GRF_SOC_CON8 {
+	RK3288_DPHY_TX0_RXMODE_SHIFT = 4,
+	RK3288_DPHY_TX0_RXMODE_MASK =
+	   0xf << RK3288_DPHY_TX0_RXMODE_SHIFT,
+	RK3288_DPHY_TX0_RXMODE_EN = 0xf,
+	RK3288_DPHY_TX0_RXMODE_DIS = 0,
+
+	RK3288_DPHY_TX0_TXSTOPMODE_SHIFT = 0x8,
+	RK3288_DPHY_TX0_TXSTOPMODE_MASK =
+	   0xf << RK3288_DPHY_TX0_TXSTOPMODE_SHIFT,
+	RK3288_DPHY_TX0_TXSTOPMODE_EN = 0xf,
+	RK3288_DPHY_TX0_TXSTOPMODE_DIS = 0,
+
+	RK3288_DPHY_TX0_TURNREQUEST_SHIFT = 0,
+	RK3288_DPHY_TX0_TURNREQUEST_MASK =
+	   0xf << RK3288_DPHY_TX0_TURNREQUEST_SHIFT,
+	RK3288_DPHY_TX0_TURNREQUEST_EN = 0xf,
+	RK3288_DPHY_TX0_TURNREQUEST_DIS = 0,
+};
+
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
index c424753..eda9956 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
@@ -151,10 +151,11 @@
 	u32 gpio2_sr[3][4];
 	u32 reserved23[4];
 	u32 gpio2_smt[3][4];
-	u32 reserved24[(0xe130 - 0xe0ec)/4 - 1];
-	u32 gpio4b_e01;
-	u32 gpio4b_e2;
-	u32 reserved24a[(0xe200 - 0xe134)/4 - 1];
+	u32 reserved24[(0xe100 - 0xe0ec)/4 - 1];
+	u32 gpio2_e[4];
+	u32 gpio3_e[7];
+	u32 gpio4_e[5];
+	u32 reserved24a[(0xe200 - 0xe13c)/4 - 1];
 	u32 soc_con0;
 	u32 soc_con1;
 	u32 soc_con2;
@@ -344,6 +345,18 @@
 	GRF_GPIO2C1_SEL_SHIFT   = 2,
 	GRF_GPIO2C1_SEL_MASK    = 3 << GRF_GPIO2C1_SEL_SHIFT,
 	GRF_UART0BT_SOUT        = 1,
+	GRF_GPIO2C4_SEL_SHIFT   = 8,
+	GRF_GPIO2C4_SEL_MASK    = 3 << GRF_GPIO2C4_SEL_SHIFT,
+	GRF_SPI5EXPPLUS_RXD     = 2,
+	GRF_GPIO2C5_SEL_SHIFT   = 10,
+	GRF_GPIO2C5_SEL_MASK    = 3 << GRF_GPIO2C5_SEL_SHIFT,
+	GRF_SPI5EXPPLUS_TXD     = 2,
+	GRF_GPIO2C6_SEL_SHIFT   = 12,
+	GRF_GPIO2C6_SEL_MASK    = 3 << GRF_GPIO2C6_SEL_SHIFT,
+	GRF_SPI5EXPPLUS_CLK     = 2,
+	GRF_GPIO2C7_SEL_SHIFT   = 14,
+	GRF_GPIO2C7_SEL_MASK    = 3 << GRF_GPIO2C7_SEL_SHIFT,
+	GRF_SPI5EXPPLUS_CSN0    = 2,
 
 	/* GRF_GPIO3A_IOMUX */
 	GRF_GPIO3A0_SEL_SHIFT   = 0,
@@ -427,9 +440,11 @@
 	GRF_GPIO4C0_SEL_SHIFT   = 0,
 	GRF_GPIO4C0_SEL_MASK    = 3 << GRF_GPIO4C0_SEL_SHIFT,
 	GRF_UART2DGBB_SIN       = 2,
+	GRF_HDMII2C_SCL         = 3,
 	GRF_GPIO4C1_SEL_SHIFT   = 2,
 	GRF_GPIO4C1_SEL_MASK    = 3 << GRF_GPIO4C1_SEL_SHIFT,
 	GRF_UART2DGBB_SOUT      = 2,
+	GRF_HDMII2C_SDA         = 3,
 	GRF_GPIO4C2_SEL_SHIFT   = 4,
 	GRF_GPIO4C2_SEL_MASK    = 3 << GRF_GPIO4C2_SEL_SHIFT,
 	GRF_PWM_0               = 1,
@@ -443,10 +458,99 @@
 	GRF_GPIO4C6_SEL_MASK    = 3 << GRF_GPIO4C6_SEL_SHIFT,
 	GRF_PWM_1               = 1,
 
+	/* GRF_GPIO3A_E01 */
+	GRF_GPIO3A0_E_SHIFT = 0,
+	GRF_GPIO3A0_E_MASK = 7 << GRF_GPIO3A0_E_SHIFT,
+	GRF_GPIO3A1_E_SHIFT = 3,
+	GRF_GPIO3A1_E_MASK = 7 << GRF_GPIO3A1_E_SHIFT,
+	GRF_GPIO3A2_E_SHIFT = 6,
+	GRF_GPIO3A2_E_MASK = 7 << GRF_GPIO3A2_E_SHIFT,
+	GRF_GPIO3A3_E_SHIFT = 9,
+	GRF_GPIO3A3_E_MASK = 7 << GRF_GPIO3A3_E_SHIFT,
+	GRF_GPIO3A4_E_SHIFT = 12,
+	GRF_GPIO3A4_E_MASK = 7 << GRF_GPIO3A4_E_SHIFT,
+	GRF_GPIO3A5_E0_SHIFT = 15,
+	GRF_GPIO3A5_E0_MASK = 1 << GRF_GPIO3A5_E0_SHIFT,
+
+	/*  GRF_GPIO3A_E2 */
+	GRF_GPIO3A5_E12_SHIFT = 0,
+	GRF_GPIO3A5_E12_MASK = 3 << GRF_GPIO3A5_E12_SHIFT,
+	GRF_GPIO3A6_E_SHIFT = 2,
+	GRF_GPIO3A6_E_MASK = 7 << GRF_GPIO3A6_E_SHIFT,
+	GRF_GPIO3A7_E_SHIFT = 5,
+	GRF_GPIO3A7_E_MASK = 7 << GRF_GPIO3A7_E_SHIFT,
+
+	/* GRF_GPIO3B_E01 */
+	GRF_GPIO3B0_E_SHIFT = 0,
+	GRF_GPIO3B0_E_MASK = 7 << GRF_GPIO3B0_E_SHIFT,
+	GRF_GPIO3B1_E_SHIFT = 3,
+	GRF_GPIO3B1_E_MASK = 7 << GRF_GPIO3B1_E_SHIFT,
+	GRF_GPIO3B2_E_SHIFT = 6,
+	GRF_GPIO3B2_E_MASK = 7 << GRF_GPIO3B2_E_SHIFT,
+	GRF_GPIO3B3_E_SHIFT = 9,
+	GRF_GPIO3B3_E_MASK = 7 << GRF_GPIO3B3_E_SHIFT,
+	GRF_GPIO3B4_E_SHIFT = 12,
+	GRF_GPIO3B4_E_MASK = 7 << GRF_GPIO3B4_E_SHIFT,
+	GRF_GPIO3B5_E0_SHIFT = 15,
+	GRF_GPIO3B5_E0_MASK = 1 << GRF_GPIO3B5_E0_SHIFT,
+
+	/*  GRF_GPIO3A_E2 */
+	GRF_GPIO3B5_E12_SHIFT = 0,
+	GRF_GPIO3B5_E12_MASK = 3 << GRF_GPIO3B5_E12_SHIFT,
+	GRF_GPIO3B6_E_SHIFT = 2,
+	GRF_GPIO3B6_E_MASK = 7 << GRF_GPIO3B6_E_SHIFT,
+	GRF_GPIO3B7_E_SHIFT = 5,
+	GRF_GPIO3B7_E_MASK = 7 << GRF_GPIO3B7_E_SHIFT,
+
+	/* GRF_GPIO3C_E01 */
+	GRF_GPIO3C0_E_SHIFT = 0,
+	GRF_GPIO3C0_E_MASK = 7 << GRF_GPIO3C0_E_SHIFT,
+	GRF_GPIO3C1_E_SHIFT = 3,
+	GRF_GPIO3C1_E_MASK = 7 << GRF_GPIO3C1_E_SHIFT,
+	GRF_GPIO3C2_E_SHIFT = 6,
+	GRF_GPIO3C2_E_MASK = 7 << GRF_GPIO3C2_E_SHIFT,
+	GRF_GPIO3C3_E_SHIFT = 9,
+	GRF_GPIO3C3_E_MASK = 7 << GRF_GPIO3C3_E_SHIFT,
+	GRF_GPIO3C4_E_SHIFT = 12,
+	GRF_GPIO3C4_E_MASK = 7 << GRF_GPIO3C4_E_SHIFT,
+	GRF_GPIO3C5_E0_SHIFT = 15,
+	GRF_GPIO3C5_E0_MASK = 1 << GRF_GPIO3C5_E0_SHIFT,
+
+	/*  GRF_GPIO3C_E2 */
+	GRF_GPIO3C5_E12_SHIFT = 0,
+	GRF_GPIO3C5_E12_MASK = 3 << GRF_GPIO3C5_E12_SHIFT,
+	GRF_GPIO3C6_E_SHIFT = 2,
+	GRF_GPIO3C6_E_MASK = 7 << GRF_GPIO3C6_E_SHIFT,
+	GRF_GPIO3C7_E_SHIFT = 5,
+	GRF_GPIO3C7_E_MASK = 7 << GRF_GPIO3C7_E_SHIFT,
+
 	/* GRF_SOC_CON7 */
-	GRF_UART_DBG_SEL_SHIFT	= 10,
-	GRF_UART_DBG_SEL_MASK	= 3 << GRF_UART_DBG_SEL_SHIFT,
-	GRF_UART_DBG_SEL_C	= 2,
+	GRF_UART_DBG_SEL_SHIFT  = 10,
+	GRF_UART_DBG_SEL_MASK   = 3 << GRF_UART_DBG_SEL_SHIFT,
+	GRF_UART_DBG_SEL_C      = 2,
+
+	/* GRF_SOC_CON20 */
+	GRF_DSI0_VOP_SEL_SHIFT  = 0,
+	GRF_DSI0_VOP_SEL_MASK   = 1 << GRF_DSI0_VOP_SEL_SHIFT,
+	GRF_DSI0_VOP_SEL_B      = 0,
+	GRF_DSI0_VOP_SEL_L      = 1,
+
+	/* GRF_SOC_CON22 */
+	GRF_DPHY_TX0_RXMODE_SHIFT = 0,
+	GRF_DPHY_TX0_RXMODE_MASK  = 0xf << GRF_DPHY_TX0_RXMODE_SHIFT,
+	GRF_DPHY_TX0_RXMODE_EN    = 0xb,
+	GRF_DPHY_TX0_RXMODE_DIS   = 0,
+
+	GRF_DPHY_TX0_TXSTOPMODE_SHIFT = 4,
+	GRF_DPHY_TX0_TXSTOPMODE_MASK  = 0xf0 << GRF_DPHY_TX0_TXSTOPMODE_SHIFT,
+	GRF_DPHY_TX0_TXSTOPMODE_EN    = 0xc,
+	GRF_DPHY_TX0_TXSTOPMODE_DIS   = 0,
+
+	GRF_DPHY_TX0_TURNREQUEST_SHIFT = 12,
+	GRF_DPHY_TX0_TURNREQUEST_MASK  =
+		0xf000 << GRF_DPHY_TX0_TURNREQUEST_SHIFT,
+	GRF_DPHY_TX0_TURNREQUEST_EN    = 0x1,
+	GRF_DPHY_TX0_TURNREQUEST_DIS   = 0,
 
 	/*  PMUGRF_GPIO0A_IOMUX */
 	PMUGRF_GPIO0A6_SEL_SHIFT        = 12,
diff --git a/arch/arm/include/asm/arch-rockchip/periph.h b/arch/arm/include/asm/arch-rockchip/periph.h
index 239a274..8018d47 100644
--- a/arch/arm/include/asm/arch-rockchip/periph.h
+++ b/arch/arm/include/asm/arch-rockchip/periph.h
@@ -27,6 +27,9 @@
 	PERIPH_ID_SPI0,
 	PERIPH_ID_SPI1,
 	PERIPH_ID_SPI2,
+	PERIPH_ID_SPI3,
+	PERIPH_ID_SPI4,
+	PERIPH_ID_SPI5,
 	PERIPH_ID_UART0,
 	PERIPH_ID_UART1,
 	PERIPH_ID_UART2,
diff --git a/arch/arm/include/asm/arch-rockchip/rockchip_mipi_dsi.h b/arch/arm/include/asm/arch-rockchip/rockchip_mipi_dsi.h
new file mode 100644
index 0000000..d7f79c5
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/rockchip_mipi_dsi.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ * author: Eric Gao <eric.gao@rock-chips.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef ROCKCHIP_MIPI_DSI_H
+#define ROCKCHIP_MIPI_DSI_H
+
+/*
+ * All these mipi controller register declaration provide reg address offset,
+ * bits width, bit offset for a specified register bits. With these message, we
+ * can set or clear every bits individually for a 32bit widthregister. We use
+ * DSI_HOST_BITS macro definition to combinat these message using the following
+ * format: val(32bit) = addr(16bit) | width(8bit) | offest(8bit)
+ * For example:
+ *    #define SHUTDOWNZ           DSI_HOST_BITS(0x004, 1, 0)
+ * means SHUTDOWNZ is a signal reg bit with bit offset qual 0,and it's reg addr
+ * offset is 0x004.The conbinat result  = (0x004 << 16) | (1 << 8) | 0
+ */
+#define ADDR_SHIFT 16
+#define BITS_SHIFT 8
+#define OFFSET_SHIFT 0
+#define DSI_HOST_BITS(addr, bits, bit_offset) \
+((addr << ADDR_SHIFT) | (bits << BITS_SHIFT) | (bit_offset << OFFSET_SHIFT))
+
+/* DWC_DSI_VERSION_0x3133302A */
+#define VERSION				DSI_HOST_BITS(0x000, 32, 0)
+#define SHUTDOWNZ			DSI_HOST_BITS(0x004, 1, 0)
+#define TO_CLK_DIVISION		DSI_HOST_BITS(0x008, 8, 8)
+#define TX_ESC_CLK_DIVISION	DSI_HOST_BITS(0x008, 8, 0)
+#define DPI_VCID			DSI_HOST_BITS(0x00c, 2, 0)
+#define EN18_LOOSELY		DSI_HOST_BITS(0x010, 1, 8)
+#define DPI_COLOR_CODING	DSI_HOST_BITS(0x010, 4, 0)
+#define COLORM_ACTIVE_LOW	DSI_HOST_BITS(0x014, 1, 4)
+#define SHUTD_ACTIVE_LOW	DSI_HOST_BITS(0x014, 1, 3)
+#define HSYNC_ACTIVE_LOW	DSI_HOST_BITS(0x014, 1, 2)
+#define VSYNC_ACTIVE_LOW	DSI_HOST_BITS(0x014, 1, 1)
+#define DATAEN_ACTIVE_LOW	DSI_HOST_BITS(0x014, 1, 0)
+#define OUTVACT_LPCMD_TIME	DSI_HOST_BITS(0x018, 8, 16)
+#define INVACT_LPCMD_TIME	DSI_HOST_BITS(0x018, 8, 0)
+#define CRC_RX_EN			DSI_HOST_BITS(0x02c, 1, 4)
+#define ECC_RX_EN			DSI_HOST_BITS(0x02c, 1, 3)
+#define BTA_EN				DSI_HOST_BITS(0x02c, 1, 2)
+#define EOTP_RX_EN			DSI_HOST_BITS(0x02c, 1, 1)
+#define EOTP_TX_EN			DSI_HOST_BITS(0x02c, 1, 0)
+#define GEN_VID_RX			DSI_HOST_BITS(0x030, 2, 0)
+#define CMD_VIDEO_MODE		DSI_HOST_BITS(0x034, 1, 0)
+#define VPG_ORIENTATION		DSI_HOST_BITS(0x038, 1, 24)
+#define VPG_MODE			DSI_HOST_BITS(0x038, 1, 20)
+#define VPG_EN				DSI_HOST_BITS(0x038, 1, 16)
+#define LP_CMD_EN			DSI_HOST_BITS(0x038, 1, 15)
+#define FRAME_BTA_ACK_EN	DSI_HOST_BITS(0x038, 1, 14)
+#define LP_HFP_EN			DSI_HOST_BITS(0x038, 1, 13)
+#define LP_HBP_EN			DSI_HOST_BITS(0x038, 1, 12)
+#define LP_VACT_EN			DSI_HOST_BITS(0x038, 1, 11)
+#define LP_VFP_EN			DSI_HOST_BITS(0x038, 1, 10)
+#define LP_VBP_EN			DSI_HOST_BITS(0x038, 1, 9)
+#define LP_VSA_EN			DSI_HOST_BITS(0x038, 1, 8)
+#define VID_MODE_TYPE		DSI_HOST_BITS(0x038, 2, 0)
+#define VID_PKT_SIZE		DSI_HOST_BITS(0x03c, 14, 0)
+#define NUM_CHUNKS			DSI_HOST_BITS(0x040, 13, 0)
+#define NULL_PKT_SIZE		DSI_HOST_BITS(0x044, 13, 0)
+#define VID_HSA_TIME		DSI_HOST_BITS(0x048, 12, 0)
+#define VID_HBP_TIME		DSI_HOST_BITS(0x04c, 12, 0)
+#define VID_HLINE_TIME		DSI_HOST_BITS(0x050, 15, 0)
+#define VID_VSA_LINES		DSI_HOST_BITS(0x054, 10, 0)
+#define VID_VBP_LINES		DSI_HOST_BITS(0x058, 10, 0)
+#define VID_VFP_LINES		DSI_HOST_BITS(0x05c, 10, 0)
+#define VID_ACTIVE_LINES	DSI_HOST_BITS(0x060, 14, 0)
+#define EDPI_CMD_SIZE		DSI_HOST_BITS(0x064, 16, 0)
+#define MAX_RD_PKT_SIZE		DSI_HOST_BITS(0x068, 1, 24)
+#define DCS_LW_TX			DSI_HOST_BITS(0x068, 1, 19)
+#define DCS_SR_0P_TX		DSI_HOST_BITS(0x068, 1, 18)
+#define DCS_SW_1P_TX		DSI_HOST_BITS(0x068, 1, 17)
+#define DCS_SW_0P_TX		DSI_HOST_BITS(0x068, 1, 16)
+#define GEN_LW_TX			DSI_HOST_BITS(0x068, 1, 14)
+#define GEN_SR_2P_TX		DSI_HOST_BITS(0x068, 1, 13)
+#define GEN_SR_1P_TX		DSI_HOST_BITS(0x068, 1, 12)
+#define GEN_SR_0P_TX		DSI_HOST_BITS(0x068, 1, 11)
+#define GEN_SW_2P_TX		DSI_HOST_BITS(0x068, 1, 10)
+#define GEN_SW_1P_TX		DSI_HOST_BITS(0x068, 1, 9)
+#define GEN_SW_0P_TX		DSI_HOST_BITS(0x068, 1, 8)
+#define ACK_RQST_EN			DSI_HOST_BITS(0x068, 1, 1)
+#define TEAR_FX_EN			DSI_HOST_BITS(0x068, 1, 0)
+#define GEN_WC_MSBYTE		DSI_HOST_BITS(0x06c, 14, 16)
+#define GEN_WC_LSBYTE		DSI_HOST_BITS(0x06c, 8, 8)
+#define GEN_VC				DSI_HOST_BITS(0x06c, 2, 6)
+#define GEN_DT				DSI_HOST_BITS(0x06c, 6, 0)
+#define GEN_PLD_DATA		DSI_HOST_BITS(0x070, 32, 0)
+#define GEN_RD_CMD_BUSY		DSI_HOST_BITS(0x074, 1, 6)
+#define GEN_PLD_R_FULL		DSI_HOST_BITS(0x074, 1, 5)
+#define GEN_PLD_R_EMPTY		DSI_HOST_BITS(0x074, 1, 4)
+#define GEN_PLD_W_FULL		DSI_HOST_BITS(0x074, 1, 3)
+#define GEN_PLD_W_EMPTY		DSI_HOST_BITS(0x074, 1, 2)
+#define GEN_CMD_FULL		DSI_HOST_BITS(0x074, 1, 1)
+#define GEN_CMD_EMPTY		DSI_HOST_BITS(0x074, 1, 0)
+#define HSTX_TO_CNT			DSI_HOST_BITS(0x078, 16, 16)
+#define LPRX_TO_CNT			DSI_HOST_BITS(0x078, 16, 0)
+#define HS_RD_TO_CNT		DSI_HOST_BITS(0x07c, 16, 0)
+#define LP_RD_TO_CNT		DSI_HOST_BITS(0x080, 16, 0)
+#define PRESP_TO_MODE		DSI_HOST_BITS(0x084, 1, 24)
+#define HS_WR_TO_CNT		DSI_HOST_BITS(0x084, 16, 0)
+#define LP_WR_TO_CNT		DSI_HOST_BITS(0x088, 16, 0)
+#define BTA_TO_CNT			DSI_HOST_BITS(0x08c, 16, 0)
+#define AUTO_CLKLANE_CTRL	DSI_HOST_BITS(0x094, 1, 1)
+#define PHY_TXREQUESTCLKHS	DSI_HOST_BITS(0x094, 1, 0)
+#define PHY_HS2LP_TIME_CLK_LANE	DSI_HOST_BITS(0x098, 10, 16)
+#define PHY_HS2HS_TIME_CLK_LANE	DSI_HOST_BITS(0x098, 10, 0)
+#define PHY_HS2LP_TIME		DSI_HOST_BITS(0x09c, 8, 24)
+#define PHY_LP2HS_TIME		DSI_HOST_BITS(0x09c, 8, 16)
+#define MAX_RD_TIME			DSI_HOST_BITS(0x09c, 15, 0)
+#define PHY_FORCEPLL		DSI_HOST_BITS(0x0a0, 1, 3)
+#define PHY_ENABLECLK		DSI_HOST_BITS(0x0a0, 1, 2)
+#define PHY_RSTZ			DSI_HOST_BITS(0x0a0, 1, 1)
+#define PHY_SHUTDOWNZ		DSI_HOST_BITS(0x0a0, 1, 0)
+#define PHY_STOP_WAIT_TIME	DSI_HOST_BITS(0x0a4, 8, 8)
+#define N_LANES				DSI_HOST_BITS(0x0a4, 2, 0)
+#define PHY_TXEXITULPSLAN	DSI_HOST_BITS(0x0a8, 1, 3)
+#define PHY_TXREQULPSLAN	DSI_HOST_BITS(0x0a8, 1, 2)
+#define PHY_TXEXITULPSCLK	DSI_HOST_BITS(0x0a8, 1, 1)
+#define PHY_TXREQULPSCLK	DSI_HOST_BITS(0x0a8, 1, 0)
+#define PHY_TX_TRIGGERS		DSI_HOST_BITS(0x0ac, 4, 0)
+#define PHYSTOPSTATECLKLANE	DSI_HOST_BITS(0x0b0, 1, 2)
+#define PHYLOCK				DSI_HOST_BITS(0x0b0, 1, 0)
+#define PHY_TESTCLK			DSI_HOST_BITS(0x0b4, 1, 1)
+#define PHY_TESTCLR			DSI_HOST_BITS(0x0b4, 1, 0)
+#define PHY_TESTEN			DSI_HOST_BITS(0x0b8, 1, 16)
+#define PHY_TESTDOUT		DSI_HOST_BITS(0x0b8, 8, 8)
+#define PHY_TESTDIN			DSI_HOST_BITS(0x0b8, 8, 0)
+#define PHY_TEST_CTRL1		DSI_HOST_BITS(0x0b8, 17, 0)
+#define PHY_TEST_CTRL0		DSI_HOST_BITS(0x0b4, 2, 0)
+#define INT_ST0				DSI_HOST_BITS(0x0bc, 21, 0)
+#define INT_ST1				DSI_HOST_BITS(0x0c0, 18, 0)
+#define INT_MKS0			DSI_HOST_BITS(0x0c4, 21, 0)
+#define INT_MKS1			DSI_HOST_BITS(0x0c8, 18, 0)
+#define INT_FORCE0			DSI_HOST_BITS(0x0d8, 21, 0)
+#define INT_FORCE1			DSI_HOST_BITS(0x0dc, 18, 0)
+
+#define CODE_HS_RX_CLOCK	0x34
+#define CODE_HS_RX_LANE0	0x44
+#define CODE_HS_RX_LANE1	0x54
+#define CODE_HS_RX_LANE2	0x84
+#define CODE_HS_RX_LANE3	0x94
+
+#define CODE_PLL_VCORANGE_VCOCAP	0x10
+#define CODE_PLL_CPCTRL	0x11
+#define CODE_PLL_LPF_CP 0x12
+#define CODE_PLL_INPUT_DIV_RAT	0x17
+#define CODE_PLL_LOOP_DIV_RAT	0x18
+#define CODE_PLL_INPUT_LOOP_DIV_RAT	0x19
+#define CODE_BANDGAP_BIAS_CTRL	0x20
+#define CODE_TERMINATION_CTRL	0x21
+#define CODE_AFE_BIAS_BANDGAP_ANOLOG 0x22
+
+#define CODE_HSTXDATALANEREQUSETSTATETIME	0x70
+#define CODE_HSTXDATALANEPREPARESTATETIME	0x71
+#define CODE_HSTXDATALANEHSZEROSTATETIME	0x72
+
+/* Transmission mode between vop and MIPI controller */
+enum vid_mode_type_t {
+	NON_BURST_SYNC_PLUSE = 0,
+	NON_BURST_SYNC_EVENT,
+	BURST_MODE,
+};
+
+enum cmd_video_mode {
+	VIDEO_MODE = 0,
+	CMD_MODE,
+};
+
+/* Indicate MIPI DSI color mode */
+enum dpi_color_coding {
+	DPI_16BIT_CFG_1 = 0,
+	DPI_16BIT_CFG_2,
+	DPI_16BIT_CFG_3,
+	DPI_18BIT_CFG_1,
+	DPI_18BIT_CFG_2,
+	DPI_24BIT,
+	DPI_20BIT_YCBCR_422_LP,
+	DPI_24BIT_YCBCR_422,
+	DPI_16BIT_YCBCR_422,
+	DPI_30BIT,
+	DPI_36BIT,
+	DPI_12BIT_YCBCR_420,
+};
+
+/* Indicate which VOP the MIPI DSI use, bit or little one */
+enum  vop_id {
+	VOP_B = 0,
+	VOP_L,
+};
+
+#endif /* end of ROCKCHIP_MIPI_DSI_H */
diff --git a/arch/arm/include/asm/arch-rockchip/vop_rk3288.h b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
index 0ce3d67..d5599ec 100644
--- a/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
@@ -90,6 +90,7 @@
 	VOP_MODE_EDP = 0,
 	VOP_MODE_HDMI,
 	VOP_MODE_LVDS,
+	VOP_MODE_MIPI,
 	VOP_MODE_NONE,
 	VOP_MODE_AUTO_DETECT,
 	VOP_MODE_UNKNOWN,
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 2b752ad..740dbdf 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -74,6 +74,14 @@
           SPL will return to the boot rom, which will then load the U-Boot
           binary to keep going on.
 
+config ROCKCHIP_SPL_RESERVE_IRAM
+	hex "Size of IRAM reserved in SPL"
+	default 0x4000
+	help
+	  SPL may need reserve memory for firmware loaded by SPL, whose load
+	  address is in IRAM and may overlay with SPL text area if not
+	  reserved.
+
 config ROCKCHIP_BROM_HELPER
 	bool
 
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index 74f3379..8ca6b1e 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -164,7 +164,6 @@
 	int ret;
 
 	/* Example code showing how to enable the debug UART on RK3288 */
-#ifdef EARLY_UART
 #include <asm/arch/grf_rk3288.h>
 	/* Enable early UART on the RK3288 */
 #define GRF_BASE	0xff770000
@@ -183,8 +182,7 @@
 	 * printascii("string");
 	 */
 	debug_uart_init();
-#endif
-
+	debug("\nspl:debug uart enabled in %s\n", __func__);
 	ret = spl_early_init();
 	if (ret) {
 		debug("spl_early_init() failed: %d\n", ret);
@@ -205,7 +203,7 @@
 		debug("Pinctrl init failed: %d\n", ret);
 		return;
 	}
-
+	debug("\nspl:init dram\n");
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
 		debug("DRAM init failed: %d\n", ret);
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
index 8549b28..2feda61 100644
--- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
@@ -24,7 +24,7 @@
 #include <asm/arch/sdram.h>
 #include <linux/err.h>
 #include <power/regulator.h>
-#include <power/rk808_pmic.h>
+#include <power/rk8xx_pmic.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -981,11 +981,11 @@
 		return ret;
 
 	/* Slowly raise to max CPU voltage to prevent overshoot */
-	ret = rk808_spl_configure_buck(pmic, 1, 1200000);
+	ret = rk8xx_spl_configure_buck(pmic, 1, 1200000);
 	if (ret)
 		return ret;
 	udelay(175);/* Must wait for voltage to stabilize, 2mV/us */
-	ret = rk808_spl_configure_buck(pmic, 1, 1400000);
+	ret = rk8xx_spl_configure_buck(pmic, 1, 1400000);
 	if (ret)
 		return ret;
 	udelay(100);/* Must wait for voltage to stabilize, 2mV/us */
diff --git a/arch/arm/mach-rockchip/rk3399/rk3399.c b/arch/arm/mach-rockchip/rk3399/rk3399.c
index 8bb950e..a621a6f 100644
--- a/arch/arm/mach-rockchip/rk3399/rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/rk3399.c
@@ -15,13 +15,13 @@
 	{
 		.virt = 0x0UL,
 		.phys = 0x0UL,
-		.size = 0x80000000UL,
+		.size = 0xf8000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-		.virt = 0xf0000000UL,
-		.phys = 0xf0000000UL,
-		.size = 0x10000000UL,
+		.virt = 0xf8000000UL,
+		.phys = 0xf8000000UL,
+		.size = 0x08000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
index 749b52c..536879d 100644
--- a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
@@ -1280,6 +1280,8 @@
 
 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
 	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
+	priv->info.base = 0;
+	priv->info.size = sdram_size_mb(priv) << 20;
 #endif
 	return 0;
 }
@@ -1288,9 +1290,7 @@
 {
 	struct dram_info *priv = dev_get_priv(dev);
 
-	info = &priv->info;
-	priv->info.base = 0;
-	priv->info.size = sdram_size_mb(priv) << 20;
+	*info = priv->info;
 
 	return 0;
 }
@@ -1314,8 +1314,8 @@
 	.ofdata_to_platdata = rk3399_dmc_ofdata_to_platdata,
 #endif
 	.probe = rk3399_dmc_probe,
-#ifdef CONFIG_SPL_BUILD
 	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_SPL_BUILD
 	.platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat),
 #endif
 };
diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c
index 362fa0b..f63f003 100644
--- a/board/rockchip/evb_rk3399/evb-rk3399.c
+++ b/board/rockchip/evb_rk3399/evb-rk3399.c
@@ -5,6 +5,7 @@
  */
 #include <common.h>
 #include <dm.h>
+#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/arch/periph.h>
@@ -28,6 +29,13 @@
 		goto out;
 	}
 
+	/* Enable pwm0 for panel backlight */
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM0);
+	if (ret) {
+		debug("%s PWM0 pinctrl init fail! (ret=%d)\n", __func__, ret);
+		goto out;
+	}
+
 	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2);
 	if (ret) {
 		debug("%s PWM2 pinctrl init fail!\n", __func__);
@@ -40,10 +48,9 @@
 		goto out;
 	}
 
-	/* rk3399 need init vdd_center to get correct output voltage */
-	ret = regulator_get_by_platname("vdd_center", &regulator);
+	ret = regulators_enable_boot_on(false);
 	if (ret)
-		debug("%s: Cannot get vdd_center regulator\n", __func__);
+		debug("%s: Cannot enable boot on regulator\n", __func__);
 
 	ret = regulator_get_by_platname("vcc5v0_host", &regulator);
 	if (ret) {
@@ -63,7 +70,23 @@
 
 int dram_init(void)
 {
-	gd->ram_size = 0x80000000;
+	struct ram_info ram;
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return ret;
+	}
+	ret = ram_get_info(dev, &ram);
+	if (ret) {
+		debug("Cannot get DRAM size: %d\n", ret);
+		return ret;
+	}
+	debug("SDRAM base=%llx, size=%x\n", ram.base, (unsigned int)ram.size);
+	gd->ram_size = ram.size;
+
 	return 0;
 }
 
diff --git a/board/rockchip/tinker_rk3288/tinker-rk3288.c b/board/rockchip/tinker_rk3288/tinker-rk3288.c
index 79541a3..c2872e7 100644
--- a/board/rockchip/tinker_rk3288/tinker-rk3288.c
+++ b/board/rockchip/tinker_rk3288/tinker-rk3288.c
@@ -5,3 +5,31 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <i2c_eeprom.h>
+#include <netdev.h>
+
+static int get_ethaddr_from_eeprom(u8 *addr)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_I2C_EEPROM, &dev);
+	if (ret)
+		return ret;
+
+	return i2c_eeprom_read(dev, 0, addr, 6);
+}
+
+int rk_board_late_init(void)
+{
+	u8 ethaddr[6];
+
+	if (get_ethaddr_from_eeprom(ethaddr))
+		return 0;
+
+	if (is_valid_ethaddr(ethaddr))
+		eth_setenv_enetaddr("ethaddr", ethaddr);
+
+	return 0;
+}
diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
index fb4d31e..0a8861a 100644
--- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c
+++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
@@ -5,13 +5,21 @@
  */
 #include <common.h>
 #include <dm.h>
+#include <misc.h>
+#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
+#include <u-boot/sha256.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define RK3399_CPUID_OFF  0x7
+#define RK3399_CPUID_LEN  0x10
+
+DECLARE_GLOBAL_DATA_PTR;
+
 int board_init(void)
 {
 	struct udevice *pinctrl, *regulator;
@@ -57,7 +65,23 @@
 
 int dram_init(void)
 {
-	gd->ram_size = 0x80000000;
+	struct ram_info ram;
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return ret;
+	}
+	ret = ram_get_info(dev, &ram);
+	if (ret) {
+		debug("Cannot get DRAM size: %d\n", ret);
+		return ret;
+	}
+	debug("SDRAM base=%llx, size=%x\n", ram.base, (unsigned int)ram.size);
+	gd->ram_size = ram.size;
+
 	return 0;
 }
 
diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig
index e1f96dc..649ebf7 100644
--- a/configs/chromebit_mickey_defconfig
+++ b/configs/chromebit_mickey_defconfig
@@ -54,10 +54,10 @@
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_SPL_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
@@ -72,6 +72,7 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index baebca9..6fc0dcc 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -55,9 +55,9 @@
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
@@ -72,6 +72,8 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_EDP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig
index ea57810..ef333c0 100644
--- a/configs/chromebook_minnie_defconfig
+++ b/configs/chromebook_minnie_defconfig
@@ -55,9 +55,9 @@
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
@@ -72,6 +72,8 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_DISPLAY_ROCKCHIP_EDP=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index eb5e7aa..c189e75 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -34,14 +34,21 @@
 CONFIG_MMC_DW=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK808=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_GMAC_ROCKCHIP=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_ROCKCHIP_RK3399=y
 CONFIG_DM_PMIC=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
@@ -58,5 +65,9 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
 CONFIG_USB_STORAGE=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_MIPI=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index befba18..6a32a3a 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -49,9 +49,9 @@
 # CONFIG_SPL_PINCTRL_FULL is not set
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index f2872a6..9cf576c 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -69,6 +69,7 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig
new file mode 100644
index 0000000..f30f131
--- /dev/null
+++ b/configs/firefly-rk3399_defconfig
@@ -0,0 +1,65 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-firefly"
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_SPL_OF_PLATDATA=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_ROCKCHIP_RK3399_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index d93bd97..0706ff2 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -66,6 +66,7 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index 748cda4..c9ad0c0 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -49,9 +49,9 @@
 # CONFIG_SPL_PINCTRL_FULL is not set
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index ae432ad..6b86812 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -64,6 +64,7 @@
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 95630fc..5417057 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -127,7 +127,7 @@
 CONFIG_DM_PMIC_PFUZE100=y
 CONFIG_DM_PMIC_MAX77686=y
 CONFIG_PMIC_PM8916=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_PMIC_S2MPS11=y
 CONFIG_DM_PMIC_SANDBOX=y
 CONFIG_PMIC_S5M8767=y
@@ -137,7 +137,7 @@
 CONFIG_DM_REGULATOR_PFUZE100=y
 CONFIG_DM_REGULATOR_MAX77686=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index 26183af..b30e165 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -131,7 +131,7 @@
 CONFIG_DM_PMIC_PFUZE100=y
 CONFIG_DM_PMIC_MAX77686=y
 CONFIG_PMIC_PM8916=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_PMIC_S2MPS11=y
 CONFIG_DM_PMIC_SANDBOX=y
 CONFIG_PMIC_S5M8767=y
@@ -141,7 +141,7 @@
 CONFIG_DM_REGULATOR_PFUZE100=y
 CONFIG_DM_REGULATOR_MAX77686=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 9324353..3061e5a 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -133,7 +133,7 @@
 CONFIG_DM_PMIC_PFUZE100=y
 CONFIG_DM_PMIC_MAX77686=y
 CONFIG_PMIC_PM8916=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_PMIC_S2MPS11=y
 CONFIG_DM_PMIC_SANDBOX=y
 CONFIG_PMIC_S5M8767=y
@@ -143,7 +143,7 @@
 CONFIG_DM_REGULATOR_PFUZE100=y
 CONFIG_DM_REGULATOR_MAX77686=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_REGULATOR_TPS65090=y
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index ada5950..bac801e 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -11,6 +11,7 @@
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
@@ -39,6 +40,8 @@
 CONFIG_SPL_CLK=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_DM_ETH=y
@@ -49,9 +52,9 @@
 # CONFIG_SPL_PINCTRL_FULL is not set
 CONFIG_PINCTRL_ROCKCHIP_RK3288=y
 CONFIG_DM_PMIC=y
-CONFIG_PMIC_RK808=y
+CONFIG_PMIC_RK8XX=y
 CONFIG_DM_REGULATOR_FIXED=y
-CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
diff --git a/doc/device-tree-bindings/pwm/pwm.txt b/doc/device-tree-bindings/pwm/pwm.txt
new file mode 100644
index 0000000..8556263
--- /dev/null
+++ b/doc/device-tree-bindings/pwm/pwm.txt
@@ -0,0 +1,69 @@
+Specifying PWM information for devices
+======================================
+
+1) PWM user nodes
+-----------------
+
+PWM users should specify a list of PWM devices that they want to use
+with a property containing a 'pwm-list':
+
+	pwm-list ::= <single-pwm> [pwm-list]
+	single-pwm ::= <pwm-phandle> <pwm-specifier>
+	pwm-phandle : phandle to PWM controller node
+	pwm-specifier : array of #pwm-cells specifying the given PWM
+			(controller specific)
+
+PWM properties should be named "pwms". The exact meaning of each pwms
+property must be documented in the device tree binding for each device.
+An optional property "pwm-names" may contain a list of strings to label
+each of the PWM devices listed in the "pwms" property. If no "pwm-names"
+property is given, the name of the user node will be used as fallback.
+
+Drivers for devices that use more than a single PWM device can use the
+"pwm-names" property to map the name of the PWM device requested by the
+pwm_get() call to an index into the list given by the "pwms" property.
+
+The following example could be used to describe a PWM-based backlight
+device:
+
+	pwm: pwm {
+		#pwm-cells = <2>;
+	};
+
+	[...]
+
+	bl: backlight {
+		pwms = <&pwm 0 5000000>;
+		pwm-names = "backlight";
+	};
+
+Note that in the example above, specifying the "pwm-names" is redundant
+because the name "backlight" would be used as fallback anyway.
+
+pwm-specifier typically encodes the chip-relative PWM number and the PWM
+period in nanoseconds.
+
+Optionally, the pwm-specifier can encode a number of flags (defined in
+<dt-bindings/pwm/pwm.h>) in a third cell:
+- PWM_POLARITY_INVERTED: invert the PWM signal polarity
+
+Example with optional PWM specifier for inverse polarity
+
+	bl: backlight {
+		pwms = <&pwm 0 5000000 PWM_POLARITY_INVERTED>;
+		pwm-names = "backlight";
+	};
+
+2) PWM controller nodes
+-----------------------
+
+PWM controller nodes must specify the number of cells used for the
+specifier using the '#pwm-cells' property.
+
+An example PWM controller might look like this:
+
+	pwm: pwm@7000a000 {
+		compatible = "nvidia,tegra20-pwm";
+		reg = <0x7000a000 0x100>;
+		#pwm-cells = <2>;
+	};
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index 7e3bf96..d866d0b 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -228,11 +228,13 @@
 
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		con = readl(&cru->cru_clksel_con[12]);
 		mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
 		div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
 		break;
 	case HCLK_SDIO:
+	case SCLK_SDIO:
 		con = readl(&cru->cru_clksel_con[12]);
 		mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
 		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
@@ -265,6 +267,7 @@
 
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		rk_clrsetreg(&cru->cru_clksel_con[12],
 			     EMMC_PLL_MASK << EMMC_PLL_SHIFT |
 			     EMMC_DIV_MASK << EMMC_DIV_SHIFT,
@@ -272,6 +275,7 @@
 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
 		break;
 	case HCLK_SDIO:
+	case SCLK_SDIO:
 		rk_clrsetreg(&cru->cru_clksel_con[11],
 			     MMC0_PLL_MASK << MMC0_PLL_SHIFT |
 			     MMC0_DIV_MASK << MMC0_DIV_SHIFT,
@@ -307,6 +311,7 @@
 	case 0 ... 63:
 		return 0;
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate,
 						clk->id, rate);
 		break;
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
index d36cf8f..b32491d 100644
--- a/drivers/clk/rockchip/clk_rk3188.c
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -269,14 +269,17 @@
 
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		con = readl(&cru->cru_clksel_con[12]);
 		div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
 		break;
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		con = readl(&cru->cru_clksel_con[11]);
 		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
 		break;
 	case HCLK_SDIO:
+	case SCLK_SDIO:
 		con = readl(&cru->cru_clksel_con[12]);
 		div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK;
 		break;
@@ -298,16 +301,19 @@
 
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		rk_clrsetreg(&cru->cru_clksel_con[12],
 			     EMMC_DIV_MASK << EMMC_DIV_SHIFT,
 			     src_clk_div << EMMC_DIV_SHIFT);
 		break;
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		rk_clrsetreg(&cru->cru_clksel_con[11],
 			     MMC0_DIV_MASK << MMC0_DIV_SHIFT,
 			     src_clk_div << MMC0_DIV_SHIFT);
 		break;
 	case HCLK_SDIO:
+	case SCLK_SDIO:
 		rk_clrsetreg(&cru->cru_clksel_con[12],
 			     SDIO_DIV_MASK << SDIO_DIV_SHIFT,
 			     src_clk_div << SDIO_DIV_SHIFT);
@@ -466,6 +472,9 @@
 	case HCLK_EMMC:
 	case HCLK_SDMMC:
 	case HCLK_SDIO:
+	case SCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_SDIO:
 		new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
 						clk->id);
 		break;
@@ -505,6 +514,9 @@
 	case HCLK_EMMC:
 	case HCLK_SDMMC:
 	case HCLK_SDIO:
+	case SCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_SDIO:
 		new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ,
 						clk->id, rate);
 		break;
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 7835676..fc369dd 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -513,16 +513,19 @@
 
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		con = readl(&cru->cru_clksel_con[12]);
 		mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
 		div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
 		break;
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		con = readl(&cru->cru_clksel_con[11]);
 		mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
 		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
 		break;
 	case HCLK_SDIO0:
+	case SCLK_SDIO0:
 		con = readl(&cru->cru_clksel_con[12]);
 		mux = (con >> SDIO0_PLL_SHIFT) & SDIO0_PLL_MASK;
 		div = (con >> SDIO0_DIV_SHIFT) & SDIO0_DIV_MASK;
@@ -556,6 +559,7 @@
 	}
 	switch (periph) {
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		rk_clrsetreg(&cru->cru_clksel_con[12],
 			     EMMC_PLL_MASK << EMMC_PLL_SHIFT |
 			     EMMC_DIV_MASK << EMMC_DIV_SHIFT,
@@ -563,6 +567,7 @@
 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
 		break;
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		rk_clrsetreg(&cru->cru_clksel_con[11],
 			     MMC0_PLL_MASK << MMC0_PLL_SHIFT |
 			     MMC0_DIV_MASK << MMC0_DIV_SHIFT,
@@ -570,6 +575,7 @@
 			     (src_clk_div - 1) << MMC0_DIV_SHIFT);
 		break;
 	case HCLK_SDIO0:
+	case SCLK_SDIO0:
 		rk_clrsetreg(&cru->cru_clksel_con[12],
 			     SDIO0_PLL_MASK << SDIO0_PLL_SHIFT |
 			     SDIO0_DIV_MASK << SDIO0_DIV_SHIFT,
@@ -662,6 +668,9 @@
 	case HCLK_EMMC:
 	case HCLK_SDMMC:
 	case HCLK_SDIO0:
+	case SCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_SDIO0:
 		new_rate = rockchip_mmc_get_clk(priv->cru, gclk_rate, clk->id);
 		break;
 	case SCLK_SPI0:
@@ -706,6 +715,9 @@
 	case HCLK_EMMC:
 	case HCLK_SDMMC:
 	case HCLK_SDIO0:
+	case SCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_SDIO0:
 		new_rate = rockchip_mmc_set_clk(cru, gclk_rate, clk->id, rate);
 		break;
 	case SCLK_SPI0:
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 0ff1e30..8ec1574 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -397,9 +397,11 @@
 
 	switch (clk_id) {
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		con_id = 30;
 		break;
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		con_id = 32;
 		break;
 	default:
@@ -423,9 +425,11 @@
 
 	switch (clk_id) {
 	case HCLK_SDMMC:
+	case SCLK_SDMMC:
 		con_id = 30;
 		break;
 	case HCLK_EMMC:
+	case SCLK_EMMC:
 		con_id = 32;
 		break;
 	default:
@@ -483,6 +487,8 @@
 		return 0;
 	case HCLK_SDMMC:
 	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
 		rate = rk3328_mmc_get_clk(priv->cru, clk->id);
 		break;
 	case SCLK_I2C0:
@@ -511,6 +517,8 @@
 		return 0;
 	case HCLK_SDMMC:
 	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
 		ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
 		break;
 	case SCLK_I2C0:
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index ff3cc37..026ed4d 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -1,5 +1,6 @@
 /*
  * (C) Copyright 2015 Google, Inc
+ * (C) 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:	GPL-2.0
  */
@@ -207,12 +208,15 @@
 	DCLK_VOP_DIV_CON_SHIFT          = 0,
 
 	/* CLKSEL_CON58 */
-	CLK_SPI_PLL_SEL_MASK		= 1,
-	CLK_SPI_PLL_SEL_CPLL		= 0,
-	CLK_SPI_PLL_SEL_GPLL		= 1,
-	CLK_SPI_PLL_DIV_CON_MASK	= 0x7f,
-	CLK_SPI5_PLL_DIV_CON_SHIFT	= 8,
-	CLK_SPI5_PLL_SEL_SHIFT		= 15,
+	CLK_SPI_PLL_SEL_WIDTH = 1,
+	CLK_SPI_PLL_SEL_MASK = ((1 < CLK_SPI_PLL_SEL_WIDTH) - 1),
+	CLK_SPI_PLL_SEL_CPLL = 0,
+	CLK_SPI_PLL_SEL_GPLL = 1,
+	CLK_SPI_PLL_DIV_CON_WIDTH = 7,
+	CLK_SPI_PLL_DIV_CON_MASK = ((1 << CLK_SPI_PLL_DIV_CON_WIDTH) - 1),
+
+	CLK_SPI5_PLL_DIV_CON_SHIFT      = 8,
+	CLK_SPI5_PLL_SEL_SHIFT	        = 15,
 
 	/* CLKSEL_CON59 */
 	CLK_SPI1_PLL_SEL_SHIFT		= 15,
@@ -602,7 +606,96 @@
 		return -EINVAL;
 	}
 
+	return rk3399_i2c_get_clk(cru, clk_id);
+}
+
+/*
+ * RK3399 SPI clocks have a common divider-width (7 bits) and a single bit
+ * to select either CPLL or GPLL as the clock-parent. The location within
+ * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
+ */
+
+struct spi_clkreg {
+	uint8_t reg;  /* CLKSEL_CON[reg] register in CRU */
+	uint8_t div_shift;
+	uint8_t sel_shift;
+};
+
+/*
+ * The entries are numbered relative to their offset from SCLK_SPI0.
+ *
+ * Note that SCLK_SPI3 (which is configured via PMUCRU and requires different
+ * logic is not supported).
+ */
+static const struct spi_clkreg spi_clkregs[] = {
+	[0] = { .reg = 59,
+		.div_shift = CLK_SPI0_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI0_PLL_SEL_SHIFT, },
+	[1] = { .reg = 59,
+		.div_shift = CLK_SPI1_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI1_PLL_SEL_SHIFT, },
+	[2] = { .reg = 60,
+		.div_shift = CLK_SPI2_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI2_PLL_SEL_SHIFT, },
+	[3] = { .reg = 60,
+		.div_shift = CLK_SPI4_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI4_PLL_SEL_SHIFT, },
+	[4] = { .reg = 58,
+		.div_shift = CLK_SPI5_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI5_PLL_SEL_SHIFT, },
+};
+
+static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
+{
+	return (val >> shift) & ((1 << width) - 1);
+}
+
+static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	u32 div, val;
+
+	switch (clk_id) {
+	case SCLK_SPI0 ... SCLK_SPI5:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	val = readl(&cru->clksel_con[spiclk->reg]);
+	div = extract_bits(val, CLK_SPI_PLL_DIV_CON_WIDTH, spiclk->div_shift);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3399_spi_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	int src_clk_div;
+
+	src_clk_div = RATE_TO_DIV(GPLL_HZ, hz);
+	assert(src_clk_div < 127);
+
+	switch (clk_id) {
+	case SCLK_SPI1 ... SCLK_SPI5:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
-	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
+	rk_clrsetreg(&cru->clksel_con[spiclk->reg],
+		     ((CLK_SPI_PLL_DIV_CON_MASK << spiclk->div_shift) |
+		       (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)),
+		     ((src_clk_div << spiclk->div_shift) |
+		      (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)));
+
+	return rk3399_spi_get_clk(cru, clk_id);
 }
 
 static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
@@ -654,6 +747,7 @@
 	u32 div, con;
 
 	switch (clk_id) {
+	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 		con = readl(&cru->clksel_con[16]);
 		break;
@@ -679,6 +773,7 @@
 	int aclk_emmc = 198*MHz;
 
 	switch (clk_id) {
+	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 		/* Select clk_sdmmc source from GPLL by default */
 		src_clk_div = GPLL_HZ / set_rate;
@@ -768,6 +863,7 @@
 	switch (clk->id) {
 	case 0 ... 63:
 		return 0;
+	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 	case SCLK_EMMC:
 		rate = rk3399_mmc_get_clk(priv->cru, clk->id);
@@ -780,9 +876,20 @@
 	case SCLK_I2C7:
 		rate = rk3399_i2c_get_clk(priv->cru, clk->id);
 		break;
+	case SCLK_SPI0...SCLK_SPI5:
+		rate = rk3399_spi_get_clk(priv->cru, clk->id);
+		break;
+	case SCLK_UART0:
+	case SCLK_UART2:
+		return 24000000;
+		break;
+	case PCLK_HDMI_CTRL:
+		break;
 	case DCLK_VOP0:
 	case DCLK_VOP1:
 		break;
+	case PCLK_EFUSE1024NS:
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -798,6 +905,7 @@
 	switch (clk->id) {
 	case 0 ... 63:
 		return 0;
+	case HCLK_SDMMC:
 	case SCLK_SDMMC:
 	case SCLK_EMMC:
 		ret = rk3399_mmc_set_clk(priv->cru, clk->id, rate);
@@ -814,6 +922,13 @@
 	case SCLK_I2C7:
 		ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
 		break;
+	case SCLK_SPI0...SCLK_SPI5:
+		ret = rk3399_spi_set_clk(priv->cru, clk->id, rate);
+		break;
+	case PCLK_HDMI_CTRL:
+	case PCLK_VIO_GRF:
+		/* the PCLK gates for video are enabled by default */
+		break;
 	case DCLK_VOP0:
 	case DCLK_VOP1:
 		ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);
@@ -821,6 +936,8 @@
 	case SCLK_DDRCLK:
 		ret = rk3399_ddr_set_clk(priv->cru, rate);
 		break;
+	case PCLK_EFUSE1024NS:
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
index c9f4174..da6e2b0 100644
--- a/drivers/misc/i2c_eeprom.c
+++ b/drivers/misc/i2c_eeprom.c
@@ -10,21 +10,41 @@
 #include <i2c.h>
 #include <i2c_eeprom.h>
 
-static int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf,
-			   int size)
+int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size)
+{
+	const struct i2c_eeprom_ops *ops = device_get_ops(dev);
+
+	if (!ops->read)
+		return -ENOSYS;
+
+	return ops->read(dev, offset, buf, size);
+}
+
+int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size)
+{
+	const struct i2c_eeprom_ops *ops = device_get_ops(dev);
+
+	if (!ops->write)
+		return -ENOSYS;
+
+	return ops->write(dev, offset, buf, size);
+}
+
+static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf,
+			       int size)
 {
 	return dm_i2c_read(dev, offset, buf, size);
 }
 
-static int i2c_eeprom_write(struct udevice *dev, int offset,
-			    const uint8_t *buf, int size)
+static int i2c_eeprom_std_write(struct udevice *dev, int offset,
+				const uint8_t *buf, int size)
 {
 	return -ENODEV;
 }
 
 struct i2c_eeprom_ops i2c_eeprom_std_ops = {
-	.read	= i2c_eeprom_read,
-	.write	= i2c_eeprom_write,
+	.read	= i2c_eeprom_std_read,
+	.write	= i2c_eeprom_std_write,
 };
 
 static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index c36eda0..2885ef2 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -44,7 +44,7 @@
 
 	ret = clk_set_rate(&priv->clk, freq);
 	if (ret < 0) {
-		debug("%s: err=%d\n", __func__, ret);
+		printf("%s: err=%d\n", __func__, ret);
 		return ret;
 	}
 
@@ -76,9 +76,25 @@
 		return -EINVAL;
 	priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
 					  "fifo-mode");
+
+	/*
+	 * 'clock-freq-min-max' is deprecated
+	 * (see https://github.com/torvalds/linux/commit/b023030f10573de738bbe8df63d43acab64c9f7b)
+	 */
 	if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
-				 "clock-freq-min-max", priv->minmax, 2))
-		return -EINVAL;
+				 "clock-freq-min-max", priv->minmax, 2)) {
+		int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					  "max-frequency", -EINVAL);
+
+		if (val < 0)
+			return val;
+
+		priv->minmax[0] = 400000;  /* 400 kHz */
+		priv->minmax[1] = val;
+	} else {
+		debug("%s: 'clock-freq-min-max' property was deprecated.\n",
+		      __func__);
+	}
 #endif
 	return 0;
 }
@@ -109,7 +125,7 @@
 	if (ret < 0)
 		return ret;
 #else
-	ret = clk_get_by_index(dev, 0, &priv->clk);
+	ret = clk_get_by_name(dev, "ciu", &priv->clk);
 	if (ret < 0)
 		return ret;
 #endif
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
index 507bec4..d93b903 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
@@ -145,7 +145,19 @@
 			     | GRF_SPI2TPM_CLK << GRF_GPIO2B3_SEL_SHIFT
 			     | GRF_SPI2TPM_CSN0 << GRF_GPIO2B4_SEL_SHIFT);
 		break;
+	case PERIPH_ID_SPI5:
+		if (cs != 0)
+			goto err;
+		rk_clrsetreg(&grf->gpio2c_iomux,
+			     GRF_GPIO2C4_SEL_MASK | GRF_GPIO2C5_SEL_MASK
+			     | GRF_GPIO2C6_SEL_MASK | GRF_GPIO2C7_SEL_MASK,
+			     GRF_SPI5EXPPLUS_RXD << GRF_GPIO2C4_SEL_SHIFT
+			     | GRF_SPI5EXPPLUS_TXD << GRF_GPIO2C5_SEL_SHIFT
+			     | GRF_SPI5EXPPLUS_CLK << GRF_GPIO2C6_SEL_SHIFT
+			     | GRF_SPI5EXPPLUS_CSN0 << GRF_GPIO2C7_SEL_SHIFT);
+		break;
 	default:
+		printf("%s: spi_id %d is not supported.\n", __func__, spi_id);
 		goto err;
 	}
 
@@ -232,6 +244,41 @@
 	rk_clrsetreg(&grf->gpio3c_iomux,
 		     GRF_GPIO3C1_SEL_MASK,
 		     GRF_MAC_TXCLK << GRF_GPIO3C1_SEL_SHIFT);
+
+	/* Set drive strength for GMAC tx io, value 3 means 13mA */
+	rk_clrsetreg(&grf->gpio3_e[0],
+		     GRF_GPIO3A0_E_MASK | GRF_GPIO3A1_E_MASK |
+		     GRF_GPIO3A4_E_MASK | GRF_GPIO3A5_E0_MASK,
+		     3 << GRF_GPIO3A0_E_SHIFT |
+		     3 << GRF_GPIO3A1_E_SHIFT |
+		     3 << GRF_GPIO3A4_E_SHIFT |
+		     1 << GRF_GPIO3A5_E0_SHIFT);
+	rk_clrsetreg(&grf->gpio3_e[1],
+		     GRF_GPIO3A5_E12_MASK,
+		     1 << GRF_GPIO3A5_E12_SHIFT);
+	rk_clrsetreg(&grf->gpio3_e[2],
+		     GRF_GPIO3B4_E_MASK,
+		     3 << GRF_GPIO3B4_E_SHIFT);
+	rk_clrsetreg(&grf->gpio3_e[4],
+		     GRF_GPIO3C1_E_MASK,
+		     3 << GRF_GPIO3C1_E_SHIFT);
+}
+#endif
+
+#if !defined(CONFIG_SPL_BUILD)
+static void pinctrl_rk3399_hdmi_config(struct rk3399_grf_regs *grf, int hdmi_id)
+{
+	switch (hdmi_id) {
+	case PERIPH_ID_HDMI:
+		rk_clrsetreg(&grf->gpio4c_iomux,
+			     GRF_GPIO4C0_SEL_MASK | GRF_GPIO4C1_SEL_MASK,
+			     (GRF_HDMII2C_SCL << GRF_GPIO4C0_SEL_SHIFT) |
+			     (GRF_HDMII2C_SDA << GRF_GPIO4C1_SEL_SHIFT));
+		break;
+	default:
+		debug("%s: hdmi_id = %d unsupported\n", __func__, hdmi_id);
+		break;
+	}
 }
 #endif
 
@@ -259,6 +306,9 @@
 	case PERIPH_ID_SPI0:
 	case PERIPH_ID_SPI1:
 	case PERIPH_ID_SPI2:
+	case PERIPH_ID_SPI3:
+	case PERIPH_ID_SPI4:
+	case PERIPH_ID_SPI5:
 		pinctrl_rk3399_spi_config(priv->grf, priv->pmugrf, func, flags);
 		break;
 	case PERIPH_ID_UART0:
@@ -281,6 +331,11 @@
 		pinctrl_rk3399_gmac_config(priv->grf, func);
 		break;
 #endif
+#if !defined(CONFIG_SPL_BUILD)
+	case PERIPH_ID_HDMI:
+		pinctrl_rk3399_hdmi_config(priv->grf, func);
+		break;
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -307,6 +362,8 @@
 		return PERIPH_ID_SPI1;
 	case 52:
 		return PERIPH_ID_SPI2;
+	case 132:
+		return PERIPH_ID_SPI5;
 	case 57:
 		return PERIPH_ID_I2C0;
 	case 59: /* Note strange order */
@@ -325,6 +382,10 @@
 	case 12:
 		return PERIPH_ID_GMAC;
 #endif
+#if !defined(CONFIG_SPL_BUILD)
+	case 23:
+		return PERIPH_ID_HDMI;
+#endif
 	}
 #endif
 	return -ENOENT;
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 4891b17..3f50c12 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -28,7 +28,7 @@
 	This allows PMICs to support child devices (such as regulators) in
 	SPL. This adds quite a bit of code so if you are not using this
 	feature you can turn it off. In this case you may need a 'back door'
-	to call your regulator code (e.g. see rk808.c for direct functions
+	to call your regulator code (e.g. see rk8xx.c for direct functions
 	for use in SPL).
 
 config PMIC_ACT8846
@@ -100,8 +100,8 @@
 
 	Driver binding info: doc/device-tree-bindings/pmic/pm8916.txt
 
-config PMIC_RK808
-	bool "Enable support for Rockchip PMIC RK808"
+config PMIC_RK8XX
+	bool "Enable support for Rockchip PMIC RK8XX"
 	depends on DM_PMIC
 	---help---
 	The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs,
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 5f1bef3..f409e3a 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_PMIC_AS3722) += as3722.o
 obj-$(CONFIG_PMIC_MAX8997) += max8997.o
 obj-$(CONFIG_PMIC_PM8916) += pm8916.o
-obj-$(CONFIG_PMIC_RK808) += rk808.o
+obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
 obj-$(CONFIG_PMIC_RN5T567) += rn5t567.o
 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
 obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
diff --git a/drivers/power/pmic/rk808.c b/drivers/power/pmic/rk808.c
deleted file mode 100644
index 3f5f316..0000000
--- a/drivers/power/pmic/rk808.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2015 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <errno.h>
-#include <fdtdec.h>
-#include <libfdt.h>
-#include <power/rk808_pmic.h>
-#include <power/pmic.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static const struct pmic_child_info pmic_children_info[] = {
-	{ .prefix = "DCDC_REG", .driver = "rk808_buck"},
-	{ .prefix = "LDO_REG", .driver = "rk808_ldo"},
-	{ .prefix = "SWITCH_REG", .driver = "rk808_switch"},
-	{ },
-};
-
-static int rk808_reg_count(struct udevice *dev)
-{
-	return RK808_NUM_OF_REGS;
-}
-
-static int rk808_write(struct udevice *dev, uint reg, const uint8_t *buff,
-			  int len)
-{
-	int ret;
-
-	ret = dm_i2c_write(dev, reg, buff, len);
-	if (ret) {
-		debug("write error to device: %p register: %#x!", dev, reg);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int rk808_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
-{
-	int ret;
-
-	ret = dm_i2c_read(dev, reg, buff, len);
-	if (ret) {
-		debug("read error from device: %p register: %#x!", dev, reg);
-		return ret;
-	}
-
-	return 0;
-}
-
-#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
-static int rk808_bind(struct udevice *dev)
-{
-	const void *blob = gd->fdt_blob;
-	int regulators_node;
-	int children;
-
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "regulators");
-	if (regulators_node <= 0) {
-		debug("%s: %s regulators subnode not found!", __func__,
-		      dev->name);
-		return -ENXIO;
-	}
-
-	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
-
-	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
-	if (!children)
-		debug("%s: %s - no child found\n", __func__, dev->name);
-
-	/* Always return success for this device */
-	return 0;
-}
-#endif
-
-static struct dm_pmic_ops rk808_ops = {
-	.reg_count = rk808_reg_count,
-	.read = rk808_read,
-	.write = rk808_write,
-};
-
-static const struct udevice_id rk808_ids[] = {
-	{ .compatible = "rockchip,rk808" },
-	{ }
-};
-
-U_BOOT_DRIVER(pmic_rk808) = {
-	.name = "rk808 pmic",
-	.id = UCLASS_PMIC,
-	.of_match = rk808_ids,
-#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
-	.bind = rk808_bind,
-#endif
-	.ops = &rk808_ops,
-};
diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
new file mode 100644
index 0000000..394e2ff
--- /dev/null
+++ b/drivers/power/pmic/rk8xx.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <power/rk8xx_pmic.h>
+#include <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
+	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
+	{ .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
+	{ },
+};
+
+static int rk8xx_reg_count(struct udevice *dev)
+{
+	return RK808_NUM_OF_REGS;
+}
+
+static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
+			  int len)
+{
+	int ret;
+
+	ret = dm_i2c_write(dev, reg, buff, len);
+	if (ret) {
+		debug("write error to device: %p register: %#x!", dev, reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, buff, len);
+	if (ret) {
+		debug("read error from device: %p register: %#x!", dev, reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+static int rk8xx_bind(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	int regulators_node;
+	int children;
+
+	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
+					     "regulators");
+	if (regulators_node <= 0) {
+		debug("%s: %s regulators subnode not found!", __func__,
+		      dev->name);
+		return -ENXIO;
+	}
+
+	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+	if (!children)
+		debug("%s: %s - no child found\n", __func__, dev->name);
+
+	/* Always return success for this device */
+	return 0;
+}
+#endif
+
+static int rk8xx_probe(struct udevice *dev)
+{
+	struct rk8xx_priv *priv = dev_get_priv(dev);
+	uint8_t msb, lsb;
+
+	/* read Chip variant */
+	rk8xx_read(dev, ID_MSB, &msb, 1);
+	rk8xx_read(dev, ID_LSB, &lsb, 1);
+
+	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
+
+	return 0;
+}
+
+static struct dm_pmic_ops rk8xx_ops = {
+	.reg_count = rk8xx_reg_count,
+	.read = rk8xx_read,
+	.write = rk8xx_write,
+};
+
+static const struct udevice_id rk8xx_ids[] = {
+	{ .compatible = "rockchip,rk808" },
+	{ .compatible = "rockchip,rk818" },
+	{ }
+};
+
+U_BOOT_DRIVER(pmic_rk8xx) = {
+	.name = "rk8xx pmic",
+	.id = UCLASS_PMIC,
+	.of_match = rk8xx_ids,
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+	.bind = rk8xx_bind,
+#endif
+	.probe = rk8xx_probe,
+	.ops = &rk8xx_ops,
+};
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index f870e8b..ef057e0 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -76,11 +76,11 @@
 	features for gpio regulators. The driver implements get/set for
 	voltage value.
 
-config REGULATOR_RK808
-	bool "Enable driver for RK808 regulators"
-	depends on DM_REGULATOR && PMIC_RK808
+config REGULATOR_RK8XX
+	bool "Enable driver for RK8XX regulators"
+	depends on DM_REGULATOR && PMIC_RK8XX
 	---help---
-	Enable support for the regulator functions of the RK808 PMIC. The
+	Enable support for the regulator functions of the RK8XX PMIC. The
 	driver implements get/set api for the various BUCKS and LDOs supported
 	by the PMIC device. This driver is controlled by a device tree node
 	which includes voltage limits.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 6002c88..3e01021 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -12,7 +12,7 @@
 obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
-obj-$(CONFIG_REGULATOR_RK808) += rk808.o
+obj-$(CONFIG_REGULATOR_RK8XX) += rk8xx.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c
index 4875238..a6c9fcc 100644
--- a/drivers/power/regulator/pwm_regulator.c
+++ b/drivers/power/regulator/pwm_regulator.c
@@ -24,6 +24,12 @@
 	int pwm_id;
 	/* the period of one PWM cycle */
 	int period_ns;
+	/*
+	 * the polarity of one PWM
+	 * 0: normal polarity
+	 * 1: inverted polarity
+	 */
+	bool polarity;
 	struct udevice *pwm;
 	/* initialize voltage of regulator */
 	unsigned int init_voltage;
@@ -49,7 +55,7 @@
 	int max_uV = priv->max_voltage;
 	int diff = max_uV - min_uV;
 
-	return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
+	return ((req_uV * 100) - (min_uV * 100)) / diff;
 }
 
 static int pwm_regulator_get_voltage(struct udevice *dev)
@@ -67,6 +73,12 @@
 
 	duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt);
 
+	ret = pwm_set_invert(priv->pwm, priv->pwm_id, priv->polarity);
+	if (ret) {
+		dev_err(dev, "Failed to init PWM\n");
+		return ret;
+	}
+
 	ret = pwm_set_config(priv->pwm, priv->pwm_id,
 			(priv->period_ns / 100) * duty_cycle, priv->period_ns);
 	if (ret) {
@@ -97,9 +109,9 @@
 		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->polarity = args.args[2];
 
 	priv->init_voltage = fdtdec_get_int(blob, node,
 			"regulator-init-microvolt", -1);
diff --git a/drivers/power/regulator/rk808.c b/drivers/power/regulator/rk808.c
deleted file mode 100644
index adef8f5..0000000
--- a/drivers/power/regulator/rk808.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2015 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
- *
- * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
- * Copyright (C) 2012 rockchips
- * zyw <zyw@rock-chips.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <errno.h>
-#include <power/rk808_pmic.h>
-#include <power/pmic.h>
-#include <power/regulator.h>
-
-#ifndef CONFIG_SPL_BUILD
-#define ENABLE_DRIVER
-#endif
-
-struct rk808_reg_info {
-	uint min_uv;
-	uint step_uv;
-	s8 vsel_reg;
-	u8 vsel_bits;
-};
-
-static const struct rk808_reg_info rk808_buck[] = {
-	{ 712500, 12500, REG_BUCK1_ON_VSEL, 6, },
-	{ 712500, 12500, REG_BUCK2_ON_VSEL, 6, },
-	{ 712500, 12500, -1, 6, },
-	{ 1800000, 100000, REG_BUCK4_ON_VSEL, 4, },
-};
-
-static const struct rk808_reg_info rk808_ldo[] = {
-	{ 1800000, 100000, LDO1_ON_VSEL, 5, },
-	{ 1800000, 100000, LDO2_ON_VSEL, 5, },
-	{ 800000, 100000, LDO3_ON_VSEL, 4, },
-	{ 1800000, 100000, LDO4_ON_VSEL, 5, },
-	{ 1800000, 100000, LDO5_ON_VSEL, 5, },
-	{ 800000, 100000, LDO6_ON_VSEL, 5, },
-	{ 800000, 100000, LDO7_ON_VSEL, 5, },
-	{ 1800000, 100000, LDO8_ON_VSEL, 5, },
-};
-
-
-static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
-{
-	const struct rk808_reg_info *info = &rk808_buck[buck - 1];
-	int mask = (1 << info->vsel_bits) - 1;
-	int val;
-
-	if (info->vsel_reg == -1)
-		return -ENOSYS;
-	val = (uvolt - info->min_uv) / info->step_uv;
-	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
-	      val);
-
-	return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
-}
-
-static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
-{
-	uint mask;
-	int ret;
-
-	buck--;
-	mask = 1 << buck;
-	if (enable) {
-		ret = pmic_clrsetbits(pmic, DCDC_ILMAX, 0, 3 << (buck * 2));
-		if (ret)
-			return ret;
-		ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
-		if (ret)
-			return ret;
-	}
-
-	return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
-}
-
-#ifdef ENABLE_DRIVER
-static int buck_get_value(struct udevice *dev)
-{
-	int buck = dev->driver_data - 1;
-	const struct rk808_reg_info *info = &rk808_buck[buck];
-	int mask = (1 << info->vsel_bits) - 1;
-	int ret, val;
-
-	if (info->vsel_reg == -1)
-		return -ENOSYS;
-	ret = pmic_reg_read(dev->parent, info->vsel_reg);
-	if (ret < 0)
-		return ret;
-	val = ret & mask;
-
-	return info->min_uv + val * info->step_uv;
-}
-
-static int buck_set_value(struct udevice *dev, int uvolt)
-{
-	int buck = dev->driver_data;
-
-	return _buck_set_value(dev->parent, buck, uvolt);
-}
-
-static int buck_set_enable(struct udevice *dev, bool enable)
-{
-	int buck = dev->driver_data;
-
-	return _buck_set_enable(dev->parent, buck, enable);
-}
-
-static bool buck_get_enable(struct udevice *dev)
-{
-	int buck = dev->driver_data - 1;
-	int ret;
-	uint mask;
-
-	mask = 1 << buck;
-
-	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask ? true : false;
-}
-
-static int ldo_get_value(struct udevice *dev)
-{
-	int ldo = dev->driver_data - 1;
-	const struct rk808_reg_info *info = &rk808_ldo[ldo];
-	int mask = (1 << info->vsel_bits) - 1;
-	int ret, val;
-
-	if (info->vsel_reg == -1)
-		return -ENOSYS;
-	ret = pmic_reg_read(dev->parent, info->vsel_reg);
-	if (ret < 0)
-		return ret;
-	val = ret & mask;
-
-	return info->min_uv + val * info->step_uv;
-}
-
-static int ldo_set_value(struct udevice *dev, int uvolt)
-{
-	int ldo = dev->driver_data - 1;
-	const struct rk808_reg_info *info = &rk808_ldo[ldo];
-	int mask = (1 << info->vsel_bits) - 1;
-	int val;
-
-	if (info->vsel_reg == -1)
-		return -ENOSYS;
-	val = (uvolt - info->min_uv) / info->step_uv;
-	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
-	      val);
-
-	return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
-}
-
-static int ldo_set_enable(struct udevice *dev, bool enable)
-{
-	int ldo = dev->driver_data - 1;
-	uint mask;
-
-	mask = 1 << ldo;
-
-	return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask,
-			       enable ? mask : 0);
-}
-
-static bool ldo_get_enable(struct udevice *dev)
-{
-	int ldo = dev->driver_data - 1;
-	int ret;
-	uint mask;
-
-	mask = 1 << ldo;
-
-	ret = pmic_reg_read(dev->parent, REG_LDO_EN);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask ? true : false;
-}
-
-static int switch_set_enable(struct udevice *dev, bool enable)
-{
-	int sw = dev->driver_data - 1;
-	uint mask;
-
-	mask = 1 << (sw + 5);
-
-	return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
-			       enable ? mask : 0);
-}
-
-static bool switch_get_enable(struct udevice *dev)
-{
-	int sw = dev->driver_data - 1;
-	int ret;
-	uint mask;
-
-	mask = 1 << (sw + 5);
-
-	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask ? true : false;
-}
-
-static int rk808_buck_probe(struct udevice *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;
-
-	return 0;
-}
-
-static int rk808_ldo_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_LDO;
-	uc_pdata->mode_count = 0;
-
-	return 0;
-}
-
-static int rk808_switch_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_FIXED;
-	uc_pdata->mode_count = 0;
-
-	return 0;
-}
-
-static const struct dm_regulator_ops rk808_buck_ops = {
-	.get_value  = buck_get_value,
-	.set_value  = buck_set_value,
-	.get_enable = buck_get_enable,
-	.set_enable = buck_set_enable,
-};
-
-static const struct dm_regulator_ops rk808_ldo_ops = {
-	.get_value  = ldo_get_value,
-	.set_value  = ldo_set_value,
-	.get_enable = ldo_get_enable,
-	.set_enable = ldo_set_enable,
-};
-
-static const struct dm_regulator_ops rk808_switch_ops = {
-	.get_enable = switch_get_enable,
-	.set_enable = switch_set_enable,
-};
-
-U_BOOT_DRIVER(rk808_buck) = {
-	.name = "rk808_buck",
-	.id = UCLASS_REGULATOR,
-	.ops = &rk808_buck_ops,
-	.probe = rk808_buck_probe,
-};
-
-U_BOOT_DRIVER(rk808_ldo) = {
-	.name = "rk808_ldo",
-	.id = UCLASS_REGULATOR,
-	.ops = &rk808_ldo_ops,
-	.probe = rk808_ldo_probe,
-};
-
-U_BOOT_DRIVER(rk808_switch) = {
-	.name = "rk808_switch",
-	.id = UCLASS_REGULATOR,
-	.ops = &rk808_switch_ops,
-	.probe = rk808_switch_probe,
-};
-#endif
-
-int rk808_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
-{
-	int ret;
-
-	ret = _buck_set_value(pmic, buck, uvolt);
-	if (ret)
-		return ret;
-
-	return _buck_set_enable(pmic, buck, true);
-}
diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
new file mode 100644
index 0000000..e655c2d
--- /dev/null
+++ b/drivers/power/regulator/rk8xx.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
+ * Copyright (C) 2012 rockchips
+ * zyw <zyw@rock-chips.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/rk8xx_pmic.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#ifndef CONFIG_SPL_BUILD
+#define ENABLE_DRIVER
+#endif
+
+/* Field Definitions */
+#define RK808_BUCK_VSEL_MASK	0x3f
+#define RK808_BUCK4_VSEL_MASK	0xf
+#define RK808_LDO_VSEL_MASK	0x1f
+
+#define RK818_BUCK_VSEL_MASK		0x3f
+#define RK818_BUCK4_VSEL_MASK		0x1f
+#define RK818_LDO_VSEL_MASK		0x1f
+#define RK818_LDO3_ON_VSEL_MASK	0xf
+#define RK818_BOOST_ON_VSEL_MASK	0xe0
+
+struct rk8xx_reg_info {
+	uint min_uv;
+	uint step_uv;
+	s8 vsel_reg;
+	u8 vsel_mask;
+};
+
+static const struct rk8xx_reg_info rk808_buck[] = {
+	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK808_BUCK_VSEL_MASK, },
+	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK808_BUCK_VSEL_MASK, },
+	{ 712500, 12500, -1, RK808_BUCK_VSEL_MASK, },
+	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
+};
+
+static const struct rk8xx_reg_info rk808_ldo[] = {
+	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO3_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO6_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO7_ON_VSEL, RK808_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, },
+};
+
+static const struct rk8xx_reg_info rk818_buck[] = {
+	{ 712500, 12500, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+	{ 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+	{ 712500, 12500, -1, RK818_BUCK_VSEL_MASK, },
+	{ 1800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, },
+};
+
+static const struct rk8xx_reg_info rk818_ldo[] = {
+	{ 1800000, 100000, REG_LDO1_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO3_ON_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 800000, 100000, REG_LDO7_ON_VSEL, RK818_LDO_VSEL_MASK, },
+	{ 1800000, 100000, REG_LDO8_ON_VSEL, RK818_LDO_VSEL_MASK, },
+};
+
+static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
+					     int num)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	switch (priv->variant) {
+	case RK818_ID:
+		return &rk818_buck[num];
+	default:
+		return &rk808_buck[num];
+	}
+}
+
+static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
+					     int num)
+{
+	struct rk8xx_priv *priv = dev_get_priv(pmic);
+	switch (priv->variant) {
+	case RK818_ID:
+		return &rk818_ldo[num - 1];
+	default:
+		return &rk808_ldo[num - 1];
+	}
+}
+
+static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
+{
+	const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck - 1);
+	int mask = info->vsel_mask;
+	int val;
+
+	if (info->vsel_reg == -1)
+		return -ENOSYS;
+	val = (uvolt - info->min_uv) / info->step_uv;
+	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
+	      val);
+
+	return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
+}
+
+static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
+{
+	uint mask;
+	int ret;
+
+	buck--;
+	mask = 1 << buck;
+	if (enable) {
+		ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2));
+		if (ret)
+			return ret;
+		ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
+		if (ret)
+			return ret;
+	}
+
+	return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
+}
+
+#ifdef ENABLE_DRIVER
+static int buck_get_value(struct udevice *dev)
+{
+	int buck = dev->driver_data - 1;
+	const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck);
+	int mask = info->vsel_mask;
+	int ret, val;
+
+	if (info->vsel_reg == -1)
+		return -ENOSYS;
+	ret = pmic_reg_read(dev->parent, info->vsel_reg);
+	if (ret < 0)
+		return ret;
+	val = ret & mask;
+
+	return info->min_uv + val * info->step_uv;
+}
+
+static int buck_set_value(struct udevice *dev, int uvolt)
+{
+	int buck = dev->driver_data;
+
+	return _buck_set_value(dev->parent, buck, uvolt);
+}
+
+static int buck_set_enable(struct udevice *dev, bool enable)
+{
+	int buck = dev->driver_data;
+
+	return _buck_set_enable(dev->parent, buck, enable);
+}
+
+static bool buck_get_enable(struct udevice *dev)
+{
+	int buck = dev->driver_data - 1;
+	int ret;
+	uint mask;
+
+	mask = 1 << buck;
+
+	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask ? true : false;
+}
+
+static int ldo_get_value(struct udevice *dev)
+{
+	int ldo = dev->driver_data - 1;
+	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo);
+	int mask = info->vsel_mask;
+	int ret, val;
+
+	if (info->vsel_reg == -1)
+		return -ENOSYS;
+	ret = pmic_reg_read(dev->parent, info->vsel_reg);
+	if (ret < 0)
+		return ret;
+	val = ret & mask;
+
+	return info->min_uv + val * info->step_uv;
+}
+
+static int ldo_set_value(struct udevice *dev, int uvolt)
+{
+	int ldo = dev->driver_data - 1;
+	const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo);
+	int mask = info->vsel_mask;
+	int val;
+
+	if (info->vsel_reg == -1)
+		return -ENOSYS;
+	val = (uvolt - info->min_uv) / info->step_uv;
+	debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
+	      val);
+
+	return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
+}
+
+static int ldo_set_enable(struct udevice *dev, bool enable)
+{
+	int ldo = dev->driver_data - 1;
+	uint mask;
+
+	mask = 1 << ldo;
+
+	return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask,
+			       enable ? mask : 0);
+}
+
+static bool ldo_get_enable(struct udevice *dev)
+{
+	int ldo = dev->driver_data - 1;
+	int ret;
+	uint mask;
+
+	mask = 1 << ldo;
+
+	ret = pmic_reg_read(dev->parent, REG_LDO_EN);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask ? true : false;
+}
+
+static int switch_set_enable(struct udevice *dev, bool enable)
+{
+	int sw = dev->driver_data - 1;
+	uint mask;
+
+	mask = 1 << (sw + 5);
+
+	return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
+			       enable ? mask : 0);
+}
+
+static bool switch_get_enable(struct udevice *dev)
+{
+	int sw = dev->driver_data - 1;
+	int ret;
+	uint mask;
+
+	mask = 1 << (sw + 5);
+
+	ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask ? true : false;
+}
+
+static int rk8xx_buck_probe(struct udevice *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;
+
+	return 0;
+}
+
+static int rk8xx_ldo_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_LDO;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+static int rk8xx_switch_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_FIXED;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops rk8xx_buck_ops = {
+	.get_value  = buck_get_value,
+	.set_value  = buck_set_value,
+	.get_enable = buck_get_enable,
+	.set_enable = buck_set_enable,
+};
+
+static const struct dm_regulator_ops rk8xx_ldo_ops = {
+	.get_value  = ldo_get_value,
+	.set_value  = ldo_set_value,
+	.get_enable = ldo_get_enable,
+	.set_enable = ldo_set_enable,
+};
+
+static const struct dm_regulator_ops rk8xx_switch_ops = {
+	.get_enable = switch_get_enable,
+	.set_enable = switch_set_enable,
+};
+
+U_BOOT_DRIVER(rk8xx_buck) = {
+	.name = "rk8xx_buck",
+	.id = UCLASS_REGULATOR,
+	.ops = &rk8xx_buck_ops,
+	.probe = rk8xx_buck_probe,
+};
+
+U_BOOT_DRIVER(rk8xx_ldo) = {
+	.name = "rk8xx_ldo",
+	.id = UCLASS_REGULATOR,
+	.ops = &rk8xx_ldo_ops,
+	.probe = rk8xx_ldo_probe,
+};
+
+U_BOOT_DRIVER(rk8xx_switch) = {
+	.name = "rk8xx_switch",
+	.id = UCLASS_REGULATOR,
+	.ops = &rk8xx_switch_ops,
+	.probe = rk8xx_switch_probe,
+};
+#endif
+
+int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
+{
+	int ret;
+
+	ret = _buck_set_value(pmic, buck, uvolt);
+	if (ret)
+		return ret;
+
+	return _buck_set_enable(pmic, buck, true);
+}
diff --git a/drivers/pwm/pwm-uclass.c b/drivers/pwm/pwm-uclass.c
index c2200af..69051fe 100644
--- a/drivers/pwm/pwm-uclass.c
+++ b/drivers/pwm/pwm-uclass.c
@@ -9,6 +9,16 @@
 #include <dm.h>
 #include <pwm.h>
 
+int pwm_set_invert(struct udevice *dev, uint channel, bool polarity)
+{
+	struct pwm_ops *ops = pwm_get_ops(dev);
+
+	if (!ops->set_invert)
+		return -ENOSYS;
+
+	return ops->set_invert(dev, channel, polarity);
+}
+
 int pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
 		   uint duty_ns)
 {
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c
index 9254f5b..f3b2f76 100644
--- a/drivers/pwm/rk_pwm.c
+++ b/drivers/pwm/rk_pwm.c
@@ -21,8 +21,22 @@
 struct rk_pwm_priv {
 	struct rk3288_pwm *regs;
 	ulong freq;
+	uint enable_conf;
 };
 
+static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity)
+{
+	struct rk_pwm_priv *priv = dev_get_priv(dev);
+
+	debug("%s: polarity=%u\n", __func__, polarity);
+	if (polarity)
+		priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
+	else
+		priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
+
+	return 0;
+}
+
 static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
 			     uint duty_ns)
 {
@@ -32,7 +46,7 @@
 
 	debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
 	writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
-		PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE |
+		PWM_CONTINUOUS | priv->enable_conf |
 		RK_PWM_DISABLE,
 		&regs->ctrl);
 
@@ -83,6 +97,7 @@
 }
 
 static const struct pwm_ops rk_pwm_ops = {
+	.set_invert	= rk_pwm_set_invert,
 	.set_config	= rk_pwm_set_config,
 	.set_enable	= rk_pwm_set_enable,
 };
diff --git a/drivers/pwm/sandbox_pwm.c b/drivers/pwm/sandbox_pwm.c
index c2ce974..fcb1084 100644
--- a/drivers/pwm/sandbox_pwm.c
+++ b/drivers/pwm/sandbox_pwm.c
@@ -21,6 +21,7 @@
 	uint period_ns;
 	uint duty_ns;
 	bool enable;
+	bool polarity;
 };
 
 struct sandbox_pwm_priv {
@@ -56,9 +57,24 @@
 	return 0;
 }
 
+static int sandbox_pwm_set_invert(struct udevice *dev, uint channel,
+				  bool polarity)
+{
+	struct sandbox_pwm_priv *priv = dev_get_priv(dev);
+	struct sandbox_pwm_chan *chan;
+
+	if (channel >= NUM_CHANNELS)
+		return -ENOSPC;
+	chan = &priv->chan[channel];
+	chan->polarity = polarity;
+
+	return 0;
+}
+
 static const struct pwm_ops sandbox_pwm_ops = {
 	.set_config	= sandbox_pwm_set_config,
 	.set_enable	= sandbox_pwm_set_enable,
+	.set_invert	= sandbox_pwm_set_invert,
 };
 
 static const struct udevice_id sandbox_pwm_ids[] = {
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 3e44f17..ea20980 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -79,12 +79,31 @@
 
 static void rkspi_set_clk(struct rockchip_spi_priv *priv, uint speed)
 {
-	uint clk_div;
+	/*
+	 * We should try not to exceed the speed requested by the caller:
+	 * when selecting a divider, we need to make sure we round up.
+	 */
+	uint clk_div = DIV_ROUND_UP(priv->input_rate, speed);
+
+	/* The baudrate register (BAUDR) is defined as a 32bit register where
+	 * the upper 16bit are reserved and having 'Fsclk_out' in the lower
+	 * 16bits with 'Fsclk_out' defined as follows:
+	 *
+	 *   Fsclk_out = Fspi_clk/ SCKDV
+	 *   Where SCKDV is any even value between 2 and 65534.
+	 */
+	if (clk_div > 0xfffe) {
+		clk_div = 0xfffe;
+		debug("%s: can't divide down to %d hz (actual will be %d hz)\n",
+		      __func__, speed, priv->input_rate / clk_div);
+	}
 
-	clk_div = clk_get_divisor(priv->input_rate, speed);
+	/* Round up to the next even 16bit number */
+	clk_div = (clk_div + 1) & 0xfffe;
+
 	debug("spi speed %u, div %u\n", speed, clk_div);
 
-	writel(clk_div, &priv->regs->baudr);
+	clrsetbits_le32(&priv->regs->baudr, 0xffff, clk_div);
 	priv->last_speed_hz = speed;
 }
 
@@ -190,6 +209,26 @@
 	return 0;
 }
 
+static int rockchip_spi_calc_modclk(ulong max_freq)
+{
+	unsigned div;
+	const unsigned long gpll_hz = 594000000UL;
+
+	/*
+	 * We need to find an input clock that provides at least twice
+	 * the maximum frequency and can be generated from the assumed
+	 * speed of GPLL (594MHz) using an integer divider.
+	 *
+	 * To give us more achievable bitrates at higher speeds (these
+	 * are generated by dividing by an even 16-bit integer from
+	 * this frequency), we try to have an input frequency of at
+	 * least 4x our max_freq.
+	 */
+
+	div = DIV_ROUND_UP(gpll_hz, max_freq * 4);
+	return gpll_hz / div;
+}
+
 static int rockchip_spi_probe(struct udevice *bus)
 {
 	struct rockchip_spi_platdata *plat = dev_get_platdata(bus);
@@ -207,11 +246,13 @@
 	priv->last_transaction_us = timer_get_us();
 	priv->max_freq = plat->frequency;
 
-	/*
-	 * Use 99 MHz as our clock since it divides nicely into 594 MHz which
-	 * is the assumed speed for CLK_GENERAL.
-	 */
-	ret = clk_set_rate(&priv->clk, 99000000);
+	/* Clamp the value from the DTS against any hardware limits */
+	if (priv->max_freq > ROCKCHIP_SPI_MAX_RATE)
+		priv->max_freq = ROCKCHIP_SPI_MAX_RATE;
+
+	/* Find a module-input clock that fits with the max_freq setting */
+	ret = clk_set_rate(&priv->clk,
+			   rockchip_spi_calc_modclk(priv->max_freq));
 	if (ret < 0) {
 		debug("%s: Failed to set clock: %d\n", __func__, ret);
 		return ret;
@@ -371,10 +412,10 @@
 {
 	struct rockchip_spi_priv *priv = dev_get_priv(bus);
 
-	if (speed > ROCKCHIP_SPI_MAX_RATE)
-		return -EINVAL;
+	/* Clamp to the maximum frequency specified in the DTS */
 	if (speed > priv->max_freq)
 		speed = priv->max_freq;
+
 	priv->speed_hz = speed;
 
 	return 0;
@@ -403,6 +444,7 @@
 
 static const struct udevice_id rockchip_spi_ids[] = {
 	{ .compatible = "rockchip,rk3288-spi" },
+	{ .compatible = "rockchip,rk3399-spi" },
 	{ }
 };
 
diff --git a/drivers/spi/rk_spi.h b/drivers/spi/rk_spi.h
index f1ac812..02aa9d0 100644
--- a/drivers/spi/rk_spi.h
+++ b/drivers/spi/rk_spi.h
@@ -119,6 +119,13 @@
 };
 
 #define ROCKCHIP_SPI_TIMEOUT_MS		1000
-#define ROCKCHIP_SPI_MAX_RATE		48000000
+
+/*
+ * We limit the maximum bitrate to 50MBit/s (50MHz) due to an assumed
+ * hardware limitation...  the Linux kernel source has the following
+ * comment:
+ *   "sclk_out: spi master internal logic in rk3x can support 50Mhz"
+ */
+#define ROCKCHIP_SPI_MAX_RATE		50000000
 
 #endif /* __RK_SPI_H */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e29c3fc..446cca9 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -425,15 +425,7 @@
 	 Set maximum framebuffer size to be used for Freescale Display
 	 Controller Unit (DCU4).
 
-config VIDEO_ROCKCHIP
-	bool "Enable Rockchip video support"
-	depends on DM_VIDEO
-	help
-	   Rockchip SoCs provide video output capabilities for High-Definition
-	   Multimedia Interface (HDMI), Low-voltage Differential Signalling
-	   (LVDS), embedded DisplayPort (eDP) and Display Serial Interface
-	   (DSI). This driver supports the on-chip video output device, and
-	   targets the Rockchip RK3288.
+source "drivers/video/rockchip/Kconfig"
 
 config VIDEO_SANDBOX_SDL
 	bool "Enable sandbox video console using SDL"
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
new file mode 100644
index 0000000..9267b2878
--- /dev/null
+++ b/drivers/video/rockchip/Kconfig
@@ -0,0 +1,50 @@
+#
+# Video drivers selection for rockchip soc. These configs only impact the
+# compile process. You can surely check all the options. In this case, all the
+# display driver will be compiled, but which drivers finally  will be used is
+# decided by device tree configuration. What's more, enable needed power for
+# display by configure the device tree, and the vop driver will do the rest.
+#
+# Author: Eric Gao <eric.gao@rock-chips.com>
+#
+
+menuconfig VIDEO_ROCKCHIP
+	bool "Enable Rockchip Video Support"
+	depends on DM_VIDEO
+	help
+		Rockchip SoCs provide video output capabilities for High-Definition
+		Multimedia Interface (HDMI), Low-voltage Differential Signalling
+		(LVDS), embedded DisplayPort (eDP) and Display Serial Interface
+		(DSI). This driver supports the on-chip video output device, and
+		targets the Rockchip RK3288 and RK3399.
+
+if VIDEO_ROCKCHIP
+
+config DISPLAY_ROCKCHIP_EDP
+	bool "EDP Port"
+	depends on VIDEO_ROCKCHIP
+	help
+	  This enables Embedded DisplayPort(EDP) display support.
+
+config DISPLAY_ROCKCHIP_LVDS
+	bool "LVDS Port"
+	depends on VIDEO_ROCKCHIP
+	help
+	  This enables Low-voltage Differential Signaling(LVDS) display
+	  support.
+
+config DISPLAY_ROCKCHIP_HDMI
+	bool "HDMI port"
+	depends on VIDEO_ROCKCHIP
+	help
+	  This enables High-Definition Multimedia Interface display support.
+
+config DISPLAY_ROCKCHIP_MIPI
+	bool "MIPI Port"
+	depends on VIDEO_ROCKCHIP
+	help
+	  This enables Mobile Industry Processor Interface(MIPI) display
+	  support. The mipi controller and dphy on rk3288& rk3399 support
+	  16,18, 24 bits per pixel with upto 2k resolution ratio.
+
+endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 755350b..c742902 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -5,4 +5,10 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += rk_edp.o rk_hdmi.o rk_vop.o rk_lvds.o ../dw_hdmi.o
+ifdef CONFIG_VIDEO_ROCKCHIP
+obj-y += rk_vop.o
+obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
+obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
+obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o ../dw_hdmi.o
+obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o
+endif
diff --git a/drivers/video/rockchip/rk_mipi.c b/drivers/video/rockchip/rk_mipi.c
new file mode 100644
index 0000000..4d9d12e
--- /dev/null
+++ b/drivers/video/rockchip/rk_mipi.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Eric Gao <eric.gao@rock-chips.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <panel.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <dm/uclass-internal.h>
+#include <linux/kernel.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3399.h>
+#include <asm/arch/grf_rk3399.h>
+#include <asm/arch/rockchip_mipi_dsi.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Private information for rk mipi
+ *
+ * @regs: mipi controller address
+ * @grf: GRF register
+ * @panel: panel assined by device tree
+ * @ref_clk: reference clock for mipi dsi pll
+ * @sysclk: config clock for mipi dsi register
+ * @pix_clk: pixel clock for vop->dsi data transmission
+ * @phy_clk: mipi dphy output clock
+ * @txbyte_clk: clock for dsi->dphy high speed data transmission
+ * @txesc_clk: clock for tx esc mode
+ */
+struct rk_mipi_priv {
+	void __iomem *regs;
+	struct rk3399_grf_regs *grf;
+	struct udevice *panel;
+	struct mipi_dsi *dsi;
+	u32 ref_clk;
+	u32 sys_clk;
+	u32 pix_clk;
+	u32 phy_clk;
+	u32 txbyte_clk;
+	u32 txesc_clk;
+};
+
+static int rk_mipi_read_timing(struct udevice *dev,
+			       struct display_timing *timing)
+{
+	int ret;
+
+	ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(dev),
+					 0, timing);
+	if (ret) {
+		debug("%s: Failed to decode display timing (ret=%d)\n",
+		      __func__, ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Register write function used only for mipi dsi controller.
+ * Parameter:
+ *  @regs: mipi controller address
+ *  @reg: combination of regaddr(16bit)|bitswidth(8bit)|offset(8bit) you can
+ *        use define in rk_mipi.h directly for this parameter
+ *  @val: value that will be write to specified bits of register
+ */
+static void rk_mipi_dsi_write(u32 regs, u32 reg, u32 val)
+{
+	u32 dat;
+	u32 mask;
+	u32 offset = (reg >> OFFSET_SHIFT) & 0xff;
+	u32 bits = (reg >> BITS_SHIFT) & 0xff;
+	u64 addr = (reg >> ADDR_SHIFT) + regs;
+
+	/* Mask for specifiled bits,the corresponding bits will be clear */
+	mask = ~((0xffffffff << offset) & (0xffffffff >> (32 - offset - bits)));
+
+	/* Make sure val in the available range */
+	val &= ~(0xffffffff << bits);
+
+	/* Get register's original val */
+	dat = readl(addr);
+
+	/* Clear specified bits */
+	dat &= mask;
+
+	/* Fill specified bits */
+	dat |= val << offset;
+
+	writel(dat, addr);
+}
+
+static int rk_mipi_dsi_enable(struct udevice *dev,
+			      const struct display_timing *timing)
+{
+	int node, timing_node;
+	int val;
+	struct rk_mipi_priv *priv = dev_get_priv(dev);
+	u64 regs = (u64)priv->regs;
+	struct display_plat *disp_uc_plat = dev_get_uclass_platdata(dev);
+	u32 txbyte_clk = priv->txbyte_clk;
+	u32 txesc_clk = priv->txesc_clk;
+
+	txesc_clk = txbyte_clk/(txbyte_clk/txesc_clk + 1);
+
+	/* Select the video source */
+	switch (disp_uc_plat->source_id) {
+	case VOP_B:
+		rk_clrsetreg(&priv->grf->soc_con20, GRF_DSI0_VOP_SEL_MASK,
+			     GRF_DSI0_VOP_SEL_B << GRF_DSI0_VOP_SEL_SHIFT);
+		 break;
+	case VOP_L:
+		rk_clrsetreg(&priv->grf->soc_con20, GRF_DSI0_VOP_SEL_MASK,
+			     GRF_DSI0_VOP_SEL_L << GRF_DSI0_VOP_SEL_SHIFT);
+		 break;
+	default:
+		 debug("%s: Invalid VOP id\n", __func__);
+		 return -EINVAL;
+	}
+
+	/* Set Controller as TX mode */
+	val = GRF_DPHY_TX0_RXMODE_DIS << GRF_DPHY_TX0_RXMODE_SHIFT;
+	rk_clrsetreg(&priv->grf->soc_con22, GRF_DPHY_TX0_RXMODE_MASK, val);
+
+	/* Exit tx stop mode */
+	val |= GRF_DPHY_TX0_TXSTOPMODE_DIS << GRF_DPHY_TX0_TXSTOPMODE_SHIFT;
+	rk_clrsetreg(&priv->grf->soc_con22, GRF_DPHY_TX0_TXSTOPMODE_MASK, val);
+
+	/* Disable turnequest */
+	val |= GRF_DPHY_TX0_TURNREQUEST_DIS << GRF_DPHY_TX0_TURNREQUEST_SHIFT;
+	rk_clrsetreg(&priv->grf->soc_con22, GRF_DPHY_TX0_TURNREQUEST_MASK, val);
+
+	/* Set Display timing parameter */
+	rk_mipi_dsi_write(regs, VID_HSA_TIME, timing->hsync_len.typ);
+	rk_mipi_dsi_write(regs, VID_HBP_TIME, timing->hback_porch.typ);
+	rk_mipi_dsi_write(regs, VID_HLINE_TIME, (timing->hsync_len.typ
+			  + timing->hback_porch.typ + timing->hactive.typ
+			  + timing->hfront_porch.typ));
+	rk_mipi_dsi_write(regs, VID_VSA_LINES, timing->vsync_len.typ);
+	rk_mipi_dsi_write(regs, VID_VBP_LINES, timing->vback_porch.typ);
+	rk_mipi_dsi_write(regs, VID_VFP_LINES, timing->vfront_porch.typ);
+	rk_mipi_dsi_write(regs, VID_ACTIVE_LINES, timing->vactive.typ);
+
+	/* Set Signal Polarity */
+	val = (timing->flags & DISPLAY_FLAGS_HSYNC_LOW) ? 1 : 0;
+	rk_mipi_dsi_write(regs, HSYNC_ACTIVE_LOW, val);
+
+	val = (timing->flags & DISPLAY_FLAGS_VSYNC_LOW) ? 1 : 0;
+	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);
+
+	val = (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) ? 1 : 0;
+	rk_mipi_dsi_write(regs, COLORM_ACTIVE_LOW, val);
+
+	/* Set video mode */
+	rk_mipi_dsi_write(regs, CMD_VIDEO_MODE, VIDEO_MODE);
+
+	/* Set video mode transmission type as burst mode */
+	rk_mipi_dsi_write(regs, VID_MODE_TYPE, BURST_MODE);
+
+	/* Set pix num in a video package */
+	rk_mipi_dsi_write(regs, VID_PKT_SIZE, 0x4b0);
+
+	/* Set dpi color coding depth 24 bit */
+	timing_node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(dev),
+									 "display-timings");
+	node = fdt_first_subnode(gd->fdt_blob, timing_node);
+	val = fdtdec_get_int(gd->fdt_blob, node, "bits-per-pixel", -1);
+	switch (val) {
+	case 16:
+		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_16BIT_CFG_1);
+		break;
+	case 24:
+		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_24BIT);
+		break;
+	case 30:
+		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_30BIT);
+		break;
+	default:
+		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_24BIT);
+	}
+	/* Enable low power mode */
+	rk_mipi_dsi_write(regs, LP_CMD_EN, 1);
+	rk_mipi_dsi_write(regs, LP_HFP_EN, 1);
+	rk_mipi_dsi_write(regs, LP_VACT_EN, 1);
+	rk_mipi_dsi_write(regs, LP_VFP_EN, 1);
+	rk_mipi_dsi_write(regs, LP_VBP_EN, 1);
+	rk_mipi_dsi_write(regs, LP_VSA_EN, 1);
+
+	/* Division for timeout counter clk */
+	rk_mipi_dsi_write(regs, TO_CLK_DIVISION, 0x0a);
+
+	/* Tx esc clk division from txbyte clk */
+	rk_mipi_dsi_write(regs, TX_ESC_CLK_DIVISION, txbyte_clk/txesc_clk);
+
+	/* Timeout count for hs<->lp transation between Line period */
+	rk_mipi_dsi_write(regs, HSTX_TO_CNT, 0x3e8);
+
+	/* Phy State transfer timing */
+	rk_mipi_dsi_write(regs, PHY_STOP_WAIT_TIME, 32);
+	rk_mipi_dsi_write(regs, PHY_TXREQUESTCLKHS, 1);
+	rk_mipi_dsi_write(regs, PHY_HS2LP_TIME, 0x14);
+	rk_mipi_dsi_write(regs, PHY_LP2HS_TIME, 0x10);
+	rk_mipi_dsi_write(regs, MAX_RD_TIME, 0x2710);
+
+	/* Power on */
+	rk_mipi_dsi_write(regs, SHUTDOWNZ, 1);
+
+	return 0;
+}
+
+/* rk mipi dphy write function. It is used to write test data to dphy */
+static void rk_mipi_phy_write(u32 regs, unsigned char test_code,
+			      unsigned char *test_data, unsigned char size)
+{
+	int i = 0;
+
+	/* Write Test code */
+	rk_mipi_dsi_write(regs, PHY_TESTCLK, 1);
+	rk_mipi_dsi_write(regs, PHY_TESTDIN, test_code);
+	rk_mipi_dsi_write(regs, PHY_TESTEN, 1);
+	rk_mipi_dsi_write(regs, PHY_TESTCLK, 0);
+	rk_mipi_dsi_write(regs, PHY_TESTEN, 0);
+
+	/* Write Test data */
+	for (i = 0; i < size; i++) {
+		rk_mipi_dsi_write(regs, PHY_TESTCLK, 0);
+		rk_mipi_dsi_write(regs, PHY_TESTDIN, test_data[i]);
+		rk_mipi_dsi_write(regs, PHY_TESTCLK, 1);
+	}
+}
+
+/*
+ * Mipi dphy config function. Calculate the suitable prediv, feedback div,
+ * fsfreqrang value ,cap ,lpf and so on according to the given pix clk rate,
+ * and then enable phy.
+ */
+static int rk_mipi_phy_enable(struct udevice *dev)
+{
+	int i;
+	struct rk_mipi_priv *priv = dev_get_priv(dev);
+	u64 regs = (u64)priv->regs;
+	u64 fbdiv;
+	u64 prediv = 1;
+	u32 max_fbdiv = 512;
+	u32 max_prediv, min_prediv;
+	u64 ddr_clk = priv->phy_clk;
+	u32 refclk = priv->ref_clk;
+	u32 remain = refclk;
+	unsigned char test_data[2] = {0};
+
+	int freq_rang[][2] = {
+		{90, 0x01},   {100, 0x10},  {110, 0x20},  {130, 0x01},
+		{140, 0x11},  {150, 0x21},  {170, 0x02},  {180, 0x12},
+		{200, 0x22},  {220, 0x03},  {240, 0x13},  {250, 0x23},
+		{270, 0x04},  {300, 0x14},  {330, 0x05},  {360, 0x15},
+		{400, 0x25},  {450, 0x06},  {500, 0x16},  {550, 0x07},
+		{600, 0x17},  {650, 0x08},  {700, 0x18},  {750, 0x09},
+		{800, 0x19},  {850, 0x29},  {900, 0x39},  {950, 0x0a},
+		{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
+		{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
+		{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
+	};
+
+	/* Shutdown mode */
+	rk_mipi_dsi_write(regs, PHY_SHUTDOWNZ, 0);
+	rk_mipi_dsi_write(regs, PHY_RSTZ, 0);
+	rk_mipi_dsi_write(regs, PHY_TESTCLR, 1);
+
+	/* Pll locking */
+	rk_mipi_dsi_write(regs, PHY_TESTCLR, 0);
+
+	/* config cp and lfp */
+	test_data[0] = 0x80 | (ddr_clk / (200 * MHz)) << 3 | 0x3;
+	rk_mipi_phy_write(regs, CODE_PLL_VCORANGE_VCOCAP, test_data, 1);
+
+	test_data[0] = 0x8;
+	rk_mipi_phy_write(regs, CODE_PLL_CPCTRL, test_data, 1);
+
+	test_data[0] = 0x80 | 0x40;
+	rk_mipi_phy_write(regs, CODE_PLL_LPF_CP, test_data, 1);
+
+	/* select the suitable value for fsfreqrang reg */
+	for (i = 0; i < ARRAY_SIZE(freq_rang); i++) {
+		if (ddr_clk / (MHz) >= freq_rang[i][0])
+			break;
+	}
+	if (i == ARRAY_SIZE(freq_rang)) {
+		debug("%s: Dphy freq out of range!\n", __func__);
+		return -EINVAL;
+	}
+	test_data[0] = freq_rang[i][1] << 1;
+	rk_mipi_phy_write(regs, CODE_HS_RX_LANE0, test_data, 1);
+
+	/*
+	 * Calculate the best ddrclk and it's corresponding div value. If the
+	 * given pixelclock is great than 250M, ddrclk will be fix 1500M.
+	 * Otherwise,
+	 * it's equal to ddr_clk= pixclk * 6. 40MHz >= refclk / prediv >= 5MHz
+	 * according to spec.
+	 */
+	max_prediv = (refclk / (5 * MHz));
+	min_prediv = ((refclk / (40 * MHz)) ? (refclk / (40 * MHz) + 1) : 1);
+
+	debug("%s: DEBUG: max_prediv=%u, min_prediv=%u\n", __func__, max_prediv,
+	      min_prediv);
+
+	if (max_prediv < min_prediv) {
+		debug("%s: Invalid refclk value\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Calculate the best refclk and feedback division value for dphy pll */
+	for (i = min_prediv; i < max_prediv; i++) {
+		if ((ddr_clk * i % refclk < remain) &&
+		    (ddr_clk * i / refclk) < max_fbdiv) {
+			prediv = i;
+			remain = ddr_clk * i % refclk;
+		}
+	}
+	fbdiv = ddr_clk * prediv / refclk;
+	ddr_clk = refclk * fbdiv / prediv;
+	priv->phy_clk = ddr_clk;
+
+	debug("%s: DEBUG: refclk=%u, refclk=%llu, fbdiv=%llu, phyclk=%llu\n",
+	      __func__, refclk, prediv, fbdiv, ddr_clk);
+
+	/* config prediv and feedback reg */
+	test_data[0] = prediv - 1;
+	rk_mipi_phy_write(regs, CODE_PLL_INPUT_DIV_RAT, test_data, 1);
+	test_data[0] = (fbdiv - 1) & 0x1f;
+	rk_mipi_phy_write(regs, CODE_PLL_LOOP_DIV_RAT, test_data, 1);
+	test_data[0] = (fbdiv - 1) >> 5 | 0x80;
+	rk_mipi_phy_write(regs, CODE_PLL_LOOP_DIV_RAT, test_data, 1);
+	test_data[0] = 0x30;
+	rk_mipi_phy_write(regs, CODE_PLL_INPUT_LOOP_DIV_RAT, test_data, 1);
+
+	/* rest config */
+	test_data[0] = 0x4d;
+	rk_mipi_phy_write(regs, CODE_BANDGAP_BIAS_CTRL, test_data, 1);
+
+	test_data[0] = 0x3d;
+	rk_mipi_phy_write(regs, CODE_TERMINATION_CTRL, test_data, 1);
+
+	test_data[0] = 0xdf;
+	rk_mipi_phy_write(regs, CODE_TERMINATION_CTRL, test_data, 1);
+
+	test_data[0] =  0x7;
+	rk_mipi_phy_write(regs, CODE_AFE_BIAS_BANDGAP_ANOLOG, test_data, 1);
+
+	test_data[0] = 0x80 | 0x7;
+	rk_mipi_phy_write(regs, CODE_AFE_BIAS_BANDGAP_ANOLOG, test_data, 1);
+
+	test_data[0] = 0x80 | 15;
+	rk_mipi_phy_write(regs, CODE_HSTXDATALANEREQUSETSTATETIME,
+			  test_data, 1);
+	test_data[0] = 0x80 | 85;
+	rk_mipi_phy_write(regs, CODE_HSTXDATALANEPREPARESTATETIME,
+			  test_data, 1);
+	test_data[0] = 0x40 | 10;
+	rk_mipi_phy_write(regs, CODE_HSTXDATALANEHSZEROSTATETIME,
+			  test_data, 1);
+
+	/* enter into stop mode */
+	rk_mipi_dsi_write(regs, N_LANES, 0x03);
+	rk_mipi_dsi_write(regs, PHY_ENABLECLK, 1);
+	rk_mipi_dsi_write(regs, PHY_FORCEPLL, 1);
+	rk_mipi_dsi_write(regs, PHY_SHUTDOWNZ, 1);
+	rk_mipi_dsi_write(regs, PHY_RSTZ, 1);
+
+	return 0;
+}
+
+/*
+ * This function is called by rk_display_init() using rk_mipi_dsi_enable() and
+ * rk_mipi_phy_enable() to initialize mipi controller and dphy. If success,
+ * enable backlight.
+ */
+static int rk_display_enable(struct udevice *dev, int panel_bpp,
+			  const struct display_timing *timing)
+{
+	int ret;
+	struct rk_mipi_priv *priv = dev_get_priv(dev);
+
+	/* Fill the mipi controller parameter */
+	priv->ref_clk = 24 * MHz;
+	priv->sys_clk = priv->ref_clk;
+	priv->pix_clk = timing->pixelclock.typ;
+	priv->phy_clk = priv->pix_clk * 6;
+	priv->txbyte_clk = priv->phy_clk / 8;
+	priv->txesc_clk = 20 * MHz;
+
+	/* Config  and enable mipi dsi according to timing */
+	ret = rk_mipi_dsi_enable(dev, timing);
+	if (ret) {
+		debug("%s: rk_mipi_dsi_enable() failed (err=%d)\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	/* Config and enable mipi phy */
+	ret = rk_mipi_phy_enable(dev);
+	if (ret) {
+		debug("%s: rk_mipi_phy_enable() failed (err=%d)\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	/* Enable backlight */
+	ret = panel_enable_backlight(priv->panel);
+	if (ret) {
+		debug("%s: panel_enable_backlight() failed (err=%d)\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rk_mipi_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk_mipi_priv *priv = dev_get_priv(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (priv->grf <= 0) {
+		debug("%s: Get syscon grf failed (ret=%llu)\n",
+		      __func__, (u64)priv->grf);
+		return  -ENXIO;
+	}
+	priv->regs = (void *)dev_get_addr(dev);
+	if (priv->regs <= 0) {
+		debug("%s: Get MIPI dsi address failed (ret=%llu)\n", __func__,
+		      (u64)priv->regs);
+		return  -ENXIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Probe function: check panel existence and readingit's timing. Then config
+ * mipi dsi controller and enable it according to the timing parameter.
+ */
+static int rk_mipi_probe(struct udevice *dev)
+{
+	int ret;
+	struct rk_mipi_priv *priv = dev_get_priv(dev);
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "rockchip,panel",
+					   &priv->panel);
+	if (ret) {
+		debug("%s: Can not find panel (err=%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dm_display_ops rk_mipi_dsi_ops = {
+	.read_timing = rk_mipi_read_timing,
+	.enable = rk_display_enable,
+};
+
+static const struct udevice_id rk_mipi_dsi_ids[] = {
+	{ .compatible = "rockchip,rk3399_mipi_dsi" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk_mipi_dsi) = {
+	.name	= "rk_mipi_dsi",
+	.id	= UCLASS_DISPLAY,
+	.of_match = rk_mipi_dsi_ids,
+	.ofdata_to_platdata = rk_mipi_ofdata_to_platdata,
+	.probe	= rk_mipi_probe,
+	.ops	= &rk_mipi_dsi_ops,
+	.priv_auto_alloc_size   = sizeof(struct rk_mipi_priv),
+};
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index bc02f80..aa6ca8c 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -117,6 +117,10 @@
 		clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
 				V_RGB_OUT_EN(1));
 		break;
+	case VOP_MODE_MIPI:
+		clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN,
+				V_MIPI_OUT_EN(1));
+		 break;
 	}
 
 	if (mode == VOP_MODE_HDMI || mode == VOP_MODE_EDP)
@@ -177,13 +181,11 @@
  *
  * @dev:	VOP device that we want to connect to the display
  * @fbbase:	Frame buffer address
- * @l2bpp	Log2 of bits-per-pixels for the display
  * @ep_node:	Device tree node to process - this is the offset of an endpoint
  *		node within the VOP's 'port' list.
  * @return 0 if OK, -ve if something went wrong
  */
-int rk_display_init(struct udevice *dev, ulong fbbase,
-		    enum video_log2_bpp l2bpp, int ep_node)
+int rk_display_init(struct udevice *dev, ulong fbbase, int ep_node)
 {
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
 	const void *blob = gd->fdt_blob;
@@ -195,6 +197,7 @@
 	int ret, remote, i, offset;
 	struct display_plat *disp_uc_plat;
 	struct clk clk;
+	enum video_log2_bpp l2bpp;
 
 	vop_id = fdtdec_get_int(blob, ep_node, "reg", -1);
 	debug("vop_id=%d\n", vop_id);
@@ -244,11 +247,24 @@
 	ret = clk_get_by_index(dev, 1, &clk);
 	if (!ret)
 		ret = clk_set_rate(&clk, timing.pixelclock.typ);
-	if (ret) {
+	if (IS_ERR_VALUE(ret)) {
 		debug("%s: Failed to set pixel clock: ret=%d\n", __func__, ret);
 		return ret;
 	}
 
+	/* Set bitwidth for vop display according to vop mode */
+	switch (vop_id) {
+	case VOP_MODE_EDP:
+	case VOP_MODE_HDMI:
+	case VOP_MODE_LVDS:
+		l2bpp = VIDEO_BPP16;
+		break;
+	case VOP_MODE_MIPI:
+		l2bpp = VIDEO_BPP32;
+		break;
+	default:
+		l2bpp = VIDEO_BPP16;
+	}
 	rkvop_mode_set(regs, &timing, vop_id);
 
 	rkvop_enable(regs, fbbase, 1 << l2bpp, &timing);
@@ -326,7 +342,7 @@
 	for (node = fdt_first_subnode(blob, port);
 	     node > 0;
 	     node = fdt_next_subnode(blob, node)) {
-		ret = rk_display_init(dev, plat->base, VIDEO_BPP16, node);
+		ret = rk_display_init(dev, plat->base, node);
 		if (ret)
 			debug("Device failed: ret=%d\n", ret);
 		if (!ret)
@@ -341,7 +357,7 @@
 {
 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
 
-	plat->size = 1920 * 1080 * 2;
+	plat->size = 1920 * 1200 * 4;
 
 	return 0;
 }
@@ -350,6 +366,8 @@
 };
 
 static const struct udevice_id rk_vop_ids[] = {
+	{ .compatible = "rockchip,rk3399-vop-big" },
+	{ .compatible = "rockchip,rk3399-vop-lit" },
 	{ .compatible = "rockchip,rk3288-vop" },
 	{ }
 };
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index b7b89b0..49f56f2 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -18,6 +18,9 @@
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_DRIVERS_MISC_SUPPORT
 #define CONFIG_SPL_SERIAL_SUPPORT
+#if defined(CONFIG_SPL_SPI_SUPPORT)
+#define CONFIG_SPL_SPI_LOAD
+#endif
 
 #define COUNTER_FREQUENCY               24000000
 
diff --git a/include/dt-bindings/pinctrl/rockchip.h b/include/dt-bindings/pinctrl/rockchip.h
index ecb76c7..0798287 100644
--- a/include/dt-bindings/pinctrl/rockchip.h
+++ b/include/dt-bindings/pinctrl/rockchip.h
@@ -4,7 +4,7 @@
  * Copyright (c) 2013 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
@@ -17,6 +17,39 @@
 #define RK_GPIO4	4
 #define RK_GPIO6	6
 
+#define RK_PA0		0
+#define RK_PA1		1
+#define RK_PA2		2
+#define RK_PA3		3
+#define RK_PA4		4
+#define RK_PA5		5
+#define RK_PA6		6
+#define RK_PA7		7
+#define RK_PB0		8
+#define RK_PB1		9
+#define RK_PB2		10
+#define RK_PB3		11
+#define RK_PB4		12
+#define RK_PB5		13
+#define RK_PB6		14
+#define RK_PB7		15
+#define RK_PC0		16
+#define RK_PC1		17
+#define RK_PC2		18
+#define RK_PC3		19
+#define RK_PC4		20
+#define RK_PC5		21
+#define RK_PC6		22
+#define RK_PC7		23
+#define RK_PD0		24
+#define RK_PD1		25
+#define RK_PD2		26
+#define RK_PD3		27
+#define RK_PD4		28
+#define RK_PD5		29
+#define RK_PD6		30
+#define RK_PD7		31
+
 #define RK_FUNC_GPIO	0
 #define RK_FUNC_1	1
 #define RK_FUNC_2	2
diff --git a/include/dt-bindings/power/rk3399-power.h b/include/dt-bindings/power/rk3399-power.h
new file mode 100644
index 0000000..168b3bf
--- /dev/null
+++ b/include/dt-bindings/power/rk3399-power.h
@@ -0,0 +1,53 @@
+#ifndef __DT_BINDINGS_POWER_RK3399_POWER_H__
+#define __DT_BINDINGS_POWER_RK3399_POWER_H__
+
+/* VD_CORE_L */
+#define RK3399_PD_A53_L0	0
+#define RK3399_PD_A53_L1	1
+#define RK3399_PD_A53_L2	2
+#define RK3399_PD_A53_L3	3
+#define RK3399_PD_SCU_L		4
+
+/* VD_CORE_B */
+#define RK3399_PD_A72_B0	5
+#define RK3399_PD_A72_B1	6
+#define RK3399_PD_SCU_B		7
+
+/* VD_LOGIC */
+#define RK3399_PD_TCPD0		8
+#define RK3399_PD_TCPD1		9
+#define RK3399_PD_CCI		10
+#define RK3399_PD_CCI0		11
+#define RK3399_PD_CCI1		12
+#define RK3399_PD_PERILP	13
+#define RK3399_PD_PERIHP	14
+#define RK3399_PD_VIO		15
+#define RK3399_PD_VO		16
+#define RK3399_PD_VOPB		17
+#define RK3399_PD_VOPL		18
+#define RK3399_PD_ISP0		19
+#define RK3399_PD_ISP1		20
+#define RK3399_PD_HDCP		21
+#define RK3399_PD_GMAC		22
+#define RK3399_PD_EMMC		23
+#define RK3399_PD_USB3		24
+#define RK3399_PD_EDP		25
+#define RK3399_PD_GIC		26
+#define RK3399_PD_SD		27
+#define RK3399_PD_SDIOAUDIO	28
+#define RK3399_PD_ALIVE		29
+
+/* VD_CENTER */
+#define RK3399_PD_CENTER	30
+#define RK3399_PD_VCODEC	31
+#define RK3399_PD_VDU		32
+#define RK3399_PD_RGA		33
+#define RK3399_PD_IEP		34
+
+/* VD_GPU */
+#define RK3399_PD_GPU		35
+
+/* VD_PMU */
+#define RK3399_PD_PMU		36
+
+#endif
diff --git a/include/i2c_eeprom.h b/include/i2c_eeprom.h
index 0452892..bb5c6b1 100644
--- a/include/i2c_eeprom.h
+++ b/include/i2c_eeprom.h
@@ -20,4 +20,28 @@
 	unsigned pagewidth;
 };
 
+/*
+ * i2c_eeprom_read() - read bytes from an I2C EEPROM chip
+ *
+ * @dev:	Chip to read from
+ * @offset:	Offset within chip to start reading
+ * @buf:	Place to put data
+ * @size:	Number of bytes to read
+ *
+ * @return 0 on success, -ve on failure
+ */
+int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size);
+
+/*
+ * i2c_eeprom_write() - write bytes to an I2C EEPROM chip
+ *
+ * @dev:	Chip to write to
+ * @offset:	Offset within chip to start writing
+ * @buf:	Buffer containing data to write
+ * @size:	Number of bytes to write
+ *
+ * @return 0 on success, -ve on failure
+ */
+int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size);
+
 #endif
diff --git a/include/power/rk808_pmic.h b/include/power/rk808_pmic.h
deleted file mode 100644
index fb0800b..0000000
--- a/include/power/rk808_pmic.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2015 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef _PMIC_RK808_H_
-#define _PMIC_RK808_H_
-
-enum {
-	REG_DCDC_EN			= 0x23,
-	REG_LDO_EN,
-	REG_SLEEP_SET_OFF1,
-	REG_SLEEP_SET_OFF2,
-	REG_DCDC_UV_STS,
-
-	REG_DCDC_UV_ACT,
-	REG_LDO_UV_STS,
-	REG_LDO_UV_ACT,
-	REG_DCDC_PG,
-	REG_LDO_PG,
-	REG_VOUT_MON_TDB,
-	REG_BUCK1_CONFIG,
-	REG_BUCK1_ON_VSEL,
-
-	REG_BUCK1_SLP_VSEL,
-	REG_BUCK1_DVS_VSEL,
-	REG_BUCK2_CONFIG,
-	REG_BUCK2_ON_VSEL,
-	REG_BUCK2_SLP_VSEL,
-	REG_BUCK2_DVS_VSEL,
-	REG_BUCK3_CONFIG,
-	REG_BUCK4_CONFIG,
-
-	REG_BUCK4_ON_VSEL,
-	REG_BUCK4_SLP_VSEL,
-	LDO1_ON_VSEL			= 0x3b,
-	LDO1_SLP_VSEL,
-	LDO2_ON_VSEL,
-	LDO2_SLP_VSEL,
-	LDO3_ON_VSEL,
-
-	LDO3_SLP_VSEL,
-	LDO4_ON_VSEL,
-	LDO4_SLP_VSEL,
-	LDO5_ON_VSEL,
-	LDO5_SLP_VSEL,
-	LDO6_ON_VSEL,
-	LDO6_SLP_VSEL,
-	LDO7_ON_VSEL,
-
-	LDO7_SLP_VSEL,
-	LDO8_ON_VSEL,
-	LDO8_SLP_VSEL,
-	DEVCTRL,
-	INT_STS1,
-	INT_STS_MSK1,
-	INT_STS2,
-	INT_STS_MSK2,
-	IO_POL,
-
-	/* Not sure what this does */
-	DCDC_ILMAX			= 0x90,
-
-	RK808_NUM_OF_REGS,
-};
-
-struct rk808_reg_table {
-	char *name;
-	u8 reg_ctl;
-	u8 reg_vol;
-};
-
-int rk808_spl_configure_buck(struct udevice *pmic, int buck, int uvolt);
-
-#endif
diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h
new file mode 100644
index 0000000..589f8c4
--- /dev/null
+++ b/include/power/rk8xx_pmic.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _PMIC_RK8XX_H_
+#define _PMIC_RK8XX_H_
+
+enum {
+	REG_SECONDS			= 0x00,
+	REG_MINUTES,
+	REG_HOURS,
+	REG_DAYS,
+	REG_MONTHS,
+	REG_YEARS,
+	REG_WEEKS,
+	REG_ALARM_SECONDS,
+	REG_ALARM_MINUTES,
+	REG_ALARM_HOURS,
+	REG_ALARM_DAYS,
+	REG_ALARM_MONTHS,
+	REG_ALARM_YEARS,
+
+	REG_RTC_CTRL			= 0x10,
+	REG_RTC_STATUS,
+	REG_RTC_INT,
+	REG_RTC_COMP_LSB,
+	REG_RTC_COMP_MSB,
+
+	ID_MSB				= 0x17,
+	ID_LSB,
+
+	REG_CLK32OUT			= 0x20,
+	REG_VB_MON,
+	REG_THERMAL,
+	REG_DCDC_EN,
+	REG_LDO_EN,
+	REG_SLEEP_SET_OFF1,
+	REG_SLEEP_SET_OFF2,
+	REG_DCDC_UV_STS,
+	REG_DCDC_UV_ACT,
+	REG_LDO_UV_STS,
+	REG_LDO_UV_ACT,
+	REG_DCDC_PG,
+	REG_LDO_PG,
+	REG_VOUT_MON_TDB,
+	REG_BUCK1_CONFIG,
+	REG_BUCK1_ON_VSEL,
+	REG_BUCK1_SLP_VSEL,
+	REG_BUCK1_DVS_VSEL,
+	REG_BUCK2_CONFIG,
+	REG_BUCK2_ON_VSEL,
+	REG_BUCK2_SLP_VSEL,
+	REG_BUCK2_DVS_VSEL,
+	REG_BUCK3_CONFIG,
+	REG_BUCK4_CONFIG,
+	REG_BUCK4_ON_VSEL,
+	REG_BUCK4_SLP_VSEL,
+	REG_BOOST_CONFIG_REG,
+	REG_LDO1_ON_VSEL,
+	REG_LDO1_SLP_VSEL,
+	REG_LDO2_ON_VSEL,
+	REG_LDO2_SLP_VSEL,
+	REG_LDO3_ON_VSEL,
+	REG_LDO3_SLP_VSEL,
+	REG_LDO4_ON_VSEL,
+	REG_LDO4_SLP_VSEL,
+	REG_LDO5_ON_VSEL,
+	REG_LDO5_SLP_VSEL,
+	REG_LDO6_ON_VSEL,
+	REG_LDO6_SLP_VSEL,
+	REG_LDO7_ON_VSEL,
+	REG_LDO7_SLP_VSEL,
+	REG_LDO8_ON_VSEL,
+	REG_LDO8_SLP_VSEL,
+	REG_DEVCTRL,
+	REG_INT_STS1,
+	REG_INT_STS_MSK1,
+	REG_INT_STS2,
+	REG_INT_STS_MSK2,
+	REG_IO_POL,
+	REG_OTP_VDD_EN,
+	REG_H5V_EN,
+	REG_SLEEP_SET_OFF,
+	REG_BOOST_LDO9_ON_VSEL,
+	REG_BOOST_LDO9_SLP_VSEL,
+	REG_BOOST_CTRL,
+
+	/* Not sure what this does */
+	REG_DCDC_ILMAX			= 0x90,
+	REG_CHRG_COMP			= 0x9a,
+	REG_SUP_STS			= 0xa0,
+	REG_USB_CTRL,
+	REG1_CHRG_CTRL,
+	REG2_CHRG_CTRL,
+	REG3_CHRG_CTRL,
+	REG_BAT_CTRL,
+	REG_BAT_HTS_TS1,
+	REG_BAT_LTS_TS1,
+	REG_BAT_HTS_TS2,
+	REG_BAT_LTS_TS2,
+	REG_TS_CTRL,
+	REG_ADC_CTRL,
+	REG_ON_SOURCE,
+	REG_OFF_SOURCE,
+	REG_GGCON,
+	REG_GGSTS,
+	REG_FRAME_SMP_INTERV,
+	REG_AUTO_SLP_CUR_THR,
+	REG3_GASCNT_CAL,
+	REG2_GASCNT_CAL,
+	REG1_GASCNT_CAL,
+	REG0_GASCNT_CAL,
+	REG3_GASCNT,
+	REG2_GASCNT,
+	REG1_GASCNT,
+	REG0_GASCNT,
+	REGH_BAT_CUR_AVG,
+	REGL_BAT_CUR_AVG,
+	REGH_TS1_ADC,
+	REGL_TS1_ADC,
+	REGH_TS2_ADC,
+	REGL_TS2_ADC,
+	REGH_BAT_OCV,
+	REGL_BAT_OCV,
+	REGH_BAT_VOL,
+	REGL_BAT_VOL,
+	REGH_RELAX_ENTRY_THRES,
+	REGL_RELAX_ENTRY_THRES,
+	REGH_RELAX_EXIT_THRES,
+	REGL_RELAX_EXIT_THRES,
+	REGH_RELAX_VOL1,
+	REGL_RELAX_VOL1,
+	REGH_RELAX_VOL2,
+	REGL_RELAX_VOL2,
+	REGH_BAT_CUR_R_CALC,
+	REGL_BAT_CUR_R_CALC,
+	REGH_BAT_VOL_R_CALC,
+	REGL_BAT_VOL_R_CALC,
+	REGH_CAL_OFFSET,
+	REGL_CAL_OFFSET,
+	REG_NON_ACT_TIMER_CNT,
+	REGH_VCALIB0,
+	REGL_VCALIB0,
+	REGH_VCALIB1,
+	REGL_VCALIB1,
+	REGH_IOFFSET,
+	REGL_IOFFSET,
+	REG_SOC,
+	REG3_REMAIN_CAP,
+	REG2_REMAIN_CAP,
+	REG1_REMAIN_CAP,
+	REG0_REMAIN_CAP,
+	REG_UPDAT_LEVE,
+	REG3_NEW_FCC,
+	REG2_NEW_FCC,
+	REG1_NEW_FCC,
+	REG0_NEW_FCC,
+	REG_NON_ACT_TIMER_CNT_SAVE,
+	REG_OCV_VOL_VALID,
+	REG_REBOOT_CNT,
+	REG_POFFSET,
+	REG_MISC_MARK,
+	REG_HALT_CNT,
+	REGH_CALC_REST,
+	REGL_CALC_REST,
+	SAVE_DATA19,
+	RK808_NUM_OF_REGS,
+};
+
+enum {
+	RK805_ID = 0x8050,
+	RK808_ID = 0x0000,
+	RK818_ID = 0x8180,
+};
+
+#define RK8XX_ID_MSK	0xfff0
+
+struct rk8xx_reg_table {
+	char *name;
+	u8 reg_ctl;
+	u8 reg_vol;
+};
+
+struct rk8xx_priv {
+	int variant;
+};
+
+int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt);
+
+#endif
diff --git a/include/pwm.h b/include/pwm.h
index 851915e..ebee227 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -34,6 +34,15 @@
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*set_enable)(struct udevice *dev, uint channel, bool enable);
+	/**
+	 * set_invert() - Set the PWM invert
+	 *
+	 * @dev:        PWM device to update
+	 * @channel:    PWM channel to update
+	 * @polarity:   true to invert, false to keep normal polarity
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_invert)(struct udevice *dev, uint channel, bool polarity);
 };
 
 #define pwm_get_ops(dev)	((struct pwm_ops *)(dev)->driver->ops)
@@ -60,6 +69,16 @@
  */
 int pwm_set_enable(struct udevice *dev, uint channel, bool enable);
 
+/**
+ * pwm_set_invert() - Set pwm default polarity
+ *
+ * @dev:	PWM device to update
+ * @channel:	PWM channel to update
+ * @polarity:	true to invert, false to keep normal polarity
+ * @return 0 if OK, -ve on error
+ */
+int pwm_set_invert(struct udevice *dev, uint channel, bool polarity);
+
 /* Legacy interface */
 #ifndef CONFIG_DM_PWM
 int	pwm_init		(int pwm_id, int div, int invert);
diff --git a/test/dm/pwm.c b/test/dm/pwm.c
index 7bdc75a..f1e38c7 100644
--- a/test/dm/pwm.c
+++ b/test/dm/pwm.c
@@ -23,6 +23,7 @@
 	ut_assertok(pwm_set_enable(dev, 1, true));
 	ut_assertok(pwm_set_enable(dev, 2, true));
 	ut_asserteq(-ENOSPC, pwm_set_enable(dev, 3, true));
+	ut_assertok(pwm_set_invert(dev, 0, true));
 
 	ut_assertok(uclass_get_device(UCLASS_PWM, 1, &dev));
 	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PWM, 2, &dev));
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
index afc5171..2e0b9c0 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/dtoc.py
@@ -272,6 +272,33 @@
             upto += 1
         return structs
 
+    def ScanPhandles(self):
+        """Figure out what phandles each node uses
+
+        We need to be careful when outputing nodes that use phandles since
+        they must come after the declaration of the phandles in the C file.
+        Otherwise we get a compiler error since the phandle struct is not yet
+        declared.
+
+        This function adds to each node a list of phandle nodes that the node
+        depends on. This allows us to output things in the right order.
+        """
+        for node in self._valid_nodes:
+            node.phandles = set()
+            for pname, prop in node.props.items():
+                if pname in PROP_IGNORE_LIST or pname[0] == '#':
+                    continue
+                if type(prop.value) == list:
+                    if self.IsPhandle(prop):
+                        # Process the list as pairs of (phandle, id)
+                        it = iter(prop.value)
+                        for phandle_cell, id_cell in zip(it, it):
+                            phandle = fdt_util.fdt32_to_cpu(phandle_cell)
+                            id = fdt_util.fdt32_to_cpu(id_cell)
+                            target_node = self._phandle_node[phandle]
+                            node.phandles.add(target_node)
+
+
     def GenerateStructs(self, structs):
         """Generate struct defintions for the platform data
 
@@ -301,6 +328,59 @@
                 self.Out(';\n')
             self.Out('};\n')
 
+    def OutputNode(self, node):
+        """Output the C code for a node
+
+        Args:
+            node: node to output
+        """
+        struct_name = self.GetCompatName(node)
+        var_name = Conv_name_to_c(node.name)
+        self.Buf('static struct %s%s %s%s = {\n' %
+            (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
+        for pname, prop in node.props.items():
+            if pname in PROP_IGNORE_LIST or pname[0] == '#':
+                continue
+            ptype = TYPE_NAMES[prop.type]
+            member_name = Conv_name_to_c(prop.name)
+            self.Buf('\t%s= ' % TabTo(3, '.' + member_name))
+
+            # Special handling for lists
+            if type(prop.value) == list:
+                self.Buf('{')
+                vals = []
+                # For phandles, output a reference to the platform data
+                # of the target node.
+                if self.IsPhandle(prop):
+                    # Process the list as pairs of (phandle, id)
+                    it = iter(prop.value)
+                    for phandle_cell, id_cell in zip(it, it):
+                        phandle = fdt_util.fdt32_to_cpu(phandle_cell)
+                        id = fdt_util.fdt32_to_cpu(id_cell)
+                        target_node = self._phandle_node[phandle]
+                        name = Conv_name_to_c(target_node.name)
+                        vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id))
+                else:
+                    for val in prop.value:
+                        vals.append(self.GetValue(prop.type, val))
+                self.Buf(', '.join(vals))
+                self.Buf('}')
+            else:
+                self.Buf(self.GetValue(prop.type, prop.value))
+            self.Buf(',\n')
+        self.Buf('};\n')
+
+        # Add a device declaration
+        self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
+        self.Buf('\t.name\t\t= "%s",\n' % struct_name)
+        self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
+        self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
+                    (VAL_PREFIX, var_name))
+        self.Buf('};\n')
+        self.Buf('\n')
+
+        self.Out(''.join(self.GetBuf()))
+
     def GenerateTables(self):
         """Generate device defintions for the platform data
 
@@ -312,64 +392,18 @@
         self.Out('#include <dm.h>\n')
         self.Out('#include <dt-structs.h>\n')
         self.Out('\n')
-        node_txt_list = []
-        for node in self._valid_nodes:
-            struct_name = self.GetCompatName(node)
-            var_name = Conv_name_to_c(node.name)
-            self.Buf('static struct %s%s %s%s = {\n' %
-                (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
-            for pname, prop in node.props.items():
-                if pname in PROP_IGNORE_LIST or pname[0] == '#':
-                    continue
-                ptype = TYPE_NAMES[prop.type]
-                member_name = Conv_name_to_c(prop.name)
-                self.Buf('\t%s= ' % TabTo(3, '.' + member_name))
-
-                # Special handling for lists
-                if type(prop.value) == list:
-                    self.Buf('{')
-                    vals = []
-                    # For phandles, output a reference to the platform data
-                    # of the target node.
-                    if self.IsPhandle(prop):
-                        # Process the list as pairs of (phandle, id)
-                        it = iter(prop.value)
-                        for phandle_cell, id_cell in zip(it, it):
-                            phandle = fdt_util.fdt32_to_cpu(phandle_cell)
-                            id = fdt_util.fdt32_to_cpu(id_cell)
-                            target_node = self._phandle_node[phandle]
-                            name = Conv_name_to_c(target_node.name)
-                            vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id))
-                    else:
-                        for val in prop.value:
-                            vals.append(self.GetValue(prop.type, val))
-                    self.Buf(', '.join(vals))
-                    self.Buf('}')
-                else:
-                    self.Buf(self.GetValue(prop.type, prop.value))
-                self.Buf(',\n')
-            self.Buf('};\n')
-
-            # Add a device declaration
-            self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
-            self.Buf('\t.name\t\t= "%s",\n' % struct_name)
-            self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
-            self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
-                     (VAL_PREFIX, var_name))
-            self.Buf('};\n')
-            self.Buf('\n')
-
-            # Output phandle target nodes first, since they may be referenced
-            # by others
-            if 'phandle' in node.props:
-                self.Out(''.join(self.GetBuf()))
-            else:
-                node_txt_list.append(self.GetBuf())
+        nodes_to_output = list(self._valid_nodes)
 
-        # Output all the nodes which are not phandle targets themselves, but
-        # may reference them. This avoids the need for forward declarations.
-        for node_txt in node_txt_list:
-            self.Out(''.join(node_txt))
+        # Keep outputing nodes until there is none left
+        while nodes_to_output:
+            node = nodes_to_output[0]
+            # Output all the node's dependencies first
+            for req_node in node.phandles:
+                if req_node in nodes_to_output:
+                    self.OutputNode(req_node)
+                    nodes_to_output.remove(req_node)
+            self.OutputNode(node)
+            nodes_to_output.remove(node)
 
 
 if __name__ != "__main__":
@@ -392,6 +426,7 @@
 plat.ScanTree()
 plat.SetupOutput(options.output)
 structs = plat.ScanStructs()
+plat.ScanPhandles()
 
 for cmd in args[0].split(','):
     if cmd == 'struct':
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index b34373e..8283a74 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -13,6 +13,8 @@
 #include "mkimage.h"
 #include "rkcommon.h"
 
+#define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
+
 enum {
 	RK_SIGNATURE		= 0x0ff0aa55,
 };
@@ -71,6 +73,7 @@
 	{ "rk3036", "RK30", 0x1000, false, false },
 	{ "rk3188", "RK31", 0x8000 - 0x800, true, false },
 	{ "rk3288", "RK32", 0x8000, false, false },
+	{ "rk3328", "RK32", 0x8000 - 0x1000, false, false },
 	{ "rk3399", "RK33", 0x20000, false, true },
 };
 
@@ -83,6 +86,9 @@
 {
 	int i;
 
+	if (!imagename)
+		return NULL;
+
 	for (i = 0; i < ARRAY_SIZE(spl_infos); i++)
 		if (!strncmp(imagename, spl_infos[i].imagename, 6))
 			return spl_infos + i;
@@ -95,17 +101,24 @@
 	int i;
 
 	if (rkcommon_get_spl_info(params->imagename) != NULL)
-		return 0;
+		return EXIT_SUCCESS;
+
+	/*
+	 * If this is a operation (list or extract), the don't require
+	 * imagename to be set.
+	 */
+	if (params->lflag || params->iflag)
+		return EXIT_SUCCESS;
 
 	fprintf(stderr, "ERROR: imagename (%s) is not supported!\n",
-		strlen(params->imagename) > 0 ? params->imagename : "NULL");
+		params->imagename ? params->imagename : "NULL");
 
 	fprintf(stderr, "Available imagename:");
 	for (i = 0; i < ARRAY_SIZE(spl_infos); i++)
 		fprintf(stderr, "\t%s", spl_infos[i].imagename);
 	fprintf(stderr, "\n");
 
-	return -1;
+	return EXIT_FAILURE;
 }
 
 const char *rkcommon_get_spl_hdr(struct image_tool_params *params)
@@ -159,9 +172,21 @@
 	hdr->disable_rc4 = !rkcommon_need_rc4_spl(params);
 	hdr->init_offset = RK_INIT_OFFSET;
 
-	hdr->init_size = (file_size + RK_BLK_SIZE - 1) / RK_BLK_SIZE;
-	hdr->init_size = (hdr->init_size + 3) & ~3;
-	hdr->init_boot_size = hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE;
+	hdr->init_size = DIV_ROUND_UP(file_size, RK_BLK_SIZE);
+	/*
+	 * The init_size has to be a multiple of 4 blocks (i.e. of 2K)
+	 * or the BootROM will not boot the image.
+	 *
+	 * Note: To verify that this is not a legacy constraint, we
+	 *       rechecked this against the RK3399 BootROM.
+	 */
+	hdr->init_size = ROUND(hdr->init_size, 4);
+	/*
+	 * The images we create do not contain the stage following the SPL as
+	 * part of the SPL image, so the init_boot_size (which might have been
+	 * read by Rockchip's miniloder) should be the same as the init_size.
+	 */
+	hdr->init_boot_size = hdr->init_size;
 
 	rc4_encode(buf, RK_BLK_SIZE, rc4_key);
 }
@@ -176,7 +201,7 @@
 
 	rkcommon_set_header0(buf, file_size, params);
 
-	/* Set up the SPL name and add the AArch64 'nop' padding, if needed */
+	/* Set up the SPL name */
 	memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
 
 	if (rkcommon_need_rc4_spl(params))
@@ -199,25 +224,33 @@
 	}
 }
 
-void rkcommon_vrec_header(struct image_tool_params *params,
-			  struct image_type_params *tparams)
+int rkcommon_vrec_header(struct image_tool_params *params,
+			 struct image_type_params *tparams,
+			 unsigned int alignment)
 {
+	unsigned int  unpadded_size;
+	unsigned int  padded_size;
+
 	/*
 	 * The SPL image looks as follows:
 	 *
 	 * 0x0    header0 (see rkcommon.c)
 	 * 0x800  spl_name ('RK30', ..., 'RK33')
+	 *        (start of the payload for AArch64 payloads: we expect the
+	 *        first 4 bytes to be available for overwriting with our
+	 *        spl_name)
 	 * 0x804  first instruction to be executed
-	 *        (image start for AArch32, 'nop' for AArch64))
-	 * 0x808  second instruction to be executed
-	 *        (image start for AArch64)
+	 *        (start of the image/payload for 32bit payloads)
 	 *
-	 * For AArch64 (ARMv8) payloads, we receive an input file that
-	 * needs to start on an 8-byte boundary (natural alignment), so
-	 * we need to put a NOP at 0x804.
+	 * For AArch64 (ARMv8) payloads, natural alignment (8-bytes) is
+	 * required for its sections (so the image we receive needs to
+	 * have the first 4 bytes reserved for the spl_name).  Reserving
+	 * these 4 bytes is done using the BOOT0_HOOK infrastructure.
 	 *
-	 * Depending on this, the header is either 0x804 or 0x808 bytes
-	 * in length.
+	 * Depending on this, the header is either 0x800 (if this is a
+	 * 'boot0'-style payload, which has reserved 4 bytes at the
+	 * beginning for the 'spl_name' and expects us to overwrite
+	 * its first 4 bytes) or 0x804 bytes in length.
 	 */
 	if (rkcommon_spl_is_boot0(params))
 		tparams->header_size = RK_SPL_HDR_START;
@@ -227,4 +260,17 @@
 	/* Allocate, clear and install the header */
 	tparams->hdr = malloc(tparams->header_size);
 	memset(tparams->hdr, 0, tparams->header_size);
+	tparams->header_size = tparams->header_size;
+
+	/*
+	 * If someone passed in 0 for the alignment, we'd better handle
+	 * it correctly...
+	 */
+	if (!alignment)
+		alignment = 1;
+
+	unpadded_size = tparams->header_size + params->file_size;
+	padded_size = ROUND(unpadded_size, alignment);
+
+	return padded_size - unpadded_size;
 }
diff --git a/tools/rkcommon.h b/tools/rkcommon.h
index cc161a6..a21321f 100644
--- a/tools/rkcommon.h
+++ b/tools/rkcommon.h
@@ -83,8 +83,14 @@
  * @params:     Pointer to the tool params structure
  * @tparams:    Pointer tot the image type structure (for setting
  *              the header and header_size)
+ * @alignment:  Alignment (a power of two) that the image should be
+ *              padded to (e.g. 512 if we want to align with SD/MMC
+ *              blocksizes or 2048 for the SPI format)
+ *
+ * @return bytes of padding required/added (does not include the header_size)
  */
-void rkcommon_vrec_header(struct image_tool_params *params,
-			  struct image_type_params *tparams);
+int rkcommon_vrec_header(struct image_tool_params *params,
+			 struct image_type_params *tparams,
+			 unsigned int alignment);
 
 #endif
diff --git a/tools/rkimage.c b/tools/rkimage.c
index 44d098c..9880b15 100644
--- a/tools/rkimage.c
+++ b/tools/rkimage.c
@@ -13,16 +13,6 @@
 
 static uint32_t header;
 
-static int rkimage_verify_header(unsigned char *buf, int size,
-				 struct image_tool_params *params)
-{
-	return 0;
-}
-
-static void rkimage_print_header(const void *buf)
-{
-}
-
 static void rkimage_set_header(void *buf, struct stat *sbuf, int ifd,
 			       struct image_tool_params *params)
 {
@@ -33,11 +23,6 @@
 		rkcommon_rc4_encode_spl(buf, 4, params->file_size);
 }
 
-static int rkimage_extract_subimage(void *buf, struct image_tool_params *params)
-{
-	return 0;
-}
-
 static int rkimage_check_image_type(uint8_t type)
 {
 	if (type == IH_TYPE_RKIMAGE)
@@ -55,10 +40,10 @@
 	4,
 	&header,
 	rkcommon_check_params,
-	rkimage_verify_header,
-	rkimage_print_header,
+	NULL,
+	NULL,
 	rkimage_set_header,
-	rkimage_extract_subimage,
+	NULL,
 	rkimage_check_image_type,
 	NULL,
 	NULL
diff --git a/tools/rksd.c b/tools/rksd.c
index ac8a67d..8627b6d 100644
--- a/tools/rksd.c
+++ b/tools/rksd.c
@@ -29,12 +29,20 @@
 	unsigned int size;
 	int ret;
 
+	printf("params->file_size %d\n", params->file_size);
+	printf("params->orig_file_size %d\n", params->orig_file_size);
+
+	/*
+	 * We need to calculate this using 'RK_SPL_HDR_START' and not using
+	 * 'tparams->header_size', as the additional byte inserted when
+	 * 'is_boot0' is true counts towards the payload.
+	 */
 	size = params->file_size - RK_SPL_HDR_START;
 	ret = rkcommon_set_header(buf, size, params);
 	if (ret) {
 		/* TODO(sjg@chromium.org): This method should return an error */
-		printf("Warning: SPL image is too large (size %#x) and will not boot\n",
-		       size);
+		printf("Warning: SPL image is too large (size %#x) and will "
+		       "not boot\n", size);
 	}
 }
 
@@ -51,18 +59,14 @@
 		return EXIT_FAILURE;
 }
 
-/* We pad the file out to a fixed size - this method returns that size */
 static int rksd_vrec_header(struct image_tool_params *params,
 			    struct image_type_params *tparams)
 {
-	int pad_size;
-
-	rkcommon_vrec_header(params, tparams);
-
-	pad_size = RK_SPL_HDR_START + rkcommon_get_spl_size(params);
-	debug("pad_size %x\n", pad_size);
-
-	return pad_size - params->file_size - tparams->header_size;
+	/*
+	 * Pad to the RK_BLK_SIZE (512 bytes) to be consistent with init_size
+	 * being encoded in RK_BLK_SIZE units in header0 (see rkcommon.c).
+	 */
+	return rkcommon_vrec_header(params, tparams, RK_BLK_SIZE);
 }
 
 /*
diff --git a/tools/rkspi.c b/tools/rkspi.c
index d2d3fdd..87bd1a9 100644
--- a/tools/rkspi.c
+++ b/tools/rkspi.c
@@ -39,8 +39,8 @@
 	debug("size %x\n", size);
 	if (ret) {
 		/* TODO(sjg@chromium.org): This method should return an error */
-		printf("Warning: SPL image is too large (size %#x) and will not boot\n",
-		       size);
+		printf("Warning: SPL image is too large (size %#x) and will "
+		       "not boot\n", size);
 	}
 
 	/*
@@ -71,23 +71,36 @@
 		return EXIT_FAILURE;
 }
 
-/* We pad the file out to a fixed size - this method returns that size */
+/*
+ * The SPI payload needs to be padded out to make space for odd half-sector
+ * layout used in flash (i.e. only the first 2K of each 4K sector is used).
+ */
 static int rkspi_vrec_header(struct image_tool_params *params,
 			     struct image_type_params *tparams)
 {
-	int pad_size;
-
-	rkcommon_vrec_header(params, tparams);
-
-	pad_size = (rkcommon_get_spl_size(params) + 0x7ff) / 0x800 * 0x800;
-	params->orig_file_size = pad_size;
+	int padding = rkcommon_vrec_header(params, tparams, 2048);
+	/*
+	 * The file size has not been adjusted at this point (our caller will
+	 * eventually add the header/padding to the file_size), so we need to
+	 * add up the header_size, file_size and padding ourselves.
+	 */
+	int padded_size = tparams->header_size + params->file_size + padding;
 
-	/* We will double the image size due to the SPI format */
-	pad_size *= 2;
-	pad_size += RK_SPL_HDR_START;
-	debug("pad_size %x\n", pad_size);
+	/*
+	 * We need to store the original file-size (i.e. before padding), as
+	 * imagetool does not set this during its adjustment of file_size.
+	 */
+	params->orig_file_size = padded_size;
 
-	return pad_size - params->file_size - tparams->header_size;
+	/*
+	 * Converting to the SPI format (i.e. splitting each 4K page into two
+	 * 2K subpages and then padding these 2K pages up to take a complete
+	 * 4K sector again) will will double the image size.
+	 *
+	 * Thus we return the padded_size as an additional padding requirement
+	 * (be sure to add this to the padding returned from the common code).
+	 */
+	return padded_size + padding;
 }
 
 /*