diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7b80630aa1cf6bcac44d7656946151eee542234c..f96841c77717b176d5bb26f47bb0540fc5700a7f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1604,7 +1604,6 @@ config ARCH_ROCKCHIP
 	select OF_CONTROL
 	select SPI
 	select SPL_DM if SPL
-	select SPL_SYS_MALLOC_SIMPLE if SPL
 	select SYS_MALLOC_F
 	select SYS_THUMB_BUILD if !ARM64
 	imply ADC
@@ -1614,6 +1613,7 @@ config ARCH_ROCKCHIP
 	imply FAT_WRITE
 	imply SARADC_ROCKCHIP
 	imply SPL_SYSRESET
+	imply SPL_SYS_MALLOC_SIMPLE
 	imply SYS_NS16550
 	imply TPL_SYSRESET
 	imply USB_FUNCTION_FASTBOOT
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 85ef00a2bd117a5e3c9aa2d0b2430681f823b2b2..d8846df1bdd9031d059f0df69f0a656153e71a1d 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -67,6 +67,9 @@ dtb-$(CONFIG_KIRKWOOD) += \
 dtb-$(CONFIG_ARCH_OWL) += \
 	bubblegum_96.dtb
 
+dtb-$(CONFIG_ROCKCHIP_PX30) += \
+	px30-evb.dtb
+
 dtb-$(CONFIG_ROCKCHIP_RK3036) += \
 	rk3036-sdk.dtb
 
@@ -87,12 +90,17 @@ dtb-$(CONFIG_ROCKCHIP_RK3288) += \
 	rk3288-popmetal.dtb \
 	rk3288-rock2-square.dtb \
 	rk3288-tinker.dtb \
+	rk3288-tinker-s.dtb \
 	rk3288-veyron-jerry.dtb \
 	rk3288-veyron-mickey.dtb \
 	rk3288-veyron-minnie.dtb \
 	rk3288-veyron-speedy.dtb \
 	rk3288-vyasa.dtb
 
+dtb-$(CONFIG_ROCKCHIP_RK3308) += \
+	rk3308-evb.dtb \
+	rk3308-roc-cc.dtb
+
 dtb-$(CONFIG_ROCKCHIP_RK3328) += \
 	rk3328-evb.dtb \
 	rk3328-rock64.dtb
diff --git a/arch/arm/dts/px30-evb-u-boot.dtsi b/arch/arm/dts/px30-evb-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..3de9c7068ea5629ebfc589815b7fe9234e05b7b6
--- /dev/null
+++ b/arch/arm/dts/px30-evb-u-boot.dtsi
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+/ {
+	aliases {
+		mmc0 = &emmc;
+		mmc1 = &sdmmc;
+	};
+
+	chosen {
+		u-boot,spl-boot-order = &emmc, &sdmmc;
+	};
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	clock-frequency = <24000000>;
+	u-boot,dm-pre-reloc;
+};
+
+&uart5 {
+	clock-frequency = <24000000>;
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+
+	/* temporary till I find out why dma mode doesn't work */
+	fifo-mode;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&xin24m {
+	u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&pmucru {
+	u-boot,dm-pre-reloc;
+};
+
+&saradc {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&gpio0 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio1 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio2 {
+	u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/px30-evb.dts b/arch/arm/dts/px30-evb.dts
new file mode 100644
index 0000000000000000000000000000000000000000..d886f17242fcb17aa3f06cbb540ddcbed287212c
--- /dev/null
+++ b/arch/arm/dts/px30-evb.dts
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "px30.dtsi"
+#include "px30-evb-u-boot.dtsi"
+
+/ {
+	model = "Rockchip PX30 EVB";
+	compatible = "rockchip,px30-evb", "rockchip,px30";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 2>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1800000>;
+		poll-interval = <100>;
+
+		esc-key {
+			label = "esc";
+			linux,code = <KEY_ESC>;
+			press-threshold-microvolt = <1310000>;
+		};
+
+		home-key {
+			label = "home";
+			linux,code = <KEY_HOME>;
+			press-threshold-microvolt = <624000>;
+		};
+
+		menu-key {
+			label = "menu";
+			linux,code = <KEY_MENU>;
+			press-threshold-microvolt = <987000>;
+		};
+
+		vol-down-key {
+			label = "volume down";
+			linux,code = <KEY_VOLUMEDOWN>;
+			press-threshold-microvolt = <300000>;
+		};
+
+		vol-up-key {
+			label = "volume up";
+			linux,code = <KEY_VOLUMEUP>;
+			press-threshold-microvolt = <17000>;
+		};
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 25000 0>;
+		power-supply = <&vcc3v3_lcd>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		pinctrl-0 = <&emmc_reset>;
+		pinctrl-names = "default";
+		reset-gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_HIGH>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		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_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */
+	};
+
+	vcc5v0_sys: vccsys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc5v0_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+	cpu-supply = <&vdd_arm>;
+};
+
+&display_subsystem {
+	status = "okay";
+};
+
+&dsi {
+	status = "okay";
+
+	ports {
+		mipi_out: port@1 {
+			reg = <1>;
+
+			mipi_out_panel: endpoint {
+				remote-endpoint = <&mipi_in_panel>;
+			};
+		};
+	};
+
+	panel@0 {
+		compatible = "sitronix,st7703";
+		reg = <0>;
+		backlight = <&backlight>;
+		iovcc-supply = <&vcc_1v8>;
+		vci-supply = <&vcc3v3_lcd>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				mipi_in_panel: endpoint {
+					remote-endpoint = <&mipi_out_panel>;
+				};
+			};
+		};
+	};
+};
+
+&dsi_dphy {
+	status = "okay";
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	non-removable;
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v0>;
+	vqmmc-supply = <&vccio_flash>;
+	status = "okay";
+};
+
+&gmac {
+	clock_in_out = "output";
+	phy-supply = <&vcc_rmii>;
+	snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 50000 50000>;
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	rk809: pmic@20 {
+		compatible = "rockchip,rk809";
+		reg = <0x20>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int>;
+		rockchip,system-power-controller;
+		wakeup-source;
+		#clock-cells = <0>;
+		clock-output-names = "xin32k";
+
+		vcc1-supply = <&vcc5v0_sys>;
+		vcc2-supply = <&vcc5v0_sys>;
+		vcc3-supply = <&vcc5v0_sys>;
+		vcc4-supply = <&vcc5v0_sys>;
+		vcc5-supply = <&vcc3v3_sys>;
+		vcc6-supply = <&vcc3v3_sys>;
+		vcc7-supply = <&vcc3v3_sys>;
+		vcc8-supply = <&vcc3v3_sys>;
+		vcc9-supply = <&vcc5v0_sys>;
+
+		regulators {
+			vdd_log: DCDC_REG1 {
+				regulator-name = "vdd_log";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <950000>;
+				};
+			};
+
+			vdd_arm: DCDC_REG2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <950000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-name = "vcc_ddr";
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_3v0: vcc_rmii: DCDC_REG4 {
+				regulator-name = "vcc_3v0";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3000000>;
+				};
+			};
+
+			vcc3v3_sys: DCDC_REG5 {
+				regulator-name = "vcc3v3_sys";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc_1v0: LDO_REG1 {
+				regulator-name = "vcc_1v0";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_1v8: vccio_flash: vccio_sdio: LDO_REG2 {
+				regulator-name = "vcc_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vdd_1v0: LDO_REG3 {
+				regulator-name = "vdd_1v0";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc3v0_pmu: LDO_REG4 {
+				regulator-name = "vcc3v0_pmu";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3000000>;
+				};
+			};
+
+			vccio_sd: LDO_REG5 {
+				regulator-name = "vccio_sd";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc_sd: LDO_REG6 {
+				regulator-name = "vcc_sd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc2v8_dvp: LDO_REG7 {
+				regulator-name = "vcc2v8_dvp";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <2800000>;
+				};
+			};
+
+			vcc1v8_dvp: LDO_REG8 {
+				regulator-name = "vcc1v8_dvp";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc1v5_dvp: LDO_REG9 {
+				regulator-name = "vcc1v5_dvp";
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+					regulator-suspend-microvolt = <1500000>;
+				};
+			};
+
+			vcc3v3_lcd: SWITCH_REG1 {
+				regulator-name = "vcc3v3_lcd";
+				regulator-boot-on;
+			};
+
+			vcc5v0_host: SWITCH_REG2 {
+				regulator-name = "vcc5v0_host";
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2s1_2ch {
+	status = "okay";
+};
+
+&io_domains {
+	status = "okay";
+
+	vccio1-supply = <&vccio_sdio>;
+	vccio2-supply = <&vccio_sd>;
+	vccio3-supply = <&vcc_3v0>;
+	vccio4-supply = <&vcc3v0_pmu>;
+	vccio5-supply = <&vcc_3v0>;
+	vccio6-supply = <&vccio_flash>;
+};
+
+&pinctrl {
+	headphone {
+		hp_det: hp-det {
+			rockchip,pins =
+				<2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+
+	emmc {
+		emmc_reset: emmc-reset {
+			rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_int: pmic_int {
+			rockchip,pins =
+				<0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		soc_slppin_gpio: soc_slppin_gpio {
+			rockchip,pins =
+				<0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>;
+		};
+
+		soc_slppin_slp: soc_slppin_slp {
+			rockchip,pins =
+				<0 RK_PA4 1 &pcfg_pull_none>;
+		};
+
+		soc_slppin_rst: soc_slppin_rst {
+			rockchip,pins =
+				<0 RK_PA4 2 &pcfg_pull_none>;
+		};
+	};
+
+	sdio-pwrseq {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins =
+				<0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&pmu_io_domains {
+	status = "okay";
+
+	pmuio1-supply = <&vcc3v0_pmu>;
+	pmuio2-supply = <&vcc3v0_pmu>;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&saradc {
+	vref-supply = <&vcc_1v8>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <800>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+};
+
+&sdio {
+	bus-width = <4>;
+	cap-sd-highspeed;
+	keep-power-in-suspend;
+	non-removable;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	sd-uhs-sdr104;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_xfer &uart1_cts>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart5 {
+	status = "okay";
+};
+
+&usb20_otg {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..0d2325a77fcdda0aaedad735112386a4775006e3
--- /dev/null
+++ b/arch/arm/dts/px30.dtsi
@@ -0,0 +1,2068 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+#include <dt-bindings/clock/px30-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#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/px30-power.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
+
+/ {
+	compatible = "rockchip,px30";
+
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &gmac;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &uart5;
+		spi0 = &spi0;
+		spi1 = &spi1;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLK>;
+			#cooling-cells = <2>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+			dynamic-power-coefficient = <90>;
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLK>;
+			#cooling-cells = <2>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+			dynamic-power-coefficient = <90>;
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLK>;
+			#cooling-cells = <2>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+			dynamic-power-coefficient = <90>;
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLK>;
+			#cooling-cells = <2>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+			dynamic-power-coefficient = <90>;
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+
+		idle-states {
+			entry-method = "psci";
+
+			CPU_SLEEP: cpu-sleep {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x0010000>;
+				entry-latency-us = <120>;
+				exit-latency-us = <250>;
+				min-residency-us = <900>;
+			};
+
+			CLUSTER_SLEEP: cluster-sleep {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x1010000>;
+				entry-latency-us = <400>;
+				exit-latency-us = <500>;
+				min-residency-us = <2000>;
+			};
+		};
+	};
+
+	cpu0_opp_table: cpu0-opp-table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-microvolt = <950000 950000 1350000>;
+			clock-latency-ns = <40000>;
+			opp-suspend;
+		};
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <950000 950000 1350000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-816000000 {
+			opp-hz = /bits/ 64 <816000000>;
+			opp-microvolt = <1050000 1050000 1350000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-1008000000 {
+			opp-hz = /bits/ 64 <1008000000>;
+			opp-microvolt = <1175000 1175000 1350000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <1300000 1300000 1350000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-1296000000 {
+			opp-hz = /bits/ 64 <1296000000>;
+			opp-microvolt = <1350000 1350000 1350000>;
+			clock-latency-ns = <40000>;
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	dmc: dmc {
+		compatible = "rockchip,px30-dmc", "syscon";
+		reg = <0x0 0xff2a0000 0x0 0x1000>;
+	};
+
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vopb_out>, <&vopl_out>;
+		status = "disabled";
+	};
+
+	gmac_clkin: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+		clock-output-names = "gmac_clkin";
+		#clock-cells = <0>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	xin24m: xin24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+	};
+
+	pmu: power-management@ff000000 {
+		compatible = "rockchip,px30-pmu", "syscon", "simple-mfd";
+		reg = <0x0 0xff000000 0x0 0x1000>;
+
+		power: power-controller {
+			compatible = "rockchip,px30-power-controller";
+			#power-domain-cells = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* These power domains are grouped by VD_LOGIC */
+			pd_usb@PX30_PD_USB {
+				reg = <PX30_PD_USB>;
+				clocks = <&cru HCLK_HOST>,
+					 <&cru HCLK_OTG>,
+					 <&cru SCLK_OTG_ADP>;
+				pm_qos = <&qos_usb_host>, <&qos_usb_otg>;
+			};
+			pd_sdcard@PX30_PD_SDCARD {
+				reg = <PX30_PD_SDCARD>;
+				clocks = <&cru HCLK_SDMMC>,
+					 <&cru SCLK_SDMMC>;
+				pm_qos = <&qos_sdmmc>;
+			};
+			pd_gmac@PX30_PD_GMAC {
+				reg = <PX30_PD_GMAC>;
+				clocks = <&cru ACLK_GMAC>,
+					 <&cru PCLK_GMAC>,
+					 <&cru SCLK_MAC_REF>,
+					 <&cru SCLK_GMAC_RX_TX>;
+				pm_qos = <&qos_gmac>;
+			};
+			pd_mmc_nand@PX30_PD_MMC_NAND {
+				reg = <PX30_PD_MMC_NAND>;
+				clocks =  <&cru HCLK_NANDC>,
+					  <&cru HCLK_EMMC>,
+					  <&cru HCLK_SDIO>,
+					  <&cru HCLK_SFC>,
+					  <&cru SCLK_EMMC>,
+					  <&cru SCLK_NANDC>,
+					  <&cru SCLK_SDIO>,
+					  <&cru SCLK_SFC>;
+				pm_qos = <&qos_emmc>, <&qos_nand>,
+					 <&qos_sdio>, <&qos_sfc>;
+			};
+			pd_vpu@PX30_PD_VPU {
+				reg = <PX30_PD_VPU>;
+				clocks = <&cru ACLK_VPU>,
+					 <&cru HCLK_VPU>,
+					 <&cru SCLK_CORE_VPU>;
+				pm_qos = <&qos_vpu>, <&qos_vpu_r128>;
+			};
+			pd_vo@PX30_PD_VO {
+				reg = <PX30_PD_VO>;
+				clocks = <&cru ACLK_RGA>,
+					 <&cru ACLK_VOPB>,
+					 <&cru ACLK_VOPL>,
+					 <&cru DCLK_VOPB>,
+					 <&cru DCLK_VOPL>,
+					 <&cru HCLK_RGA>,
+					 <&cru HCLK_VOPB>,
+					 <&cru HCLK_VOPL>,
+					 <&cru PCLK_MIPI_DSI>,
+					 <&cru SCLK_RGA_CORE>,
+					 <&cru SCLK_VOPB_PWM>;
+				pm_qos = <&qos_rga_rd>, <&qos_rga_wr>,
+					 <&qos_vop_m0>, <&qos_vop_m1>;
+			};
+			pd_vi@PX30_PD_VI {
+				reg = <PX30_PD_VI>;
+				clocks = <&cru ACLK_CIF>,
+					 <&cru ACLK_ISP>,
+					 <&cru HCLK_CIF>,
+					 <&cru HCLK_ISP>,
+					 <&cru SCLK_ISP>;
+				pm_qos = <&qos_isp_128>, <&qos_isp_rd>,
+					 <&qos_isp_wr>, <&qos_isp_m1>,
+					 <&qos_vip>;
+			};
+			pd_gpu@PX30_PD_GPU {
+				reg = <PX30_PD_GPU>;
+				clocks = <&cru SCLK_GPU>;
+				pm_qos = <&qos_gpu>;
+			};
+		};
+	};
+
+	pmugrf: syscon@ff010000 {
+		compatible = "rockchip,px30-pmugrf", "syscon", "simple-mfd";
+		reg = <0x0 0xff010000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		pmu_io_domains: io-domains {
+			compatible = "rockchip,px30-pmu-io-voltage-domain";
+			status = "disabled";
+		};
+
+		reboot-mode {
+			compatible = "syscon-reboot-mode";
+			offset = <0x200>;
+			mode-bootloader = <BOOT_BL_DOWNLOAD>;
+			mode-fastboot = <BOOT_FASTBOOT>;
+			mode-loader = <BOOT_BL_DOWNLOAD>;
+			mode-normal = <BOOT_NORMAL>;
+			mode-recovery = <BOOT_RECOVERY>;
+		};
+	};
+
+	uart0: serial@ff030000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff030000 0x0 0x100>;
+		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 0>, <&dmac 1>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+		status = "disabled";
+	};
+
+	i2s1_2ch: i2s@ff070000 {
+		compatible = "rockchip,px30-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff070000 0x0 0x1000>;
+		interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		dmas = <&dmac 18>, <&dmac 19>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s1_2ch_sclk &i2s1_2ch_lrck
+			     &i2s1_2ch_sdi &i2s1_2ch_sdo>;
+		#sound-dai-cells = <0>;
+		status = "disabled";
+	};
+
+	i2s2_2ch: i2s@ff080000 {
+		compatible = "rockchip,px30-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff080000 0x0 0x1000>;
+		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_I2S2>, <&cru HCLK_I2S2>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		dmas = <&dmac 20>, <&dmac 21>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s2_2ch_sclk &i2s2_2ch_lrck
+			     &i2s2_2ch_sdi &i2s2_2ch_sdo>;
+		#sound-dai-cells = <0>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@ff131000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0x0 0xff131000 0 0x1000>,
+		      <0x0 0xff132000 0 0x2000>,
+		      <0x0 0xff134000 0 0x2000>,
+		      <0x0 0xff136000 0 0x2000>;
+		interrupts = <GIC_PPI 9
+		      (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	grf: syscon@ff140000 {
+		compatible = "rockchip,px30-grf", "syscon", "simple-mfd";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		io_domains: io-domains {
+			compatible = "rockchip,px30-io-voltage-domain";
+			status = "disabled";
+		};
+	};
+
+	uart1: serial@ff158000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff158000 0x0 0x100>;
+		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 2>, <&dmac 3>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer &uart1_cts &uart1_rts>;
+		status = "disabled";
+	};
+
+	uart2: serial@ff160000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff160000 0x0 0x100>;
+		interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 4>, <&dmac 5>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2m0_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff168000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff168000 0x0 0x100>;
+		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 6>, <&dmac 7>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3m1_xfer &uart3m1_cts &uart3m1_rts>;
+		status = "disabled";
+	};
+
+	uart4: serial@ff170000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff170000 0x0 0x100>;
+		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 8>, <&dmac 9>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_xfer &uart4_cts &uart4_rts>;
+		status = "disabled";
+	};
+
+	uart5: serial@ff178000 {
+		compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff178000 0x0 0x100>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
+		clock-names = "baudclk", "apb_pclk";
+		dmas = <&dmac 10>, <&dmac 11>;
+		dma-names = "tx", "rx";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart5_xfer &uart5_cts &uart5_rts>;
+		status = "disabled";
+	};
+
+	i2c0: i2c@ff180000 {
+		compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff180000 0x0 0x1000>;
+		clocks =  <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@ff190000 {
+		compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff190000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@ff1a0000 {
+		compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff1a0000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@ff1b0000 {
+		compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff1b0000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi0: spi@ff1d0000 {
+		compatible = "rockchip,px30-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1d0000 0x0 0x1000>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		dmas = <&dmac 12>, <&dmac 13>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_clk &spi0_csn &spi0_miso &spi0_mosi>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi@ff1d8000 {
+		compatible = "rockchip,px30-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1d8000 0x0 0x1000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		dmas = <&dmac 14>, <&dmac 15>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	wdt: watchdog@ff1e0000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x0 0xff1e0000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT_NS>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	pwm0: pwm@ff200000 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff200000 0x0 0x10>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm1: pwm@ff200010 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff200010 0x0 0x10>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm2: pwm@ff200020 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff200020 0x0 0x10>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm3: pwm@ff200030 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff200030 0x0 0x10>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm4: pwm@ff208000 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff208000 0x0 0x10>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm4_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm5: pwm@ff208010 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff208010 0x0 0x10>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm5_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm6: pwm@ff208020 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff208020 0x0 0x10>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm6_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	pwm7: pwm@ff208030 {
+		compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff208030 0x0 0x10>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm7_pin>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
+
+	rktimer: timer@ff210000 {
+		compatible = "rockchip,px30-timer", "rockchip,rk3288-timer";
+		reg = <0x0 0xff210000 0x0 0x1000>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER0>;
+		clock-names = "pclk", "timer";
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dmac: dmac@ff240000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff240000 0x0 0x4000>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru ACLK_DMAC>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+		};
+	};
+
+	saradc: saradc@ff288000 {
+		compatible = "rockchip,px30-saradc", "rockchip,rk3399-saradc";
+		reg = <0x0 0xff288000 0x0 0x100>;
+		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_SARADC_P>;
+		reset-names = "saradc-apb";
+		status = "disabled";
+	};
+
+	otp: nvmem@ff290000 {
+		compatible = "rockchip,px30-otp";
+		reg = <0x0 0xff290000 0x0 0x4000>;
+		clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
+			 <&cru PCLK_OTP_PHY>;
+		clock-names = "otp", "apb_pclk", "phy";
+		resets = <&cru SRST_OTP_PHY>;
+		reset-names = "phy";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* Data cells */
+		cpu_id: id@7 {
+			reg = <0x07 0x10>;
+		};
+		cpu_leakage: cpu-leakage@17 {
+			reg = <0x17 0x1>;
+		};
+		performance: performance@1e {
+			reg = <0x1e 0x1>;
+			bits = <4 3>;
+		};
+	};
+
+	cru: clock-controller@ff2b0000 {
+		compatible = "rockchip,px30-cru";
+		reg = <0x0 0xff2b0000 0x0 0x1000>;
+		clocks = <&xin24m>, <&pmucru PLL_GPLL>;
+		clock-names = "xin24m", "gpll";
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	pmucru: clock-controller@ff2bc000 {
+		compatible = "rockchip,px30-pmucru";
+		reg = <0x0 0xff2bc000 0x0 0x1000>;
+		clocks = <&xin24m>;
+		clock-names = "xin24m";
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	dsi_dphy: phy@ff2e0000 {
+		compatible = "rockchip,px30-dsi-dphy";
+		reg = <0x0 0xff2e0000 0x0 0x10000>;
+		clocks = <&pmucru SCLK_MIPIDSIPHY_REF>, <&cru PCLK_MIPIDSIPHY>;
+		clock-names = "ref", "pclk";
+		#clock-cells = <0>;
+		resets = <&cru SRST_MIPIDSIPHY_P>;
+		reset-names = "apb";
+		#phy-cells = <0>;
+		power-domains = <&power PX30_PD_VO>;
+		status = "disabled";
+	};
+
+	usb20_otg: usb@ff300000 {
+		compatible = "rockchip,px30-usb", "rockchip,rk3066-usb",
+			     "snps,dwc2";
+		reg = <0x0 0xff300000 0x0 0x40000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_OTG>;
+		clock-names = "otg";
+		dr_mode = "otg";
+		g-np-tx-fifo-size = <16>;
+		g-rx-fifo-size = <280>;
+		g-tx-fifo-size = <256 128 128 64 32 16>;
+		g-use-dma;
+		power-domains = <&power PX30_PD_USB>;
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb@ff340000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xff340000 0x0 0x10000>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST>;
+		clock-names = "usbhost";
+		power-domains = <&power PX30_PD_USB>;
+		status = "disabled";
+	};
+
+	usb_host0_ohci: usb@ff350000 {
+		compatible = "generic-ohci";
+		reg = <0x0 0xff350000 0x0 0x10000>;
+		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST>;
+		clock-names = "usbhost";
+		power-domains = <&power PX30_PD_USB>;
+		status = "disabled";
+	};
+
+	gmac: ethernet@ff360000 {
+		compatible = "rockchip,px30-gmac";
+		reg = <0x0 0xff360000 0x0 0x10000>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "macirq";
+		clocks = <&cru SCLK_GMAC>, <&cru SCLK_GMAC_RX_TX>,
+			 <&cru SCLK_GMAC_RX_TX>, <&cru SCLK_MAC_REF>,
+			 <&cru SCLK_MAC_REFOUT>, <&cru ACLK_GMAC>,
+			 <&cru PCLK_GMAC>, <&cru SCLK_GMAC_RMII>;
+		clock-names = "stmmaceth", "mac_clk_rx",
+			      "mac_clk_tx", "clk_mac_ref",
+			      "clk_mac_refout", "aclk_mac",
+			      "pclk_mac", "clk_mac_speed";
+		rockchip,grf = <&grf>;
+		phy-mode = "rmii";
+		pinctrl-names = "default";
+		pinctrl-0 = <&rmii_pins &mac_refclk_12ma>;
+		power-domains = <&power PX30_PD_GMAC>;
+		resets = <&cru SRST_GMAC_A>;
+		reset-names = "stmmaceth";
+		status = "disabled";
+	};
+
+	sdmmc: dwmmc@ff370000 {
+		compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff370000 0x0 0x4000>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
+		power-domains = <&power PX30_PD_SDCARD>;
+		status = "disabled";
+	};
+
+	sdio: dwmmc@ff380000 {
+		compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff380000 0x0 0x4000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdio_bus4 &sdio_cmd &sdio_clk>;
+		power-domains = <&power PX30_PD_MMC_NAND>;
+		status = "disabled";
+	};
+
+	emmc: dwmmc@ff390000 {
+		compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff390000 0x0 0x4000>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
+			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+		power-domains = <&power PX30_PD_MMC_NAND>;
+		status = "disabled";
+	};
+
+	dsi: dsi@ff450000 {
+		compatible = "rockchip,px30-mipi-dsi";
+		reg = <0x0 0xff450000 0x0 0x10000>;
+		interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_MIPI_DSI>, <&dsi_dphy>;
+		clock-names = "pclk", "pll";
+		resets = <&cru SRST_MIPIDSI_HOST_P>;
+		reset-names = "apb";
+		phys = <&dsi_dphy>;
+		phy-names = "dphy";
+		power-domains = <&power PX30_PD_VO>;
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				dsi_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_dsi>;
+				};
+
+				dsi_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_dsi>;
+				};
+			};
+		};
+	};
+
+	vopb: vop@ff460000 {
+		compatible = "rockchip,px30-vop-big";
+		reg = <0x0 0xff460000 0x0 0xefc>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOPB>, <&cru DCLK_VOPB>,
+			 <&cru HCLK_VOPB>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_VOPB_A>, <&cru SRST_VOPB_H>, <&cru SRST_VOPB>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopb_mmu>;
+		power-domains = <&power PX30_PD_VO>;
+		rockchip,grf = <&grf>;
+		status = "disabled";
+
+		vopb_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vopb_out_dsi: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&dsi_in_vopb>;
+			};
+		};
+	};
+
+	vopb_mmu: iommu@ff460f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff460f00 0x0 0x100>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopb_mmu";
+		clocks = <&cru ACLK_VOPB>, <&cru HCLK_VOPB>;
+		clock-names = "aclk", "iface";
+		power-domains = <&power PX30_PD_VO>;
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	vopl: vop@ff470000 {
+		compatible = "rockchip,px30-vop-lit";
+		reg = <0x0 0xff470000 0x0 0xefc>;
+		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOPL>, <&cru DCLK_VOPL>,
+			 <&cru HCLK_VOPL>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_VOPL_A>, <&cru SRST_VOPL_H>, <&cru SRST_VOPL>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopl_mmu>;
+		power-domains = <&power PX30_PD_VO>;
+		rockchip,grf = <&grf>;
+		status = "disabled";
+
+		vopl_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vopl_out_dsi: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&dsi_in_vopl>;
+			};
+		};
+	};
+
+	vopl_mmu: iommu@ff470f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff470f00 0x0 0x100>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopl_mmu";
+		clocks = <&cru ACLK_VOPL>, <&cru HCLK_VOPL>;
+		clock-names = "aclk", "iface";
+		power-domains = <&power PX30_PD_VO>;
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	qos_gmac: qos@ff518000 {
+		compatible = "syscon";
+		reg = <0x0 0xff518000 0x0 0x20>;
+	};
+
+	qos_gpu: qos@ff520000 {
+		compatible = "syscon";
+		reg = <0x0 0xff520000 0x0 0x20>;
+	};
+
+	qos_sdmmc: qos@ff52c000 {
+		compatible = "syscon";
+		reg = <0x0 0xff52c000 0x0 0x20>;
+	};
+
+	qos_emmc: qos@ff538000 {
+		compatible = "syscon";
+		reg = <0x0 0xff538000 0x0 0x20>;
+	};
+
+	qos_nand: qos@ff538080 {
+		compatible = "syscon";
+		reg = <0x0 0xff538080 0x0 0x20>;
+	};
+
+	qos_sdio: qos@ff538100 {
+		compatible = "syscon";
+		reg = <0x0 0xff538100 0x0 0x20>;
+	};
+
+	qos_sfc: qos@ff538180 {
+		compatible = "syscon";
+		reg = <0x0 0xff538180 0x0 0x20>;
+	};
+
+	qos_usb_host: qos@ff540000 {
+		compatible = "syscon";
+		reg = <0x0 0xff540000 0x0 0x20>;
+	};
+
+	qos_usb_otg: qos@ff540080 {
+		compatible = "syscon";
+		reg = <0x0 0xff540080 0x0 0x20>;
+	};
+
+	qos_isp_128: qos@ff548000 {
+		compatible = "syscon";
+		reg = <0x0 0xff548000 0x0 0x20>;
+	};
+
+	qos_isp_rd: qos@ff548080 {
+		compatible = "syscon";
+		reg = <0x0 0xff548080 0x0 0x20>;
+	};
+
+	qos_isp_wr: qos@ff548100 {
+		compatible = "syscon";
+		reg = <0x0 0xff548100 0x0 0x20>;
+	};
+
+	qos_isp_m1: qos@ff548180 {
+		compatible = "syscon";
+		reg = <0x0 0xff548180 0x0 0x20>;
+	};
+
+	qos_vip: qos@ff548200 {
+		compatible = "syscon";
+		reg = <0x0 0xff548200 0x0 0x20>;
+	};
+
+	qos_rga_rd: qos@ff550000 {
+		compatible = "syscon";
+		reg = <0x0 0xff550000 0x0 0x20>;
+	};
+
+	qos_rga_wr: qos@ff550080 {
+		compatible = "syscon";
+		reg = <0x0 0xff550080 0x0 0x20>;
+	};
+
+	qos_vop_m0: qos@ff550100 {
+		compatible = "syscon";
+		reg = <0x0 0xff550100 0x0 0x20>;
+	};
+
+	qos_vop_m1: qos@ff550180 {
+		compatible = "syscon";
+		reg = <0x0 0xff550180 0x0 0x20>;
+	};
+
+	qos_vpu: qos@ff558000 {
+		compatible = "syscon";
+		reg = <0x0 0xff558000 0x0 0x20>;
+	};
+
+	qos_vpu_r128: qos@ff558080 {
+		compatible = "syscon";
+		reg = <0x0 0xff558080 0x0 0x20>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,px30-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio0: gpio0@ff040000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff040000 0x0 0x100>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmucru PCLK_GPIO0_PMU>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@ff250000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff250000 0x0 0x100>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2@ff260000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff260000 0x0 0x100>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio3@ff270000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff270000 0x0 0x100>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_2ma: pcfg-pull-none-2ma {
+			bias-disable;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+			bias-pull-up;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_up_4ma: pcfg-pull-up-4ma {
+			bias-pull-up;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_none_4ma: pcfg-pull-none-4ma {
+			bias-disable;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_down_4ma: pcfg-pull-down-4ma {
+			bias-pull-down;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_none_8ma: pcfg-pull-none-8ma {
+			bias-disable;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_up_8ma: pcfg-pull-up-8ma {
+			bias-pull-up;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_up_12ma: pcfg-pull-up-12ma {
+			bias-pull-up;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_none_smt: pcfg-pull-none-smt {
+			bias-disable;
+			input-schmitt-enable;
+		};
+
+		pcfg_output_high: pcfg-output-high {
+			output-high;
+		};
+
+		pcfg_output_low: pcfg-output-low {
+			output-low;
+		};
+
+		pcfg_input_high: pcfg-input-high {
+			bias-pull-up;
+			input-enable;
+		};
+
+		pcfg_input: pcfg-input {
+			input-enable;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins =
+					<0 RK_PB0 1 &pcfg_pull_none_smt>,
+					<0 RK_PB1 1 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins =
+					<0 RK_PC2 1 &pcfg_pull_none_smt>,
+					<0 RK_PC3 1 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins =
+					<2 RK_PB7 2 &pcfg_pull_none_smt>,
+					<2 RK_PC0 2 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins =
+					<1 RK_PB4 4 &pcfg_pull_none_smt>,
+					<1 RK_PB5 4 &pcfg_pull_none_smt>;
+			};
+		};
+
+		tsadc {
+			tsadc_otp_gpio: tsadc-otp-gpio {
+				rockchip,pins =
+					<0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			tsadc_otp_out: tsadc-otp-out {
+				rockchip,pins =
+					<0 RK_PA6 1 &pcfg_pull_none>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins =
+					<0 RK_PB2 1 &pcfg_pull_up>,
+					<0 RK_PB3 1 &pcfg_pull_up>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins =
+					<0 RK_PB4 1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins =
+					<0 RK_PB5 1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins =
+					<1 RK_PC1 1 &pcfg_pull_up>,
+					<1 RK_PC0 1 &pcfg_pull_up>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins =
+					<1 RK_PC2 1 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins =
+					<1 RK_PC3 1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2-m0 {
+			uart2m0_xfer: uart2m0-xfer {
+				rockchip,pins =
+					<1 RK_PD2 2 &pcfg_pull_up>,
+					<1 RK_PD3 2 &pcfg_pull_up>;
+			};
+		};
+
+		uart2-m1 {
+			uart2m1_xfer: uart2m1-xfer {
+				rockchip,pins =
+					<2 RK_PB4 2 &pcfg_pull_up>,
+					<2 RK_PB6 2 &pcfg_pull_up>;
+			};
+		};
+
+		uart3-m0 {
+			uart3m0_xfer: uart3m0-xfer {
+				rockchip,pins =
+					<0 RK_PC0 2 &pcfg_pull_up>,
+					<0 RK_PC1 2 &pcfg_pull_up>;
+			};
+
+			uart3m0_cts: uart3m0-cts {
+				rockchip,pins =
+					<0 RK_PC2 2 &pcfg_pull_none>;
+			};
+
+			uart3m0_rts: uart3m0-rts {
+				rockchip,pins =
+					<0 RK_PC3 2 &pcfg_pull_none>;
+			};
+		};
+
+		uart3-m1 {
+			uart3m1_xfer: uart3m1-xfer {
+				rockchip,pins =
+					<1 RK_PB6 2 &pcfg_pull_up>,
+					<1 RK_PB7 2 &pcfg_pull_up>;
+			};
+
+			uart3m1_cts: uart3m1-cts {
+				rockchip,pins =
+					<1 RK_PB4 2 &pcfg_pull_none>;
+			};
+
+			uart3m1_rts: uart3m1-rts {
+				rockchip,pins =
+					<1 RK_PB5 2 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins =
+					<1 RK_PD4 2 &pcfg_pull_up>,
+					<1 RK_PD5 2 &pcfg_pull_up>;
+			};
+
+			uart4_cts: uart4-cts {
+				rockchip,pins =
+					<1 RK_PD6 2 &pcfg_pull_none>;
+			};
+
+			uart4_rts: uart4-rts {
+				rockchip,pins =
+					<1 RK_PD7 2 &pcfg_pull_none>;
+			};
+		};
+
+		uart5 {
+			uart5_xfer: uart5-xfer {
+				rockchip,pins =
+					<3 RK_PA2 4 &pcfg_pull_up>,
+					<3 RK_PA1 4 &pcfg_pull_up>;
+			};
+
+			uart5_cts: uart5-cts {
+				rockchip,pins =
+					<3 RK_PA3 4 &pcfg_pull_none>;
+			};
+
+			uart5_rts: uart5-rts {
+				rockchip,pins =
+					<3 RK_PA5 4 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins =
+					<1 RK_PB7 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_csn: spi0-csn {
+				rockchip,pins =
+					<1 RK_PB6 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_miso: spi0-miso {
+				rockchip,pins =
+					<1 RK_PB5 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_mosi: spi0-mosi {
+				rockchip,pins =
+					<1 RK_PB4 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_clk_hs: spi0-clk-hs {
+				rockchip,pins =
+					<1 RK_PB7 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi0_miso_hs: spi0-miso-hs {
+				rockchip,pins =
+					<1 RK_PB5 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi0_mosi_hs: spi0-mosi-hs {
+				rockchip,pins =
+					<1 RK_PB4 3 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins =
+					<3 RK_PB7 4 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_csn0: spi1-csn0 {
+				rockchip,pins =
+					<3 RK_PB1 4 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_csn1: spi1-csn1 {
+				rockchip,pins =
+					<3 RK_PB2 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_miso: spi1-miso {
+				rockchip,pins =
+					<3 RK_PB6 4 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_mosi: spi1-mosi {
+				rockchip,pins =
+					<3 RK_PB4 4 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_clk_hs: spi1-clk-hs {
+				rockchip,pins =
+					<3 RK_PB7 4 &pcfg_pull_up_8ma>;
+			};
+
+			spi1_miso_hs: spi1-miso-hs {
+				rockchip,pins =
+					<3 RK_PB6 4 &pcfg_pull_up_8ma>;
+			};
+
+			spi1_mosi_hs: spi1-mosi-hs {
+				rockchip,pins =
+					<3 RK_PB4 4 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		pdm {
+			pdm_clk0m0: pdm-clk0m0 {
+				rockchip,pins =
+					<3 RK_PC6 2 &pcfg_pull_none>;
+			};
+
+			pdm_clk0m1: pdm-clk0m1 {
+				rockchip,pins =
+					<2 RK_PC6 1 &pcfg_pull_none>;
+			};
+
+			pdm_clk1: pdm-clk1 {
+				rockchip,pins =
+					<3 RK_PC7 2 &pcfg_pull_none>;
+			};
+
+			pdm_sdi0m0: pdm-sdi0m0 {
+				rockchip,pins =
+					<3 RK_PD3 2 &pcfg_pull_none>;
+			};
+
+			pdm_sdi0m1: pdm-sdi0m1 {
+				rockchip,pins =
+					<2 RK_PC5 2 &pcfg_pull_none>;
+			};
+
+			pdm_sdi1: pdm-sdi1 {
+				rockchip,pins =
+					<3 RK_PD0 2 &pcfg_pull_none>;
+			};
+
+			pdm_sdi2: pdm-sdi2 {
+				rockchip,pins =
+					<3 RK_PD1 2 &pcfg_pull_none>;
+			};
+
+			pdm_sdi3: pdm-sdi3 {
+				rockchip,pins =
+					<3 RK_PD2 2 &pcfg_pull_none>;
+			};
+
+			pdm_clk0m0_sleep: pdm-clk0m0-sleep {
+				rockchip,pins =
+					<3 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_clk0m_sleep1: pdm-clk0m1-sleep {
+				rockchip,pins =
+					<2 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_clk1_sleep: pdm-clk1-sleep {
+				rockchip,pins =
+					<3 RK_PC7 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_sdi0m0_sleep: pdm-sdi0m0-sleep {
+				rockchip,pins =
+					<3 RK_PD3 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_sdi0m1_sleep: pdm-sdi0m1-sleep {
+				rockchip,pins =
+					<2 RK_PC5 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_sdi1_sleep: pdm-sdi1-sleep {
+				rockchip,pins =
+					<3 RK_PD0 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_sdi2_sleep: pdm-sdi2-sleep {
+				rockchip,pins =
+					<3 RK_PD1 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+
+			pdm_sdi3_sleep: pdm-sdi3-sleep {
+				rockchip,pins =
+					<3 RK_PD2 RK_FUNC_GPIO &pcfg_input_high>;
+			};
+		};
+
+		i2s0 {
+			i2s0_8ch_mclk: i2s0-8ch-mclk {
+				rockchip,pins =
+					<3 RK_PC1 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sclktx: i2s0-8ch-sclktx {
+				rockchip,pins =
+					<3 RK_PC3 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sclkrx: i2s0-8ch-sclkrx {
+				rockchip,pins =
+					<3 RK_PB4 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_lrcktx: i2s0-8ch-lrcktx {
+				rockchip,pins =
+					<3 RK_PC2 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_lrckrx: i2s0-8ch-lrckrx {
+				rockchip,pins =
+					<3 RK_PB5 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdo0: i2s0-8ch-sdo0 {
+				rockchip,pins =
+					<3 RK_PC4 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdo1: i2s0-8ch-sdo1 {
+				rockchip,pins =
+					<3 RK_PC0 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdo2: i2s0-8ch-sdo2 {
+				rockchip,pins =
+					<3 RK_PB7 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdo3: i2s0-8ch-sdo3 {
+				rockchip,pins =
+					<3 RK_PB6 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdi0: i2s0-8ch-sdi0 {
+				rockchip,pins =
+					<3 RK_PC5 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdi1: i2s0-8ch-sdi1 {
+				rockchip,pins =
+					<3 RK_PB3 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdi2: i2s0-8ch-sdi2 {
+				rockchip,pins =
+					<3 RK_PB1 2 &pcfg_pull_none>;
+			};
+
+			i2s0_8ch_sdi3: i2s0-8ch-sdi3 {
+				rockchip,pins =
+					<3 RK_PB0 2 &pcfg_pull_none>;
+			};
+		};
+
+		i2s1 {
+			i2s1_2ch_mclk: i2s1-2ch-mclk {
+				rockchip,pins =
+					<2 RK_PC3 1 &pcfg_pull_none>;
+			};
+
+			i2s1_2ch_sclk: i2s1-2ch-sclk {
+				rockchip,pins =
+					<2 RK_PC2 1 &pcfg_pull_none>;
+			};
+
+			i2s1_2ch_lrck: i2s1-2ch-lrck {
+				rockchip,pins =
+					<2 RK_PC1 1 &pcfg_pull_none>;
+			};
+
+			i2s1_2ch_sdi: i2s1-2ch-sdi {
+				rockchip,pins =
+					<2 RK_PC5 1 &pcfg_pull_none>;
+			};
+
+			i2s1_2ch_sdo: i2s1-2ch-sdo {
+				rockchip,pins =
+					<2 RK_PC4 1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s2 {
+			i2s2_2ch_mclk: i2s2-2ch-mclk {
+				rockchip,pins =
+					<3 RK_PA1 2 &pcfg_pull_none>;
+			};
+
+			i2s2_2ch_sclk: i2s2-2ch-sclk {
+				rockchip,pins =
+					<3 RK_PA2 2 &pcfg_pull_none>;
+			};
+
+			i2s2_2ch_lrck: i2s2-2ch-lrck {
+				rockchip,pins =
+					<3 RK_PA3 2 &pcfg_pull_none>;
+			};
+
+			i2s2_2ch_sdi: i2s2-2ch-sdi {
+				rockchip,pins =
+					<3 RK_PA5 2 &pcfg_pull_none>;
+			};
+
+			i2s2_2ch_sdo: i2s2-2ch-sdo {
+				rockchip,pins =
+					<3 RK_PA7 2 &pcfg_pull_none>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins =
+					<1 RK_PD6 1 &pcfg_pull_none_8ma>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins =
+					<1 RK_PD7 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdmmc_det: sdmmc-det {
+				rockchip,pins =
+					<0 RK_PA3 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins =
+					<1 RK_PD2 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins =
+					<1 RK_PD2 1 &pcfg_pull_up_8ma>,
+					<1 RK_PD3 1 &pcfg_pull_up_8ma>,
+					<1 RK_PD4 1 &pcfg_pull_up_8ma>,
+					<1 RK_PD5 1 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		sdio {
+			sdio_clk: sdio-clk {
+				rockchip,pins =
+					<1 RK_PC5 1 &pcfg_pull_none>;
+			};
+
+			sdio_cmd: sdio-cmd {
+				rockchip,pins =
+					<1 RK_PC4 1 &pcfg_pull_up>;
+			};
+
+			sdio_bus4: sdio-bus4 {
+				rockchip,pins =
+					<1 RK_PC6 1 &pcfg_pull_up>,
+					<1 RK_PC7 1 &pcfg_pull_up>,
+					<1 RK_PD0 1 &pcfg_pull_up>,
+					<1 RK_PD1 1 &pcfg_pull_up>;
+			};
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins =
+					<1 RK_PB1 2 &pcfg_pull_none_8ma>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins =
+					<1 RK_PB2 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_rstnout: emmc-rstnout {
+				rockchip,pins =
+					<1 RK_PB3 2 &pcfg_pull_none>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins =
+					<1 RK_PA0 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_bus4: emmc-bus4 {
+				rockchip,pins =
+					<1 RK_PA0 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA1 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA2 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA3 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins =
+					<1 RK_PA0 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA1 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA2 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA3 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA4 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA5 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA6 2 &pcfg_pull_up_8ma>,
+					<1 RK_PA7 2 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		flash {
+			flash_cs0: flash-cs0 {
+				rockchip,pins =
+					<1 RK_PB0 1 &pcfg_pull_none>;
+			};
+
+			flash_rdy: flash-rdy {
+				rockchip,pins =
+					<1 RK_PB1 1 &pcfg_pull_none>;
+			};
+
+			flash_dqs: flash-dqs {
+				rockchip,pins =
+					<1 RK_PB2 1 &pcfg_pull_none>;
+			};
+
+			flash_ale: flash-ale {
+				rockchip,pins =
+					<1 RK_PB3 1 &pcfg_pull_none>;
+			};
+
+			flash_cle: flash-cle {
+				rockchip,pins =
+					<1 RK_PB4 1 &pcfg_pull_none>;
+			};
+
+			flash_wrn: flash-wrn {
+				rockchip,pins =
+					<1 RK_PB5 1 &pcfg_pull_none>;
+			};
+
+			flash_csl: flash-csl {
+				rockchip,pins =
+					<1 RK_PB6 1 &pcfg_pull_none>;
+			};
+
+			flash_rdn: flash-rdn {
+				rockchip,pins =
+					<1 RK_PB7 1 &pcfg_pull_none>;
+			};
+
+			flash_bus8: flash-bus8 {
+				rockchip,pins =
+					<1 RK_PA0 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA1 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA2 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA3 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA4 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA5 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA6 1 &pcfg_pull_up_12ma>,
+					<1 RK_PA7 1 &pcfg_pull_up_12ma>;
+			};
+		};
+
+		lcdc {
+			lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin {
+				rockchip,pins =
+					<3 RK_PA0 1 &pcfg_pull_none_12ma>;
+			};
+
+			lcdc_rgb_m0_hsync_pin: lcdc-rgb-m0-hsync-pin {
+				rockchip,pins =
+					<3 RK_PA1 1 &pcfg_pull_none_12ma>;
+			};
+
+			lcdc_rgb_m0_vsync_pin: lcdc-rgb-m0-vsync-pin {
+				rockchip,pins =
+					<3 RK_PA2 1 &pcfg_pull_none_12ma>;
+			};
+
+			lcdc_rgb_m0_den_pin: lcdc-rgb-m0-den-pin {
+				rockchip,pins =
+					<3 RK_PA3 1 &pcfg_pull_none_12ma>;
+			};
+
+			lcdc_rgb888_m0_data_pins: lcdc-rgb888-m0-data-pins {
+				rockchip,pins =
+					<3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */
+					<3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */
+					<3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */
+					<3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */
+					<3 RK_PC7 1 &pcfg_pull_none_8ma>, /* lcdc_d19 */
+					<3 RK_PC6 1 &pcfg_pull_none_8ma>, /* lcdc_d18 */
+					<3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */
+					<3 RK_PC4 1 &pcfg_pull_none_8ma>, /* lcdc_d16 */
+					<3 RK_PD3 1 &pcfg_pull_none_8ma>, /* lcdc_d23 */
+					<3 RK_PD2 1 &pcfg_pull_none_8ma>, /* lcdc_d22 */
+					<3 RK_PD1 1 &pcfg_pull_none_8ma>, /* lcdc_d21 */
+					<3 RK_PD0 1 &pcfg_pull_none_8ma>; /* lcdc_d20 */
+			};
+
+			lcdc_rgb666_m0_data_pins: lcdc-rgb666-m0-data-pins {
+				rockchip,pins =
+					<3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */
+					<3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */
+					<3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */
+					<3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */
+					<3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */
+					<3 RK_PC4 1 &pcfg_pull_none_8ma>; /* lcdc_d16 */
+			};
+
+			lcdc_rgb565_m0_data_pins: lcdc-rgb565-m0-data-pins {
+				rockchip,pins =
+					<3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */
+					<3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */
+					<3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */
+					<3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>; /* lcdc_d12 */
+			};
+
+			lcdc_rgb888_m1_data_pins: lcdc-rgb888-m1-data-pins {
+				rockchip,pins =
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */
+					<3 RK_PC7 1 &pcfg_pull_none_8ma>, /* lcdc_d19 */
+					<3 RK_PC6 1 &pcfg_pull_none_8ma>, /* lcdc_d18 */
+					<3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */
+					<3 RK_PC4 1 &pcfg_pull_none_8ma>, /* lcdc_d16 */
+					<3 RK_PD3 1 &pcfg_pull_none_8ma>, /* lcdc_d23 */
+					<3 RK_PD2 1 &pcfg_pull_none_8ma>, /* lcdc_d22 */
+					<3 RK_PD1 1 &pcfg_pull_none_8ma>, /* lcdc_d21 */
+					<3 RK_PD0 1 &pcfg_pull_none_8ma>; /* lcdc_d20 */
+			};
+
+			lcdc_rgb666_m1_data_pins: lcdc-rgb666-m1-data-pins {
+				rockchip,pins =
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */
+					<3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */
+					<3 RK_PC4 1 &pcfg_pull_none_8ma>; /* lcdc_d16 */
+			};
+
+			lcdc_rgb565_m1_data_pins: lcdc-rgb565-m1-data-pins {
+				rockchip,pins =
+					<3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */
+					<3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */
+					<3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */
+					<3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */
+					<3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */
+					<3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */
+					<3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */
+					<3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */
+					<3 RK_PC0 1 &pcfg_pull_none_8ma>; /* lcdc_d12 */
+			};
+		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins =
+					<0 RK_PB7 1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins =
+					<0 RK_PC0 1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins =
+					<2 RK_PB5 1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_pin: pwm3-pin {
+				rockchip,pins =
+					<0 RK_PC1 1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm4 {
+			pwm4_pin: pwm4-pin {
+				rockchip,pins =
+					<3 RK_PC2 3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm5 {
+			pwm5_pin: pwm5-pin {
+				rockchip,pins =
+					<3 RK_PC3 3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm6 {
+			pwm6_pin: pwm6-pin {
+				rockchip,pins =
+					<3 RK_PC4 3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm7 {
+			pwm7_pin: pwm7-pin {
+				rockchip,pins =
+					<3 RK_PC5 3 &pcfg_pull_none>;
+			};
+		};
+
+		gmac {
+			rmii_pins: rmii-pins {
+				rockchip,pins =
+					<2 RK_PA0 2 &pcfg_pull_none_12ma>, /* mac_txen */
+					<2 RK_PA1 2 &pcfg_pull_none_12ma>, /* mac_txd1 */
+					<2 RK_PA2 2 &pcfg_pull_none_12ma>, /* mac_txd0 */
+					<2 RK_PA3 2 &pcfg_pull_none>, /* mac_rxd0 */
+					<2 RK_PA4 2 &pcfg_pull_none>, /* mac_rxd1 */
+					<2 RK_PA5 2 &pcfg_pull_none>, /* mac_rxer */
+					<2 RK_PA6 2 &pcfg_pull_none>, /* mac_rxdv */
+					<2 RK_PA7 2 &pcfg_pull_none>, /* mac_mdio */
+					<2 RK_PB1 2 &pcfg_pull_none>; /* mac_mdc */
+			};
+
+			mac_refclk_12ma: mac-refclk-12ma {
+				rockchip,pins =
+					<2 RK_PB2 2 &pcfg_pull_none_12ma>;
+			};
+
+			mac_refclk: mac-refclk {
+				rockchip,pins =
+					<2 RK_PB2 2 &pcfg_pull_none>;
+			};
+		};
+
+		cif-m0 {
+			cif_clkout_m0: cif-clkout-m0 {
+				rockchip,pins =
+					<2 RK_PB3 1 &pcfg_pull_none>;
+			};
+
+			dvp_d2d9_m0: dvp-d2d9-m0 {
+				rockchip,pins =
+					<2 RK_PA0 1 &pcfg_pull_none>, /* cif_data2 */
+					<2 RK_PA1 1 &pcfg_pull_none>, /* cif_data3 */
+					<2 RK_PA2 1 &pcfg_pull_none>, /* cif_data4 */
+					<2 RK_PA3 1 &pcfg_pull_none>, /* cif_data5 */
+					<2 RK_PA4 1 &pcfg_pull_none>, /* cif_data6 */
+					<2 RK_PA5 1 &pcfg_pull_none>, /* cif_data7 */
+					<2 RK_PA6 1 &pcfg_pull_none>, /* cif_data8 */
+					<2 RK_PA7 1 &pcfg_pull_none>, /* cif_data9 */
+					<2 RK_PB0 1 &pcfg_pull_none>, /* cif_sync */
+					<2 RK_PB1 1 &pcfg_pull_none>, /* cif_href */
+					<2 RK_PB2 1 &pcfg_pull_none>, /* cif_clkin */
+					<2 RK_PB3 1 &pcfg_pull_none>; /* cif_clkout */
+			};
+
+			dvp_d0d1_m0: dvp-d0d1-m0 {
+				rockchip,pins =
+					<2 RK_PB4 1 &pcfg_pull_none>, /* cif_data0 */
+					<2 RK_PB6 1 &pcfg_pull_none>; /* cif_data1 */
+			};
+
+			dvp_d10d11_m0:d10-d11-m0 {
+				rockchip,pins =
+					<2 RK_PB7 1 &pcfg_pull_none>, /* cif_data10 */
+					<2 RK_PC0 1 &pcfg_pull_none>; /* cif_data11 */
+			};
+		};
+
+		cif-m1 {
+			cif_clkout_m1: cif-clkout-m1 {
+				rockchip,pins =
+					<3 RK_PD0 3 &pcfg_pull_none>;
+			};
+
+			dvp_d2d9_m1: dvp-d2d9-m1 {
+				rockchip,pins =
+					<3 RK_PA3 3 &pcfg_pull_none>, /* cif_data2 */
+					<3 RK_PA5 3 &pcfg_pull_none>, /* cif_data3 */
+					<3 RK_PA7 3 &pcfg_pull_none>, /* cif_data4 */
+					<3 RK_PB0 3 &pcfg_pull_none>, /* cif_data5 */
+					<3 RK_PB1 3 &pcfg_pull_none>, /* cif_data6 */
+					<3 RK_PB4 3 &pcfg_pull_none>, /* cif_data7 */
+					<3 RK_PB6 3 &pcfg_pull_none>, /* cif_data8 */
+					<3 RK_PB7 3 &pcfg_pull_none>, /* cif_data9 */
+					<3 RK_PD1 3 &pcfg_pull_none>, /* cif_sync */
+					<3 RK_PD2 3 &pcfg_pull_none>, /* cif_href */
+					<3 RK_PD3 3 &pcfg_pull_none>, /* cif_clkin */
+					<3 RK_PD0 3 &pcfg_pull_none>; /* cif_clkout */
+			};
+
+			dvp_d0d1_m1: dvp-d0d1-m1 {
+				rockchip,pins =
+					<3 RK_PA1 3 &pcfg_pull_none>, /* cif_data0 */
+					<3 RK_PA2 3 &pcfg_pull_none>; /* cif_data1 */
+			};
+
+			dvp_d10d11_m1:d10-d11-m1 {
+				rockchip,pins =
+					<3 RK_PC6 3 &pcfg_pull_none>, /* cif_data10 */
+					<3 RK_PC7 3 &pcfg_pull_none>; /* cif_data11 */
+			};
+		};
+
+		isp {
+			isp_prelight: isp-prelight {
+				rockchip,pins =
+					<3 RK_PD1 4 &pcfg_pull_none>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi b/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..a177fca73a55c3a24f6f6ff2adb1dfe2deadc8ff
--- /dev/null
+++ b/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Amarula Solutions SRO
+ */
+
+#include "rk3288-u-boot.dtsi"
+#include "rk3288-tinker-u-boot.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = \
+			"same-as-spl", &sdmmc, &emmc;
+	};
+};
+
+&emmc {
+	u-boot,dm-spl;
+};
+
+&emmc_clk {
+	u-boot,dm-spl;
+};
+
+&emmc_cmd {
+	u-boot,dm-spl;
+};
+
+&emmc_pwr {
+	u-boot,dm-spl;
+};
+
+&emmc_bus8 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rk3288-tinker-s.dts b/arch/arm/dts/rk3288-tinker-s.dts
new file mode 100644
index 0000000000000000000000000000000000000000..cc7ac5f8811c71fd35edeb8f174c9b3314ba14e7
--- /dev/null
+++ b/arch/arm/dts/rk3288-tinker-s.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "rk3288-tinker.dtsi"
+
+/ {
+	model = "Rockchip RK3288 Asus Tinker Board S";
+	compatible = "asus,rk3288-tinker-s", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+	max-frequency = <150000000>;
+	mmc-hs200-1_8v;
+	mmc-ddr-1_8v;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-tinker-u-boot.dtsi b/arch/arm/dts/rk3288-tinker-u-boot.dtsi
index f7f9d6dc721aae3c5f67c4ef54ad2edaa2ff3c40..732aa4f91fc7aab52613b0af3e2e79bce7579967 100644
--- a/arch/arm/dts/rk3288-tinker-u-boot.dtsi
+++ b/arch/arm/dts/rk3288-tinker-u-boot.dtsi
@@ -5,6 +5,18 @@
 
 #include "rk3288-u-boot.dtsi"
 
+&dmc {
+	u-boot,dm-pre-reloc;
+	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
+		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
+		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
+		0x1 0x2 0x2 0x4 0x0 0x0 0xc0 0x4
+		0x8 0x1f4>;
+	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
+		0x0 0xc3 0x6 0x2>;
+	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
+};
+
 &pinctrl {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/rk3288-tinker.dts b/arch/arm/dts/rk3288-tinker.dts
index 94c3afe8604ef532b266ec1e59f27d66c11703b2..4b8405fd82445ffc22d7af4abe1be711d15f14b2 100644
--- a/arch/arm/dts/rk3288-tinker.dts
+++ b/arch/arm/dts/rk3288-tinker.dts
@@ -15,18 +15,6 @@
 	};
 };
 
-&dmc {
-	rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
-		0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
-		0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
-		0x1 0x2 0x2 0x4 0x0 0x0 0xc0 0x4
-		0x8 0x1f4>;
-	rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
-		0x0 0xc3 0x6 0x2>;
-	rockchip,sdram-params = <0x20d266a4 0x5b6 2 533000000 6 9 0>;
-};
-
-
 &pinctrl {
 	usb {
 		host_vbus_drv: host-vbus-drv {
diff --git a/arch/arm/dts/rk3308-evb-u-boot.dtsi b/arch/arm/dts/rk3308-evb-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..c6ea746de071881f781f762229ef14c0d59a99ef
--- /dev/null
+++ b/arch/arm/dts/rk3308-evb-u-boot.dtsi
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd
+ */
+#include "rk3308-u-boot.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = "same-as-spl", &emmc;
+	};
+};
+
+&uart4 {
+	u-boot,dm-pre-reloc;
+	clock-frequency = <24000000>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3308-evb.dts b/arch/arm/dts/rk3308-evb.dts
new file mode 100644
index 0000000000000000000000000000000000000000..124a24086684b7227fa208e43c810750dd4825d0
--- /dev/null
+++ b/arch/arm/dts/rk3308-evb.dts
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rk3308.dtsi"
+
+/ {
+	model = "Rockchip RK3308 EVB";
+	compatible = "rockchip,rk3308-evb", "rockchip,rk3308";
+
+	chosen {
+		stdout-path = "serial4:1500000n8";
+	};
+
+	adc-keys0 {
+		compatible = "adc-keys";
+		io-channels = <&saradc 0>;
+		io-channel-names = "buttons";
+		poll-interval = <100>;
+		keyup-threshold-microvolt = <1800000>;
+
+		func-key {
+			linux,code = <KEY_FN>;
+			label = "function";
+			press-threshold-microvolt = <18000>;
+		};
+	};
+
+	adc-keys1 {
+		compatible = "adc-keys";
+		io-channels = <&saradc 1>;
+		io-channel-names = "buttons";
+		poll-interval = <100>;
+		keyup-threshold-microvolt = <1800000>;
+
+		esc-key {
+			linux,code = <KEY_MICMUTE>;
+			label = "micmute";
+			press-threshold-microvolt = <1130000>;
+		};
+
+		home-key {
+			linux,code = <KEY_MODE>;
+			label = "mode";
+			press-threshold-microvolt = <901000>;
+		};
+
+		menu-key {
+			linux,code = <KEY_PLAY>;
+			label = "play";
+			press-threshold-microvolt = <624000>;
+		};
+
+		vol-down-key {
+			linux,code = <KEY_VOLUMEDOWN>;
+			label = "volume down";
+			press-threshold-microvolt = <300000>;
+		};
+
+		vol-up-key {
+			linux,code = <KEY_VOLUMEUP>;
+			label = "volume up";
+			press-threshold-microvolt = <18000>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_key>;
+
+		power {
+			gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			label = "GPIO Key Power";
+			wakeup-source;
+			debounce-interval = <100>;
+		};
+	};
+
+	vcc12v_dcin: vcc12v-dcin {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc12v_dcin";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+	};
+
+	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>;
+		vin-supply = <&vcc12v_dcin>;
+	};
+
+	vdd_core: vdd-core {
+		compatible = "pwm-regulator";
+		pwms = <&pwm0 0 5000 1>;
+		regulator-name = "vdd_core";
+		regulator-min-microvolt = <827000>;
+		regulator-max-microvolt = <1340000>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-settling-time-up-us = <250>;
+		pwm-supply = <&vcc5v0_sys>;
+	};
+
+	vdd_log: vdd-log {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_log";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vdd_1v0: vdd-1v0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_1v0";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vccio_sdio: vcc_1v8: vcc-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_1v8";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_ddr: vcc-ddr {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_ddr";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc_io: vcc-io {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vccio_flash: vccio-flash {
+		compatible = "regulator-fixed";
+		regulator-name = "vccio_flash";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc5v0_host: vcc5v0-host {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb_drv>;
+		regulator-name = "vbus_host";
+		vin-supply = <&vcc5v0_sys>;
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&vdd_core>;
+};
+
+&saradc {
+	status = "okay";
+	vref-supply = <&vcc_1v8>;
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rtc_32k>;
+
+	buttons {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 RK_PA6 0 &pcfg_pull_up>;
+		};
+	};
+
+	usb {
+		usb_drv: usb-drv {
+			rockchip,pins = <0 RK_PC5 0 &pcfg_pull_none>;
+		};
+	};
+
+	sdio-pwrseq {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins = <0 RK_PA2 0 &pcfg_pull_none>;
+		};
+	};
+};
+
+&pwm0 {
+	status = "okay";
+	pinctrl-0 = <&pwm0_pin_pull_down>;
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_xfer>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3308-roc-cc-u-boot.dtsi b/arch/arm/dts/rk3308-roc-cc-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..ffbe742053fc0827b09d20847d2cf8d9cb75e8ef
--- /dev/null
+++ b/arch/arm/dts/rk3308-roc-cc-u-boot.dtsi
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd
+ */
+#include "rk3308-u-boot.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = "same-as-spl", &emmc;
+	};
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+	clock-frequency = <24000000>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3308-roc-cc.dts b/arch/arm/dts/rk3308-roc-cc.dts
new file mode 100644
index 0000000000000000000000000000000000000000..e10aa638a305b9a57e01b6e46d3f2d2373769b19
--- /dev/null
+++ b/arch/arm/dts/rk3308-roc-cc.dts
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+/dts-v1/;
+#include "rk3308.dtsi"
+
+/ {
+	model = "Firefly ROC-RK3308-CC board";
+	compatible = "firefly,roc-rk3308-cc", "rockchip,rk3308";
+	chosen {
+		stdout-path = "serial2:1500000n8";
+	};
+
+	ir_rx {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_recv_pin>;
+	};
+
+	ir_tx {
+		compatible = "pwm-ir-tx";
+		pwms = <&pwm5 0 25000 0>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		power {
+			label = "firefly:red:power";
+			linux,default-trigger = "ir-power-click";
+			default-state = "on";
+			gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+		};
+
+		user {
+			label = "firefly:blue:user";
+			linux,default-trigger = "ir-user-click";
+			default-state = "off";
+			gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	typec_vcc5v: typec-vcc5v {
+		compatible = "regulator-fixed";
+		regulator-name = "typec_vcc5v";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vcc5v0_sys: vcc5v0-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc5v0_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&typec_vcc5v>;
+	};
+
+	vdd_core: vdd-core {
+		compatible = "pwm-regulator";
+		pwms = <&pwm0 0 5000 1>;
+		regulator-name = "vdd_core";
+		regulator-min-microvolt = <827000>;
+		regulator-max-microvolt = <1340000>;
+		regulator-init-microvolt = <1015000>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-settling-time-up-us = <250>;
+		pwm-supply = <&vcc5v0_sys>;
+	};
+
+	vdd_log: vdd-log {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_log";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc_io: vcc-io {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc_sdmmc: vcc-sdmmc {
+		compatible = "regulator-gpio";
+		regulator-name = "vcc_sdmmc";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0
+			  3300000 0x1>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	vcc_sd: vcc-sd {
+		compatible = "regulator-fixed";
+		gpio = <&gpio4 RK_PD6 GPIO_ACTIVE_LOW>;
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vim-supply = <&vcc_io>;
+	};
+
+};
+
+&cpu0 {
+	cpu-supply = <&vdd_core>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	supports-emmc;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	rtc: rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+	};
+};
+
+&pwm5 {
+	status = "okay";
+	pinctrl-names = "active";
+	pinctrl-0 = <&pwm5_pin_pull_down>;
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rtc_32k>;
+
+	ir-receiver {
+		ir_recv_pin: ir-recv-pin  {
+			rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	buttons {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+};
+
+&pwm0 {
+	status = "okay";
+	pinctrl-0 = <&pwm0_pin_pull_down>;
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	supports-sd;
+	card-detect-delay = <300>;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vcc_sdmmc>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3308-u-boot.dtsi b/arch/arm/dts/rk3308-u-boot.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..1a68decef386efe23958bf1d5814c06132157d31
--- /dev/null
+++ b/arch/arm/dts/rk3308-u-boot.dtsi
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *(C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&saradc {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3308.dtsi b/arch/arm/dts/rk3308.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..0eeec165d4d4a6e50d84fb7af86c7b5d577860a4
--- /dev/null
+++ b/arch/arm/dts/rk3308.dtsi
@@ -0,0 +1,1829 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ */
+
+#include <dt-bindings/clock/rk3308-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+	compatible = "rockchip,rk3308";
+
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLK>;
+			#cooling-cells = <2>;
+			dynamic-power-coefficient = <90>;
+			operating-points-v2 = <&cpu0_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP>;
+			next-level-cache = <&l2>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			operating-points-v2 = <&cpu0_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP>;
+			next-level-cache = <&l2>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			operating-points-v2 = <&cpu0_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP>;
+			next-level-cache = <&l2>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			operating-points-v2 = <&cpu0_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP>;
+			next-level-cache = <&l2>;
+		};
+
+		idle-states {
+			entry-method = "psci";
+
+			CPU_SLEEP: cpu-sleep {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x0010000>;
+				entry-latency-us = <120>;
+				exit-latency-us = <250>;
+				min-residency-us = <900>;
+			};
+		};
+
+		l2: l2-cache {
+			compatible = "cache";
+		};
+	};
+
+	cpu0_opp_table: cpu0-opp-table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-microvolt = <950000 950000 1340000>;
+			clock-latency-ns = <40000>;
+			opp-suspend;
+		};
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <950000 950000 1340000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-816000000 {
+			opp-hz = /bits/ 64 <816000000>;
+			opp-microvolt = <1025000 1025000 1340000>;
+			clock-latency-ns = <40000>;
+		};
+		opp-1008000000 {
+			opp-hz = /bits/ 64 <1008000000>;
+			opp-microvolt = <1125000 1125000 1340000>;
+			clock-latency-ns = <40000>;
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	mac_clkin: external-mac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+		clock-output-names = "mac_clkin";
+		#clock-cells = <0>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	xin24m: xin24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+	};
+
+	grf: grf@ff000000 {
+		compatible = "rockchip,rk3308-grf", "syscon", "simple-mfd";
+		reg = <0x0 0xff000000 0x0 0x10000>;
+	};
+
+	dmc: dmc@0xff010000 {
+		compatible = "rockchip,rk3308-dmc";
+		reg = <0x0 0xff010000 0x0 0x10000>;
+	};
+
+	detect_grf: syscon@ff00b000 {
+		compatible = "rockchip,rk3308-detect-grf", "syscon", "simple-mfd";
+		reg = <0x0 0xff00b000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	core_grf: syscon@ff00c000 {
+		compatible = "rockchip,rk3308-core-grf", "syscon", "simple-mfd";
+		reg = <0x0 0xff00c000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+	};
+
+	i2c0: i2c@ff040000 {
+		compatible = "rockchip,rk3308-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff040000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@ff050000 {
+		compatible = "rockchip,rk3308-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff050000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@ff060000 {
+		compatible = "rockchip,rk3308-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff060000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@ff070000 {
+		compatible = "rockchip,rk3308-i2c", "rockchip,rk3399-i2c";
+		reg = <0x0 0xff070000 0x0 0x1000>;
+		clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3m0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	wdt: watchdog@ff080000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x0 0xff080000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	uart0: serial@ff0a0000 {
+		compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff0a0000 0x0 0x100>;
+		interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+		status = "disabled";
+	};
+
+	uart1: serial@ff0b0000 {
+		compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff0b0000 0x0 0x100>;
+		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer &uart1_cts &uart1_rts>;
+		status = "disabled";
+	};
+
+	uart2: serial@ff0c0000 {
+		compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff0c0000 0x0 0x100>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2m0_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff0d0000 {
+		compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff0d0000 0x0 0x100>;
+		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3_xfer>;
+		status = "disabled";
+	};
+
+	uart4: serial@ff0e0000 {
+		compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff0e0000 0x0 0x100>;
+		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_xfer &uart4_cts &uart4_rts>;
+		status = "disabled";
+	};
+
+	spi0: spi@ff120000 {
+		compatible = "rockchip,rk3308-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff120000 0x0 0x1000>;
+		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		dmas = <&dmac0 0>, <&dmac0 1>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default", "high_speed";
+		pinctrl-0 = <&spi0_clk &spi0_csn0 &spi0_miso &spi0_mosi>;
+		pinctrl-1 = <&spi0_clk_hs &spi0_csn0 &spi0_miso_hs &spi0_mosi_hs>;
+		status = "disabled";
+	};
+
+	spi1: spi@ff130000 {
+		compatible = "rockchip,rk3308-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff130000 0x0 0x1000>;
+		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		dmas = <&dmac0 2>, <&dmac0 3>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default", "high_speed";
+		pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_miso &spi1_mosi>;
+		pinctrl-1 = <&spi1_clk_hs &spi1_csn0 &spi1_miso_hs &spi1_mosi_hs>;
+		status = "disabled";
+	};
+
+	spi2: spi@ff140000 {
+		compatible = "rockchip,rk3308-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+		clock-names = "spiclk", "apb_pclk";
+		dmas = <&dmac1 16>, <&dmac1 17>;
+		dma-names = "tx", "rx";
+		pinctrl-names = "default", "high_speed";
+		pinctrl-0 = <&spi2_clk &spi2_csn0 &spi2_miso &spi2_mosi>;
+		pinctrl-1 = <&spi2_clk_hs &spi2_csn0 &spi2_miso_hs &spi2_mosi_hs>;
+		status = "disabled";
+	};
+
+	pwm8: pwm@ff160000 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff160000 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm8_pin>;
+		clocks = <&cru SCLK_PWM2>, <&cru PCLK_PWM2>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm9: pwm@ff160010 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff160010 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm9_pin>;
+		clocks = <&cru SCLK_PWM2>, <&cru PCLK_PWM2>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm10: pwm@ff160020 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff160020 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm10_pin>;
+		clocks = <&cru SCLK_PWM2>, <&cru PCLK_PWM2>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm11: pwm@ff160030 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff160030 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm11_pin>;
+		clocks = <&cru SCLK_PWM2>, <&cru PCLK_PWM2>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm4: pwm@ff170000 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff170000 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm4_pin>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm5: pwm@ff170010 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff170010 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm5_pin>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm6: pwm@ff170020 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff170020 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm6_pin>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm7: pwm@ff170030 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff170030 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm7_pin>;
+		clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm0: pwm@ff180000 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff180000 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm1: pwm@ff180010 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff180010 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm2: pwm@ff180020 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff180020 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	pwm3: pwm@ff180030 {
+		compatible = "rockchip,rk3308-pwm", "rockchip,rk3328-pwm";
+		reg = <0x0 0xff180030 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_pin>;
+		clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>;
+		clock-names = "pwm", "pclk";
+		status = "disabled";
+	};
+
+	rktimer: rktimer@ff1a0000 {
+		compatible = "rockchip,rk3288-timer";
+		reg = <0x0 0xff1a0000 0x0 0x20>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER0>;
+		clock-names = "pclk", "timer";
+	};
+
+	saradc: saradc@ff1e0000 {
+		compatible = "rockchip,rk3308-saradc", "rockchip,rk3399-saradc";
+		reg = <0x0 0xff1e0000 0x0 0x100>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_SARADC_P>;
+		reset-names = "saradc-apb";
+		status = "disabled";
+	};
+
+	amba {
+		compatible = "arm,amba-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dmac0: dma-controller@ff2c0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff2c0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC0>;
+			clock-names = "apb_pclk";
+			peripherals-req-type-burst;
+		};
+
+		dmac1: dma-controller@ff2d0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff2d0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC1>;
+			clock-names = "apb_pclk";
+			peripherals-req-type-burst;
+		};
+	};
+
+	i2s_2ch_0: i2s@ff350000 {
+		compatible = "rockchip,rk3308-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff350000 0x0 0x1000>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_I2S0_2CH>, <&cru HCLK_I2S0_2CH>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		dmas = <&dmac1 8>, <&dmac1 9>;
+		dma-names = "tx", "rx";
+		resets = <&cru SRST_I2S0_2CH_M>, <&cru SRST_I2S0_2CH_H>;
+		reset-names = "reset-m", "reset-h";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s_2ch_0_sclk
+			     &i2s_2ch_0_lrck
+			     &i2s_2ch_0_sdi
+			     &i2s_2ch_0_sdo>;
+		status = "disabled";
+	};
+
+	i2s_2ch_1: i2s@ff360000 {
+		compatible = "rockchip,rk3308-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff360000 0x0 0x1000>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_I2S1_2CH>, <&cru HCLK_I2S1_2CH>;
+		clock-names = "i2s_clk", "i2s_hclk";
+		dmas = <&dmac1 11>;
+		dma-names = "rx";
+		resets = <&cru SRST_I2S1_2CH_M>, <&cru SRST_I2S1_2CH_H>;
+		reset-names = "reset-m", "reset-h";
+		status = "disabled";
+	};
+
+	spdif_tx: spdif-tx@ff3a0000 {
+		compatible = "rockchip,rk3308-spdif", "rockchip,rk3328-spdif";
+		reg = <0x0 0xff3a0000 0x0 0x1000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SPDIF_TX>, <&cru HCLK_SPDIFTX>;
+		clock-names = "mclk", "hclk";
+		dmas = <&dmac1 13>;
+		dma-names = "tx";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_out>;
+		status = "disabled";
+	};
+
+	sdmmc: dwmmc@ff480000 {
+		compatible = "rockchip,rk3308-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff480000 0x0 0x4000>;
+		max-frequency = <150000000>;
+		bus-width = <4>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
+		status = "disabled";
+	};
+
+	emmc: dwmmc@ff490000 {
+		compatible = "rockchip,rk3308-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff490000 0x0 0x4000>;
+		max-frequency = <150000000>;
+		bus-width = <8>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
+			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	sdio: dwmmc@ff4a0000 {
+		compatible = "rockchip,rk3308-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff4a0000 0x0 0x4000>;
+		max-frequency = <150000000>;
+		bus-width = <4>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdio_bus4 &sdio_cmd &sdio_clk>;
+		status = "disabled";
+	};
+
+	cru: clock-controller@ff500000 {
+		compatible = "rockchip,rk3308-cru";
+		reg = <0x0 0xff500000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	gic: interrupt-controller@ff580000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+
+		reg = <0x0 0xff581000 0x0 0x1000>,
+		      <0x0 0xff582000 0x0 0x2000>,
+		      <0x0 0xff584000 0x0 0x2000>,
+		      <0x0 0xff586000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	sram: sram@fff80000 {
+		compatible = "mmio-sram";
+		reg = <0x0 0xfff80000 0x0 0x40000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x0 0xfff80000 0x40000>;
+		/* reserved for ddr dvfs and system suspend/resume */
+		ddr-sram@0 {
+			reg = <0x0 0x8000>;
+		};
+		/* reserved for vad audio buffer */
+		vad_sram: vad-sram@8000 {
+			reg = <0x8000 0x38000>;
+		};
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3308-pinctrl";
+		rockchip,grf = <&grf>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		gpio0: gpio0@ff220000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff220000 0x0 0x100>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@ff230000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff230000 0x0 0x100>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2@ff240000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff240000 0x0 0x100>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio3@ff250000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff250000 0x0 0x100>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio4: gpio4@ff260000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff260000 0x0 0x100>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_2ma: pcfg-pull-none-2ma {
+			bias-disable;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+			bias-pull-up;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_up_4ma: pcfg-pull-up-4ma {
+			bias-pull-up;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_none_4ma: pcfg-pull-none-4ma {
+			bias-disable;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_down_4ma: pcfg-pull-down-4ma {
+			bias-pull-down;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_none_8ma: pcfg-pull-none-8ma {
+			bias-disable;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_up_8ma: pcfg-pull-up-8ma {
+			bias-pull-up;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_up_12ma: pcfg-pull-up-12ma {
+			bias-pull-up;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_none_smt: pcfg-pull-none-smt {
+			bias-disable;
+			input-schmitt-enable;
+		};
+
+		pcfg_output_high: pcfg-output-high {
+			output-high;
+		};
+
+		pcfg_output_low: pcfg-output-low {
+			output-low;
+		};
+
+		pcfg_input_high: pcfg-input-high {
+			bias-pull-up;
+			input-enable;
+		};
+
+		pcfg_input: pcfg-input {
+			input-enable;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins =
+					<1 RK_PD0 2 &pcfg_pull_none_smt>,
+					<1 RK_PD1 2 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins =
+					<0 RK_PB3 1 &pcfg_pull_none_smt>,
+					<0 RK_PB4 1 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins =
+					<2 RK_PA2 3 &pcfg_pull_none_smt>,
+					<2 RK_PA3 3 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c3-m0 {
+			i2c3m0_xfer: i2c3m0-xfer {
+				rockchip,pins =
+					<0 RK_PB7 2 &pcfg_pull_none_smt>,
+					<0 RK_PC0 2 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c3-m1 {
+			i2c3m1_xfer: i2c3m1-xfer {
+				rockchip,pins =
+					<3 RK_PB4 2 &pcfg_pull_none_smt>,
+					<3 RK_PB5 2 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2c3-m2 {
+			i2c3m2_xfer: i2c3m2-xfer {
+				rockchip,pins =
+					<2 RK_PA1 3 &pcfg_pull_none_smt>,
+					<2 RK_PA0 3 &pcfg_pull_none_smt>;
+			};
+		};
+
+		i2s_2ch_0 {
+			i2s_2ch_0_mclk: i2s-2ch-0-mclk {
+				rockchip,pins =
+					<4 RK_PB4 1 &pcfg_pull_none>;
+			};
+
+			i2s_2ch_0_sclk: i2s-2ch-0-sclk {
+				rockchip,pins =
+					<4 RK_PB5 1 &pcfg_pull_none>;
+			};
+
+			i2s_2ch_0_lrck: i2s-2ch-0-lrck {
+				rockchip,pins =
+					<4 RK_PB6 1 &pcfg_pull_none>;
+			};
+
+			i2s_2ch_0_sdo: i2s-2ch-0-sdo {
+				rockchip,pins =
+					<4 RK_PB7 1 &pcfg_pull_none>;
+			};
+
+			i2s_2ch_0_sdi: i2s-2ch-0-sdi {
+				rockchip,pins =
+					<4 RK_PC0 1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s_8ch_0 {
+			i2s_8ch_0_mclk: i2s-8ch-0-mclk {
+				rockchip,pins =
+					<2 RK_PA4 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sclktx: i2s-8ch-0-sclktx {
+				rockchip,pins =
+					<2 RK_PA5 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sclkrx: i2s-8ch-0-sclkrx {
+				rockchip,pins =
+					<2 RK_PA6 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_lrcktx: i2s-8ch-0-lrcktx {
+				rockchip,pins =
+					<2 RK_PA7 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_lrckrx: i2s-8ch-0-lrckrx {
+				rockchip,pins =
+					<2 RK_PB0 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdo0: i2s-8ch-0-sdo0 {
+				rockchip,pins =
+					<2 RK_PB1 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdo1: i2s-8ch-0-sdo1 {
+				rockchip,pins =
+					<2 RK_PB2 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdo2: i2s-8ch-0-sdo2 {
+				rockchip,pins =
+					<2 RK_PB3 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdo3: i2s-8ch-0-sdo3 {
+				rockchip,pins =
+					<2 RK_PB4 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdi0: i2s-8ch-0-sdi0 {
+				rockchip,pins =
+					<2 RK_PB5 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdi1: i2s-8ch-0-sdi1 {
+				rockchip,pins =
+					<2 RK_PB6 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdi2: i2s-8ch-0-sdi2 {
+				rockchip,pins =
+					<2 RK_PB7 1 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_0_sdi3: i2s-8ch-0-sdi3 {
+				rockchip,pins =
+					<2 RK_PC0 1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s_8ch_1_m0 {
+			i2s_8ch_1_m0_mclk: i2s-8ch-1-m0-mclk {
+				rockchip,pins =
+					<1 RK_PA2 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sclktx: i2s-8ch-1-m0-sclktx {
+				rockchip,pins =
+					<1 RK_PA3 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sclkrx: i2s-8ch-1-m0-sclkrx {
+				rockchip,pins =
+					<1 RK_PA4 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_lrcktx: i2s-8ch-1-m0-lrcktx {
+				rockchip,pins =
+					<1 RK_PA5 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_lrckrx: i2s-8ch-1-m0-lrckrx {
+				rockchip,pins =
+					<1 RK_PA6 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sdo0: i2s-8ch-1-m0-sdo0 {
+				rockchip,pins =
+					<1 RK_PA7 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sdo1_sdi3: i2s-8ch-1-m0-sdo1-sdi3 {
+				rockchip,pins =
+					<1 RK_PB0 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sdo2_sdi2: i2s-8ch-1-m0-sdo2-sdi2 {
+				rockchip,pins =
+					<1 RK_PB1 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sdo3_sdi1: i2s-8ch-1-m0-sdo3_sdi1 {
+				rockchip,pins =
+					<1 RK_PB2 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m0_sdi0: i2s-8ch-1-m0-sdi0 {
+				rockchip,pins =
+					<1 RK_PB3 2 &pcfg_pull_none>;
+			};
+		};
+
+		i2s_8ch_1_m1 {
+			i2s_8ch_1_m1_mclk: i2s-8ch-1-m1-mclk {
+				rockchip,pins =
+					<1 RK_PB4 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sclktx: i2s-8ch-1-m1-sclktx {
+				rockchip,pins =
+					<1 RK_PB5 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sclkrx: i2s-8ch-1-m1-sclkrx {
+				rockchip,pins =
+					<1 RK_PB6 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_lrcktx: i2s-8ch-1-m1-lrcktx {
+				rockchip,pins =
+					<1 RK_PB7 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_lrckrx: i2s-8ch-1-m1-lrckrx {
+				rockchip,pins =
+					<1 RK_PC0 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sdo0: i2s-8ch-1-m1-sdo0 {
+				rockchip,pins =
+					<1 RK_PC1 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sdo1_sdi3: i2s-8ch-1-m1-sdo1-sdi3 {
+				rockchip,pins =
+					<1 RK_PC2 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sdo2_sdi2: i2s-8ch-1-m1-sdo2-sdi2 {
+				rockchip,pins =
+					<1 RK_PC3 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sdo3_sdi1: i2s-8ch-1-m1-sdo3_sdi1 {
+				rockchip,pins =
+					<1 RK_PC4 2 &pcfg_pull_none>;
+			};
+
+			i2s_8ch_1_m1_sdi0: i2s-8ch-1-m1-sdi0 {
+				rockchip,pins =
+					<1 RK_PC5 2 &pcfg_pull_none>;
+			};
+		};
+
+		pdm_m0 {
+			pdm_m0_clk: pdm-m0-clk {
+				rockchip,pins =
+					<1 RK_PA4 3 &pcfg_pull_none>;
+			};
+
+			pdm_m0_sdi0: pdm-m0-sdi0 {
+				rockchip,pins =
+					<1 RK_PB3 3 &pcfg_pull_none>;
+			};
+
+			pdm_m0_sdi1: pdm-m0-sdi1 {
+				rockchip,pins =
+					<1 RK_PB2 3 &pcfg_pull_none>;
+			};
+
+			pdm_m0_sdi2: pdm-m0-sdi2 {
+				rockchip,pins =
+					<1 RK_PB1 3 &pcfg_pull_none>;
+			};
+
+			pdm_m0_sdi3: pdm-m0-sdi3 {
+				rockchip,pins =
+					<1 RK_PB0 3 &pcfg_pull_none>;
+			};
+		};
+
+		pdm_m1 {
+			pdm_m1_clk: pdm-m1-clk {
+				rockchip,pins =
+					<1 RK_PB6 4 &pcfg_pull_none>;
+			};
+
+			pdm_m1_sdi0: pdm-m1-sdi0 {
+				rockchip,pins =
+					<1 RK_PC5 4 &pcfg_pull_none>;
+			};
+
+			pdm_m1_sdi1: pdm-m1-sdi1 {
+				rockchip,pins =
+					<1 RK_PC4 4 &pcfg_pull_none>;
+			};
+
+			pdm_m1_sdi2: pdm-m1-sdi2 {
+				rockchip,pins =
+					<1 RK_PC3 4 &pcfg_pull_none>;
+			};
+
+			pdm_m1_sdi3: pdm-m1-sdi3 {
+				rockchip,pins =
+					<1 RK_PC2 4 &pcfg_pull_none>;
+			};
+		};
+
+		pdm_m2 {
+			pdm_m2_clkm: pdm-m2-clkm {
+				rockchip,pins =
+					<2 RK_PA4 3 &pcfg_pull_none>;
+			};
+
+			pdm_m2_clk: pdm-m2-clk {
+				rockchip,pins =
+					<2 RK_PA6 2 &pcfg_pull_none>;
+			};
+
+			pdm_m2_sdi0: pdm-m2-sdi0 {
+				rockchip,pins =
+					<2 RK_PB5 2 &pcfg_pull_none>;
+			};
+
+			pdm_m2_sdi1: pdm-m2-sdi1 {
+				rockchip,pins =
+					<2 RK_PB6 2 &pcfg_pull_none>;
+			};
+
+			pdm_m2_sdi2: pdm-m2-sdi2 {
+				rockchip,pins =
+					<2 RK_PB7 2 &pcfg_pull_none>;
+			};
+
+			pdm_m2_sdi3: pdm-m2-sdi3 {
+				rockchip,pins =
+					<2 RK_PC0 2 &pcfg_pull_none>;
+			};
+		};
+
+		spdif_in {
+			spdif_in: spdif-in {
+				rockchip,pins =
+					<0 RK_PC2 1 &pcfg_pull_none>;
+			};
+		};
+
+		spdif_out {
+			spdif_out: spdif-out {
+				rockchip,pins =
+					<0 RK_PC1 1 &pcfg_pull_none>;
+			};
+		};
+
+		tsadc {
+			tsadc_otp_gpio: tsadc-otp-gpio {
+				rockchip,pins =
+					<0 RK_PB2 0 &pcfg_pull_none>;
+			};
+
+			tsadc_otp_out: tsadc-otp-out {
+				rockchip,pins =
+					<0 RK_PB2 1 &pcfg_pull_none>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins =
+					<2 RK_PA1 1 &pcfg_pull_up>,
+					<2 RK_PA0 1 &pcfg_pull_up>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins =
+					<2 RK_PA2 1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins =
+					<2 RK_PA3 1 &pcfg_pull_none>;
+			};
+
+			uart0_rts_gpio: uart0-rts-gpio {
+				rockchip,pins =
+					<2 RK_PA3 0 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins =
+					<1 RK_PD1 1 &pcfg_pull_up>,
+					<1 RK_PD0 1 &pcfg_pull_up>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins =
+					<1 RK_PC6 1 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins =
+					<1 RK_PC7 1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2-m0 {
+			uart2m0_xfer: uart2m0-xfer {
+				rockchip,pins =
+					<1 RK_PC7 2 &pcfg_pull_up>,
+					<1 RK_PC6 2 &pcfg_pull_up>;
+			};
+		};
+
+		uart2-m1 {
+			uart2m1_xfer: uart2m1-xfer {
+				rockchip,pins =
+					<4 RK_PD3 2 &pcfg_pull_up>,
+					<4 RK_PD2 2 &pcfg_pull_up>;
+			};
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins =
+					<3 RK_PB5 4 &pcfg_pull_up>,
+					<3 RK_PB4 4 &pcfg_pull_up>;
+			};
+		};
+
+		uart3-m1 {
+			uart3m1_xfer: uart3m1-xfer {
+				rockchip,pins =
+					<0 RK_PC2 3 &pcfg_pull_up>,
+					<0 RK_PC1 3 &pcfg_pull_up>;
+			};
+		};
+
+		uart4 {
+
+			uart4_xfer: uart4-xfer {
+				rockchip,pins =
+					<4 RK_PB1 1 &pcfg_pull_up>,
+					<4 RK_PB0 1 &pcfg_pull_up>;
+			};
+
+			uart4_cts: uart4-cts {
+				rockchip,pins =
+					<4 RK_PA6 1 &pcfg_pull_none>;
+
+			};
+
+			uart4_rts: uart4-rts {
+				rockchip,pins =
+					<4 RK_PA7 1 &pcfg_pull_none>;
+			};
+
+			uart4_rts_gpio: uart4-rts-gpio {
+				rockchip,pins =
+					<4 RK_PA7 0 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins =
+					<2 RK_PA2 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_csn0: spi0-csn0 {
+				rockchip,pins =
+					<2 RK_PA3 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_miso: spi0-miso {
+				rockchip,pins =
+					<2 RK_PA0 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_mosi: spi0-mosi {
+				rockchip,pins =
+					<2 RK_PA1 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi0_clk_hs: spi0-clk-hs {
+				rockchip,pins =
+					<2 RK_PA2 2 &pcfg_pull_up_8ma>;
+			};
+
+			spi0_miso_hs: spi0-miso-hs {
+				rockchip,pins =
+					<2 RK_PA0 2 &pcfg_pull_up_8ma>;
+			};
+
+			spi0_mosi_hs: spi0-mosi-hs {
+				rockchip,pins =
+					<2 RK_PA1 2 &pcfg_pull_up_8ma>;
+			};
+
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins =
+					<3 RK_PB3 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_csn0: spi1-csn0 {
+				rockchip,pins =
+					<3 RK_PB5 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_miso: spi1-miso {
+				rockchip,pins =
+					<3 RK_PB2 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_mosi: spi1-mosi {
+				rockchip,pins =
+					<3 RK_PB4 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi1_clk_hs: spi1-clk-hs {
+				rockchip,pins =
+					<3 RK_PB3 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi1_miso_hs: spi1-miso-hs {
+				rockchip,pins =
+					<3 RK_PB2 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi1_mosi_hs: spi1-mosi-hs {
+				rockchip,pins =
+					<3 RK_PB4 3 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		spi1-m1 {
+			spi1m1_miso: spi1m1-miso {
+				rockchip,pins =
+					<2 RK_PA4 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi1m1_mosi: spi1m1-mosi {
+				rockchip,pins =
+					<2 RK_PA5 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi1m1_clk: spi1m1-clk {
+				rockchip,pins =
+					<2 RK_PA7 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi1m1_csn0: spi1m1-csn0 {
+				rockchip,pins =
+					<2 RK_PB1 2 &pcfg_pull_up_4ma>;
+			};
+
+			spi1m1_miso_hs: spi1m1-miso-hs {
+				rockchip,pins =
+					<2 RK_PA4 2 &pcfg_pull_up_8ma>;
+			};
+
+			spi1m1_mosi_hs: spi1m1-mosi-hs {
+				rockchip,pins =
+					<2 RK_PA5 2 &pcfg_pull_up_8ma>;
+			};
+
+			spi1m1_clk_hs: spi1m1-clk-hs {
+				rockchip,pins =
+					<2 RK_PA7 2 &pcfg_pull_up_8ma>;
+			};
+
+			spi1m1_csn0_hs: spi1m1-csn0-hs {
+				rockchip,pins =
+					<2 RK_PB1 2 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		spi2 {
+			spi2_clk: spi2-clk {
+				rockchip,pins =
+					<1 RK_PD0 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi2_csn0: spi2-csn0 {
+				rockchip,pins =
+					<1 RK_PD1 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi2_miso: spi2-miso {
+				rockchip,pins =
+					<1 RK_PC6 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi2_mosi: spi2-mosi {
+				rockchip,pins =
+					<1 RK_PC7 3 &pcfg_pull_up_4ma>;
+			};
+
+			spi2_clk_hs: spi2-clk-hs {
+				rockchip,pins =
+					<1 RK_PD0 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi2_miso_hs: spi2-miso-hs {
+				rockchip,pins =
+					<1 RK_PC6 3 &pcfg_pull_up_8ma>;
+			};
+
+			spi2_mosi_hs: spi2-mosi-hs {
+				rockchip,pins =
+					<1 RK_PC7 3 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins =
+					<4 RK_PD5 1 &pcfg_pull_none_4ma>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins =
+					<4 RK_PD4 1 &pcfg_pull_up_4ma>;
+			};
+
+			sdmmc_det: sdmmc-det {
+				rockchip,pins =
+					<0 RK_PA3 1 &pcfg_pull_up_4ma>;
+			};
+
+			sdmmc_pwren: sdmmc-pwren {
+				rockchip,pins =
+					<4 RK_PD6 1 &pcfg_pull_none_4ma>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins =
+					<4 RK_PD0 1 &pcfg_pull_up_4ma>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins =
+					<4 RK_PD0 1 &pcfg_pull_up_4ma>,
+					<4 RK_PD1 1 &pcfg_pull_up_4ma>,
+					<4 RK_PD2 1 &pcfg_pull_up_4ma>,
+					<4 RK_PD3 1 &pcfg_pull_up_4ma>;
+			};
+
+			sdmmc_gpio: sdmmc-gpio {
+				rockchip,pins =
+					<4 RK_PD0 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD1 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD2 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD3 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD4 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD5 0 &pcfg_pull_up_4ma>,
+					<4 RK_PD6 0 &pcfg_pull_up_4ma>;
+			};
+		};
+
+		sdio {
+			sdio_clk: sdio-clk {
+				rockchip,pins =
+					<4 RK_PA5 1 &pcfg_pull_none_8ma>;
+			};
+
+			sdio_cmd: sdio-cmd {
+				rockchip,pins =
+					<4 RK_PA4 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdio_pwren: sdio-pwren {
+				rockchip,pins =
+					<0 RK_PA2 1 &pcfg_pull_none_8ma>;
+			};
+
+			sdio_wrpt: sdio-wrpt {
+				rockchip,pins =
+					<0 RK_PA1 1 &pcfg_pull_none_8ma>;
+			};
+
+			sdio_intn: sdio-intn {
+				rockchip,pins =
+					<0 RK_PA0 1 &pcfg_pull_none_8ma>;
+			};
+
+			sdio_bus1: sdio-bus1 {
+				rockchip,pins =
+					<4 RK_PA0 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdio_bus4: sdio-bus4 {
+				rockchip,pins =
+					<4 RK_PA0 1 &pcfg_pull_up_8ma>,
+					<4 RK_PA1 1 &pcfg_pull_up_8ma>,
+					<4 RK_PA2 1 &pcfg_pull_up_8ma>,
+					<4 RK_PA3 1 &pcfg_pull_up_8ma>;
+			};
+
+			sdio_gpio: sdio-gpio {
+				rockchip,pins =
+					<4 RK_PA0 0 &pcfg_pull_up_4ma>,
+					<4 RK_PA1 0 &pcfg_pull_up_4ma>,
+					<4 RK_PA2 0 &pcfg_pull_up_4ma>,
+					<4 RK_PA3 0 &pcfg_pull_up_4ma>,
+					<4 RK_PA4 0 &pcfg_pull_up_4ma>,
+					<4 RK_PA5 0 &pcfg_pull_up_4ma>;
+			};
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins =
+					<3 RK_PB1 2 &pcfg_pull_none_8ma>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins =
+					<3 RK_PB0 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_pwren: emmc-pwren {
+				rockchip,pins =
+					<3 RK_PB3 2 &pcfg_pull_none>;
+			};
+
+			emmc_rstn: emmc-rstn {
+				rockchip,pins =
+					<3 RK_PB2 2 &pcfg_pull_none>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins =
+					<3 RK_PA0 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_bus4: emmc-bus4 {
+				rockchip,pins =
+					<3 RK_PA0 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA1 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA2 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA3 2 &pcfg_pull_up_8ma>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins =
+					<3 RK_PA0 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA1 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA2 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA3 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA4 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA5 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA6 2 &pcfg_pull_up_8ma>,
+					<3 RK_PA7 2 &pcfg_pull_up_8ma>;
+			};
+		};
+
+		flash {
+			flash_csn0: flash-csn0 {
+				rockchip,pins =
+					<3 RK_PB5 1 &pcfg_pull_none>;
+			};
+
+			flash_rdy: flash-rdy {
+				rockchip,pins =
+					<3 RK_PB4 1 &pcfg_pull_none>;
+			};
+
+			flash_ale: flash-ale {
+				rockchip,pins =
+					<3 RK_PB3 1 &pcfg_pull_none>;
+			};
+
+			flash_cle: flash-cle {
+				rockchip,pins =
+					<3 RK_PB1 1 &pcfg_pull_none>;
+			};
+
+			flash_wrn: flash-wrn {
+				rockchip,pins =
+					<3 RK_PB0 1 &pcfg_pull_none>;
+			};
+
+			flash_rdn: flash-rdn {
+				rockchip,pins =
+					<3 RK_PB2 1 &pcfg_pull_none>;
+			};
+
+			flash_bus8: flash-bus8 {
+				rockchip,pins =
+					<3 RK_PA0 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA1 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA2 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA3 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA4 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA5 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA6 1 &pcfg_pull_up_12ma>,
+					<3 RK_PA7 1 &pcfg_pull_up_12ma>;
+			};
+		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins =
+					<0 RK_PB5 1 &pcfg_pull_none>;
+			};
+
+			pwm0_pin_pull_down: pwm0-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PB5 1 &pcfg_pull_down>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins =
+					<0 RK_PB6 1 &pcfg_pull_none>;
+			};
+
+			pwm1_pin_pull_down: pwm1-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PB6 1 &pcfg_pull_down>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins =
+					<0 RK_PB7 1 &pcfg_pull_none>;
+			};
+
+			pwm2_pin_pull_down: pwm2-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PB7 1 &pcfg_pull_down>;
+			};
+		};
+
+		pwm3 {
+			pwm3_pin: pwm3-pin {
+				rockchip,pins =
+					<0 RK_PC0 1 &pcfg_pull_none>;
+			};
+
+			pwm3_pin_pull_down: pwm3-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PC0 1 &pcfg_pull_down>;
+			};
+		};
+
+		pwm4 {
+			pwm4_pin: pwm4-pin {
+				rockchip,pins =
+					<0 RK_PA1 2 &pcfg_pull_none>;
+			};
+
+			pwm4_pin_pull_down: pwm4-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PA1 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm5 {
+			pwm5_pin: pwm5-pin {
+				rockchip,pins =
+					<0 RK_PC1 2 &pcfg_pull_none>;
+			};
+
+			pwm5_pin_pull_down: pwm5-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PC1 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm6 {
+			pwm6_pin: pwm6-pin {
+				rockchip,pins =
+					<0 RK_PC2 2 &pcfg_pull_none>;
+			};
+
+			pwm6_pin_pull_down: pwm6-pin-pull-down {
+				rockchip,pins =
+					<0 RK_PC2 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm7 {
+			pwm7_pin: pwm7-pin {
+				rockchip,pins =
+					<2 RK_PB0 2 &pcfg_pull_none>;
+			};
+
+			pwm7_pin_pull_down: pwm7-pin-pull-down {
+				rockchip,pins =
+					<2 RK_PB0 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm8 {
+			pwm8_pin: pwm8-pin {
+				rockchip,pins =
+					<2 RK_PB2 2 &pcfg_pull_none>;
+			};
+
+			pwm8_pin_pull_down: pwm8-pin-pull-down {
+				rockchip,pins =
+					<2 RK_PB2 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm9 {
+			pwm9_pin: pwm9-pin {
+				rockchip,pins =
+					<2 RK_PB3 2 &pcfg_pull_none>;
+			};
+
+			pwm9_pin_pull_down: pwm9-pin-pull-down {
+				rockchip,pins =
+					<2 RK_PB3 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm10 {
+			pwm10_pin: pwm10-pin {
+				rockchip,pins =
+					<2 RK_PB4 2 &pcfg_pull_none>;
+			};
+
+			pwm10_pin_pull_down: pwm10-pin-pull-down {
+				rockchip,pins =
+					<2 RK_PB4 2 &pcfg_pull_down>;
+			};
+		};
+
+		pwm11 {
+			pwm11_pin: pwm11-pin {
+				rockchip,pins =
+					<2 RK_PC0 4 &pcfg_pull_none>;
+			};
+
+			pwm11_pin_pull_down: pwm11-pin-pull-down {
+				rockchip,pins =
+					<2 RK_PC0 4 &pcfg_pull_down>;
+			};
+		};
+
+		gmac {
+			rmii_pins: rmii-pins {
+				rockchip,pins =
+					/* mac_txen */
+					<1 RK_PC1 3 &pcfg_pull_none_12ma>,
+					/* mac_txd1 */
+					<1 RK_PC3 3 &pcfg_pull_none_12ma>,
+					/* mac_txd0 */
+					<1 RK_PC2 3 &pcfg_pull_none_12ma>,
+					/* mac_rxd0 */
+					<1 RK_PC4 3 &pcfg_pull_none>,
+					/* mac_rxd1 */
+					<1 RK_PC5 3 &pcfg_pull_none>,
+					/* mac_rxer */
+					<1 RK_PB7 3 &pcfg_pull_none>,
+					/* mac_rxdv */
+					<1 RK_PC0 3 &pcfg_pull_none>,
+					/* mac_mdio */
+					<1 RK_PB6 3 &pcfg_pull_none>,
+					/* mac_mdc */
+					<1 RK_PB5 3 &pcfg_pull_none>;
+			};
+
+			mac_refclk_12ma: mac-refclk-12ma {
+				rockchip,pins =
+					<1 RK_PB4 3 &pcfg_pull_none_12ma>;
+			};
+
+			mac_refclk: mac-refclk {
+				rockchip,pins =
+					<1 RK_PB4 3 &pcfg_pull_none>;
+			};
+		};
+
+		gmac-m1 {
+			rmiim1_pins: rmiim1-pins {
+				rockchip,pins =
+					/* mac_txen */
+					<4 RK_PB7 2 &pcfg_pull_none_12ma>,
+					/* mac_txd1 */
+					<4 RK_PA5 2 &pcfg_pull_none_12ma>,
+					/* mac_txd0 */
+					<4 RK_PA4 2 &pcfg_pull_none_12ma>,
+					/* mac_rxd0 */
+					<4 RK_PA2 2 &pcfg_pull_none>,
+					/* mac_rxd1 */
+					<4 RK_PA3 2 &pcfg_pull_none>,
+					/* mac_rxer */
+					<4 RK_PA0 2 &pcfg_pull_none>,
+					/* mac_rxdv */
+					<4 RK_PA1 2 &pcfg_pull_none>,
+					/* mac_mdio */
+					<4 RK_PB6 2 &pcfg_pull_none>,
+					/* mac_mdc */
+					<4 RK_PB5 2 &pcfg_pull_none>;
+			};
+
+			macm1_refclk_12ma: macm1-refclk-12ma {
+				rockchip,pins =
+					<4 RK_PB4 2 &pcfg_pull_none_12ma>;
+			};
+
+			macm1_refclk: macm1-refclk {
+				rockchip,pins =
+					<4 RK_PB4 2 &pcfg_pull_none>;
+			};
+		};
+
+		rtc {
+			rtc_32k: rtc-32k {
+				rockchip,pins =
+					<0 RK_PC3 1 &pcfg_pull_none>;
+			};
+		};
+
+	};
+};
diff --git a/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi b/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi
index d99e7e0352716acfa93d936256b81ae80e516b2a..3e88ed443ba04cebd19e6546c926829cb33beddc 100644
--- a/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi
+++ b/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi
@@ -14,6 +14,8 @@
 		0x0
 		0x10
 		0x10
+		0x10
+		0x10
 		0
 
 		0x9028b189
@@ -26,6 +28,8 @@
 
 		333
 		3
+		1
+		0
 		0
 
 		0x00000000
diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi
index cc0011cf7b1dc2a5d6a9e8adcc3e7a603824bb91..d63c761a0283e25301d40ec0f7a6d0c5be2da48c 100644
--- a/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi
+++ b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi
@@ -14,6 +14,8 @@
 		0x0
 		0x10
 		0x10
+		0x10
+		0x10
 		0
 
 		0x98899459
@@ -27,6 +29,8 @@
 		800
 		6
 		1
+		0
+		1
 
 		0x00000000
 		0x43041008
diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi
index 62d809e833a9ecc01f7490bcaba600afcfed833c..b9d3b3b948578f986f4a9e93d1861f2a89104ecb 100644
--- a/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi
+++ b/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi
@@ -14,6 +14,8 @@
 		0x0
 		0x10
 		0x10
+		0x10
+		0x10
 		0
 
 		0x0c48a18a
@@ -26,6 +28,8 @@
 
 		333
 		6
+		1
+		0
 		0
 
 		0x00000000
diff --git a/arch/arm/dts/rk3399-evb-u-boot.dtsi b/arch/arm/dts/rk3399-evb-u-boot.dtsi
index 20910e744bb9a32b95c9f7303a1003246c2f1e48..ccb33d34d12d0ed20856b0c042a37d80a8962e0e 100644
--- a/arch/arm/dts/rk3399-evb-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-evb-u-boot.dtsi
@@ -5,3 +5,9 @@
 
 #include "rk3399-u-boot.dtsi"
 #include "rk3399-sdram-lpddr3-4GB-1600.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
index a506e8da370232aab5486d2acd0ec9ee3e8f7450..8e887f3a177faaa770363e9433825cecba82c789 100644
--- a/arch/arm/dts/rk3399-evb.dts
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -15,8 +15,6 @@
 
 	chosen {
 		stdout-path = &uart2;
-		u-boot,spl-boot-order = \
-			&sdhci, &sdmmc;
 	};
 
 	vdd_center: vdd-center {
diff --git a/arch/arm/dts/rk3399-firefly-u-boot.dtsi b/arch/arm/dts/rk3399-firefly-u-boot.dtsi
index 67b63a835238b075610a1f2023bf5ec445b81bc6..38e0897db91dd3d1306c3ce0c30b40939ab6e220 100644
--- a/arch/arm/dts/rk3399-firefly-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-firefly-u-boot.dtsi
@@ -5,3 +5,9 @@
 
 #include "rk3399-u-boot.dtsi"
 #include "rk3399-sdram-ddr3-1600.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/rk3399-firefly.dts b/arch/arm/dts/rk3399-firefly.dts
index a4cb64f8bde18ae8d69cdfab614b6f0d4ff28ef8..89c67fd24cc93894ef354f3480bce3398818c786 100644
--- a/arch/arm/dts/rk3399-firefly.dts
+++ b/arch/arm/dts/rk3399-firefly.dts
@@ -14,7 +14,6 @@
 
 	chosen {
 		stdout-path = &uart2;
-		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
 	};
 
 	backlight: backlight {
diff --git a/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi b/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
index 35b9fdda778a9181862f68ce80a2baa2376405bf..a7039d74a0167b44be29473e3e670a9a5514fc14 100644
--- a/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
@@ -11,3 +11,7 @@
 		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
 	};
 };
+
+&vdd_log {
+	regulator-init-microvolt = <950000>;
+};
diff --git a/arch/arm/dts/rk3399-orangepi-u-boot.dtsi b/arch/arm/dts/rk3399-orangepi-u-boot.dtsi
index 236b61d78dcecea33eb318cd155cf35890341eff..d4327ea607c4360244253bc678b6638265baf329 100644
--- a/arch/arm/dts/rk3399-orangepi-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-orangepi-u-boot.dtsi
@@ -5,3 +5,7 @@
 
 #include "rk3399-u-boot.dtsi"
 #include "rk3399-sdram-ddr3-1333.dtsi"
+
+&vdd_log {
+	regulator-init-microvolt = <950000>;
+};
diff --git a/arch/arm/dts/rk3399-roc-pc.dts b/arch/arm/dts/rk3399-roc-pc.dts
index 19f7732d728c10de5473081a51a542fe9a100a03..257543d069d8f33c10af950821830e1db21dda15 100644
--- a/arch/arm/dts/rk3399-roc-pc.dts
+++ b/arch/arm/dts/rk3399-roc-pc.dts
@@ -57,9 +57,9 @@
 	 * should be placed inside mp8859, but not until mp8859 has
 	 * its own dt-binding.
 	 */
-	vcc12v_sys: mp8859-dcdc1 {
+	dc_12v: mp8859-dcdc1 {
 		compatible = "regulator-fixed";
-		regulator-name = "vcc12v_sys";
+		regulator-name = "dc_12v";
 		regulator-always-on;
 		regulator-boot-on;
 		regulator-min-microvolt = <12000000>;
@@ -85,7 +85,7 @@
 		regulator-boot-on;
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		vin-supply = <&vcc12v_sys>;
+		vin-supply = <&vcc_sys>;
 	};
 
 	/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
@@ -118,7 +118,7 @@
 		regulator-boot-on;
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
-		vin-supply = <&vcc12v_sys>;
+		vin-supply = <&dc_12v>;
 	};
 
 	vdd_log: vdd-log {
@@ -129,7 +129,7 @@
 		regulator-boot-on;
 		regulator-min-microvolt = <800000>;
 		regulator-max-microvolt = <1400000>;
-		vin-supply = <&vcc3v3_sys>;
+		vin-supply = <&vcc_sys>;
 	};
 };
 
@@ -202,16 +202,16 @@
 		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>;
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
 		vcc8-supply = <&vcc3v3_sys>;
-		vcc9-supply = <&vcc3v3_sys>;
-		vcc10-supply = <&vcc3v3_sys>;
-		vcc11-supply = <&vcc3v3_sys>;
+		vcc9-supply = <&vcc_sys>;
+		vcc10-supply = <&vcc_sys>;
+		vcc11-supply = <&vcc_sys>;
 		vcc12-supply = <&vcc3v3_sys>;
 		vddio-supply = <&vcc1v8_pmu>;
 
@@ -385,7 +385,7 @@
 		regulator-ramp-delay = <1000>;
 		regulator-always-on;
 		regulator-boot-on;
-		vin-supply = <&vcc3v3_sys>;
+		vin-supply = <&vcc_sys>;
 
 		regulator-state-mem {
 			regulator-off-in-suspend;
@@ -404,7 +404,7 @@
 		regulator-ramp-delay = <1000>;
 		regulator-always-on;
 		regulator-boot-on;
-		vin-supply = <&vcc3v3_sys>;
+		vin-supply = <&vcc_sys>;
 
 		regulator-state-mem {
 			regulator-off-in-suspend;
diff --git a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
index 5bd8696666aabfbc13fb285d3f6203f3133fd876..c17e769f649f2125a568c85fbc3dc06143733296 100644
--- a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
@@ -11,3 +11,7 @@
 		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
 	};
 };
+
+&vdd_log {
+	regulator-init-microvolt = <950000>;
+};
diff --git a/arch/arm/dts/rk3399-rock960-u-boot.dtsi b/arch/arm/dts/rk3399-rock960-u-boot.dtsi
index 4850debdf0b0717af8f79ce7273d4cee4a33063c..82f2c311afbec944783030209634d265b4204be9 100644
--- a/arch/arm/dts/rk3399-rock960-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rock960-u-boot.dtsi
@@ -10,4 +10,17 @@
 	chosen {
 		u-boot,spl-boot-order = &sdhci, &sdmmc;
 	};
+
+	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>;
+		regulator-init-microvolt = <950000>;
+		vin-supply = <&vcc5v0_sys>;
+	};
+
 };
diff --git a/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi b/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
index a073ea25f51b80e9fd06bde1e203c9f4abb45ec7..4648513ea9bd4b8bc73bfe76e0d7313a7743caa0 100644
--- a/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
@@ -11,6 +11,11 @@
 	};
 };
 
+&vdd_center {
+	regulator-min-microvolt = <950000>;
+	regulator-max-microvolt = <950000>;
+};
+
 &vdd_log {
 	regulator-init-microvolt = <950000>;
 };
diff --git a/arch/arm/dts/rk3399-rockpro64.dts b/arch/arm/dts/rk3399-rockpro64.dts
index 1f2394e0587db4f4a7d6c065bd3f868a45ecd654..e544deb61d288285610a2d28aea8ecf1a40adc17 100644
--- a/arch/arm/dts/rk3399-rockpro64.dts
+++ b/arch/arm/dts/rk3399-rockpro64.dts
@@ -58,6 +58,13 @@
 		};
 	};
 
+	fan: pwm-fan {
+		compatible = "pwm-fan";
+		#cooling-cells = <2>;
+		fan-supply = <&vcc12v_dcin>;
+		pwms = <&pwm1 0 50000 0>;
+	};
+
 	sdio_pwrseq: sdio-pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		clocks = <&rk808 1>;
@@ -166,7 +173,7 @@
 		regulator-always-on;
 		regulator-boot-on;
 		regulator-min-microvolt = <800000>;
-		regulator-max-microvolt = <1400000>;
+		regulator-max-microvolt = <1700000>;
 		vin-supply = <&vcc5v0_sys>;
 	};
 };
@@ -222,6 +229,10 @@
 	status = "okay";
 };
 
+&hdmi_sound {
+	status = "okay";
+};
+
 &gpu {
 	mali-supply = <&vdd_gpu>;
 	status = "okay";
@@ -236,8 +247,8 @@
 	rk808: pmic@1b {
 		compatible = "rockchip,rk808";
 		reg = <0x1b>;
-		interrupt-parent = <&gpio1>;
-		interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
 		#clock-cells = <1>;
 		clock-output-names = "xin32k", "rk808-clkout2";
 		pinctrl-names = "default";
@@ -504,11 +515,25 @@
 	status = "okay";
 
 	bt656-supply = <&vcc1v8_dvp>;
-	audio-supply = <&vcca1v8_codec>;
+	audio-supply = <&vcc_3v0>;
 	sdmmc-supply = <&vcc_sdio>;
 	gpio1830-supply = <&vcc_3v0>;
 };
 
+&pcie0 {
+	ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
+	num-lanes = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_perst>;
+	vpcie12v-supply = <&vcc12v_dcin>;
+	vpcie3v3-supply = <&vcc3v3_pcie>;
+	status = "okay";
+};
+
+&pcie_phy {
+	status = "okay";
+};
+
 &pmu_io_domains {
 	pmu1830-supply = <&vcc_3v0>;
 	status = "okay";
@@ -538,6 +563,10 @@
 	};
 
 	pcie {
+		pcie_perst: pcie-perst {
+			rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
 		pcie_pwr_en: pcie-pwr-en {
 			rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
@@ -545,7 +574,7 @@
 
 	pmic {
 		pmic_int_l: pmic-int-l {
-			rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 
 		vsel1_gpio: vsel1-gpio {
@@ -580,6 +609,10 @@
 	status = "okay";
 };
 
+&pwm1 {
+	status = "okay";
+};
+
 &pwm2 {
 	status = "okay";
 };
@@ -591,7 +624,6 @@
 
 &sdmmc {
 	bus-width = <4>;
-	cap-mmc-highspeed;
 	cap-sd-highspeed;
 	cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
 	disable-wp;
@@ -603,12 +635,21 @@
 
 &sdhci {
 	bus-width = <8>;
-	mmc-hs400-1_8v;
-	mmc-hs400-enhanced-strobe;
+	mmc-hs200-1_8v;
 	non-removable;
 	status = "okay";
 };
 
+&spi1 {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+	};
+};
+
 &tcphy0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
index 3708bd674b820a7eb25e1591de7c7b9865f46cfe..7fae249536bb6789b915f7add5767ac651e146fc 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1333.dtsi
@@ -13,6 +13,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80120e12
 		0x11030802
@@ -28,6 +30,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80120e12
 		0x11030802
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
index fcd01f8b462f2a6209eac7b1aed3e6bf4c64647f..23c7c34a9ac253bc461126e01c7767893eb5402c 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1600.dtsi
@@ -13,6 +13,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80151015
 		0x14040902
@@ -28,6 +30,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80151015
 		0x14040902
diff --git a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
index c46c1996bec4e4b9143e219ecb6c65dc3923a55c..ea029ca90afddcfd0e0a9224136fc51161259a93 100644
--- a/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
+++ b/arch/arm/dts/rk3399-sdram-ddr3-1866.dtsi
@@ -13,6 +13,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80181219
 		0x17050a03
@@ -28,6 +30,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80181219
 		0x17050a03
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
index d14e833d228484334fe3b2b573fd2bb10d6b3509..7296dbb80e0ee1f7e3c233e82c1b86388820656d 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-2GB-1600.dtsi
@@ -14,6 +14,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x1d191519
 		0x14040808
@@ -29,6 +31,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x1d191519
 		0x14040808
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
index fc4cccb6a0d3f30db00dbc48d6459095b0fe0fac..bf429c21e4eec8dc570e1ae4adbf750a9df695b8 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-4GB-1600.dtsi
@@ -13,6 +13,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x1d191519
 		0x14040808
@@ -28,6 +30,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x1d191519
 		0x14040808
diff --git a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
index 2a627e1be5742ca8744309989182b23232e1a862..96f459fd0b7886e01f98ac56c19cb612cba943e3 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr3-samsung-4GB-1866.dtsi
@@ -13,6 +13,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 
 		0x801d181e
@@ -30,6 +32,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 
 		0x801d181e
diff --git a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
index 4a4414a960fc14317129a6b4a61402137f7b7eae..f0c478d189ed38d61762efbf3326c069a3a0c39b 100644
--- a/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
+++ b/arch/arm/dts/rk3399-sdram-lpddr4-100.dtsi
@@ -15,6 +15,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80241d22
 		0x15050f08
@@ -30,6 +32,8 @@
 		0x0
 		0xf
 		0xf
+		0xf
+		0xf
 		1
 		0x80241d22
 		0x15050f08
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index 2738a3889ef65788853205b877ebfb017729722c..40240bbfc2b8561e73fdfaeaa64239db6e7bcc03 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -3,10 +3,50 @@
  * Copyright (C) 2019 Jagan Teki <jagan@amarulasolutions.com>
  */
 
+&cic {
+	u-boot,dm-pre-reloc;
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&dmc {
+	u-boot,dm-pre-reloc;
+};
+
+&grf {
+	u-boot,dm-pre-reloc;
+};
+
+&pinctrl {
+	u-boot,dm-pre-reloc;
+};
+
 &pmu {
 	u-boot,dm-pre-reloc;
 };
 
+&pmugrf {
+	u-boot,dm-pre-reloc;
+};
+
+&pmu {
+	u-boot,dm-pre-reloc;
+};
+
+&pmucru {
+	u-boot,dm-pre-reloc;
+};
+
+&pmusgrf {
+	u-boot,dm-pre-reloc;
+};
+
+&sdhci {
+	u-boot,dm-pre-reloc;
+};
+
 &sdmmc {
 	u-boot,dm-pre-reloc;
 };
@@ -22,3 +62,11 @@
 &uart2 {
 	u-boot,dm-pre-reloc;
 };
+
+&vopb {
+	u-boot,dm-pre-reloc;
+};
+
+&vopl {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi
index b73442ee34393ed84d0cd928e232e323cad97c79..3f773b10f4de648305bb1ffee68ce32138b064bc 100644
--- a/arch/arm/dts/rk3399.dtsi
+++ b/arch/arm/dts/rk3399.dtsi
@@ -275,7 +275,6 @@
 	};
 
 	sdhci: sdhci@fe330000 {
-		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 0>;
@@ -1072,7 +1071,6 @@
 	};
 
 	pmugrf: syscon@ff320000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd";
 		reg = <0x0 0xff320000 0x0 0x1000>;
 
@@ -1083,7 +1081,6 @@
 	};
 
 	pmusgrf: syscon@ff330000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmusgrf", "syscon";
 		reg = <0x0 0xff330000 0x0 0xe3d4>;
 	};
@@ -1204,7 +1201,6 @@
 	};
 
 	cic: syscon@ff620000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-cic", "syscon";
 		reg = <0x0 0xff620000 0x0 0x100>;
 	};
@@ -1219,7 +1215,6 @@
 	};
 
 	dmc: dmc {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-dmc";
 		devfreq-events = <&dfi>;
 		interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -1268,7 +1263,6 @@
 	};
 
 	pmucru: pmu-clock-controller@ff750000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pmucru";
 		reg = <0x0 0xff750000 0x0 0x1000>;
 		rockchip,grf = <&pmugrf>;
@@ -1279,7 +1273,6 @@
 	};
 
 	cru: clock-controller@ff760000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-cru";
 		reg = <0x0 0xff760000 0x0 0x1000>;
 		rockchip,grf = <&grf>;
@@ -1310,7 +1303,6 @@
 	};
 
 	grf: syscon@ff770000 {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
 		#address-cells = <1>;
@@ -1520,7 +1512,6 @@
 	};
 
 	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>;
@@ -1578,7 +1569,6 @@
 	};
 
 	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>;
@@ -1818,7 +1808,6 @@
 	};
 
 	pinctrl: pinctrl {
-		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3399-pinctrl";
 		rockchip,grf = <&grf>;
 		rockchip,pmu = <&pmugrf>;
diff --git a/arch/arm/include/asm/arch-px30/boot0.h b/arch/arm/include/asm/arch-px30/boot0.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e78b074ade8fd7985a125f56a67980afcab5e47
--- /dev/null
+++ b/arch/arm/include/asm/arch-px30/boot0.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-px30/gpio.h b/arch/arm/include/asm/arch-px30/gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..eca79d51594081053481fc3e909d73d838867add
--- /dev/null
+++ b/arch/arm/include/asm/arch-px30/gpio.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_GPIO_H__
+#define __ASM_ARCH_GPIO_H__
+
+#include <asm/arch-rockchip/gpio.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-rk3308/boot0.h b/arch/arm/include/asm/arch-rk3308/boot0.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e78b074ade8fd7985a125f56a67980afcab5e47
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3308/boot0.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-rk3308/cru_rk3308.h b/arch/arm/include/asm/arch-rk3308/cru_rk3308.h
new file mode 100644
index 0000000000000000000000000000000000000000..a14b64cdb3e077386cee6516efeb8c7d5dbe262f
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3308/cru_rk3308.h
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+#ifndef _ASM_ARCH_CRU_RK3308_H
+#define _ASM_ARCH_CRU_RK3308_H
+
+#include <common.h>
+
+#define MHz		1000000
+#define OSC_HZ		(24 * MHz)
+
+#define APLL_HZ		(816 * MHz)
+
+#define CORE_ACLK_HZ	408000000
+#define CORE_DBG_HZ	204000000
+
+#define BUS_ACLK_HZ	200000000
+#define BUS_HCLK_HZ	100000000
+#define BUS_PCLK_HZ	100000000
+
+#define PERI_ACLK_HZ	200000000
+#define PERI_HCLK_HZ	100000000
+#define PERI_PCLK_HZ	100000000
+
+#define AUDIO_HCLK_HZ	100000000
+#define AUDIO_PCLK_HZ	100000000
+
+#define RK3308_PLL_CON(x)	((x) * 0x4)
+#define RK3308_MODE_CON		0xa0
+
+/* RK3308 pll id */
+enum rk3308_pll_id {
+	APLL,
+	DPLL,
+	VPLL0,
+	VPLL1,
+	PLL_COUNT,
+};
+
+struct rk3308_clk_info {
+	unsigned long id;
+	char *name;
+};
+
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rk3308_clk_priv {
+	struct rk3308_cru *cru;
+	ulong armclk_hz;
+	ulong dpll_hz;
+	ulong vpll0_hz;
+	ulong vpll1_hz;
+};
+
+struct rk3308_cru {
+	struct rk3308_pll {
+		unsigned int con0;
+		unsigned int con1;
+		unsigned int con2;
+		unsigned int con3;
+		unsigned int con4;
+		unsigned int reserved0[3];
+	} pll[4];
+	unsigned int reserved1[8];
+	unsigned int mode;
+	unsigned int misc;
+	unsigned int reserved2[2];
+	unsigned int glb_cnt_th;
+	unsigned int glb_rst_st;
+	unsigned int glb_srst_fst;
+	unsigned int glb_srst_snd;
+	unsigned int glb_rst_con;
+	unsigned int pll_lock;
+	unsigned int reserved3[6];
+	unsigned int hwffc_con0;
+	unsigned int reserved4;
+	unsigned int hwffc_th;
+	unsigned int hwffc_intst;
+	unsigned int apll_con0_s;
+	unsigned int apll_con1_s;
+	unsigned int clksel_con0_s;
+	unsigned int reserved5;
+	unsigned int clksel_con[74];
+	unsigned int reserved6[54];
+	unsigned int clkgate_con[15];
+	unsigned int reserved7[(0x380 - 0x338) / 4 - 1];
+	unsigned int ssgtbl[32];
+	unsigned int softrst_con[10];
+	unsigned int reserved8[(0x480 - 0x424) / 4 - 1];
+	unsigned int sdmmc_con[2];
+	unsigned int sdio_con[2];
+	unsigned int emmc_con[2];
+};
+
+enum {
+	/* PLLCON0*/
+	PLL_BP_SHIFT		= 15,
+	PLL_POSTDIV1_SHIFT	= 12,
+	PLL_POSTDIV1_MASK	= 7 << PLL_POSTDIV1_SHIFT,
+	PLL_FBDIV_SHIFT		= 0,
+	PLL_FBDIV_MASK		= 0xfff,
+
+	/* PLLCON1 */
+	PLL_PDSEL_SHIFT		= 15,
+	PLL_PD1_SHIFT		= 14,
+	PLL_PD_SHIFT		= 13,
+	PLL_PD_MASK		= 1 << PLL_PD_SHIFT,
+	PLL_DSMPD_SHIFT		= 12,
+	PLL_DSMPD_MASK		= 1 << PLL_DSMPD_SHIFT,
+	PLL_LOCK_STATUS_SHIFT	= 10,
+	PLL_LOCK_STATUS_MASK	= 1 << PLL_LOCK_STATUS_SHIFT,
+	PLL_POSTDIV2_SHIFT	= 6,
+	PLL_POSTDIV2_MASK	= 7 << PLL_POSTDIV2_SHIFT,
+	PLL_REFDIV_SHIFT	= 0,
+	PLL_REFDIV_MASK		= 0x3f,
+
+	/* PLLCON2 */
+	PLL_FOUT4PHASEPD_SHIFT	= 27,
+	PLL_FOUTVCOPD_SHIFT	= 26,
+	PLL_FOUTPOSTDIVPD_SHIFT	= 25,
+	PLL_DACPD_SHIFT		= 24,
+	PLL_FRAC_DIV	= 0xffffff,
+
+	/* CRU_MODE */
+	PLLMUX_FROM_XIN24M	= 0,
+	PLLMUX_FROM_PLL,
+	PLLMUX_FROM_RTC32K,
+	USBPHY480M_MODE_SHIFT	= 8,
+	USBPHY480M_MODE_MASK	= 3 << USBPHY480M_MODE_SHIFT,
+	VPLL1_MODE_SHIFT		= 6,
+	VPLL1_MODE_MASK		= 3 << VPLL1_MODE_SHIFT,
+	VPLL0_MODE_SHIFT		= 4,
+	VPLL0_MODE_MASK		= 3 << VPLL0_MODE_SHIFT,
+	DPLL_MODE_SHIFT		= 2,
+	DPLL_MODE_MASK		= 3 << DPLL_MODE_SHIFT,
+	APLL_MODE_SHIFT		= 0,
+	APLL_MODE_MASK		= 3 << APLL_MODE_SHIFT,
+
+	/* CRU_CLK_SEL0_CON */
+	CORE_ACLK_DIV_SHIFT	= 12,
+	CORE_ACLK_DIV_MASK	= 0x7 << CORE_ACLK_DIV_SHIFT,
+	CORE_DBG_DIV_SHIFT	= 8,
+	CORE_DBG_DIV_MASK	= 0xf << CORE_DBG_DIV_SHIFT,
+	CORE_CLK_PLL_SEL_SHIFT	= 6,
+	CORE_CLK_PLL_SEL_MASK	= 0x3 << CORE_CLK_PLL_SEL_SHIFT,
+	CORE_CLK_PLL_SEL_APLL	= 0,
+	CORE_CLK_PLL_SEL_VPLL0,
+	CORE_CLK_PLL_SEL_VPLL1,
+	CORE_DIV_CON_SHIFT	= 0,
+	CORE_DIV_CON_MASK	= 0x0f << CORE_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL5_CON */
+	BUS_PLL_SEL_SHIFT	= 6,
+	BUS_PLL_SEL_MASK	= 0x3 << BUS_PLL_SEL_SHIFT,
+	BUS_PLL_SEL_DPLL	= 0,
+	BUS_PLL_SEL_VPLL0,
+	BUS_PLL_SEL_VPLL1,
+	BUS_ACLK_DIV_SHIFT	= 0,
+	BUS_ACLK_DIV_MASK	= 0x1f << BUS_ACLK_DIV_SHIFT,
+
+	/* CRU_CLK_SEL6_CON */
+	BUS_PCLK_DIV_SHIFT	= 8,
+	BUS_PCLK_DIV_MASK	= 0x1f << BUS_PCLK_DIV_SHIFT,
+	BUS_HCLK_DIV_SHIFT	= 0,
+	BUS_HCLK_DIV_MASK	= 0x1f << BUS_HCLK_DIV_SHIFT,
+
+	/* CRU_CLK_SEL7_CON */
+	CRYPTO_APK_SEL_SHIFT	= 14,
+	CRYPTO_APK_PLL_SEL_MASK	= 3 << CRYPTO_APK_SEL_SHIFT,
+	CRYPTO_PLL_SEL_DPLL	= 0,
+	CRYPTO_PLL_SEL_VPLL0,
+	CRYPTO_PLL_SEL_VPLL1	= 0,
+	CRYPTO_APK_DIV_SHIFT	= 8,
+	CRYPTO_APK_DIV_MASK	= 0x1f << CRYPTO_APK_DIV_SHIFT,
+	CRYPTO_PLL_SEL_SHIFT	= 6,
+	CRYPTO_PLL_SEL_MASK	= 3 << CRYPTO_PLL_SEL_SHIFT,
+	CRYPTO_DIV_SHIFT	= 0,
+	CRYPTO_DIV_MASK		= 0x1f << CRYPTO_DIV_SHIFT,
+
+	/* CRU_CLK_SEL8_CON */
+	DCLK_VOP_SEL_SHIFT	= 14,
+	DCLK_VOP_SEL_MASK	= 0x3 << DCLK_VOP_SEL_SHIFT,
+	DCLK_VOP_SEL_DIVOUT	= 0,
+	DCLK_VOP_SEL_FRACOUT,
+	DCLK_VOP_SEL_24M,
+	DCLK_VOP_PLL_SEL_SHIFT	= 10,
+	DCLK_VOP_PLL_SEL_MASK	= 0x3 << DCLK_VOP_PLL_SEL_SHIFT,
+	DCLK_VOP_PLL_SEL_DPLL	= 0,
+	DCLK_VOP_PLL_SEL_VPLL0,
+	DCLK_VOP_PLL_SEL_VPLL1,
+	DCLK_VOP_DIV_SHIFT	= 0,
+	DCLK_VOP_DIV_MASK	= 0xff,
+
+	/* CRU_CLK_SEL25_CON */
+	/* CRU_CLK_SEL26_CON */
+	/* CRU_CLK_SEL27_CON */
+	/* CRU_CLK_SEL28_CON */
+	CLK_I2C_PLL_SEL_SHIFT		= 14,
+	CLK_I2C_PLL_SEL_MASK		= 0x3 << CLK_I2C_PLL_SEL_SHIFT,
+	CLK_I2C_PLL_SEL_DPLL		= 0,
+	CLK_I2C_PLL_SEL_VPLL0,
+	CLK_I2C_PLL_SEL_24M,
+	CLK_I2C_DIV_CON_SHIFT		= 0,
+	CLK_I2C_DIV_CON_MASK		= 0x7f << CLK_I2C_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL29_CON */
+	CLK_PWM_PLL_SEL_SHIFT		= 14,
+	CLK_PWM_PLL_SEL_MASK		= 0x3 << CLK_PWM_PLL_SEL_SHIFT,
+	CLK_PWM_PLL_SEL_DPLL		= 0,
+	CLK_PWM_PLL_SEL_VPLL0,
+	CLK_PWM_PLL_SEL_24M,
+	CLK_PWM_DIV_CON_SHIFT		= 0,
+	CLK_PWM_DIV_CON_MASK		= 0x7f << CLK_PWM_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL30_CON */
+	/* CRU_CLK_SEL31_CON */
+	/* CRU_CLK_SEL32_CON */
+	CLK_SPI_PLL_SEL_SHIFT		= 14,
+	CLK_SPI_PLL_SEL_MASK		= 0x3 << CLK_SPI_PLL_SEL_SHIFT,
+	CLK_SPI_PLL_SEL_DPLL		= 0,
+	CLK_SPI_PLL_SEL_VPLL0,
+	CLK_SPI_PLL_SEL_24M,
+	CLK_SPI_DIV_CON_SHIFT		= 0,
+	CLK_SPI_DIV_CON_MASK		= 0x7f << CLK_SPI_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL34_CON */
+	CLK_SARADC_DIV_CON_SHIFT	= 0,
+	CLK_SARADC_DIV_CON_MASK		= 0x7ff << CLK_SARADC_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL36_CON */
+	PERI_PLL_SEL_SHIFT	= 6,
+	PERI_PLL_SEL_MASK	= 0x3 << PERI_PLL_SEL_SHIFT,
+	PERI_PLL_DPLL		= 0,
+	PERI_PLL_VPLL0,
+	PERI_PLL_VPLL1,
+	PERI_ACLK_DIV_SHIFT	= 0,
+	PERI_ACLK_DIV_MASK	= 0x1f << PERI_ACLK_DIV_SHIFT,
+
+	/* CRU_CLK_SEL37_CON */
+	PERI_PCLK_DIV_SHIFT	= 8,
+	PERI_PCLK_DIV_MASK	= 0x1f << PERI_PCLK_DIV_SHIFT,
+	PERI_HCLK_DIV_SHIFT	= 0,
+	PERI_HCLK_DIV_MASK	= 0x1f << PERI_HCLK_DIV_SHIFT,
+
+	/* CRU_CLKSEL41_CON */
+	EMMC_CLK_SEL_SHIFT	= 15,
+	EMMC_CLK_SEL_MASK	= 1 << EMMC_CLK_SEL_SHIFT,
+	EMMC_CLK_SEL_EMMC	= 0,
+	EMMC_CLK_SEL_EMMC_DIV50,
+	EMMC_PLL_SHIFT		= 8,
+	EMMC_PLL_MASK		= 0x3 << EMMC_PLL_SHIFT,
+	EMMC_SEL_DPLL		= 0,
+	EMMC_SEL_VPLL0,
+	EMMC_SEL_VPLL1,
+	EMMC_SEL_24M,
+	EMMC_DIV_SHIFT		= 0,
+	EMMC_DIV_MASK		= 0xff << EMMC_DIV_SHIFT,
+
+	/* CRU_CLKSEL43_CON */
+	MAC_CLK_SPEED_SEL_SHIFT = 15,
+	MAC_CLK_SPEED_SEL_MASK = 1 << MAC_CLK_SPEED_SEL_SHIFT,
+	MAC_CLK_SPEED_SEL_10M = 0,
+	MAC_CLK_SPEED_SEL_100M,
+	MAC_CLK_SOURCE_SEL_SHIFT = 14,
+	MAC_CLK_SOURCE_SEL_MASK = 1 << MAC_CLK_SOURCE_SEL_SHIFT,
+	MAC_CLK_SOURCE_SEL_INTERNAL	= 0,
+	MAC_CLK_SOURCE_SEL_EXTERNAL,
+	MAC_PLL_SHIFT		= 6,
+	MAC_PLL_MASK		= 0x3 << MAC_PLL_SHIFT,
+	MAC_SEL_DPLL		= 0,
+	MAC_SEL_VPLL0,
+	MAC_SEL_VPLL1,
+	MAC_DIV_SHIFT		= 0,
+	MAC_DIV_MASK		= 0x1f << MAC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL45_CON */
+	AUDIO_PCLK_DIV_SHIFT	= 8,
+	AUDIO_PCLK_DIV_MASK	= 0x1f << AUDIO_PCLK_DIV_SHIFT,
+	AUDIO_PLL_SEL_SHIFT	= 6,
+	AUDIO_PLL_SEL_MASK	= 0x3 << AUDIO_PLL_SEL_SHIFT,
+	AUDIO_PLL_VPLL0		= 0,
+	AUDIO_PLL_VPLL1,
+	AUDIO_PLL_24M,
+	AUDIO_HCLK_DIV_SHIFT	= 0,
+	AUDIO_HCLK_DIV_MASK	= 0x1f << AUDIO_HCLK_DIV_SHIFT,
+};
+
+check_member(rk3308_cru, emmc_con[1], 0x494);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rk3308/gpio.h b/arch/arm/include/asm/arch-rk3308/gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..eca79d51594081053481fc3e909d73d838867add
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3308/gpio.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_GPIO_H__
+#define __ASM_ARCH_GPIO_H__
+
+#include <asm/arch-rockchip/gpio.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-rk3308/grf_rk3308.h b/arch/arm/include/asm/arch-rk3308/grf_rk3308.h
new file mode 100644
index 0000000000000000000000000000000000000000..3e68626d3e9adbf5645f71f07c61d1f44304ba9a
--- /dev/null
+++ b/arch/arm/include/asm/arch-rk3308/grf_rk3308.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *Copyright 2019 Rockchip Electronics Co., Ltd.
+ */
+#ifndef _ASM_ARCH_GRF_rk3308_H
+#define _ASM_ARCH_GRF_rk3308_H
+
+#include <common.h>
+
+struct rk3308_grf {
+	unsigned int gpio0a_iomux;
+	unsigned int reserved0;
+	unsigned int gpio0b_iomux;
+	unsigned int reserved1;
+	unsigned int gpio0c_iomux;
+	unsigned int reserved2[3];
+	unsigned int gpio1a_iomux;
+	unsigned int reserved3;
+	unsigned int gpio1bl_iomux;
+	unsigned int gpio1bh_iomux;
+	unsigned int gpio1cl_iomux;
+	unsigned int gpio1ch_iomux;
+	unsigned int gpio1d_iomux;
+	unsigned int reserved4;
+	unsigned int gpio2a_iomux;
+	unsigned int reserved5;
+	unsigned int gpio2b_iomux;
+	unsigned int reserved6;
+	unsigned int gpio2c_iomux;
+	unsigned int reserved7[3];
+	unsigned int gpio3a_iomux;
+	unsigned int reserved8;
+	unsigned int gpio3b_iomux;
+	unsigned int reserved9[5];
+	unsigned int gpio4a_iomux;
+	unsigned int reserved33;
+	unsigned int gpio4b_iomux;
+	unsigned int reserved10;
+	unsigned int gpio4c_iomux;
+	unsigned int reserved11;
+	unsigned int gpio4d_iomux;
+	unsigned int reserved34;
+	unsigned int gpio0a_p;
+	unsigned int gpio0b_p;
+	unsigned int gpio0c_p;
+	unsigned int reserved12;
+	unsigned int gpio1a_p;
+	unsigned int gpio1b_p;
+	unsigned int gpio1c_p;
+	unsigned int gpio1d_p;
+	unsigned int gpio2a_p;
+	unsigned int gpio2b_p;
+	unsigned int gpio2c_p;
+	unsigned int reserved13;
+	unsigned int gpio3a_p;
+	unsigned int gpio3b_p;
+	unsigned int reserved14[2];
+	unsigned int gpio4a_p;
+	unsigned int gpio4b_p;
+	unsigned int gpio4c_p;
+	unsigned int gpio4d_p;
+	unsigned int reserved15[(0x100 - 0xec) / 4 - 1];
+	unsigned int gpio0a_e;
+	unsigned int gpio0b_e;
+	unsigned int gpio0c_e;
+	unsigned int reserved16;
+	unsigned int gpio1a_e;
+	unsigned int gpio1b_e;
+	unsigned int gpio1c_e;
+	unsigned int gpio1d_e;
+	unsigned int gpio2a_e;
+	unsigned int gpio2b_e;
+	unsigned int gpio2c_e;
+	unsigned int reserved17;
+	unsigned int gpio3a_e;
+	unsigned int gpio3b_e;
+	unsigned int reserved18[2];
+	unsigned int gpio4a_e;
+	unsigned int gpio4b_e;
+	unsigned int gpio4c_e;
+	unsigned int gpio4d_e;
+	unsigned int gpio0a_sr;
+	unsigned int gpio0b_sr;
+	unsigned int gpio0c_sr;
+	unsigned int reserved19;
+	unsigned int gpio1a_sr;
+	unsigned int gpio1b_sr;
+	unsigned int gpio1c_sr;
+	unsigned int gpio1d_sr;
+	unsigned int gpio2a_sr;
+	unsigned int gpio2b_sr;
+	unsigned int gpio2c_sr;
+	unsigned int reserved20;
+	unsigned int gpio3a_sr;
+	unsigned int gpio3b_sr;
+	unsigned int reserved21[2];
+	unsigned int gpio4a_sr;
+	unsigned int gpio4b_sr;
+	unsigned int gpio4c_sr;
+	unsigned int gpio4d_sr;
+	unsigned int gpio0a_smt;
+	unsigned int gpio0b_smt;
+	unsigned int gpio0c_smt;
+	unsigned int reserved22;
+	unsigned int gpio1a_smt;
+	unsigned int gpio1b_smt;
+	unsigned int gpio1c_smt;
+	unsigned int gpio1d_smt;
+	unsigned int gpio2a_smt;
+	unsigned int gpio2b_smt;
+	unsigned int gpio2c_smt;
+	unsigned int reserved23;
+	unsigned int gpio3a_smt;
+	unsigned int gpio3b_smt;
+	unsigned int reserved35[2];
+	unsigned int gpio4a_smt;
+	unsigned int gpio4b_smt;
+	unsigned int gpio4c_smt;
+	unsigned int gpio4d_smt;
+	unsigned int reserved24[(0x300 - 0x1EC) / 4 - 1];
+	unsigned int soc_con0;
+	unsigned int soc_con1;
+	unsigned int soc_con2;
+	unsigned int soc_con3;
+	unsigned int soc_con4;
+	unsigned int soc_con5;
+	unsigned int soc_con6;
+	unsigned int soc_con7;
+	unsigned int soc_con8;
+	unsigned int soc_con9;
+	unsigned int soc_con10;
+	unsigned int reserved25[(0x380 - 0x328) / 4 - 1];
+	unsigned int soc_status0;
+	unsigned int reserved26[(0x400 - 0x380) / 4 - 1];
+	unsigned int cpu_con0;
+	unsigned int cpu_con1;
+	unsigned int cpu_con2;
+	unsigned int reserved27[(0x420 - 0x408) / 4 - 1];
+	unsigned int cpu_status0;
+	unsigned int cpu_status1;
+	unsigned int reserved28[(0x440 - 0x424) / 4 - 1];
+	unsigned int pvtm_con0;
+	unsigned int pvtm_con1;
+	unsigned int pvtm_status0;
+	unsigned int pvtm_status1;
+	unsigned int reserved29[(0x460 - 0x44C) / 4 - 1];
+	unsigned int tsadc_tbl;
+	unsigned int tsadc_tbh;
+	unsigned int reserved30[(0x480 - 0x464) / 4 - 1];
+	unsigned int host0_con0;
+	unsigned int host0_con1;
+	unsigned int otg_con0;
+	unsigned int host0_status0;
+	unsigned int reserved31[(0x4a0 - 0x48C) / 4 - 1];
+	unsigned int mac_con0;
+	unsigned int upctrl_con0;
+	unsigned int upctrl_status0;
+	unsigned int reserved32[(0x500 - 0x4A8) / 4 - 1];
+	unsigned int os_reg0;
+	unsigned int os_reg1;
+	unsigned int os_reg2;
+	unsigned int os_reg3;
+	unsigned int os_reg4;
+	unsigned int os_reg5;
+	unsigned int os_reg6;
+	unsigned int os_reg7;
+	unsigned int os_reg8;
+	unsigned int os_reg9;
+	unsigned int os_reg10;
+	unsigned int os_reg11;
+	unsigned int reserved38[(0x600 - 0x52c) / 4 - 1];
+	unsigned int soc_con12;
+	unsigned int reserved39;
+	unsigned int soc_con13;
+	unsigned int soc_con14;
+	unsigned int soc_con15;
+	unsigned int reserved40[(0x800 - 0x610) / 4 - 1];
+	unsigned int chip_id;
+};
+check_member(rk3308_grf, gpio0a_p, 0xa0);
+
+struct rk3308_sgrf {
+	unsigned int soc_con0;
+	unsigned int soc_con1;
+	unsigned int con_tzma_r0size;
+	unsigned int con_secure0;
+	unsigned int reserved0;
+	unsigned int clk_timer_en;
+	unsigned int clkgat_con;
+	unsigned int fastboot_addr;
+	unsigned int fastboot_en;
+	unsigned int reserved1[(0x30 - 0x24) / 4];
+	unsigned int srst_con;
+};
+check_member(rk3308_sgrf, fastboot_en, 0x20);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 0eb19ca86f295bbd37ed87975bec8c36ecfd29dc..8f7fc86a9eb432429c00ebe2f1c19cdea2857b3f 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -9,6 +9,7 @@
 /* define pll mode */
 #define RKCLK_PLL_MODE_SLOW		0
 #define RKCLK_PLL_MODE_NORMAL		1
+#define RKCLK_PLL_MODE_DEEP		2
 
 enum {
 	ROCKCHIP_SYSCON_NOC,
@@ -33,6 +34,81 @@ enum rk_clk_id {
 	CLK_COUNT,
 };
 
+#define PLL(_type, _id, _con, _mode, _mshift,			\
+		 _lshift, _pflags, _rtable)			\
+	{							\
+		.id		= _id,				\
+		.type		= _type,			\
+		.con_offset	= _con,				\
+		.mode_offset	= _mode,			\
+		.mode_shift	= _mshift,			\
+		.lock_shift	= _lshift,			\
+		.pll_flags	= _pflags,			\
+		.rate_table	= _rtable,			\
+	}
+
+#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
+			_postdiv2, _dsmpd, _frac)		\
+{								\
+	.rate	= _rate##U,					\
+	.fbdiv = _fbdiv,					\
+	.postdiv1 = _postdiv1,					\
+	.refdiv = _refdiv,					\
+	.postdiv2 = _postdiv2,					\
+	.dsmpd = _dsmpd,					\
+	.frac = _frac,						\
+}
+
+struct rockchip_pll_rate_table {
+	unsigned long rate;
+	unsigned int nr;
+	unsigned int nf;
+	unsigned int no;
+	unsigned int nb;
+	/* for RK3036/RK3399 */
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
+};
+
+enum rockchip_pll_type {
+	pll_rk3036,
+	pll_rk3066,
+	pll_rk3328,
+	pll_rk3366,
+	pll_rk3399,
+};
+
+struct rockchip_pll_clock {
+	unsigned int			id;
+	unsigned int			con_offset;
+	unsigned int			mode_offset;
+	unsigned int			mode_shift;
+	unsigned int			lock_shift;
+	enum rockchip_pll_type		type;
+	unsigned int			pll_flags;
+	struct rockchip_pll_rate_table *rate_table;
+	unsigned int			mode_mask;
+};
+
+struct rockchip_cpu_rate_table {
+	unsigned long rate;
+	unsigned int aclk_div;
+	unsigned int pclk_div;
+};
+
+int rockchip_pll_set_rate(struct rockchip_pll_clock *pll,
+			  void __iomem *base, ulong clk_id,
+			  ulong drate);
+ulong rockchip_pll_get_rate(struct rockchip_pll_clock *pll,
+			    void __iomem *base, ulong clk_id);
+const struct rockchip_cpu_rate_table *
+rockchip_get_cpu_settings(struct rockchip_cpu_rate_table *cpu_table,
+			  ulong rate);
+
 static inline int rk_pll_id(enum rk_clk_id clk_id)
 {
 	return clk_id - 1;
@@ -43,12 +119,6 @@ struct sysreset_reg {
 	unsigned int glb_srst_snd_value;
 };
 
-struct softreset_reg {
-        void __iomem *base;
-        unsigned int sf_reset_offset;
-        unsigned int sf_reset_num;
-};
-
 /**
  * clk_get_divisor() - Calculate the required clock divisior
  *
diff --git a/arch/arm/include/asm/arch-rockchip/cru_px30.h b/arch/arm/include/asm/arch-rockchip/cru_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d9fd181aca227069f1ca1052dbcd61a8c94976e
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_px30.h
@@ -0,0 +1,432 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ */
+#ifndef _ASM_ARCH_CRU_PX30_H
+#define _ASM_ARCH_CRU_PX30_H
+
+#include <common.h>
+
+#define MHz		1000000
+#define KHz		1000
+#define OSC_HZ		(24 * MHz)
+
+#define APLL_HZ		(600 * MHz)
+#define GPLL_HZ		(1200 * MHz)
+#define NPLL_HZ		(1188 * MHz)
+#define ACLK_BUS_HZ	(200 * MHz)
+#define HCLK_BUS_HZ	(150 * MHz)
+#define PCLK_BUS_HZ	(100 * MHz)
+#define ACLK_PERI_HZ	(200 * MHz)
+#define HCLK_PERI_HZ	(150 * MHz)
+#define PCLK_PMU_HZ	(100 * MHz)
+
+/* PX30 pll id */
+enum px30_pll_id {
+	APLL,
+	DPLL,
+	CPLL,
+	NPLL,
+	GPLL,
+	PLL_COUNT,
+};
+
+struct px30_clk_priv {
+	struct px30_cru *cru;
+	ulong gpll_hz;
+};
+
+struct px30_pmuclk_priv {
+	struct px30_pmucru *pmucru;
+	ulong gpll_hz;
+};
+
+struct px30_pll {
+	unsigned int con0;
+	unsigned int con1;
+	unsigned int con2;
+	unsigned int con3;
+	unsigned int con4;
+	unsigned int reserved0[3];
+};
+
+struct px30_cru {
+	struct px30_pll pll[4];
+	unsigned int reserved1[8];
+	unsigned int mode;
+	unsigned int misc;
+	unsigned int reserved2[2];
+	unsigned int glb_cnt_th;
+	unsigned int glb_rst_st;
+	unsigned int glb_srst_fst;
+	unsigned int glb_srst_snd;
+	unsigned int glb_rst_con;
+	unsigned int reserved3[7];
+	unsigned int hwffc_con0;
+	unsigned int reserved4;
+	unsigned int hwffc_th;
+	unsigned int hwffc_intst;
+	unsigned int apll_con0_s;
+	unsigned int apll_con1_s;
+	unsigned int clksel_con0_s;
+	unsigned int reserved5;
+	unsigned int clksel_con[60];
+	unsigned int reserved6[4];
+	unsigned int clkgate_con[18];
+	unsigned int reserved7[(0x280 - 0x244) / 4 - 1];
+	unsigned int ssgtbl[32];
+	unsigned int softrst_con[12];
+	unsigned int reserved8[(0x380 - 0x32c) / 4 - 1];
+	unsigned int sdmmc_con[2];
+	unsigned int sdio_con[2];
+	unsigned int emmc_con[2];
+	unsigned int reserved9[(0x400 - 0x394) / 4 - 1];
+	unsigned int autocs_con[8];
+};
+
+check_member(px30_cru, autocs_con[7], 0x41c);
+
+struct px30_pmucru {
+	struct px30_pll pll;
+	unsigned int pmu_mode;
+	unsigned int reserved1[7];
+	unsigned int pmu_clksel_con[6];
+	unsigned int reserved2[10];
+	unsigned int pmu_clkgate_con[2];
+	unsigned int reserved3[14];
+	unsigned int pmu_autocs_con[2];
+};
+
+check_member(px30_pmucru, pmu_autocs_con[1], 0xc4);
+
+struct pll_rate_table {
+	unsigned long rate;
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
+};
+
+struct cpu_rate_table {
+	unsigned long rate;
+	unsigned int aclk_div;
+	unsigned int pclk_div;
+};
+
+enum {
+	/* PLLCON0*/
+	PLL_BP_SHIFT		= 15,
+	PLL_POSTDIV1_SHIFT	= 12,
+	PLL_POSTDIV1_MASK	= 7 << PLL_POSTDIV1_SHIFT,
+	PLL_FBDIV_SHIFT		= 0,
+	PLL_FBDIV_MASK		= 0xfff,
+
+	/* PLLCON1 */
+	PLL_PDSEL_SHIFT		= 15,
+	PLL_PD1_SHIFT		= 14,
+	PLL_PD_SHIFT		= 13,
+	PLL_PD_MASK		= 1 << PLL_PD_SHIFT,
+	PLL_DSMPD_SHIFT		= 12,
+	PLL_DSMPD_MASK		= 1 << PLL_DSMPD_SHIFT,
+	PLL_LOCK_STATUS_SHIFT	= 10,
+	PLL_LOCK_STATUS_MASK	= 1 << PLL_LOCK_STATUS_SHIFT,
+	PLL_POSTDIV2_SHIFT	= 6,
+	PLL_POSTDIV2_MASK	= 7 << PLL_POSTDIV2_SHIFT,
+	PLL_REFDIV_SHIFT	= 0,
+	PLL_REFDIV_MASK		= 0x3f,
+
+	/* PLLCON2 */
+	PLL_FOUT4PHASEPD_SHIFT	= 27,
+	PLL_FOUTVCOPD_SHIFT	= 26,
+	PLL_FOUTPOSTDIVPD_SHIFT	= 25,
+	PLL_DACPD_SHIFT		= 24,
+	PLL_FRAC_DIV	= 0xffffff,
+
+	/* CRU_MODE */
+	PLLMUX_FROM_XIN24M	= 0,
+	PLLMUX_FROM_PLL,
+	PLLMUX_FROM_RTC32K,
+	USBPHY480M_MODE_SHIFT	= 8,
+	USBPHY480M_MODE_MASK	= 3 << USBPHY480M_MODE_SHIFT,
+	NPLL_MODE_SHIFT		= 6,
+	NPLL_MODE_MASK		= 3 << NPLL_MODE_SHIFT,
+	DPLL_MODE_SHIFT		= 4,
+	DPLL_MODE_MASK		= 3 << DPLL_MODE_SHIFT,
+	CPLL_MODE_SHIFT		= 2,
+	CPLL_MODE_MASK		= 3 << CPLL_MODE_SHIFT,
+	APLL_MODE_SHIFT		= 0,
+	APLL_MODE_MASK		= 3 << APLL_MODE_SHIFT,
+
+	/* CRU_CLK_SEL0_CON */
+	CORE_ACLK_DIV_SHIFT	= 12,
+	CORE_ACLK_DIV_MASK	= 0x07 << CORE_ACLK_DIV_SHIFT,
+	CORE_DBG_DIV_SHIFT	= 8,
+	CORE_DBG_DIV_MASK	= 0x03 << CORE_DBG_DIV_SHIFT,
+	CORE_CLK_PLL_SEL_SHIFT	= 7,
+	CORE_CLK_PLL_SEL_MASK	= 1 << CORE_CLK_PLL_SEL_SHIFT,
+	CORE_CLK_PLL_SEL_APLL	= 0,
+	CORE_CLK_PLL_SEL_GPLL,
+	CORE_DIV_CON_SHIFT	= 0,
+	CORE_DIV_CON_MASK	= 0x0f << CORE_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL3_CON */
+	ACLK_VO_PLL_SHIFT	= 6,
+	ACLK_VO_PLL_MASK	= 0x3 << ACLK_VO_PLL_SHIFT,
+	ACLK_VO_SEL_GPLL	= 0,
+	ACLK_VO_SEL_CPLL,
+	ACLK_VO_SEL_NPLL,
+	ACLK_VO_DIV_SHIFT	= 0,
+	ACLK_VO_DIV_MASK	= 0x1f << ACLK_VO_DIV_SHIFT,
+
+	/* CRU_CLK_SEL5_CON */
+	DCLK_VOPB_SEL_SHIFT	= 14,
+	DCLK_VOPB_SEL_MASK	= 0x3 << DCLK_VOPB_SEL_SHIFT,
+	DCLK_VOPB_SEL_DIVOUT	= 0,
+	DCLK_VOPB_SEL_FRACOUT,
+	DCLK_VOPB_SEL_24M,
+	DCLK_VOPB_PLL_SEL_SHIFT	= 11,
+	DCLK_VOPB_PLL_SEL_MASK	= 0x1 << DCLK_VOPB_PLL_SEL_SHIFT,
+	DCLK_VOPB_PLL_SEL_CPLL	= 0,
+	DCLK_VOPB_PLL_SEL_NPLL,
+	DCLK_VOPB_DIV_SHIFT	= 0,
+	DCLK_VOPB_DIV_MASK	= 0xff,
+
+	/* CRU_CLK_SEL8_CON */
+	DCLK_VOPL_SEL_SHIFT	= 14,
+	DCLK_VOPL_SEL_MASK	= 0x3 << DCLK_VOPL_SEL_SHIFT,
+	DCLK_VOPL_SEL_DIVOUT	= 0,
+	DCLK_VOPL_SEL_FRACOUT,
+	DCLK_VOPL_SEL_24M,
+	DCLK_VOPL_PLL_SEL_SHIFT	= 11,
+	DCLK_VOPL_PLL_SEL_MASK	= 0x1 << DCLK_VOPL_PLL_SEL_SHIFT,
+	DCLK_VOPL_PLL_SEL_NPLL	= 0,
+	DCLK_VOPL_PLL_SEL_CPLL,
+	DCLK_VOPL_DIV_SHIFT	= 0,
+	DCLK_VOPL_DIV_MASK	= 0xff,
+
+	/* CRU_CLK_SEL14_CON */
+	PERI_PLL_SEL_SHIFT	= 15,
+	PERI_PLL_SEL_MASK	= 3 << PERI_PLL_SEL_SHIFT,
+	PERI_PLL_GPLL		= 0,
+	PERI_PLL_CPLL,
+	PERI_HCLK_DIV_SHIFT	= 8,
+	PERI_HCLK_DIV_MASK	= 0x1f << PERI_HCLK_DIV_SHIFT,
+	PERI_ACLK_DIV_SHIFT	= 0,
+	PERI_ACLK_DIV_MASK	= 0x1f << PERI_ACLK_DIV_SHIFT,
+
+	/* CRU_CLKSEL15_CON */
+	NANDC_CLK_SEL_SHIFT	= 15,
+	NANDC_CLK_SEL_MASK	= 0x1 << NANDC_CLK_SEL_SHIFT,
+	NANDC_CLK_SEL_NANDC	= 0,
+	NANDC_CLK_SEL_NANDC_DIV50,
+	NANDC_DIV50_SHIFT	= 8,
+	NANDC_DIV50_MASK	= 0x1f << NANDC_DIV50_SHIFT,
+	NANDC_PLL_SHIFT		= 6,
+	NANDC_PLL_MASK		= 0x3 << NANDC_PLL_SHIFT,
+	NANDC_SEL_GPLL		= 0,
+	NANDC_SEL_CPLL,
+	NANDC_SEL_NPLL,
+	NANDC_DIV_SHIFT		= 0,
+	NANDC_DIV_MASK		= 0x1f << NANDC_DIV_SHIFT,
+
+	/* CRU_CLKSEL20_CON */
+	EMMC_PLL_SHIFT		= 14,
+	EMMC_PLL_MASK		= 3 << EMMC_PLL_SHIFT,
+	EMMC_SEL_GPLL		= 0,
+	EMMC_SEL_CPLL,
+	EMMC_SEL_NPLL,
+	EMMC_SEL_24M,
+	EMMC_DIV_SHIFT		= 0,
+	EMMC_DIV_MASK		= 0xff << EMMC_DIV_SHIFT,
+
+	/* CRU_CLKSEL21_CON */
+	EMMC_CLK_SEL_SHIFT	= 15,
+	EMMC_CLK_SEL_MASK	= 1 << EMMC_CLK_SEL_SHIFT,
+	EMMC_CLK_SEL_EMMC	= 0,
+	EMMC_CLK_SEL_EMMC_DIV50,
+	EMMC_DIV50_SHIFT	= 0,
+	EMMC_DIV50_MASK		= 0xff << EMMC_DIV_SHIFT,
+
+	/* CRU_CLKSEL22_CON */
+	GMAC_PLL_SEL_SHIFT	= 14,
+	GMAC_PLL_SEL_MASK	= 3 << GMAC_PLL_SEL_SHIFT,
+	GMAC_PLL_SEL_GPLL	= 0,
+	GMAC_PLL_SEL_CPLL,
+	GMAC_PLL_SEL_NPLL,
+	CLK_GMAC_DIV_SHIFT	= 8,
+	CLK_GMAC_DIV_MASK	= 0x1f << CLK_GMAC_DIV_SHIFT,
+	SFC_PLL_SEL_SHIFT	= 7,
+	SFC_PLL_SEL_MASK	= 1 << SFC_PLL_SEL_SHIFT,
+	SFC_DIV_CON_SHIFT	= 0,
+	SFC_DIV_CON_MASK	= 0x7f,
+
+	/* CRU_CLK_SEL23_CON */
+	BUS_PLL_SEL_SHIFT	= 15,
+	BUS_PLL_SEL_MASK	= 1 << BUS_PLL_SEL_SHIFT,
+	BUS_PLL_SEL_GPLL	= 0,
+	BUS_PLL_SEL_CPLL,
+	BUS_ACLK_DIV_SHIFT	= 8,
+	BUS_ACLK_DIV_MASK	= 0x1f << BUS_ACLK_DIV_SHIFT,
+	RMII_CLK_SEL_SHIFT	= 7,
+	RMII_CLK_SEL_MASK	= 1 << RMII_CLK_SEL_SHIFT,
+	RMII_CLK_SEL_10M	= 0,
+	RMII_CLK_SEL_100M,
+	RMII_EXTCLK_SEL_SHIFT	= 6,
+	RMII_EXTCLK_SEL_MASK	= 1 << RMII_EXTCLK_SEL_SHIFT,
+	RMII_EXTCLK_SEL_INT	= 0,
+	RMII_EXTCLK_SEL_EXT,
+	PCLK_GMAC_DIV_SHIFT	= 0,
+	PCLK_GMAC_DIV_MASK	= 0x0f << PCLK_GMAC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL24_CON */
+	BUS_PCLK_DIV_SHIFT	= 8,
+	BUS_PCLK_DIV_MASK	= 3 << BUS_PCLK_DIV_SHIFT,
+	BUS_HCLK_DIV_SHIFT	= 0,
+	BUS_HCLK_DIV_MASK	= 0x1f << BUS_HCLK_DIV_SHIFT,
+
+	/* CRU_CLK_SEL25_CON */
+	CRYPTO_APK_SEL_SHIFT	= 14,
+	CRYPTO_APK_PLL_SEL_MASK	= 3 << CRYPTO_APK_SEL_SHIFT,
+	CRYPTO_PLL_SEL_GPLL	= 0,
+	CRYPTO_PLL_SEL_CPLL,
+	CRYPTO_PLL_SEL_NPLL	= 0,
+	CRYPTO_APK_DIV_SHIFT	= 8,
+	CRYPTO_APK_DIV_MASK	= 0x1f << CRYPTO_APK_DIV_SHIFT,
+	CRYPTO_PLL_SEL_SHIFT	= 6,
+	CRYPTO_PLL_SEL_MASK	= 3 << CRYPTO_PLL_SEL_SHIFT,
+	CRYPTO_DIV_SHIFT	= 0,
+	CRYPTO_DIV_MASK		= 0x1f << CRYPTO_DIV_SHIFT,
+
+	/* CRU_CLK_SEL30_CON */
+	CLK_I2S1_DIV_CON_MASK	= 0x7f,
+	CLK_I2S1_PLL_SEL_MASK	= 0X1 << 8,
+	CLK_I2S1_PLL_SEL_GPLL	= 0X0 << 8,
+	CLK_I2S1_PLL_SEL_NPLL	= 0X1 << 8,
+	CLK_I2S1_SEL_MASK	= 0x3 << 10,
+	CLK_I2S1_SEL_I2S1	= 0x0 << 10,
+	CLK_I2S1_SEL_FRAC	= 0x1 << 10,
+	CLK_I2S1_SEL_MCLK_IN	= 0x2 << 10,
+	CLK_I2S1_SEL_OSC	= 0x3 << 10,
+	CLK_I2S1_OUT_SEL_MASK	= 0x1 << 15,
+	CLK_I2S1_OUT_SEL_I2S1	= 0x0 << 15,
+	CLK_I2S1_OUT_SEL_OSC	= 0x1 << 15,
+
+	/* CRU_CLK_SEL31_CON */
+	CLK_I2S1_FRAC_NUMERATOR_SHIFT	= 16,
+	CLK_I2S1_FRAC_NUMERATOR_MASK	= 0xffff << 16,
+	CLK_I2S1_FRAC_DENOMINATOR_SHIFT	= 0,
+	CLK_I2S1_FRAC_DENOMINATOR_MASK	= 0xffff,
+
+	/* CRU_CLK_SEL34_CON */
+	UART1_PLL_SEL_SHIFT	= 14,
+	UART1_PLL_SEL_MASK	= 3 << UART1_PLL_SEL_SHIFT,
+	UART1_PLL_SEL_GPLL	= 0,
+	UART1_PLL_SEL_24M,
+	UART1_PLL_SEL_480M,
+	UART1_PLL_SEL_NPLL,
+	UART1_DIV_CON_SHIFT	= 0,
+	UART1_DIV_CON_MASK	= 0x1f << UART1_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL35_CON */
+	UART1_CLK_SEL_SHIFT	= 14,
+	UART1_CLK_SEL_MASK	= 3 << UART1_PLL_SEL_SHIFT,
+	UART1_CLK_SEL_UART1	= 0,
+	UART1_CLK_SEL_UART1_NP5,
+	UART1_CLK_SEL_UART1_FRAC,
+	UART1_DIVNP5_SHIFT	= 0,
+	UART1_DIVNP5_MASK	= 0x1f << UART1_DIVNP5_SHIFT,
+
+	/* CRU_CLK_SEL37_CON */
+	UART2_PLL_SEL_SHIFT	= 14,
+	UART2_PLL_SEL_MASK	= 3 << UART2_PLL_SEL_SHIFT,
+	UART2_PLL_SEL_GPLL	= 0,
+	UART2_PLL_SEL_24M,
+	UART2_PLL_SEL_480M,
+	UART2_PLL_SEL_NPLL,
+	UART2_DIV_CON_SHIFT	= 0,
+	UART2_DIV_CON_MASK	= 0x1f << UART2_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL38_CON */
+	UART2_CLK_SEL_SHIFT	= 14,
+	UART2_CLK_SEL_MASK	= 3 << UART2_PLL_SEL_SHIFT,
+	UART2_CLK_SEL_UART2	= 0,
+	UART2_CLK_SEL_UART2_NP5,
+	UART2_CLK_SEL_UART2_FRAC,
+	UART2_DIVNP5_SHIFT	= 0,
+	UART2_DIVNP5_MASK	= 0x1f << UART2_DIVNP5_SHIFT,
+
+	/* CRU_CLK_SEL46_CON */
+	UART5_PLL_SEL_SHIFT	= 14,
+	UART5_PLL_SEL_MASK	= 3 << UART5_PLL_SEL_SHIFT,
+	UART5_PLL_SEL_GPLL	= 0,
+	UART5_PLL_SEL_24M,
+	UART5_PLL_SEL_480M,
+	UART5_PLL_SEL_NPLL,
+	UART5_DIV_CON_SHIFT	= 0,
+	UART5_DIV_CON_MASK	= 0x1f << UART5_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL47_CON */
+	UART5_CLK_SEL_SHIFT	= 14,
+	UART5_CLK_SEL_MASK	= 3 << UART5_PLL_SEL_SHIFT,
+	UART5_CLK_SEL_UART5	= 0,
+	UART5_CLK_SEL_UART5_NP5,
+	UART5_CLK_SEL_UART5_FRAC,
+	UART5_DIVNP5_SHIFT	= 0,
+	UART5_DIVNP5_MASK	= 0x1f << UART5_DIVNP5_SHIFT,
+
+	/* CRU_CLK_SEL49_CON */
+	CLK_I2C_PLL_SEL_GPLL		= 0,
+	CLK_I2C_PLL_SEL_24M,
+	CLK_I2C_DIV_CON_MASK		= 0x7f,
+	CLK_I2C_PLL_SEL_MASK		= 1,
+	CLK_I2C1_PLL_SEL_SHIFT		= 15,
+	CLK_I2C1_DIV_CON_SHIFT		= 8,
+	CLK_I2C0_PLL_SEL_SHIFT		= 7,
+	CLK_I2C0_DIV_CON_SHIFT		= 0,
+
+	/* CRU_CLK_SEL50_CON */
+	CLK_I2C3_PLL_SEL_SHIFT		= 15,
+	CLK_I2C3_DIV_CON_SHIFT		= 8,
+	CLK_I2C2_PLL_SEL_SHIFT		= 7,
+	CLK_I2C2_DIV_CON_SHIFT		= 0,
+
+	/* CRU_CLK_SEL52_CON */
+	CLK_PWM_PLL_SEL_GPLL		= 0,
+	CLK_PWM_PLL_SEL_24M,
+	CLK_PWM_DIV_CON_MASK		= 0x7f,
+	CLK_PWM_PLL_SEL_MASK		= 1,
+	CLK_PWM1_PLL_SEL_SHIFT		= 15,
+	CLK_PWM1_DIV_CON_SHIFT		= 8,
+	CLK_PWM0_PLL_SEL_SHIFT		= 7,
+	CLK_PWM0_DIV_CON_SHIFT		= 0,
+
+	/* CRU_CLK_SEL53_CON */
+	CLK_SPI_PLL_SEL_GPLL		= 0,
+	CLK_SPI_PLL_SEL_24M,
+	CLK_SPI_DIV_CON_MASK		= 0x7f,
+	CLK_SPI_PLL_SEL_MASK		= 1,
+	CLK_SPI1_PLL_SEL_SHIFT		= 15,
+	CLK_SPI1_DIV_CON_SHIFT		= 8,
+	CLK_SPI0_PLL_SEL_SHIFT		= 7,
+	CLK_SPI0_DIV_CON_SHIFT		= 0,
+
+	/* CRU_CLK_SEL55_CON */
+	CLK_SARADC_DIV_CON_SHIFT	= 0,
+	CLK_SARADC_DIV_CON_MASK		= 0x7ff,
+
+	/* CRU_CLK_GATE10_CON */
+	CLK_I2S1_OUT_MCLK_PAD_MASK	= 0x1 << 9,
+	CLK_I2S1_OUT_MCLK_PAD_ENABLE	= 0x1 << 9,
+	CLK_I2S1_OUT_MCLK_PAD_DISABLE	= 0x0 << 9,
+
+	/* CRU_PMU_MODE */
+	GPLL_MODE_SHIFT			= 0,
+	GPLL_MODE_MASK			= 3 << GPLL_MODE_SHIFT,
+
+	/* CRU_PMU_CLK_SEL0_CON */
+	CLK_PMU_PCLK_DIV_SHIFT		= 0,
+	CLK_PMU_PCLK_DIV_MASK		= 0x1f << CLK_PMU_PCLK_DIV_SHIFT,
+};
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_px30.h b/arch/arm/include/asm/arch-rockchip/grf_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..c167bb42fac91584c5c4005bd70803b29236e476
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/grf_px30.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ */
+#ifndef _ASM_ARCH_GRF_px30_H
+#define _ASM_ARCH_GRF_px30_H
+
+#include <common.h>
+
+struct px30_grf {
+	unsigned int gpio1al_iomux;
+	unsigned int gpio1ah_iomux;
+	unsigned int gpio1bl_iomux;
+	unsigned int gpio1bh_iomux;
+	unsigned int gpio1cl_iomux;
+	unsigned int gpio1ch_iomux;
+	unsigned int gpio1dl_iomux;
+	unsigned int gpio1dh_iomux;
+
+	unsigned int gpio2al_iomux;
+	unsigned int gpio2ah_iomux;
+	unsigned int gpio2bl_iomux;
+	unsigned int gpio2bh_iomux;
+	unsigned int gpio2cl_iomux;
+	unsigned int gpio2ch_iomux;
+	unsigned int gpio2dl_iomux;
+	unsigned int gpio2dh_iomux;
+
+	unsigned int gpio3al_iomux;
+	unsigned int gpio3ah_iomux;
+	unsigned int gpio3bl_iomux;
+	unsigned int gpio3bh_iomux;
+	unsigned int gpio3cl_iomux;
+	unsigned int gpio3ch_iomux;
+	unsigned int gpio3dl_iomux;
+	unsigned int gpio3dh_iomux;
+
+	unsigned int gpio1a_p;
+	unsigned int gpio1b_p;
+	unsigned int gpio1c_p;
+	unsigned int gpio1d_p;
+	unsigned int gpio2a_p;
+	unsigned int gpio2b_p;
+	unsigned int gpio2c_p;
+	unsigned int gpio2d_p;
+	unsigned int gpio3a_p;
+	unsigned int gpio3b_p;
+	unsigned int gpio3c_p;
+	unsigned int gpio3d_p;
+	unsigned int gpio1a_sr;
+	unsigned int gpio1b_sr;
+	unsigned int gpio1c_sr;
+	unsigned int gpio1d_sr;
+	unsigned int gpio2a_sr;
+	unsigned int gpio2b_sr;
+	unsigned int gpio2c_sr;
+	unsigned int gpio2d_sr;
+	unsigned int gpio3a_sr;
+	unsigned int gpio3b_sr;
+	unsigned int gpio3c_sr;
+	unsigned int gpio3d_sr;
+	unsigned int gpio1a_smt;
+	unsigned int gpio1b_smt;
+	unsigned int gpio1c_smt;
+	unsigned int gpio1d_smt;
+	unsigned int gpio2a_smt;
+	unsigned int gpio2b_smt;
+	unsigned int gpio2c_smt;
+	unsigned int gpio2d_smt;
+	unsigned int gpio3a_smt;
+	unsigned int gpio3b_smt;
+	unsigned int gpio3c_smt;
+	unsigned int gpio3d_smt;
+	unsigned int gpio1a_e;
+	unsigned int gpio1b_e;
+	unsigned int gpio1c_e;
+	unsigned int gpio1d_e;
+	unsigned int gpio2a_e;
+	unsigned int gpio2b_e;
+	unsigned int gpio2c_e;
+	unsigned int gpio2d_e;
+	unsigned int gpio3a_e;
+	unsigned int gpio3b_e;
+	unsigned int gpio3c_e;
+	unsigned int gpio3d_e;
+
+	unsigned int reserved0[(0x180 - 0x11C) / 4 - 1];
+	unsigned int io_vsel;
+	unsigned int iofunc_con0;
+	unsigned int reserved1[(0x400 - 0x184) / 4 - 1];
+	unsigned int soc_con[6];
+	unsigned int reserved2[(0x480 - 0x414) / 4 - 1];
+	unsigned int soc_status0;
+	unsigned int reserved3[(0x500 - 0x480) / 4 - 1];
+	unsigned int cpu_con[3];
+	unsigned int reserved4[5];
+	unsigned int cpu_status[2];
+	unsigned int reserved5[2];
+	unsigned int soc_noc_con[2];
+	unsigned int reserved6[6];
+	unsigned int ddr_bankhash[4];
+	unsigned int reserved7[(0x700 - 0x55c) / 4 - 1];
+	unsigned int host0_con[2];
+	unsigned int reserved8[(0x880 - 0x704) / 4 - 1];
+	unsigned int otg_con3;
+	unsigned int reserved9[3];
+	unsigned int host0_status4;
+	unsigned int reserved10[(0x904 - 0x890) / 4 - 1];
+	unsigned int mac_con1;
+};
+
+check_member(px30_grf, mac_con1, 0x904);
+
+struct px30_pmugrf {
+	unsigned int gpio0a_e;
+	unsigned int gpio0b_e;
+	unsigned int gpio0c_e;
+	unsigned int gpio0d_e;
+	unsigned int gpio0a_p;
+	unsigned int gpio0b_p;
+	unsigned int gpio0c_p;
+	unsigned int gpio0d_p;
+	unsigned int gpio0al_iomux;
+	unsigned int gpio0bl_iomux;
+	unsigned int gpio0cl_iomux;
+	unsigned int gpio0dl_iomux;
+	unsigned int gpio0l_sr;
+	unsigned int gpio0h_sr;
+	unsigned int gpio0l_smt;
+	unsigned int gpio0h_smt;
+	unsigned int reserved1[(0x100 - 0x3c) / 4 - 1];
+	unsigned int soc_con[4];
+	unsigned int reserved2[(0x180 - 0x10c) / 4 - 1];
+	unsigned int pvtm_con[2];
+	unsigned int reserved3[2];
+	unsigned int pvtm_status[2];
+	unsigned int reserved4[(0x200 - 0x194) / 4 - 1];
+	unsigned int os_reg[12];
+	unsigned int reset_function_status;
+};
+
+check_member(px30_pmugrf, reset_function_status, 0x230);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
index 9220763fa7fe77f4cdcae1ef48fe8bb8d026761c..cf2a7b7d105fd3665220447051a186b7e50b0f74 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram.h
@@ -1,102 +1,86 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright (c) 2015 Google, Inc
- *
- * Copyright 2014 Rockchip Inc.
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
  */
 
-#ifndef _ASM_ARCH_RK3288_SDRAM_H__
-#define _ASM_ARCH_RK3288_SDRAM_H__
+#ifndef _ASM_ARCH_SDRAM_H
+#define _ASM_ARCH_SDRAM_H
 
-struct rk3288_sdram_channel {
-	/*
-	 * bit width in address, eg:
-	 * 8 banks using 3 bit to address,
-	 * 2 cs using 1 bit to address.
-	 */
-	u8 rank;
-	u8 col;
-	u8 bk;
-	u8 bw;
-	u8 dbw;
-	u8 row_3_4;
-	u8 cs0_row;
-	u8 cs1_row;
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
-	/*
-	 * For of-platdata, which would otherwise convert this into two
-	 * byte-swapped integers. With a size of 9 bytes, this struct will
-	 * appear in of-platdata as a byte array.
-	 *
-	 * If OF_PLATDATA enabled, need to add a dummy byte in dts.(i.e 0xff)
-	 */
-	u8 dummy;
-#endif
+enum {
+	DDR4 = 0,
+	DDR3 = 0x3,
+	LPDDR2 = 0x5,
+	LPDDR3 = 0x6,
+	LPDDR4 = 0x7,
+	UNUSED = 0xFF
 };
 
-struct rk3288_sdram_pctl_timing {
-	u32 togcnt1u;
-	u32 tinit;
-	u32 trsth;
-	u32 togcnt100n;
-	u32 trefi;
-	u32 tmrd;
-	u32 trfc;
-	u32 trp;
-	u32 trtw;
-	u32 tal;
-	u32 tcl;
-	u32 tcwl;
-	u32 tras;
-	u32 trc;
-	u32 trcd;
-	u32 trrd;
-	u32 trtp;
-	u32 twr;
-	u32 twtr;
-	u32 texsr;
-	u32 txp;
-	u32 txpdll;
-	u32 tzqcs;
-	u32 tzqcsi;
-	u32 tdqs;
-	u32 tcksre;
-	u32 tcksrx;
-	u32 tcke;
-	u32 tmod;
-	u32 trstl;
-	u32 tzqcl;
-	u32 tmrr;
-	u32 tckesr;
-	u32 tdpd;
-};
-check_member(rk3288_sdram_pctl_timing, tdpd, 0x144 - 0xc0);
+/*
+ * sys_reg2 bitfield struct
+ * [31]		row_3_4_ch1
+ * [30]		row_3_4_ch0
+ * [29:28]	chinfo
+ * [27]		rank_ch1
+ * [26:25]	col_ch1
+ * [24]		bk_ch1
+ * [23:22]	low bits of cs0_row_ch1
+ * [21:20]	low bits of cs1_row_ch1
+ * [19:18]	bw_ch1
+ * [17:16]	dbw_ch1;
+ * [15:13]	ddrtype
+ * [12]		channelnum
+ * [11]		rank_ch0
+ * [10:9]	col_ch0,
+ * [8]		bk_ch0
+ * [7:6]	low bits of cs0_row_ch0
+ * [5:4]	low bits of cs1_row_ch0
+ * [3:2]	bw_ch0
+ * [1:0]	dbw_ch0
+ */
+#define SYS_REG_DDRTYPE_SHIFT		13
+#define SYS_REG_DDRTYPE_MASK		7
+#define SYS_REG_NUM_CH_SHIFT		12
+#define SYS_REG_NUM_CH_MASK		1
+#define SYS_REG_ROW_3_4_SHIFT(ch)	(30 + (ch))
+#define SYS_REG_ROW_3_4_MASK		1
+#define SYS_REG_CHINFO_SHIFT(ch)	(28 + (ch))
+#define SYS_REG_RANK_SHIFT(ch)		(11 + (ch) * 16)
+#define SYS_REG_RANK_MASK		1
+#define SYS_REG_COL_SHIFT(ch)		(9 + (ch) * 16)
+#define SYS_REG_COL_MASK		3
+#define SYS_REG_BK_SHIFT(ch)		(8 + (ch) * 16)
+#define SYS_REG_BK_MASK			1
+#define SYS_REG_CS0_ROW_SHIFT(ch)	(6 + (ch) * 16)
+#define SYS_REG_CS0_ROW_MASK		3
+#define SYS_REG_CS1_ROW_SHIFT(ch)	(4 + (ch) * 16)
+#define SYS_REG_CS1_ROW_MASK		3
+#define SYS_REG_BW_SHIFT(ch)		(2 + (ch) * 16)
+#define SYS_REG_BW_MASK			3
+#define SYS_REG_DBW_SHIFT(ch)		((ch) * 16)
+#define SYS_REG_DBW_MASK		3
 
-struct rk3288_sdram_phy_timing {
-	u32 dtpr0;
-	u32 dtpr1;
-	u32 dtpr2;
-	u32 mr[4];
-};
+/*
+ * sys_reg3 bitfield struct
+ * [7]		high bit of cs0_row_ch1
+ * [6]		high bit of cs1_row_ch1
+ * [5]		high bit of cs0_row_ch0
+ * [4]		high bit of cs1_row_ch0
+ * [3:2]	cs1_col_ch1
+ * [1:0]	cs1_col_ch0
+ */
+#define SYS_REG_VERSION_SHIFT			28
+#define SYS_REG_VERSION_MASK			0xf
+#define SYS_REG_EXTEND_CS0_ROW_SHIFT(ch)	(5 + (ch) * 2)
+#define SYS_REG_EXTEND_CS0_ROW_MASK		1
+#define SYS_REG_EXTEND_CS1_ROW_SHIFT(ch)	(4 + (ch) * 2)
+#define SYS_REG_EXTEND_CS1_ROW_MASK		1
+#define SYS_REG_CS1_COL_SHIFT(ch)		(0 + (ch) * 2)
+#define SYS_REG_CS1_COL_MASK			3
 
-struct rk3288_base_params {
-	u32 noc_timing;
-	u32 noc_activate;
-	u32 ddrconfig;
-	u32 ddr_freq;
-	u32 dramtype;
-	/*
-	 * DDR Stride is address mapping for DRAM space
-	 * Stride	Ch 0 range	Ch1 range	Total
-	 * 0x00		0-256MB		256MB-512MB	512MB
-	 * 0x05		0-1GB		0-1GB		1GB
-	 * 0x09		0-2GB		0-2GB		2GB
-	 * 0x0d		0-4GB		0-4GB		4GB
-	 * 0x17		N/A		0-4GB		4GB
-	 * 0x1a		0-4GB		4GB-8GB		8GB
-	 */
-	u32 stride;
-	u32 odt;
-};
+/* Get sdram size decode from reg */
+size_t rockchip_sdram_size(phys_addr_t reg);
+
+/* Called by U-Boot board_init_r for Rockchip SoCs */
+int dram_init(void);
 
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_common.h b/arch/arm/include/asm/arch-rockchip/sdram_common.h
index 8027b53636ac3cf24a6db1da1c6d783667c11a25..36d31156be25f749b206a673883870e11e593615 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_common.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_common.h
@@ -1,19 +1,19 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier:     GPL-2.0+ */
 /*
- * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd
  */
 
 #ifndef _ASM_ARCH_SDRAM_COMMON_H
 #define _ASM_ARCH_SDRAM_COMMON_H
 
-enum {
-	DDR4 = 0,
-	DDR3 = 0x3,
-	LPDDR2 = 0x5,
-	LPDDR3 = 0x6,
-	LPDDR4 = 0x7,
-	UNUSED = 0xFF
-};
+#ifndef MHZ
+#define MHZ		(1000 * 1000)
+#endif
+
+#define PATTERN		(0x5aa5f00f)
+
+#define MIN(a, b)	(((a) > (b)) ? (b) : (a))
+#define MAX(a, b)	(((a) > (b)) ? (a) : (b))
 
 struct sdram_cap_info {
 	unsigned int rank;
@@ -32,6 +32,8 @@ struct sdram_cap_info {
 	unsigned int row_3_4;
 	unsigned int cs0_row;
 	unsigned int cs1_row;
+	unsigned int cs0_high16bit_row;
+	unsigned int cs1_high16bit_row;
 	unsigned int ddrconfig;
 };
 
@@ -43,8 +45,9 @@ struct sdram_base_params {
 	unsigned int odt;
 };
 
+#define DDR_SYS_REG_VERSION		(0x2)
 /*
- * sys_reg bitfield struct
+ * sys_reg2 bitfield struct
  * [31]		row_3_4_ch1
  * [30]		row_3_4_ch0
  * [29:28]	chinfo
@@ -64,49 +67,38 @@ struct sdram_base_params {
  * [5:4]	cs1_row_ch0
  * [3:2]	bw_ch0
  * [1:0]	dbw_ch0
-*/
-#define SYS_REG_DDRTYPE_SHIFT		13
-#define DDR_SYS_REG_VERSION		2
-#define SYS_REG_DDRTYPE_MASK		7
-#define SYS_REG_NUM_CH_SHIFT		12
-#define SYS_REG_NUM_CH_MASK		1
-#define SYS_REG_ROW_3_4_SHIFT(ch)	(30 + (ch))
-#define SYS_REG_ROW_3_4_MASK		1
+ */
 #define SYS_REG_ENC_ROW_3_4(n, ch)	((n) << (30 + (ch)))
-#define SYS_REG_CHINFO_SHIFT(ch)	(28 + (ch))
-#define SYS_REG_ENC_CHINFO(ch)		(1 << SYS_REG_CHINFO_SHIFT(ch))
-#define SYS_REG_ENC_DDRTYPE(n)		((n) << SYS_REG_DDRTYPE_SHIFT)
-#define SYS_REG_ENC_NUM_CH(n)		(((n) - SYS_REG_NUM_CH_MASK) << \
-					SYS_REG_NUM_CH_SHIFT)
-#define SYS_REG_RANK_SHIFT(ch)		(11 + (ch) * 16)
-#define SYS_REG_RANK_MASK		1
-#define SYS_REG_ENC_RANK(n, ch)		(((n) - SYS_REG_RANK_MASK) << \
-					 SYS_REG_RANK_SHIFT(ch))
-#define SYS_REG_COL_SHIFT(ch)		(9 + (ch) * 16)
-#define SYS_REG_COL_MASK		3
-#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << SYS_REG_COL_SHIFT(ch))
-#define SYS_REG_BK_SHIFT(ch)		(8 + (ch) * 16)
-#define SYS_REG_BK_MASK			1
+#define SYS_REG_DEC_ROW_3_4(n, ch)	(((n) >> (30 + (ch))) & 0x1)
+#define SYS_REG_ENC_CHINFO(ch)		(1 << (28 + (ch)))
+#define SYS_REG_ENC_DDRTYPE(n)		((n) << 13)
+#define SYS_REG_DEC_DDRTYPE(n)		(((n) >> 13) & 0x7)
+#define SYS_REG_ENC_NUM_CH(n)		(((n) - 1) << 12)
+#define SYS_REG_DEC_NUM_CH(n)		(1 + (((n) >> 12) & 0x1))
+#define SYS_REG_ENC_RANK(n, ch)		(((n) - 1) << (11 + ((ch) * 16)))
+#define SYS_REG_DEC_RANK(n, ch)		(1 + (((n) >> (11 + 16 * (ch))) & 0x1))
+#define SYS_REG_ENC_COL(n, ch)		(((n) - 9) << (9 + ((ch) * 16)))
+#define SYS_REG_DEC_COL(n, ch)		(9 + (((n) >> (9 + 16 * (ch))) & 0x3))
 #define SYS_REG_ENC_BK(n, ch)		(((n) == 3 ? 0 : 1) << \
-					SYS_REG_BK_SHIFT(ch))
-#define SYS_REG_CS0_ROW_SHIFT(ch)	(6 + (ch) * 16)
-#define SYS_REG_CS0_ROW_MASK		3
-#define SYS_REG_CS1_ROW_SHIFT(ch)	(4 + (ch) * 16)
-#define SYS_REG_CS1_ROW_MASK		3
-#define SYS_REG_BW_SHIFT(ch)		(2 + (ch) * 16)
-#define SYS_REG_BW_MASK			3
-#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << SYS_REG_BW_SHIFT(ch))
-#define SYS_REG_DBW_SHIFT(ch)		((ch) * 16)
-#define SYS_REG_DBW_MASK		3
-#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << SYS_REG_DBW_SHIFT(ch))
-
+						(8 + ((ch) * 16)))
+#define SYS_REG_DEC_BK(n, ch)		(3 - (((n) >> (8 + 16 * (ch))) & 0x1))
+#define SYS_REG_ENC_BW(n, ch)		((2 >> (n)) << (2 + ((ch) * 16)))
+#define SYS_REG_DEC_BW(n, ch)		(2 >> (((n) >> (2 + 16 * (ch))) & 0x3))
+#define SYS_REG_ENC_DBW(n, ch)		((2 >> (n)) << (0 + ((ch) * 16)))
+#define SYS_REG_DEC_DBW(n, ch)		(2 >> (((n) >> (0 + 16 * (ch))) & 0x3))
+/* sys reg 3 */
 #define SYS_REG_ENC_VERSION(n)		((n) << 28)
+#define SYS_REG_DEC_VERSION(n)		(((n) >> 28) & 0xf)
 #define SYS_REG_ENC_CS0_ROW(n, os_reg2, os_reg3, ch) do { \
 			(os_reg2) |= (((n) - 13) & 0x3) << (6 + 16 * (ch)); \
 			(os_reg3) |= ((((n) - 13) & 0x4) >> 2) << \
 				     (5 + 2 * (ch)); \
 		} while (0)
 
+#define SYS_REG_DEC_CS0_ROW(os_reg2, os_reg3, ch)	\
+		((((((os_reg2) >> (6 + 16 * (ch)) & 0x3) | \
+		 ((((os_reg3) >> (5 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12)
+
 #define SYS_REG_ENC_CS1_ROW(n, os_reg2, os_reg3, ch) do { \
 			(os_reg2) &= (~(0x3 << (4 + 16 * (ch)))); \
 			(os_reg3) &= (~(0x1 << (4 + 2 * (ch)))); \
@@ -115,14 +107,12 @@ struct sdram_base_params {
 				     (4 + 2 * (ch)); \
 		} while (0)
 
-#define SYS_REG_CS1_COL_SHIFT(ch)	(0 + 2 * (ch))
-#define SYS_REG_ENC_CS1_COL(n, ch)      (((n) - 9) << SYS_REG_CS1_COL_SHIFT(ch))
-
-/* Get sdram size decode from reg */
-size_t rockchip_sdram_size(phys_addr_t reg);
+#define SYS_REG_DEC_CS1_ROW(os_reg2, os_reg3, ch) \
+		((((((os_reg2) >> (4 + 16 * (ch)) & 0x3) | \
+		 ((((os_reg3) >> (4 + 2 * (ch))) & 0x1) << 2)) + 1) & 0x7) + 12)
 
-/* Called by U-Boot board_init_r for Rockchip SoCs */
-int dram_init(void);
+#define SYS_REG_ENC_CS1_COL(n, ch)	(((n) - 9) << (0 + 2 * (ch)))
+#define SYS_REG_DEC_CS1_COL(n, ch)	(9 + (((n) >> (0 + 2 * (ch))) & 0x3))
 
 #if !defined(CONFIG_RAM_ROCKCHIP_DEBUG)
 inline void sdram_print_dram_type(unsigned char dramtype)
@@ -144,4 +134,26 @@ void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
 void sdram_print_stride(unsigned int stride);
 #endif /* CONFIG_RAM_ROCKCHIP_DEBUG */
 
+void sdram_org_config(struct sdram_cap_info *cap_info,
+		      struct sdram_base_params *base,
+		      u32 *p_os_reg2, u32 *p_os_reg3, u32 channel);
+
+int sdram_detect_bw(struct sdram_cap_info *cap_info);
+int sdram_detect_cs(struct sdram_cap_info *cap_info);
+int sdram_detect_col(struct sdram_cap_info *cap_info,
+		     u32 coltmp);
+int sdram_detect_bank(struct sdram_cap_info *cap_info,
+		      u32 coltmp, u32 bktmp);
+int sdram_detect_bg(struct sdram_cap_info *cap_info,
+		    u32 coltmp);
+int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type);
+int sdram_detect_row(struct sdram_cap_info *cap_info,
+		     u32 coltmp, u32 bktmp, u32 rowtmp);
+int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
+			 u32 coltmp, u32 bktmp);
+int sdram_detect_high_row(struct sdram_cap_info *cap_info);
+int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type);
+u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type);
+void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n);
+
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_msch.h b/arch/arm/include/asm/arch-rockchip/sdram_msch.h
new file mode 100644
index 0000000000000000000000000000000000000000..cfb3d9cc86983db7a0e9b858ad58ff2b7a57c00d
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_msch.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_MSCH_H
+#define _ASM_ARCH_SDRAM_MSCH_H
+
+union noc_ddrtiminga0 {
+	u32 d32;
+	struct {
+		unsigned acttoact : 6;
+		unsigned reserved0 : 2;
+		unsigned rdtomiss : 6;
+		unsigned reserved1 : 2;
+		unsigned wrtomiss : 6;
+		unsigned reserved2 : 2;
+		unsigned readlatency : 8;
+	} b;
+};
+
+union noc_ddrtimingb0 {
+	u32 d32;
+	struct {
+		unsigned rdtowr : 5;
+		unsigned reserved0 : 3;
+		unsigned wrtord : 5;
+		unsigned reserved1 : 3;
+		unsigned rrd : 4;
+		unsigned reserved2 : 4;
+		unsigned faw : 6;
+		unsigned reserved3 : 2;
+	} b;
+};
+
+union noc_ddrtimingc0 {
+	u32 d32;
+	struct {
+		unsigned burstpenalty : 4;
+		unsigned reserved0 : 4;
+		unsigned wrtomwr : 6;
+		unsigned reserved1 : 18;
+	} b;
+};
+
+union noc_devtodev0 {
+	u32 d32;
+	struct {
+		unsigned busrdtord : 3;
+		unsigned reserved0 : 1;
+		unsigned busrdtowr : 3;
+		unsigned reserved1 : 1;
+		unsigned buswrtord : 3;
+		unsigned reserved2 : 1;
+		unsigned buswrtowr : 3;
+		unsigned reserved3 : 17;
+	} b;
+};
+
+union noc_ddrmode {
+	u32 d32;
+	struct {
+		unsigned autoprecharge : 1;
+		unsigned bypassfiltering : 1;
+		unsigned fawbank : 1;
+		unsigned burstsize : 2;
+		unsigned mwrsize : 2;
+		unsigned reserved2 : 1;
+		unsigned forceorder : 8;
+		unsigned forceorderstate : 8;
+		unsigned reserved3 : 8;
+	} b;
+};
+
+union noc_ddr4timing {
+	u32 d32;
+	struct {
+		unsigned ccdl : 3;
+		unsigned wrtordl : 5;
+		unsigned rrdl : 4;
+		unsigned reserved1 : 20;
+	} b;
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..97818817389e3448e29c30ac8c472d6f728900dd
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_PCTL_PX30_H
+#define _ASM_ARCH_SDRAM_PCTL_PX30_H
+#include <asm/arch-rockchip/sdram_common.h>
+
+struct ddr_pctl_regs {
+	u32 pctl[30][2];
+};
+
+/* ddr pctl registers define */
+#define DDR_PCTL2_MSTR			0x0
+#define DDR_PCTL2_STAT			0x4
+#define DDR_PCTL2_MSTR1			0x8
+#define DDR_PCTL2_MRCTRL0		0x10
+#define DDR_PCTL2_MRCTRL1		0x14
+#define DDR_PCTL2_MRSTAT		0x18
+#define DDR_PCTL2_MRCTRL2		0x1c
+#define DDR_PCTL2_DERATEEN		0x20
+#define DDR_PCTL2_DERATEINT		0x24
+#define DDR_PCTL2_PWRCTL		0x30
+#define DDR_PCTL2_PWRTMG		0x34
+#define DDR_PCTL2_HWLPCTL		0x38
+#define DDR_PCTL2_RFSHCTL0		0x50
+#define DDR_PCTL2_RFSHCTL1		0x54
+#define DDR_PCTL2_RFSHCTL2		0x58
+#define DDR_PCTL2_RFSHCTL4		0x5c
+#define DDR_PCTL2_RFSHCTL3		0x60
+#define DDR_PCTL2_RFSHTMG		0x64
+#define DDR_PCTL2_RFSHTMG1		0x68
+#define DDR_PCTL2_RFSHCTL5		0x6c
+#define DDR_PCTL2_INIT0			0xd0
+#define DDR_PCTL2_INIT1			0xd4
+#define DDR_PCTL2_INIT2			0xd8
+#define DDR_PCTL2_INIT3			0xdc
+#define DDR_PCTL2_INIT4			0xe0
+#define DDR_PCTL2_INIT5			0xe4
+#define DDR_PCTL2_INIT6			0xe8
+#define DDR_PCTL2_INIT7			0xec
+#define DDR_PCTL2_DIMMCTL		0xf0
+#define DDR_PCTL2_RANKCTL		0xf4
+#define DDR_PCTL2_CHCTL			0xfc
+#define DDR_PCTL2_DRAMTMG0		0x100
+#define DDR_PCTL2_DRAMTMG1		0x104
+#define DDR_PCTL2_DRAMTMG2		0x108
+#define DDR_PCTL2_DRAMTMG3		0x10c
+#define DDR_PCTL2_DRAMTMG4		0x110
+#define DDR_PCTL2_DRAMTMG5		0x114
+#define DDR_PCTL2_DRAMTMG6		0x118
+#define DDR_PCTL2_DRAMTMG7		0x11c
+#define DDR_PCTL2_DRAMTMG8		0x120
+#define DDR_PCTL2_DRAMTMG9		0x124
+#define DDR_PCTL2_DRAMTMG10		0x128
+#define DDR_PCTL2_DRAMTMG11		0x12c
+#define DDR_PCTL2_DRAMTMG12		0x130
+#define DDR_PCTL2_DRAMTMG13		0x134
+#define DDR_PCTL2_DRAMTMG14		0x138
+#define DDR_PCTL2_DRAMTMG15		0x13c
+#define DDR_PCTL2_DRAMTMG16		0x140
+#define DDR_PCTL2_ZQCTL0		0x180
+#define DDR_PCTL2_ZQCTL1		0x184
+#define DDR_PCTL2_ZQCTL2		0x188
+#define DDR_PCTL2_ZQSTAT		0x18c
+#define DDR_PCTL2_DFITMG0		0x190
+#define DDR_PCTL2_DFITMG1		0x194
+#define DDR_PCTL2_DFILPCFG0		0x198
+#define DDR_PCTL2_DFILPCFG1		0x19c
+#define DDR_PCTL2_DFIUPD0		0x1a0
+#define DDR_PCTL2_DFIUPD1		0x1a4
+#define DDR_PCTL2_DFIUPD2		0x1a8
+#define DDR_PCTL2_DFIMISC		0x1b0
+#define DDR_PCTL2_DFITMG2		0x1b4
+#define DDR_PCTL2_DFITMG3		0x1b8
+#define DDR_PCTL2_DFISTAT		0x1bc
+#define DDR_PCTL2_DBICTL		0x1c0
+#define DDR_PCTL2_ADDRMAP0		0x200
+#define DDR_PCTL2_ADDRMAP1		0x204
+#define DDR_PCTL2_ADDRMAP2		0x208
+#define DDR_PCTL2_ADDRMAP3		0x20c
+#define DDR_PCTL2_ADDRMAP4		0x210
+#define DDR_PCTL2_ADDRMAP5		0x214
+#define DDR_PCTL2_ADDRMAP6		0x218
+#define DDR_PCTL2_ADDRMAP7		0x21c
+#define DDR_PCTL2_ADDRMAP8		0x220
+#define DDR_PCTL2_ADDRMAP9		0x224
+#define DDR_PCTL2_ADDRMAP10		0x228
+#define DDR_PCTL2_ADDRMAP11		0x22c
+#define DDR_PCTL2_ODTCFG		0x240
+#define DDR_PCTL2_ODTMAP		0x244
+#define DDR_PCTL2_SCHED			0x250
+#define DDR_PCTL2_SCHED1		0x254
+#define DDR_PCTL2_PERFHPR1		0x25c
+#define DDR_PCTL2_PERFLPR1		0x264
+#define DDR_PCTL2_PERFWR1		0x26c
+#define DDR_PCTL2_DQMAP0		0x280
+#define DDR_PCTL2_DQMAP1		0x284
+#define DDR_PCTL2_DQMAP2		0x288
+#define DDR_PCTL2_DQMAP3		0x28c
+#define DDR_PCTL2_DQMAP4		0x290
+#define DDR_PCTL2_DQMAP5		0x294
+#define DDR_PCTL2_DBG0			0x300
+#define DDR_PCTL2_DBG1			0x304
+#define DDR_PCTL2_DBGCAM		0x308
+#define DDR_PCTL2_DBGCMD		0x30c
+#define DDR_PCTL2_DBGSTAT		0x310
+#define DDR_PCTL2_SWCTL			0x320
+#define DDR_PCTL2_SWSTAT		0x324
+#define DDR_PCTL2_POISONCFG		0x36c
+#define DDR_PCTL2_POISONSTAT		0x370
+#define DDR_PCTL2_ADVECCINDEX		0x374
+#define DDR_PCTL2_ADVECCSTAT		0x378
+#define DDR_PCTL2_PSTAT			0x3fc
+#define DDR_PCTL2_PCCFG			0x400
+#define DDR_PCTL2_PCFGR_n		0x404
+#define DDR_PCTL2_PCFGW_n		0x408
+#define DDR_PCTL2_PCTRL_n		0x490
+
+/* PCTL2_MRSTAT */
+#define MR_WR_BUSY			BIT(0)
+
+void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num);
+int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
+		  u32 dramtype);
+int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate,
+		      u32 dramtype);
+
+u32 pctl_dis_zqcs_aref(void __iomem *pctl_base);
+void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq);
+
+u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs,
+			       struct sdram_cap_info *cap_info,
+			       u32 dram_type);
+int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs,
+	     u32 sr_idle, u32 pd_idle);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..c75a633c919ebb3147ea78925a4b65c4d1f18653
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_PHY_PX30_H
+#define _ASM_ARCH_SDRAM_PHY_PX30_H
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_phy_ron_rtt_px30.h>
+
+struct ddr_phy_regs {
+	u32 phy[5][2];
+};
+
+#define PHY_REG(base, n)		((base) + 4 * (n))
+
+/* PHY_REG0 */
+#define DIGITAL_DERESET			BIT(3)
+#define ANALOG_DERESET			BIT(2)
+#define DIGITAL_RESET			(0 << 3)
+#define ANALOG_RESET			(0 << 2)
+
+/* PHY_REG1 */
+#define PHY_DDR2			(0)
+#define PHY_LPDDR2			(1)
+#define PHY_DDR3			(2)
+#define PHY_LPDDR3			(3)
+#define PHY_DDR4			(4)
+#define PHY_BL_4			(0 << 2)
+#define PHY_BL_8			BIT(2)
+
+/* PHY_REG2 */
+#define PHY_DTT_EN			BIT(0)
+#define PHY_DTT_DISB			(0 << 0)
+#define PHY_WRITE_LEVELING_EN		BIT(2)
+#define PHY_WRITE_LEVELING_DISB		(0 << 2)
+#define PHY_SELECT_CS0			(2)
+#define PHY_SELECT_CS1			(1)
+#define PHY_SELECT_CS0_1		(0)
+#define PHY_WRITE_LEVELING_SELECTCS(n)	((n) << 6)
+#define PHY_DATA_TRAINING_SELECTCS(n)	((n) << 4)
+
+struct ddr_phy_skew {
+	u32 a0_a1_skew[15];
+	u32 cs0_dm0_skew[11];
+	u32 cs0_dm1_skew[11];
+	u32 cs0_dm2_skew[11];
+	u32 cs0_dm3_skew[11];
+	u32 cs1_dm0_skew[11];
+	u32 cs1_dm1_skew[11];
+	u32 cs1_dm2_skew[11];
+	u32 cs1_dm3_skew[11];
+};
+
+void phy_soft_reset(void __iomem *phy_base);
+void phy_dram_set_bw(void __iomem *phy_base, u32 bw);
+void phy_cfg(void __iomem *phy_base,
+	     struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
+	     struct sdram_base_params *base, u32 bw);
+int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c15232047cd58eb718b2fab9cd448d92fcbbad2
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H
+#define _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H
+
+#define PHY_DDR3_RON_RTT_DISABLE	(0)
+#define PHY_DDR3_RON_RTT_451ohm		(1)
+#define PHY_DDR3_RON_RTT_225ohm		(2)
+#define PHY_DDR3_RON_RTT_150ohm		(3)
+#define PHY_DDR3_RON_RTT_112ohm		(4)
+#define PHY_DDR3_RON_RTT_90ohm		(5)
+#define PHY_DDR3_RON_RTT_75ohm		(6)
+#define PHY_DDR3_RON_RTT_64ohm		(7)
+#define PHY_DDR3_RON_RTT_56ohm		(16)
+#define PHY_DDR3_RON_RTT_50ohm		(17)
+#define PHY_DDR3_RON_RTT_45ohm		(18)
+#define PHY_DDR3_RON_RTT_41ohm		(19)
+#define PHY_DDR3_RON_RTT_37ohm		(20)
+#define PHY_DDR3_RON_RTT_34ohm		(21)
+#define PHY_DDR3_RON_RTT_33ohm		(22)
+#define PHY_DDR3_RON_RTT_30ohm		(23)
+#define PHY_DDR3_RON_RTT_28ohm		(24)
+#define PHY_DDR3_RON_RTT_26ohm		(25)
+#define PHY_DDR3_RON_RTT_25ohm		(26)
+#define PHY_DDR3_RON_RTT_23ohm		(27)
+#define PHY_DDR3_RON_RTT_22ohm		(28)
+#define PHY_DDR3_RON_RTT_21ohm		(29)
+#define PHY_DDR3_RON_RTT_20ohm		(30)
+#define PHY_DDR3_RON_RTT_19ohm		(31)
+
+#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE	(0)
+#define PHY_DDR4_LPDDR3_RON_RTT_480ohm	(1)
+#define PHY_DDR4_LPDDR3_RON_RTT_240ohm	(2)
+#define PHY_DDR4_LPDDR3_RON_RTT_160ohm	(3)
+#define PHY_DDR4_LPDDR3_RON_RTT_120ohm	(4)
+#define PHY_DDR4_LPDDR3_RON_RTT_96ohm	(5)
+#define PHY_DDR4_LPDDR3_RON_RTT_80ohm	(6)
+#define PHY_DDR4_LPDDR3_RON_RTT_68ohm	(7)
+#define PHY_DDR4_LPDDR3_RON_RTT_60ohm	(16)
+#define PHY_DDR4_LPDDR3_RON_RTT_53ohm	(17)
+#define PHY_DDR4_LPDDR3_RON_RTT_48ohm	(18)
+#define PHY_DDR4_LPDDR3_RON_RTT_43ohm	(19)
+#define PHY_DDR4_LPDDR3_RON_RTT_40ohm	(20)
+#define PHY_DDR4_LPDDR3_RON_RTT_37ohm	(21)
+#define PHY_DDR4_LPDDR3_RON_RTT_34ohm	(22)
+#define PHY_DDR4_LPDDR3_RON_RTT_32ohm	(23)
+#define PHY_DDR4_LPDDR3_RON_RTT_30ohm	(24)
+#define PHY_DDR4_LPDDR3_RON_RTT_28ohm	(25)
+#define PHY_DDR4_LPDDR3_RON_RTT_26ohm	(26)
+#define PHY_DDR4_LPDDR3_RON_RTT_25ohm	(27)
+#define PHY_DDR4_LPDDR3_RON_RTT_24ohm	(28)
+#define PHY_DDR4_LPDDR3_RON_RTT_22ohm	(29)
+#define PHY_DDR4_LPDDR3_RON_RTT_21ohm	(30)
+#define PHY_DDR4_LPDDR3_RON_RTT_20ohm	(31)
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ab8e97ae1df92e02df4f85721bfa99c7346ea90
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_px30.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_PX30_H
+#define _ASM_ARCH_SDRAM_PX30_H
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_msch.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+#include <asm/arch-rockchip/sdram_phy_px30.h>
+#include <asm/arch-rockchip/sdram_phy_ron_rtt_px30.h>
+
+#define SR_IDLE				93
+#define PD_IDLE				13
+
+/* PMUGRF */
+#define PMUGRF_OS_REG0			(0x200)
+#define PMUGRF_OS_REG(n)		(PMUGRF_OS_REG0 + (n) * 4)
+
+/* DDR GRF */
+#define DDR_GRF_CON(n)			(0 + (n) * 4)
+#define DDR_GRF_STATUS_BASE		(0X100)
+#define DDR_GRF_STATUS(n)		(DDR_GRF_STATUS_BASE + (n) * 4)
+#define DDR_GRF_LP_CON			(0x20)
+
+#define SPLIT_MODE_32_L16_VALID		(0)
+#define SPLIT_MODE_32_H16_VALID		(1)
+#define SPLIT_MODE_16_L8_VALID		(2)
+#define SPLIT_MODE_16_H8_VALID		(3)
+
+#define DDR_GRF_SPLIT_CON		(0x8)
+#define SPLIT_MODE_MASK			(0x3)
+#define SPLIT_MODE_OFFSET		(9)
+#define SPLIT_BYPASS_MASK		(1)
+#define SPLIT_BYPASS_OFFSET		(8)
+#define SPLIT_SIZE_MASK			(0xff)
+#define SPLIT_SIZE_OFFSET		(0)
+
+/* CRU define */
+/* CRU_PLL_CON0 */
+#define PB(n)				((0x1 << (15 + 16)) | ((n) << 15))
+#define POSTDIV1(n)			((0x7 << (12 + 16)) | ((n) << 12))
+#define FBDIV(n)			((0xFFF << 16) | (n))
+
+/* CRU_PLL_CON1 */
+#define RSTMODE(n)			((0x1 << (15 + 16)) | ((n) << 15))
+#define RST(n)				((0x1 << (14 + 16)) | ((n) << 14))
+#define PD(n)				((0x1 << (13 + 16)) | ((n) << 13))
+#define DSMPD(n)			((0x1 << (12 + 16)) | ((n) << 12))
+#define LOCK(n)				(((n) >> 10) & 0x1)
+#define POSTDIV2(n)			((0x7 << (6 + 16)) | ((n) << 6))
+#define REFDIV(n)			((0x3F << 16) | (n))
+
+/* CRU_MODE */
+#define CLOCK_FROM_XIN_OSC		(0)
+#define CLOCK_FROM_PLL			(1)
+#define CLOCK_FROM_RTC_32K		(2)
+#define DPLL_MODE(n)			((0x3 << (4 + 16)) | ((n) << 4))
+
+/* CRU_SOFTRESET_CON1 */
+#define upctl2_psrstn_req(n)		(((0x1 << 6) << 16) | ((n) << 6))
+#define upctl2_asrstn_req(n)		(((0x1 << 5) << 16) | ((n) << 5))
+#define upctl2_srstn_req(n)		(((0x1 << 4) << 16) | ((n) << 4))
+
+/* CRU_SOFTRESET_CON2 */
+#define ddrphy_psrstn_req(n)		(((0x1 << 2) << 16) | ((n) << 2))
+#define ddrphy_srstn_req(n)		(((0x1 << 0) << 16) | ((n) << 0))
+
+/* CRU register */
+#define CRU_PLL_CON(pll_id, n)		((pll_id)  * 0x20 + (n) * 4)
+#define CRU_MODE			(0xa0)
+#define CRU_GLB_CNT_TH			(0xb0)
+#define CRU_CLKSEL_CON_BASE		0x100
+#define CRU_CLKSELS_CON(i)		(CRU_CLKSEL_CON_BASE + ((i) * 4))
+#define CRU_CLKGATE_CON_BASE		0x200
+#define CRU_CLKGATE_CON(i)		(CRU_CLKGATE_CON_BASE + ((i) * 4))
+#define CRU_CLKSFTRST_CON_BASE		0x300
+#define CRU_CLKSFTRST_CON(i)		(CRU_CLKSFTRST_CON_BASE + ((i) * 4))
+
+struct px30_ddr_grf_regs {
+	u32 ddr_grf_con[4];
+	u32 reserved1[(0x20 - 0x10) / 4];
+	u32 ddr_grf_lp_con;
+	u32 reserved2[(0x100 - 0x24) / 4];
+	u32 ddr_grf_status[11];
+};
+
+struct msch_regs {
+	u32 coreid;
+	u32 revisionid;
+	u32 deviceconf;
+	u32 devicesize;
+	u32 ddrtiminga0;
+	u32 ddrtimingb0;
+	u32 ddrtimingc0;
+	u32 devtodev0;
+	u32 reserved1[(0x110 - 0x20) / 4];
+	u32 ddrmode;
+	u32 ddr4timing;
+	u32 reserved2[(0x1000 - 0x118) / 4];
+	u32 agingx0;
+	u32 reserved3[(0x1040 - 0x1004) / 4];
+	u32 aging0;
+	u32 aging1;
+	u32 aging2;
+	u32 aging3;
+};
+
+struct sdram_msch_timings {
+	union noc_ddrtiminga0 ddrtiminga0;
+	union noc_ddrtimingb0 ddrtimingb0;
+	union noc_ddrtimingc0 ddrtimingc0;
+	union noc_devtodev0 devtodev0;
+	union noc_ddrmode ddrmode;
+	union noc_ddr4timing ddr4timing;
+	u32 agingx0;
+};
+
+struct px30_sdram_channel {
+	struct sdram_cap_info cap_info;
+	struct sdram_msch_timings noc_timings;
+};
+
+struct px30_sdram_params {
+	struct px30_sdram_channel ch;
+	struct sdram_base_params base;
+	struct ddr_pctl_regs pctl_regs;
+	struct ddr_phy_regs phy_regs;
+	struct ddr_phy_skew *skew;
+};
+
+int sdram_init(void);
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3288.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3288.h
new file mode 100644
index 0000000000000000000000000000000000000000..9220763fa7fe77f4cdcae1ef48fe8bb8d026761c
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3288.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * Copyright 2014 Rockchip Inc.
+ */
+
+#ifndef _ASM_ARCH_RK3288_SDRAM_H__
+#define _ASM_ARCH_RK3288_SDRAM_H__
+
+struct rk3288_sdram_channel {
+	/*
+	 * bit width in address, eg:
+	 * 8 banks using 3 bit to address,
+	 * 2 cs using 1 bit to address.
+	 */
+	u8 rank;
+	u8 col;
+	u8 bk;
+	u8 bw;
+	u8 dbw;
+	u8 row_3_4;
+	u8 cs0_row;
+	u8 cs1_row;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	/*
+	 * For of-platdata, which would otherwise convert this into two
+	 * byte-swapped integers. With a size of 9 bytes, this struct will
+	 * appear in of-platdata as a byte array.
+	 *
+	 * If OF_PLATDATA enabled, need to add a dummy byte in dts.(i.e 0xff)
+	 */
+	u8 dummy;
+#endif
+};
+
+struct rk3288_sdram_pctl_timing {
+	u32 togcnt1u;
+	u32 tinit;
+	u32 trsth;
+	u32 togcnt100n;
+	u32 trefi;
+	u32 tmrd;
+	u32 trfc;
+	u32 trp;
+	u32 trtw;
+	u32 tal;
+	u32 tcl;
+	u32 tcwl;
+	u32 tras;
+	u32 trc;
+	u32 trcd;
+	u32 trrd;
+	u32 trtp;
+	u32 twr;
+	u32 twtr;
+	u32 texsr;
+	u32 txp;
+	u32 txpdll;
+	u32 tzqcs;
+	u32 tzqcsi;
+	u32 tdqs;
+	u32 tcksre;
+	u32 tcksrx;
+	u32 tcke;
+	u32 tmod;
+	u32 trstl;
+	u32 tzqcl;
+	u32 tmrr;
+	u32 tckesr;
+	u32 tdpd;
+};
+check_member(rk3288_sdram_pctl_timing, tdpd, 0x144 - 0xc0);
+
+struct rk3288_sdram_phy_timing {
+	u32 dtpr0;
+	u32 dtpr1;
+	u32 dtpr2;
+	u32 mr[4];
+};
+
+struct rk3288_base_params {
+	u32 noc_timing;
+	u32 noc_activate;
+	u32 ddrconfig;
+	u32 ddr_freq;
+	u32 dramtype;
+	/*
+	 * DDR Stride is address mapping for DRAM space
+	 * Stride	Ch 0 range	Ch1 range	Total
+	 * 0x00		0-256MB		256MB-512MB	512MB
+	 * 0x05		0-1GB		0-1GB		1GB
+	 * 0x09		0-2GB		0-2GB		2GB
+	 * 0x0d		0-4GB		0-4GB		4GB
+	 * 0x17		N/A		0-4GB		4GB
+	 * 0x1a		0-4GB		4GB-8GB		8GB
+	 */
+	u32 stride;
+	u32 odt;
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h
index 11411ead10bde5ce458023124e290e25e36e47db..10923505d6e112c9f3eff94c49c61e6b191bd5a3 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h
@@ -6,197 +6,14 @@
 
 #ifndef _ASM_ARCH_SDRAM_RK3328_H
 #define _ASM_ARCH_SDRAM_RK3328_H
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+#include <asm/arch-rockchip/sdram_phy_px30.h>
+#include <asm/arch-rockchip/sdram_phy_ron_rtt_px30.h>
 
 #define SR_IDLE		93
 #define PD_IDLE		13
 #define SDRAM_ADDR	0x00000000
-#define PATTERN		(0x5aa5f00f)
-
-/* ddr pctl registers define */
-#define DDR_PCTL2_MSTR			0x0
-#define DDR_PCTL2_STAT			0x4
-#define DDR_PCTL2_MSTR1			0x8
-#define DDR_PCTL2_MRCTRL0		0x10
-#define DDR_PCTL2_MRCTRL1		0x14
-#define DDR_PCTL2_MRSTAT		0x18
-#define DDR_PCTL2_MRCTRL2		0x1c
-#define DDR_PCTL2_DERATEEN		0x20
-#define DDR_PCTL2_DERATEINT		0x24
-#define DDR_PCTL2_PWRCTL		0x30
-#define DDR_PCTL2_PWRTMG		0x34
-#define DDR_PCTL2_HWLPCTL		0x38
-#define DDR_PCTL2_RFSHCTL0		0x50
-#define DDR_PCTL2_RFSHCTL1		0x54
-#define DDR_PCTL2_RFSHCTL2		0x58
-#define DDR_PCTL2_RFSHCTL4		0x5c
-#define DDR_PCTL2_RFSHCTL3		0x60
-#define DDR_PCTL2_RFSHTMG		0x64
-#define DDR_PCTL2_RFSHTMG1		0x68
-#define DDR_PCTL2_RFSHCTL5		0x6c
-#define DDR_PCTL2_INIT0			0xd0
-#define DDR_PCTL2_INIT1			0xd4
-#define DDR_PCTL2_INIT2			0xd8
-#define DDR_PCTL2_INIT3			0xdc
-#define DDR_PCTL2_INIT4			0xe0
-#define DDR_PCTL2_INIT5			0xe4
-#define DDR_PCTL2_INIT6			0xe8
-#define DDR_PCTL2_INIT7			0xec
-#define DDR_PCTL2_DIMMCTL		0xf0
-#define DDR_PCTL2_RANKCTL		0xf4
-#define DDR_PCTL2_CHCTL			0xfc
-#define DDR_PCTL2_DRAMTMG0		0x100
-#define DDR_PCTL2_DRAMTMG1		0x104
-#define DDR_PCTL2_DRAMTMG2		0x108
-#define DDR_PCTL2_DRAMTMG3		0x10c
-#define DDR_PCTL2_DRAMTMG4		0x110
-#define DDR_PCTL2_DRAMTMG5		0x114
-#define DDR_PCTL2_DRAMTMG6		0x118
-#define DDR_PCTL2_DRAMTMG7		0x11c
-#define DDR_PCTL2_DRAMTMG8		0x120
-#define DDR_PCTL2_DRAMTMG9		0x124
-#define DDR_PCTL2_DRAMTMG10		0x128
-#define DDR_PCTL2_DRAMTMG11		0x12c
-#define DDR_PCTL2_DRAMTMG12		0x130
-#define DDR_PCTL2_DRAMTMG13		0x134
-#define DDR_PCTL2_DRAMTMG14		0x138
-#define DDR_PCTL2_DRAMTMG15		0x13c
-#define DDR_PCTL2_DRAMTMG16		0x140
-#define DDR_PCTL2_ZQCTL0		0x180
-#define DDR_PCTL2_ZQCTL1		0x184
-#define DDR_PCTL2_ZQCTL2		0x188
-#define DDR_PCTL2_ZQSTAT		0x18c
-#define DDR_PCTL2_DFITMG0		0x190
-#define DDR_PCTL2_DFITMG1		0x194
-#define DDR_PCTL2_DFILPCFG0		0x198
-#define DDR_PCTL2_DFILPCFG1		0x19c
-#define DDR_PCTL2_DFIUPD0		0x1a0
-#define DDR_PCTL2_DFIUPD1		0x1a4
-#define DDR_PCTL2_DFIUPD2		0x1a8
-#define DDR_PCTL2_DFIMISC		0x1b0
-#define DDR_PCTL2_DFITMG2		0x1b4
-#define DDR_PCTL2_DFITMG3		0x1b8
-#define DDR_PCTL2_DFISTAT		0x1bc
-#define DDR_PCTL2_DBICTL		0x1c0
-#define DDR_PCTL2_ADDRMAP0		0x200
-#define DDR_PCTL2_ADDRMAP1		0x204
-#define DDR_PCTL2_ADDRMAP2		0x208
-#define DDR_PCTL2_ADDRMAP3		0x20c
-#define DDR_PCTL2_ADDRMAP4		0x210
-#define DDR_PCTL2_ADDRMAP5		0x214
-#define DDR_PCTL2_ADDRMAP6		0x218
-#define DDR_PCTL2_ADDRMAP7		0x21c
-#define DDR_PCTL2_ADDRMAP8		0x220
-#define DDR_PCTL2_ADDRMAP9		0x224
-#define DDR_PCTL2_ADDRMAP10		0x228
-#define DDR_PCTL2_ADDRMAP11		0x22c
-#define DDR_PCTL2_ODTCFG		0x240
-#define DDR_PCTL2_ODTMAP		0x244
-#define DDR_PCTL2_SCHED			0x250
-#define DDR_PCTL2_SCHED1		0x254
-#define DDR_PCTL2_PERFHPR1		0x25c
-#define DDR_PCTL2_PERFLPR1		0x264
-#define DDR_PCTL2_PERFWR1		0x26c
-#define DDR_PCTL2_DQMAP0		0x280
-#define DDR_PCTL2_DQMAP1		0x284
-#define DDR_PCTL2_DQMAP2		0x288
-#define DDR_PCTL2_DQMAP3		0x28c
-#define DDR_PCTL2_DQMAP4		0x290
-#define DDR_PCTL2_DQMAP5		0x294
-#define DDR_PCTL2_DBG0			0x300
-#define DDR_PCTL2_DBG1			0x304
-#define DDR_PCTL2_DBGCAM		0x308
-#define DDR_PCTL2_DBGCMD		0x30c
-#define DDR_PCTL2_DBGSTAT		0x310
-#define DDR_PCTL2_SWCTL			0x320
-#define DDR_PCTL2_SWSTAT		0x324
-#define DDR_PCTL2_POISONCFG		0x36c
-#define DDR_PCTL2_POISONSTAT		0x370
-#define DDR_PCTL2_ADVECCINDEX		0x374
-#define DDR_PCTL2_ADVECCSTAT		0x378
-#define DDR_PCTL2_PSTAT			0x3fc
-#define DDR_PCTL2_PCCFG			0x400
-#define DDR_PCTL2_PCFGR_n		0x404
-#define DDR_PCTL2_PCFGW_n		0x408
-#define DDR_PCTL2_PCTRL_n		0x490
-
-/* PCTL2_MRSTAT */
-#define MR_WR_BUSY			BIT(0)
-
-/* PHY_REG0 */
-#define DIGITAL_DERESET			BIT(3)
-#define ANALOG_DERESET			BIT(2)
-#define DIGITAL_RESET			(0 << 3)
-#define ANALOG_RESET			(0 << 2)
-
-/* PHY_REG1 */
-#define PHY_DDR2			(0)
-#define PHY_LPDDR2			(1)
-#define PHY_DDR3			(2)
-#define PHY_LPDDR3			(3)
-#define PHY_DDR4			(4)
-#define PHY_BL_4			(0 << 2)
-#define PHY_BL_8			BIT(2)
-
-/* PHY_REG2 */
-#define PHY_DTT_EN			BIT(0)
-#define PHY_DTT_DISB			(0 << 0)
-#define PHY_WRITE_LEVELING_EN		BIT(2)
-#define PHY_WRITE_LEVELING_DISB		(0 << 2)
-#define PHY_SELECT_CS0			(2)
-#define PHY_SELECT_CS1			(1)
-#define PHY_SELECT_CS0_1		(0)
-#define PHY_WRITE_LEVELING_SELECTCS(n)	(n << 6)
-#define PHY_DATA_TRAINING_SELECTCS(n)	(n << 4)
-
-#define PHY_DDR3_RON_RTT_DISABLE	(0)
-#define PHY_DDR3_RON_RTT_451ohm		(1)
-#define PHY_DDR3_RON_RTT_225ohm		(2)
-#define PHY_DDR3_RON_RTT_150ohm		(3)
-#define PHY_DDR3_RON_RTT_112ohm		(4)
-#define PHY_DDR3_RON_RTT_90ohm		(5)
-#define PHY_DDR3_RON_RTT_75ohm		(6)
-#define PHY_DDR3_RON_RTT_64ohm		(7)
-#define PHY_DDR3_RON_RTT_56ohm		(16)
-#define PHY_DDR3_RON_RTT_50ohm		(17)
-#define PHY_DDR3_RON_RTT_45ohm		(18)
-#define PHY_DDR3_RON_RTT_41ohm		(19)
-#define PHY_DDR3_RON_RTT_37ohm		(20)
-#define PHY_DDR3_RON_RTT_34ohm		(21)
-#define PHY_DDR3_RON_RTT_33ohm		(22)
-#define PHY_DDR3_RON_RTT_30ohm		(23)
-#define PHY_DDR3_RON_RTT_28ohm		(24)
-#define PHY_DDR3_RON_RTT_26ohm		(25)
-#define PHY_DDR3_RON_RTT_25ohm		(26)
-#define PHY_DDR3_RON_RTT_23ohm		(27)
-#define PHY_DDR3_RON_RTT_22ohm		(28)
-#define PHY_DDR3_RON_RTT_21ohm		(29)
-#define PHY_DDR3_RON_RTT_20ohm		(30)
-#define PHY_DDR3_RON_RTT_19ohm		(31)
-
-#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE	(0)
-#define PHY_DDR4_LPDDR3_RON_RTT_480ohm	(1)
-#define PHY_DDR4_LPDDR3_RON_RTT_240ohm	(2)
-#define PHY_DDR4_LPDDR3_RON_RTT_160ohm	(3)
-#define PHY_DDR4_LPDDR3_RON_RTT_120ohm	(4)
-#define PHY_DDR4_LPDDR3_RON_RTT_96ohm	(5)
-#define PHY_DDR4_LPDDR3_RON_RTT_80ohm	(6)
-#define PHY_DDR4_LPDDR3_RON_RTT_68ohm	(7)
-#define PHY_DDR4_LPDDR3_RON_RTT_60ohm	(16)
-#define PHY_DDR4_LPDDR3_RON_RTT_53ohm	(17)
-#define PHY_DDR4_LPDDR3_RON_RTT_48ohm	(18)
-#define PHY_DDR4_LPDDR3_RON_RTT_43ohm	(19)
-#define PHY_DDR4_LPDDR3_RON_RTT_40ohm	(20)
-#define PHY_DDR4_LPDDR3_RON_RTT_37ohm	(21)
-#define PHY_DDR4_LPDDR3_RON_RTT_34ohm	(22)
-#define PHY_DDR4_LPDDR3_RON_RTT_32ohm	(23)
-#define PHY_DDR4_LPDDR3_RON_RTT_30ohm	(24)
-#define PHY_DDR4_LPDDR3_RON_RTT_28ohm	(25)
-#define PHY_DDR4_LPDDR3_RON_RTT_26ohm	(26)
-#define PHY_DDR4_LPDDR3_RON_RTT_25ohm	(27)
-#define PHY_DDR4_LPDDR3_RON_RTT_24ohm	(28)
-#define PHY_DDR4_LPDDR3_RON_RTT_22ohm	(29)
-#define PHY_DDR4_LPDDR3_RON_RTT_21ohm	(30)
-#define PHY_DDR4_LPDDR3_RON_RTT_20ohm	(31)
 
 /* noc registers define */
 #define DDRCONF				0x8
@@ -219,16 +36,16 @@
 #define DDR_GRF_STATUS(n)	(DDR_GRF_STATUS_BASE + (n) * 4)
 
 /* CRU_SOFTRESET_CON5 */
-#define ddrphy_psrstn_req(n)    (((0x1 << 15) << 16) | (n << 15))
-#define ddrphy_srstn_req(n)     (((0x1 << 14) << 16) | (n << 14))
-#define ddrctrl_psrstn_req(n)	(((0x1 << 13) << 16) | (n << 13))
-#define ddrctrl_srstn_req(n)	(((0x1 << 12) << 16) | (n << 12))
-#define ddrmsch_srstn_req(n)	(((0x1 << 11) << 16) | (n << 11))
-#define msch_srstn_req(n)		(((0x1 << 9) << 16) | (n << 9))
-#define dfimon_srstn_req(n)		(((0x1 << 8) << 16) | (n << 8))
-#define grf_ddr_srstn_req(n)	(((0x1 << 7) << 16) | (n << 7))
+#define ddrphy_psrstn_req(n)    (((0x1 << 15) << 16) | ((n) << 15))
+#define ddrphy_srstn_req(n)     (((0x1 << 14) << 16) | ((n) << 14))
+#define ddrctrl_psrstn_req(n)	(((0x1 << 13) << 16) | ((n) << 13))
+#define ddrctrl_srstn_req(n)	(((0x1 << 12) << 16) | ((n) << 12))
+#define ddrmsch_srstn_req(n)	(((0x1 << 11) << 16) | ((n) << 11))
+#define msch_srstn_req(n)		(((0x1 << 9) << 16) | ((n) << 9))
+#define dfimon_srstn_req(n)		(((0x1 << 8) << 16) | ((n) << 8))
+#define grf_ddr_srstn_req(n)	(((0x1 << 7) << 16) | ((n) << 7))
 /* CRU_SOFTRESET_CON9 */
-#define ddrctrl_asrstn_req(n)		(((0x1 << 9) << 16) | (n << 9))
+#define ddrctrl_asrstn_req(n)		(((0x1 << 9) << 16) | ((n) << 9))
 
 /* CRU register */
 #define CRU_PLL_CON(pll_id, n)	((pll_id)  * 0x20 + (n) * 4)
@@ -255,56 +72,46 @@
 #define POSTDIV2(n)   ((0x7 << (6 + 16)) | ((n) << 6))
 #define REFDIV(n)     ((0x3F << 16) | (n))
 
-union noc_ddrtiming {
-	u32 d32;
-	struct {
-		unsigned acttoact:6;
-		unsigned rdtomiss:6;
-		unsigned wrtomiss:6;
-		unsigned burstlen:3;
-		unsigned rdtowr:5;
-		unsigned wrtord:5;
-		unsigned bwratio:1;
-	} b;
-} NOC_TIMING_T;
-
-union noc_activate {
-	u32 d32;
-	struct {
-		unsigned rrd:4;
-		unsigned faw:6;
-		unsigned fawbank:1;
-		unsigned reserved1:21;
-	} b;
-};
-
-union noc_devtodev {
-	u32 d32;
-	struct {
-		unsigned busrdtord:2;
-		unsigned busrdtowr:2;
-		unsigned buswrtord:2;
-		unsigned reserved2:26;
-	} b;
-};
-
-union noc_ddr4timing {
-	u32 d32;
-	struct {
-		unsigned ccdl:3;
-		unsigned wrtordl:5;
-		unsigned rrdl:4;
-		unsigned reserved2:20;
-	} b;
+u16 ddr_cfg_2_rbc[] = {
+	/*
+	 * [5:4]  row(13+n)
+	 * [3]    cs(0:0 cs, 1:2 cs)
+	 * [2]  bank(0:0bank,1:8bank)
+	 * [1:0]    col(11+n)
+	 */
+	/* row,        cs,       bank,   col */
+	((3 << 4) | (0 << 3) | (1 << 2) | 0),
+	((3 << 4) | (0 << 3) | (1 << 2) | 1),
+	((2 << 4) | (0 << 3) | (1 << 2) | 2),
+	((3 << 4) | (0 << 3) | (1 << 2) | 2),
+	((2 << 4) | (0 << 3) | (1 << 2) | 3),
+	((3 << 4) | (1 << 3) | (1 << 2) | 0),
+	((3 << 4) | (1 << 3) | (1 << 2) | 1),
+	((2 << 4) | (1 << 3) | (1 << 2) | 2),
+	((3 << 4) | (0 << 3) | (0 << 2) | 1),
+	((2 << 4) | (0 << 3) | (1 << 2) | 1),
 };
 
-union noc_ddrmode {
-	u32 d32;
-	struct {
-		unsigned autoprecharge:1;
-		unsigned bwratioextended:1;
-		unsigned reserved3:30;
-	} b;
+u16 ddr4_cfg_2_rbc[] = {
+	/***************************
+	 * [6]	cs 0:0cs 1:2 cs
+	 * [5:3]  row(13+n)
+	 * [2]  cs(0:0 cs, 1:2 cs)
+	 * [1]  bw    0: 16bit 1:32bit
+	 * [0]  diebw 0:8bit 1:16bit
+	 ***************************/
+	/*  cs,       row,        cs,       bw,   diebw */
+	((0 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 0),
+	((1 << 6) | (2 << 3) | (0 << 2) | (1 << 1) | 0),
+	((0 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 0),
+	((1 << 6) | (3 << 3) | (0 << 2) | (0 << 1) | 0),
+	((0 << 6) | (4 << 3) | (0 << 2) | (1 << 1) | 1),
+	((1 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 1),
+	((1 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 1),
+	((0 << 6) | (2 << 3) | (1 << 2) | (1 << 1) | 0),
+	((0 << 6) | (3 << 3) | (1 << 2) | (0 << 1) | 0),
+	((0 << 6) | (3 << 3) | (1 << 2) | (1 << 1) | 1),
+	((0 << 6) | (4 << 3) | (1 << 2) | (0 << 1) | 1),
 };
 
 u32 addrmap[21][9] = {
@@ -355,17 +162,65 @@ u32 addrmap[21][9] = {
 		0x07070707, 0x00000f07, 0x3f00}
 };
 
-struct rk3328_msch_timings {
-	union noc_ddrtiming ddrtiming;
-	union noc_ddrmode ddrmode;
-	u32 readlatency;
-	union noc_activate activate;
-	union noc_devtodev devtodev;
-	union noc_ddr4timing ddr4timing;
-	u32 agingx0;
+struct rk3328_ddr_grf_regs {
+	u32 ddr_grf_con[4];
+	u32 reserved[(0x100 - 0x10) / 4];
+	u32 ddr_grf_status[11];
 };
 
-struct rk3328_msch_regs {
+union noc_ddrtiming {
+	u32 d32;
+	struct {
+		unsigned acttoact:6;
+		unsigned rdtomiss:6;
+		unsigned wrtomiss:6;
+		unsigned burstlen:3;
+		unsigned rdtowr:5;
+		unsigned wrtord:5;
+		unsigned bwratio:1;
+	} b;
+};
+
+union noc_activate {
+	u32 d32;
+	struct {
+		unsigned rrd:4;
+		unsigned faw:6;
+		unsigned fawbank:1;
+		unsigned reserved1:21;
+	} b;
+};
+
+union noc_devtodev {
+	u32 d32;
+	struct {
+		unsigned busrdtord:2;
+		unsigned busrdtowr:2;
+		unsigned buswrtord:2;
+		unsigned reserved2:26;
+	} b;
+};
+
+union noc_ddr4timing {
+	u32 d32;
+	struct {
+		unsigned ccdl:3;
+		unsigned wrtordl:5;
+		unsigned rrdl:4;
+		unsigned reserved2:20;
+	} b;
+};
+
+union noc_ddrmode {
+	u32 d32;
+	struct {
+		unsigned autoprecharge:1;
+		unsigned bwratioextended:1;
+		unsigned reserved3:30;
+	} b;
+};
+
+struct msch_regs {
 	u32 coreid;
 	u32 revisionid;
 	u32 ddrconf;
@@ -384,58 +239,27 @@ struct rk3328_msch_regs {
 	u32 ddr4_timing;
 };
 
-struct rk3328_ddr_grf_regs {
-	u32 ddr_grf_con[4];
-	u32 reserved[(0x100 - 0x10) / 4];
-	u32 ddr_grf_status[11];
-};
-
-struct rk3328_ddr_pctl_regs {
-	u32 pctl[30][2];
-};
-
-struct rk3328_ddr_phy_regs {
-	u32 phy[5][2];
-};
-
-struct rk3328_ddr_skew {
-	u32 a0_a1_skew[15];
-	u32 cs0_dm0_skew[11];
-	u32 cs0_dm1_skew[11];
-	u32 cs0_dm2_skew[11];
-	u32 cs0_dm3_skew[11];
-	u32 cs1_dm0_skew[11];
-	u32 cs1_dm1_skew[11];
-	u32 cs1_dm2_skew[11];
-	u32 cs1_dm3_skew[11];
+struct sdram_msch_timings {
+	union noc_ddrtiming ddrtiming;
+	union noc_ddrmode ddrmode;
+	u32 readlatency;
+	union noc_activate activate;
+	union noc_devtodev devtodev;
+	union noc_ddr4timing ddr4timing;
+	u32 agingx0;
 };
 
 struct rk3328_sdram_channel {
-	unsigned int rank;
-	unsigned int col;
-	/* 3:8bank, 2:4bank */
-	unsigned int bk;
-	/* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
-	unsigned int bw;
-	/* die buswidth, 2:32bit, 1:16bit, 0:8bit */
-	unsigned int dbw;
-	unsigned int row_3_4;
-	unsigned int cs0_row;
-	unsigned int cs1_row;
-	unsigned int ddrconfig;
-	struct rk3328_msch_timings noc_timings;
+	struct sdram_cap_info cap_info;
+	struct sdram_msch_timings noc_timings;
 };
 
 struct rk3328_sdram_params {
 	struct rk3328_sdram_channel ch;
-	unsigned int ddr_freq;
-	unsigned int dramtype;
-	unsigned int odt;
-	struct rk3328_ddr_pctl_regs pctl_regs;
-	struct rk3328_ddr_phy_regs phy_regs;
-	struct rk3328_ddr_skew skew;
+	struct sdram_base_params base;
+	struct ddr_pctl_regs pctl_regs;
+	struct ddr_phy_regs phy_regs;
+	struct ddr_phy_skew skew;
 };
 
-#define PHY_REG(base, n)		(base + 4 * (n))
-
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
index dc65ae792431c3ca0409740e176a919c9420e18a..267649fda4cb6fc82b280c024319edc9f8cb568d 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3399.h
@@ -5,6 +5,8 @@
 
 #ifndef _ASM_ARCH_SDRAM_RK3399_H
 #define _ASM_ARCH_SDRAM_RK3399_H
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_msch.h>
 
 struct rk3399_ddr_pctl_regs {
 	u32 denali_ctl[332];
@@ -18,55 +20,6 @@ struct rk3399_ddr_pi_regs {
 	u32 denali_pi[200];
 };
 
-union noc_ddrtimingc0 {
-	u32 d32;
-	struct {
-		unsigned burstpenalty : 4;
-		unsigned reserved0 : 4;
-		unsigned wrtomwr : 6;
-		unsigned reserved1 : 18;
-	} b;
-};
-
-union noc_ddrmode {
-	u32 d32;
-	struct {
-		unsigned autoprecharge : 1;
-		unsigned bypassfiltering : 1;
-		unsigned fawbank : 1;
-		unsigned burstsize : 2;
-		unsigned mwrsize : 2;
-		unsigned reserved2 : 1;
-		unsigned forceorder : 8;
-		unsigned forceorderstate : 8;
-		unsigned reserved3 : 8;
-	} b;
-};
-
-struct rk3399_msch_regs {
-	u32 coreid;
-	u32 revisionid;
-	u32 ddrconf;
-	u32 ddrsize;
-	u32 ddrtiminga0;
-	u32 ddrtimingb0;
-	u32 ddrtimingc0;
-	u32 devtodev0;
-	u32 reserved0[(0x110 - 0x20) / 4];
-	u32 ddrmode;
-	u32 reserved1[(0x1000 - 0x114) / 4];
-	u32 agingx0;
-};
-
-struct rk3399_msch_timings {
-	u32 ddrtiminga0;
-	u32 ddrtimingb0;
-	union noc_ddrtimingc0 ddrtimingc0;
-	u32 devtodev0;
-	union noc_ddrmode ddrmode;
-	u32 agingx0;
-};
-
 struct rk3399_ddr_cic_regs {
 	u32 cic_ctrl0;
 	u32 cic_ctrl1;
@@ -83,14 +36,38 @@ struct rk3399_ddr_cic_regs {
 #define START		1
 
 /* DENALI_CTL_68 */
-#define PWRUP_SREFRESH_EXIT	(1 << 16)
+#define PWRUP_SREFRESH_EXIT	BIT(16)
 
 /* DENALI_CTL_274 */
 #define MEM_RST_VALID	1
 
+struct msch_regs {
+	u32 coreid;
+	u32 revisionid;
+	u32 ddrconf;
+	u32 ddrsize;
+	union noc_ddrtiminga0 ddrtiminga0;
+	union noc_ddrtimingb0 ddrtimingb0;
+	union noc_ddrtimingc0 ddrtimingc0;
+	union noc_devtodev0 devtodev0;
+	u32 reserved0[(0x110 - 0x20) / 4];
+	union noc_ddrmode ddrmode;
+	u32 reserved1[(0x1000 - 0x114) / 4];
+	u32 agingx0;
+};
+
+struct sdram_msch_timings {
+	union noc_ddrtiminga0 ddrtiminga0;
+	union noc_ddrtimingb0 ddrtimingb0;
+	union noc_ddrtimingc0 ddrtimingc0;
+	union noc_devtodev0 devtodev0;
+	union noc_ddrmode ddrmode;
+	u32 agingx0;
+};
+
 struct rk3399_sdram_channel {
 	struct sdram_cap_info cap_info;
-	struct rk3399_msch_timings noc_timings;
+	struct sdram_msch_timings noc_timings;
 };
 
 struct rk3399_sdram_params {
@@ -101,11 +78,20 @@ struct rk3399_sdram_params {
 	struct rk3399_ddr_publ_regs phy_regs;
 };
 
-#define PI_CA_TRAINING		(1 << 0)
-#define PI_WRITE_LEVELING	(1 << 1)
-#define PI_READ_GATE_TRAINING	(1 << 2)
-#define PI_READ_LEVELING	(1 << 3)
-#define PI_WDQ_LEVELING		(1 << 4)
+#define PI_CA_TRAINING		BIT(0)
+#define PI_WRITE_LEVELING	BIT(1)
+#define PI_READ_GATE_TRAINING	BIT(2)
+#define PI_READ_LEVELING	BIT(3)
+#define PI_WDQ_LEVELING		BIT(4)
 #define PI_FULL_TRAINING	0xff
 
+enum {
+	STRIDE_128B = 0,
+	STRIDE_256B = 1,
+	STRIDE_512B = 2,
+	STRIDE_4KB = 3,
+	UN_STRIDE = 4,
+	PART_STRIDE = 5,
+};
+
 #endif
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 48ee6c3c603fc1d67316563857d902b0850186fa..9de9a9acee7c9b428831ccc89fb175bce7e9abde 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-$(CONFIG_CMD_BOOTZ) += bootm.o zimage.o
 obj-$(CONFIG_SYS_L2_PL310) += cache-pl310.o
 else
-obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
+obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o
 obj-$(CONFIG_SPL_FRAMEWORK) += zimage.o
 obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
 endif
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index c74641dcd9b661fa97237d21b62a2b4019214c28..fb6c37cf519494aa55a562354e066dcf434ddce6 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -149,7 +149,7 @@ here:
 
 	bl	c_runtime_cpu_setup	/* we still call old routine here */
 #endif
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
+#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)
 
 #if !defined(CONFIG_SPL_EARLY_BSS)
 	SPL_CLEAR_BSS
diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S
index e76b25a03e8c7621717cc9595c7b2fd5be9807e9..04afa518acf011b58ae28664e03480b31d6a00c1 100644
--- a/arch/arm/lib/crt0_64.S
+++ b/arch/arm/lib/crt0_64.S
@@ -120,6 +120,7 @@ relocation_return:
  */
 	bl	c_runtime_cpu_setup		/* still call old routine */
 #endif /* !CONFIG_SPL_BUILD */
+#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)
 #if defined(CONFIG_SPL_BUILD)
 	bl	spl_relocate_stack_gd           /* may return NULL */
 	/* set up gd here, outside any C code, if new stack is returned */
@@ -152,5 +153,6 @@ clear_loop:
 	b	board_init_r			/* PC relative jump */
 
 	/* NOTREACHED - board_init_r() does not return */
+#endif
 
 ENDPROC(_main)
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index f5a80b4f0c0c1d470a0844e0507d5e14fb1597da..493699472c701beb13e766fc9a16646d0a4f8e07 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -1,5 +1,27 @@
 if ARCH_ROCKCHIP
 
+config ROCKCHIP_PX30
+	bool "Support Rockchip PX30"
+	select ARM64
+	select SUPPORT_SPL
+	select SUPPORT_TPL
+	select SPL
+	select TPL
+	select TPL_TINY_FRAMEWORK if TPL
+	select TPL_NEEDS_SEPARATE_TEXT_BASE if SPL
+	select TPL_NEEDS_SEPARATE_STACK if TPL
+	imply SPL_SEPARATE_BSS
+	select SPL_SERIAL_SUPPORT
+	select TPL_SERIAL_SUPPORT
+	select DEBUG_UART_BOARD_INIT
+	imply ROCKCHIP_COMMON_BOARD
+	imply SPL_ROCKCHIP_COMMON_BOARD
+	help
+	  The Rockchip PX30 is a ARM-based SoC with a quad-core Cortex-A35
+	  including NEON and GPU, Mali-400 graphics, several DDR3 options
+	  and video codec support. Peripherals include Gigabit Ethernet,
+	  USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
+
 config ROCKCHIP_RK3036
 	bool "Support Rockchip RK3036"
 	select CPU_V7A
@@ -105,6 +127,29 @@ config ROCKCHIP_RK3288
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs.
 
+config ROCKCHIP_RK3308
+	bool "Support Rockchip RK3308"
+	select ARM64
+	select DEBUG_UART_BOARD_INIT
+	select SUPPORT_SPL
+	select SUPPORT_TPL
+	select SPL
+	select SPL_ATF
+	select SPL_ATF_NO_PLATFORM_PARAM
+	select SPL_LOAD_FIT
+	imply ROCKCHIP_COMMON_BOARD
+	imply SPL_ROCKCHIP_COMMON_BOARD
+	imply SPL_CLK
+	imply SPL_REGMAP
+	imply SPL_SYSCON
+	imply SPL_RAM
+	imply SPL_SERIAL_SUPPORT
+	imply TPL_SERIAL_SUPPORT
+	imply SPL_SEPARATE_BSS
+	help
+	  The Rockchip RK3308 is a ARM-based Soc which embedded with quad
+	  Cortex-A35 and highly integrated audio interfaces.
+
 config ROCKCHIP_RK3328
 	bool "Support Rockchip RK3328"
 	select ARM64
@@ -115,6 +160,7 @@ config ROCKCHIP_RK3328
 	select TPL_NEEDS_SEPARATE_TEXT_BASE if TPL
 	select TPL_NEEDS_SEPARATE_STACK if TPL
 	imply ROCKCHIP_COMMON_BOARD
+	imply ROCKCHIP_SDRAM_COMMON
 	imply SPL_ROCKCHIP_COMMON_BOARD
 	imply SPL_SERIAL_SUPPORT
 	imply TPL_SERIAL_SUPPORT
@@ -183,6 +229,7 @@ config ROCKCHIP_RK3399
 	select DM_REGULATOR_FIXED
 	select BOARD_LATE_INIT
 	imply ROCKCHIP_COMMON_BOARD
+	imply ROCKCHIP_SDRAM_COMMON
 	imply SPL_ROCKCHIP_COMMON_BOARD
 	imply TPL_SERIAL_SUPPORT
 	imply TPL_LIBCOMMON_SUPPORT
@@ -315,11 +362,13 @@ config TPL_ROCKCHIP_EARLYRETURN_TO_BROM
 config SPL_MMC_SUPPORT
 	default y if !SPL_ROCKCHIP_BACK_TO_BROM
 
+source "arch/arm/mach-rockchip/px30/Kconfig"
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
 source "arch/arm/mach-rockchip/rk3128/Kconfig"
 source "arch/arm/mach-rockchip/rk3188/Kconfig"
 source "arch/arm/mach-rockchip/rk322x/Kconfig"
 source "arch/arm/mach-rockchip/rk3288/Kconfig"
+source "arch/arm/mach-rockchip/rk3308/Kconfig"
 source "arch/arm/mach-rockchip/rk3328/Kconfig"
 source "arch/arm/mach-rockchip/rk3368/Kconfig"
 source "arch/arm/mach-rockchip/rk3399/Kconfig"
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 45d9b06233fdc347e0d3dd809c165034d7a97d51..a728acda24a3408d7b76e001ba9e9b0ed3452e68 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -11,6 +11,7 @@ obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
 obj-spl-$(CONFIG_SPL_ROCKCHIP_COMMON_BOARD) += spl.o spl-boot-order.o
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
 obj-tpl-$(CONFIG_TPL_ROCKCHIP_COMMON_BOARD) += tpl.o
+obj-tpl-$(CONFIG_ROCKCHIP_PX30) += px30-board-tpl.o
 
 obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
 
@@ -25,13 +26,15 @@ obj-$(CONFIG_ROCKCHIP_COMMON_BOARD) += board.o
 obj-$(CONFIG_MISC_INIT_R) += misc.o
 endif
 
-obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o
+obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram.o
 
+obj-$(CONFIG_ROCKCHIP_PX30) += px30/
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
 obj-$(CONFIG_ROCKCHIP_RK3128) += rk3128/
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
 obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x/
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
+obj-$(CONFIG_ROCKCHIP_RK3308) += rk3308/
 obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328/
 obj-$(CONFIG_ROCKCHIP_RK3368) += rk3368/
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 8ca34637315904e4c27cc802d8c8aee60c1e7410..c90eb976d0f71f279a16704b6b43f76c27433397 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -61,29 +61,55 @@ static struct dwc2_plat_otg_data otg_data = {
 
 int board_usb_init(int index, enum usb_init_type init)
 {
-	int node;
+	ofnode node;
 	const char *mode;
 	bool matched = false;
-	const void *blob = gd->fdt_blob;
 
 	/* find the usb_otg node */
-	node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2");
-
-	while (node > 0) {
-		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+	node = ofnode_by_compatible(ofnode_null(), "snps,dwc2");
+	while (ofnode_valid(node)) {
+		mode = ofnode_read_string(node, "dr_mode");
 		if (mode && strcmp(mode, "otg") == 0) {
 			matched = true;
 			break;
 		}
 
-		node = fdt_node_offset_by_compatible(blob, node, "snps,dwc2");
+		node = ofnode_by_compatible(node, "snps,dwc2");
 	}
 	if (!matched) {
 		debug("Not found usb_otg device\n");
 		return -ENODEV;
 	}
-	otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+	otg_data.regs_otg = ofnode_get_addr(node);
+
+#ifdef CONFIG_ROCKCHIP_RK3288
+	int ret;
+	u32 phandle, offset;
+	ofnode phy_node;
+
+	ret = ofnode_read_u32(node, "phys", &phandle);
+	if (ret)
+		return ret;
 
+	node = ofnode_get_by_phandle(phandle);
+	if (!ofnode_valid(node)) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	phy_node = ofnode_get_parent(node);
+	if (!ofnode_valid(node)) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	otg_data.phy_of_node = phy_node;
+	ret = ofnode_read_u32(node, "reg", &offset);
+	if (ret)
+		return ret;
+	otg_data.regs_phy =  offset +
+		(u32)syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+#endif
 	return dwc2_udc_probe(&otg_data);
 }
 
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c
index c0e4fdbc00fec8b5779b792d1f36940bb6a1dc9b..bed4317f7ecee173538f8f56a19ac06a55d95d6c 100644
--- a/arch/arm/mach-rockchip/misc.c
+++ b/arch/arm/mach-rockchip/misc.c
@@ -57,13 +57,18 @@ int rockchip_cpuid_from_efuse(const u32 cpuid_offset,
 			      const u32 cpuid_length,
 			      u8 *cpuid)
 {
-#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE)
+#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) || CONFIG_IS_ENABLED(ROCKCHIP_OTP)
 	struct udevice *dev;
 	int ret;
 
 	/* retrieve the device */
+#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE)
 	ret = uclass_get_device_by_driver(UCLASS_MISC,
 					  DM_GET_DRIVER(rockchip_efuse), &dev);
+#elif CONFIG_IS_ENABLED(ROCKCHIP_OTP)
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(rockchip_otp), &dev);
+#endif
 	if (ret) {
 		debug("%s: could not find efuse device\n", __func__);
 		return -1;
diff --git a/arch/arm/mach-rockchip/px30-board-tpl.c b/arch/arm/mach-rockchip/px30-board-tpl.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c8976f61cd90fcf1d7763339009c8cb2f2c3626
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30-board-tpl.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/bootrom.h>
+#include <asm/arch-rockchip/sdram_px30.h>
+
+#define TIMER_LOAD_COUNT0	0x00
+#define TIMER_LOAD_COUNT1	0x04
+#define TIMER_CUR_VALUE0	0x08
+#define TIMER_CUR_VALUE1	0x0c
+#define TIMER_CONTROL_REG	0x10
+
+#define TIMER_EN	0x1
+#define	TIMER_FMODE	(0 << 1)
+#define	TIMER_RMODE	(1 << 1)
+
+void secure_timer_init(void)
+{
+	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_LOAD_COUNT0);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + TIMER_LOAD_COUNT1);
+	writel(TIMER_EN | TIMER_FMODE,
+	       CONFIG_ROCKCHIP_STIMER_BASE + TIMER_CONTROL_REG);
+}
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_init();
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	printascii("U-Boot TPL board init\n");
+#endif
+
+	secure_timer_init();
+	ret = sdram_init();
+	if (ret)
+		printascii("sdram_init failed\n");
+
+	/* return to maskrom */
+	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
+}
diff --git a/arch/arm/mach-rockchip/px30/Kconfig b/arch/arm/mach-rockchip/px30/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..109a37be15ad3a5a2bcdb3ef69daa268ce75d805
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30/Kconfig
@@ -0,0 +1,41 @@
+if ROCKCHIP_PX30
+
+config TARGET_EVB_PX30
+	bool "EVB_PX30"
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff010200
+
+config SYS_SOC
+	default "px30"
+
+config SYS_MALLOC_F_LEN
+	default 0x400
+
+config SPL_SERIAL_SUPPORT
+	default y
+
+config TPL_LDSCRIPT
+	default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
+
+config TPL_TEXT_BASE
+	default 0xff0e1000
+
+config TPL_MAX_SIZE
+	default 10240
+
+config TPL_STACK
+	default 0xff0e4fff
+
+config DEBUG_UART2_CHANNEL
+	int "Mux channel to use for debug UART2"
+	depends on DEBUG_UART_BOARD_INIT
+	default 0
+	help
+	  UART2 can use two different set of pins to route the output.
+	  For using the UART for early debugging the route to use needs
+	  to be declared (0 or 1).
+
+source "board/rockchip/evb_px30/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/px30/Makefile b/arch/arm/mach-rockchip/px30/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..080ce146f75ee840b6895671485267118faad4d6
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += clk_px30.o
+
+ifndef CONFIG_TPL_BUILD
+obj-y += syscon_px30.o
+endif
+
+obj-y += px30.o
diff --git a/arch/arm/mach-rockchip/px30/clk_px30.c b/arch/arm/mach-rockchip/px30/clk_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..0bd6b471dae034b35790491b92fa62bd4ac54fb7
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30/clk_px30.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_px30_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct px30_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..bacdcc0b938d9960201d9530a7fbc04b9fb6d6f7
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30/px30.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co., Ltd
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <asm/armv8/mmu.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/grf_px30.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/uart.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+#include <dt-bindings/clock/px30-cru.h>
+
+static struct mm_region px30_mem_map[] = {
+	{
+		.virt = 0x0UL,
+		.phys = 0x0UL,
+		.size = 0xff000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xff000000UL,
+		.phys = 0xff000000UL,
+		.size = 0x01000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = px30_mem_map;
+
+#define PMU_PWRDN_CON			0xff000018
+#define GRF_BASE			0xff140000
+#define CRU_BASE			0xff2b0000
+#define VIDEO_PHY_BASE			0xff2e0000
+#define SERVICE_CORE_ADDR		0xff508000
+#define DDR_FW_BASE			0xff534000
+
+#define FW_DDR_CON			0x40
+
+#define QOS_PRIORITY			0x08
+
+#define QOS_PRIORITY_LEVEL(h, l)	((((h) & 3) << 8) | ((l) & 3))
+
+/* GRF_GPIO1CL_IOMUX */
+enum {
+	GPIO1C1_SHIFT		= 4,
+	GPIO1C1_MASK		= 0xf << GPIO1C1_SHIFT,
+	GPIO1C1_GPIO		= 0,
+	GPIO1C1_UART1_TX,
+
+	GPIO1C0_SHIFT		= 0,
+	GPIO1C0_MASK		= 0xf << GPIO1C0_SHIFT,
+	GPIO1C0_GPIO		= 0,
+	GPIO1C0_UART1_RX,
+};
+
+/* GRF_GPIO1DL_IOMUX */
+enum {
+	GPIO1D3_SHIFT		= 12,
+	GPIO1D3_MASK		= 0xf << GPIO1D3_SHIFT,
+	GPIO1D3_GPIO		= 0,
+	GPIO1D3_SDMMC_D1,
+	GPIO1D3_UART2_RXM0,
+
+	GPIO1D2_SHIFT		= 8,
+	GPIO1D2_MASK		= 0xf << GPIO1D2_SHIFT,
+	GPIO1D2_GPIO		= 0,
+	GPIO1D2_SDMMC_D0,
+	GPIO1D2_UART2_TXM0,
+};
+
+/* GRF_GPIO1DH_IOMUX */
+enum {
+	GPIO1D7_SHIFT		= 12,
+	GPIO1D7_MASK		= 0xf << GPIO1D7_SHIFT,
+	GPIO1D7_GPIO		= 0,
+	GPIO1D7_SDMMC_CMD,
+
+	GPIO1D6_SHIFT		= 8,
+	GPIO1D6_MASK		= 0xf << GPIO1D6_SHIFT,
+	GPIO1D6_GPIO		= 0,
+	GPIO1D6_SDMMC_CLK,
+
+	GPIO1D5_SHIFT		= 4,
+	GPIO1D5_MASK		= 0xf << GPIO1D5_SHIFT,
+	GPIO1D5_GPIO		= 0,
+	GPIO1D5_SDMMC_D3,
+
+	GPIO1D4_SHIFT		= 0,
+	GPIO1D4_MASK		= 0xf << GPIO1D4_SHIFT,
+	GPIO1D4_GPIO		= 0,
+	GPIO1D4_SDMMC_D2,
+};
+
+/* GRF_GPIO2BH_IOMUX */
+enum {
+	GPIO2B6_SHIFT		= 8,
+	GPIO2B6_MASK		= 0xf << GPIO2B6_SHIFT,
+	GPIO2B6_GPIO		= 0,
+	GPIO2B6_CIF_D1M0,
+	GPIO2B6_UART2_RXM1,
+
+	GPIO2B4_SHIFT		= 0,
+	GPIO2B4_MASK		= 0xf << GPIO2B4_SHIFT,
+	GPIO2B4_GPIO		= 0,
+	GPIO2B4_CIF_D0M0,
+	GPIO2B4_UART2_TXM1,
+};
+
+/* GRF_GPIO3AL_IOMUX */
+enum {
+	GPIO3A2_SHIFT		= 8,
+	GPIO3A2_MASK		= 0xf << GPIO3A2_SHIFT,
+	GPIO3A2_GPIO		= 0,
+	GPIO3A2_UART5_TX	= 4,
+
+	GPIO3A1_SHIFT		= 4,
+	GPIO3A1_MASK		= 0xf << GPIO3A1_SHIFT,
+	GPIO3A1_GPIO		= 0,
+	GPIO3A1_UART5_RX	= 4,
+};
+
+int arch_cpu_init(void)
+{
+	static struct px30_grf * const grf = (void *)GRF_BASE;
+	u32 __maybe_unused val;
+
+#ifdef CONFIG_SPL_BUILD
+	/* We do some SoC one time setting here. */
+	/* Disable the ddr secure region setting to make it non-secure */
+	writel(0x0, DDR_FW_BASE + FW_DDR_CON);
+
+	/* Set cpu qos priority */
+	writel(QOS_PRIORITY_LEVEL(1, 1), SERVICE_CORE_ADDR + QOS_PRIORITY);
+
+#if !defined(CONFIG_DEBUG_UART_BOARD_INIT) || \
+	(CONFIG_DEBUG_UART_BASE != 0xff160000) || \
+	(CONFIG_DEBUG_UART_CHANNEL != 0)
+	/* fix sdmmc pinmux if not using uart2-channel0 as debug uart */
+	rk_clrsetreg(&grf->gpio1dl_iomux,
+		     GPIO1D3_MASK | GPIO1D2_MASK,
+		     GPIO1D3_SDMMC_D1 << GPIO1D3_SHIFT |
+		     GPIO1D2_SDMMC_D0 << GPIO1D2_SHIFT);
+	rk_clrsetreg(&grf->gpio1dh_iomux,
+		     GPIO1D7_MASK | GPIO1D6_MASK | GPIO1D5_MASK | GPIO1D4_MASK,
+		     GPIO1D7_SDMMC_CMD << GPIO1D7_SHIFT |
+		     GPIO1D6_SDMMC_CLK << GPIO1D6_SHIFT |
+		     GPIO1D5_SDMMC_D3 << GPIO1D5_SHIFT |
+		     GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT);
+#endif
+
+#endif
+
+	/* Enable PD_VO (default disable at reset) */
+	rk_clrreg(PMU_PWRDN_CON, 1 << 13);
+
+	/* Disable video phy bandgap by default */
+	writel(0x82, VIDEO_PHY_BASE + 0x0000);
+	writel(0x05, VIDEO_PHY_BASE + 0x03ac);
+
+	/* Clear the force_jtag */
+	rk_clrreg(&grf->cpu_con[1], 1 << 7);
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
+{
+	static struct px30_grf * const grf = (void *)GRF_BASE;
+	static struct px30_cru * const cru = (void *)CRU_BASE;
+
+#if defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff158000)
+	/* uart_sel_clk default select 24MHz */
+	rk_clrsetreg(&cru->clksel_con[34],
+		     UART1_PLL_SEL_MASK | UART1_DIV_CON_MASK,
+		     UART1_PLL_SEL_24M << UART1_PLL_SEL_SHIFT | 0);
+	rk_clrsetreg(&cru->clksel_con[35],
+		     UART1_CLK_SEL_MASK,
+		     UART1_CLK_SEL_UART1 << UART1_CLK_SEL_SHIFT);
+
+	rk_clrsetreg(&grf->gpio1cl_iomux,
+		     GPIO1C1_MASK | GPIO1C0_MASK,
+		     GPIO1C1_UART1_TX << GPIO1C1_SHIFT |
+		     GPIO1C0_UART1_RX << GPIO1C0_SHIFT);
+#elif defined(CONFIG_DEBUG_UART_BASE) && (CONFIG_DEBUG_UART_BASE == 0xff178000)
+	/* uart_sel_clk default select 24MHz */
+	rk_clrsetreg(&cru->clksel_con[46],
+		     UART5_PLL_SEL_MASK | UART5_DIV_CON_MASK,
+		     UART5_PLL_SEL_24M << UART5_PLL_SEL_SHIFT | 0);
+	rk_clrsetreg(&cru->clksel_con[47],
+		     UART5_CLK_SEL_MASK,
+		     UART5_CLK_SEL_UART5 << UART5_CLK_SEL_SHIFT);
+
+	rk_clrsetreg(&grf->gpio3al_iomux,
+		     GPIO3A2_MASK | GPIO3A1_MASK,
+		     GPIO3A2_UART5_TX << GPIO3A2_SHIFT |
+		     GPIO3A1_UART5_RX << GPIO3A1_SHIFT);
+#else
+	/* GRF_IOFUNC_CON0 */
+	enum {
+		CON_IOMUX_UART2SEL_SHIFT	= 10,
+		CON_IOMUX_UART2SEL_MASK = 3 << CON_IOMUX_UART2SEL_SHIFT,
+		CON_IOMUX_UART2SEL_M0	= 0,
+		CON_IOMUX_UART2SEL_M1,
+		CON_IOMUX_UART2SEL_USBPHY,
+	};
+
+	/* uart_sel_clk default select 24MHz */
+	rk_clrsetreg(&cru->clksel_con[37],
+		     UART2_PLL_SEL_MASK | UART2_DIV_CON_MASK,
+		     UART2_PLL_SEL_24M << UART2_PLL_SEL_SHIFT | 0);
+	rk_clrsetreg(&cru->clksel_con[38],
+		     UART2_CLK_SEL_MASK,
+		     UART2_CLK_SEL_UART2 << UART2_CLK_SEL_SHIFT);
+
+#if (CONFIG_DEBUG_UART2_CHANNEL == 1)
+	/* Enable early UART2 */
+	rk_clrsetreg(&grf->iofunc_con0,
+		     CON_IOMUX_UART2SEL_MASK,
+		     CON_IOMUX_UART2SEL_M1 << CON_IOMUX_UART2SEL_SHIFT);
+
+	rk_clrsetreg(&grf->gpio2bh_iomux,
+		     GPIO2B6_MASK | GPIO2B4_MASK,
+		     GPIO2B6_UART2_RXM1 << GPIO2B6_SHIFT |
+		     GPIO2B4_UART2_TXM1 << GPIO2B4_SHIFT);
+#else
+	rk_clrsetreg(&grf->iofunc_con0,
+		     CON_IOMUX_UART2SEL_MASK,
+		     CON_IOMUX_UART2SEL_M0 << CON_IOMUX_UART2SEL_SHIFT);
+
+	rk_clrsetreg(&grf->gpio1dl_iomux,
+		     GPIO1D3_MASK | GPIO1D2_MASK,
+		     GPIO1D3_UART2_RXM0 << GPIO1D3_SHIFT |
+		     GPIO1D2_UART2_TXM0 << GPIO1D2_SHIFT);
+#endif /* CONFIG_DEBUG_UART2_CHANNEL == 1 */
+
+#endif /* CONFIG_DEBUG_UART_BASE && CONFIG_DEBUG_UART_BASE == ... */
+}
+#endif /* CONFIG_DEBUG_UART_BOARD_INIT */
diff --git a/arch/arm/mach-rockchip/px30/syscon_px30.c b/arch/arm/mach-rockchip/px30/syscon_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..0331491b408e9a022c89eb63f6eb8233e1dd0abe
--- /dev/null
+++ b/arch/arm/mach-rockchip/px30/syscon_px30.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id px30_syscon_ids[] = {
+	{ .compatible = "rockchip,px30-pmu", .data = ROCKCHIP_SYSCON_PMU },
+	{ .compatible = "rockchip,px30-pmugrf", .data = ROCKCHIP_SYSCON_PMUGRF },
+	{ .compatible = "rockchip,px30-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_px30) = {
+	.id = UCLASS_SYSCON,
+	.name = "px30_syscon",
+	.of_match = px30_syscon_ids,
+};
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int px30_syscon_bind_of_platdata(struct udevice *dev)
+{
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(rockchip_px30_pmu) = {
+	.name = "rockchip_px30_pmu",
+	.id = UCLASS_SYSCON,
+	.of_match = px30_syscon_ids,
+	.bind = px30_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_px30_pmugrf) = {
+	.name = "rockchip_px30_pmugrf",
+	.id = UCLASS_SYSCON,
+	.of_match = px30_syscon_ids + 1,
+	.bind = px30_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_px30_grf) = {
+	.name = "rockchip_px30_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = px30_syscon_ids + 2,
+	.bind = px30_syscon_bind_of_platdata,
+};
+#endif
diff --git a/arch/arm/mach-rockchip/rk3036/rk3036.c b/arch/arm/mach-rockchip/rk3036/rk3036.c
index be458cfb6425d4bdbdae5189ceb229fb3f171228..e9ada6dea3c07e10785fb56756e6c56cbd0a9138 100644
--- a/arch/arm/mach-rockchip/rk3036/rk3036.c
+++ b/arch/arm/mach-rockchip/rk3036/rk3036.c
@@ -43,7 +43,7 @@ void board_debug_uart_init(void)
 #if !CONFIG_IS_ENABLED(RAM)
 /*
  * When CONFIG_RAM is enabled, the dram_init() function is implemented
- * in sdram_common.c.
+ * in sdram.c.
  */
 int dram_init(void)
 {
diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c
index 987b4e0d58c2b732ae35486c93dfe7c4de55d4ca..ee2fb67fca69d4ab09a4add4d0caf2e543035b61 100644
--- a/arch/arm/mach-rockchip/rk3288/rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/rk3288.c
@@ -15,7 +15,7 @@
 #include <asm/arch-rockchip/grf_rk3288.h>
 #include <asm/arch-rockchip/pmu_rk3288.h>
 #include <asm/arch-rockchip/qos_rk3288.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/arm/mach-rockchip/rk3308/Kconfig b/arch/arm/mach-rockchip/rk3308/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..b9fdfe2e950d8951bad28f313fdf8b4917d15c95
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3308/Kconfig
@@ -0,0 +1,27 @@
+if ROCKCHIP_RK3308
+
+config TARGET_EVB_RK3308
+	bool "EVB_RK3308"
+	select BOARD_LATE_INIT
+
+config TARGET_ROC_RK3308_CC
+       bool "Firefly roc-rk3308-cc"
+	select BOARD_LATE_INIT
+
+config SYS_SOC
+	default "rk3308"
+
+config SYS_MALLOC_F_LEN
+	default 0x400
+
+config SPL_SERIAL_SUPPORT
+	default y
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff000500
+
+
+source "board/rockchip/evb_rk3308/Kconfig"
+source "board/firefly/firefly-rk3308/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3308/Makefile b/arch/arm/mach-rockchip/rk3308/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ce4d44bb34650cd82e099088d82db83dd4ecfedf
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3308/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += syscon_rk3308.o
+obj-y += rk3308.o
+obj-y += clk_rk3308.o
diff --git a/arch/arm/mach-rockchip/rk3308/clk_rk3308.c b/arch/arm/mach-rockchip/rk3308/clk_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..51b43153e8613f50d2a3e5210f85e9142b9ad30d
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3308/clk_rk3308.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch/cru_rk3308.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3308_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rk3308_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rk3308/rk3308.c b/arch/arm/mach-rockchip/rk3308/rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..f27f9e8c0b28a65ddd072f65109d46dbc2c0f11f
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3308/rk3308.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *Copyright (c) 2018 Rockchip Electronics Co., Ltd
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/grf_rk3308.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/gpio.h>
+#include <debug_uart.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#include <asm/armv8/mmu.h>
+static struct mm_region rk3308_mem_map[] = {
+	{
+		.virt = 0x0UL,
+		.phys = 0x0UL,
+		.size = 0xff000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xff000000UL,
+		.phys = 0xff000000UL,
+		.size = 0x01000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = rk3308_mem_map;
+
+#define GRF_BASE	0xff000000
+#define SGRF_BASE	0xff2b0000
+
+enum {
+	GPIO1C7_SHIFT		= 8,
+	GPIO1C7_MASK		= GENMASK(11, 8),
+	GPIO1C7_GPIO		= 0,
+	GPIO1C7_UART1_RTSN,
+	GPIO1C7_UART2_TX_M0,
+	GPIO1C7_SPI2_MOSI,
+	GPIO1C7_JTAG_TMS,
+
+	GPIO1C6_SHIFT		= 4,
+	GPIO1C6_MASK		= GENMASK(7, 4),
+	GPIO1C6_GPIO		= 0,
+	GPIO1C6_UART1_CTSN,
+	GPIO1C6_UART2_RX_M0,
+	GPIO1C6_SPI2_MISO,
+	GPIO1C6_JTAG_TCLK,
+
+	GPIO4D3_SHIFT           = 6,
+	GPIO4D3_MASK            = GENMASK(7, 6),
+	GPIO4D3_GPIO            = 0,
+	GPIO4D3_SDMMC_D3,
+	GPIO4D3_UART2_TX_M1,
+
+	GPIO4D2_SHIFT           = 4,
+	GPIO4D2_MASK            = GENMASK(5, 4),
+	GPIO4D2_GPIO            = 0,
+	GPIO4D2_SDMMC_D2,
+	GPIO4D2_UART2_RX_M1,
+
+	UART2_IO_SEL_SHIFT	= 2,
+	UART2_IO_SEL_MASK	= GENMASK(3, 2),
+	UART2_IO_SEL_M0		= 0,
+	UART2_IO_SEL_M1,
+	UART2_IO_SEL_USB,
+
+	GPIO3B3_SEL_SRC_CTRL_SHIFT	= 7,
+	GPIO3B3_SEL_SRC_CTRL_MASK	= BIT(7),
+	GPIO3B3_SEL_SRC_CTRL_IOMUX	= 0,
+	GPIO3B3_SEL_SRC_CTRL_SEL_PLUS,
+
+	GPIO3B3_SEL_PLUS_SHIFT		= 4,
+	GPIO3B3_SEL_PLUS_MASK		= GENMASK(6, 4),
+	GPIO3B3_SEL_PLUS_GPIO3_B3	= 0,
+	GPIO3B3_SEL_PLUS_FLASH_ALE,
+	GPIO3B3_SEL_PLUS_EMMC_PWREN,
+	GPIO3B3_SEL_PLUS_SPI1_CLK,
+	GPIO3B3_SEL_PLUS_LCDC_D23_M1,
+
+	GPIO3B2_SEL_SRC_CTRL_SHIFT	= 3,
+	GPIO3B2_SEL_SRC_CTRL_MASK	= BIT(3),
+	GPIO3B2_SEL_SRC_CTRL_IOMUX	= 0,
+	GPIO3B2_SEL_SRC_CTRL_SEL_PLUS,
+
+	GPIO3B2_SEL_PLUS_SHIFT		= 0,
+	GPIO3B2_SEL_PLUS_MASK		= GENMASK(2, 0),
+	GPIO3B2_SEL_PLUS_GPIO3_B2	= 0,
+	GPIO3B2_SEL_PLUS_FLASH_RDN,
+	GPIO3B2_SEL_PLUS_EMMC_RSTN,
+	GPIO3B2_SEL_PLUS_SPI1_MISO,
+	GPIO3B2_SEL_PLUS_LCDC_D22_M1,
+};
+
+enum {
+	IOVSEL3_CTRL_SHIFT	= 8,
+	IOVSEL3_CTRL_MASK	= BIT(8),
+	VCCIO3_SEL_BY_GPIO	= 0,
+	VCCIO3_SEL_BY_IOVSEL3,
+
+	IOVSEL3_SHIFT		= 3,
+	IOVSEL3_MASK		= BIT(3),
+	VCCIO3_3V3		= 0,
+	VCCIO3_1V8,
+};
+
+/*
+ * The voltage of VCCIO3(which is the voltage domain of emmc/flash/sfc
+ * interface) can indicated by GPIO0_A4 or io_vsel3. The SOC defaults
+ * use GPIO0_A4 to indicate power supply voltage for VCCIO3 by hardware,
+ * then we can switch to io_vsel3 after system power on, and release GPIO0_A4
+ * for other usage.
+ */
+
+#define GPIO0_A4	4
+
+int rk_board_init(void)
+{
+	static struct rk3308_grf * const grf = (void *)GRF_BASE;
+	u32 val;
+	int ret;
+
+	ret = gpio_request(GPIO0_A4, "gpio0_a4");
+	if (ret < 0) {
+		printf("request for gpio0_a4 failed:%d\n", ret);
+		return 0;
+	}
+
+	gpio_direction_input(GPIO0_A4);
+
+	if (gpio_get_value(GPIO0_A4))
+		val = VCCIO3_SEL_BY_IOVSEL3 << IOVSEL3_CTRL_SHIFT |
+		      VCCIO3_1V8 << IOVSEL3_SHIFT;
+	else
+		val = VCCIO3_SEL_BY_IOVSEL3 << IOVSEL3_CTRL_SHIFT |
+		      VCCIO3_3V3 << IOVSEL3_SHIFT;
+	rk_clrsetreg(&grf->soc_con0, IOVSEL3_CTRL_MASK | IOVSEL3_MASK, val);
+
+	gpio_free(GPIO0_A4);
+	return 0;
+}
+
+#if defined(CONFIG_DEBUG_UART)
+__weak void board_debug_uart_init(void)
+{
+	static struct rk3308_grf * const grf = (void *)GRF_BASE;
+
+	/* Enable early UART2 channel m1 on the rk3308 */
+	rk_clrsetreg(&grf->soc_con5, UART2_IO_SEL_MASK,
+		     UART2_IO_SEL_M1 << UART2_IO_SEL_SHIFT);
+	rk_clrsetreg(&grf->gpio4d_iomux,
+		     GPIO4D3_MASK | GPIO4D2_MASK,
+		     GPIO4D2_UART2_RX_M1 << GPIO4D2_SHIFT |
+		     GPIO4D3_UART2_TX_M1 << GPIO4D3_SHIFT);
+}
+#endif
+
+#if defined(CONFIG_SPL_BUILD)
+int arch_cpu_init(void)
+{
+	static struct rk3308_sgrf * const sgrf = (void *)SGRF_BASE;
+
+	/* Set CRYPTO SDMMC EMMC NAND SFC USB master bus to be secure access */
+	rk_clrreg(&sgrf->con_secure0, 0x2b83);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c b/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..b380ff5723361129e2911e74a4ed3c061a91fdb8
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id rk3308_syscon_ids[] = {
+	{ .compatible = "rockchip,rk3308-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rk3308) = {
+	.name = "rk3308_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3308_syscon_ids,
+};
diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig
index f781eacd1630ba7f50af05aba3d8450c9b6292df..01af3f1464c3723ae2de2daedca4323b4d14531c 100644
--- a/arch/arm/mach-rockchip/rk3399/Kconfig
+++ b/arch/arm/mach-rockchip/rk3399/Kconfig
@@ -62,6 +62,25 @@ config TARGET_CHROMEBOOK_BOB
 	  display. It includes a Chrome OS EC (Cortex-M3) to provide access to
 	  the keyboard and battery functions.
 
+config TARGET_ROCKPRO64_RK3399
+	bool "Pine64 Rockpro64 board"
+	help
+	  Rockro64 is SBC produced by Pine64. Key features:
+
+	   * Rockchip RK3399
+	   * 2/4GB Dual-Channel LPDDR3
+	   * SD card slot
+	   * eMMC socket
+	   * 128Mb SPI Flash
+	   * Gigabit ethernet
+	   * PCIe 4X slot
+	   * WiFI/BT module socket
+	   * HDMI In/Out, DP, MIPI DSI/CSI, eDP
+	   * USB 3.0, 2.0
+	   * USB Type C power and data
+	   * GPIO expansion ports
+	   * DC 12V/2A
+
 endchoice
 
 config ROCKCHIP_BOOT_MODE_REG
@@ -98,5 +117,6 @@ source "board/rockchip/evb_rk3399/Kconfig"
 source "board/theobroma-systems/puma_rk3399/Kconfig"
 source "board/vamrs/rock960_rk3399/Kconfig"
 source "board/google/gru/Kconfig"
+source "board/pine64/rockpro64_rk3399/Kconfig"
 
 endif
diff --git a/arch/arm/mach-rockchip/sdram_common.c b/arch/arm/mach-rockchip/sdram.c
similarity index 60%
rename from arch/arm/mach-rockchip/sdram_common.c
rename to arch/arm/mach-rockchip/sdram.c
index 22a4aca9402a9684d16d844cdde5f425d1a1e83a..af00a6b637a327b086512f64ffe6f961c1bd8582 100644
--- a/arch/arm/mach-rockchip/sdram_common.c
+++ b/arch/arm/mach-rockchip/sdram.c
@@ -7,7 +7,7 @@
 #include <dm.h>
 #include <ram.h>
 #include <asm/io.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 #include <dm/uclass-internal.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -76,39 +76,88 @@ int dram_init_banksize(void)
 
 size_t rockchip_sdram_size(phys_addr_t reg)
 {
-	u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
+	u32 rank, cs0_col, bk, cs0_row, cs1_row, bw, row_3_4;
 	size_t chipsize_mb = 0;
 	size_t size_mb = 0;
 	u32 ch;
-
-	u32 sys_reg = readl(reg);
-	u32 ch_num = 1 + ((sys_reg >> SYS_REG_NUM_CH_SHIFT)
+	u32 cs1_col = 0;
+	u32 bg = 0;
+	u32 dbw, dram_type;
+	u32 sys_reg2 = readl(reg);
+	u32 sys_reg3 = readl(reg + 4);
+	u32 ch_num = 1 + ((sys_reg2 >> SYS_REG_NUM_CH_SHIFT)
 		       & SYS_REG_NUM_CH_MASK);
 
-	debug("%s %x %x\n", __func__, (u32)reg, sys_reg);
+	dram_type = (sys_reg2 >> SYS_REG_DDRTYPE_SHIFT) & SYS_REG_DDRTYPE_MASK;
+	debug("%s %x %x\n", __func__, (u32)reg, sys_reg2);
 	for (ch = 0; ch < ch_num; ch++) {
-		rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
+		rank = 1 + (sys_reg2 >> SYS_REG_RANK_SHIFT(ch) &
 			SYS_REG_RANK_MASK);
-		col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
-		bk = 3 - ((sys_reg >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
-		cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
+		cs0_col = 9 + (sys_reg2 >> SYS_REG_COL_SHIFT(ch) &
+			  SYS_REG_COL_MASK);
+		cs1_col = cs0_col;
+		bk = 3 - ((sys_reg2 >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
+		if ((sys_reg3 >> SYS_REG_VERSION_SHIFT &
+		     SYS_REG_VERSION_MASK) == 0x2) {
+			cs1_col = 9 + (sys_reg3 >> SYS_REG_CS1_COL_SHIFT(ch) &
+				  SYS_REG_CS1_COL_MASK);
+			if (((sys_reg3 >> SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
+			    SYS_REG_EXTEND_CS0_ROW_MASK) << 2) + (sys_reg2 >>
+			    SYS_REG_CS0_ROW_SHIFT(ch) &
+			    SYS_REG_CS0_ROW_MASK) == 7)
+				cs0_row = 12;
+			else
+				cs0_row = 13 + (sys_reg2 >>
+					  SYS_REG_CS0_ROW_SHIFT(ch) &
+					  SYS_REG_CS0_ROW_MASK) +
+					  ((sys_reg3 >>
+					  SYS_REG_EXTEND_CS0_ROW_SHIFT(ch) &
+					  SYS_REG_EXTEND_CS0_ROW_MASK) << 2);
+			if (((sys_reg3 >> SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
+			    SYS_REG_EXTEND_CS1_ROW_MASK) << 2) + (sys_reg2 >>
+			    SYS_REG_CS1_ROW_SHIFT(ch) &
+			    SYS_REG_CS1_ROW_MASK) == 7)
+				cs1_row = 12;
+			else
+				cs1_row = 13 + (sys_reg2 >>
+					  SYS_REG_CS1_ROW_SHIFT(ch) &
+					  SYS_REG_CS1_ROW_MASK) +
+					  ((sys_reg3 >>
+					  SYS_REG_EXTEND_CS1_ROW_SHIFT(ch) &
+					  SYS_REG_EXTEND_CS1_ROW_MASK) << 2);
+		} else {
+			cs0_row = 13 + (sys_reg2 >> SYS_REG_CS0_ROW_SHIFT(ch) &
 				SYS_REG_CS0_ROW_MASK);
-		cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
+			cs1_row = 13 + (sys_reg2 >> SYS_REG_CS1_ROW_SHIFT(ch) &
 				SYS_REG_CS1_ROW_MASK);
-		bw = (2 >> ((sys_reg >> SYS_REG_BW_SHIFT(ch)) &
+		}
+		bw = (2 >> ((sys_reg2 >> SYS_REG_BW_SHIFT(ch)) &
 			SYS_REG_BW_MASK));
-		row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
+		row_3_4 = sys_reg2 >> SYS_REG_ROW_3_4_SHIFT(ch) &
 			SYS_REG_ROW_3_4_MASK;
-
-		chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
+		if (dram_type == DDR4) {
+			dbw = (sys_reg2 >> SYS_REG_DBW_SHIFT(ch)) &
+				SYS_REG_DBW_MASK;
+			bg = (dbw == 2) ? 2 : 1;
+		}
+		chipsize_mb = (1 << (cs0_row + cs0_col + bk + bg + bw - 20));
 
 		if (rank > 1)
-			chipsize_mb += chipsize_mb >> (cs0_row - cs1_row);
+			chipsize_mb += chipsize_mb >> ((cs0_row - cs1_row) +
+				       (cs0_col - cs1_col));
 		if (row_3_4)
 			chipsize_mb = chipsize_mb * 3 / 4;
 		size_mb += chipsize_mb;
-		debug("rank %d col %d bk %d cs0_row %d bw %d row_3_4 %d\n",
-		      rank, col, bk, cs0_row, bw, row_3_4);
+		if (rank > 1)
+			debug("rank %d cs0_col %d cs1_col %d bk %d cs0_row %d\
+			       cs1_row %d bw %d row_3_4 %d\n",
+			       rank, cs0_col, cs1_col, bk, cs0_row,
+			       cs1_row, bw, row_3_4);
+		else
+			debug("rank %d cs0_col %d bk %d cs0_row %d\
+			       bw %d row_3_4 %d\n",
+			       rank, cs0_col, bk, cs0_row,
+			       bw, row_3_4);
 	}
 
 	/*
diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c
index 92102b39e7d5142d9a4d6e547d686e1419916d6e..514032a44aab5db692af928d2d5760d6fa34cc00 100644
--- a/arch/arm/mach-rockchip/spl.c
+++ b/arch/arm/mach-rockchip/spl.c
@@ -9,7 +9,6 @@
 #include <ram.h>
 #include <spl.h>
 #include <asm/arch-rockchip/bootrom.h>
-#include <asm/arch-rockchip/sdram.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -103,7 +102,7 @@ __weak int arch_cpu_init(void)
 void board_init_f(ulong dummy)
 {
 	int ret;
-#if !defined(CONFIG_SUPPORT_TPL) || defined(CONFIG_SPL_OS_BOOT)
+#if !defined(CONFIG_TPL) || defined(CONFIG_SPL_OS_BOOT)
 	struct udevice *dev;
 #endif
 
@@ -128,20 +127,20 @@ void board_init_f(ulong dummy)
 		hang();
 	}
 	arch_cpu_init();
-#if !defined(CONFIG_SUPPORT_TPL) || defined(CONFIG_SPL_OS_BOOT)
-	debug("\nspl:init dram\n");
-	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
-	if (ret) {
-		printf("DRAM init failed: %d\n", ret);
-		return;
-	}
-#endif
 #if !defined(CONFIG_ROCKCHIP_RK3188)
 	rockchip_stimer_init();
 #endif
 #ifdef CONFIG_SYS_ARCH_TIMER
 	/* Init ARM arch timer in arch/arm/cpu/armv7/arch_timer.c */
 	timer_init();
+#endif
+#if !defined(CONFIG_TPL) || defined(CONFIG_SPL_OS_BOOT)
+	debug("\nspl:init dram\n");
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		printf("DRAM init failed: %d\n", ret);
+		return;
+	}
 #endif
 	preloader_console_init();
 }
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 8ac49bdd0603860c5719190099a60dd2782f463a..01c9dd51be8c5805af1d4148775fee40eb4ff59d 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -41,5 +41,5 @@ obj-y	+= time.o
 endif # not minimal
 
 ifdef CONFIG_SPL_BUILD
-obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
+obj-$(CONFIG_$(SPL_TPL)_FRAMEWORK) += spl.o
 endif
diff --git a/board/firefly/firefly-rk3308/Kconfig b/board/firefly/firefly-rk3308/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..80b1ad85a2e4ec4970b22b76c6bad34e946c112f
--- /dev/null
+++ b/board/firefly/firefly-rk3308/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_ROC_RK3308_CC
+
+config SYS_BOARD
+	default "firefly-rk3308"
+
+config SYS_VENDOR
+	default "firefly"
+
+config SYS_CONFIG_NAME
+	default "firefly_rk3308"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/firefly/firefly-rk3308/MAINTAINERS b/board/firefly/firefly-rk3308/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..199079717e735314429567d4490a12c327177a37
--- /dev/null
+++ b/board/firefly/firefly-rk3308/MAINTAINERS
@@ -0,0 +1,5 @@
+ROC-RK3308-CC
+M:      Andy Yan <andy.yan@rock-chips.com>
+S:      Maintained
+F:      board/firefly/firefly-rk3308/roc_cc_rk3308.c
+F:      configs/roc-cc-rk3308_defconfig
diff --git a/board/firefly/firefly-rk3308/Makefile b/board/firefly/firefly-rk3308/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..4c50b26ea9b001c320a1e64aa1d1b549ffe41554
--- /dev/null
+++ b/board/firefly/firefly-rk3308/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2018 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= roc_cc_rk3308.o
diff --git a/board/firefly/firefly-rk3308/roc_cc_rk3308.c b/board/firefly/firefly-rk3308/roc_cc_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f0a6594b679ae6a6673f674f415dd064057d56d
--- /dev/null
+++ b/board/firefly/firefly-rk3308/roc_cc_rk3308.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <asm/io.h>
+#include <asm/arch/grf_rk3308.h>
+#include <asm/arch-rockchip/hardware.h>
+
+#if defined(CONFIG_DEBUG_UART)
+#define GRF_BASE	0xff000000
+
+enum {
+	GPIO1C7_SHIFT		= 8,
+	GPIO1C7_MASK		= GENMASK(11, 8),
+	GPIO1C7_GPIO		= 0,
+	GPIO1C7_UART1_RTSN,
+	GPIO1C7_UART2_TX_M0,
+	GPIO1C7_SPI2_MOSI,
+	GPIO1C7_JTAG_TMS,
+
+	GPIO1C6_SHIFT		= 4,
+	GPIO1C6_MASK		= GENMASK(7, 4),
+	GPIO1C6_GPIO		= 0,
+	GPIO1C6_UART1_CTSN,
+	GPIO1C6_UART2_RX_M0,
+	GPIO1C6_SPI2_MISO,
+	GPIO1C6_JTAG_TCLK,
+
+	GPIO4D3_SHIFT           = 6,
+	GPIO4D3_MASK            = GENMASK(7, 6),
+	GPIO4D3_GPIO            = 0,
+	GPIO4D3_SDMMC_D3,
+	GPIO4D3_UART2_TX_M1,
+
+	GPIO4D2_SHIFT           = 4,
+	GPIO4D2_MASK            = GENMASK(5, 4),
+	GPIO4D2_GPIO            = 0,
+	GPIO4D2_SDMMC_D2,
+	GPIO4D2_UART2_RX_M1,
+
+	UART2_IO_SEL_SHIFT	= 2,
+	UART2_IO_SEL_MASK	= GENMASK(3, 2),
+	UART2_IO_SEL_M0		= 0,
+	UART2_IO_SEL_M1,
+	UART2_IO_SEL_USB,
+};
+
+void board_debug_uart_init(void)
+{
+	static struct rk3308_grf * const grf = (void *)GRF_BASE;
+
+	/* Enable early UART2 channel m0 on the rk3308 */
+	rk_clrsetreg(&grf->soc_con5, UART2_IO_SEL_MASK,
+		     UART2_IO_SEL_M0 << UART2_IO_SEL_SHIFT);
+	rk_clrsetreg(&grf->gpio1ch_iomux,
+		     GPIO1C6_MASK | GPIO1C7_MASK,
+		     GPIO1C6_UART2_RX_M0 << GPIO1C6_SHIFT |
+		     GPIO1C7_UART2_TX_M0 << GPIO1C7_SHIFT);
+}
+#endif
+
+#define KEY_DOWN_MIN_VAL        0
+#define KEY_DOWN_MAX_VAL        30
+
+int rockchip_dnl_key_pressed(void)
+{
+	unsigned int val;
+
+	if (adc_channel_single_shot("saradc", 1, &val)) {
+		printf("%s read adc key val failed\n", __func__);
+		return false;
+	}
+
+	if (val >= KEY_DOWN_MIN_VAL && val <= KEY_DOWN_MAX_VAL)
+		return true;
+	else
+		return false;
+}
diff --git a/board/pine64/rockpro64_rk3399/Kconfig b/board/pine64/rockpro64_rk3399/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..3353f1fd0958f9a9c09b97f85b09042bcf7a1f66
--- /dev/null
+++ b/board/pine64/rockpro64_rk3399/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_ROCKPRO64_RK3399
+
+config SYS_BOARD
+	default "rockpro64_rk3399"
+
+config SYS_VENDOR
+	default "pine64"
+
+config SYS_CONFIG_NAME
+	default "rockpro64_rk3399"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/pine64/rockpro64_rk3399/MAINTAINERS b/board/pine64/rockpro64_rk3399/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..303db144aab58c785756db8a4e988c0650abb8c6
--- /dev/null
+++ b/board/pine64/rockpro64_rk3399/MAINTAINERS
@@ -0,0 +1,8 @@
+ROCKPRO64
+M:	Akash Gajjar <akash@openedev.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+F:	board/pine64/rockpro64_rk3399
+F:	include/configs/rockpro64_rk3399.h
+F:	arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
+F:	configs/rockpro64-rk3399_defconfig
diff --git a/board/pine64/rockpro64_rk3399/Makefile b/board/pine64/rockpro64_rk3399/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b015c47e6fa64d05feeee9f75573f61342e698dc
--- /dev/null
+++ b/board/pine64/rockpro64_rk3399/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2019 Vasily Khoruzhick
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= rockpro64-rk3399.o
diff --git a/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c b/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f602357713b378689e57657c8fa563241c334f0
--- /dev/null
+++ b/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Vasily Khoruzhick <anarsoul@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/grf_rk3399.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/misc.h>
+
+#define GRF_IO_VSEL_BT565_SHIFT 0
+#define PMUGRF_CON0_VSEL_SHIFT 8
+
+#ifdef CONFIG_MISC_INIT_R
+static void setup_iodomain(void)
+{
+	struct rk3399_grf_regs *grf =
+	    syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	struct rk3399_pmugrf_regs *pmugrf =
+	    syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+
+	/* BT565 is in 1.8v domain */
+	rk_setreg(&grf->io_vsel, 1 << GRF_IO_VSEL_BT565_SHIFT);
+
+	/* Set GPIO1 1.8v/3.0v source select to PMU1830_VOL */
+	rk_setreg(&pmugrf->soc_con0, 1 << PMUGRF_CON0_VSEL_SHIFT);
+}
+
+int misc_init_r(void)
+{
+	const u32 cpuid_offset = 0x7;
+	const u32 cpuid_length = 0x10;
+	u8 cpuid[cpuid_length];
+	int ret;
+
+	setup_iodomain();
+
+	ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
+	if (ret)
+		return ret;
+
+	ret = rockchip_cpuid_set(cpuid, cpuid_length);
+	if (ret)
+		return ret;
+
+	ret = rockchip_setup_macaddr();
+
+	return ret;
+}
+
+#endif
diff --git a/board/rockchip/evb_px30/Kconfig b/board/rockchip/evb_px30/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..0042c8e4db155cdbe39666ef85bae24da76ad1ce
--- /dev/null
+++ b/board/rockchip/evb_px30/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_EVB_PX30
+
+config SYS_BOARD
+	default "evb_px30"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "evb_px30"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/evb_px30/MAINTAINERS b/board/rockchip/evb_px30/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..cf13f2419ea2bb8a58e09b783f0a67142ccfc989
--- /dev/null
+++ b/board/rockchip/evb_px30/MAINTAINERS
@@ -0,0 +1,6 @@
+EVB-PX30
+M:      Kever Yang <kever.yang@rock-chips.com>
+S:      Maintained
+F:      board/rockchip/evb_px30
+F:      include/configs/evb_px30.h
+F:      configs/evb-px30_defconfig
diff --git a/board/rockchip/evb_px30/Makefile b/board/rockchip/evb_px30/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..74b0b9f44fa8ed8511a8febda51a22dbe8180449
--- /dev/null
+++ b/board/rockchip/evb_px30/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2017 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= evb_px30.o
diff --git a/board/rockchip/evb_px30/evb_px30.c b/board/rockchip/evb_px30/evb_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..29464ae63ec7c6c9d6dd3498d60376310beb9a32
--- /dev/null
+++ b/board/rockchip/evb_px30/evb_px30.c
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
diff --git a/board/rockchip/evb_rk3308/Kconfig b/board/rockchip/evb_rk3308/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..0074429cb6d8e56a6bf3ffac34b0233771d6c173
--- /dev/null
+++ b/board/rockchip/evb_rk3308/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_EVB_RK3308
+
+config SYS_BOARD
+	default "evb_rk3308"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "evb_rk3308"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/evb_rk3308/MAINTAINERS b/board/rockchip/evb_rk3308/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..0af119ae0aad285f29acd4944b8144bf85eeccf0
--- /dev/null
+++ b/board/rockchip/evb_rk3308/MAINTAINERS
@@ -0,0 +1,6 @@
+EVB-RK3308
+M:      Andy Yan <andy.yan@rock-chips.com>
+S:      Maintained
+F:      board/rockchip/evb_rk3308
+F:      include/configs/evb_rk3308.h
+F:      configs/evb-rk3308_defconfig
diff --git a/board/rockchip/evb_rk3308/Makefile b/board/rockchip/evb_rk3308/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..05de5560f14cfca984ac32ded041d463933b3842
--- /dev/null
+++ b/board/rockchip/evb_rk3308/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2018 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= evb_rk3308.o
diff --git a/board/rockchip/evb_rk3308/evb_rk3308.c b/board/rockchip/evb_rk3308/evb_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..180f1fe4f00bb6735c6cb43ccdd6d30082ab68eb
--- /dev/null
+++ b/board/rockchip/evb_rk3308/evb_rk3308.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <adc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define KEY_DOWN_MIN_VAL        0
+#define KEY_DOWN_MAX_VAL        30
+
+/*
+ * Two board variants whith adc channel 3 is for board id
+ * v10: 1024, v11: 512
+ * v10: adc channel 0 for dnl key
+ * v11: adc channel 1 for dnl key
+ */
+int rockchip_dnl_key_pressed(void)
+{
+	unsigned int key_val, id_val;
+	int key_ch;
+
+	if (adc_channel_single_shot("saradc", 3, &id_val)) {
+		printf("%s read board id failed\n", __func__);
+		return false;
+	}
+
+	if (abs(id_val - 1024) <= 30)
+		key_ch = 0;
+	else
+		key_ch = 1;
+
+	if (adc_channel_single_shot("saradc", key_ch, &key_val)) {
+		printf("%s read adc key val failed\n", __func__);
+		return false;
+	}
+
+	if (key_val >= KEY_DOWN_MIN_VAL && key_val <= KEY_DOWN_MAX_VAL)
+		return true;
+	else
+		return false;
+}
diff --git a/board/rockchip/evb_rk3399/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS
index 139791795ec129cef69a5d681e53c93351305ea6..eab4c4c5259f510bf444d394c7abbf362fa5a697 100644
--- a/board/rockchip/evb_rk3399/MAINTAINERS
+++ b/board/rockchip/evb_rk3399/MAINTAINERS
@@ -58,7 +58,7 @@ F:	arch/arm/dts/rk3399-orangepi-u-boot.dtsi
 ROC-RK3399-PC
 M:	Levin Du <djw@t-chip.com.cn>
 S:	Maintained
-F:	configs/roc-rk3399-pc_defconfig
+F:	configs/roc-pc-rk3399_defconfig
 F:	arch/arm/dts/rk3399-roc-pc-u-boot.dtsi
 
 ROCK-PI-4
@@ -67,10 +67,3 @@ M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
 F:	configs/rock-pi-4-rk3399_defconfig
 F:	arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi
-
-ROCKPRO64
-M:	Akash Gajjar <akash@openedev.com>
-M:	Jagan Teki <jagan@amarulasolutions.com>
-S:	Maintained
-F:	configs/rockpro64-rk3399_defconfig
-F:	arch/arm/dts/rk3399-rockpro64-u-boot.dtsi
diff --git a/board/rockchip/tinker_rk3288/MAINTAINERS b/board/rockchip/tinker_rk3288/MAINTAINERS
index cddceafb6e93ac0e1c3bac858dd65ec0333f85a5..ed5de682c97761fd22f0a16c67d82a8e58c31229 100644
--- a/board/rockchip/tinker_rk3288/MAINTAINERS
+++ b/board/rockchip/tinker_rk3288/MAINTAINERS
@@ -4,3 +4,10 @@ S:	Maintained
 F:	board/rockchip/tinker_rk3288
 F:	include/configs/tinker_rk3288.h
 F:	configs/tinker-rk3288_defconfig
+
+TINKER-S-RK3288
+M:	Michael Trimarchi <michael@amarulasolutions.com>
+S:	Maintained
+F:	board/rockchip/tinker_rk3288
+F:	include/configs/tinker_rk3288.h
+F:	configs/tinker-s-rk3288_defconfig
diff --git a/board/rockchip/tinker_rk3288/tinker-rk3288.c b/board/rockchip/tinker_rk3288/tinker-rk3288.c
index 6c76c3c25c4d644a5f6c2c27357dec7d6f56b4a8..7a0c3c997d9bddb483777e1c7762ac0ad7645877 100644
--- a/board/rockchip/tinker_rk3288/tinker-rk3288.c
+++ b/board/rockchip/tinker_rk3288/tinker-rk3288.c
@@ -8,6 +8,8 @@
 #include <env.h>
 #include <i2c_eeprom.h>
 #include <netdev.h>
+#include <asm/arch-rockchip/bootrom.h>
+#include <asm/io.h>
 
 static int get_ethaddr_from_eeprom(u8 *addr)
 {
@@ -33,3 +35,13 @@ int rk3288_board_late_init(void)
 
 	return 0;
 }
+
+int mmc_get_env_dev(void)
+{
+	u32 bootdevice_brom_id = readl(BROM_BOOTSOURCE_ID_ADDR);
+
+	if (bootdevice_brom_id == BROM_BOOTSOURCE_EMMC)
+		return 0;
+
+	return 1;
+}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 8f0ba8ef831ec98a3d02ed590672aed7962f4ade..1f122833a777ea813ebb8e7a251fb1bc0fef7e37 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1241,6 +1241,14 @@ config TPL_SIZE_LIMIT
 	  Specifies the maximum length of the U-Boot TPL image.
 	  If this value is zero, it is ignored.
 
+config TPL_FRAMEWORK
+	bool "Support TPL based upon the common SPL framework"
+	default y if SPL_FRAMEWORK
+	help
+	  Enable the SPL framework under common/spl/ for TPL builds.
+	  This framework supports MMC, NAND and YMODEM and other methods
+	  loading of U-Boot's SPL stage. If unsure, say Y.
+
 config TPL_HANDOFF
 	bool "Pass hand-off information from TPL to SPL and U-Boot proper"
 	depends on HANDOFF && TPL_BLOBLIST
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 5ce6f4ae480c9882f5d4e1c274831ad08105efd9..eaa57f5ce5e48646b77640ab5197281b3cbbabd9 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -7,7 +7,7 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
+obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTROM_SUPPORT) += spl_bootrom.o
 obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit.o
 obj-$(CONFIG_$(SPL_TPL_)NOR_SUPPORT) += spl_nor.o
diff --git a/configs/evb-px30_defconfig b/configs/evb-px30_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..36fba600c0964edaa788949e4844831f7c78f035
--- /dev/null
+++ b/configs/evb-px30_defconfig
@@ -0,0 +1,111 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_PX30=y
+CONFIG_TARGET_EVB_PX30=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEBUG_UART_BASE=0xFF160000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_SPL_TEXT_BASE=0x00000000
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x600
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_CONSOLE_MUX is not set
+CONFIG_DEFAULT_FDT_FILE="rockchip/px30-evb.dtb"
+CONFIG_MISC_INIT_R=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_BOOTROM_SUPPORT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_STACK_R=y
+# CONFIG_TPL_BANNER_PRINT is not set
+CONFIG_SPL_CRC32_SUPPORT=y
+CONFIG_SPL_ATF=y
+# CONFIG_TPL_FRAMEWORK is not set
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_LZMADEC is not set
+# CONFIG_CMD_UNZIP is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPT=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_MISC is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="px30-evb"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_FASTBOOT_BUF_ADDR=0x800800
+CONFIG_FASTBOOT_BUF_SIZE=0x04000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_OTP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_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_TPL_RAM=y
+CONFIG_ROCKCHIP_SDRAM_COMMON=y
+CONFIG_DM_RESET=y
+# CONFIG_SPECIFY_CONSOLE_INDEX is not set
+# CONFIG_TPL_DM_SERIAL is not set
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_SKIP_INIT=y
+CONFIG_SOUND=y
+CONFIG_SYSRESET=y
+CONFIG_OPTEE=y
+CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_LCD=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_LZ4=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/evb-rk3308_defconfig b/configs/evb-rk3308_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..36d30dfa805b09756f026954cd3133949465982d
--- /dev/null
+++ b/configs/evb-rk3308_defconfig
@@ -0,0 +1,77 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00600000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3308=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_TARGET_EVB_RK3308=y
+CONFIG_SPL_STACK_R_ADDR=0xc00000
+CONFIG_DEBUG_UART_BASE=0xFF0C0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_ANDROID_BOOT_IMAGE=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=0
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_STACK_R=y
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPT=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_MISC is not set
+# CONFIG_DOS_PARTITION is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3308-evb"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+# CONFIG_USB_FUNCTION_FASTBOOT is not set
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY=y
+CONFIG_PINCTRL=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_SKIP_INIT=y
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZ4=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index cc6164e0901d3f8963789eb73b197045a601807d..a59dab48533698d774b6c256ec40717a29bfee4f 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -45,7 +45,6 @@ CONFIG_SPL_SYSCON=y
 CONFIG_TPL_SYSCON=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
-CONFIG_TPL_CLK=y
 CONFIG_FASTBOOT_BUF_ADDR=0x800800
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=1
@@ -75,6 +74,7 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_SYSRESET=y
+# CONFIG_TPL_SYSRESET is not set
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/roc-cc-rk3308_defconfig b/configs/roc-cc-rk3308_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..82ebe6a786ee6216ac2a3fb750931fcb559ec08d
--- /dev/null
+++ b/configs/roc-cc-rk3308_defconfig
@@ -0,0 +1,77 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00600000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3308=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_TARGET_ROC_RK3308_CC=y
+CONFIG_SPL_STACK_R_ADDR=0xc00000
+CONFIG_DEBUG_UART_BASE=0xFF0C0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_ANDROID_BOOT_IMAGE=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=0
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_STACK_R=y
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPT=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_MISC is not set
+# CONFIG_DOS_PARTITION is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3308-roc-cc"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_CLK=y
+# CONFIG_USB_FUNCTION_FASTBOOT is not set
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY=y
+CONFIG_PINCTRL=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_DM_RESET=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_SKIP_INIT=y
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZ4=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/roc-rk3399-pc_defconfig b/configs/roc-pc-rk3399_defconfig
similarity index 100%
rename from configs/roc-rk3399-pc_defconfig
rename to configs/roc-pc-rk3399_defconfig
diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig
index b12863567291e358fcd23682722fe697932ab9c3..021f982e687d3ed578728861eb94085f1afbe3cf 100644
--- a/configs/rock64-rk3328_defconfig
+++ b/configs/rock64-rk3328_defconfig
@@ -47,7 +47,6 @@ CONFIG_SPL_SYSCON=y
 CONFIG_TPL_SYSCON=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
-CONFIG_TPL_CLK=y
 CONFIG_FASTBOOT_BUF_ADDR=0x800800
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=1
@@ -76,6 +75,7 @@ CONFIG_DM_RESET=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYSRESET=y
+# CONFIG_TPL_SYSRESET is not set
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/rock960-rk3399_defconfig b/configs/rock960-rk3399_defconfig
index 0d6c55ce745f2f66da122105c92b3e1aedb30d42..979ca0f93bfc7bcaed8848b2f34b56ff57741ad6 100644
--- a/configs/rock960-rk3399_defconfig
+++ b/configs/rock960-rk3399_defconfig
@@ -7,13 +7,15 @@ CONFIG_TARGET_ROCK960_RK3399=y
 CONFIG_DEBUG_UART_BASE=0xFF1A0000
 CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_DEBUG_UART=y
-CONFIG_SPL_TEXT_BASE=0xff8c2000
 CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-rock960.dtb"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
 CONFIG_SPL_STACK_R=y
-CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_TPL=y
 CONFIG_SYS_PROMPT="rock960 => "
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPT=y
@@ -55,4 +57,6 @@ CONFIG_USB_ETHER_ASIX88179=y
 CONFIG_USB_ETHER_MCS7830=y
 CONFIG_USB_ETHER_RTL8152=y
 CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_TINY_MEMSET=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig
index 423148b1a56e493e58e160e264a36276269c07f3..94279ed842b126e89c4880cc22368eb4a1e22cf7 100644
--- a/configs/rockpro64-rk3399_defconfig
+++ b/configs/rockpro64-rk3399_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_ROCKCHIP_RK3399=y
+CONFIG_TARGET_ROCKPRO64_RK3399=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_DEBUG_UART_BASE=0xFF1A0000
 CONFIG_DEBUG_UART_CLOCK=24000000
diff --git a/configs/tinker-s-rk3288_defconfig b/configs/tinker-s-rk3288_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..c851a93f3127854f139be8ba472f6ca0cd38705f
--- /dev/null
+++ b/configs/tinker-s-rk3288_defconfig
@@ -0,0 +1,99 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x01000000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_TINKER_RK3288=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL_SIZE_LIMIT=307200
+CONFIG_SPL_STACK_R_ADDR=0x800000
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x4000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_USE_PREBOOT=y
+CONFIG_SILENT_CONSOLE=y
+CONFIG_CONSOLE_MUX=y
+CONFIG_DEFAULT_FDT_FILE="rk3288-tinker-s.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x300000
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_BMP=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_SPL_PARTITION_UUIDS=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-tinker-s"
+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=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_SPI_FLASH=y
+CONFIG_SF_DEFAULT_SPEED=20000000
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_SPL_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_CONSOLE_SCROLL_LINES=10
diff --git a/doc/README.rockchip b/doc/README.rockchip
index d17afeabdd2c646720bdfc483a1f92753a152b43..67c14006a373716f272c888aa9694b445935f9d7 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -47,6 +47,11 @@ Two RK3036 boards are supported:
    - EVB RK3036 - use evb-rk3036 configuration
    - Kylin - use kylin_rk3036 configuration
 
+Two RK3308 boards are supported:
+
+   - EVB RK3308 - use evb-rk3308 configuration
+   - ROC-CC-RK3308 - use roc-rk3308-cc configuration
+
 Two RK3328 board are supported:
 
    - EVB RK3328 - use evb-rk3328_defconfig
@@ -94,7 +99,20 @@ For example:
 
     (or you can use another cross compiler if you prefer)
 
-2. To build RK3399 board:
+2. To build RK3308 board:
+   - Get the rkbin
+     => git clone https://github.com/rockchip-linux/rkbin.git
+
+   - Compile U-Boot
+     => cd /path/to/u-boot
+     => export BL31=/path/to/rkbin/bin/rk33/rk3308_bl31_v2.22.elf
+     => make roc-rk3308-cc_defconfig
+     => make CROSS_COMPILE=aarch64-linux-gnu- all
+     => make CROSS_COMPILE=aarch64-linux-gnu- u-boot.itb
+     => ./tools/mkimage -n rk3308 -T rksd -d /path/to/rkbin/bin/rk33/rk3308_ddr_589MHz_uart2_m0_v1.26.bin idbloader.img
+     => cat spl/u-boot-spl.bin  >> idbloader.img
+
+3. To build RK3399 board:
 
    Option 1: Package the image with Rockchip miniloader:
 
@@ -203,6 +221,78 @@ as several other platforms do. However it does not seem to be possible to
 use the existing boot ROM code from SPL.
 
 
+Writing to the eMMC with USB on ROC-RK3308-CC
+=============================================
+For USB to work you must get your board into Bootrom mode,
+either by erasing the eMMC or short circuit the GND and D0
+on core board.
+
+Connect the board to your computer via tyepc.
+=> rkdeveloptool db rk3308_loader_v1.26.117.bin
+=> rkdeveloptool wl 0x40 idbloader.img
+=> rkdeveloptool wl 0x4000 u-boot.itb
+=> rkdeveloptool rd
+
+Then you will see the boot log from Debug UART at baud rate 1500000:
+DDR Version V1.26
+REGFB: 0x00000032, 0x00000032
+In
+589MHz
+DDR3
+ Col=10 Bank=8 Row=14 Size=256MB
+msch:1
+Returning to boot ROM...
+
+U-Boot SPL 2020.01-rc1-00225-g34b681327f (Nov 14 2019 - 10:58:04 +0800)
+Trying to boot from MMC1
+INFO:    Preloader serial: 2
+NOTICE:  BL31: v1.3(release):30f1405
+NOTICE:  BL31: Built : 17:08:28, Sep 23 2019
+INFO:    Lastlog: last=0x100000, realtime=0x102000, size=0x2000
+INFO:    ARM GICv2 driver initialized
+INFO:    Using opteed sec cpu_context!
+INFO:    boot cpu mask: 1
+INFO:    plat_rockchip_pmu_init: pd status 0xe b
+INFO:    BL31: Initializing runtime services
+WARNING: No OPTEE provided by BL2 boot loader, Booting device without OPTEE initialization. SMC`s destined for OPTEE will rK
+ERROR:   Error initializing runtime service opteed_fast
+INFO:    BL31: Preparing for EL3 exit to normal world
+INFO:    Entry point address = 0x600000
+INFO:    SPSR = 0x3c9
+
+
+U-Boot 2020.01-rc1-00225-g34b681327f (Nov 14 2019 - 10:58:47 +0800)
+
+Model: Firefly ROC-RK3308-CC board
+DRAM:  254 MiB
+MMC:   dwmmc@ff480000: 0, dwmmc@ff490000: 1
+rockchip_dnl_key_pressed read adc key val failed
+Net:   No ethernet found.
+Hit any key to stop autoboot:  0
+Card did not respond to voltage select!
+switch to partitions #0, OK
+mmc1(part 0) is current device
+Scanning mmc 1:4...
+Found /extlinux/extlinux.conf
+Retrieving file: /extlinux/extlinux.conf
+151 bytes read in 3 ms (48.8 KiB/s)
+1:      kernel-mainline
+Retrieving file: /Image
+14737920 bytes read in 377 ms (37.3 MiB/s)
+append: earlycon=uart8250,mmio32,0xff0c0000 console=ttyS2,1500000n8
+Retrieving file: /rk3308-roc-cc.dtb
+28954 bytes read in 4 ms (6.9 MiB/s)
+Flattened Device Tree blob at 01f00000
+Booting using the fdt blob at 0x1f00000
+## Loading Device Tree to 000000000df3a000, end 000000000df44119 ... OK
+
+Starting kernel ...
+[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd042]
+[    0.000000] Linux version 5.4.0-rc1-00040-g4dc2d508fa47-dirty (andy@B150) (gcc version 6.3.1 20170404 (Linaro GCC 6.3-209
+[    0.000000] Machine model: Firefly ROC-RK3308-CC board
+[    0.000000] earlycon: uart8250 at MMIO32 0x00000000ff0c0000 (options '')
+[    0.000000] printk: bootconsole [uart8250] enabled
+
 Booting from an SD card
 =======================
 
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 41cfb7ad3fd69cb70bbd45d4eadd6eb9fbe787df..4cfcf83309298b416a23bd8f95bf981f1e4c2490 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -3,11 +3,14 @@
 # Copyright (c) 2017 Rockchip Electronics Co., Ltd
 #
 
+obj-y += clk_pll.o
+obj-$(CONFIG_ROCKCHIP_PX30) += clk_px30.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
 obj-$(CONFIG_ROCKCHIP_RK3128) += clk_rk3128.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += clk_rk322x.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3308) += clk_rk3308.o
 obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o
 obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
diff --git a/drivers/clk/rockchip/clk_pll.c b/drivers/clk/rockchip/clk_pll.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4b45314ec5e5b8d6f64368c657702ec29451e68
--- /dev/null
+++ b/drivers/clk/rockchip/clk_pll.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd
+ */
+ #include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <div64.h>
+
+static struct rockchip_pll_rate_table rockchip_auto_table;
+
+#define PLL_MODE_MASK				0x3
+#define PLL_RK3328_MODE_MASK			0x1
+
+#define RK3036_PLLCON0_FBDIV_MASK		0xfff
+#define RK3036_PLLCON0_FBDIV_SHIFT		0
+#define RK3036_PLLCON0_POSTDIV1_MASK		0x7 << 12
+#define RK3036_PLLCON0_POSTDIV1_SHIFT		12
+#define RK3036_PLLCON1_REFDIV_MASK		0x3f
+#define RK3036_PLLCON1_REFDIV_SHIFT		0
+#define RK3036_PLLCON1_POSTDIV2_MASK		0x7 << 6
+#define RK3036_PLLCON1_POSTDIV2_SHIFT		6
+#define RK3036_PLLCON1_DSMPD_MASK		0x1 << 12
+#define RK3036_PLLCON1_DSMPD_SHIFT		12
+#define RK3036_PLLCON2_FRAC_MASK		0xffffff
+#define RK3036_PLLCON2_FRAC_SHIFT		0
+#define RK3036_PLLCON1_PWRDOWN_SHIT		13
+
+#define MHZ		1000000
+#define KHZ		1000
+enum {
+	OSC_HZ			= 24 * 1000000,
+	VCO_MAX_HZ	= 3200U * 1000000,
+	VCO_MIN_HZ	= 800 * 1000000,
+	OUTPUT_MAX_HZ	= 3200U * 1000000,
+	OUTPUT_MIN_HZ	= 24 * 1000000,
+};
+
+#define MIN_FOUTVCO_FREQ	(800 * MHZ)
+#define MAX_FOUTVCO_FREQ	(2000 * MHZ)
+
+int gcd(int m, int n)
+{
+	int t;
+
+	while (m > 0) {
+		if (n > m) {
+			t = m;
+			m = n;
+			n = t;
+		} /* swap */
+		m -= n;
+	}
+	return n;
+}
+
+/*
+ * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
+ * Formulas also embedded within the Fractional PLL Verilog model:
+ * If DSMPD = 1 (DSM is disabled, "integer mode")
+ * FOUTVCO = FREF / REFDIV * FBDIV
+ * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
+ * Where:
+ * FOUTVCO = Fractional PLL non-divided output frequency
+ * FOUTPOSTDIV = Fractional PLL divided output frequency
+ *               (output of second post divider)
+ * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
+ * REFDIV = Fractional PLL input reference clock divider
+ * FBDIV = Integer value programmed into feedback divide
+ *
+ */
+
+static int rockchip_pll_clk_set_postdiv(ulong fout_hz,
+					u32 *postdiv1,
+					u32 *postdiv2,
+					u32 *foutvco)
+{
+	ulong freq;
+
+	if (fout_hz < MIN_FOUTVCO_FREQ) {
+		for (*postdiv1 = 1; *postdiv1 <= 7; (*postdiv1)++) {
+			for (*postdiv2 = 1; *postdiv2 <= 7; (*postdiv2)++) {
+				freq = fout_hz * (*postdiv1) * (*postdiv2);
+				if (freq >= MIN_FOUTVCO_FREQ &&
+				    freq <= MAX_FOUTVCO_FREQ) {
+					*foutvco = freq;
+					return 0;
+				}
+			}
+		}
+		printf("Can't FIND postdiv1/2 to make fout=%lu in 800~2000M.\n",
+		       fout_hz);
+	} else {
+		*postdiv1 = 1;
+		*postdiv2 = 1;
+	}
+	return 0;
+}
+
+static struct rockchip_pll_rate_table *
+rockchip_pll_clk_set_by_auto(ulong fin_hz,
+			     ulong fout_hz)
+{
+	struct rockchip_pll_rate_table *rate_table = &rockchip_auto_table;
+	/* FIXME set postdiv1/2 always 1*/
+	u32 foutvco = fout_hz;
+	ulong fin_64, frac_64;
+	u32 f_frac, postdiv1, postdiv2;
+	ulong clk_gcd = 0;
+
+	if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
+		return NULL;
+
+	rockchip_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco);
+	rate_table->postdiv1 = postdiv1;
+	rate_table->postdiv2 = postdiv2;
+	rate_table->dsmpd = 1;
+
+	if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) {
+		fin_hz /= MHZ;
+		foutvco /= MHZ;
+		clk_gcd = gcd(fin_hz, foutvco);
+		rate_table->refdiv = fin_hz / clk_gcd;
+		rate_table->fbdiv = foutvco / clk_gcd;
+
+		rate_table->frac = 0;
+
+		debug("fin = %ld, fout = %ld, clk_gcd = %ld,\n",
+		      fin_hz, fout_hz, clk_gcd);
+		debug("refdiv= %d,fbdiv= %d,postdiv1= %d,postdiv2= %d\n",
+		      rate_table->refdiv,
+		      rate_table->fbdiv, rate_table->postdiv1,
+		      rate_table->postdiv2);
+	} else {
+		debug("frac div,fin_hz = %ld,fout_hz = %ld\n",
+		      fin_hz, fout_hz);
+		debug("frac get postdiv1 = %d,  postdiv2 = %d, foutvco = %d\n",
+		      rate_table->postdiv1, rate_table->postdiv2, foutvco);
+		clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ);
+		rate_table->refdiv = fin_hz / MHZ / clk_gcd;
+		rate_table->fbdiv = foutvco / MHZ / clk_gcd;
+		debug("frac get refdiv = %d,  fbdiv = %d\n",
+		      rate_table->refdiv, rate_table->fbdiv);
+
+		rate_table->frac = 0;
+
+		f_frac = (foutvco % MHZ);
+		fin_64 = fin_hz;
+		fin_64 = fin_64 / rate_table->refdiv;
+		frac_64 = f_frac << 24;
+		frac_64 = frac_64 / fin_64;
+		rate_table->frac = frac_64;
+		if (rate_table->frac > 0)
+			rate_table->dsmpd = 0;
+		debug("frac = %x\n", rate_table->frac);
+	}
+	return rate_table;
+}
+
+static const struct rockchip_pll_rate_table *
+rockchip_get_pll_settings(struct rockchip_pll_clock *pll, ulong rate)
+{
+	struct rockchip_pll_rate_table  *rate_table = pll->rate_table;
+
+	while (rate_table->rate) {
+		if (rate_table->rate == rate)
+			break;
+		rate_table++;
+	}
+	if (rate_table->rate != rate)
+		return rockchip_pll_clk_set_by_auto(24 * MHZ, rate);
+	else
+		return rate_table;
+}
+
+static int rk3036_pll_set_rate(struct rockchip_pll_clock *pll,
+			       void __iomem *base, ulong pll_id,
+			       ulong drate)
+{
+	const struct rockchip_pll_rate_table *rate;
+
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		printf("%s unsupport rate\n", __func__);
+		return -EINVAL;
+	}
+
+	debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d\n",
+	      __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv);
+	debug("%s: rate settings for %lu postdiv2: %d, dsmpd: %d, frac: %d\n",
+	      __func__, rate->rate, rate->postdiv2, rate->dsmpd, rate->frac);
+
+	/*
+	 * When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	rk_clrsetreg(base + pll->mode_offset,
+		     pll->mode_mask << pll->mode_shift,
+		     RKCLK_PLL_MODE_SLOW << pll->mode_shift);
+
+	/* Power down */
+	rk_setreg(base + pll->con_offset + 0x4,
+		  1 << RK3036_PLLCON1_PWRDOWN_SHIT);
+
+	rk_clrsetreg(base + pll->con_offset,
+		     (RK3036_PLLCON0_POSTDIV1_MASK |
+		     RK3036_PLLCON0_FBDIV_MASK),
+		     (rate->postdiv1 << RK3036_PLLCON0_POSTDIV1_SHIFT) |
+		     rate->fbdiv);
+	rk_clrsetreg(base + pll->con_offset + 0x4,
+		     (RK3036_PLLCON1_POSTDIV2_MASK |
+		     RK3036_PLLCON1_REFDIV_MASK),
+		     (rate->postdiv2 << RK3036_PLLCON1_POSTDIV2_SHIFT |
+		     rate->refdiv << RK3036_PLLCON1_REFDIV_SHIFT));
+	if (!rate->dsmpd) {
+		rk_clrsetreg(base + pll->con_offset + 0x4,
+			     RK3036_PLLCON1_DSMPD_MASK,
+			     rate->dsmpd << RK3036_PLLCON1_DSMPD_SHIFT);
+		writel((readl(base + pll->con_offset + 0x8) &
+			(~RK3036_PLLCON2_FRAC_MASK)) |
+			    (rate->frac << RK3036_PLLCON2_FRAC_SHIFT),
+			    base + pll->con_offset + 0x8);
+	}
+
+	/* Power Up */
+	rk_clrreg(base + pll->con_offset + 0x4,
+		  1 << RK3036_PLLCON1_PWRDOWN_SHIT);
+
+	/* waiting for pll lock */
+	while (!(readl(base + pll->con_offset + 0x4) & (1 << pll->lock_shift)))
+		udelay(1);
+
+	rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift,
+		     RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
+	debug("PLL at %p: con0=%x con1= %x con2= %x mode= %x\n",
+	      pll, readl(base + pll->con_offset),
+	      readl(base + pll->con_offset + 0x4),
+	      readl(base + pll->con_offset + 0x8),
+	      readl(base + pll->mode_offset));
+
+	return 0;
+}
+
+static ulong rk3036_pll_get_rate(struct rockchip_pll_clock *pll,
+				 void __iomem *base, ulong pll_id)
+{
+	u32 refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac;
+	u32 con = 0, shift, mask;
+	ulong rate;
+
+	con = readl(base + pll->mode_offset);
+	shift = pll->mode_shift;
+	mask = pll->mode_mask << shift;
+
+	switch ((con & mask) >> shift) {
+	case RKCLK_PLL_MODE_SLOW:
+		return OSC_HZ;
+	case RKCLK_PLL_MODE_NORMAL:
+		/* normal mode */
+		con = readl(base + pll->con_offset);
+		postdiv1 = (con & RK3036_PLLCON0_POSTDIV1_MASK) >>
+			   RK3036_PLLCON0_POSTDIV1_SHIFT;
+		fbdiv = (con & RK3036_PLLCON0_FBDIV_MASK) >>
+			RK3036_PLLCON0_FBDIV_SHIFT;
+		con = readl(base + pll->con_offset + 0x4);
+		postdiv2 = (con & RK3036_PLLCON1_POSTDIV2_MASK) >>
+			   RK3036_PLLCON1_POSTDIV2_SHIFT;
+		refdiv = (con & RK3036_PLLCON1_REFDIV_MASK) >>
+			 RK3036_PLLCON1_REFDIV_SHIFT;
+		dsmpd = (con & RK3036_PLLCON1_DSMPD_MASK) >>
+			RK3036_PLLCON1_DSMPD_SHIFT;
+		con = readl(base + pll->con_offset + 0x8);
+		frac = (con & RK3036_PLLCON2_FRAC_MASK) >>
+			RK3036_PLLCON2_FRAC_SHIFT;
+		rate = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
+		if (dsmpd == 0) {
+			u64 frac_rate = OSC_HZ * (u64)frac;
+
+			do_div(frac_rate, refdiv);
+			frac_rate >>= 24;
+			do_div(frac_rate, postdiv1);
+			do_div(frac_rate, postdiv1);
+			rate += frac_rate;
+		}
+		return rate;
+	case RKCLK_PLL_MODE_DEEP:
+	default:
+		return 32768;
+	}
+}
+
+ulong rockchip_pll_get_rate(struct rockchip_pll_clock *pll,
+			    void __iomem *base,
+			    ulong pll_id)
+{
+	ulong rate = 0;
+
+	switch (pll->type) {
+	case pll_rk3036:
+		pll->mode_mask = PLL_MODE_MASK;
+		rate = rk3036_pll_get_rate(pll, base, pll_id);
+		break;
+	case pll_rk3328:
+		pll->mode_mask = PLL_RK3328_MODE_MASK;
+		rate = rk3036_pll_get_rate(pll, base, pll_id);
+		break;
+	default:
+		printf("%s: Unknown pll type for pll clk %ld\n",
+		       __func__, pll_id);
+	}
+	return rate;
+}
+
+int rockchip_pll_set_rate(struct rockchip_pll_clock *pll,
+			  void __iomem *base, ulong pll_id,
+			  ulong drate)
+{
+	int ret = 0;
+
+	if (rockchip_pll_get_rate(pll, base, pll_id) == drate)
+		return 0;
+
+	switch (pll->type) {
+	case pll_rk3036:
+		pll->mode_mask = PLL_MODE_MASK;
+		ret = rk3036_pll_set_rate(pll, base, pll_id, drate);
+		break;
+	case pll_rk3328:
+		pll->mode_mask = PLL_RK3328_MODE_MASK;
+		ret = rk3036_pll_set_rate(pll, base, pll_id, drate);
+		break;
+	default:
+		printf("%s: Unknown pll type for pll clk %ld\n",
+		       __func__, pll_id);
+	}
+	return ret;
+}
+
+const struct rockchip_cpu_rate_table *
+rockchip_get_cpu_settings(struct rockchip_cpu_rate_table *cpu_table,
+			  ulong rate)
+{
+	struct rockchip_cpu_rate_table *ps = cpu_table;
+
+	while (ps->rate) {
+		if (ps->rate == rate)
+			break;
+		ps++;
+	}
+	if (ps->rate != rate)
+		return NULL;
+	else
+		return ps;
+}
+
diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..36764c128b05443eecefef7fd9ca4d4d06048924
--- /dev/null
+++ b/drivers/clk/rockchip/clk_px30.c
@@ -0,0 +1,1630 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/px30-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	VCO_MAX_HZ	= 3200U * 1000000,
+	VCO_MIN_HZ	= 800 * 1000000,
+	OUTPUT_MAX_HZ	= 3200U * 1000000,
+	OUTPUT_MIN_HZ	= 24 * 1000000,
+};
+
+#define PX30_VOP_PLL_LIMIT			600000000
+
+#define PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
+			_postdiv2, _dsmpd, _frac)		\
+{								\
+	.rate	= _rate##U,					\
+	.fbdiv = _fbdiv,					\
+	.postdiv1 = _postdiv1,					\
+	.refdiv = _refdiv,					\
+	.postdiv2 = _postdiv2,					\
+	.dsmpd = _dsmpd,					\
+	.frac = _frac,						\
+}
+
+#define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
+{								\
+	.rate	= _rate##U,					\
+	.aclk_div = _aclk_div,					\
+	.pclk_div = _pclk_div,					\
+}
+
+#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
+
+#define PX30_CLK_DUMP(_id, _name, _iscru)	\
+{						\
+	.id = _id,				\
+	.name = _name,				\
+	.is_cru = _iscru,			\
+}
+
+static struct pll_rate_table px30_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+	PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
+};
+
+static struct cpu_rate_table px30_cpu_rates[] = {
+	PX30_CPUCLK_RATE(1200000000, 1, 5),
+	PX30_CPUCLK_RATE(1008000000, 1, 5),
+	PX30_CPUCLK_RATE(816000000, 1, 3),
+	PX30_CPUCLK_RATE(600000000, 1, 3),
+	PX30_CPUCLK_RATE(408000000, 1, 1),
+};
+
+static u8 pll_mode_shift[PLL_COUNT] = {
+	APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
+	NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
+};
+
+static u32 pll_mode_mask[PLL_COUNT] = {
+	APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
+	NPLL_MODE_MASK, GPLL_MODE_MASK
+};
+
+static struct pll_rate_table auto_table;
+
+static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
+				   enum px30_pll_id pll_id);
+
+static struct pll_rate_table *pll_clk_set_by_auto(u32 drate)
+{
+	struct pll_rate_table *rate = &auto_table;
+	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
+	u32 postdiv1, postdiv2 = 1;
+	u32 fref_khz;
+	u32 diff_khz, best_diff_khz;
+	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
+	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
+	u32 vco_khz;
+	u32 rate_khz = drate / KHz;
+
+	if (!drate) {
+		printf("%s: the frequency can't be 0 Hz\n", __func__);
+		return NULL;
+	}
+
+	postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz);
+	if (postdiv1 > max_postdiv1) {
+		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
+		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
+	}
+
+	vco_khz = rate_khz * postdiv1 * postdiv2;
+
+	if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
+	    postdiv2 > max_postdiv2) {
+		printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
+		       __func__, rate_khz);
+		return NULL;
+	}
+
+	rate->postdiv1 = postdiv1;
+	rate->postdiv2 = postdiv2;
+
+	best_diff_khz = vco_khz;
+	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
+		fref_khz = ref_khz / refdiv;
+
+		fbdiv = vco_khz / fref_khz;
+		if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
+			continue;
+
+		diff_khz = vco_khz - fbdiv * fref_khz;
+		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
+			fbdiv++;
+			diff_khz = fref_khz - diff_khz;
+		}
+
+		if (diff_khz >= best_diff_khz)
+			continue;
+
+		best_diff_khz = diff_khz;
+		rate->refdiv = refdiv;
+		rate->fbdiv = fbdiv;
+	}
+
+	if (best_diff_khz > 4 * (MHz / KHz)) {
+		printf("%s: Failed to match output frequency %u bestis %u Hz\n",
+		       __func__, rate_khz,
+		       best_diff_khz * KHz);
+		return NULL;
+	}
+
+	return rate;
+}
+
+static const struct pll_rate_table *get_pll_settings(unsigned long rate)
+{
+	unsigned int rate_count = ARRAY_SIZE(px30_pll_rates);
+	int i;
+
+	for (i = 0; i < rate_count; i++) {
+		if (rate == px30_pll_rates[i].rate)
+			return &px30_pll_rates[i];
+	}
+
+	return pll_clk_set_by_auto(rate);
+}
+
+static const struct cpu_rate_table *get_cpu_settings(unsigned long rate)
+{
+	unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates);
+	int i;
+
+	for (i = 0; i < rate_count; i++) {
+		if (rate == px30_cpu_rates[i].rate)
+			return &px30_cpu_rates[i];
+	}
+
+	return NULL;
+}
+
+/*
+ * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
+ * Formulas also embedded within the Fractional PLL Verilog model:
+ * If DSMPD = 1 (DSM is disabled, "integer mode")
+ * FOUTVCO = FREF / REFDIV * FBDIV
+ * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
+ * Where:
+ * FOUTVCO = Fractional PLL non-divided output frequency
+ * FOUTPOSTDIV = Fractional PLL divided output frequency
+ *               (output of second post divider)
+ * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
+ * REFDIV = Fractional PLL input reference clock divider
+ * FBDIV = Integer value programmed into feedback divide
+ *
+ */
+static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode,
+			 enum px30_pll_id pll_id,
+			 unsigned long drate)
+{
+	const struct pll_rate_table *rate;
+	uint vco_hz, output_hz;
+
+	rate = get_pll_settings(drate);
+	if (!rate) {
+		printf("%s unsupport rate\n", __func__);
+		return -EINVAL;
+	}
+
+	/* All PLLs have same VCO and output frequency range restrictions. */
+	vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000;
+	output_hz = vco_hz / rate->postdiv1 / rate->postdiv2;
+
+	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
+	      pll, rate->fbdiv, rate->refdiv, rate->postdiv1,
+	      rate->postdiv2, vco_hz, output_hz);
+	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
+
+	/*
+	 * When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	rk_clrsetreg(mode, pll_mode_mask[pll_id],
+		     PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
+
+	/* use integer mode */
+	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
+	/* Power down */
+	rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
+
+	rk_clrsetreg(&pll->con0,
+		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
+		     (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv);
+	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
+		     (rate->postdiv2 << PLL_POSTDIV2_SHIFT |
+		     rate->refdiv << PLL_REFDIV_SHIFT));
+
+	/* Power Up */
+	rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
+
+	/* waiting for pll lock */
+	while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
+		udelay(1);
+
+	rk_clrsetreg(mode, pll_mode_mask[pll_id],
+		     PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
+
+	return 0;
+}
+
+static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode,
+				   enum px30_pll_id pll_id)
+{
+	u32 refdiv, fbdiv, postdiv1, postdiv2;
+	u32 con, shift, mask;
+
+	con = readl(mode);
+	shift = pll_mode_shift[pll_id];
+	mask = pll_mode_mask[pll_id];
+
+	switch ((con & mask) >> shift) {
+	case PLLMUX_FROM_XIN24M:
+		return OSC_HZ;
+	case PLLMUX_FROM_PLL:
+		/* normal mode */
+		con = readl(&pll->con0);
+		postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
+		fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
+		con = readl(&pll->con1);
+		postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
+		refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
+		return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
+	case PLLMUX_FROM_RTC32K:
+	default:
+		return 32768;
+	}
+}
+
+static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_I2C0:
+		con = readl(&cru->clksel_con[49]);
+		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+		break;
+	case SCLK_I2C1:
+		con = readl(&cru->clksel_con[49]);
+		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+		break;
+	case SCLK_I2C2:
+		con = readl(&cru->clksel_con[50]);
+		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+		break;
+	case SCLK_I2C3:
+		con = readl(&cru->clksel_con[50]);
+		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk_id) {
+	case SCLK_I2C0:
+		rk_clrsetreg(&cru->clksel_con[49],
+			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
+		break;
+	case SCLK_I2C1:
+		rk_clrsetreg(&cru->clksel_con[49],
+			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
+		break;
+	case SCLK_I2C2:
+		rk_clrsetreg(&cru->clksel_con[50],
+			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
+		break;
+	case SCLK_I2C3:
+		rk_clrsetreg(&cru->clksel_con[50],
+			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
+			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return px30_i2c_get_clk(priv, clk_id);
+}
+
+/*
+ * calculate best rational approximation for a given fraction
+ * taking into account restricted register size, e.g. to find
+ * appropriate values for a pll with 5 bit denominator and
+ * 8 bit numerator register fields, trying to set up with a
+ * frequency ratio of 3.1415, one would say:
+ *
+ * rational_best_approximation(31415, 10000,
+ *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+					unsigned long given_denominator,
+					unsigned long max_numerator,
+					unsigned long max_denominator,
+					unsigned long *best_numerator,
+					unsigned long *best_denominator)
+{
+	unsigned long n, d, n0, d0, n1, d1;
+
+	n = given_numerator;
+	d = given_denominator;
+	n0 = 0;
+	d1 = 0;
+	n1 = 1;
+	d0 = 1;
+	for (;;) {
+		unsigned long t, a;
+
+		if (n1 > max_numerator || d1 > max_denominator) {
+			n1 = n0;
+			d1 = d0;
+			break;
+		}
+		if (d == 0)
+			break;
+		t = d;
+		a = n / d;
+		d = n % d;
+		n = t;
+		t = n0 + a * n1;
+		n0 = n1;
+		n1 = t;
+		t = d0 + a * d1;
+		d0 = d1;
+		d1 = t;
+	}
+	*best_numerator = n1;
+	*best_denominator = d1;
+}
+
+static ulong px30_i2s_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	u32 con, fracdiv, gate;
+	u32 clk_src = priv->gpll_hz / 2;
+	unsigned long m, n;
+	struct px30_cru *cru = priv->cru;
+
+	switch (clk_id) {
+	case SCLK_I2S1:
+		con = readl(&cru->clksel_con[30]);
+		fracdiv = readl(&cru->clksel_con[31]);
+		gate = readl(&cru->clkgate_con[10]);
+		m = fracdiv & CLK_I2S1_FRAC_NUMERATOR_MASK;
+		m >>= CLK_I2S1_FRAC_NUMERATOR_SHIFT;
+		n = fracdiv & CLK_I2S1_FRAC_DENOMINATOR_MASK;
+		n >>= CLK_I2S1_FRAC_DENOMINATOR_SHIFT;
+		debug("con30: 0x%x, gate: 0x%x, frac: 0x%x\n",
+		      con, gate, fracdiv);
+		break;
+	default:
+		printf("do not support this i2s bus\n");
+		return -EINVAL;
+	}
+
+	return clk_src * n / m;
+}
+
+static ulong px30_i2s_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+	u32 clk_src;
+	unsigned long m, n, val;
+	struct px30_cru *cru = priv->cru;
+
+	clk_src = priv->gpll_hz / 2;
+	rational_best_approximation(hz, clk_src,
+				    GENMASK(16 - 1, 0),
+				    GENMASK(16 - 1, 0),
+				    &m, &n);
+	switch (clk_id) {
+	case SCLK_I2S1:
+		rk_clrsetreg(&cru->clksel_con[30],
+			     CLK_I2S1_PLL_SEL_MASK, CLK_I2S1_PLL_SEL_GPLL);
+		rk_clrsetreg(&cru->clksel_con[30],
+			     CLK_I2S1_DIV_CON_MASK, 0x1);
+		rk_clrsetreg(&cru->clksel_con[30],
+			     CLK_I2S1_SEL_MASK, CLK_I2S1_SEL_FRAC);
+		val = m << CLK_I2S1_FRAC_NUMERATOR_SHIFT | n;
+		writel(val, &cru->clksel_con[31]);
+		rk_clrsetreg(&cru->clkgate_con[10],
+			     CLK_I2S1_OUT_MCLK_PAD_MASK,
+			     CLK_I2S1_OUT_MCLK_PAD_ENABLE);
+		break;
+	default:
+		printf("do not support this i2s bus\n");
+		return -EINVAL;
+	}
+
+	return px30_i2s_get_clk(priv, clk_id);
+}
+
+static ulong px30_nandc_get_clk(struct px30_clk_priv *priv)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[15]);
+	div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT;
+
+	return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_nandc_set_clk(struct px30_clk_priv *priv,
+				ulong set_rate)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	/* Select nandc source from GPLL by default */
+	/* nandc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate);
+	assert(src_clk_div - 1 <= 31);
+
+	rk_clrsetreg(&cru->clksel_con[15],
+		     NANDC_CLK_SEL_MASK | NANDC_PLL_MASK |
+		     NANDC_DIV_MASK,
+		     NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT |
+		     NANDC_SEL_GPLL << NANDC_PLL_SHIFT |
+		     (src_clk_div - 1) << NANDC_DIV_SHIFT);
+
+	return px30_nandc_get_clk(priv);
+}
+
+static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con, con_id;
+
+	switch (clk_id) {
+	case HCLK_SDMMC:
+	case SCLK_SDMMC:
+		con_id = 16;
+		break;
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		con_id = 20;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	con = readl(&cru->clksel_con[con_id]);
+	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
+
+	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
+	    == EMMC_SEL_24M)
+		return DIV_TO_RATE(OSC_HZ, div) / 2;
+	else
+		return DIV_TO_RATE(priv->gpll_hz, div) / 2;
+}
+
+static ulong px30_mmc_set_clk(struct px30_clk_priv *priv,
+			      ulong clk_id, ulong set_rate)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+	u32 con_id;
+
+	switch (clk_id) {
+	case HCLK_SDMMC:
+	case SCLK_SDMMC:
+		con_id = 16;
+		break;
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+		con_id = 20;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Select clk_sdmmc/emmc source from GPLL by default */
+	/* mmc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
+
+	if (src_clk_div > 127) {
+		/* use 24MHz source for 400KHz clock */
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+		rk_clrsetreg(&cru->clksel_con[con_id],
+			     EMMC_PLL_MASK | EMMC_DIV_MASK,
+			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
+			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
+	} else {
+		rk_clrsetreg(&cru->clksel_con[con_id],
+			     EMMC_PLL_MASK | EMMC_DIV_MASK,
+			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
+			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
+	}
+	rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
+		     EMMC_CLK_SEL_EMMC);
+
+	return px30_mmc_get_clk(priv, clk_id);
+}
+
+static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_PWM0:
+		con = readl(&cru->clksel_con[52]);
+		div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+		break;
+	case SCLK_PWM1:
+		con = readl(&cru->clksel_con[52]);
+		div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+		break;
+	default:
+		printf("do not support this pwm bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk_id) {
+	case SCLK_PWM0:
+		rk_clrsetreg(&cru->clksel_con[52],
+			     CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
+			     CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
+			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
+		break;
+	case SCLK_PWM1:
+		rk_clrsetreg(&cru->clksel_con[52],
+			     CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
+			     CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
+			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
+		break;
+	default:
+		printf("do not support this pwm bus\n");
+		return -EINVAL;
+	}
+
+	return px30_pwm_get_clk(priv, clk_id);
+}
+
+static ulong px30_saradc_get_clk(struct px30_clk_priv *priv)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[55]);
+	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+	assert(src_clk_div - 1 <= 2047);
+
+	rk_clrsetreg(&cru->clksel_con[55],
+		     CLK_SARADC_DIV_CON_MASK,
+		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+	return px30_saradc_get_clk(priv);
+}
+
+static ulong px30_tsadc_get_clk(struct px30_clk_priv *priv)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[54]);
+	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong px30_tsadc_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+	assert(src_clk_div - 1 <= 2047);
+
+	rk_clrsetreg(&cru->clksel_con[54],
+		     CLK_SARADC_DIV_CON_MASK,
+		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+	return px30_tsadc_get_clk(priv);
+}
+
+static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_SPI0:
+		con = readl(&cru->clksel_con[53]);
+		div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+		break;
+	case SCLK_SPI1:
+		con = readl(&cru->clksel_con[53]);
+		div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+		break;
+	default:
+		printf("do not support this pwm bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk_id) {
+	case SCLK_SPI0:
+		rk_clrsetreg(&cru->clksel_con[53],
+			     CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
+			     CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
+			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
+		break;
+	case SCLK_SPI1:
+		rk_clrsetreg(&cru->clksel_con[53],
+			     CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
+			     CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
+			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
+			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
+		break;
+	default:
+		printf("do not support this pwm bus\n");
+		return -EINVAL;
+	}
+
+	return px30_spi_get_clk(priv, clk_id);
+}
+
+static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case ACLK_VOPB:
+	case ACLK_VOPL:
+		con = readl(&cru->clksel_con[3]);
+		div = con & ACLK_VO_DIV_MASK;
+		parent = priv->gpll_hz;
+		break;
+	case DCLK_VOPB:
+		con = readl(&cru->clksel_con[5]);
+		div = con & DCLK_VOPB_DIV_MASK;
+		parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL);
+		break;
+	case DCLK_VOPL:
+		con = readl(&cru->clksel_con[8]);
+		div = con & DCLK_VOPL_DIV_MASK;
+		parent = rkclk_pll_get_rate(&cru->pll[NPLL], &cru->mode, NPLL);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	ulong npll_hz;
+	int src_clk_div;
+
+	switch (clk_id) {
+	case ACLK_VOPB:
+	case ACLK_VOPL:
+		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+		assert(src_clk_div - 1 <= 31);
+		rk_clrsetreg(&cru->clksel_con[3],
+			     ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
+			     ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
+			     (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
+		break;
+	case DCLK_VOPB:
+		if (hz < PX30_VOP_PLL_LIMIT) {
+			src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz);
+			if (src_clk_div % 2)
+				src_clk_div = src_clk_div - 1;
+		} else {
+			src_clk_div = 1;
+		}
+		assert(src_clk_div - 1 <= 255);
+		rkclk_set_pll(&cru->pll[CPLL], &cru->mode,
+			      CPLL, hz * src_clk_div);
+		rk_clrsetreg(&cru->clksel_con[5],
+			     DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
+			     DCLK_VOPB_DIV_MASK,
+			     DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
+			     DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << DCLK_VOPB_DIV_SHIFT);
+		break;
+	case DCLK_VOPL:
+		npll_hz = px30_clk_get_pll_rate(priv, NPLL);
+		if (npll_hz >= PX30_VOP_PLL_LIMIT && npll_hz >= hz &&
+		    npll_hz % hz == 0) {
+			src_clk_div = npll_hz / hz;
+			assert(src_clk_div - 1 <= 255);
+		} else {
+			if (hz < PX30_VOP_PLL_LIMIT) {
+				src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT,
+							   hz);
+				if (src_clk_div % 2)
+					src_clk_div = src_clk_div - 1;
+			} else {
+				src_clk_div = 1;
+			}
+			assert(src_clk_div - 1 <= 255);
+			rkclk_set_pll(&cru->pll[NPLL], &cru->mode, NPLL,
+				      hz * src_clk_div);
+		}
+		rk_clrsetreg(&cru->clksel_con[8],
+			     DCLK_VOPL_SEL_MASK | DCLK_VOPL_PLL_SEL_MASK |
+			     DCLK_VOPL_DIV_MASK,
+			     DCLK_VOPL_SEL_DIVOUT << DCLK_VOPL_SEL_SHIFT |
+			     DCLK_VOPL_PLL_SEL_NPLL << DCLK_VOPL_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << DCLK_VOPL_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this vop freq\n");
+		return -EINVAL;
+	}
+
+	return px30_vop_get_clk(priv, clk_id);
+}
+
+static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case ACLK_BUS_PRE:
+		con = readl(&cru->clksel_con[23]);
+		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	case HCLK_BUS_PRE:
+		con = readl(&cru->clksel_con[24]);
+		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	case PCLK_BUS_PRE:
+	case PCLK_WDT_NS:
+		parent = px30_bus_get_clk(priv, ACLK_BUS_PRE);
+		con = readl(&cru->clksel_con[24]);
+		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+			      ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	/*
+	 * select gpll as pd_bus bus clock source and
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	switch (clk_id) {
+	case ACLK_BUS_PRE:
+		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+		assert(src_clk_div - 1 <= 31);
+		rk_clrsetreg(&cru->clksel_con[23],
+			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
+			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
+		break;
+	case HCLK_BUS_PRE:
+		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+		assert(src_clk_div - 1 <= 31);
+		rk_clrsetreg(&cru->clksel_con[24],
+			     BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK,
+			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
+		break;
+	case PCLK_BUS_PRE:
+		src_clk_div =
+			DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz);
+		assert(src_clk_div - 1 <= 3);
+		rk_clrsetreg(&cru->clksel_con[24],
+			     BUS_PCLK_DIV_MASK,
+			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this bus freq\n");
+		return -EINVAL;
+	}
+
+	return px30_bus_get_clk(priv, clk_id);
+}
+
+static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case ACLK_PERI_PRE:
+		con = readl(&cru->clksel_con[14]);
+		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	case HCLK_PERI_PRE:
+		con = readl(&cru->clksel_con[14]);
+		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+			       ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select gpll as pd_peri bus clock source and
+	 * set up dependent divisors for HCLK and ACLK clocks.
+	 */
+	switch (clk_id) {
+	case ACLK_PERI_PRE:
+		rk_clrsetreg(&cru->clksel_con[14],
+			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
+			     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
+		break;
+	case HCLK_PERI_PRE:
+		rk_clrsetreg(&cru->clksel_con[14],
+			     PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK,
+			     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this peri freq\n");
+		return -EINVAL;
+	}
+
+	return px30_peri_get_clk(priv, clk_id);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static ulong px30_crypto_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case SCLK_CRYPTO:
+		con = readl(&cru->clksel_con[25]);
+		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	case SCLK_CRYPTO_APK:
+		con = readl(&cru->clksel_con[25]);
+		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
+		parent = priv->gpll_hz;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_crypto_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+				 ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select gpll as crypto clock source and
+	 * set up dependent divisors for crypto clocks.
+	 */
+	switch (clk_id) {
+	case SCLK_CRYPTO:
+		rk_clrsetreg(&cru->clksel_con[25],
+			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
+			     CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
+		break;
+	case SCLK_CRYPTO_APK:
+		rk_clrsetreg(&cru->clksel_con[25],
+			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
+			     CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT |
+			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this peri freq\n");
+		return -EINVAL;
+	}
+
+	return px30_crypto_get_clk(priv, clk_id);
+}
+
+static ulong px30_i2s1_mclk_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 con;
+
+	con = readl(&cru->clksel_con[30]);
+
+	if (!(con & CLK_I2S1_OUT_SEL_MASK))
+		return -ENOENT;
+
+	return 12000000;
+}
+
+static ulong px30_i2s1_mclk_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+				    ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+
+	if (hz != 12000000) {
+		printf("do not support this i2s1_mclk freq\n");
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[30], CLK_I2S1_OUT_SEL_MASK,
+		     CLK_I2S1_OUT_SEL_OSC);
+	rk_clrsetreg(&cru->clkgate_con[10], CLK_I2S1_OUT_MCLK_PAD_MASK,
+		     CLK_I2S1_OUT_MCLK_PAD_ENABLE);
+
+	return px30_i2s1_mclk_get_clk(priv, clk_id);
+}
+
+static ulong px30_mac_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+	u32 con = readl(&cru->clksel_con[22]);
+	ulong pll_rate;
+	u8 div;
+
+	if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_CPLL)
+		pll_rate = px30_clk_get_pll_rate(priv, CPLL);
+	else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
+		pll_rate = px30_clk_get_pll_rate(priv, NPLL);
+	else
+		pll_rate = priv->gpll_hz;
+
+	/*default set 50MHZ for gmac*/
+	if (!hz)
+		hz = 50000000;
+
+	div = DIV_ROUND_UP(pll_rate, hz) - 1;
+	assert(div < 32);
+	rk_clrsetreg(&cru->clksel_con[22], CLK_GMAC_DIV_MASK,
+		     div << CLK_GMAC_DIV_SHIFT);
+
+	return DIV_TO_RATE(pll_rate, div);
+}
+
+static int px30_mac_set_speed_clk(struct px30_clk_priv *priv, uint hz)
+{
+	struct px30_cru *cru = priv->cru;
+
+	if (hz != 2500000 && hz != 25000000) {
+		debug("Unsupported mac speed:%d\n", hz);
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[23], RMII_CLK_SEL_MASK,
+		     ((hz == 2500000) ? 0 : 1) << RMII_CLK_SEL_SHIFT);
+
+	return 0;
+}
+
+#endif
+
+static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
+				   enum px30_pll_id pll_id)
+{
+	struct px30_cru *cru = priv->cru;
+
+	return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
+}
+
+static ulong px30_clk_set_pll_rate(struct px30_clk_priv *priv,
+				   enum px30_pll_id pll_id, ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+
+	if (rkclk_set_pll(&cru->pll[pll_id], &cru->mode, pll_id, hz))
+		return -EINVAL;
+	return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
+}
+
+static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz)
+{
+	struct px30_cru *cru = priv->cru;
+	const struct cpu_rate_table *rate;
+	ulong old_rate;
+
+	rate = get_cpu_settings(hz);
+	if (!rate) {
+		printf("%s unsupport rate\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * select apll as cpu/core clock pll source and
+	 * set up dependent divisors for PERI and ACLK clocks.
+	 * core hz : apll = 1:1
+	 */
+	old_rate = px30_clk_get_pll_rate(priv, APLL);
+	if (old_rate > hz) {
+		if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
+			return -EINVAL;
+		rk_clrsetreg(&cru->clksel_con[0],
+			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
+			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+			     0 << CORE_DIV_CON_SHIFT);
+	} else if (old_rate < hz) {
+		rk_clrsetreg(&cru->clksel_con[0],
+			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
+			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+			     0 << CORE_DIV_CON_SHIFT);
+		if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
+			return -EINVAL;
+	}
+
+	return px30_clk_get_pll_rate(priv, APLL);
+}
+
+static ulong px30_clk_get_rate(struct clk *clk)
+{
+	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	if (!priv->gpll_hz && clk->id > ARMCLK) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	debug("%s %ld\n", __func__, clk->id);
+	switch (clk->id) {
+	case PLL_APLL:
+		rate = px30_clk_get_pll_rate(priv, APLL);
+		break;
+	case PLL_DPLL:
+		rate = px30_clk_get_pll_rate(priv, DPLL);
+		break;
+	case PLL_CPLL:
+		rate = px30_clk_get_pll_rate(priv, CPLL);
+		break;
+	case PLL_NPLL:
+		rate = px30_clk_get_pll_rate(priv, NPLL);
+		break;
+	case ARMCLK:
+		rate = px30_clk_get_pll_rate(priv, APLL);
+		break;
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		rate = px30_mmc_get_clk(priv, clk->id);
+		break;
+	case SCLK_I2C0:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		rate = px30_i2c_get_clk(priv, clk->id);
+		break;
+	case SCLK_I2S1:
+		rate = px30_i2s_get_clk(priv, clk->id);
+		break;
+	case SCLK_NANDC:
+		rate = px30_nandc_get_clk(priv);
+		break;
+	case SCLK_PWM0:
+	case SCLK_PWM1:
+		rate = px30_pwm_get_clk(priv, clk->id);
+		break;
+	case SCLK_SARADC:
+		rate = px30_saradc_get_clk(priv);
+		break;
+	case SCLK_TSADC:
+		rate = px30_tsadc_get_clk(priv);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		rate = px30_spi_get_clk(priv, clk->id);
+		break;
+	case ACLK_VOPB:
+	case ACLK_VOPL:
+	case DCLK_VOPB:
+	case DCLK_VOPL:
+		rate = px30_vop_get_clk(priv, clk->id);
+		break;
+	case ACLK_BUS_PRE:
+	case HCLK_BUS_PRE:
+	case PCLK_BUS_PRE:
+	case PCLK_WDT_NS:
+		rate = px30_bus_get_clk(priv, clk->id);
+		break;
+	case ACLK_PERI_PRE:
+	case HCLK_PERI_PRE:
+		rate = px30_peri_get_clk(priv, clk->id);
+		break;
+#ifndef CONFIG_SPL_BUILD
+	case SCLK_CRYPTO:
+	case SCLK_CRYPTO_APK:
+		rate = px30_crypto_get_clk(priv, clk->id);
+		break;
+#endif
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	if (!priv->gpll_hz && clk->id > ARMCLK) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	debug("%s %ld %ld\n", __func__, clk->id, rate);
+	switch (clk->id) {
+	case PLL_NPLL:
+		ret = px30_clk_set_pll_rate(priv, NPLL, rate);
+		break;
+	case ARMCLK:
+		ret = px30_armclk_set_clk(priv, rate);
+		break;
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+		ret = px30_mmc_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_I2C0:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		ret = px30_i2c_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_I2S1:
+		ret = px30_i2s_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_NANDC:
+		ret = px30_nandc_set_clk(priv, rate);
+		break;
+	case SCLK_PWM0:
+	case SCLK_PWM1:
+		ret = px30_pwm_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_SARADC:
+		ret = px30_saradc_set_clk(priv, rate);
+		break;
+	case SCLK_TSADC:
+		ret = px30_tsadc_set_clk(priv, rate);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		ret = px30_spi_set_clk(priv, clk->id, rate);
+		break;
+	case ACLK_VOPB:
+	case ACLK_VOPL:
+	case DCLK_VOPB:
+	case DCLK_VOPL:
+		ret = px30_vop_set_clk(priv, clk->id, rate);
+		break;
+	case ACLK_BUS_PRE:
+	case HCLK_BUS_PRE:
+	case PCLK_BUS_PRE:
+		ret = px30_bus_set_clk(priv, clk->id, rate);
+		break;
+	case ACLK_PERI_PRE:
+	case HCLK_PERI_PRE:
+		ret = px30_peri_set_clk(priv, clk->id, rate);
+		break;
+#ifndef CONFIG_SPL_BUILD
+	case SCLK_CRYPTO:
+	case SCLK_CRYPTO_APK:
+		ret = px30_crypto_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_I2S1_OUT:
+		ret = px30_i2s1_mclk_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_GMAC:
+	case SCLK_GMAC_SRC:
+		ret = px30_mac_set_clk(priv, rate);
+		break;
+	case SCLK_GMAC_RMII:
+		ret = px30_mac_set_speed_clk(priv, rate);
+		break;
+#endif
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int px30_gmac_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+	struct px30_cru *cru = priv->cru;
+
+	if (parent->id == SCLK_GMAC_SRC) {
+		debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
+		rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
+			     RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
+	} else {
+		debug("%s: switching GMAC to external clock\n", __func__);
+		rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
+			     RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
+	}
+	return 0;
+}
+
+static int px30_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	switch (clk->id) {
+	case SCLK_GMAC:
+		return px30_gmac_set_parent(clk, parent);
+	default:
+		return -ENOENT;
+	}
+}
+#endif
+
+static int px30_clk_enable(struct clk *clk)
+{
+	switch (clk->id) {
+	case HCLK_HOST:
+	case SCLK_GMAC:
+	case SCLK_GMAC_RX_TX:
+	case SCLK_MAC_REF:
+	case SCLK_MAC_REFOUT:
+	case ACLK_GMAC:
+	case PCLK_GMAC:
+	case SCLK_GMAC_RMII:
+		/* Required to successfully probe the Designware GMAC driver */
+		return 0;
+	}
+
+	debug("%s: unsupported clk %ld\n", __func__, clk->id);
+	return -ENOENT;
+}
+
+static struct clk_ops px30_clk_ops = {
+	.get_rate = px30_clk_get_rate,
+	.set_rate = px30_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.set_parent = px30_clk_set_parent,
+#endif
+	.enable = px30_clk_enable,
+};
+
+static void px30_clk_init(struct px30_clk_priv *priv)
+{
+	ulong npll_hz;
+	int ret;
+
+	npll_hz = px30_clk_get_pll_rate(priv, NPLL);
+	if (npll_hz != NPLL_HZ) {
+		ret = px30_clk_set_pll_rate(priv, NPLL, NPLL_HZ);
+		if (ret < 0)
+			printf("%s failed to set npll rate\n", __func__);
+	}
+
+	px30_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ);
+	px30_bus_set_clk(priv, HCLK_BUS_PRE, HCLK_BUS_HZ);
+	px30_bus_set_clk(priv, PCLK_BUS_PRE, PCLK_BUS_HZ);
+	px30_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ);
+	px30_peri_set_clk(priv, HCLK_PERI_PRE, HCLK_PERI_HZ);
+}
+
+static int px30_clk_probe(struct udevice *dev)
+{
+	struct px30_clk_priv *priv = dev_get_priv(dev);
+	struct clk clk_gpll;
+	int ret;
+
+	if (px30_clk_get_pll_rate(priv, APLL) != APLL_HZ)
+		px30_armclk_set_clk(priv, APLL_HZ);
+
+	/* get the GPLL rate from the pmucru */
+	ret = clk_get_by_name(dev, "gpll", &clk_gpll);
+	if (ret) {
+		printf("%s: failed to get gpll clk from pmucru\n", __func__);
+		return ret;
+	}
+
+	priv->gpll_hz = clk_get_rate(&clk_gpll);
+
+	px30_clk_init(priv);
+
+	return 0;
+}
+
+static int px30_clk_ofdata_to_platdata(struct udevice *dev)
+{
+	struct px30_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static int px30_clk_bind(struct udevice *dev)
+{
+	int ret;
+	struct udevice *sys_child;
+	struct sysreset_reg *priv;
+
+	/* The reset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+				 &sys_child);
+	if (ret) {
+		debug("Warning: No sysreset driver: ret=%d\n", ret);
+	} else {
+		priv = malloc(sizeof(struct sysreset_reg));
+		priv->glb_srst_fst_value = offsetof(struct px30_cru,
+						    glb_srst_fst);
+		priv->glb_srst_snd_value = offsetof(struct px30_cru,
+						    glb_srst_snd);
+		sys_child->priv = priv;
+	}
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+	ret = offsetof(struct px30_cru, softrst_con[0]);
+	ret = rockchip_reset_bind(dev, ret, 12);
+	if (ret)
+		debug("Warning: software reset driver bind faile\n");
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id px30_clk_ids[] = {
+	{ .compatible = "rockchip,px30-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_px30_cru) = {
+	.name		= "rockchip_px30_cru",
+	.id		= UCLASS_CLK,
+	.of_match	= px30_clk_ids,
+	.priv_auto_alloc_size = sizeof(struct px30_clk_priv),
+	.ofdata_to_platdata = px30_clk_ofdata_to_platdata,
+	.ops		= &px30_clk_ops,
+	.bind		= px30_clk_bind,
+	.probe		= px30_clk_probe,
+};
+
+static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv)
+{
+	struct px30_pmucru *pmucru = priv->pmucru;
+	u32 div, con;
+
+	con = readl(&pmucru->pmu_clksel_con[0]);
+	div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT;
+
+	return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
+{
+	struct px30_pmucru *pmucru = priv->pmucru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	rk_clrsetreg(&pmucru->pmu_clksel_con[0],
+		     CLK_PMU_PCLK_DIV_MASK,
+		     (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT);
+
+	return px30_pclk_pmu_get_pmuclk(priv);
+}
+
+static ulong px30_pmuclk_get_gpll_rate(struct px30_pmuclk_priv *priv)
+{
+	struct px30_pmucru *pmucru = priv->pmucru;
+
+	return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
+}
+
+static ulong px30_pmuclk_set_gpll_rate(struct px30_pmuclk_priv *priv, ulong hz)
+{
+	struct px30_pmucru *pmucru = priv->pmucru;
+	ulong pclk_pmu_rate;
+	u32 div;
+
+	if (priv->gpll_hz == hz)
+		return priv->gpll_hz;
+
+	div = DIV_ROUND_UP(hz, priv->gpll_hz);
+
+	/* save clock rate */
+	pclk_pmu_rate = px30_pclk_pmu_get_pmuclk(priv);
+
+	/* avoid rate too large, reduce rate first */
+	px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate / div);
+
+	/* change gpll rate */
+	rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz);
+	priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
+
+	/* restore clock rate */
+	px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate);
+
+	return priv->gpll_hz;
+}
+
+static ulong px30_pmuclk_get_rate(struct clk *clk)
+{
+	struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	debug("%s %ld\n", __func__, clk->id);
+	switch (clk->id) {
+	case PLL_GPLL:
+		rate = px30_pmuclk_get_gpll_rate(priv);
+		break;
+	case PCLK_PMU_PRE:
+		rate = px30_pclk_pmu_get_pmuclk(priv);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate)
+{
+	struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	debug("%s %ld %ld\n", __func__, clk->id, rate);
+	switch (clk->id) {
+	case PLL_GPLL:
+		ret = px30_pmuclk_set_gpll_rate(priv, rate);
+		break;
+	case PCLK_PMU_PRE:
+		ret = px30_pclk_pmu_set_pmuclk(priv, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+static struct clk_ops px30_pmuclk_ops = {
+	.get_rate = px30_pmuclk_get_rate,
+	.set_rate = px30_pmuclk_set_rate,
+};
+
+static void px30_pmuclk_init(struct px30_pmuclk_priv *priv)
+{
+	priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
+	px30_pmuclk_set_gpll_rate(priv, GPLL_HZ);
+
+	px30_pclk_pmu_set_pmuclk(priv, PCLK_PMU_HZ);
+}
+
+static int px30_pmuclk_probe(struct udevice *dev)
+{
+	struct px30_pmuclk_priv *priv = dev_get_priv(dev);
+
+	px30_pmuclk_init(priv);
+
+	return 0;
+}
+
+static int px30_pmuclk_ofdata_to_platdata(struct udevice *dev)
+{
+	struct px30_pmuclk_priv *priv = dev_get_priv(dev);
+
+	priv->pmucru = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static const struct udevice_id px30_pmuclk_ids[] = {
+	{ .compatible = "rockchip,px30-pmucru" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_px30_pmucru) = {
+	.name		= "rockchip_px30_pmucru",
+	.id		= UCLASS_CLK,
+	.of_match	= px30_pmuclk_ids,
+	.priv_auto_alloc_size = sizeof(struct px30_pmuclk_priv),
+	.ofdata_to_platdata = px30_pmuclk_ofdata_to_platdata,
+	.ops		= &px30_pmuclk_ops,
+	.probe		= px30_pmuclk_probe,
+};
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index 9bf9cedaf8cded8b5aaa08adf6d96dac773be83e..6d5ae3d003143be4bfe6d32bf2bd3eab4097a59e 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -352,7 +352,7 @@ static int rk3036_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3036_cru, cru_softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 9);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
index dda686cfb3a084fa43b3fb0922afafef8f50f7a9..3ea9a81b32456c1afe69344acf9c7a659610f6f2 100644
--- a/drivers/clk/rockchip/clk_rk3188.c
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -590,7 +590,7 @@ static int rk3188_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3188_cru, cru_softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 9);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index f09730c91b452be2880d7e5fcfb40b2f95fbce6f..6e8a164d6220594bce61f7ca3c3062275765648d 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -508,7 +508,7 @@ static int rk322x_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk322x_cru, cru_softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 9);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 01223816337660386bc5f163c30c1e1b6caf3412..85d1b67e4311985f7f1fa9e3fb67cb23108315e3 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -1015,7 +1015,7 @@ static int rk3288_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3288_cru, cru_softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 12);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk3308.c b/drivers/clk/rockchip/clk_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..f212c5ffc2c632a1e91462aa95103371b274db5c
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3308.c
@@ -0,0 +1,1072 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017-2019 Rockchip Electronics Co., Ltd
+ */
+#include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <div64.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/cru_rk3308.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rk3308-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	VCO_MAX_HZ	= 3200U * 1000000,
+	VCO_MIN_HZ	= 800 * 1000000,
+	OUTPUT_MAX_HZ	= 3200U * 1000000,
+	OUTPUT_MIN_HZ	= 24 * 1000000,
+};
+
+#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
+
+#define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)         \
+{                                                               \
+	.rate   = _rate##U,                                     \
+	.aclk_div = _aclk_div,                                  \
+	.pclk_div = _pclk_div,                                  \
+}
+
+static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
+};
+
+static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
+	RK3308_CPUCLK_RATE(1200000000, 1, 5),
+	RK3308_CPUCLK_RATE(1008000000, 1, 5),
+	RK3308_CPUCLK_RATE(816000000, 1, 3),
+	RK3308_CPUCLK_RATE(600000000, 1, 3),
+	RK3308_CPUCLK_RATE(408000000, 1, 1),
+};
+
+static struct rockchip_pll_clock rk3308_pll_clks[] = {
+	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
+		     RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
+	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
+		     RK3308_MODE_CON, 2, 10, 0, NULL),
+	[VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
+		      RK3308_MODE_CON, 4, 10, 0, NULL),
+	[VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
+		      RK3308_MODE_CON, 6, 10, 0, NULL),
+};
+
+static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
+{
+	struct rk3308_cru *cru = priv->cru;
+	const struct rockchip_cpu_rate_table *rate;
+	ulong old_rate;
+
+	rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
+	if (!rate) {
+		printf("%s unsupport rate\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * select apll as cpu/core clock pll source and
+	 * set up dependent divisors for PERI and ACLK clocks.
+	 * core hz : apll = 1:1
+	 */
+	old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+					 priv->cru, APLL);
+	if (old_rate > hz) {
+		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
+					  priv->cru, APLL, hz))
+			return -EINVAL;
+		rk_clrsetreg(&cru->clksel_con[0],
+			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
+			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+			     0 << CORE_DIV_CON_SHIFT);
+	} else if (old_rate < hz) {
+		rk_clrsetreg(&cru->clksel_con[0],
+			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
+			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+			     0 << CORE_DIV_CON_SHIFT);
+		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
+					  priv->cru, APLL, hz))
+			return -EINVAL;
+	}
+
+	return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
+}
+
+static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
+{
+	if (!priv->dpll_hz)
+		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+						      priv->cru, DPLL);
+	if (!priv->vpll0_hz)
+		priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+						       priv->cru, VPLL0);
+	if (!priv->vpll1_hz)
+		priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+						       priv->cru, VPLL1);
+}
+
+static ulong rk3308_i2c_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, con_id;
+
+	switch (clk->id) {
+	case SCLK_I2C0:
+		con_id = 25;
+		break;
+	case SCLK_I2C1:
+		con_id = 26;
+		break;
+	case SCLK_I2C2:
+		con_id = 27;
+		break;
+	case SCLK_I2C3:
+		con_id = 28;
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	con = readl(&cru->clksel_con[con_id]);
+	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+
+	return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 src_clk_div, con_id;
+
+	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk->id) {
+	case SCLK_I2C0:
+		con_id = 25;
+		break;
+	case SCLK_I2C1:
+		con_id = 26;
+		break;
+	case SCLK_I2C2:
+		con_id = 27;
+		break;
+	case SCLK_I2C3:
+		con_id = 28;
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+	rk_clrsetreg(&cru->clksel_con[con_id],
+		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
+		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
+		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
+
+	return rk3308_i2c_get_clk(clk);
+}
+
+static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 con = readl(&cru->clksel_con[43]);
+	ulong pll_rate;
+	u8 div;
+
+	if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
+		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+						 priv->cru, VPLL0);
+	else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
+		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+						 priv->cru, VPLL1);
+	else
+		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+						 priv->cru, DPLL);
+
+	/*default set 50MHZ for gmac*/
+	if (!hz)
+		hz = 50000000;
+
+	div = DIV_ROUND_UP(pll_rate, hz) - 1;
+	assert(div < 32);
+	rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
+		     div << MAC_DIV_SHIFT);
+
+	return DIV_TO_RATE(pll_rate, div);
+}
+
+static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+
+	if (hz != 2500000 && hz != 25000000) {
+		debug("Unsupported mac speed:%d\n", hz);
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
+		     ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
+
+	return 0;
+}
+
+static ulong rk3308_mmc_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, con_id;
+
+	switch (clk->id) {
+	case HCLK_SDMMC:
+	case SCLK_SDMMC:
+		con_id = 39;
+		break;
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		con_id = 41;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	con = readl(&cru->clksel_con[con_id]);
+	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
+
+	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
+	    == EMMC_SEL_24M)
+		return DIV_TO_RATE(OSC_HZ, div) / 2;
+	else
+		return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
+}
+
+static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+	u32 con_id;
+
+	switch (clk->id) {
+	case HCLK_SDMMC:
+	case SCLK_SDMMC:
+		con_id = 39;
+		break;
+	case HCLK_EMMC:
+	case SCLK_EMMC:
+		con_id = 41;
+		break;
+	default:
+		return -EINVAL;
+	}
+	/* Select clk_sdmmc/emmc source from VPLL0 by default */
+	/* mmc clock defaulg div 2 internal, need provide double in cru */
+	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
+
+	if (src_clk_div > 127) {
+		/* use 24MHz source for 400KHz clock */
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+		rk_clrsetreg(&cru->clksel_con[con_id],
+			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
+			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
+			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
+			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
+	} else {
+		rk_clrsetreg(&cru->clksel_con[con_id],
+			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
+			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
+			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
+			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
+	}
+
+	return rk3308_mmc_get_clk(clk);
+}
+
+static ulong rk3308_saradc_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[34]);
+	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+	assert(src_clk_div - 1 <= 2047);
+
+	rk_clrsetreg(&cru->clksel_con[34],
+		     CLK_SARADC_DIV_CON_MASK,
+		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rk3308_saradc_get_clk(clk);
+}
+
+static ulong rk3308_tsadc_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[33]);
+	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+	assert(src_clk_div - 1 <= 2047);
+
+	rk_clrsetreg(&cru->clksel_con[33],
+		     CLK_SARADC_DIV_CON_MASK,
+		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rk3308_tsadc_get_clk(clk);
+}
+
+static ulong rk3308_spi_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, con_id;
+
+	switch (clk->id) {
+	case SCLK_SPI0:
+		con_id = 30;
+		break;
+	case SCLK_SPI1:
+		con_id = 31;
+		break;
+	case SCLK_SPI2:
+		con_id = 32;
+		break;
+	default:
+		printf("do not support this spi bus\n");
+		return -EINVAL;
+	}
+
+	con = readl(&cru->clksel_con[con_id]);
+	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+
+	return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 src_clk_div, con_id;
+
+	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk->id) {
+	case SCLK_SPI0:
+		con_id = 30;
+		break;
+	case SCLK_SPI1:
+		con_id = 31;
+		break;
+	case SCLK_SPI2:
+		con_id = 32;
+		break;
+	default:
+		printf("do not support this spi bus\n");
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[con_id],
+		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
+		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
+		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
+
+	return rk3308_spi_get_clk(clk);
+}
+
+static ulong rk3308_pwm_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[29]);
+	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+
+	return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+	assert(src_clk_div - 1 <= 127);
+
+	rk_clrsetreg(&cru->clksel_con[29],
+		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
+		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
+		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
+
+	return rk3308_pwm_get_clk(clk);
+}
+
+static ulong rk3308_vop_get_clk(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, pll_sel, vol_sel, con, parent;
+
+	con = readl(&cru->clksel_con[8]);
+	vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
+	pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
+	div = con & DCLK_VOP_DIV_MASK;
+
+	if (vol_sel == DCLK_VOP_SEL_24M) {
+		parent = OSC_HZ;
+	} else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
+		switch (pll_sel) {
+		case DCLK_VOP_PLL_SEL_DPLL:
+			parent = priv->dpll_hz;
+			break;
+		case DCLK_VOP_PLL_SEL_VPLL0:
+			parent = priv->vpll0_hz;
+			break;
+		case DCLK_VOP_PLL_SEL_VPLL1:
+			parent = priv->vpll0_hz;
+			break;
+		default:
+			printf("do not support this vop pll sel\n");
+			return -EINVAL;
+		}
+	} else {
+		printf("do not support this vop sel\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3308_cru *cru = priv->cru;
+	ulong pll_rate, now, best_rate = 0;
+	u32 i, div, best_div = 0, best_sel = 0;
+
+	for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
+		switch (i) {
+		case DCLK_VOP_PLL_SEL_DPLL:
+			pll_rate = priv->dpll_hz;
+			break;
+		case DCLK_VOP_PLL_SEL_VPLL0:
+			pll_rate = priv->vpll0_hz;
+			break;
+		case DCLK_VOP_PLL_SEL_VPLL1:
+			pll_rate = priv->vpll1_hz;
+			break;
+		default:
+			printf("do not support this vop pll sel\n");
+			return -EINVAL;
+		}
+
+		div = DIV_ROUND_UP(pll_rate, hz);
+		if (div > 255)
+			continue;
+		now = pll_rate / div;
+		if (abs(hz - now) < abs(hz - best_rate)) {
+			best_rate = now;
+			best_div = div;
+			best_sel = i;
+		}
+		debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
+		      pll_rate, best_rate, best_div, best_sel);
+	}
+
+	if (best_rate != hz && hz == OSC_HZ) {
+		rk_clrsetreg(&cru->clksel_con[8],
+			     DCLK_VOP_SEL_MASK,
+			     DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
+	} else if (best_rate) {
+		rk_clrsetreg(&cru->clksel_con[8],
+			     DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
+			     DCLK_VOP_DIV_MASK,
+			     DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
+			     best_sel << DCLK_VOP_PLL_SEL_SHIFT |
+			     (best_div - 1) << DCLK_VOP_DIV_SHIFT);
+	} else {
+		printf("do not support this vop freq\n");
+		return -EINVAL;
+	}
+
+	return rk3308_vop_get_clk(clk);
+}
+
+static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, parent = priv->dpll_hz;
+
+	switch (clk_id) {
+	case ACLK_BUS:
+		con = readl(&cru->clksel_con[5]);
+		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
+		break;
+	case HCLK_BUS:
+		con = readl(&cru->clksel_con[6]);
+		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
+		break;
+	case PCLK_BUS:
+	case PCLK_WDT:
+		con = readl(&cru->clksel_con[6]);
+		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+				ulong hz)
+{
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select dpll as pd_bus bus clock source and
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	switch (clk_id) {
+	case ACLK_BUS:
+		rk_clrsetreg(&cru->clksel_con[5],
+			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
+			     BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
+		break;
+	case HCLK_BUS:
+		rk_clrsetreg(&cru->clksel_con[6],
+			     BUS_HCLK_DIV_MASK,
+			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
+		break;
+	case PCLK_BUS:
+		rk_clrsetreg(&cru->clksel_con[6],
+			     BUS_PCLK_DIV_MASK,
+			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this bus freq\n");
+		return -EINVAL;
+	}
+
+	return rk3308_bus_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, parent = priv->dpll_hz;
+
+	switch (clk_id) {
+	case ACLK_PERI:
+		con = readl(&cru->clksel_con[36]);
+		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
+		break;
+	case HCLK_PERI:
+		con = readl(&cru->clksel_con[37]);
+		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
+		break;
+	case PCLK_PERI:
+		con = readl(&cru->clksel_con[37]);
+		div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+				 ulong hz)
+{
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select dpll as pd_peri bus clock source and
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	switch (clk_id) {
+	case ACLK_PERI:
+		rk_clrsetreg(&cru->clksel_con[36],
+			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
+			     PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
+		break;
+	case HCLK_PERI:
+		rk_clrsetreg(&cru->clksel_con[37],
+			     PERI_HCLK_DIV_MASK,
+			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
+		break;
+	case PCLK_PERI:
+		rk_clrsetreg(&cru->clksel_con[37],
+			     PERI_PCLK_DIV_MASK,
+			     (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this peri freq\n");
+		return -EINVAL;
+	}
+
+	return rk3308_peri_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, parent = priv->vpll0_hz;
+
+	switch (clk_id) {
+	case HCLK_AUDIO:
+		con = readl(&cru->clksel_con[45]);
+		div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
+		break;
+	case PCLK_AUDIO:
+		con = readl(&cru->clksel_con[45]);
+		div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+				  ulong hz)
+{
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select vpll0 as audio bus clock source and
+	 * set up dependent divisors for HCLK and PCLK clocks.
+	 */
+	switch (clk_id) {
+	case HCLK_AUDIO:
+		rk_clrsetreg(&cru->clksel_con[45],
+			     AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
+			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
+		break;
+	case PCLK_AUDIO:
+		rk_clrsetreg(&cru->clksel_con[45],
+			     AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
+			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this audio freq\n");
+		return -EINVAL;
+	}
+
+	return rk3308_peri_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+	struct rk3308_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case SCLK_CRYPTO:
+		con = readl(&cru->clksel_con[7]);
+		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
+		parent = priv->vpll0_hz;
+		break;
+	case SCLK_CRYPTO_APK:
+		con = readl(&cru->clksel_con[7]);
+		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
+		parent = priv->vpll0_hz;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+				   ulong hz)
+{
+	struct rk3308_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
+	assert(src_clk_div - 1 <= 31);
+
+	/*
+	 * select gpll as crypto clock source and
+	 * set up dependent divisors for crypto clocks.
+	 */
+	switch (clk_id) {
+	case SCLK_CRYPTO:
+		rk_clrsetreg(&cru->clksel_con[7],
+			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
+			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
+		break;
+	case SCLK_CRYPTO_APK:
+		rk_clrsetreg(&cru->clksel_con[7],
+			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
+			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
+			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
+		break;
+	default:
+		printf("do not support this peri freq\n");
+		return -EINVAL;
+	}
+
+	return rk3308_crypto_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_clk_get_rate(struct clk *clk)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	debug("%s id:%ld\n", __func__, clk->id);
+
+	switch (clk->id) {
+	case PLL_APLL:
+	case ARMCLK:
+		rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+					     priv->cru, APLL);
+		break;
+	case PLL_DPLL:
+		rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+					     priv->cru, DPLL);
+		break;
+	case PLL_VPLL0:
+		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+					     priv->cru, VPLL0);
+		break;
+	case PLL_VPLL1:
+		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+					     priv->cru, VPLL1);
+		break;
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		rate = rk3308_mmc_get_clk(clk);
+		break;
+	case SCLK_I2C0:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		rate = rk3308_i2c_get_clk(clk);
+		break;
+	case SCLK_SARADC:
+		rate = rk3308_saradc_get_clk(clk);
+		break;
+	case SCLK_TSADC:
+		rate = rk3308_tsadc_get_clk(clk);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		rate = rk3308_spi_get_clk(clk);
+		break;
+	case SCLK_PWM0:
+		rate = rk3308_pwm_get_clk(clk);
+		break;
+	case DCLK_VOP:
+		rate = rk3308_vop_get_clk(clk);
+		break;
+	case ACLK_BUS:
+	case HCLK_BUS:
+	case PCLK_BUS:
+	case PCLK_WDT:
+		rate = rk3308_bus_get_clk(priv, clk->id);
+		break;
+	case ACLK_PERI:
+	case HCLK_PERI:
+	case PCLK_PERI:
+		rate = rk3308_peri_get_clk(priv, clk->id);
+		break;
+	case HCLK_AUDIO:
+	case PCLK_AUDIO:
+		rate = rk3308_audio_get_clk(priv, clk->id);
+		break;
+	case SCLK_CRYPTO:
+	case SCLK_CRYPTO_APK:
+		rate = rk3308_crypto_get_clk(priv, clk->id);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	debug("%s %ld %ld\n", __func__, clk->id, rate);
+
+	switch (clk->id) {
+	case PLL_DPLL:
+		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
+					    DPLL, rate);
+		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+						      priv->cru, DPLL);
+		break;
+	case ARMCLK:
+		if (priv->armclk_hz)
+			rk3308_armclk_set_clk(priv, rate);
+		priv->armclk_hz = rate;
+		break;
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+		ret = rk3308_mmc_set_clk(clk, rate);
+		break;
+	case SCLK_I2C0:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		ret = rk3308_i2c_set_clk(clk, rate);
+		break;
+	case SCLK_MAC:
+		ret = rk3308_mac_set_clk(clk, rate);
+		break;
+	case SCLK_MAC_RMII:
+		ret = rk3308_mac_set_speed_clk(clk, rate);
+		break;
+	case SCLK_SARADC:
+		ret = rk3308_saradc_set_clk(clk, rate);
+		break;
+	case SCLK_TSADC:
+		ret = rk3308_tsadc_set_clk(clk, rate);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		ret = rk3308_spi_set_clk(clk, rate);
+		break;
+	case SCLK_PWM0:
+		ret = rk3308_pwm_set_clk(clk, rate);
+		break;
+	case DCLK_VOP:
+		ret = rk3308_vop_set_clk(clk, rate);
+		break;
+	case ACLK_BUS:
+	case HCLK_BUS:
+	case PCLK_BUS:
+		rate = rk3308_bus_set_clk(priv, clk->id, rate);
+		break;
+	case ACLK_PERI:
+	case HCLK_PERI:
+	case PCLK_PERI:
+		rate = rk3308_peri_set_clk(priv, clk->id, rate);
+		break;
+	case HCLK_AUDIO:
+	case PCLK_AUDIO:
+		rate = rk3308_audio_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_CRYPTO:
+	case SCLK_CRYPTO_APK:
+		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+
+	/*
+	 * If the requested parent is in the same clock-controller and
+	 * the id is SCLK_MAC_SRC, switch to the internal clock.
+	 */
+	if (parent->id == SCLK_MAC_SRC) {
+		debug("%s: switching RMII to SCLK_MAC\n", __func__);
+		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
+	} else {
+		debug("%s: switching RMII to CLKIN\n", __func__);
+		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
+	}
+
+	return 0;
+}
+
+static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	switch (clk->id) {
+	case SCLK_MAC:
+		return rk3308_mac_set_parent(clk, parent);
+	default:
+		break;
+	}
+
+	debug("%s: unsupported clk %ld\n", __func__, clk->id);
+	return -ENOENT;
+}
+#endif
+
+static struct clk_ops rk3308_clk_ops = {
+	.get_rate = rk3308_clk_get_rate,
+	.set_rate = rk3308_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.set_parent = rk3308_clk_set_parent,
+#endif
+};
+
+static void rk3308_clk_init(struct udevice *dev)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+				  priv->cru, APLL) != APLL_HZ) {
+		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
+		if (ret < 0)
+			printf("%s failed to set armclk rate\n", __func__);
+	}
+
+	rk3308_clk_get_pll_rate(priv);
+
+	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
+	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
+	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
+
+	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
+	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
+	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
+
+	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
+	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
+}
+
+static int rk3308_clk_probe(struct udevice *dev)
+{
+	int ret;
+
+	rk3308_clk_init(dev);
+
+	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+	ret = clk_set_defaults(dev, 1);
+	if (ret)
+		debug("%s clk_set_defaults failed %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk3308_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static int rk3308_clk_bind(struct udevice *dev)
+{
+	int ret;
+	struct udevice *sys_child;
+	struct sysreset_reg *priv;
+
+	/* The reset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+				 &sys_child);
+	if (ret) {
+		debug("Warning: No sysreset driver: ret=%d\n", ret);
+	} else {
+		priv = malloc(sizeof(struct sysreset_reg));
+		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
+						    glb_srst_fst);
+		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
+						    glb_srst_snd);
+		sys_child->priv = priv;
+	}
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+	ret = offsetof(struct rk3308_cru, softrst_con[0]);
+	ret = rockchip_reset_bind(dev, ret, 12);
+	if (ret)
+		debug("Warning: software reset driver bind faile\n");
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id rk3308_clk_ids[] = {
+	{ .compatible = "rockchip,rk3308-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rk3308_cru) = {
+	.name		= "rockchip_rk3308_cru",
+	.id		= UCLASS_CLK,
+	.of_match	= rk3308_clk_ids,
+	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
+	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
+	.ops		= &rk3308_clk_ops,
+	.bind		= rk3308_clk_bind,
+	.probe		= rk3308_clk_probe,
+};
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 4331048a87612113bf3f2a684eccc21e32e05782..e700a1bc25cb0e5ed431e085b247c8b80c407f96 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -791,7 +791,7 @@ static int rk3328_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3328_cru, softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 12);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c
index c1a867b2eded7fb355ef72233584c979e08580f7..b51d529adea02858e33242d1122d01533649f0c6 100644
--- a/drivers/clk/rockchip/clk_rk3368.c
+++ b/drivers/clk/rockchip/clk_rk3368.c
@@ -620,7 +620,7 @@ static int rk3368_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3368_cru, softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 15);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index a273bd1bebe476164a2356a3ed03aba993d3f30b..9020a9f202acb2f6286726c3f1cfb2b28fde00c3 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -1195,7 +1195,7 @@ static int rk3399_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
 	ret = offsetof(struct rk3399_cru, softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 21);
 	if (ret)
diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c
index 3ebb007fab36a31d1e3ba3f011ba76ebe6935e06..97fdd099ef39a04e6f151cbe63c3bdb40565ae25 100644
--- a/drivers/clk/rockchip/clk_rv1108.c
+++ b/drivers/clk/rockchip/clk_rv1108.c
@@ -679,9 +679,8 @@ static int rv1108_clk_probe(struct udevice *dev)
 static int rv1108_clk_bind(struct udevice *dev)
 {
 	int ret;
-	struct udevice *sys_child, *sf_child;
+	struct udevice *sys_child;
 	struct sysreset_reg *priv;
-	struct softreset_reg *sf_priv;
 
 	/* The reset driver does not have a device node, so bind it here */
 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
@@ -697,23 +696,12 @@ static int rv1108_clk_bind(struct udevice *dev)
 		sys_child->priv = priv;
 	}
 
-#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
-	ret = offsetof(struct rk3368_cru, softrst_con[0]);
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+	ret = offsetof(struct rv1108_cru, softrst_con[0]);
 	ret = rockchip_reset_bind(dev, ret, 13);
 	if (ret)
 		debug("Warning: software reset driver bind faile\n");
 #endif
-	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
-					 dev_ofnode(dev), &sf_child);
-	if (ret) {
-		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
-	} else {
-		sf_priv = malloc(sizeof(struct softreset_reg));
-		sf_priv->sf_reset_offset = offsetof(struct rv1108_cru,
-						    softrst_con[0]);
-		sf_priv->sf_reset_num = 13;
-		sf_child->priv = sf_priv;
-	}
 
 	return 0;
 }
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 7a8ba587da5bf1441d0dbbb4be6e13209c6f7f2b..82bb093c564c577e014d09b8e7802f6f1b490912 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -59,6 +59,15 @@ config ROCKCHIP_EFUSE
 	  extended (by porting the read function from the Linux kernel sources)
 	  to support other recent Rockchip devices.
 
+config ROCKCHIP_OTP
+	bool "Rockchip OTP Support"
+	depends on MISC
+	help
+	  Enable (read-only) access for the one-time-programmable memory block
+	  found in Rockchip SoCs: accesses can either be made using byte
+	  addressing and a length or through child-nodes that are generated
+	  based on the e-fuse map retrieved from the DTS.
+
 config VEXPRESS_CONFIG
 	bool "Enable support for Arm Versatile Express config bus"
 	depends on MISC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 870655e80228d09cea5433982c2373b4114e50c2..55976d6be5ffee5d1002bfeafbc44e3ffbe2aadf 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
 obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
+obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o
 obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
 obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
 obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c
new file mode 100644
index 0000000000000000000000000000000000000000..bdd443b3db9bea0da1386e01bb902b4476303691
--- /dev/null
+++ b/drivers/misc/rockchip-otp.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <command.h>
+#include <dm.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <misc.h>
+
+/* OTP Register Offsets */
+#define OTPC_SBPI_CTRL			0x0020
+#define OTPC_SBPI_CMD_VALID_PRE		0x0024
+#define OTPC_SBPI_CS_VALID_PRE		0x0028
+#define OTPC_SBPI_STATUS		0x002C
+#define OTPC_USER_CTRL			0x0100
+#define OTPC_USER_ADDR			0x0104
+#define OTPC_USER_ENABLE		0x0108
+#define OTPC_USER_QP			0x0120
+#define OTPC_USER_Q			0x0124
+#define OTPC_INT_STATUS			0x0304
+#define OTPC_SBPI_CMD0_OFFSET		0x1000
+#define OTPC_SBPI_CMD1_OFFSET		0x1004
+
+/* OTP Register bits and masks */
+#define OTPC_USER_ADDR_MASK		GENMASK(31, 16)
+#define OTPC_USE_USER			BIT(0)
+#define OTPC_USE_USER_MASK		GENMASK(16, 16)
+#define OTPC_USER_FSM_ENABLE		BIT(0)
+#define OTPC_USER_FSM_ENABLE_MASK	GENMASK(16, 16)
+#define OTPC_SBPI_DONE			BIT(1)
+#define OTPC_USER_DONE			BIT(2)
+
+#define SBPI_DAP_ADDR			0x02
+#define SBPI_DAP_ADDR_SHIFT		8
+#define SBPI_DAP_ADDR_MASK		GENMASK(31, 24)
+#define SBPI_CMD_VALID_MASK		GENMASK(31, 16)
+#define SBPI_DAP_CMD_WRF		0xC0
+#define SBPI_DAP_REG_ECC		0x3A
+#define SBPI_ECC_ENABLE			0x00
+#define SBPI_ECC_DISABLE		0x09
+#define SBPI_ENABLE			BIT(0)
+#define SBPI_ENABLE_MASK		GENMASK(16, 16)
+
+#define OTPC_TIMEOUT			10000
+
+struct rockchip_otp_platdata {
+	void __iomem *base;
+	unsigned long secure_conf_base;
+	unsigned long otp_mask_base;
+};
+
+static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp,
+				    u32 flag)
+{
+	int delay = OTPC_TIMEOUT;
+
+	while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
+		udelay(1);
+		delay--;
+		if (delay <= 0) {
+			printf("%s: wait init status timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* clean int status */
+	writel(flag, otp->base + OTPC_INT_STATUS);
+
+	return 0;
+}
+
+static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp,
+				   bool enable)
+{
+	int ret = 0;
+
+	writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
+	       otp->base + OTPC_SBPI_CTRL);
+
+	writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
+	writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
+	       otp->base + OTPC_SBPI_CMD0_OFFSET);
+
+	if (enable)
+		writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
+	else
+		writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
+
+	writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
+
+	ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
+	if (ret < 0)
+		printf("%s timeout during ecc_enable\n", __func__);
+
+	return ret;
+}
+
+static int rockchip_px30_otp_read(struct udevice *dev, int offset,
+				  void *buf, int size)
+{
+	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
+	u8 *buffer = buf;
+	int ret = 0;
+
+	ret = rockchip_otp_ecc_enable(otp, false);
+	if (ret < 0) {
+		printf("%s rockchip_otp_ecc_enable err\n", __func__);
+		return ret;
+	}
+
+	writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+	udelay(5);
+	while (size--) {
+		writel(offset++ | OTPC_USER_ADDR_MASK,
+		       otp->base + OTPC_USER_ADDR);
+		writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
+		       otp->base + OTPC_USER_ENABLE);
+
+		ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
+		if (ret < 0) {
+			printf("%s timeout during read setup\n", __func__);
+			goto read_end;
+		}
+
+		*buffer++ = readb(otp->base + OTPC_USER_Q);
+	}
+
+read_end:
+	writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+
+	return ret;
+}
+
+static int rockchip_otp_read(struct udevice *dev, int offset,
+			     void *buf, int size)
+{
+	return rockchip_px30_otp_read(dev, offset, buf, size);
+}
+
+static const struct misc_ops rockchip_otp_ops = {
+	.read = rockchip_otp_read,
+};
+
+static int rockchip_otp_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
+
+	otp->base = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static const struct udevice_id rockchip_otp_ids[] = {
+	{
+		.compatible = "rockchip,px30-otp",
+		.data = (ulong)&rockchip_px30_otp_read,
+	},
+	{
+		.compatible = "rockchip,rk3308-otp",
+		.data = (ulong)&rockchip_px30_otp_read,
+	},
+	{}
+};
+
+U_BOOT_DRIVER(rockchip_otp) = {
+	.name = "rockchip_otp",
+	.id = UCLASS_MISC,
+	.of_match = rockchip_otp_ids,
+	.ops = &rockchip_otp_ops,
+	.ofdata_to_platdata = rockchip_otp_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata),
+};
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 26a612117506bf4059654cb48648bd290badab67..d2c52b4c46f878b47cede7e2d6783c5dca77f627 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -14,6 +14,7 @@
 #include <asm/arch-rockchip/periph.h>
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/grf_px30.h>
 #include <asm/arch-rockchip/grf_rk322x.h>
 #include <asm/arch-rockchip/grf_rk3288.h>
 #include <asm/arch-rockchip/grf_rk3328.h>
@@ -72,6 +73,47 @@ static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev)
 	return designware_eth_ofdata_to_platdata(dev);
 }
 
+static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+{
+	struct px30_grf *grf;
+	struct clk clk_speed;
+	int speed, ret;
+	enum {
+		PX30_GMAC_SPEED_SHIFT = 0x2,
+		PX30_GMAC_SPEED_MASK  = BIT(2),
+		PX30_GMAC_SPEED_10M   = 0,
+		PX30_GMAC_SPEED_100M  = BIT(2),
+	};
+
+	ret = clk_get_by_name(priv->phydev->dev, "clk_mac_speed",
+			      &clk_speed);
+	if (ret)
+		return ret;
+
+	switch (priv->phydev->speed) {
+	case 10:
+		speed = PX30_GMAC_SPEED_10M;
+		ret = clk_set_rate(&clk_speed, 2500000);
+		if (ret)
+			return ret;
+		break;
+	case 100:
+		speed = PX30_GMAC_SPEED_100M;
+		ret = clk_set_rate(&clk_speed, 25000000);
+		if (ret)
+			return ret;
+		break;
+	default:
+		debug("Unknown phy speed: %d\n", priv->phydev->speed);
+		return -EINVAL;
+	}
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	rk_clrsetreg(&grf->mac_con1, PX30_GMAC_SPEED_MASK, speed);
+
+	return 0;
+}
+
 static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 {
 	struct rk322x_grf *grf;
@@ -257,6 +299,22 @@ static int rv1108_set_rmii_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
+static void px30_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata)
+{
+	struct px30_grf *grf;
+	enum {
+		PX30_GMAC_PHY_INTF_SEL_SHIFT = 4,
+		PX30_GMAC_PHY_INTF_SEL_MASK  = GENMASK(4, 6),
+		PX30_GMAC_PHY_INTF_SEL_RMII  = BIT(6),
+	};
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+
+	rk_clrsetreg(&grf->mac_con1,
+		     PX30_GMAC_PHY_INTF_SEL_MASK,
+		     PX30_GMAC_PHY_INTF_SEL_RMII);
+}
+
 static void rk3228_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
 {
 	struct rk322x_grf *grf;
@@ -445,6 +503,10 @@ static int gmac_rockchip_probe(struct udevice *dev)
 	ulong rate;
 	int ret;
 
+	ret = clk_set_defaults(dev, 0);
+	if (ret)
+		debug("%s clk_set_defaults failed %d\n", __func__, ret);
+
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret)
 		return ret;
@@ -569,6 +631,11 @@ const struct eth_ops gmac_rockchip_eth_ops = {
 	.write_hwaddr		= designware_eth_write_hwaddr,
 };
 
+const struct rk_gmac_ops px30_gmac_ops = {
+	.fix_mac_speed = px30_gmac_fix_mac_speed,
+	.set_to_rmii = px30_gmac_set_to_rmii,
+};
+
 const struct rk_gmac_ops rk3228_gmac_ops = {
 	.fix_mac_speed = rk3228_gmac_fix_mac_speed,
 	.set_to_rgmii = rk3228_gmac_set_to_rgmii,
@@ -600,6 +667,8 @@ const struct rk_gmac_ops rv1108_gmac_ops = {
 };
 
 static const struct udevice_id rockchip_gmac_ids[] = {
+	{ .compatible = "rockchip,px30-gmac",
+	  .data = (ulong)&px30_gmac_ops },
 	{ .compatible = "rockchip,rk3228-gmac",
 	  .data = (ulong)&rk3228_gmac_ops },
 	{ .compatible = "rockchip,rk3288-gmac",
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index a616d8587fe0273c65460d099b7447ed9d0e0d7f..83913f668f44e2cd3d4c4cad88c380a7b91a3511 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -3,6 +3,7 @@
 # Copyright (c) 2017 Rockchip Electronics Co., Ltd
 
 obj-y += pinctrl-rockchip-core.o
+obj-$(CONFIG_ROCKCHIP_PX30) += pinctrl-px30.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += pinctrl-rk3036.o
 obj-$(CONFIG_ROCKCHIP_RK3128) += pinctrl-rk3128.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += pinctrl-rk3188.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-px30.c b/drivers/pinctrl/rockchip/pinctrl-px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb56ae9fb343a59d2517f85819a36155e432e214
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-px30.c
@@ -0,0 +1,368 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+
+static struct rockchip_mux_route_data px30_mux_route_data[] = {
+	{
+		/* cif-d2m0 */
+		.bank_num = 2,
+		.pin = 0,
+		.func = 1,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 7),
+	}, {
+		/* cif-d2m1 */
+		.bank_num = 3,
+		.pin = 3,
+		.func = 3,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 7) | BIT(7),
+	}, {
+		/* pdm-m0 */
+		.bank_num = 3,
+		.pin = 22,
+		.func = 2,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 8),
+	}, {
+		/* pdm-m1 */
+		.bank_num = 2,
+		.pin = 22,
+		.func = 1,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 8) | BIT(8),
+	}, {
+		/* uart2-rxm0 */
+		.bank_num = 1,
+		.pin = 27,
+		.func = 2,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 10),
+	}, {
+		/* uart2-rxm1 */
+		.bank_num = 2,
+		.pin = 14,
+		.func = 2,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 10) | BIT(10),
+	}, {
+		/* uart3-rxm0 */
+		.bank_num = 0,
+		.pin = 17,
+		.func = 2,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 9),
+	}, {
+		/* uart3-rxm1 */
+		.bank_num = 1,
+		.pin = 15,
+		.func = 2,
+		.route_offset = 0x184,
+		.route_val = BIT(16 + 9) | BIT(9),
+	},
+};
+
+static int px30_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	int reg, ret, mask, mux_type;
+	u8 bit;
+	u32 data, route_reg, route_val;
+
+	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+				? priv->regmap_pmu : priv->regmap_base;
+
+	/* get basic quadrupel of mux registers and the correct reg inside */
+	mux_type = bank->iomux[iomux_num].type;
+	reg = bank->iomux[iomux_num].offset;
+	reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
+
+	if (bank->route_mask & BIT(pin)) {
+		if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
+					   &route_val)) {
+			ret = regmap_write(regmap, route_reg, route_val);
+			if (ret)
+				return ret;
+		}
+	}
+
+	data = (mask << (bit + 16));
+	data |= (mux & mask) << bit;
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+#define PX30_PULL_PMU_OFFSET		0x10
+#define PX30_PULL_GRF_OFFSET		0x60
+#define PX30_PULL_BITS_PER_PIN		2
+#define PX30_PULL_PINS_PER_REG		8
+#define PX30_PULL_BANK_STRIDE		16
+
+static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = priv->regmap_pmu;
+		*reg = PX30_PULL_PMU_OFFSET;
+	} else {
+		*regmap = priv->regmap_base;
+		*reg = PX30_PULL_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * PX30_PULL_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4);
+	*bit = (pin_num % PX30_PULL_PINS_PER_REG);
+	*bit *= PX30_PULL_BITS_PER_PIN;
+}
+
+static int px30_set_pull(struct rockchip_pin_bank *bank,
+			 int pin_num, int pull)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u8 bit, type;
+	u32 data;
+
+	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+		return -ENOTSUPP;
+
+	px30_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	type = bank->pull_type[pin_num / 8];
+	ret = rockchip_translate_pull_value(type, pull);
+	if (ret < 0) {
+		debug("unsupported pull setting %d\n", pull);
+		return ret;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (ret << bit);
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+#define PX30_DRV_PMU_OFFSET		0x20
+#define PX30_DRV_GRF_OFFSET		0xf0
+#define PX30_DRV_BITS_PER_PIN		2
+#define PX30_DRV_PINS_PER_REG		8
+#define PX30_DRV_BANK_STRIDE		16
+
+static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				      int pin_num, struct regmap **regmap,
+				      int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = priv->regmap_pmu;
+		*reg = PX30_DRV_PMU_OFFSET;
+	} else {
+		*regmap = priv->regmap_base;
+		*reg = PX30_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * PX30_DRV_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4);
+	*bit = (pin_num % PX30_DRV_PINS_PER_REG);
+	*bit *= PX30_DRV_BITS_PER_PIN;
+}
+
+static int px30_set_drive(struct rockchip_pin_bank *bank,
+			  int pin_num, int strength)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u32 data, rmask_bits, temp;
+	u8 bit;
+	int drv_type = bank->drv[pin_num / 8].drv_type;
+
+	px30_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	ret = rockchip_translate_drive_value(drv_type, strength);
+	if (ret < 0) {
+		debug("unsupported driver strength %d\n", strength);
+		return ret;
+	}
+
+	switch (drv_type) {
+	case DRV_TYPE_IO_1V8_3V0_AUTO:
+	case DRV_TYPE_IO_3V3_ONLY:
+		rmask_bits = ROCKCHIP_DRV_3BITS_PER_PIN;
+		switch (bit) {
+		case 0 ... 12:
+			/* regular case, nothing to do */
+			break;
+		case 15:
+			/*
+			 * drive-strength offset is special, as it is spread
+			 * over 2 registers, the bit data[15] contains bit 0
+			 * of the value while temp[1:0] contains bits 2 and 1
+			 */
+			data = (ret & 0x1) << 15;
+			temp = (ret >> 0x1) & 0x3;
+
+			data |= BIT(31);
+			ret = regmap_write(regmap, reg, data);
+			if (ret)
+				return ret;
+
+			temp |= (0x3 << 16);
+			reg += 0x4;
+			ret = regmap_write(regmap, reg, temp);
+
+			return ret;
+		case 18 ... 21:
+			/* setting fully enclosed in the second register */
+			reg += 4;
+			bit -= 16;
+			break;
+		default:
+			debug("unsupported bit: %d for pinctrl drive type: %d\n",
+			      bit, drv_type);
+			return -EINVAL;
+		}
+		break;
+	case DRV_TYPE_IO_DEFAULT:
+	case DRV_TYPE_IO_1V8_OR_3V0:
+	case DRV_TYPE_IO_1V8_ONLY:
+		rmask_bits = ROCKCHIP_DRV_BITS_PER_PIN;
+		break;
+	default:
+		debug("unsupported pinctrl drive type: %d\n",
+		      drv_type);
+		return -EINVAL;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << rmask_bits) - 1) << (bit + 16);
+	data |= (ret << bit);
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+#define PX30_SCHMITT_PMU_OFFSET			0x38
+#define PX30_SCHMITT_GRF_OFFSET			0xc0
+#define PX30_SCHMITT_PINS_PER_PMU_REG		16
+#define PX30_SCHMITT_BANK_STRIDE		16
+#define PX30_SCHMITT_PINS_PER_GRF_REG		8
+
+static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num,
+					 struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int pins_per_reg;
+
+	if (bank->bank_num == 0) {
+		*regmap = priv->regmap_pmu;
+		*reg = PX30_SCHMITT_PMU_OFFSET;
+		pins_per_reg = PX30_SCHMITT_PINS_PER_PMU_REG;
+	} else {
+		*regmap = priv->regmap_base;
+		*reg = PX30_SCHMITT_GRF_OFFSET;
+		pins_per_reg = PX30_SCHMITT_PINS_PER_GRF_REG;
+		*reg += (bank->bank_num - 1) * PX30_SCHMITT_BANK_STRIDE;
+	}
+	*reg += ((pin_num / pins_per_reg) * 4);
+	*bit = pin_num % pins_per_reg;
+
+	return 0;
+}
+
+static int px30_set_schmitt(struct rockchip_pin_bank *bank,
+			    int pin_num, int enable)
+{
+	struct regmap *regmap;
+	int reg;
+	u8 bit;
+	u32 data;
+
+	px30_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	/* enable the write to the equivalent lower bits */
+	data = BIT(bit + 16) | (enable << bit);
+
+	return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank px30_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU
+			    ),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT,
+					     IOMUX_WIDTH_4BIT
+			    ),
+};
+
+static struct rockchip_pin_ctrl px30_pin_ctrl = {
+	.pin_banks		= px30_pin_banks,
+	.nr_banks		= ARRAY_SIZE(px30_pin_banks),
+	.grf_mux_offset		= 0x0,
+	.pmu_mux_offset		= 0x0,
+	.grf_drv_offset		= 0xf0,
+	.pmu_drv_offset		= 0x20,
+	.iomux_routes		= px30_mux_route_data,
+	.niomux_routes		= ARRAY_SIZE(px30_mux_route_data),
+	.set_mux		= px30_set_mux,
+	.set_pull		= px30_set_pull,
+	.set_drive		= px30_set_drive,
+	.set_schmitt		= px30_set_schmitt,
+};
+
+static const struct udevice_id px30_pinctrl_ids[] = {
+	{
+		.compatible = "rockchip,px30-pinctrl",
+		.data = (ulong)&px30_pin_ctrl
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_px30) = {
+	.name		= "rockchip_px30_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= px30_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
+	.ops		= &rockchip_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rockchip_pinctrl_probe,
+};
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index bb431ccfbf0a0136af88cfac90ca9afbd3a8bb96..b454ceb599c23a80f5217505ebf5c3918db8ad16 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -19,7 +19,7 @@ config SPL_RAM
 
 config TPL_RAM
 	bool "Enable RAM support in TPL"
-	depends on RAM && TPL_DM
+	depends on RAM
 	help
 	  The RAM subsystem adds a small amount of overhead to the image.
 	  If this is acceptable and you have a need to use RAM drivers in
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
index 4f274e01b3565a4f1f5ca49b73c8210c97d0d661..b75d581f579722b0de832772f695e83f8e8c518f 100644
--- a/drivers/ram/rockchip/Kconfig
+++ b/drivers/ram/rockchip/Kconfig
@@ -5,10 +5,15 @@ config RAM_ROCKCHIP
 	help
 	  This enables support for ram drivers Rockchip SoCs.
 
-if RAM_ROCKCHIP
+config ROCKCHIP_SDRAM_COMMON
+	bool "Enable rockchip sdram common driver"
+	depends on TPL_RAM || SPL_RAM
+	help
+	  This enable sdram common driver
 
 config RAM_ROCKCHIP_DEBUG
 	bool "Rockchip ram drivers debugging"
+	default y
 	help
 	  This enables debugging ram driver API's for the platforms
 	  based on Rockchip SoCs.
@@ -16,18 +21,10 @@ config RAM_ROCKCHIP_DEBUG
 	  This is an option for developers to understand the ram drivers
 	  initialization, configurations and etc.
 
-config RAM_RK3399
-	bool "Ram driver for Rockchip RK3399"
-	default ROCKCHIP_RK3399
-	help
-	  This enables ram drivers support for the platforms based on
-	  Rockchip RK3399 SoC.
-
 config RAM_RK3399_LPDDR4
 	bool "LPDDR4 support for Rockchip RK3399"
-	depends on RAM_RK3399
+	depends on RAM_ROCKCHIP && ROCKCHIP_RK3399
 	help
 	  This enables LPDDR4 sdram code support for the platforms based
 	  on Rockchip RK3399 SoC.
 
-endif # RAM_ROCKCHIP
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index feb1f82d00773f643fc40063cbdbe09d865e5861..c3ec89ada4c581810faac8c66dd29001f01c161b 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -3,11 +3,13 @@
 # Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
 #
 
-obj-$(CONFIG_RAM_ROCKCHIP_DEBUG) += sdram_debug.o
+obj-$(CONFIG_ROCKCHIP_PX30) += sdram_px30.o sdram_pctl_px30.o sdram_phy_px30.o
 obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3128) = sdram_rk3128.o
 obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
 obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
-obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o
-obj-$(CONFIG_RAM_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3308) = sdram_rk3308.o
+obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
+obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o
diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c
index e52fc3baad92dc4a58395d8b4afb12b7cf4b67b4..9df8f8f4af009e6315b997cf1a2ec7386c4cfa9c 100644
--- a/drivers/ram/rockchip/dmc-rk3368.c
+++ b/drivers/ram/rockchip/dmc-rk3368.c
@@ -17,7 +17,7 @@
 #include <asm/arch-rockchip/grf_rk3368.h>
 #include <asm/arch-rockchip/ddr_rk3368.h>
 #include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
 
 struct dram_info {
 	struct ram_info info;
diff --git a/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc b/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc
new file mode 100644
index 0000000000000000000000000000000000000000..76cd8dc1a5908fd7061768286565c8f5cb4bd713
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr3-detect-333.inc
@@ -0,0 +1,72 @@
+{
+	{
+		{
+			.rank = 0x1,
+			.col = 0xC,
+			.bk = 0x3,
+			.bw = 0x1,
+			.dbw = 0x0,
+			.row_3_4 = 0x0,
+			.cs0_row = 0x10,
+			.cs1_row = 0x10,
+			.cs0_high16bit_row = 0x10,
+			.cs1_high16bit_row = 0x10,
+			.ddrconfig = 0,
+		},
+		{
+			{0x290b0609},
+			{0x08020401},
+			{0x00000002},
+			{0x00001111},
+			{0x0000000c},
+			{0x00000222},
+			0x000000ff
+		}
+	},
+	{
+		.ddr_freq = 333,
+		.dramtype = DDR3,
+		.num_channels = 1,
+		.stride = 0,
+		.odt = 0,
+	},
+	{
+		{
+			{0x00000000, 0x43041001},	/* MSTR */
+			{0x00000064, 0x0028003b},	/* RFSHTMG */
+			{0x000000d0, 0x00020053},	/* INIT0 */
+			{0x000000d4, 0x00020000},	/* INIT1 */
+			{0x000000d8, 0x00000100},	/* INIT2 */
+			{0x000000dc, 0x03200000},	/* INIT3 */
+			{0x000000e0, 0x00000000},	/* INIT4 */
+			{0x000000e4, 0x00090000},	/* INIT5 */
+			{0x000000f4, 0x000f012f},	/* RANKCTL */
+			{0x00000100, 0x07090b06},	/* DRAMTMG0 */
+			{0x00000104, 0x00050209},	/* DRAMTMG1 */
+			{0x00000108, 0x03030407},	/* DRAMTMG2 */
+			{0x0000010c, 0x00202006},	/* DRAMTMG3 */
+			{0x00000110, 0x03020204},	/* DRAMTMG4 */
+			{0x00000114, 0x03030202},	/* DRAMTMG5 */
+			{0x00000120, 0x00000903},	/* DRAMTMG8 */
+			{0x00000180, 0x00800020},	/* ZQCTL0 */
+			{0x00000184, 0x00000000},	/* ZQCTL1 */
+			{0x00000190, 0x07010001},	/* DFITMG0 */
+			{0x00000198, 0x07000101},	/* DFILPCFG0 */
+			{0x000001a0, 0xc0400003},	/* DFIUPD0 */
+			{0x00000240, 0x06000604},	/* ODTCFG */
+			{0x00000244, 0x00000201},	/* ODTMAP */
+			{0x00000250, 0x00001f00},	/* SCHED */
+			{0x00000490, 0x00000001},	/* PCTRL_0 */
+			{0xffffffff, 0xffffffff}
+		}
+	},
+	{
+		{
+			{0x00000004, 0x0000000a},	/* PHYREG01 */
+			{0x00000028, 0x00000006},	/* PHYREG0A */
+			{0x0000002c, 0x00000000},	/* PHYREG0B */
+			{0x00000030, 0x00000005},	/* PHYREG0C */
+			{0xffffffff, 0xffffffff}
+		}
+	}
+},
diff --git a/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc b/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc
new file mode 100644
index 0000000000000000000000000000000000000000..f804d2839326546c80cbdfebd8b14aa966d27aca
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr4-detect-333.inc
@@ -0,0 +1,75 @@
+{
+	{
+		{
+			.rank = 0x1,
+			.col = 0xA,
+			.bk = 0x2,
+			.bw = 0x1,
+			.dbw = 0x0,
+			.row_3_4 = 0x0,
+			.cs0_row = 0x11,
+			.cs1_row = 0x0,
+			.cs0_high16bit_row = 0x11,
+			.cs1_high16bit_row = 0x0,
+			.ddrconfig = 0,
+		},
+		{
+			{0x4d110a08},
+			{0x06020501},
+			{0x00000002},
+			{0x00001111},
+			{0x0000000c},
+			{0x0000022a},
+			0x000000ff
+		}
+	},
+	{
+		.ddr_freq = 333,
+		.dramtype = DDR4,
+		.num_channels = 1,
+		.stride = 0,
+		.odt = 0,
+	},
+	{
+		{
+			{0x00000000, 0x43049010},	/* MSTR */
+			{0x00000064, 0x0028003b},	/* RFSHTMG */
+			{0x000000d0, 0x00020053},	/* INIT0 */
+			{0x000000d4, 0x00220000},	/* INIT1 */
+			{0x000000d8, 0x00000100},	/* INIT2 */
+			{0x000000dc, 0x00040000},	/* INIT3 */
+			{0x000000e0, 0x00000000},	/* INIT4 */
+			{0x000000e4, 0x00110000},	/* INIT5 */
+			{0x000000e8, 0x00000420},	/* INIT6 */
+			{0x000000ec, 0x00000400},	/* INIT7 */
+			{0x000000f4, 0x000f012f},	/* RANKCTL */
+			{0x00000100, 0x09060b06},	/* DRAMTMG0 */
+			{0x00000104, 0x00020209},	/* DRAMTMG1 */
+			{0x00000108, 0x0505040a},	/* DRAMTMG2 */
+			{0x0000010c, 0x0040400c},	/* DRAMTMG3 */
+			{0x00000110, 0x05030206},	/* DRAMTMG4 */
+			{0x00000114, 0x03030202},	/* DRAMTMG5 */
+			{0x00000120, 0x03030b03},	/* DRAMTMG8 */
+			{0x00000124, 0x00020208},	/* DRAMTMG9 */
+			{0x00000180, 0x01000040},	/* ZQCTL0 */
+			{0x00000184, 0x00000000},	/* ZQCTL1 */
+			{0x00000190, 0x07030003},	/* DFITMG0 */
+			{0x00000198, 0x07000101},	/* DFILPCFG0 */
+			{0x000001a0, 0xc0400003},	/* DFIUPD0 */
+			{0x00000240, 0x06000604},	/* ODTCFG */
+			{0x00000244, 0x00000201},	/* ODTMAP */
+			{0x00000250, 0x00001f00},	/* SCHED */
+			{0x00000490, 0x00000001},	/* PCTRL_0 */
+			{0xffffffff, 0xffffffff}
+		}
+	},
+	{
+		{
+			{0x00000004, 0x0000000c},	/* PHYREG01 */
+			{0x00000028, 0x0000000a},	/* PHYREG0A */
+			{0x0000002c, 0x00000000},	/* PHYREG0B */
+			{0x00000030, 0x00000009},	/* PHYREG0C */
+			{0xffffffff, 0xffffffff}
+		}
+	}
+},
\ No newline at end of file
diff --git a/drivers/ram/rockchip/sdram-px30-ddr_skew.inc b/drivers/ram/rockchip/sdram-px30-ddr_skew.inc
new file mode 100644
index 0000000000000000000000000000000000000000..f24343dda1b94796d9b5558f8ffe15494b318e16
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-ddr_skew.inc
@@ -0,0 +1,121 @@
+		{
+			0x77,
+			0x88,
+			0x79,
+			0x79,
+			0x87,
+			0x97,
+			0x87,
+			0x78,
+			0x77,
+			0x78,
+			0x87,
+			0x88,
+			0x87,
+			0x87,
+			0x77
+		},
+		{
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x69,
+			0x9,
+		},
+		{
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x79,
+			0x9,
+		},
+		{
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x69,
+			0x9,
+		},
+		{
+			0x77,
+			0x78,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x79,
+			0x9,
+		},
+		{
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x69,
+			0x9,
+		},
+		{
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x78,
+			0x77,
+			0x79,
+			0x9,
+		},
+		{
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x78,
+			0x69,
+			0x9,
+		},
+		{
+			0x77,
+			0x78,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x77,
+			0x79,
+			0x9,
+		}
diff --git a/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc b/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc
new file mode 100644
index 0000000000000000000000000000000000000000..948ade483b31b8ed4e2655d64bad09615566bde5
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-lpddr2-detect-333.inc
@@ -0,0 +1,73 @@
+{
+	{
+		{
+			.rank = 0x1,
+			.col = 0xC,
+			.bk = 0x3,
+			.bw = 0x1,
+			.dbw = 0x0,
+			.row_3_4 = 0x0,
+			.cs0_row = 0xF,
+			.cs1_row = 0xF,
+			.cs0_high16bit_row = 0xF,
+			.cs1_high16bit_row = 0xF,
+			.ddrconfig = 0,
+		},
+		{
+			{0x2b0c070a},
+			{0x08020303},
+			{0x00000002},
+			{0x00001111},
+			{0x0000000c},
+			{0x00000219},
+			0x000000ff
+		}
+	},
+	{
+		.ddr_freq = 333,
+		.dramtype = LPDDR2,
+		.num_channels = 1,
+		.stride = 0,
+		.odt = 0,
+	},
+	{
+		{
+			{0x00000000, 0x41041004},	/* MSTR */
+			{0x00000064, 0x00140023},	/* RFSHTMG */
+			{0x000000d0, 0x00220002},	/* INIT0 */
+			{0x000000d4, 0x00010000},	/* INIT1 */
+			{0x000000d8, 0x00000703},	/* INIT2 */
+			{0x000000dc, 0x00630005},	/* INIT3 */
+			{0x000000e0, 0x00010000},	/* INIT4 */
+			{0x000000e4, 0x00070003},	/* INIT5 */
+			{0x000000f4, 0x000f012f},	/* RANKCTL */
+			{0x00000100, 0x07090b07},	/* DRAMTMG0 */
+			{0x00000104, 0x0002010b},	/* DRAMTMG1 */
+			{0x00000108, 0x02040506},	/* DRAMTMG2 */
+			{0x0000010c, 0x00303000},	/* DRAMTMG3 */
+			{0x00000110, 0x04010204},	/* DRAMTMG4 */
+			{0x00000114, 0x01010303},	/* DRAMTMG5 */
+			{0x00000118, 0x02020003},	/* DRAMTMG6 */
+			{0x00000120, 0x00000303},	/* DRAMTMG8 */
+			{0x00000138, 0x00000025},	/* DRAMTMG14 */
+			{0x00000180, 0x003c000f},	/* ZQCTL0 */
+			{0x00000184, 0x00900000},	/* ZQCTL1 */
+			{0x00000190, 0x07020001},	/* DFITMG0 */
+			{0x00000198, 0x07000101},	/* DFILPCFG0 */
+			{0x000001a0, 0xc0400003},	/* DFIUPD0 */
+			{0x00000240, 0x07030718},	/* ODTCFG */
+			{0x00000250, 0x00001f00},	/* SCHED */
+			{0x00000490, 0x00000001},	/* PCTRL_0 */
+			{0xffffffff, 0xffffffff}
+		}
+	},
+	{
+		{
+			{0x00000004, 0x00000009},	/* PHYREG01 */
+			{0x00000028, 0x00000007},	/* PHYREG0A */
+			{0x0000002c, 0x00000000},	/* PHYREG0B */
+			{0x00000030, 0x00000004},	/* PHYREG0C */
+			{0xffffffff, 0xffffffff}
+		}
+	}
+},
diff --git a/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc b/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc
new file mode 100644
index 0000000000000000000000000000000000000000..f694a0e5b0dcd49ce7d762c28d4df9e18d9f255e
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-px30-lpddr3-detect-333.inc
@@ -0,0 +1,74 @@
+{
+	{
+		{
+			.rank = 0x1,
+			.col = 0xC,
+			.bk = 0x3,
+			.bw = 0x1,
+			.dbw = 0x0,
+			.row_3_4 = 0x0,
+			.cs0_row = 0x10,
+			.cs1_row = 0x10,
+			.cs0_high16bit_row = 0x10,
+			.cs1_high16bit_row = 0x10,
+			.ddrconfig = 0,
+		},
+		{
+			{0x290a060a},
+			{0x08020303},
+			{0x00000002},
+			{0x00001111},
+			{0x0000000c},
+			{0x0000021a},
+			0x000000ff
+		}
+	},
+	{
+		.ddr_freq = 333,
+		.dramtype = LPDDR3,
+		.num_channels = 1,
+		.stride = 0,
+		.odt = 0,
+	},
+	{
+		{
+			{0x00000000, 0x43041008},	/* MSTR */
+			{0x00000064, 0x00140023},	/* RFSHTMG */
+			{0x000000d0, 0x00220002},	/* INIT0 */
+			{0x000000d4, 0x00010000},	/* INIT1 */
+			{0x000000d8, 0x00000703},	/* INIT2 */
+			{0x000000dc, 0x00830004},	/* INIT3 */
+			{0x000000e0, 0x00010000},	/* INIT4 */
+			{0x000000e4, 0x00070003},	/* INIT5 */
+			{0x000000f4, 0x000f012f},	/* RANKCTL */
+			{0x00000100, 0x06090b07},	/* DRAMTMG0 */
+			{0x00000104, 0x0002020b},	/* DRAMTMG1 */
+			{0x00000108, 0x02030506},	/* DRAMTMG2 */
+			{0x0000010c, 0x00505000},	/* DRAMTMG3 */
+			{0x00000110, 0x03020204},	/* DRAMTMG4 */
+			{0x00000114, 0x01010303},	/* DRAMTMG5 */
+			{0x00000118, 0x02020003},	/* DRAMTMG6 */
+			{0x00000120, 0x00000303},	/* DRAMTMG8 */
+			{0x00000138, 0x00000025},	/* DRAMTMG14 */
+			{0x00000180, 0x003c000f},	/* ZQCTL0 */
+			{0x00000184, 0x00900000},	/* ZQCTL1 */
+			{0x00000190, 0x07020000},	/* DFITMG0 */
+			{0x00000198, 0x07000101},	/* DFILPCFG0 */
+			{0x000001a0, 0xc0400003},	/* DFIUPD0 */
+			{0x00000240, 0x0900090c},	/* ODTCFG */
+			{0x00000244, 0x00000101},	/* ODTMAP */
+			{0x00000250, 0x00001f00},	/* SCHED */
+			{0x00000490, 0x00000001},	/* PCTRL_0 */
+			{0xffffffff, 0xffffffff}
+		}
+	},
+	{
+		{
+			{0x00000004, 0x0000000b},	/* PHYREG01 */
+			{0x00000028, 0x00000006},	/* PHYREG0A */
+			{0x0000002c, 0x00000000},	/* PHYREG0B */
+			{0x00000030, 0x00000003},	/* PHYREG0C */
+			{0xffffffff, 0xffffffff}
+		}
+	}
+},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
index c50a03d9dd231b1560895dbc12d4390edc3309bb..209ef572286e0da9cef0c95e7a6e26686f7cca72 100644
--- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-400.inc
@@ -16,15 +16,23 @@
 				.row_3_4 = 0x0,
 				.cs0_row = 0xF,
 				.cs1_row = 0xF,
+				.cs0_high16bit_row = 0xF,
+				.cs1_high16bit_row = 0xF,
 				.ddrconfig = 1,
 			},
 			{
-				.ddrtiminga0 = 0x80241d22,
-				.ddrtimingb0 = 0x15050f08,
+				.ddrtiminga0 = {
+					0x8010100d,
+				},
+				.ddrtimingb0 = {
+					0x08020b04,
+				},
 				.ddrtimingc0 = {
 					0x00000602,
 				},
-				.devtodev0 = 0x00002122,
+				.devtodev0 = {
+					0x00002562,
+				},
 				.ddrmode = {
 					0x0000004c,
 				},
@@ -41,15 +49,23 @@
 				.row_3_4 = 0x0,
 				.cs0_row = 0xF,
 				.cs1_row = 0xF,
+				.cs0_high16bit_row = 0xF,
+				.cs1_high16bit_row = 0xF,
 				.ddrconfig = 1,
 			},
 			{
-				.ddrtiminga0 = 0x80241d22,
-				.ddrtimingb0 = 0x15050f08,
+				.ddrtiminga0 = {
+					0x8010100d,
+				},
+				.ddrtimingb0 = {
+					0x08020b04,
+				},
 				.ddrtimingc0 = {
 					0x00000602,
 				},
-				.devtodev0 = 0x00002122,
+				.devtodev0 = {
+					0x00002562,
+				},
 				.ddrmode = {
 					0x0000004c,
 				},
diff --git a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
index d8ae3359a394c5d7131479f091443fc9b85c1f2e..7d11b4c5632a9a82c012f6a55eb68c3981f0afbc 100644
--- a/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
+++ b/drivers/ram/rockchip/sdram-rk3399-lpddr4-800.inc
@@ -16,15 +16,23 @@
 				.row_3_4 = 0x0,
 				.cs0_row = 0xF,
 				.cs1_row = 0xF,
+				.cs0_high16bit_row = 0xF,
+				.cs1_high16bit_row = 0xF,
 				.ddrconfig = 1,
 			},
 			{
-				.ddrtiminga0 = 0x80241d22,
-				.ddrtimingb0 = 0x15050f08,
+				.ddrtiminga0 = {
+					0x801c1819,
+				},
+				.ddrtimingb0 = {
+					0x10040c05,
+				},
 				.ddrtimingc0 = {
 					0x00000602,
 				},
-				.devtodev0 = 0x00002122,
+				.devtodev0 = {
+					0x00002672,
+				},
 				.ddrmode = {
 					0x0000004c,
 				},
@@ -41,15 +49,23 @@
 				.row_3_4 = 0x0,
 				.cs0_row = 0xF,
 				.cs1_row = 0xF,
+				.cs0_high16bit_row = 0xF,
+				.cs1_high16bit_row = 0xF,
 				.ddrconfig = 1,
 			},
 			{
-				.ddrtiminga0 = 0x80241d22,
-				.ddrtimingb0 = 0x15050f08,
+				.ddrtiminga0 = {
+					0x80241d22,
+				},
+				.ddrtimingb0 = {
+					0x15050f08,
+				},
 				.ddrtimingc0 = {
 					0x00000602,
 				},
-				.devtodev0 = 0x00002122,
+				.devtodev0 = {
+					0x00002122,
+				},
 				.ddrmode = {
 					0x0000004c,
 				},
diff --git a/drivers/ram/rockchip/sdram_common.c b/drivers/ram/rockchip/sdram_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..6bc51572b2f1a563e43995040eb22894b186d7b1
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_common.c
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+
+#ifdef CONFIG_RAM_ROCKCHIP_DEBUG
+void sdram_print_dram_type(unsigned char dramtype)
+{
+	switch (dramtype) {
+	case DDR3:
+		printascii("DDR3");
+		break;
+	case DDR4:
+		printascii("DDR4");
+		break;
+	case LPDDR2:
+		printascii("LPDDR2");
+		break;
+	case LPDDR3:
+		printascii("LPDDR3");
+		break;
+	case LPDDR4:
+		printascii("LPDDR4");
+		break;
+	default:
+		printascii("Unknown Device");
+		break;
+	}
+}
+
+void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
+			  struct sdram_base_params *base)
+{
+	u64 cap;
+	u32 bg;
+
+	bg = (cap_info->dbw == 0) ? 2 : 1;
+
+	sdram_print_dram_type(base->dramtype);
+
+	printascii(", ");
+	printdec(base->ddr_freq);
+	printascii("MHz\n");
+
+	printascii("BW=");
+	printdec(8 << cap_info->bw);
+	printascii(" Col=");
+	printdec(cap_info->col);
+	printascii(" Bk=");
+	printdec(0x1 << cap_info->bk);
+	if (base->dramtype == DDR4) {
+		printascii(" BG=");
+		printdec(1 << bg);
+	}
+	printascii(" CS0 Row=");
+	printdec(cap_info->cs0_row);
+	if (cap_info->cs0_high16bit_row !=
+		cap_info->cs0_row) {
+		printascii("/");
+		printdec(cap_info->cs0_high16bit_row);
+	}
+	if (cap_info->rank > 1) {
+		printascii(" CS1 Row=");
+		printdec(cap_info->cs1_row);
+		if (cap_info->cs1_high16bit_row !=
+			cap_info->cs1_row) {
+			printascii("/");
+			printdec(cap_info->cs1_high16bit_row);
+		}
+	}
+	printascii(" CS=");
+	printdec(cap_info->rank);
+	printascii(" Die BW=");
+	printdec(8 << cap_info->dbw);
+
+	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
+	if (cap_info->row_3_4)
+		cap = cap * 3 / 4;
+
+	printascii(" Size=");
+	printdec(cap >> 20);
+	printascii("MB\n");
+}
+
+void sdram_print_stride(unsigned int stride)
+{
+	switch (stride) {
+	case 0xc:
+		printf("128B stride\n");
+		break;
+	case 5:
+	case 9:
+	case 0xd:
+	case 0x11:
+	case 0x19:
+		printf("256B stride\n");
+		break;
+	case 0xa:
+	case 0xe:
+	case 0x12:
+		printf("512B stride\n");
+		break;
+	case 0xf:
+		printf("4K stride\n");
+		break;
+	case 0x1f:
+		printf("32MB + 256B stride\n");
+		break;
+	default:
+		printf("no stride\n");
+	}
+}
+#endif
+
+/*
+ * cs: 0:cs0
+ *	   1:cs1
+ *     else cs0+cs1
+ * note: it didn't consider about row_3_4
+ */
+u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
+{
+	u32 bg;
+	u64 cap[2];
+
+	if (dram_type == DDR4)
+		/* DDR4 8bit dram BG = 2(4bank groups),
+		 * 16bit dram BG = 1 (2 bank groups)
+		 */
+		bg = (cap_info->dbw == 0) ? 2 : 1;
+	else
+		bg = 0;
+	cap[0] = 1llu << (cap_info->bw + cap_info->col +
+		bg + cap_info->bk + cap_info->cs0_row);
+
+	if (cap_info->rank == 2)
+		cap[1] = 1llu << (cap_info->bw + cap_info->col +
+			bg + cap_info->bk + cap_info->cs1_row);
+	else
+		cap[1] = 0;
+
+	if (cs == 0)
+		return cap[0];
+	else if (cs == 1)
+		return cap[1];
+	else
+		return (cap[0] + cap[1]);
+}
+
+/* n: Unit bytes */
+void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+	int i;
+
+	for (i = 0; i < n / sizeof(u32); i++) {
+		writel(*src, dest);
+		src++;
+		dest++;
+	}
+}
+
+void sdram_org_config(struct sdram_cap_info *cap_info,
+		      struct sdram_base_params *base,
+		      u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
+{
+	*p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
+	*p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
+
+	*p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
+	*p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
+	*p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
+	*p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
+	*p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
+	*p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
+	*p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
+
+	SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
+	if (cap_info->cs1_row)
+		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
+				    *p_os_reg3, channel);
+	*p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
+	*p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
+}
+
+int sdram_detect_bw(struct sdram_cap_info *cap_info)
+{
+	return 0;
+}
+
+int sdram_detect_cs(struct sdram_cap_info *cap_info)
+{
+	return 0;
+}
+
+int sdram_detect_col(struct sdram_cap_info *cap_info,
+		     u32 coltmp)
+{
+	void __iomem *test_addr;
+	u32 col;
+	u32 bw = cap_info->bw;
+
+	for (col = coltmp; col >= 9; col -= 1) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+				(1ul << (col + bw - 1ul)));
+		writel(PATTERN, test_addr);
+		if ((readl(test_addr) == PATTERN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (col == 8) {
+		printascii("col error\n");
+		return -1;
+	}
+
+	cap_info->col = col;
+
+	return 0;
+}
+
+int sdram_detect_bank(struct sdram_cap_info *cap_info,
+		      u32 coltmp, u32 bktmp)
+{
+	void __iomem *test_addr;
+	u32 bk;
+	u32 bw = cap_info->bw;
+
+	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+			(1ul << (coltmp + bktmp + bw - 1ul)));
+	writel(0, CONFIG_SYS_SDRAM_BASE);
+	writel(PATTERN, test_addr);
+	if ((readl(test_addr) == PATTERN) &&
+	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+		bk = 3;
+	else
+		bk = 2;
+
+	cap_info->bk = bk;
+
+	return 0;
+}
+
+/* detect bg for ddr4 */
+int sdram_detect_bg(struct sdram_cap_info *cap_info,
+		    u32 coltmp)
+{
+	void __iomem *test_addr;
+	u32 dbw;
+	u32 bw = cap_info->bw;
+
+	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+			(1ul << (coltmp + bw + 1ul)));
+	writel(0, CONFIG_SYS_SDRAM_BASE);
+	writel(PATTERN, test_addr);
+	if ((readl(test_addr) == PATTERN) &&
+	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+		dbw = 0;
+	else
+		dbw = 1;
+
+	cap_info->dbw = dbw;
+
+	return 0;
+}
+
+/* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
+int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
+{
+	u32 row, col, bk, bw, cs_cap, cs;
+	u32 die_bw_0 = 0, die_bw_1 = 0;
+
+	if (dram_type == DDR3 || dram_type == LPDDR4) {
+		cap_info->dbw = 1;
+	} else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
+		row = cap_info->cs0_row;
+		col = cap_info->col;
+		bk = cap_info->bk;
+		cs = cap_info->rank;
+		bw = cap_info->bw;
+		cs_cap = (1 << (row + col + bk + bw - 20));
+		if (bw == 2) {
+			if (cs_cap <= 0x2000000) /* 256Mb */
+				die_bw_0 = (col < 9) ? 2 : 1;
+			else if (cs_cap <= 0x10000000) /* 2Gb */
+				die_bw_0 = (col < 10) ? 2 : 1;
+			else if (cs_cap <= 0x40000000) /* 8Gb */
+				die_bw_0 = (col < 11) ? 2 : 1;
+			else
+				die_bw_0 = (col < 12) ? 2 : 1;
+			if (cs > 1) {
+				row = cap_info->cs1_row;
+				cs_cap = (1 << (row + col + bk + bw - 20));
+				if (cs_cap <= 0x2000000) /* 256Mb */
+					die_bw_0 = (col < 9) ? 2 : 1;
+				else if (cs_cap <= 0x10000000) /* 2Gb */
+					die_bw_0 = (col < 10) ? 2 : 1;
+				else if (cs_cap <= 0x40000000) /* 8Gb */
+					die_bw_0 = (col < 11) ? 2 : 1;
+				else
+					die_bw_0 = (col < 12) ? 2 : 1;
+			}
+		} else {
+			die_bw_1 = 1;
+			die_bw_0 = 1;
+		}
+		cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
+	}
+
+	return 0;
+}
+
+int sdram_detect_row(struct sdram_cap_info *cap_info,
+		     u32 coltmp, u32 bktmp, u32 rowtmp)
+{
+	u32 row;
+	u32 bw = cap_info->bw;
+	void __iomem *test_addr;
+
+	for (row = rowtmp; row > 12; row--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+				(1ul << (row + bktmp + coltmp + bw - 1ul)));
+		writel(PATTERN, test_addr);
+		if ((readl(test_addr) == PATTERN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (row == 12) {
+		printascii("row error");
+		return -1;
+	}
+
+	cap_info->cs0_row = row;
+
+	return 0;
+}
+
+int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
+			 u32 coltmp, u32 bktmp)
+{
+	u32 row_3_4;
+	u32 bw = cap_info->bw;
+	u32 row = cap_info->cs0_row;
+	void __iomem *test_addr, *test_addr1;
+
+	test_addr = CONFIG_SYS_SDRAM_BASE;
+	test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
+
+	writel(0, test_addr);
+	writel(PATTERN, test_addr1);
+	if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
+		row_3_4 = 0;
+	else
+		row_3_4 = 1;
+
+	cap_info->row_3_4 = row_3_4;
+
+	return 0;
+}
+
+int sdram_detect_high_row(struct sdram_cap_info *cap_info)
+{
+	cap_info->cs0_high16bit_row = cap_info->cs0_row;
+	cap_info->cs1_high16bit_row = cap_info->cs1_row;
+
+	return 0;
+}
+
+int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
+{
+	void __iomem *test_addr;
+	u32 row = 0, bktmp, coltmp, bw;
+	ulong cs0_cap;
+	u32 byte_mask;
+
+	if (cap_info->rank == 2) {
+		cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
+
+		if (dram_type == DDR4) {
+			if (cap_info->dbw == 0)
+				bktmp = cap_info->bk + 2;
+			else
+				bktmp = cap_info->bk + 1;
+		} else {
+			bktmp = cap_info->bk;
+		}
+		bw = cap_info->bw;
+		coltmp = cap_info->col;
+
+		/*
+		 * because px30 support axi split,min bandwidth
+		 * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
+		 * so we check low 16bit data when detect cs1 row.
+		 * if cs0 is 16bit/8bit, we check low 8bit data.
+		 */
+		if (bw == 2)
+			byte_mask = 0xFFFF;
+		else
+			byte_mask = 0xFF;
+
+		/* detect cs1 row */
+		for (row = cap_info->cs0_row; row > 12; row--) {
+			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
+				    cs0_cap +
+				    (1ul << (row + bktmp + coltmp + bw - 1ul)));
+			writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
+			writel(PATTERN, test_addr);
+
+			if (((readl(test_addr) & byte_mask) ==
+			     (PATTERN & byte_mask)) &&
+			    ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
+			      byte_mask) == 0)) {
+				break;
+			}
+		}
+	}
+
+	cap_info->cs1_row = row;
+
+	return 0;
+}
diff --git a/drivers/ram/rockchip/sdram_debug.c b/drivers/ram/rockchip/sdram_debug.c
deleted file mode 100644
index 9cf662675b2eb0500f28fae70c0f1135167de75b..0000000000000000000000000000000000000000
--- a/drivers/ram/rockchip/sdram_debug.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * (C) Copyright 2019 Rockchip Electronics Co., Ltd
- * (C) Copyright 2019 Amarula Solutions.
- * Author: Jagan Teki <jagan@amarulasolutions.com>
- */
-
-#include <common.h>
-#include <debug_uart.h>
-#include <asm/arch-rockchip/sdram_common.h>
-
-void sdram_print_dram_type(unsigned char dramtype)
-{
-	switch (dramtype) {
-	case DDR3:
-		printascii("DDR3");
-		break;
-	case DDR4:
-		printascii("DDR4");
-		break;
-	case LPDDR2:
-		printascii("LPDDR2");
-		break;
-	case LPDDR3:
-		printascii("LPDDR3");
-		break;
-	case LPDDR4:
-		printascii("LPDDR4");
-		break;
-	default:
-		printascii("Unknown Device");
-		break;
-	}
-}
-
-/**
- * cs  = 0, cs0
- * cs  = 1, cs1
- * cs => 2, cs0+cs1
- * note: it didn't consider about row_3_4
- */
-u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
-{
-	u32 bg;
-	u64 cap[2];
-
-	if (dram_type == DDR4)
-		/* DDR4 8bit dram BG = 2(4bank groups),
-		 * 16bit dram BG = 1 (2 bank groups)
-		 */
-		bg = (cap_info->dbw == 0) ? 2 : 1;
-	else
-		bg = 0;
-
-	cap[0] = 1llu << (cap_info->bw + cap_info->col +
-		 bg + cap_info->bk + cap_info->cs0_row);
-
-	if (cap_info->rank == 2)
-		cap[1] = 1llu << (cap_info->bw + cap_info->col +
-			 bg + cap_info->bk + cap_info->cs1_row);
-	else
-		cap[1] = 0;
-
-	if (cs == 0)
-		return cap[0];
-	else if (cs == 1)
-		return cap[1];
-	else
-		return (cap[0] + cap[1]);
-}
-
-void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
-			  struct sdram_base_params *base)
-{
-	u32 bg, cap;
-
-	bg = (cap_info->dbw == 0) ? 2 : 1;
-
-	sdram_print_dram_type(base->dramtype);
-
-	printascii(", ");
-	printdec(base->ddr_freq);
-	printascii("MHz\n");
-
-	printascii("BW=");
-	printdec(8 << cap_info->bw);
-
-	printascii(" Col=");
-	printdec(cap_info->col);
-
-	printascii(" Bk=");
-	printdec(0x1 << cap_info->bk);
-	if (base->dramtype == DDR4) {
-		printascii(" BG=");
-		printdec(1 << bg);
-	}
-
-	printascii(" CS0 Row=");
-	printdec(cap_info->cs0_row);
-	if (cap_info->rank > 1) {
-		printascii(" CS1 Row=");
-		printdec(cap_info->cs1_row);
-	}
-
-	printascii(" CS=");
-	printdec(cap_info->rank);
-
-	printascii(" Die BW=");
-	printdec(8 << cap_info->dbw);
-
-	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
-	if (cap_info->row_3_4)
-		cap = cap * 3 / 4;
-
-	printascii(" Size=");
-	printdec(cap >> 20);
-	printascii("MB\n");
-}
-
-void sdram_print_stride(unsigned int stride)
-{
-	switch (stride) {
-	case 0xc:
-		printf("128B stride\n");
-		break;
-	case 5:
-	case 9:
-	case 0xd:
-	case 0x11:
-	case 0x19:
-		printf("256B stride\n");
-		break;
-	case 0xa:
-	case 0xe:
-	case 0x12:
-		printf("512B stride\n");
-		break;
-	case 0xf:
-		printf("4K stride\n");
-		break;
-	case 0x1f:
-		printf("32MB + 256B stride\n");
-		break;
-	default:
-		printf("no stride\n");
-	}
-}
diff --git a/drivers/ram/rockchip/sdram_pctl_px30.c b/drivers/ram/rockchip/sdram_pctl_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..1839cebb677476197fb8346c627829b4c5096d1f
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_pctl_px30.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num)
+{
+	writel((rank << 4) | (1 << 0), pctl_base + DDR_PCTL2_MRCTRL0);
+	writel((mr_num << 8), pctl_base + DDR_PCTL2_MRCTRL1);
+	setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
+	while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
+		continue;
+	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+		continue;
+}
+
+/* rank = 1: cs0
+ * rank = 2: cs1
+ * rank = 3: cs0 & cs1
+ * note: be careful of keep mr original val
+ */
+int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
+		  u32 dramtype)
+{
+	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+		continue;
+	if (dramtype == DDR3 || dramtype == DDR4) {
+		writel((mr_num << 12) | (rank << 4) | (0 << 0),
+		       pctl_base + DDR_PCTL2_MRCTRL0);
+		writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
+	} else {
+		writel((rank << 4) | (0 << 0),
+		       pctl_base + DDR_PCTL2_MRCTRL0);
+		writel((mr_num << 8) | (arg & 0xff),
+		       pctl_base + DDR_PCTL2_MRCTRL1);
+	}
+
+	setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
+	while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
+		continue;
+	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+		continue;
+
+	return 0;
+}
+
+/*
+ * rank : 1:cs0, 2:cs1, 3:cs0&cs1
+ * vrefrate: 4500: 45%,
+ */
+int pctl_write_vrefdq(void __iomem *pctl_base, u32 rank, u32 vrefrate,
+		      u32 dramtype)
+{
+	u32 tccd_l, value;
+	u32 dis_auto_zq = 0;
+
+	if (dramtype != DDR4 || vrefrate < 4500 ||
+	    vrefrate > 9200)
+		return (-1);
+
+	tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
+	tccd_l = (tccd_l - 4) << 10;
+
+	if (vrefrate > 7500) {
+		/* range 1 */
+		value = ((vrefrate - 6000) / 65) | tccd_l;
+	} else {
+		/* range 2 */
+		value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
+	}
+
+	dis_auto_zq = pctl_dis_zqcs_aref(pctl_base);
+
+	/* enable vrefdq calibratin */
+	pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
+	udelay(1);/* tvrefdqe */
+	/* write vrefdq value */
+	pctl_write_mr(pctl_base, rank, 6, value | (1 << 7), dramtype);
+	udelay(1);/* tvref_time */
+	pctl_write_mr(pctl_base, rank, 6, value | (0 << 7), dramtype);
+	udelay(1);/* tvrefdqx */
+
+	pctl_rest_zqcs_aref(pctl_base, dis_auto_zq);
+
+	return 0;
+}
+
+static int upctl2_update_ref_reg(void __iomem *pctl_base)
+{
+	u32 ret;
+
+	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
+	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
+
+	return 0;
+}
+
+u32 pctl_dis_zqcs_aref(void __iomem *pctl_base)
+{
+	u32 dis_auto_zq = 0;
+
+	/* disable zqcs */
+	if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
+		(1ul << 31))) {
+		dis_auto_zq = 1;
+		setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+	}
+
+	/* disable auto refresh */
+	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+
+	upctl2_update_ref_reg(pctl_base);
+
+	return dis_auto_zq;
+}
+
+void pctl_rest_zqcs_aref(void __iomem *pctl_base, u32 dis_auto_zq)
+{
+	/* restore zqcs */
+	if (dis_auto_zq)
+		clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+
+	/* restore auto refresh */
+	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+
+	upctl2_update_ref_reg(pctl_base);
+}
+
+u32 pctl_remodify_sdram_params(struct ddr_pctl_regs *pctl_regs,
+			       struct sdram_cap_info *cap_info,
+			       u32 dram_type)
+{
+	u32 tmp = 0, tmp_adr = 0, i;
+
+	for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
+		if (pctl_regs->pctl[i][0] == 0) {
+			tmp = pctl_regs->pctl[i][1];/* MSTR */
+			tmp_adr = i;
+		}
+	}
+
+	tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
+
+	switch (cap_info->dbw) {
+	case 2:
+		tmp |= (3ul << 30);
+		break;
+	case 1:
+		tmp |= (2ul << 30);
+		break;
+	case 0:
+	default:
+		tmp |= (1ul << 30);
+		break;
+	}
+
+	/*
+	 * If DDR3 or DDR4 MSTR.active_ranks=1,
+	 * it will gate memory clock when enter power down.
+	 * Force set active_ranks to 3 to workaround it.
+	 */
+	if (cap_info->rank == 2 || dram_type == DDR3 ||
+	    dram_type == DDR4)
+		tmp |= 3 << 24;
+	else
+		tmp |= 1 << 24;
+
+	tmp |= (2 - cap_info->bw) << 12;
+
+	pctl_regs->pctl[tmp_adr][1] = tmp;
+
+	return 0;
+}
+
+int pctl_cfg(void __iomem *pctl_base, struct ddr_pctl_regs *pctl_regs,
+	     u32 sr_idle, u32 pd_idle)
+{
+	u32 i;
+
+	for (i = 0; pctl_regs->pctl[i][0] != 0xFFFFFFFF; i++) {
+		writel(pctl_regs->pctl[i][1],
+		       pctl_base + pctl_regs->pctl[i][0]);
+	}
+	clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
+			(0xff << 16) | 0x1f,
+			((sr_idle & 0xff) << 16) | (pd_idle & 0x1f));
+
+	clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
+			0xfff << 16,
+			5 << 16);
+	/* disable zqcs */
+	setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
+
+	return 0;
+}
diff --git a/drivers/ram/rockchip/sdram_phy_px30.c b/drivers/ram/rockchip/sdram_phy_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..5de73770a8c0bc48abbc9388e0a4bdecc389a88e
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_phy_px30.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_phy_px30.h>
+
+static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
+{
+	u32 tmp;
+	u32 i, j;
+	u32 dqs_dll_freq;
+
+	setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
+	for (i = 0; i < 4; i++) {
+		j = 0x26 + i * 0x10;
+		setbits_le32(PHY_REG(phy_base, j), 1 << 4);
+		clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
+	}
+
+	if (freq <= 400)
+		/* DLL bypass */
+		setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+	else
+		clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+
+	#ifdef CONFIG_ROCKCHIP_RK3328
+	dqs_dll_freq = 680;
+	#else
+	dqs_dll_freq = 801;
+	#endif
+
+	if (freq <= dqs_dll_freq)
+		tmp = 2;
+	else
+		tmp = 1;
+
+	for (i = 0; i < 4; i++) {
+		j = 0x28 + i * 0x10;
+		writel(tmp, PHY_REG(phy_base, j));
+	}
+}
+
+static void sdram_phy_set_ds_odt(void __iomem *phy_base,
+				 u32 dram_type)
+{
+	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
+	u32 i, j;
+
+	if (dram_type == DDR3) {
+		cmd_drv = PHY_DDR3_RON_RTT_34ohm;
+		clk_drv = PHY_DDR3_RON_RTT_45ohm;
+		dqs_drv = PHY_DDR3_RON_RTT_34ohm;
+		dqs_odt = PHY_DDR3_RON_RTT_225ohm;
+	} else {
+		cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+		clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
+		dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+		if (dram_type == LPDDR2)
+			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
+		else
+			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
+	}
+	/* DS */
+	writel(cmd_drv, PHY_REG(phy_base, 0x11));
+	clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
+	writel(clk_drv, PHY_REG(phy_base, 0x16));
+	writel(clk_drv, PHY_REG(phy_base, 0x18));
+
+	for (i = 0; i < 4; i++) {
+		j = 0x20 + i * 0x10;
+		writel(dqs_drv, PHY_REG(phy_base, j));
+		writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
+		/* ODT */
+		writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
+		writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
+	}
+}
+
+void phy_soft_reset(void __iomem *phy_base)
+{
+	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
+	udelay(1);
+	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
+	udelay(5);
+	setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
+	udelay(1);
+}
+
+void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
+{
+	if (bw == 2) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
+		setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	} else if (bw == 1) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
+		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	} else if (bw == 0) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
+		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	}
+
+	phy_soft_reset(phy_base);
+}
+
+int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
+{
+	u32 ret;
+	u32 odt_val;
+	u32 i, j;
+
+	odt_val = readl(PHY_REG(phy_base, 0x2e));
+
+	for (i = 0; i < 4; i++) {
+		j = 0x20 + i * 0x10;
+		writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
+		writel(0, PHY_REG(phy_base, j + 0xe));
+	}
+
+	if (dramtype == DDR4) {
+		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
+	}
+	/* choose training cs */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
+	/* enable gate training */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
+	udelay(50);
+	ret = readl(PHY_REG(phy_base, 0xff));
+	/* disable gate training */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
+	#ifndef CONFIG_ROCKCHIP_RK3328
+	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
+	#endif
+
+	if (dramtype == DDR4) {
+		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
+	}
+
+	if (ret & 0x10) {
+		ret = -1;
+	} else {
+		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
+		ret = (ret == 0) ? 0 : -1;
+	}
+
+	for (i = 0; i < 4; i++) {
+		j = 0x20 + i * 0x10;
+		writel(odt_val, PHY_REG(phy_base, j + 0x1));
+		writel(odt_val, PHY_REG(phy_base, j + 0xe));
+	}
+	return ret;
+}
+
+void phy_cfg(void __iomem *phy_base,
+	     struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
+	     struct sdram_base_params *base, u32 bw)
+{
+	u32 i;
+
+	sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
+	for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
+		writel(phy_regs->phy[i][1],
+		       phy_base + phy_regs->phy[i][0]);
+	}
+	if (bw == 2) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
+	} else if (bw == 1) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
+		/* disable DQS2,DQS3 tx dll  for saving power */
+		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	} else {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
+		/* disable DQS2,DQS3 tx dll  for saving power */
+		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	}
+	sdram_phy_set_ds_odt(phy_base, base->dramtype);
+
+	/* deskew */
+	setbits_le32(PHY_REG(phy_base, 2), 8);
+	sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
+			  &skew->a0_a1_skew[0], 15 * 4);
+	sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
+			  &skew->cs0_dm0_skew[0], 44 * 4);
+	sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
+			  &skew->cs1_dm0_skew[0], 44 * 4);
+}
diff --git a/drivers/ram/rockchip/sdram_px30.c b/drivers/ram/rockchip/sdram_px30.c
new file mode 100644
index 0000000000000000000000000000000000000000..729255493af408cd76b4fd841f15dc25c1739166
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_px30.c
@@ -0,0 +1,751 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+#include <asm/arch-rockchip/grf_px30.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_px30.h>
+
+struct dram_info {
+#ifdef CONFIG_TPL_BUILD
+	struct ddr_pctl_regs *pctl;
+	struct ddr_phy_regs *phy;
+	struct px30_cru *cru;
+	struct msch_regs *msch;
+	struct px30_ddr_grf_regs *ddr_grf;
+	struct px30_grf *grf;
+#endif
+	struct ram_info info;
+	struct px30_pmugrf *pmugrf;
+};
+
+#ifdef CONFIG_TPL_BUILD
+
+u8 ddr_cfg_2_rbc[] = {
+	/*
+	 * [6:4] max row: 13+n
+	 * [3]  bank(0:4bank,1:8bank)
+	 * [2:0]    col(10+n)
+	 */
+	((5 << 4) | (1 << 3) | 0), /* 0 */
+	((5 << 4) | (1 << 3) | 1), /* 1 */
+	((4 << 4) | (1 << 3) | 2), /* 2 */
+	((3 << 4) | (1 << 3) | 3), /* 3 */
+	((2 << 4) | (1 << 3) | 4), /* 4 */
+	((5 << 4) | (0 << 3) | 2), /* 5 */
+	((4 << 4) | (1 << 3) | 2), /* 6 */
+	/*((0<<3)|3),*/	 /* 12 for ddr4 */
+	/*((1<<3)|1),*/  /* 13 B,C exchange for rkvdec */
+};
+
+/*
+ * for ddr4 if ddrconfig=7, upctl should set 7 and noc should
+ * set to 1 for more efficient.
+ * noc ddrconf, upctl addrmap
+ * 1  7
+ * 2  8
+ * 3  9
+ * 12 10
+ * 5  11
+ */
+u8 d4_rbc_2_d3_rbc[] = {
+	1, /* 7 */
+	2, /* 8 */
+	3, /* 9 */
+	12, /* 10 */
+	5, /* 11 */
+};
+
+/*
+ * row higher than cs should be disabled by set to 0xf
+ * rank addrmap calculate by real cap.
+ */
+u32 addrmap[][8] = {
+	/* map0 map1,   map2,       map3,       map4,      map5
+	 * map6,        map7,       map8
+	 * -------------------------------------------------------
+	 * bk2-0       col 5-2     col 9-6    col 11-10   row 11-0
+	 * row 15-12   row 17-16   bg1,0
+	 * -------------------------------------------------------
+	 * 4,3,2       5-2         9-6                    6
+	 *                         3,2
+	 */
+	{0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
+		0x05050505, 0x00000505, 0x3f3f}, /* 0 */
+	{0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x06060606, 0x3f3f}, /* 1 */
+	{0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x3f3f}, /* 2 */
+	{0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+		0x08080808, 0x00000f0f, 0x3f3f}, /* 3 */
+	{0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
+		0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
+	{0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000606, 0x3f3f}, /* 5 */
+	{0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f0f, 0x3f3f}, /* 6 */
+	{0x003f0808, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000606, 0x0600}, /* 7 */
+	{0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x0700}, /* 8 */
+	{0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+		0x08080808, 0x00000f0f, 0x0801}, /* 9 */
+	{0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x3f01}, /* 10 */
+	{0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000606, 0x3f00}, /* 11 */
+	/* when ddr4 12 map to 10, when ddr3 12 unused */
+	{0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x3f01}, /* 10 */
+	{0x00070706, 0x00000000, 0x1f010000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000606, 0x3f3f}, /* 13 */
+};
+
+#define PMUGRF_BASE_ADDR		0xFF010000
+#define CRU_BASE_ADDR			0xFF2B0000
+#define GRF_BASE_ADDR			0xFF140000
+#define DDRC_BASE_ADDR			0xFF600000
+#define DDR_PHY_BASE_ADDR		0xFF2A0000
+#define SERVER_MSCH0_BASE_ADDR		0xFF530000
+#define DDR_GRF_BASE_ADDR		0xff630000
+
+struct dram_info dram_info;
+
+struct px30_sdram_params sdram_configs[] = {
+#include	"sdram-px30-ddr3-detect-333.inc"
+};
+
+struct ddr_phy_skew skew = {
+#include	"sdram-px30-ddr_skew.inc"
+};
+
+static void rkclk_ddr_reset(struct dram_info *dram,
+			    u32 ctl_srstn, u32 ctl_psrstn,
+			    u32 phy_srstn, u32 phy_psrstn)
+{
+	writel(upctl2_srstn_req(ctl_srstn) | upctl2_psrstn_req(ctl_psrstn) |
+	       upctl2_asrstn_req(ctl_srstn),
+	       &dram->cru->softrst_con[1]);
+	writel(ddrphy_srstn_req(phy_srstn) | ddrphy_psrstn_req(phy_psrstn),
+	       &dram->cru->softrst_con[2]);
+}
+
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
+{
+	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
+	int delay = 1000;
+	u32 mhz = hz / MHz;
+
+	refdiv = 1;
+	if (mhz <= 300) {
+		postdiv1 = 4;
+		postdiv2 = 2;
+	} else if (mhz <= 400) {
+		postdiv1 = 6;
+		postdiv2 = 1;
+	} else if (mhz <= 600) {
+		postdiv1 = 4;
+		postdiv2 = 1;
+	} else if (mhz <= 800) {
+		postdiv1 = 3;
+		postdiv2 = 1;
+	} else if (mhz <= 1600) {
+		postdiv1 = 2;
+		postdiv2 = 1;
+	} else {
+		postdiv1 = 1;
+		postdiv2 = 1;
+	}
+	fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
+
+	writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
+
+	writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
+	writel(DSMPD(1) | POSTDIV2(postdiv2) | REFDIV(refdiv),
+	       &dram->cru->pll[1].con1);
+
+	while (delay > 0) {
+		udelay(1);
+		if (LOCK(readl(&dram->cru->pll[1].con1)))
+			break;
+		delay--;
+	}
+
+	writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
+}
+
+static void rkclk_configure_ddr(struct dram_info *dram,
+				struct px30_sdram_params *sdram_params)
+{
+	/* for inno ddr phy need 2*freq */
+	rkclk_set_dpll(dram,  sdram_params->base.ddr_freq * MHz * 2);
+}
+
+/* return ddrconfig value
+ *       (-1), find ddrconfig fail
+ *       other, the ddrconfig value
+ * only support cs0_row >= cs1_row
+ */
+static unsigned int calculate_ddrconfig(struct px30_sdram_params *sdram_params)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	u32 bw, die_bw, col, bank;
+	u32 i, tmp;
+	u32 ddrconf = -1;
+
+	bw = cap_info->bw;
+	die_bw = cap_info->dbw;
+	col = cap_info->col;
+	bank = cap_info->bk;
+
+	if (sdram_params->base.dramtype == DDR4) {
+		if (die_bw == 0)
+			ddrconf = 7 + bw;
+		else
+			ddrconf = 12 - bw;
+		ddrconf = d4_rbc_2_d3_rbc[ddrconf - 7];
+	} else {
+		tmp = ((bank - 2) << 3) | (col + bw - 10);
+		for (i = 0; i < 7; i++)
+			if ((ddr_cfg_2_rbc[i] & 0xf) == tmp) {
+				ddrconf = i;
+				break;
+			}
+		if (i > 6)
+			printascii("calculate ddrconfig error\n");
+	}
+
+	return ddrconf;
+}
+
+/*
+ * calculate controller dram address map, and setting to register.
+ * argument sdram_params->ch.ddrconf must be right value before
+ * call this function.
+ */
+static void set_ctl_address_map(struct dram_info *dram,
+				struct px30_sdram_params *sdram_params)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	void __iomem *pctl_base = dram->pctl;
+	u32 cs_pst, bg, max_row, ddrconf;
+	u32 i;
+
+	if (sdram_params->base.dramtype == DDR4)
+		/*
+		 * DDR4 8bit dram BG = 2(4bank groups),
+		 * 16bit dram BG = 1 (2 bank groups)
+		 */
+		bg = (cap_info->dbw == 0) ? 2 : 1;
+	else
+		bg = 0;
+
+	cs_pst = cap_info->bw + cap_info->col +
+		bg + cap_info->bk + cap_info->cs0_row;
+	if (cs_pst >= 32 || cap_info->rank == 1)
+		writel(0x1f, pctl_base + DDR_PCTL2_ADDRMAP0);
+	else
+		writel(cs_pst - 8, pctl_base + DDR_PCTL2_ADDRMAP0);
+
+	ddrconf = cap_info->ddrconfig;
+	if (sdram_params->base.dramtype == DDR4) {
+		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc); i++) {
+			if (d4_rbc_2_d3_rbc[i] == ddrconf) {
+				ddrconf = 7 + i;
+				break;
+			}
+		}
+	}
+
+	sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP1),
+			  &addrmap[ddrconf][0], 8 * 4);
+	max_row = cs_pst - 1 - 8 - (addrmap[ddrconf][5] & 0xf);
+
+	if (max_row < 12)
+		printascii("set addrmap fail\n");
+	/* need to disable row ahead of rank by set to 0xf */
+	for (i = 17; i > max_row; i--)
+		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
+			((i - 12) * 8 / 32) * 4,
+			0xf << ((i - 12) * 8 % 32),
+			0xf << ((i - 12) * 8 % 32));
+
+	if ((sdram_params->base.dramtype == LPDDR3 ||
+	     sdram_params->base.dramtype == LPDDR2) &&
+		 cap_info->row_3_4)
+		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
+	if (sdram_params->base.dramtype == DDR4 && cap_info->bw != 0x2)
+		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
+}
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+int read_mr(struct dram_info *dram, u32 rank, u32 mr_num)
+{
+	void __iomem *ddr_grf_base = dram->ddr_grf;
+
+	pctl_read_mr(dram->pctl, rank, mr_num);
+
+	return (readl(ddr_grf_base + DDR_GRF_STATUS(0)) & 0xff);
+}
+
+#define MIN(a, b)	(((a) > (b)) ? (b) : (a))
+#define MAX(a, b)	(((a) > (b)) ? (a) : (b))
+static u32 check_rd_gate(struct dram_info *dram)
+{
+	void __iomem *phy_base = dram->phy;
+
+	u32 max_val = 0;
+	u32 min_val = 0xff;
+	u32 gate[4];
+	u32 i, bw;
+
+	bw = (readl(PHY_REG(phy_base, 0x0)) >> 4) & 0xf;
+	switch (bw) {
+	case 0x1:
+		bw = 1;
+		break;
+	case 0x3:
+		bw = 2;
+		break;
+	case 0xf:
+	default:
+		bw = 4;
+		break;
+	}
+
+	for (i = 0; i < bw; i++) {
+		gate[i] = readl(PHY_REG(phy_base, 0xfb + i));
+		max_val = MAX(max_val, gate[i]);
+		min_val = MIN(min_val, gate[i]);
+	}
+
+	if (max_val > 0x80 || min_val < 0x20)
+		return -1;
+	else
+		return 0;
+}
+
+static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
+{
+	void __iomem *pctl_base = dram->pctl;
+	u32 dis_auto_zq = 0;
+	u32 pwrctl;
+	u32 ret;
+
+	/* disable auto low-power */
+	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+
+	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+	ret = phy_data_training(dram->phy, cs, dramtype);
+
+	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+	/* restore auto low-power */
+	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
+
+	return ret;
+}
+
+static void dram_set_bw(struct dram_info *dram, u32 bw)
+{
+	phy_dram_set_bw(dram->phy, bw);
+}
+
+static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
+{
+	writel(ddrconfig | (ddrconfig << 8), &dram->msch->deviceconf);
+	rk_clrsetreg(&dram->grf->soc_noc_con[1], 0x3 << 14, 0 << 14);
+}
+
+static void sdram_msch_config(struct msch_regs *msch,
+			      struct sdram_msch_timings *noc_timings,
+			      struct sdram_cap_info *cap_info,
+			      struct sdram_base_params *base)
+{
+	u64 cs_cap[2];
+
+	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, base->dramtype);
+	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, base->dramtype);
+	writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
+			(((cs_cap[0] >> 20) / 64) & 0xff),
+			&msch->devicesize);
+
+	writel(noc_timings->ddrtiminga0.d32,
+	       &msch->ddrtiminga0);
+	writel(noc_timings->ddrtimingb0.d32,
+	       &msch->ddrtimingb0);
+	writel(noc_timings->ddrtimingc0.d32,
+	       &msch->ddrtimingc0);
+	writel(noc_timings->devtodev0.d32,
+	       &msch->devtodev0);
+	writel(noc_timings->ddrmode.d32, &msch->ddrmode);
+	writel(noc_timings->ddr4timing.d32,
+	       &msch->ddr4timing);
+	writel(noc_timings->agingx0, &msch->agingx0);
+	writel(noc_timings->agingx0, &msch->aging0);
+	writel(noc_timings->agingx0, &msch->aging1);
+	writel(noc_timings->agingx0, &msch->aging2);
+	writel(noc_timings->agingx0, &msch->aging3);
+}
+
+static void dram_all_config(struct dram_info *dram,
+			    struct px30_sdram_params *sdram_params)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	u32 sys_reg2 = 0;
+	u32 sys_reg3 = 0;
+
+	set_ddrconfig(dram, cap_info->ddrconfig);
+	sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+			 &sys_reg3, 0);
+	writel(sys_reg2, &dram->pmugrf->os_reg[2]);
+	writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+	sdram_msch_config(dram->msch, &sdram_params->ch.noc_timings, cap_info,
+			  &sdram_params->base);
+}
+
+static void enable_low_power(struct dram_info *dram,
+			     struct px30_sdram_params *sdram_params)
+{
+	void __iomem *pctl_base = dram->pctl;
+	void __iomem *phy_base = dram->phy;
+	void __iomem *ddr_grf_base = dram->ddr_grf;
+	u32 grf_lp_con;
+
+	/*
+	 * bit0: grf_upctl_axi_cg_en = 1 enable upctl2 axi clk auto gating
+	 * bit1: grf_upctl_apb_cg_en = 1 ungated axi,core clk for apb access
+	 * bit2: grf_upctl_core_cg_en = 1 enable upctl2 core clk auto gating
+	 * bit3: grf_selfref_type2_en = 0 disable core clk gating when type2 sr
+	 * bit4: grf_upctl_syscreq_cg_en = 1
+	 *       ungating coreclk when c_sysreq assert
+	 * bit8-11: grf_auto_sr_dly = 6
+	 */
+	writel(0x1f1f0617, &dram->ddr_grf->ddr_grf_con[1]);
+
+	if (sdram_params->base.dramtype == DDR4)
+		grf_lp_con = (0x7 << 16) | (1 << 1);
+	else if (sdram_params->base.dramtype == DDR3)
+		grf_lp_con = (0x7 << 16) | (1 << 0);
+	else
+		grf_lp_con = (0x7 << 16) | (1 << 2);
+
+	/* en lpckdis_en */
+	grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
+	writel(grf_lp_con, ddr_grf_base + DDR_GRF_LP_CON);
+
+	/* off digit module clock when enter power down */
+	setbits_le32(PHY_REG(phy_base, 7), 1 << 7);
+
+	/* enable sr, pd */
+	if (PD_IDLE == 0)
+		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+	else
+		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+	if (SR_IDLE == 0)
+		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+	else
+		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
+}
+
+/*
+ * pre_init: 0: pre init for dram cap detect
+ * 1: detect correct cap(except cs1 row)info, than reinit
+ * 2: after reinit, we detect cs1_row, if cs1_row not equal
+ *    to cs0_row and cs is in middle on ddrconf map, we need
+ *    to reinit dram, than set the correct ddrconf.
+ */
+static int sdram_init_(struct dram_info *dram,
+		       struct px30_sdram_params *sdram_params, u32 pre_init)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	void __iomem *pctl_base = dram->pctl;
+
+	rkclk_ddr_reset(dram, 1, 1, 1, 1);
+	udelay(10);
+	/*
+	 * dereset ddr phy psrstn to config pll,
+	 * if using phy pll psrstn must be dereset
+	 * before config pll
+	 */
+	rkclk_ddr_reset(dram, 1, 1, 1, 0);
+	rkclk_configure_ddr(dram, sdram_params);
+
+	/* release phy srst to provide clk to ctrl */
+	rkclk_ddr_reset(dram, 1, 1, 0, 0);
+	udelay(10);
+	phy_soft_reset(dram->phy);
+	/* release ctrl presetn, and config ctl registers */
+	rkclk_ddr_reset(dram, 1, 0, 0, 0);
+	pctl_cfg(dram->pctl, &sdram_params->pctl_regs, SR_IDLE, PD_IDLE);
+	cap_info->ddrconfig = calculate_ddrconfig(sdram_params);
+	set_ctl_address_map(dram, sdram_params);
+	phy_cfg(dram->phy, &sdram_params->phy_regs, sdram_params->skew,
+		&sdram_params->base, cap_info->bw);
+
+	/* enable dfi_init_start to init phy after ctl srstn deassert */
+	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
+
+	rkclk_ddr_reset(dram, 0, 0, 0, 0);
+	/* wait for dfi_init_done and dram init complete */
+	while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
+		continue;
+
+	if (sdram_params->base.dramtype == LPDDR3)
+		pctl_write_mr(dram->pctl, 3, 11, 3, LPDDR3);
+
+	/* do ddr gate training */
+redo_cs0_training:
+	if (data_training(dram, 0, sdram_params->base.dramtype) != 0) {
+		if (pre_init != 0)
+			printascii("DTT cs0 error\n");
+		return -1;
+	}
+	if (check_rd_gate(dram)) {
+		printascii("re training cs0");
+		goto redo_cs0_training;
+	}
+
+	if (sdram_params->base.dramtype == LPDDR3) {
+		if ((read_mr(dram, 1, 8) & 0x3) != 0x3)
+			return -1;
+	} else if (sdram_params->base.dramtype == LPDDR2) {
+		if ((read_mr(dram, 1, 8) & 0x3) != 0x0)
+			return -1;
+	}
+	/* for px30: when 2cs, both 2 cs should be training */
+	if (pre_init != 0 && cap_info->rank == 2) {
+redo_cs1_training:
+		if (data_training(dram, 1, sdram_params->base.dramtype) != 0) {
+			printascii("DTT cs1 error\n");
+			return -1;
+		}
+		if (check_rd_gate(dram)) {
+			printascii("re training cs1");
+			goto redo_cs1_training;
+		}
+	}
+
+	if (sdram_params->base.dramtype == DDR4)
+		pctl_write_vrefdq(dram->pctl, 0x3, 5670,
+				  sdram_params->base.dramtype);
+
+	dram_all_config(dram, sdram_params);
+	enable_low_power(dram, sdram_params);
+
+	return 0;
+}
+
+static int dram_detect_cap(struct dram_info *dram,
+			   struct px30_sdram_params *sdram_params,
+			   unsigned char channel)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+
+	/*
+	 * for ddr3: ddrconf = 3
+	 * for ddr4: ddrconf = 12
+	 * for lpddr3: ddrconf = 3
+	 * default bw = 1
+	 */
+	u32 bk, bktmp;
+	u32 col, coltmp;
+	u32 rowtmp;
+	u32 cs;
+	u32 bw = 1;
+	u32 dram_type = sdram_params->base.dramtype;
+
+	if (dram_type != DDR4) {
+		/* detect col and bk for ddr3/lpddr3 */
+		coltmp = 12;
+		bktmp = 3;
+		if (dram_type == LPDDR2)
+			rowtmp = 15;
+		else
+			rowtmp = 16;
+
+		if (sdram_detect_col(cap_info, coltmp) != 0)
+			goto cap_err;
+		sdram_detect_bank(cap_info, coltmp, bktmp);
+		sdram_detect_dbw(cap_info, dram_type);
+	} else {
+		/* detect bg for ddr4 */
+		coltmp = 10;
+		bktmp = 4;
+		rowtmp = 17;
+
+		col = 10;
+		bk = 2;
+		cap_info->col = col;
+		cap_info->bk = bk;
+		sdram_detect_bg(cap_info, coltmp);
+	}
+
+	/* detect row */
+	if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
+		goto cap_err;
+
+	/* detect row_3_4 */
+	sdram_detect_row_3_4(cap_info, coltmp, bktmp);
+
+	/* bw and cs detect using data training */
+	if (data_training(dram, 1, dram_type) == 0)
+		cs = 1;
+	else
+		cs = 0;
+	cap_info->rank = cs + 1;
+
+	dram_set_bw(dram, 2);
+	if (data_training(dram, 0, dram_type) == 0)
+		bw = 2;
+	else
+		bw = 1;
+	cap_info->bw = bw;
+
+	cap_info->cs0_high16bit_row = cap_info->cs0_row;
+	if (cs) {
+		cap_info->cs1_row = cap_info->cs0_row;
+		cap_info->cs1_high16bit_row = cap_info->cs0_row;
+	} else {
+		cap_info->cs1_row = 0;
+		cap_info->cs1_high16bit_row = 0;
+	}
+
+	return 0;
+cap_err:
+	return -1;
+}
+
+/* return: 0 = success, other = fail */
+static int sdram_init_detect(struct dram_info *dram,
+			     struct px30_sdram_params *sdram_params)
+{
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	u32 ret;
+	u32 sys_reg = 0;
+	u32 sys_reg3 = 0;
+
+	if (sdram_init_(dram, sdram_params, 0) != 0)
+		return -1;
+
+	if (dram_detect_cap(dram, sdram_params, 0) != 0)
+		return -1;
+
+	/* modify bw, cs related timing */
+	pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+				   sdram_params->base.dramtype);
+	/* reinit sdram by real dram cap */
+	ret = sdram_init_(dram, sdram_params, 1);
+	if (ret != 0)
+		goto out;
+
+	/* redetect cs1 row */
+	sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
+	if (cap_info->cs1_row) {
+		sys_reg = readl(&dram->pmugrf->os_reg[2]);
+		sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
+		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+				    sys_reg, sys_reg3, 0);
+		writel(sys_reg, &dram->pmugrf->os_reg[2]);
+		writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+	}
+
+	ret = sdram_detect_high_row(cap_info);
+
+out:
+	return ret;
+}
+
+struct px30_sdram_params
+		*get_default_sdram_config(void)
+{
+	sdram_configs[0].skew = &skew;
+
+	return &sdram_configs[0];
+}
+
+/* return: 0 = success, other = fail */
+int sdram_init(void)
+{
+	struct px30_sdram_params *sdram_params;
+	int ret = 0;
+
+	dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
+	dram_info.pctl = (void *)DDRC_BASE_ADDR;
+	dram_info.grf = (void *)GRF_BASE_ADDR;
+	dram_info.cru = (void *)CRU_BASE_ADDR;
+	dram_info.msch = (void *)SERVER_MSCH0_BASE_ADDR;
+	dram_info.ddr_grf = (void *)DDR_GRF_BASE_ADDR;
+	dram_info.pmugrf = (void *)PMUGRF_BASE_ADDR;
+
+	sdram_params = get_default_sdram_config();
+	ret = sdram_init_detect(&dram_info, sdram_params);
+
+	if (ret)
+		goto error;
+
+	sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
+
+	printascii("out\n");
+	return ret;
+error:
+	return (-1);
+}
+#else
+
+static int px30_dmc_probe(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+	debug("%s: grf=%p\n", __func__, priv->pmugrf);
+	priv->info.base = CONFIG_SYS_SDRAM_BASE;
+	priv->info.size =
+		rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg[2]);
+
+	return 0;
+}
+
+static int px30_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	*info = priv->info;
+
+	return 0;
+}
+
+static struct ram_ops px30_dmc_ops = {
+	.get_info = px30_dmc_get_info,
+};
+
+static const struct udevice_id px30_dmc_ids[] = {
+	{ .compatible = "rockchip,px30-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_px30) = {
+	.name = "rockchip_px30_dmc",
+	.id = UCLASS_RAM,
+	.of_match = px30_dmc_ids,
+	.ops = &px30_dmc_ops,
+	.probe = px30_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+};
+#endif /* CONFIG_TPL_BUILD */
diff --git a/drivers/ram/rockchip/sdram_rk3128.c b/drivers/ram/rockchip/sdram_rk3128.c
index bfabc22a7d897e1cab9bf9930ee59a8eb0817e36..8486653c6fb19fefc52cb70ca0535b04f4d737e3 100644
--- a/drivers/ram/rockchip/sdram_rk3128.c
+++ b/drivers/ram/rockchip/sdram_rk3128.c
@@ -9,7 +9,7 @@
 #include <syscon.h>
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/grf_rk3128.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 
 struct dram_info {
 	struct ram_info info;
diff --git a/drivers/ram/rockchip/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c
index 00e52ec949e721f63ef580d5b658740dc2f310fa..d3e4316ef019b44ef3efafaa9023f037315b8144 100644
--- a/drivers/ram/rockchip/sdram_rk3188.c
+++ b/drivers/ram/rockchip/sdram_rk3188.c
@@ -21,7 +21,7 @@
 #include <asm/arch-rockchip/grf_rk3188.h>
 #include <asm/arch-rockchip/pmu_rk3188.h>
 #include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
 #include <linux/err.h>
 
 struct chan_info {
diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c
index 94893e17cf5c194d3a45cac5c09d21d627340150..223f048161e0ba00905a94f96cda114da7c3fe32 100644
--- a/drivers/ram/rockchip/sdram_rk322x.c
+++ b/drivers/ram/rockchip/sdram_rk322x.c
@@ -17,7 +17,7 @@
 #include <asm/arch-rockchip/hardware.h>
 #include <asm/arch-rockchip/sdram_rk322x.h>
 #include <asm/arch-rockchip/uart.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 #include <asm/types.h>
 #include <linux/err.h>
 
diff --git a/drivers/ram/rockchip/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c
index 57752540073fc720fc46e1ccf4a3805dd2ff7e1b..690751d0747eb3ea01174db1b3e5a153690bedbe 100644
--- a/drivers/ram/rockchip/sdram_rk3288.c
+++ b/drivers/ram/rockchip/sdram_rk3288.c
@@ -21,7 +21,7 @@
 #include <asm/arch-rockchip/grf_rk3288.h>
 #include <asm/arch-rockchip/pmu_rk3288.h>
 #include <asm/arch-rockchip/sdram.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3288.h>
 #include <linux/err.h>
 #include <power/regulator.h>
 #include <power/rk8xx_pmic.h>
diff --git a/drivers/ram/rockchip/sdram_rk3308.c b/drivers/ram/rockchip/sdram_rk3308.c
new file mode 100644
index 0000000000000000000000000000000000000000..310df79123c930f9f47c51235a006fe316ad2d75
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rk3308.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/arch/grf_rk3308.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/sdram.h>
+
+struct dram_info {
+	struct ram_info info;
+	struct rk3308_grf *grf;
+};
+
+static int rk3308_dmc_probe(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->info.base = CONFIG_SYS_SDRAM_BASE;
+	priv->info.size = rockchip_sdram_size((phys_addr_t)&priv->grf->os_reg2);
+
+	return 0;
+}
+
+static int rk3308_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	*info = priv->info;
+
+	return 0;
+}
+
+static struct ram_ops rk3308_dmc_ops = {
+	.get_info = rk3308_dmc_get_info,
+};
+
+static const struct udevice_id rk3308_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3308-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk3308) = {
+	.name = "rockchip_rk3308_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk3308_dmc_ids,
+	.ops = &rk3308_dmc_ops,
+	.probe = rk3308_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+};
diff --git a/drivers/ram/rockchip/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c
index e84c9be6a29443f176a33cc2238ba33b596f38d9..69521cef6992e28b125ad0a2e984d14fffbf16ce 100644
--- a/drivers/ram/rockchip/sdram_rk3328.c
+++ b/drivers/ram/rockchip/sdram_rk3328.c
@@ -14,17 +14,17 @@
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/cru_rk3328.h>
 #include <asm/arch-rockchip/grf_rk3328.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 #include <asm/arch-rockchip/sdram_rk3328.h>
 #include <asm/arch-rockchip/uart.h>
 
 struct dram_info {
 #ifdef CONFIG_TPL_BUILD
-	struct rk3328_ddr_pctl_regs *pctl;
-	struct rk3328_ddr_phy_regs *phy;
+	struct ddr_pctl_regs *pctl;
+	struct ddr_phy_regs *phy;
 	struct clk ddr_clk;
 	struct rk3328_cru *cru;
-	struct rk3328_msch_regs *msch;
+	struct msch_regs *msch;
 	struct rk3328_ddr_grf_regs *ddr_grf;
 #endif
 	struct ram_info info;
@@ -71,10 +71,11 @@ static void rkclk_ddr_reset(struct dram_info *dram,
 	writel(ddrctrl_asrstn_req(ctl_srstn), &dram->cru->softrst_con[9]);
 }
 
-static void rkclk_set_dpll(struct dram_info *dram, unsigned int mhz)
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
 {
 	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
 	int delay = 1000;
+	u32 mhz = hz / MHZ;
 
 	refdiv = 1;
 	if (mhz <= 300) {
@@ -122,52 +123,7 @@ static void rkclk_configure_ddr(struct dram_info *dram,
 	clrbits_le32(PHY_REG(phy_base, 0xef), 1 << 7);
 
 	/* for inno ddr phy need 2*freq */
-	rkclk_set_dpll(dram,  sdram_params->ddr_freq * 2);
-}
-
-static void phy_soft_reset(struct dram_info *dram)
-{
-	void __iomem *phy_base = dram->phy;
-
-	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
-	udelay(1);
-	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
-	udelay(5);
-	setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
-	udelay(1);
-}
-
-static int pctl_cfg(struct dram_info *dram,
-		    struct rk3328_sdram_params *sdram_params)
-{
-	u32 i;
-	void __iomem *pctl_base = dram->pctl;
-
-	for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
-		writel(sdram_params->pctl_regs.pctl[i][1],
-		       pctl_base + sdram_params->pctl_regs.pctl[i][0]);
-	}
-	clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
-			(0xff << 16) | 0x1f,
-			((SR_IDLE & 0xff) << 16) | (PD_IDLE & 0x1f));
-	/*
-	 * dfi_lp_en_pd=1,dfi_lp_wakeup_pd=2
-	 * hw_lp_idle_x32=1
-	 */
-	if (sdram_params->dramtype == LPDDR3) {
-		setbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0, 1);
-		clrsetbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0,
-				0xf << 4,
-				2 << 4);
-	}
-	clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
-			0xfff << 16,
-			1 << 16);
-	/* disable zqcs */
-	setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
-	setbits_le32(pctl_base + 0x2000 + DDR_PCTL2_ZQCTL0, 1u << 31);
-
-	return 0;
+	rkclk_set_dpll(dram,  sdram_params->base.ddr_freq * MHZ * 2);
 }
 
 /* return ddrconfig value
@@ -175,62 +131,39 @@ static int pctl_cfg(struct dram_info *dram,
  *       other, the ddrconfig value
  * only support cs0_row >= cs1_row
  */
-static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params)
+static u32 calculate_ddrconfig(struct rk3328_sdram_params *sdram_params)
 {
-	static const u16 ddr_cfg_2_rbc[] = {
-		/***************************
-		 * [5:4]  row(13+n)
-		 * [3]    cs(0:0 cs, 1:2 cs)
-		 * [2]  bank(0:0bank,1:8bank)
-		 * [1:0]    col(11+n)
-		 ****************************/
-		/* row,        cs,       bank,   col */
-		((3 << 4) | (0 << 3) | (1 << 2) | 0),
-		((3 << 4) | (0 << 3) | (1 << 2) | 1),
-		((2 << 4) | (0 << 3) | (1 << 2) | 2),
-		((3 << 4) | (0 << 3) | (1 << 2) | 2),
-		((2 << 4) | (0 << 3) | (1 << 2) | 3),
-		((3 << 4) | (1 << 3) | (1 << 2) | 0),
-		((3 << 4) | (1 << 3) | (1 << 2) | 1),
-		((2 << 4) | (1 << 3) | (1 << 2) | 2),
-		((3 << 4) | (0 << 3) | (0 << 2) | 1),
-		((2 << 4) | (0 << 3) | (1 << 2) | 1),
-	};
-
-	static const u16 ddr4_cfg_2_rbc[] = {
-		/***************************
-		 * [6]	cs 0:0cs 1:2 cs
-		 * [5:3]  row(13+n)
-		 * [2]  cs(0:0 cs, 1:2 cs)
-		 * [1]  bw    0: 16bit 1:32bit
-		 * [0]  diebw 0:8bit 1:16bit
-		 ***************************/
-		/*  cs,       row,        cs,       bw,   diebw */
-		((0 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 0),
-		((1 << 6) | (2 << 3) | (0 << 2) | (1 << 1) | 0),
-		((0 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 0),
-		((1 << 6) | (3 << 3) | (0 << 2) | (0 << 1) | 0),
-		((0 << 6) | (4 << 3) | (0 << 2) | (1 << 1) | 1),
-		((1 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 1),
-		((1 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 1),
-		((0 << 6) | (2 << 3) | (1 << 2) | (1 << 1) | 0),
-		((0 << 6) | (3 << 3) | (1 << 2) | (0 << 1) | 0),
-		((0 << 6) | (3 << 3) | (1 << 2) | (1 << 1) | 1),
-		((0 << 6) | (4 << 3) | (1 << 2) | (0 << 1) | 1),
-	};
-
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
 	u32 cs, bw, die_bw, col, row, bank;
+	u32 cs1_row;
 	u32 i, tmp;
 	u32 ddrconf = -1;
 
-	cs = sdram_ch.rank;
-	bw = sdram_ch.bw;
-	die_bw = sdram_ch.dbw;
-	col = sdram_ch.col;
-	row = sdram_ch.cs0_row;
-	bank = sdram_ch.bk;
+	cs = cap_info->rank;
+	bw = cap_info->bw;
+	die_bw = cap_info->dbw;
+	col = cap_info->col;
+	row = cap_info->cs0_row;
+	cs1_row = cap_info->cs1_row;
+	bank = cap_info->bk;
+
+	if (sdram_params->base.dramtype == DDR4) {
+		/* when DDR_TEST, CS always at MSB position for easy test */
+		if (cs == 2 && row == cs1_row) {
+			/* include 2cs cap both 2^n  or both (2^n - 2^(n-2)) */
+			tmp = ((row - 13) << 3) | (1 << 2) | (bw & 0x2) |
+			      die_bw;
+			for (i = 17; i < 21; i++) {
+				if (((tmp & 0x7) ==
+				     (ddr4_cfg_2_rbc[i - 10] & 0x7)) &&
+				    ((tmp & 0x3c) <=
+				     (ddr4_cfg_2_rbc[i - 10] & 0x3c))) {
+					ddrconf = i;
+					goto out;
+				}
+			}
+		}
 
-	if (sdram_params->dramtype == DDR4) {
 		tmp = ((cs - 1) << 6) | ((row - 13) << 3) | (bw & 0x2) | die_bw;
 		for (i = 10; i < 17; i++) {
 			if (((tmp & 0x7) == (ddr4_cfg_2_rbc[i - 10] & 0x7)) &&
@@ -246,6 +179,18 @@ static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params
 			goto out;
 		}
 
+		/* when DDR_TEST, CS always at MSB position for easy test */
+		if (cs == 2 && row == cs1_row) {
+			/* include 2cs cap both 2^n  or both (2^n - 2^(n-2)) */
+			for (i = 5; i < 8; i++) {
+				if ((bw + col - 11) == (ddr_cfg_2_rbc[i] &
+							0x3)) {
+					ddrconf = i;
+					goto out;
+				}
+			}
+		}
+
 		tmp = ((row - 13) << 4) | (1 << 2) | ((bw + col - 11) << 0);
 		for (i = 0; i < 5; i++)
 			if (((tmp & 0xf) == (ddr_cfg_2_rbc[i] & 0xf)) &&
@@ -257,23 +202,11 @@ static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params
 
 out:
 	if (ddrconf > 20)
-		printf("calculate_ddrconfig error\n");
+		printf("calculate ddrconfig error\n");
 
 	return ddrconf;
 }
 
-/* n: Unit bytes */
-static void copy_to_reg(u32 *dest, u32 *src, u32 n)
-{
-	int i;
-
-	for (i = 0; i < n / sizeof(u32); i++) {
-		writel(*src, dest);
-		src++;
-		dest++;
-	}
-}
-
 /*******
  * calculate controller dram address map, and setting to register.
  * argument sdram_ch.ddrconf must be right value before
@@ -282,273 +215,42 @@ static void copy_to_reg(u32 *dest, u32 *src, u32 n)
 static void set_ctl_address_map(struct dram_info *dram,
 				struct rk3328_sdram_params *sdram_params)
 {
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
 	void __iomem *pctl_base = dram->pctl;
 
-	copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
-		    &addrmap[sdram_ch.ddrconfig][0], 9 * 4);
-	if (sdram_params->dramtype == LPDDR3 && sdram_ch.row_3_4)
+	sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
+			  &addrmap[cap_info->ddrconfig][0], 9 * 4);
+	if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
-	if (sdram_params->dramtype == DDR4 && sdram_ch.bw == 0x1)
+	if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
 		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
 
-	if (sdram_ch.rank == 1)
+	if (cap_info->rank == 1)
 		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
 }
 
-static void phy_dll_bypass_set(struct dram_info *dram, u32 freq)
-{
-	u32 tmp;
-	void __iomem *phy_base = dram->phy;
-
-	setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
-	clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
-	setbits_le32(PHY_REG(phy_base, 0x26), 1 << 4);
-	clrbits_le32(PHY_REG(phy_base, 0x27), 1 << 3);
-	setbits_le32(PHY_REG(phy_base, 0x36), 1 << 4);
-	clrbits_le32(PHY_REG(phy_base, 0x37), 1 << 3);
-	setbits_le32(PHY_REG(phy_base, 0x46), 1 << 4);
-	clrbits_le32(PHY_REG(phy_base, 0x47), 1 << 3);
-	setbits_le32(PHY_REG(phy_base, 0x56), 1 << 4);
-	clrbits_le32(PHY_REG(phy_base, 0x57), 1 << 3);
-
-	if (freq <= 400)
-		/* DLL bypass */
-		setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
-	else
-		clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
-	if (freq <= 680)
-		tmp = 2;
-	else
-		tmp = 1;
-	writel(tmp, PHY_REG(phy_base, 0x28));
-	writel(tmp, PHY_REG(phy_base, 0x38));
-	writel(tmp, PHY_REG(phy_base, 0x48));
-	writel(tmp, PHY_REG(phy_base, 0x58));
-}
-
-static void set_ds_odt(struct dram_info *dram,
-		       struct rk3328_sdram_params *sdram_params)
-{
-	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
-	void __iomem *phy_base = dram->phy;
-
-	if (sdram_params->dramtype == DDR3) {
-		cmd_drv = PHY_DDR3_RON_RTT_34ohm;
-		clk_drv = PHY_DDR3_RON_RTT_45ohm;
-		dqs_drv = PHY_DDR3_RON_RTT_34ohm;
-		dqs_odt = PHY_DDR3_RON_RTT_225ohm;
-	} else {
-		cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
-		clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
-		dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
-		dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
-	}
-	/* DS */
-	writel(cmd_drv, PHY_REG(phy_base, 0x11));
-	clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
-	writel(clk_drv, PHY_REG(phy_base, 0x16));
-	writel(clk_drv, PHY_REG(phy_base, 0x18));
-	writel(dqs_drv, PHY_REG(phy_base, 0x20));
-	writel(dqs_drv, PHY_REG(phy_base, 0x2f));
-	writel(dqs_drv, PHY_REG(phy_base, 0x30));
-	writel(dqs_drv, PHY_REG(phy_base, 0x3f));
-	writel(dqs_drv, PHY_REG(phy_base, 0x40));
-	writel(dqs_drv, PHY_REG(phy_base, 0x4f));
-	writel(dqs_drv, PHY_REG(phy_base, 0x50));
-	writel(dqs_drv, PHY_REG(phy_base, 0x5f));
-	/* ODT */
-	writel(dqs_odt, PHY_REG(phy_base, 0x21));
-	writel(dqs_odt, PHY_REG(phy_base, 0x2e));
-	writel(dqs_odt, PHY_REG(phy_base, 0x31));
-	writel(dqs_odt, PHY_REG(phy_base, 0x3e));
-	writel(dqs_odt, PHY_REG(phy_base, 0x41));
-	writel(dqs_odt, PHY_REG(phy_base, 0x4e));
-	writel(dqs_odt, PHY_REG(phy_base, 0x51));
-	writel(dqs_odt, PHY_REG(phy_base, 0x5e));
-}
-
-static void phy_cfg(struct dram_info *dram,
-		    struct rk3328_sdram_params *sdram_params)
-{
-	u32 i;
-	void __iomem *phy_base = dram->phy;
-
-	phy_dll_bypass_set(dram, sdram_params->ddr_freq);
-	for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
-		writel(sdram_params->phy_regs.phy[i][1],
-		       phy_base + sdram_params->phy_regs.phy[i][0]);
-	}
-	if (sdram_ch.bw == 2) {
-		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
-	} else {
-		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
-		/* disable DQS2,DQS3 tx dll  for saving power */
-		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
-		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
-	}
-	set_ds_odt(dram, sdram_params);
-	/* deskew */
-	setbits_le32(PHY_REG(phy_base, 2), 8);
-	copy_to_reg(PHY_REG(phy_base, 0xb0),
-		    &sdram_params->skew.a0_a1_skew[0], 15 * 4);
-	copy_to_reg(PHY_REG(phy_base, 0x70),
-		    &sdram_params->skew.cs0_dm0_skew[0], 44 * 4);
-	copy_to_reg(PHY_REG(phy_base, 0xc0),
-		    &sdram_params->skew.cs1_dm0_skew[0], 44 * 4);
-}
-
-static int update_refresh_reg(struct dram_info *dram)
-{
-	void __iomem *pctl_base = dram->pctl;
-	u32 ret;
-
-	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
-	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
-
-	return 0;
-}
-
 static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
-{
-	u32 ret;
-	u32 dis_auto_zq = 0;
-	void __iomem *pctl_base = dram->pctl;
-	void __iomem *phy_base = dram->phy;
-
-	/* disable zqcs */
-	if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
-		(1ul << 31))) {
-		dis_auto_zq = 1;
-		setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
-	}
-	/* disable auto refresh */
-	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
-	update_refresh_reg(dram);
-
-	if (dramtype == DDR4) {
-		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
-		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
-		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
-		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
-	}
-	/* choose training cs */
-	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
-	/* enable gate training */
-	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
-	udelay(50);
-	ret = readl(PHY_REG(phy_base, 0xff));
-	/* disable gate training */
-	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
-	/* restore zqcs */
-	if (dis_auto_zq)
-		clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
-	/* restore auto refresh */
-	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
-	update_refresh_reg(dram);
-
-	if (dramtype == DDR4) {
-		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
-		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
-		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
-		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
-	}
-
-	if (ret & 0x10) {
-		ret = -1;
-	} else {
-		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
-		ret = (ret == 0) ? 0 : -1;
-	}
-	return ret;
-}
-
-/* rank = 1: cs0
- * rank = 2: cs1
- * rank = 3: cs0 & cs1
- * note: be careful of keep mr original val
- */
-static int write_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 arg,
-		    u32 dramtype)
 {
 	void __iomem *pctl_base = dram->pctl;
-
-	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
-		continue;
-	if (dramtype == DDR3 || dramtype == DDR4) {
-		writel((mr_num << 12) | (rank << 4) | (0 << 0),
-		       pctl_base + DDR_PCTL2_MRCTRL0);
-		writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
-	} else {
-		writel((rank << 4) | (0 << 0),
-		       pctl_base + DDR_PCTL2_MRCTRL0);
-		writel((mr_num << 8) | (arg & 0xff),
-		       pctl_base + DDR_PCTL2_MRCTRL1);
-	}
-
-	setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
-	while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
-		continue;
-	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
-		continue;
-
-	return 0;
-}
-
-/*
- * rank : 1:cs0, 2:cs1, 3:cs0&cs1
- * vrefrate: 4500: 45%,
- */
-static int write_vrefdq(struct dram_info *dram, u32 rank, u32 vrefrate,
-			u32 dramtype)
-{
-	u32 tccd_l, value;
 	u32 dis_auto_zq = 0;
-	void __iomem *pctl_base = dram->pctl;
+	u32 pwrctl;
+	u32 ret;
 
-	if (dramtype != DDR4 || vrefrate < 4500 || vrefrate > 9200)
-		return -1;
+	/* disable auto low-power */
+	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
 
-	tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
-	tccd_l = (tccd_l - 4) << 10;
+	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
 
-	if (vrefrate > 7500) {
-		/* range 1 */
-		value = ((vrefrate - 6000) / 65) | tccd_l;
-	} else {
-		/* range 2 */
-		value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
-	}
+	ret = phy_data_training(dram->phy, cs, dramtype);
 
-	/* disable zqcs */
-	if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
-		(1ul << 31))) {
-		dis_auto_zq = 1;
-		setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
-	}
-	/* disable auto refresh */
-	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
-	update_refresh_reg(dram);
-
-	/* enable vrefdq calibratin */
-	write_mr(dram, rank, 6, value | (1 << 7), dramtype);
-	udelay(1);/* tvrefdqe */
-	/* write vrefdq value */
-	write_mr(dram, rank, 6, value | (1 << 7), dramtype);
-	udelay(1);/* tvref_time */
-	write_mr(dram, rank, 6, value | (0 << 7), dramtype);
-	udelay(1);/* tvrefdqx */
-
-	/* restore zqcs */
-	if (dis_auto_zq)
-		clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
-	/* restore auto refresh */
-	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
-	update_refresh_reg(dram);
+	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
 
-	return 0;
-}
+	/* restore auto low-power */
+	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
 
-#define _MAX_(x, y) ((x) > (y) ? (x) : (y))
+	return ret;
+}
 
 static void rx_deskew_switch_adjust(struct dram_info *dram)
 {
@@ -557,7 +259,7 @@ static void rx_deskew_switch_adjust(struct dram_info *dram)
 	void __iomem *phy_base = dram->phy;
 
 	for (i = 0; i < 4; i++)
-		gate_val = _MAX_(readl(PHY_REG(phy_base, 0xfb + i)), gate_val);
+		gate_val = MAX(readl(PHY_REG(phy_base, 0xfb + i)), gate_val);
 
 	deskew_val = (gate_val >> 3) + 1;
 	deskew_val = (deskew_val > 0x1f) ? 0x1f : deskew_val;
@@ -566,8 +268,6 @@ static void rx_deskew_switch_adjust(struct dram_info *dram)
 			(deskew_val & 0x1c) << 2);
 }
 
-#undef _MAX_
-
 static void tx_deskew_switch_adjust(struct dram_info *dram)
 {
 	void __iomem *phy_base = dram->phy;
@@ -580,40 +280,39 @@ static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
 	writel(ddrconfig, &dram->msch->ddrconf);
 }
 
+static void sdram_msch_config(struct msch_regs *msch,
+			      struct sdram_msch_timings *noc_timings)
+{
+	writel(noc_timings->ddrtiming.d32, &msch->ddrtiming);
+
+	writel(noc_timings->ddrmode.d32, &msch->ddrmode);
+	writel(noc_timings->readlatency, &msch->readlatency);
+
+	writel(noc_timings->activate.d32, &msch->activate);
+	writel(noc_timings->devtodev.d32, &msch->devtodev);
+	writel(noc_timings->ddr4timing.d32, &msch->ddr4_timing);
+	writel(noc_timings->agingx0, &msch->aging0);
+	writel(noc_timings->agingx0, &msch->aging1);
+	writel(noc_timings->agingx0, &msch->aging2);
+	writel(noc_timings->agingx0, &msch->aging3);
+	writel(noc_timings->agingx0, &msch->aging4);
+	writel(noc_timings->agingx0, &msch->aging5);
+}
+
 static void dram_all_config(struct dram_info *dram,
 			    struct rk3328_sdram_params *sdram_params)
 {
-	u32 sys_reg = 0, tmp = 0;
-
-	set_ddrconfig(dram, sdram_ch.ddrconfig);
-
-	sys_reg |= SYS_REG_ENC_DDRTYPE(sdram_params->dramtype);
-	sys_reg |= SYS_REG_ENC_ROW_3_4(sdram_ch.row_3_4, 0);
-	sys_reg |= SYS_REG_ENC_RANK(sdram_ch.rank, 0);
-	sys_reg |= SYS_REG_ENC_COL(sdram_ch.col, 0);
-	sys_reg |= SYS_REG_ENC_BK(sdram_ch.bk, 0);
-	SYS_REG_ENC_CS0_ROW(sdram_ch.cs0_row, sys_reg, tmp, 0);
-	if (sdram_ch.cs1_row)
-		SYS_REG_ENC_CS1_ROW(sdram_ch.cs1_row, sys_reg, tmp, 0);
-	sys_reg |= SYS_REG_ENC_BW(sdram_ch.bw, 0);
-	sys_reg |= SYS_REG_ENC_DBW(sdram_ch.dbw, 0);
-
-	writel(sys_reg, &dram->grf->os_reg[2]);
-
-	writel(sdram_ch.noc_timings.ddrtiming.d32, &dram->msch->ddrtiming);
-
-	writel(sdram_ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
-	writel(sdram_ch.noc_timings.readlatency, &dram->msch->readlatency);
-
-	writel(sdram_ch.noc_timings.activate.d32, &dram->msch->activate);
-	writel(sdram_ch.noc_timings.devtodev.d32, &dram->msch->devtodev);
-	writel(sdram_ch.noc_timings.ddr4timing.d32, &dram->msch->ddr4_timing);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging0);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging1);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging2);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging3);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging4);
-	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging5);
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+	u32 sys_reg2 = 0;
+	u32 sys_reg3 = 0;
+
+	set_ddrconfig(dram, cap_info->ddrconfig);
+	sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+			 &sys_reg3, 0);
+	writel(sys_reg2, &dram->grf->os_reg[2]);
+	writel(sys_reg3, &dram->grf->os_reg[3]);
+
+	sdram_msch_config(dram->msch, &sdram_ch.noc_timings);
 }
 
 static void enable_low_power(struct dram_info *dram,
@@ -641,6 +340,7 @@ static void enable_low_power(struct dram_info *dram,
 static int sdram_init(struct dram_info *dram,
 		      struct rk3328_sdram_params *sdram_params, u32 pre_init)
 {
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
 	void __iomem *pctl_base = dram->pctl;
 
 	rkclk_ddr_reset(dram, 1, 1, 1, 1);
@@ -652,30 +352,18 @@ static int sdram_init(struct dram_info *dram,
 	 */
 	rkclk_ddr_reset(dram, 1, 1, 1, 0);
 	rkclk_configure_ddr(dram, sdram_params);
-	if (pre_init == 0) {
-		switch (sdram_params->dramtype) {
-		case DDR3:
-			printf("DDR3\n");
-			break;
-		case DDR4:
-			printf("DDR4\n");
-			break;
-		case LPDDR3:
-		default:
-			printf("LPDDR3\n");
-			break;
-		}
-	}
+
 	/* release phy srst to provide clk to ctrl */
 	rkclk_ddr_reset(dram, 1, 1, 0, 0);
 	udelay(10);
-	phy_soft_reset(dram);
+	phy_soft_reset(dram->phy);
 	/* release ctrl presetn, and config ctl registers */
 	rkclk_ddr_reset(dram, 1, 0, 0, 0);
-	pctl_cfg(dram, sdram_params);
-	sdram_ch.ddrconfig = calculate_ddrconfig(sdram_params);
+	pctl_cfg(dram->pctl, &sdram_params->pctl_regs, SR_IDLE, PD_IDLE);
+	cap_info->ddrconfig = calculate_ddrconfig(sdram_params);
 	set_ctl_address_map(dram, sdram_params);
-	phy_cfg(dram, sdram_params);
+	phy_cfg(dram->phy, &sdram_params->phy_regs, &sdram_params->skew,
+		&sdram_params->base, cap_info->bw);
 
 	/* enable dfi_init_start to init phy after ctl srstn deassert */
 	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
@@ -685,13 +373,18 @@ static int sdram_init(struct dram_info *dram,
 		continue;
 
 	/* do ddr gate training */
-	if (data_training(dram, 0, sdram_params->dramtype) != 0) {
+	if (data_training(dram, 0, sdram_params->base.dramtype) != 0) {
+		printf("data training error\n");
+		return -1;
+	}
+	if (data_training(dram, 1, sdram_params->base.dramtype) != 0) {
 		printf("data training error\n");
 		return -1;
 	}
 
-	if (sdram_params->dramtype == DDR4)
-		write_vrefdq(dram, 0x3, 5670, sdram_params->dramtype);
+	if (sdram_params->base.dramtype == DDR4)
+		pctl_write_vrefdq(dram->pctl, 0x3, 5670,
+				  sdram_params->base.dramtype);
 
 	if (pre_init == 0) {
 		rx_deskew_switch_adjust(dram);
@@ -708,7 +401,7 @@ static u64 dram_detect_cap(struct dram_info *dram,
 			   struct rk3328_sdram_params *sdram_params,
 			   unsigned char channel)
 {
-	void __iomem *pctl_base = dram->pctl;
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
 
 	/*
 	 * for ddr3: ddrconf = 3
@@ -718,14 +411,10 @@ static u64 dram_detect_cap(struct dram_info *dram,
 	 */
 	u32 bk, bktmp;
 	u32 col, coltmp;
-	u32 row, rowtmp, row_3_4;
-	void __iomem *test_addr, *test_addr1;
-	u32 dbw;
+	u32 rowtmp;
 	u32 cs;
 	u32 bw = 1;
-	u64 cap = 0;
-	u32 dram_type = sdram_params->dramtype;
-	u32 pwrctl;
+	u32 dram_type = sdram_params->base.dramtype;
 
 	if (dram_type != DDR4) {
 		/* detect col and bk for ddr3/lpddr3 */
@@ -733,33 +422,10 @@ static u64 dram_detect_cap(struct dram_info *dram,
 		bktmp = 3;
 		rowtmp = 16;
 
-		for (col = coltmp; col >= 9; col -= 1) {
-			writel(0, SDRAM_ADDR);
-			test_addr = (void __iomem *)(SDRAM_ADDR +
-					(1ul << (col + bw - 1ul)));
-			writel(PATTERN, test_addr);
-			if ((readl(test_addr) == PATTERN) &&
-			    (readl(SDRAM_ADDR) == 0))
-				break;
-		}
-		if (col == 8) {
-			printf("col error\n");
+		if (sdram_detect_col(cap_info, coltmp) != 0)
 			goto cap_err;
-		}
-
-		test_addr = (void __iomem *)(SDRAM_ADDR +
-				(1ul << (coltmp + bktmp + bw - 1ul)));
-		writel(0, SDRAM_ADDR);
-		writel(PATTERN, test_addr);
-		if ((readl(test_addr) == PATTERN) &&
-		    (readl(SDRAM_ADDR) == 0))
-			bk = 3;
-		else
-			bk = 2;
-		if (dram_type == LPDDR3)
-			dbw = 2;
-		else
-			dbw = 1;
+		sdram_detect_bank(cap_info, coltmp, bktmp);
+		sdram_detect_dbw(cap_info, dram_type);
 	} else {
 		/* detect bg for ddr4 */
 		coltmp = 10;
@@ -768,178 +434,49 @@ static u64 dram_detect_cap(struct dram_info *dram,
 
 		col = 10;
 		bk = 2;
-		test_addr = (void __iomem *)(SDRAM_ADDR +
-				(1ul << (coltmp + bw + 1ul)));
-		writel(0, SDRAM_ADDR);
-		writel(PATTERN, test_addr);
-		if ((readl(test_addr) == PATTERN) &&
-		    (readl(SDRAM_ADDR) == 0))
-			dbw = 0;
-		else
-			dbw = 1;
+		cap_info->col = col;
+		cap_info->bk = bk;
+		sdram_detect_bg(cap_info, coltmp);
 	}
+
 	/* detect row */
-	for (row = rowtmp; row > 12; row--) {
-		writel(0, SDRAM_ADDR);
-		test_addr = (void __iomem *)(SDRAM_ADDR +
-				(1ul << (row + bktmp + coltmp + bw - 1ul)));
-		writel(PATTERN, test_addr);
-		if ((readl(test_addr) == PATTERN) &&
-		    (readl(SDRAM_ADDR) == 0))
-			break;
-	}
-	if (row == 12) {
-		printf("row error");
+	if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
 		goto cap_err;
-	}
-	/* detect row_3_4 */
-	test_addr = SDRAM_ADDR;
-	test_addr1 = (void __iomem *)(SDRAM_ADDR +
-			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
-
-	writel(0, test_addr);
-	writel(PATTERN, test_addr1);
-	if ((readl(test_addr) == 0) &&
-	    (readl(test_addr1) == PATTERN))
-		row_3_4 = 0;
-	else
-		row_3_4 = 1;
 
-	/* disable auto low-power */
-	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
-	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+	/* detect row_3_4 */
+	sdram_detect_row_3_4(cap_info, coltmp, bktmp);
 
-	/* bw and cs detect using phy read gate training */
+	/* bw and cs detect using data training */
 	if (data_training(dram, 1, dram_type) == 0)
 		cs = 1;
 	else
 		cs = 0;
+	cap_info->rank = cs + 1;
 
 	bw = 2;
+	cap_info->bw = bw;
 
-	/* restore auto low-power */
-	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
-
-	sdram_ch.rank = cs + 1;
-	sdram_ch.col = col;
-	sdram_ch.bk = bk;
-	sdram_ch.dbw = dbw;
-	sdram_ch.bw = bw;
-	sdram_ch.cs0_row = row;
-	if (cs)
-		sdram_ch.cs1_row = row;
-	else
-		sdram_ch.cs1_row = 0;
-	sdram_ch.row_3_4 = row_3_4;
-
-	if (dram_type == DDR4)
-		cap = 1llu << (cs + row + bk + col + ((dbw == 0) ? 2 : 1) + bw);
-	else
-		cap = 1llu << (cs + row + bk + col + bw);
-
-	return cap;
-
-cap_err:
-	return 0;
-}
-
-static u32 remodify_sdram_params(struct rk3328_sdram_params *sdram_params)
-{
-	u32 tmp = 0, tmp_adr = 0, i;
-
-	for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
-		if (sdram_params->pctl_regs.pctl[i][0] == 0) {
-			tmp = sdram_params->pctl_regs.pctl[i][1];/* MSTR */
-			tmp_adr = i;
-		}
-	}
-
-	tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
-
-	switch (sdram_ch.dbw) {
-	case 2:
-		tmp |= (3ul << 30);
-		break;
-	case 1:
-		tmp |= (2ul << 30);
-		break;
-	case 0:
-	default:
-		tmp |= (1ul << 30);
-		break;
+	cap_info->cs0_high16bit_row = cap_info->cs0_row;
+	if (cs) {
+		cap_info->cs1_row = cap_info->cs0_row;
+		cap_info->cs1_high16bit_row = cap_info->cs0_row;
+	} else {
+		cap_info->cs1_row = 0;
+		cap_info->cs1_high16bit_row = 0;
 	}
 
-	if (sdram_ch.rank == 2)
-		tmp |= 3 << 24;
-	else
-		tmp |= 1 << 24;
-
-	tmp |= (2 - sdram_ch.bw) << 12;
-
-	sdram_params->pctl_regs.pctl[tmp_adr][1] = tmp;
-
-	if (sdram_ch.bw == 2)
-		sdram_ch.noc_timings.ddrtiming.b.bwratio = 0;
-	else
-		sdram_ch.noc_timings.ddrtiming.b.bwratio = 1;
-
 	return 0;
-}
-
-static int dram_detect_cs1_row(struct rk3328_sdram_params *sdram_params,
-			       unsigned char channel)
-{
-	u32 ret = 0;
-	u32 cs1_bit;
-	void __iomem *test_addr, *cs1_addr;
-	u32 row, bktmp, coltmp, bw;
-	u32 ddrconf = sdram_ch.ddrconfig;
-
-	if (sdram_ch.rank == 2) {
-		cs1_bit = addrmap[ddrconf][0] + 8;
-
-		if (cs1_bit > 31)
-			goto out;
-
-		cs1_addr = (void __iomem *)(1ul << cs1_bit);
-		if (cs1_bit < 20)
-			cs1_bit = 1;
-		else
-			cs1_bit = 0;
-
-		if (sdram_params->dramtype == DDR4) {
-			if (sdram_ch.dbw == 0)
-				bktmp = sdram_ch.bk + 2;
-			else
-				bktmp = sdram_ch.bk + 1;
-		} else {
-			bktmp = sdram_ch.bk;
-		}
-		bw = sdram_ch.bw;
-		coltmp = sdram_ch.col;
-
-		/* detect cs1 row */
-		for (row = sdram_ch.cs0_row; row > 12; row--) {
-			test_addr = (void __iomem *)(SDRAM_ADDR + cs1_addr +
-					(1ul << (row + cs1_bit + bktmp +
-					 coltmp + bw - 1ul)));
-			writel(0, SDRAM_ADDR + cs1_addr);
-			writel(PATTERN, test_addr);
-			if ((readl(test_addr) == PATTERN) &&
-			    (readl(SDRAM_ADDR + cs1_addr) == 0)) {
-				ret = row;
-				break;
-			}
-		}
-	}
-
-out:
-	return ret;
+cap_err:
+	return -1;
 }
 
 static int sdram_init_detect(struct dram_info *dram,
 			     struct rk3328_sdram_params *sdram_params)
 {
+	u32 sys_reg = 0;
+	u32 sys_reg3 = 0;
+	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+
 	debug("Starting SDRAM initialization...\n");
 
 	memcpy(&sdram_ch, &sdram_params->ch,
@@ -949,13 +486,29 @@ static int sdram_init_detect(struct dram_info *dram,
 	dram_detect_cap(dram, sdram_params, 0);
 
 	/* modify bw, cs related timing */
-	remodify_sdram_params(sdram_params);
+	pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+				   sdram_params->base.dramtype);
+
+	if (cap_info->bw == 2)
+		sdram_ch.noc_timings.ddrtiming.b.bwratio = 0;
+	else
+		sdram_ch.noc_timings.ddrtiming.b.bwratio = 1;
+
 	/* reinit sdram by real dram cap */
 	sdram_init(dram, sdram_params, 0);
 
 	/* redetect cs1 row */
-	sdram_ch.cs1_row =
-		dram_detect_cs1_row(sdram_params, 0);
+	sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
+	if (cap_info->cs1_row) {
+		sys_reg = readl(&dram->grf->os_reg[2]);
+		sys_reg3 = readl(&dram->grf->os_reg[3]);
+		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+				    sys_reg, sys_reg3, 0);
+		writel(sys_reg, &dram->grf->os_reg[2]);
+		writel(sys_reg3, &dram->grf->os_reg[3]);
+	}
+
+	sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
 
 	return 0;
 }
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index ed70137ce7a461e5798e8d43d0de5e7f4ea6b87c..7b2bba03fe06ec8869c280fb28e000eaf58cd602 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -18,7 +18,7 @@
 #include <asm/arch-rockchip/grf_rk3399.h>
 #include <asm/arch-rockchip/pmu_rk3399.h>
 #include <asm/arch-rockchip/hardware.h>
-#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram.h>
 #include <asm/arch-rockchip/sdram_rk3399.h>
 #include <linux/err.h>
 #include <time.h>
@@ -44,6 +44,11 @@
 #define CS0_MR22_VAL		0
 #define CS1_MR22_VAL		3
 
+/* LPDDR3 DRAM DS */
+#define LPDDR3_DS_34		0x1
+#define LPDDR3_DS_40		0x2
+#define LPDDR3_DS_48		0x3
+
 #define CRU_SFTRST_DDR_CTRL(ch, n)	((0x1 << (8 + 16 + (ch) * 4)) | \
 					((n) << (8 + (ch) * 4)))
 #define CRU_SFTRST_DDR_PHY(ch, n)	((0x1 << (9 + 16 + (ch) * 4)) | \
@@ -52,7 +57,7 @@ struct chan_info {
 	struct rk3399_ddr_pctl_regs *pctl;
 	struct rk3399_ddr_pi_regs *pi;
 	struct rk3399_ddr_publ_regs *publ;
-	struct rk3399_msch_regs *msch;
+	struct msch_regs *msch;
 };
 
 struct dram_info {
@@ -74,10 +79,15 @@ struct dram_info {
 };
 
 struct sdram_rk3399_ops {
-	int (*data_training)(struct dram_info *dram, u32 channel, u8 rank,
-			     struct rk3399_sdram_params *sdram);
-	int (*set_rate)(struct dram_info *dram,
-			struct rk3399_sdram_params *params);
+	int (*data_training_first)(struct dram_info *dram, u32 channel, u8 rank,
+				   struct rk3399_sdram_params *sdram);
+	int (*set_rate_index)(struct dram_info *dram,
+			      struct rk3399_sdram_params *params);
+	void (*modify_param)(const struct chan_info *chan,
+			     struct rk3399_sdram_params *params);
+	struct rk3399_sdram_params *
+		(*get_phy_index_params)(u32 phy_fn,
+					struct rk3399_sdram_params *params);
 };
 
 #if defined(CONFIG_TPL_BUILD) || \
@@ -144,38 +154,21 @@ struct io_setting {
 		32,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
 	},
 	{
-		800 * MHz,
+		933 * MHz,
 		0,
 		/* dram side */
 		1,	/* dq_odt; */
 		0,	/* ca_odt; */
-		1,	/* pdds; */
+		3,	/* pdds; */
 		0x72,	/* dq_vref; */
 		0x72,	/* ca_vref; */
 		/* phy side */
-		PHY_DRV_ODT_40,	/* rd_odt; */
-		PHY_DRV_ODT_48,	/* wr_dq_drv; */
+		PHY_DRV_ODT_80,	/* rd_odt; */
+		PHY_DRV_ODT_40,	/* wr_dq_drv; */
 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
 		1,	/* rd_odt_en; */
-		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
-	},
-	{
-		933 * MHz,
-		0,
-		/* dram side */
-		3,	/* dq_odt; */
-		0,	/* ca_odt; */
-		6,	/* pdds; */
-		0x59,	/* dq_vref; 32% */
-		0x72,	/* ca_vref; */
-		/* phy side */
-		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
-		PHY_DRV_ODT_48,	/* wr_dq_drv; */
-		PHY_DRV_ODT_40,	/* wr_ca_drv; */
-		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
-		0,	/* rd_odt_en; */
-		32,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+		20,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
 	},
 	{
 		1066 * MHz,
@@ -183,24 +176,19 @@ struct io_setting {
 		/* dram side */
 		6,	/* dq_odt; */
 		0,	/* ca_odt; */
-		1,	/* pdds; */
+		3,	/* pdds; */
 		0x10,	/* dq_vref; */
 		0x72,	/* ca_vref; */
 		/* phy side */
-		PHY_DRV_ODT_40,	/* rd_odt; */
+		PHY_DRV_ODT_80,	/* rd_odt; */
 		PHY_DRV_ODT_60,	/* wr_dq_drv; */
 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
 		1,	/* rd_odt_en; */
-		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
+		20,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
 	},
 };
 
-/**
- * phy = 0, PHY boot freq
- * phy = 1, PHY index 0
- * phy = 2, PHY index 1
- */
 static struct io_setting *
 lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
 {
@@ -223,32 +211,21 @@ lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
 	return io;
 }
 
-static void *get_denali_phy(const struct chan_info *chan,
-			    struct rk3399_sdram_params *params, bool reg)
-{
-	return reg ? &chan->publ->denali_phy : &params->phy_regs.denali_phy;
-}
-
 static void *get_denali_ctl(const struct chan_info *chan,
 			    struct rk3399_sdram_params *params, bool reg)
 {
 	return reg ? &chan->pctl->denali_ctl : &params->pctl_regs.denali_ctl;
 }
 
-static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
+static void *get_denali_phy(const struct chan_info *chan,
+			    struct rk3399_sdram_params *params, bool reg)
 {
-	return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;
+	return reg ? &chan->publ->denali_phy : &params->phy_regs.denali_phy;
 }
 
-static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
 {
-	int i;
-
-	for (i = 0; i < n / sizeof(u32); i++) {
-		writel(*src, dest);
-		src++;
-		dest++;
-	}
+	return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc1_con0;
 }
 
 static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl,
@@ -319,7 +296,8 @@ static void set_memory_map(const struct chan_info *chan, u32 channel,
 	if (sdram_ch->cap_info.ddrconfig < 2 ||
 	    sdram_ch->cap_info.ddrconfig == 4)
 		row = 16;
-	else if (sdram_ch->cap_info.ddrconfig == 3)
+	else if (sdram_ch->cap_info.ddrconfig == 3 ||
+		 sdram_ch->cap_info.ddrconfig == 5)
 		row = 14;
 	else
 		row = 15;
@@ -344,7 +322,7 @@ static void set_memory_map(const struct chan_info *chan, u32 channel,
 			((3 - sdram_ch->cap_info.bk) << 16) |
 			((16 - row) << 24));
 
-	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+	if (params->base.dramtype == LPDDR4) {
 		if (cs_map == 1)
 			cs_map = 0x5;
 		else if (cs_map == 2)
@@ -363,11 +341,12 @@ static int phy_io_config(const struct chan_info *chan,
 			 const struct rk3399_sdram_params *params, u32 mr5)
 {
 	u32 *denali_phy = chan->publ->denali_phy;
+	u32 *denali_ctl = chan->pctl->denali_ctl;
 	u32 vref_mode_dq, vref_value_dq, vref_mode_ac, vref_value_ac;
 	u32 mode_sel;
-	u32 reg_value;
-	u32 drv_value, odt_value;
 	u32 speed;
+	u32 reg_value;
+	u32 ds_value, odt_value;
 
 	/* vref setting & mode setting */
 	if (params->base.dramtype == LPDDR4) {
@@ -393,12 +372,12 @@ static int phy_io_config(const struct chan_info *chan,
 	} else if (params->base.dramtype == LPDDR3) {
 		if (params->base.odt == 1) {
 			vref_mode_dq = 0x5;  /* LPDDR3 ODT */
-			drv_value = (readl(&denali_phy[6]) >> 12) & 0xf;
+			ds_value = readl(&denali_ctl[138]) & 0xf;
 			odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
-			if (drv_value == PHY_DRV_ODT_48) {
+			if (ds_value == LPDDR3_DS_48) {
 				switch (odt_value) {
 				case PHY_DRV_ODT_240:
-					vref_value_dq = 0x16;
+					vref_value_dq = 0x1B;
 					break;
 				case PHY_DRV_ODT_120:
 					vref_value_dq = 0x26;
@@ -410,7 +389,7 @@ static int phy_io_config(const struct chan_info *chan,
 					debug("Invalid ODT value.\n");
 					return -EINVAL;
 				}
-			} else if (drv_value == PHY_DRV_ODT_40) {
+			} else if (ds_value == LPDDR3_DS_40) {
 				switch (odt_value) {
 				case PHY_DRV_ODT_240:
 					vref_value_dq = 0x19;
@@ -425,7 +404,7 @@ static int phy_io_config(const struct chan_info *chan,
 					debug("Invalid ODT value.\n");
 					return -EINVAL;
 				}
-			} else if (drv_value == PHY_DRV_ODT_34_3) {
+			} else if (ds_value == LPDDR3_DS_34) {
 				switch (odt_value) {
 				case PHY_DRV_ODT_240:
 					vref_value_dq = 0x17;
@@ -496,7 +475,7 @@ static int phy_io_config(const struct chan_info *chan,
 	/* PHY_939 PHY_PAD_CS_DRIVE */
 	clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
 
-	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+	if (params->base.dramtype == LPDDR4) {
 		/* BOOSTP_EN & BOOSTN_EN */
 		reg_value = ((PHY_BOOSTP_EN << 4) | PHY_BOOSTN_EN);
 		/* PHY_925 PHY_PAD_FDBK_DRIVE2 */
@@ -537,14 +516,7 @@ static int phy_io_config(const struct chan_info *chan,
 	}
 
 	/* speed setting */
-	if (params->base.ddr_freq < 400)
-		speed = 0x0;
-	else if (params->base.ddr_freq < 800)
-		speed = 0x1;
-	else if (params->base.ddr_freq < 1200)
-		speed = 0x2;
-	else
-		speed = 0x3;
+	speed = 0x2;
 
 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
 	clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
@@ -563,7 +535,7 @@ static int phy_io_config(const struct chan_info *chan,
 	/* PHY_939 PHY_PAD_CS_DRIVE */
 	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
 
-	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+	if (params->base.dramtype == LPDDR4) {
 		/* RX_CM_INPUT */
 		reg_value = PHY_RX_CM_INPUT;
 		/* PHY_924 PHY_PAD_FDBK_DRIVE */
@@ -610,16 +582,17 @@ static void set_ds_odt(const struct chan_info *chan,
 		tsel_rd_select_n = io->rd_odt;
 
 		tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
-		tsel_idle_select_n = PHY_DRV_ODT_240;
+		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
 
 		tsel_wr_select_dq_p = io->wr_dq_drv;
-		tsel_wr_select_dq_n = PHY_DRV_ODT_40;
+		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
 
 		tsel_wr_select_ca_p = io->wr_ca_drv;
-		tsel_wr_select_ca_n = PHY_DRV_ODT_40;
+		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
 
 		tsel_ckcs_select_p = io->wr_ckcs_drv;
 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
+
 		switch (tsel_rd_select_n) {
 		case PHY_DRV_ODT_240:
 			soc_odt = 1;
@@ -659,8 +632,8 @@ static void set_ds_odt(const struct chan_info *chan,
 		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
 
-		tsel_wr_select_ca_p = PHY_DRV_ODT_48;
-		tsel_wr_select_ca_n = PHY_DRV_ODT_48;
+		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
+		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
 
 		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
@@ -733,7 +706,7 @@ static void set_ds_odt(const struct chan_info *chan,
 
 	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
 	reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4);
-	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+	if (params->base.dramtype == LPDDR4) {
 		/* LPDDR4 these register read always return 0, so
 		 * can not use clrsetbits_le32(), need to write32
 		 */
@@ -766,9 +739,9 @@ static void set_ds_odt(const struct chan_info *chan,
 
 	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
 	clrsetbits_le32(&denali_phy[924], 0xff,
-			tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
+			tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 4));
 	clrsetbits_le32(&denali_phy[925], 0xff,
-			tsel_rd_select_n | (tsel_rd_select_p << 4));
+			tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
 
 	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
 	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
@@ -810,46 +783,107 @@ static void set_ds_odt(const struct chan_info *chan,
 	phy_io_config(chan, params, mr5);
 }
 
-static void pctl_start(struct dram_info *dram, u8 channel)
+static void pctl_start(struct dram_info *dram,
+		       struct rk3399_sdram_params *params,
+		       u32 channel_mask)
 {
-	const struct chan_info *chan = &dram->chan[channel];
-	u32 *denali_ctl = chan->pctl->denali_ctl;
-	u32 *denali_phy = chan->publ->denali_phy;
-	u32 *ddrc0_con = get_ddrc0_con(dram, channel);
+	const struct chan_info *chan_0 = &dram->chan[0];
+	const struct chan_info *chan_1 = &dram->chan[1];
+
+	u32 *denali_ctl_0 = chan_0->pctl->denali_ctl;
+	u32 *denali_phy_0 = chan_0->publ->denali_phy;
+	u32 *ddrc0_con_0 = get_ddrc0_con(dram, 0);
+	u32 *denali_ctl_1 = chan_1->pctl->denali_ctl;
+	u32 *denali_phy_1 = chan_1->publ->denali_phy;
+	u32 *ddrc1_con_0 = get_ddrc0_con(dram, 1);
 	u32 count = 0;
 	u32 byte, tmp;
 
-	writel(0x01000000, &ddrc0_con);
+	/* PHY_DLL_RST_EN */
+	if (channel_mask & 1) {
+		writel(0x01000000, &ddrc0_con_0);
+		clrsetbits_le32(&denali_phy_0[957], 0x3 << 24, 0x2 << 24);
+	}
 
-	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 0x2 << 24);
+	if (channel_mask & 1) {
+		count = 0;
+		while (!(readl(&denali_ctl_0[203]) & (1 << 3))) {
+			if (count > 1000) {
+				printf("%s: Failed to init pctl channel 0\n",
+				       __func__);
+				while (1)
+					;
+			}
+			udelay(1);
+			count++;
+		}
 
-	while (!(readl(&denali_ctl[203]) & (1 << 3))) {
-		if (count > 1000) {
-			printf("%s: Failed to init pctl for channel %d\n",
-			       __func__, channel);
-			while (1)
-				;
+		writel(0x01000100, &ddrc0_con_0);
+		for (byte = 0; byte < 4; byte++)	{
+			tmp = 0x820;
+			writel((tmp << 16) | tmp,
+			       &denali_phy_0[53 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_0[54 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_0[55 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_0[56 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_0[57 + (128 * byte)]);
+			clrsetbits_le32(&denali_phy_0[58 + (128 * byte)],
+					0xffff, tmp);
 		}
+		clrsetbits_le32(&denali_ctl_0[68], PWRUP_SREFRESH_EXIT,
+				dram->pwrup_srefresh_exit[0]);
+	}
 
-		udelay(1);
-		count++;
+	if (channel_mask & 2) {
+		writel(0x01000000, &ddrc1_con_0);
+		clrsetbits_le32(&denali_phy_1[957], 0x3 << 24, 0x2 << 24);
 	}
+	if (channel_mask & 2) {
+		count = 0;
+		while (!(readl(&denali_ctl_1[203]) & (1 << 3))) {
+			if (count > 1000) {
+				printf("%s: Failed to init pctl channel 1\n",
+				       __func__);
+				while (1)
+					;
+			}
+			udelay(1);
+			count++;
+		}
 
-	writel(0x01000100, &ddrc0_con);
+		writel(0x01000100, &ddrc1_con_0);
+		for (byte = 0; byte < 4; byte++)	{
+			tmp = 0x820;
+			writel((tmp << 16) | tmp,
+			       &denali_phy_1[53 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_1[54 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_1[55 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_1[56 + (128 * byte)]);
+			writel((tmp << 16) | tmp,
+			       &denali_phy_1[57 + (128 * byte)]);
+			clrsetbits_le32(&denali_phy_1[58 + (128 * byte)],
+					0xffff, tmp);
+		}
 
-	for (byte = 0; byte < 4; byte++) {
-		tmp = 0x820;
-		writel((tmp << 16) | tmp, &denali_phy[53 + (128 * byte)]);
-		writel((tmp << 16) | tmp, &denali_phy[54 + (128 * byte)]);
-		writel((tmp << 16) | tmp, &denali_phy[55 + (128 * byte)]);
-		writel((tmp << 16) | tmp, &denali_phy[56 + (128 * byte)]);
-		writel((tmp << 16) | tmp, &denali_phy[57 + (128 * byte)]);
+		clrsetbits_le32(&denali_ctl_1[68], PWRUP_SREFRESH_EXIT,
+				dram->pwrup_srefresh_exit[1]);
 
-		clrsetbits_le32(&denali_phy[58 + (128 * byte)], 0xffff, tmp);
+		/*
+		 * restore channel 1 RESET original setting
+		 * to avoid 240ohm too weak to prevent ESD test
+		 */
+		if (params->base.dramtype == LPDDR4)
+			clrsetbits_le32(&denali_phy_1[937], 0xff,
+					params->phy_regs.denali_phy[937] &
+					0xFF);
 	}
-
-	clrsetbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT,
-			dram->pwrup_srefresh_exit[channel]);
 }
 
 static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
@@ -861,13 +895,16 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
 	const u32 *params_ctl = params->pctl_regs.denali_ctl;
 	const u32 *params_phy = params->phy_regs.denali_phy;
 	u32 tmp, tmp1, tmp2;
+	struct rk3399_sdram_params *params_cfg;
+	u32 byte;
 
+	dram->ops->modify_param(chan, params);
 	/*
 	 * work around controller bug:
 	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
 	 */
-	copy_to_reg(&denali_ctl[1], &params_ctl[1],
-		    sizeof(struct rk3399_ddr_pctl_regs) - 4);
+	sdram_copy_to_reg(&denali_ctl[1], &params_ctl[1],
+			  sizeof(struct rk3399_ddr_pctl_regs) - 4);
 	writel(params_ctl[0], &denali_ctl[0]);
 
 	/*
@@ -884,8 +921,8 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
 		writel(tmp + tmp1, &denali_ctl[14]);
 	}
 
-	copy_to_reg(denali_pi, &params->pi_regs.denali_pi[0],
-		    sizeof(struct rk3399_ddr_pi_regs));
+	sdram_copy_to_reg(denali_pi, &params->pi_regs.denali_pi[0],
+			  sizeof(struct rk3399_ddr_pi_regs));
 
 	/* rank count need to set for init */
 	set_memory_map(chan, channel, params);
@@ -894,7 +931,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
 	writel(params->phy_regs.denali_phy[911], &denali_phy[911]);
 	writel(params->phy_regs.denali_phy[912], &denali_phy[912]);
 
-	if (IS_ENABLED(CONFIG_RAM_RK3399_LPDDR4)) {
+	if (params->base.dramtype == LPDDR4) {
 		writel(params->phy_regs.denali_phy[898], &denali_phy[898]);
 		writel(params->phy_regs.denali_phy[919], &denali_phy[919]);
 	}
@@ -927,41 +964,67 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
 		}
 	}
 
-	copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
-	copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
-	copy_to_reg(&denali_phy[128], &params_phy[128], (218 - 128 + 1) * 4);
-	copy_to_reg(&denali_phy[256], &params_phy[256], (346 - 256 + 1) * 4);
-	copy_to_reg(&denali_phy[384], &params_phy[384], (474 - 384 + 1) * 4);
-	copy_to_reg(&denali_phy[512], &params_phy[512], (549 - 512 + 1) * 4);
-	copy_to_reg(&denali_phy[640], &params_phy[640], (677 - 640 + 1) * 4);
-	copy_to_reg(&denali_phy[768], &params_phy[768], (805 - 768 + 1) * 4);
-	set_ds_odt(chan, params, true, 0);
+	sdram_copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
+	sdram_copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[128], &params_phy[128],
+			  (218 - 128 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[256], &params_phy[256],
+			  (346 - 256 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[384], &params_phy[384],
+			  (474 - 384 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[512], &params_phy[512],
+			  (549 - 512 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[640], &params_phy[640],
+			  (677 - 640 + 1) * 4);
+	sdram_copy_to_reg(&denali_phy[768], &params_phy[768],
+			  (805 - 768 + 1) * 4);
 
-	/*
-	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
-	 * dqs_tsel_wr_end[7:4] add Half cycle
-	 */
-	tmp = (readl(&denali_phy[84]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[84], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[212]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[212], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[340]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[340], 0xff << 8, (tmp + 0x10) << 8);
-	tmp = (readl(&denali_phy[468]) >> 8) & 0xff;
-	clrsetbits_le32(&denali_phy[468], 0xff << 8, (tmp + 0x10) << 8);
+	if (params->base.dramtype == LPDDR4)
+		params_cfg = dram->ops->get_phy_index_params(1, params);
+	else
+		params_cfg = dram->ops->get_phy_index_params(0, params);
+
+	clrsetbits_le32(&params_cfg->phy_regs.denali_phy[896], 0x3 << 8,
+			0 << 8);
+	writel(params_cfg->phy_regs.denali_phy[896], &denali_phy[896]);
+
+	writel(params->phy_regs.denali_phy[83] + (0x10 << 16),
+	       &denali_phy[83]);
+	writel(params->phy_regs.denali_phy[84] + (0x10 << 8),
+	       &denali_phy[84]);
+	writel(params->phy_regs.denali_phy[211] + (0x10 << 16),
+	       &denali_phy[211]);
+	writel(params->phy_regs.denali_phy[212] + (0x10 << 8),
+	       &denali_phy[212]);
+	writel(params->phy_regs.denali_phy[339] + (0x10 << 16),
+	       &denali_phy[339]);
+	writel(params->phy_regs.denali_phy[340] + (0x10 << 8),
+	       &denali_phy[340]);
+	writel(params->phy_regs.denali_phy[467] + (0x10 << 16),
+	       &denali_phy[467]);
+	writel(params->phy_regs.denali_phy[468] + (0x10 << 8),
+	       &denali_phy[468]);
 
-	/*
-	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
-	 * dq_tsel_wr_end[7:4] add Half cycle
-	 */
-	tmp = (readl(&denali_phy[83]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[83], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[211]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[211], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[339]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[339], 0xff << 16, (tmp + 0x10) << 16);
-	tmp = (readl(&denali_phy[467]) >> 16) & 0xff;
-	clrsetbits_le32(&denali_phy[467], 0xff << 16, (tmp + 0x10) << 16);
+	if (params->base.dramtype == LPDDR4) {
+		/*
+		 * to improve write dqs and dq phase from 1.5ns to 3.5ns
+		 * at 50MHz. this's the measure result from oscilloscope
+		 * of dqs and dq write signal.
+		 */
+		for (byte = 0; byte < 4; byte++) {
+			tmp = 0x680;
+			clrsetbits_le32(&denali_phy[1 + (128 * byte)],
+					0xfff << 8, tmp << 8);
+		}
+		/*
+		 * to workaround 366ball two channel's RESET connect to
+		 * one RESET signal of die
+		 */
+		if (channel == 1)
+			clrsetbits_le32(&denali_phy[937], 0xff,
+					PHY_DRV_ODT_240 |
+					(PHY_DRV_ODT_240 << 0x4));
+	}
 
 	return 0;
 }
@@ -1277,10 +1340,9 @@ static int data_training_wdql(const struct chan_info *chan, u32 channel,
 
 		/*
 		 * disable PI_WDQLVL_VREF_EN before wdq leveling?
-		 * PI_181 PI_WDQLVL_VREF_EN:RW:8:1
+		 * PI_117 PI_WDQLVL_VREF_EN:RW:8:1
 		 */
-		clrbits_le32(&denali_pi[181], 0x1 << 8);
-
+		clrbits_le32(&denali_pi[117], 0x1 << 8);
 		/* PI_124 PI_WDQLVL_EN:RW:16:2 */
 		clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
 
@@ -1392,7 +1454,7 @@ static void set_ddrconfig(const struct chan_info *chan,
 			  unsigned char channel, u32 ddrconfig)
 {
 	/* only need to set ddrconfig */
-	struct rk3399_msch_regs *ddr_msch_regs = chan->msch;
+	struct msch_regs *ddr_msch_regs = chan->msch;
 	unsigned int cs0_cap = 0;
 	unsigned int cs1_cap = 0;
 
@@ -1413,52 +1475,43 @@ static void set_ddrconfig(const struct chan_info *chan,
 	       &ddr_msch_regs->ddrsize);
 }
 
+static void sdram_msch_config(struct msch_regs *msch,
+			      struct sdram_msch_timings *noc_timings)
+{
+	writel(noc_timings->ddrtiminga0.d32,
+	       &msch->ddrtiminga0.d32);
+	writel(noc_timings->ddrtimingb0.d32,
+	       &msch->ddrtimingb0.d32);
+	writel(noc_timings->ddrtimingc0.d32,
+	       &msch->ddrtimingc0.d32);
+	writel(noc_timings->devtodev0.d32,
+	       &msch->devtodev0.d32);
+	writel(noc_timings->ddrmode.d32,
+	       &msch->ddrmode.d32);
+}
+
 static void dram_all_config(struct dram_info *dram,
-			    const struct rk3399_sdram_params *params)
+			    struct rk3399_sdram_params *params)
 {
 	u32 sys_reg2 = 0;
 	u32 sys_reg3 = 0;
 	unsigned int channel, idx;
 
-	sys_reg2 |= SYS_REG_ENC_DDRTYPE(params->base.dramtype);
-	sys_reg2 |= SYS_REG_ENC_NUM_CH(params->base.num_channels);
-
 	for (channel = 0, idx = 0;
 	     (idx < params->base.num_channels) && (channel < 2);
 	     channel++) {
-		const struct rk3399_sdram_channel *info = &params->ch[channel];
-		struct rk3399_msch_regs *ddr_msch_regs;
-		const struct rk3399_msch_timings *noc_timing;
+		struct msch_regs *ddr_msch_regs;
+		struct sdram_msch_timings *noc_timing;
 
 		if (params->ch[channel].cap_info.col == 0)
 			continue;
 		idx++;
-		sys_reg2 |= SYS_REG_ENC_ROW_3_4(info->cap_info.row_3_4, channel);
-		sys_reg2 |= SYS_REG_ENC_CHINFO(channel);
-		sys_reg2 |= SYS_REG_ENC_RANK(info->cap_info.rank, channel);
-		sys_reg2 |= SYS_REG_ENC_COL(info->cap_info.col, channel);
-		sys_reg2 |= SYS_REG_ENC_BK(info->cap_info.bk, channel);
-		sys_reg2 |= SYS_REG_ENC_BW(info->cap_info.bw, channel);
-		sys_reg2 |= SYS_REG_ENC_DBW(info->cap_info.dbw, channel);
-		SYS_REG_ENC_CS0_ROW(info->cap_info.cs0_row, sys_reg2, sys_reg3, channel);
-		if (info->cap_info.cs1_row)
-			SYS_REG_ENC_CS1_ROW(info->cap_info.cs1_row, sys_reg2,
-					    sys_reg3, channel);
-		sys_reg3 |= SYS_REG_ENC_CS1_COL(info->cap_info.col, channel);
-		sys_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
-
+		sdram_org_config(&params->ch[channel].cap_info,
+				 &params->base, &sys_reg2,
+				 &sys_reg3, channel);
 		ddr_msch_regs = dram->chan[channel].msch;
 		noc_timing = &params->ch[channel].noc_timings;
-		writel(noc_timing->ddrtiminga0,
-		       &ddr_msch_regs->ddrtiminga0);
-		writel(noc_timing->ddrtimingb0,
-		       &ddr_msch_regs->ddrtimingb0);
-		writel(noc_timing->ddrtimingc0.d32,
-		       &ddr_msch_regs->ddrtimingc0);
-		writel(noc_timing->devtodev0,
-		       &ddr_msch_regs->devtodev0);
-		writel(noc_timing->ddrmode.d32,
-		       &ddr_msch_regs->ddrmode);
+		sdram_msch_config(ddr_msch_regs, noc_timing);
 
 		/**
 		 * rank 1 memory clock disable (dfi_dram_clk_disable = 1)
@@ -1494,7 +1547,7 @@ static void set_cap_relate_config(const struct chan_info *chan,
 {
 	u32 *denali_ctl = chan->pctl->denali_ctl;
 	u32 tmp;
-	struct rk3399_msch_timings *noc_timing;
+	struct sdram_msch_timings *noc_timing;
 
 	if (params->base.dramtype == LPDDR3) {
 		tmp = (8 << params->ch[channel].cap_info.bw) /
@@ -1566,9 +1619,14 @@ static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel)
 	return i;
 }
 
+static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
+{
+	rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
+}
+
 #if !defined(CONFIG_RAM_RK3399_LPDDR4)
-static int default_data_training(struct dram_info *dram, u32 channel, u8 rank,
-				 struct rk3399_sdram_params *params)
+static int data_training_first(struct dram_info *dram, u32 channel, u8 rank,
+			       struct rk3399_sdram_params *params)
 {
 	u8 training_flag = PI_READ_GATE_TRAINING;
 
@@ -1629,31 +1687,72 @@ static int switch_to_phy_index1(struct dram_info *dram,
 	return 0;
 }
 
+struct rk3399_sdram_params
+	*get_phy_index_params(u32 phy_fn,
+			      struct rk3399_sdram_params *params)
+{
+	if (phy_fn == 0)
+		return params;
+	else
+		return NULL;
+}
+
+void modify_param(const struct chan_info *chan,
+		  struct rk3399_sdram_params *params)
+{
+	struct rk3399_sdram_params *params_cfg;
+	u32 *denali_pi_params;
+
+	denali_pi_params = params->pi_regs.denali_pi;
+
+	/* modify PHY F0/F1/F2 params */
+	params_cfg = get_phy_index_params(0, params);
+	set_ds_odt(chan, params_cfg, false, 0);
+
+	clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
+}
 #else
 
-struct rk3399_sdram_params lpddr4_timings[] = {
-	#include "sdram-rk3399-lpddr4-400.inc"
-	#include "sdram-rk3399-lpddr4-800.inc"
+struct rk3399_sdram_params dfs_cfgs_lpddr4[] = {
+#include "sdram-rk3399-lpddr4-400.inc"
+#include "sdram-rk3399-lpddr4-800.inc"
 };
 
+static struct rk3399_sdram_params
+	*lpddr4_get_phy_index_params(u32 phy_fn,
+				     struct rk3399_sdram_params *params)
+{
+	if (phy_fn == 0)
+		return params;
+	else if (phy_fn == 1)
+		return &dfs_cfgs_lpddr4[1];
+	else if (phy_fn == 2)
+		return &dfs_cfgs_lpddr4[0];
+	else
+		return NULL;
+}
+
 static void *get_denali_pi(const struct chan_info *chan,
 			   struct rk3399_sdram_params *params, bool reg)
 {
 	return reg ? &chan->pi->denali_pi : &params->pi_regs.denali_pi;
 }
 
-static u32 lpddr4_get_phy(struct rk3399_sdram_params *params, u32 ctl)
+static u32 lpddr4_get_phy_fn(struct rk3399_sdram_params *params, u32 ctl_fn)
 {
-	u32 lpddr4_phy[] = {1, 0, 0xb};
+	u32 lpddr4_phy_fn[] = {1, 0, 0xb};
 
-	return lpddr4_phy[ctl];
+	return lpddr4_phy_fn[ctl_fn];
 }
 
-static u32 lpddr4_get_ctl(struct rk3399_sdram_params *params, u32 phy)
+static u32 lpddr4_get_ctl_fn(struct rk3399_sdram_params *params, u32 phy_fn)
 {
-	u32 lpddr4_ctl[] = {1, 0, 2};
+	u32 lpddr4_ctl_fn[] = {1, 0, 2};
 
-	return lpddr4_ctl[phy];
+	return lpddr4_ctl_fn[phy_fn];
 }
 
 static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
@@ -1661,12 +1760,7 @@ static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
 	return ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F);
 }
 
-static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
-{
-	rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
-}
-
-/**
+/*
  * read mr_num mode register
  * rank = 1: cs0
  * rank = 2: cs1
@@ -1797,7 +1891,7 @@ end:
 }
 
 static void set_lpddr4_dq_odt(const struct chan_info *chan,
-			      struct rk3399_sdram_params *params, u32 ctl,
+			      struct rk3399_sdram_params *params, u32 ctl_fn,
 			      bool en, bool ctl_phy_reg, u32 mr5)
 {
 	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1805,14 +1899,13 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan,
 	struct io_setting *io;
 	u32 reg_value;
 
-	if (!en)
-		return;
-
 	io = lpddr4_get_io_settings(params, mr5);
+	if (en)
+		reg_value = io->dq_odt;
+	else
+		reg_value = 0;
 
-	reg_value = io->dq_odt;
-
-	switch (ctl) {
+	switch (ctl_fn) {
 	case 0:
 		clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);
 		clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);
@@ -1845,7 +1938,7 @@ static void set_lpddr4_dq_odt(const struct chan_info *chan,
 }
 
 static void set_lpddr4_ca_odt(const struct chan_info *chan,
-			      struct rk3399_sdram_params *params, u32 ctl,
+			      struct rk3399_sdram_params *params, u32 ctl_fn,
 			      bool en, bool ctl_phy_reg, u32 mr5)
 {
 	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1853,14 +1946,13 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan,
 	struct io_setting *io;
 	u32 reg_value;
 
-	if (!en)
-		return;
-
 	io = lpddr4_get_io_settings(params, mr5);
+	if (en)
+		reg_value = io->ca_odt;
+	else
+		reg_value = 0;
 
-	reg_value = io->ca_odt;
-
-	switch (ctl) {
+	switch (ctl_fn) {
 	case 0:
 		clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);
 		clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);
@@ -1893,7 +1985,7 @@ static void set_lpddr4_ca_odt(const struct chan_info *chan,
 }
 
 static void set_lpddr4_MR3(const struct chan_info *chan,
-			   struct rk3399_sdram_params *params, u32 ctl,
+			   struct rk3399_sdram_params *params, u32 ctl_fn,
 			   bool ctl_phy_reg, u32 mr5)
 {
 	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1905,7 +1997,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan,
 
 	reg_value = ((io->pdds << 3) | 1);
 
-	switch (ctl) {
+	switch (ctl_fn) {
 	case 0:
 		clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);
 		clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);
@@ -1940,7 +2032,7 @@ static void set_lpddr4_MR3(const struct chan_info *chan,
 }
 
 static void set_lpddr4_MR12(const struct chan_info *chan,
-			    struct rk3399_sdram_params *params, u32 ctl,
+			    struct rk3399_sdram_params *params, u32 ctl_fn,
 			    bool ctl_phy_reg, u32 mr5)
 {
 	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -1952,7 +2044,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan,
 
 	reg_value = io->ca_vref;
 
-	switch (ctl) {
+	switch (ctl_fn) {
 	case 0:
 		clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,
 				reg_value << 16);
@@ -1989,7 +2081,7 @@ static void set_lpddr4_MR12(const struct chan_info *chan,
 }
 
 static void set_lpddr4_MR14(const struct chan_info *chan,
-			    struct rk3399_sdram_params *params, u32 ctl,
+			    struct rk3399_sdram_params *params, u32 ctl_fn,
 			    bool ctl_phy_reg, u32 mr5)
 {
 	u32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);
@@ -2001,7 +2093,7 @@ static void set_lpddr4_MR14(const struct chan_info *chan,
 
 	reg_value = io->dq_vref;
 
-	switch (ctl) {
+	switch (ctl_fn) {
 	case 0:
 		clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,
 				reg_value << 16);
@@ -2037,22 +2129,73 @@ static void set_lpddr4_MR14(const struct chan_info *chan,
 	}
 }
 
+void lpddr4_modify_param(const struct chan_info *chan,
+			 struct rk3399_sdram_params *params)
+{
+	struct rk3399_sdram_params *params_cfg;
+	u32 *denali_ctl_params;
+	u32 *denali_pi_params;
+	u32 *denali_phy_params;
+
+	denali_ctl_params = params->pctl_regs.denali_ctl;
+	denali_pi_params = params->pi_regs.denali_pi;
+	denali_phy_params = params->phy_regs.denali_phy;
+
+	set_lpddr4_dq_odt(chan, params, 2, true, false, 0);
+	set_lpddr4_ca_odt(chan, params, 2, true, false, 0);
+	set_lpddr4_MR3(chan, params, 2, false, 0);
+	set_lpddr4_MR12(chan, params, 2, false, 0);
+	set_lpddr4_MR14(chan, params, 2, false, 0);
+	params_cfg = lpddr4_get_phy_index_params(0, params);
+	set_ds_odt(chan, params_cfg, false, 0);
+	/* read two cycle preamble */
+	clrsetbits_le32(&denali_ctl_params[200], 0x3 << 24, 0x3 << 24);
+	clrsetbits_le32(&denali_phy_params[7], 0x3 << 24, 0x3 << 24);
+	clrsetbits_le32(&denali_phy_params[135], 0x3 << 24, 0x3 << 24);
+	clrsetbits_le32(&denali_phy_params[263], 0x3 << 24, 0x3 << 24);
+	clrsetbits_le32(&denali_phy_params[391], 0x3 << 24, 0x3 << 24);
+
+	/* boot frequency two cycle preamble */
+	clrsetbits_le32(&denali_phy_params[2], 0x3 << 16, 0x3 << 16);
+	clrsetbits_le32(&denali_phy_params[130], 0x3 << 16, 0x3 << 16);
+	clrsetbits_le32(&denali_phy_params[258], 0x3 << 16, 0x3 << 16);
+	clrsetbits_le32(&denali_phy_params[386], 0x3 << 16, 0x3 << 16);
+
+	clrsetbits_le32(&denali_pi_params[45], 0x3 << 8, 0x3 << 8);
+	clrsetbits_le32(&denali_pi_params[58], 0x1, 0x1);
+
+	/*
+	 * bypass mode need PHY_SLICE_PWR_RDC_DISABLE_x = 1,
+	 * boot frequency mode use bypass mode
+	 */
+	setbits_le32(&denali_phy_params[10], 1 << 16);
+	setbits_le32(&denali_phy_params[138], 1 << 16);
+	setbits_le32(&denali_phy_params[266], 1 << 16);
+	setbits_le32(&denali_phy_params[394], 1 << 16);
+
+	clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
+	clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
+}
+
 static void lpddr4_copy_phy(struct dram_info *dram,
-			    struct rk3399_sdram_params *params, u32 phy,
-			    struct rk3399_sdram_params *timings,
+			    struct rk3399_sdram_params *params, u32 phy_fn,
+			    struct rk3399_sdram_params *params_cfg,
 			    u32 channel)
 {
 	u32 *denali_ctl, *denali_phy;
 	u32 *denali_phy_params;
 	u32 speed = 0;
-	u32 ctl, mr5;
+	u32 ctl_fn, mr5;
 
 	denali_ctl = dram->chan[channel].pctl->denali_ctl;
 	denali_phy = dram->chan[channel].publ->denali_phy;
-	denali_phy_params = timings->phy_regs.denali_phy;
+	denali_phy_params = params_cfg->phy_regs.denali_phy;
 
 	/* switch index */
-	clrsetbits_le32(&denali_phy_params[896], 0x3 << 8, phy << 8);
+	clrsetbits_le32(&denali_phy_params[896], 0x3 << 8,
+			phy_fn << 8);
 	writel(denali_phy_params[896], &denali_phy[896]);
 
 	/* phy_pll_ctrl_ca, phy_pll_ctrl */
@@ -2112,14 +2255,14 @@ static void lpddr4_copy_phy(struct dram_info *dram,
 	 * phy_clk_wrdqz_slave_delay_x
 	 * phy_clk_wrdqs_slave_delay_x
 	 */
-	copy_to_reg((u32 *)&denali_phy[59], (u32 *)&denali_phy_params[59],
-		    (63 - 58) * 4);
-	copy_to_reg((u32 *)&denali_phy[187], (u32 *)&denali_phy_params[187],
-		    (191 - 186) * 4);
-	copy_to_reg((u32 *)&denali_phy[315], (u32 *)&denali_phy_params[315],
-		    (319 - 314) * 4);
-	copy_to_reg((u32 *)&denali_phy[443], (u32 *)&denali_phy_params[443],
-		    (447 - 442) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[59],
+			  (u32 *)&denali_phy_params[59], (63 - 58) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[187],
+			  (u32 *)&denali_phy_params[187], (191 - 186) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[315],
+			  (u32 *)&denali_phy_params[315], (319 - 314) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[443],
+			  (u32 *)&denali_phy_params[443], (447 - 442) * 4);
 
 	/*
 	 * phy_dqs_tsel_wr_timing_x 8bits denali_phy_84/212/340/468 offset_8
@@ -2218,31 +2361,30 @@ static void lpddr4_copy_phy(struct dram_info *dram,
 	 * phy_wrlvl_delay_period_threshold_x
 	 * phy_wrlvl_early_force_zero_x
 	 */
-	copy_to_reg((u32 *)&denali_phy[64], (u32 *)&denali_phy_params[64],
-		    (67 - 63) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[64],
+			  (u32 *)&denali_phy_params[64], (67 - 63) * 4);
 	clrsetbits_le32(&denali_phy[68], 0xfffffc00,
 			denali_phy_params[68] & 0xfffffc00);
-	copy_to_reg((u32 *)&denali_phy[69], (u32 *)&denali_phy_params[69],
-		    (79 - 68) * 4);
-	copy_to_reg((u32 *)&denali_phy[192], (u32 *)&denali_phy_params[192],
-		    (195 - 191) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[69],
+			  (u32 *)&denali_phy_params[69], (79 - 68) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[192],
+			  (u32 *)&denali_phy_params[192], (195 - 191) * 4);
 	clrsetbits_le32(&denali_phy[196], 0xfffffc00,
 			denali_phy_params[196] & 0xfffffc00);
-	copy_to_reg((u32 *)&denali_phy[197], (u32 *)&denali_phy_params[197],
-		    (207 - 196) * 4);
-	copy_to_reg((u32 *)&denali_phy[320], (u32 *)&denali_phy_params[320],
-		    (323 - 319) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[197],
+			  (u32 *)&denali_phy_params[197], (207 - 196) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[320],
+			  (u32 *)&denali_phy_params[320], (323 - 319) * 4);
 	clrsetbits_le32(&denali_phy[324], 0xfffffc00,
 			denali_phy_params[324] & 0xfffffc00);
-	copy_to_reg((u32 *)&denali_phy[325], (u32 *)&denali_phy_params[325],
-		    (335 - 324) * 4);
-
-	copy_to_reg((u32 *)&denali_phy[448], (u32 *)&denali_phy_params[448],
-		    (451 - 447) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[325],
+			  (u32 *)&denali_phy_params[325], (335 - 324) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[448],
+			  (u32 *)&denali_phy_params[448], (451 - 447) * 4);
 	clrsetbits_le32(&denali_phy[452], 0xfffffc00,
 			denali_phy_params[452] & 0xfffffc00);
-	copy_to_reg((u32 *)&denali_phy[453], (u32 *)&denali_phy_params[453],
-		    (463 - 452) * 4);
+	sdram_copy_to_reg((u32 *)&denali_phy[453],
+			  (u32 *)&denali_phy_params[453], (463 - 452) * 4);
 
 	/* phy_two_cyc_preamble_x */
 	clrsetbits_le32(&denali_phy[7], 0x3 << 24,
@@ -2255,11 +2397,11 @@ static void lpddr4_copy_phy(struct dram_info *dram,
 			denali_phy_params[391] & (0x3 << 24));
 
 	/* speed */
-	if (timings->base.ddr_freq < 400 * MHz)
+	if (params_cfg->base.ddr_freq < 400)
 		speed = 0x0;
-	else if (timings->base.ddr_freq < 800 * MHz)
+	else if (params_cfg->base.ddr_freq < 800)
 		speed = 0x1;
-	else if (timings->base.ddr_freq < 1200 * MHz)
+	else if (params_cfg->base.ddr_freq < 1200)
 		speed = 0x2;
 
 	/* phy_924 phy_pad_fdbk_drive */
@@ -2279,52 +2421,63 @@ static void lpddr4_copy_phy(struct dram_info *dram,
 	/* phy_939 phy_pad_cs_drive */
 	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
 
-	read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
-	set_ds_odt(&dram->chan[channel], timings, true, mr5);
+	if (params_cfg->base.dramtype == LPDDR4) {
+		read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
+		set_ds_odt(&dram->chan[channel], params_cfg, true, mr5);
+
+		ctl_fn = lpddr4_get_ctl_fn(params_cfg, phy_fn);
+		set_lpddr4_dq_odt(&dram->chan[channel], params_cfg,
+				  ctl_fn, true, true, mr5);
+		set_lpddr4_ca_odt(&dram->chan[channel], params_cfg,
+				  ctl_fn, true, true, mr5);
+		set_lpddr4_MR3(&dram->chan[channel], params_cfg,
+			       ctl_fn, true, mr5);
+		set_lpddr4_MR12(&dram->chan[channel], params_cfg,
+				ctl_fn, true, mr5);
+		set_lpddr4_MR14(&dram->chan[channel], params_cfg,
+				ctl_fn, true, mr5);
 
-	ctl = lpddr4_get_ctl(timings, phy);
-	set_lpddr4_dq_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
-	set_lpddr4_ca_odt(&dram->chan[channel], timings, ctl, true, true, mr5);
-	set_lpddr4_MR3(&dram->chan[channel], timings, ctl, true, mr5);
-	set_lpddr4_MR12(&dram->chan[channel], timings, ctl, true, mr5);
-	set_lpddr4_MR14(&dram->chan[channel], timings, ctl, true, mr5);
-
-	/*
-	 * if phy_sw_master_mode_x not bypass mode,
-	 * clear phy_slice_pwr_rdc_disable.
-	 * note: need use timings, not ddr_publ_regs
-	 */
-	if (!((denali_phy_params[86] >> 8) & (1 << 2))) {
-		clrbits_le32(&denali_phy[10], 1 << 16);
-		clrbits_le32(&denali_phy[138], 1 << 16);
-		clrbits_le32(&denali_phy[266], 1 << 16);
-		clrbits_le32(&denali_phy[394], 1 << 16);
-	}
+		/*
+		 * if phy_sw_master_mode_x not bypass mode,
+		 * clear phy_slice_pwr_rdc_disable.
+		 * note: need use timings, not ddr_publ_regs
+		 */
+		if (!((denali_phy_params[86] >> 8) & (1 << 2))) {
+			clrbits_le32(&denali_phy[10], 1 << 16);
+			clrbits_le32(&denali_phy[138], 1 << 16);
+			clrbits_le32(&denali_phy[266], 1 << 16);
+			clrbits_le32(&denali_phy[394], 1 << 16);
+		}
 
-	/*
-	 * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
-	 * smaller than 8
-	 * NOTE: need use timings, not ddr_publ_regs
-	 */
-	if ((denali_phy_params[84] >> 16) & 1) {
-		if (((readl(&denali_ctl[217 + ctl]) >> 16) & 0x1f) < 8)
-			clrsetbits_le32(&denali_ctl[217 + ctl],
-					0x1f << 16, 8 << 16);
+		/*
+		 * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
+		 * smaller than 8
+		 * NOTE: need use timings, not ddr_publ_regs
+		 */
+		if ((denali_phy_params[84] >> 16) & 1) {
+			if (((readl(&denali_ctl[217 + ctl_fn]) >>
+				16) & 0x1f) < 8)
+				clrsetbits_le32(&denali_ctl[217 + ctl_fn],
+						0x1f << 16,
+						8 << 16);
+		}
 	}
 }
 
 static void lpddr4_set_phy(struct dram_info *dram,
-			   struct rk3399_sdram_params *params, u32 phy,
-			   struct rk3399_sdram_params *timings)
+			   struct rk3399_sdram_params *params, u32 phy_fn,
+			   struct rk3399_sdram_params *params_cfg)
 {
 	u32 channel;
 
 	for (channel = 0; channel < 2; channel++)
-		lpddr4_copy_phy(dram, params, phy, timings, channel);
+		lpddr4_copy_phy(dram, params, phy_fn, params_cfg,
+				channel);
 }
 
 static int lpddr4_set_ctl(struct dram_info *dram,
-			  struct rk3399_sdram_params *params, u32 ctl, u32 hz)
+			  struct rk3399_sdram_params *params,
+			  u32 fn, u32 hz)
 {
 	u32 channel;
 	int ret_clk, ret;
@@ -2343,7 +2496,7 @@ static int lpddr4_set_ctl(struct dram_info *dram,
 
 	/* change freq */
 	writel((((0x3 << 4) | (1 << 2) | 1) << 16) |
-		(ctl << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
+		(fn << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
 	while (!(readl(&dram->cic->cic_status0) & (1 << 2)))
 		;
 
@@ -2366,12 +2519,12 @@ static int lpddr4_set_ctl(struct dram_info *dram,
 	clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
 
 	/* lpddr4 ctl2 can not do training, all training will fail */
-	if (!(params->base.dramtype == LPDDR4 && ctl == 2)) {
+	if (!(params->base.dramtype == LPDDR4 && fn == 2)) {
 		for (channel = 0; channel < 2; channel++) {
 			if (!(params->ch[channel].cap_info.col))
 				continue;
 			ret = data_training(dram, channel, params,
-						     PI_FULL_TRAINING);
+					    PI_FULL_TRAINING);
 			if (ret)
 				printf("%s: channel %d training failed!\n",
 				       __func__, channel);
@@ -2387,35 +2540,237 @@ static int lpddr4_set_ctl(struct dram_info *dram,
 static int lpddr4_set_rate(struct dram_info *dram,
 			   struct rk3399_sdram_params *params)
 {
-	u32 ctl;
-	u32 phy;
+	u32 ctl_fn;
+	u32 phy_fn;
 
-	for (ctl = 0; ctl < 2; ctl++) {
-		phy = lpddr4_get_phy(params, ctl);
+	for (ctl_fn = 0; ctl_fn < 2; ctl_fn++) {
+		phy_fn = lpddr4_get_phy_fn(params, ctl_fn);
 
-		lpddr4_set_phy(dram, params, phy, &lpddr4_timings[ctl]);
-		lpddr4_set_ctl(dram, params, ctl,
-			       lpddr4_timings[ctl].base.ddr_freq);
+		lpddr4_set_phy(dram, params, phy_fn, &dfs_cfgs_lpddr4[ctl_fn]);
+		lpddr4_set_ctl(dram, params, ctl_fn,
+			       dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq);
 
-		debug("%s: change freq to %d mhz %d, %d\n", __func__,
-		      lpddr4_timings[ctl].base.ddr_freq / MHz, ctl, phy);
+		printf("%s: change freq to %d mhz %d, %d\n", __func__,
+		       dfs_cfgs_lpddr4[ctl_fn].base.ddr_freq, ctl_fn, phy_fn);
 	}
 
 	return 0;
 }
 #endif /* CONFIG_RAM_RK3399_LPDDR4 */
 
+/* CS0,n=1
+ * CS1,n=2
+ * CS0 & CS1, n=3
+ * cs0_cap: MB unit
+ */
+static void dram_set_cs(const struct chan_info *chan, u32 cs_map, u32 cs0_cap,
+			unsigned char dramtype)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_pi = chan->pi->denali_pi;
+	struct msch_regs *ddr_msch_regs = chan->msch;
+
+	clrsetbits_le32(&denali_ctl[196], 0x3, cs_map);
+	writel((cs0_cap / 32) | (((4096 - cs0_cap) / 32) << 8),
+	       &ddr_msch_regs->ddrsize);
+	if (dramtype == LPDDR4) {
+		if (cs_map == 1)
+			cs_map = 0x5;
+		else if (cs_map == 2)
+			cs_map = 0xa;
+		else
+			cs_map = 0xF;
+	}
+	/*PI_41 PI_CS_MAP:RW:24:4*/
+	clrsetbits_le32(&denali_pi[41],
+			0xf << 24, cs_map << 24);
+	if (cs_map == 1 && dramtype == DDR3)
+		writel(0x2EC7FFFF, &denali_pi[34]);
+}
+
+static void dram_set_bw(const struct chan_info *chan, u32 bw)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+
+	if (bw == 2)
+		clrbits_le32(&denali_ctl[196], 1 << 16);
+	else
+		setbits_le32(&denali_ctl[196], 1 << 16);
+}
+
+static void dram_set_max_col(const struct chan_info *chan, u32 bw, u32 *pcol)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	struct msch_regs *ddr_msch_regs = chan->msch;
+	u32 *denali_pi = chan->pi->denali_pi;
+	u32 ddrconfig;
+
+	clrbits_le32(&denali_ctl[191], 0xf);
+	clrsetbits_le32(&denali_ctl[190],
+			(7 << 24),
+			((16 - ((bw == 2) ? 14 : 15)) << 24));
+	/*PI_199 PI_COL_DIFF:RW:0:4*/
+	clrbits_le32(&denali_pi[199], 0xf);
+	/*PI_155 PI_ROW_DIFF:RW:24:3*/
+	clrsetbits_le32(&denali_pi[155],
+			(7 << 24),
+			((16 - 12) << 24));
+	ddrconfig = (bw == 2) ? 3 : 2;
+	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
+	/* set max cs0 size */
+	writel((4096 / 32) | ((0 / 32) << 8),
+	       &ddr_msch_regs->ddrsize);
+
+	*pcol = 12;
+}
+
+static void dram_set_max_bank(const struct chan_info *chan, u32 bw, u32 *pbank,
+			      u32 *pcol)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_pi = chan->pi->denali_pi;
+
+	clrbits_le32(&denali_ctl[191], 0xf);
+	clrbits_le32(&denali_ctl[190], (3 << 16));
+	/*PI_199 PI_COL_DIFF:RW:0:4*/
+	clrbits_le32(&denali_pi[199], 0xf);
+	/*PI_155 PI_BANK_DIFF:RW:16:2*/
+	clrbits_le32(&denali_pi[155], (3 << 16));
+
+	*pbank = 3;
+	*pcol = 12;
+}
+
+static void dram_set_max_row(const struct chan_info *chan, u32 bw, u32 *prow,
+			     u32 *pbank, u32 *pcol)
+{
+	u32 *denali_ctl = chan->pctl->denali_ctl;
+	u32 *denali_pi = chan->pi->denali_pi;
+	struct msch_regs *ddr_msch_regs = chan->msch;
+
+	clrsetbits_le32(&denali_ctl[191], 0xf, 12 - 10);
+	clrbits_le32(&denali_ctl[190],
+		     (0x3 << 16) | (0x7 << 24));
+	/*PI_199 PI_COL_DIFF:RW:0:4*/
+	clrsetbits_le32(&denali_pi[199], 0xf, 12 - 10);
+	/*PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2*/
+	clrbits_le32(&denali_pi[155],
+		     (0x3 << 16) | (0x7 << 24));
+	writel(1 | (1 << 8), &ddr_msch_regs->ddrconf);
+	/* set max cs0 size */
+	writel((4096 / 32) | ((0 / 32) << 8),
+	       &ddr_msch_regs->ddrsize);
+
+	*prow = 16;
+	*pbank = 3;
+	*pcol = (bw == 2) ? 10 : 11;
+}
+
+static u64 dram_detect_cap(struct dram_info *dram,
+			   struct rk3399_sdram_params *params,
+			   unsigned char channel)
+{
+	const struct chan_info *chan = &dram->chan[channel];
+	struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+	u32 bw;
+	u32 col_tmp;
+	u32 bk_tmp;
+	u32 row_tmp;
+	u32 cs0_cap;
+	u32 training_flag;
+	u32 ddrconfig;
+
+	/* detect bw */
+	bw = 2;
+	if (params->base.dramtype != LPDDR4) {
+		dram_set_bw(chan, bw);
+		cap_info->bw = bw;
+		if (data_training(dram, channel, params,
+				  PI_READ_GATE_TRAINING)) {
+			bw = 1;
+			dram_set_bw(chan, 1);
+			cap_info->bw = bw;
+			if (data_training(dram, channel, params,
+					  PI_READ_GATE_TRAINING)) {
+				printf("16bit error!!!\n");
+				goto error;
+			}
+		}
+	}
+	/*
+	 * LPDDR3 CA training msut be trigger before other training.
+	 * DDR3 is not have CA training.
+	 */
+	if (params->base.dramtype == LPDDR3)
+		training_flag = PI_WRITE_LEVELING;
+	else
+		training_flag = PI_FULL_TRAINING;
+
+	if (params->base.dramtype != LPDDR4) {
+		if (data_training(dram, channel, params, training_flag)) {
+			printf("full training error!!!\n");
+			goto error;
+		}
+	}
+
+	/* detect col */
+	dram_set_max_col(chan, bw, &col_tmp);
+	if (sdram_detect_col(cap_info, col_tmp) != 0)
+		goto error;
+
+	/* detect bank */
+	dram_set_max_bank(chan, bw, &bk_tmp, &col_tmp);
+	sdram_detect_bank(cap_info, col_tmp, bk_tmp);
+
+	/* detect row */
+	dram_set_max_row(chan, bw, &row_tmp, &bk_tmp, &col_tmp);
+	if (sdram_detect_row(cap_info, col_tmp, bk_tmp, row_tmp) != 0)
+		goto error;
+
+	/* detect row_3_4 */
+	sdram_detect_row_3_4(cap_info, col_tmp, bk_tmp);
+
+	/* set ddrconfig */
+	cs0_cap = (1 << (cap_info->cs0_row + cap_info->col + cap_info->bk +
+			 cap_info->bw - 20));
+	if (cap_info->row_3_4)
+		cs0_cap = cs0_cap * 3 / 4;
+
+	cap_info->cs1_row = cap_info->cs0_row;
+	set_memory_map(chan, channel, params);
+	ddrconfig = calculate_ddrconfig(params, channel);
+	if (-1 == ddrconfig)
+		goto error;
+	set_ddrconfig(chan, params, channel,
+		      cap_info->ddrconfig);
+
+	/* detect cs1 row */
+	sdram_detect_cs1_row(cap_info, params->base.dramtype);
+
+	/* detect die bw */
+	sdram_detect_dbw(cap_info, params->base.dramtype);
+
+	return 0;
+error:
+	return (-1);
+}
+
 static unsigned char calculate_stride(struct rk3399_sdram_params *params)
 {
-	unsigned int stride = params->base.stride;
-	unsigned int channel, chinfo = 0;
+	unsigned int gstride_type;
+	unsigned int channel;
+	unsigned int chinfo = 0;
+	unsigned int cap = 0;
+	unsigned int stride = -1;
 	unsigned int ch_cap[2] = {0, 0};
-	u64 cap;
+
+	gstride_type = STRIDE_256B;
 
 	for (channel = 0; channel < 2; channel++) {
 		unsigned int cs0_cap = 0;
 		unsigned int cs1_cap = 0;
-		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+		struct sdram_cap_info *cap_info =
+			&params->ch[channel].cap_info;
 
 		if (cap_info->col == 0)
 			continue;
@@ -2433,49 +2788,124 @@ static unsigned char calculate_stride(struct rk3399_sdram_params *params)
 		chinfo |= 1 << channel;
 	}
 
-	/* stride calculation for 1 channel */
-	if (params->base.num_channels == 1 && chinfo & 1)
-		return 0x17;	/* channel a */
-
-	/* stride calculation for 2 channels, default gstride type is 256B */
-	if (ch_cap[0] == ch_cap[1]) {
-		cap = ch_cap[0] + ch_cap[1];
-		switch (cap) {
-		/* 512MB */
-		case 512:
-			stride = 0;
-			break;
-		/* 1GB */
-		case 1024:
-			stride = 0x5;
-			break;
+	cap = ch_cap[0] + ch_cap[1];
+	if (params->base.num_channels == 1) {
+		if (chinfo & 1) /* channel a only */
+			stride = 0x17;
+		else /* channel b only */
+			stride = 0x18;
+	} else {/* 2 channel */
+		if (ch_cap[0] == ch_cap[1]) {
+			/* interleaved */
+			if (gstride_type == PART_STRIDE) {
+			/*
+			 * first 64MB no interleaved other 256B interleaved
+			 * if 786M+768M.useful space from 0-1280MB and
+			 * 1536MB-1792MB
+			 * if 1.5G+1.5G(continuous).useful space from 0-2560MB
+			 * and 3072MB-3584MB
+			 */
+				stride = 0x1F;
+			} else {
+				switch (cap) {
+				/* 512MB */
+				case 512:
+					stride = 0;
+					break;
+				/* 1GB unstride or 256B stride*/
+				case 1024:
+					stride = (gstride_type == UN_STRIDE) ?
+						0x1 : 0x5;
+					break;
+				/*
+				 * 768MB + 768MB same as total 2GB memory
+				 * useful space: 0-768MB 1GB-1792MB
+				 */
+				case 1536:
+				/* 2GB unstride or 256B or 512B stride */
+				case 2048:
+					stride = (gstride_type == UN_STRIDE) ?
+						0x2 :
+						((gstride_type == STRIDE_512B) ?
+						 0xA : 0x9);
+					break;
+				/* 1536MB + 1536MB */
+				case 3072:
+					stride = (gstride_type == UN_STRIDE) ?
+						0x3 :
+						((gstride_type == STRIDE_512B) ?
+						 0x12 : 0x11);
+					break;
+				/* 4GB  unstride or 128B,256B,512B,4KB stride */
+				case 4096:
+					stride = (gstride_type == UN_STRIDE) ?
+						0x3 : (0xC + gstride_type);
+					break;
+				}
+			}
+		}
+		if (ch_cap[0] == 2048 && ch_cap[1] == 1024) {
+			/* 2GB + 1GB */
+			stride = (gstride_type == UN_STRIDE) ? 0x3 : 0x19;
+		}
 		/*
-		 * 768MB + 768MB same as total 2GB memory
-		 * useful space: 0-768MB 1GB-1792MB
+		 * remain two channel capability not equal OR capability
+		 * power function of 2
 		 */
-		case 1536:
-		/* 2GB */
-		case 2048:
-			stride = 0x9;
-			break;
-		/* 1536MB + 1536MB */
-		case 3072:
-			stride = 0x11;
-			break;
-		/* 4GB */
-		case 4096:
-			stride = 0xD;
-			break;
-		default:
-			printf("%s: Unable to calculate stride for ", __func__);
-			print_size((cap * (1 << 20)), " capacity\n");
-			break;
+		if (stride == (-1)) {
+			switch ((ch_cap[0] > ch_cap[1]) ?
+				ch_cap[0] : ch_cap[1]) {
+			case 256: /* 256MB + 128MB */
+				stride = 0;
+				break;
+			case 512: /* 512MB + 256MB */
+				stride = 1;
+				break;
+			case 1024:/* 1GB + 128MB/256MB/384MB/512MB/768MB */
+				stride = 2;
+				break;
+			case 2048: /* 2GB + 128MB/256MB/384MB/512MB/768MB/1GB */
+				stride = 3;
+				break;
+			default:
+				break;
+			}
 		}
+		if (stride == (-1))
+			goto error;
+	}
+	switch (stride) {
+	case 0xc:
+		printf("128B stride\n");
+		break;
+	case 5:
+	case 9:
+	case 0xd:
+	case 0x11:
+	case 0x19:
+		printf("256B stride\n");
+		break;
+	case 0xa:
+	case 0xe:
+	case 0x12:
+		printf("512B stride\n");
+		break;
+	case 0xf:
+		printf("4K stride\n");
+		break;
+	case 0x1f:
+		printf("32MB + 256B stride\n");
+		break;
+	default:
+		printf("no stride\n");
 	}
 
 	sdram_print_stride(stride);
 
 	return stride;
+error:
+	printf("Cap not support!\n");
+	return (-1);
 }
 
 static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
@@ -2491,39 +2921,13 @@ static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
 	params->ch[channel].cap_info.ddrconfig = 0;
 }
 
-static int pctl_init(struct dram_info *dram, struct rk3399_sdram_params *params)
-{
-	int channel;
-	int ret;
-
-	for (channel = 0; channel < 2; channel++) {
-		const struct chan_info *chan = &dram->chan[channel];
-		struct rk3399_cru *cru = dram->cru;
-		struct rk3399_ddr_publ_regs *publ = chan->publ;
-
-		phy_pctrl_reset(cru, channel);
-		phy_dll_bypass_set(publ, params->base.ddr_freq);
-
-		ret = pctl_cfg(dram, chan, channel, params);
-		if (ret < 0) {
-			printf("%s: pctl config failed\n", __func__);
-			return ret;
-		}
-
-		/* start to trigger initialization */
-		pctl_start(dram, channel);
-	}
-
-	return 0;
-}
-
 static int sdram_init(struct dram_info *dram,
 		      struct rk3399_sdram_params *params)
 {
 	unsigned char dramtype = params->base.dramtype;
 	unsigned int ddr_freq = params->base.ddr_freq;
 	int channel, ch, rank;
-	int ret;
+	u32 tmp, ret;
 
 	debug("Starting SDRAM initialization...\n");
 
@@ -2534,22 +2938,35 @@ static int sdram_init(struct dram_info *dram,
 		return -E2BIG;
 	}
 
+	/* detect rank */
 	for (ch = 0; ch < 2; ch++) {
 		params->ch[ch].cap_info.rank = 2;
 		for (rank = 2; rank != 0; rank--) {
-			ret = pctl_init(dram, params);
-			if (ret < 0) {
-				printf("%s: pctl init failed\n", __func__);
-				return ret;
+			for (channel = 0; channel < 2; channel++) {
+				const struct chan_info *chan =
+					&dram->chan[channel];
+				struct rk3399_cru *cru = dram->cru;
+				struct rk3399_ddr_publ_regs *publ = chan->publ;
+
+				phy_pctrl_reset(cru, channel);
+				phy_dll_bypass_set(publ, ddr_freq);
+				pctl_cfg(dram, chan, channel, params);
 			}
 
+			/* start to trigger initialization */
+			pctl_start(dram, params, 3);
+
 			/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
 			if (dramtype == LPDDR3)
 				udelay(10);
 
+			tmp = (rank == 2) ? 3 : 1;
+			dram_set_cs(&dram->chan[ch], tmp, 2048,
+				    params->base.dramtype);
 			params->ch[ch].cap_info.rank = rank;
 
-			ret = dram->ops->data_training(dram, ch, rank, params);
+			ret = dram->ops->data_training_first(dram, ch,
+							     rank, params);
 			if (!ret) {
 				debug("%s: data trained for rank %d, ch %d\n",
 				      __func__, rank, ch);
@@ -2563,38 +2980,37 @@ static int sdram_init(struct dram_info *dram,
 	params->base.num_channels = 0;
 	for (channel = 0; channel < 2; channel++) {
 		const struct chan_info *chan = &dram->chan[channel];
-		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
-		u8 training_flag = PI_FULL_TRAINING;
+		struct sdram_cap_info *cap_info =
+			&params->ch[channel].cap_info;
 
 		if (cap_info->rank == 0) {
-			clear_channel_params(params, channel);
+			clear_channel_params(params, 1);
 			continue;
 		} else {
 			params->base.num_channels++;
 		}
 
-		debug("Channel ");
-		debug(channel ? "1: " : "0: ");
+		printf("Channel ");
+		printf(channel ? "1: " : "0: ");
 
-		/* LPDDR3 should have write and read gate training */
-		if (params->base.dramtype == LPDDR3)
-			training_flag = PI_WRITE_LEVELING |
-					PI_READ_GATE_TRAINING;
+		if (channel == 0)
+			set_ddr_stride(dram->pmusgrf, 0x17);
+		else
+			set_ddr_stride(dram->pmusgrf, 0x18);
 
-		if (params->base.dramtype != LPDDR4) {
-			ret = data_training(dram, channel, params,
-					    training_flag);
-			if (!ret) {
-				debug("%s: data train failed for channel %d\n",
-				      __func__, ret);
-				continue;
-			}
+		if (dram_detect_cap(dram, params, channel)) {
+			printf("Cap error!\n");
+			continue;
 		}
 
 		sdram_print_ddr_info(cap_info, &params->base);
 		set_memory_map(chan, channel, params);
-		cap_info->ddrconfig = calculate_ddrconfig(params, channel);
-
+		cap_info->ddrconfig =
+			calculate_ddrconfig(params, channel);
+		if (-1 == cap_info->ddrconfig) {
+			printf("no ddrconfig find, Cap not support!\n");
+			continue;
+		}
 		set_ddrconfig(chan, params, channel, cap_info->ddrconfig);
 		set_cap_relate_config(chan, params, channel);
 	}
@@ -2608,7 +3024,8 @@ static int sdram_init(struct dram_info *dram,
 
 	params->base.stride = calculate_stride(params);
 	dram_all_config(dram, params);
-	dram->ops->set_rate(dram, params);
+
+	dram->ops->set_rate_index(dram, params);
 
 	debug("Finish SDRAM initialization...\n");
 	return 0;
@@ -2655,11 +3072,15 @@ static int conv_of_platdata(struct udevice *dev)
 
 static const struct sdram_rk3399_ops rk3399_ops = {
 #if !defined(CONFIG_RAM_RK3399_LPDDR4)
-	.data_training = default_data_training,
-	.set_rate = switch_to_phy_index1,
+	.data_training_first = data_training_first,
+	.set_rate_index = switch_to_phy_index1,
+	.modify_param = modify_param,
+	.get_phy_index_params = get_phy_index_params,
 #else
-	.data_training = lpddr4_mr_detect,
-	.set_rate = lpddr4_set_rate,
+	.data_training_first = lpddr4_mr_detect,
+	.set_rate_index = lpddr4_set_rate,
+	.modify_param = lpddr4_modify_param,
+	.get_phy_index_params = lpddr4_get_phy_index_params,
 #endif
 };
 
diff --git a/drivers/usb/phy/rockchip_usb2_phy.c b/drivers/usb/phy/rockchip_usb2_phy.c
index 16e899954a39974e6d57964c1d13ae2cde0db5bc..69e408b6c1bc61c55096824eb1aa06970acd3737 100644
--- a/drivers/usb/phy/rockchip_usb2_phy.c
+++ b/drivers/usb/phy/rockchip_usb2_phy.c
@@ -5,7 +5,6 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <linux/libfdt.h>
 
 #include "../gadget/dwc2_udc_otg_priv.h"
 
@@ -71,8 +70,8 @@ void otg_phy_init(struct dwc2_udc *dev)
 
 	for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) {
 		of_id = &rockchip_usb2_phy_dt_ids[i];
-		if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node,
-					      of_id->compatible) == 0) {
+		if (ofnode_device_is_compatible(pdata->phy_of_node,
+						of_id->compatible)){
 			phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data;
 			break;
 		}
diff --git a/include/configs/evb_px30.h b/include/configs/evb_px30.h
new file mode 100644
index 0000000000000000000000000000000000000000..e761c7c519602fd89ca3c82305d74c786e966c80
--- /dev/null
+++ b/include/configs/evb_px30.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __EVB_PX30_H
+#define __EVB_PX30_H
+
+#include <configs/px30_common.h>
+
+#define CONFIG_SYS_MMC_ENV_DEV 0
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
+
+#define CONFIG_SUPPORT_EMMC_RPMB
+
+#endif
diff --git a/include/configs/evb_rk3308.h b/include/configs/evb_rk3308.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d40606e4bd3d4103707cf8be718fcb4483736ac
--- /dev/null
+++ b/include/configs/evb_rk3308.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2018 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __EVB_RK3308_H
+#define __EVB_RK3308_H
+
+#include <configs/rk3308_common.h>
+
+#define CONFIG_SUPPORT_EMMC_RPMB
+#define CONFIG_SYS_MMC_ENV_DEV 0
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+			"stdout=serial,vidconsole\0" \
+			"stderr=serial,vidconsole\0"
+#undef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES            10
+
+#endif
diff --git a/include/configs/firefly_rk3308.h b/include/configs/firefly_rk3308.h
new file mode 100644
index 0000000000000000000000000000000000000000..2cc7b4a153f8dacca71a5cbf83267113f10c3c28
--- /dev/null
+++ b/include/configs/firefly_rk3308.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __FIREFLY_RK3308_H
+#define __FIREFLY_RK3308_H
+
+#include <configs/rk3308_common.h>
+
+#define CONFIG_SUPPORT_EMMC_RPMB
+#define CONFIG_SYS_MMC_ENV_DEV 0
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+			"stdout=serial,vidconsole\0" \
+			"stderr=serial,vidconsole\0"
+#undef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES            10
+
+#endif
diff --git a/include/configs/px30_common.h b/include/configs/px30_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6c70601dd019be99154a17257cbb49077e662d4
--- /dev/null
+++ b/include/configs/px30_common.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __CONFIG_PX30_COMMON_H
+#define __CONFIG_PX30_COMMON_H
+
+#include "rockchip-common.h"
+
+#define CONFIG_SYS_CBSIZE		1024
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+#define CONFIG_SYS_NS16550_MEM32
+
+#define CONFIG_ROCKCHIP_STIMER_BASE	0xff220020
+#define COUNTER_FREQUENCY		24000000
+
+/* FIXME: ff020000 is pmu_mem (10k), while ff0e0000 is regular int_mem */
+#define CONFIG_IRAM_BASE		0xff020000
+
+#define CONFIG_SYS_INIT_SP_ADDR		0x00400000
+#define CONFIG_SYS_LOAD_ADDR		0x00800800
+#define CONFIG_SPL_STACK		0x00400000
+#define CONFIG_SPL_MAX_SIZE		0x20000
+#define CONFIG_SPL_BSS_START_ADDR	0x4000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x4000
+#define CONFIG_SYS_BOOTM_LEN		(64 << 20)	/* 64M */
+
+#define GICD_BASE			0xff131000
+#define GICC_BASE			0xff132000
+
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* 64M */
+
+/* MMC/SD IP block */
+//#define CONFIG_BOUNCE_BUFFER
+
+#define CONFIG_SYS_SDRAM_BASE		0
+#define SDRAM_MAX_SIZE			0xff000000
+#define SDRAM_BANK_SIZE			(2UL << 30)
+
+#ifndef CONFIG_SPL_BUILD
+
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x00500000\0" \
+	"pxefile_addr_r=0x00600000\0" \
+	"fdt_addr_r=0x08300000\0" \
+	"kernel_addr_r=0x00280000\0" \
+	"kernel_addr_c=0x03e80000\0" \
+	"ramdisk_addr_r=0x0a200000\0"
+
+#include <config_distro_bootcmd.h>
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
+	"partitions=" PARTS_DEFAULT \
+	ROCKCHIP_DEVICE_SETTINGS \
+	BOOTENV
+
+#endif
+
+#endif
diff --git a/include/configs/rk3308_common.h b/include/configs/rk3308_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..a67d3d7d1b748f470f3c6fb21be6020adaecd55d
--- /dev/null
+++ b/include/configs/rk3308_common.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __CONFIG_RK3308_COMMON_H
+#define __CONFIG_RK3308_COMMON_H
+
+#include "rockchip-common.h"
+
+#define CONFIG_SYS_CBSIZE		1024
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_NAND_PAGE_SIZE	2048
+#define CONFIG_SYS_NAND_PAGE_COUNT	64
+#define CONFIG_SYS_NAND_SIZE		(256 * 1024 * 1024)
+#define CONFIG_SPL_MAX_SIZE		0x20000
+#define CONFIG_SPL_BSS_START_ADDR	0x00400000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x2000
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x8000
+
+#define CONFIG_SYS_NS16550_MEM32
+
+#define CONFIG_ROCKCHIP_STIMER_BASE	0xff1b00a0
+#define CONFIG_IRAM_BASE		0xfff80000
+#define CONFIG_SYS_INIT_SP_ADDR		0x00800000
+#define CONFIG_SYS_LOAD_ADDR		0x00C00800
+#define CONFIG_SPL_STACK		0x00400000
+#define CONFIG_SYS_BOOTM_LEN		(64 << 20)	/* 64M */
+
+#define COUNTER_FREQUENCY		24000000
+
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)	/* 64M */
+
+#define CONFIG_SYS_SDRAM_BASE		0
+#define SDRAM_MAX_SIZE			0xff000000
+#define SDRAM_BANK_SIZE			(2UL << 30)
+
+#ifndef CONFIG_SPL_BUILD
+
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x00500000\0" \
+	"pxefile_addr_r=0x00600000\0" \
+	"fdt_addr_r=0x01f00000\0" \
+	"kernel_addr_r=0x00680000\0" \
+	"ramdisk_addr_r=0x04000000\0"
+
+#include <config_distro_bootcmd.h>
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	"partitions=" PARTS_DEFAULT \
+	ROCKCHIP_DEVICE_SETTINGS \
+	BOOTENV
+
+#endif
+
+#endif
diff --git a/include/configs/rockpro64_rk3399.h b/include/configs/rockpro64_rk3399.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f52c1e4f601844b340f0ebdacd7ecc581984c65
--- /dev/null
+++ b/include/configs/rockpro64_rk3399.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Vasily Khoruzhick <anarsoul@gmail.com>
+ */
+
+#ifndef __ROCKPRO64_RK3399_H
+#define __ROCKPRO64_RK3399_H
+
+#include <configs/rk3399_common.h>
+
+#define CONFIG_SYS_MMC_ENV_DEV 0
+
+#define SDRAM_BANK_SIZE			(2UL << 30)
+
+#endif
diff --git a/include/configs/tinker_rk3288.h b/include/configs/tinker_rk3288.h
index 5adae68c91bbde65589b4b41e9d36cdb29357d0e..f8a55a2cec60d31b594b2c558b2dababb259cd2f 100644
--- a/include/configs/tinker_rk3288.h
+++ b/include/configs/tinker_rk3288.h
@@ -12,6 +12,7 @@
 #undef BOOT_TARGET_DEVICES
 
 #define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
 	func(MMC, mmc, 1) \
 	func(USB, usb, 0) \
 	func(PXE, pxe, na) \
diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5e59690b5f5d555027eb25b86c4c6be2fafba29
--- /dev/null
+++ b/include/dt-bindings/clock/px30-cru.h
@@ -0,0 +1,389 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+
+/* core clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_CPLL		3
+#define PLL_NPLL		4
+#define APLL_BOOST_H		5
+#define APLL_BOOST_L		6
+#define ARMCLK			7
+
+/* sclk gates (special clocks) */
+#define USB480M			14
+#define SCLK_PDM		15
+#define SCLK_I2S0_TX		16
+#define SCLK_I2S0_TX_OUT	17
+#define SCLK_I2S0_RX		18
+#define SCLK_I2S0_RX_OUT	19
+#define SCLK_I2S1		20
+#define SCLK_I2S1_OUT		21
+#define SCLK_I2S2		22
+#define SCLK_I2S2_OUT		23
+#define SCLK_UART1		24
+#define SCLK_UART2		25
+#define SCLK_UART3		26
+#define SCLK_UART4		27
+#define SCLK_UART5		28
+#define SCLK_I2C0		29
+#define SCLK_I2C1		30
+#define SCLK_I2C2		31
+#define SCLK_I2C3		32
+#define SCLK_I2C4		33
+#define SCLK_PWM0		34
+#define SCLK_PWM1		35
+#define SCLK_SPI0		36
+#define SCLK_SPI1		37
+#define SCLK_TIMER0		38
+#define SCLK_TIMER1		39
+#define SCLK_TIMER2		40
+#define SCLK_TIMER3		41
+#define SCLK_TIMER4		42
+#define SCLK_TIMER5		43
+#define SCLK_TSADC		44
+#define SCLK_SARADC		45
+#define SCLK_OTP		46
+#define SCLK_OTP_USR		47
+#define SCLK_CRYPTO		48
+#define SCLK_CRYPTO_APK		49
+#define SCLK_DDRC		50
+#define SCLK_ISP		51
+#define SCLK_CIF_OUT		52
+#define SCLK_RGA_CORE		53
+#define SCLK_VOPB_PWM		54
+#define SCLK_NANDC		55
+#define SCLK_SDIO		56
+#define SCLK_EMMC		57
+#define SCLK_SFC		58
+#define SCLK_SDMMC		59
+#define SCLK_OTG_ADP		60
+#define SCLK_GMAC_SRC		61
+#define SCLK_GMAC		62
+#define SCLK_GMAC_RX_TX		63
+#define SCLK_MAC_REF		64
+#define SCLK_MAC_REFOUT		65
+#define SCLK_MAC_OUT		66
+#define SCLK_SDMMC_DRV		67
+#define SCLK_SDMMC_SAMPLE	68
+#define SCLK_SDIO_DRV		69
+#define SCLK_SDIO_SAMPLE	70
+#define SCLK_EMMC_DRV		71
+#define SCLK_EMMC_SAMPLE	72
+#define SCLK_GPU		73
+#define SCLK_PVTM		74
+#define SCLK_CORE_VPU		75
+#define SCLK_GMAC_RMII		76
+#define SCLK_UART2_SRC		77
+#define SCLK_NANDC_DIV		78
+#define SCLK_NANDC_DIV50	79
+#define SCLK_SDIO_DIV		80
+#define SCLK_SDIO_DIV50		81
+#define SCLK_EMMC_DIV		82
+#define SCLK_EMMC_DIV50		83
+
+/* dclk gates */
+#define DCLK_VOPB		150
+#define DCLK_VOPL		151
+
+/* aclk gates */
+#define ACLK_GPU		170
+#define ACLK_BUS_PRE		171
+#define ACLK_CRYPTO		172
+#define ACLK_VI_PRE		173
+#define ACLK_VO_PRE		174
+#define ACLK_VPU		175
+#define ACLK_PERI_PRE		176
+#define ACLK_GMAC		178
+#define ACLK_CIF		179
+#define ACLK_ISP		180
+#define ACLK_VOPB		181
+#define ACLK_VOPL		182
+#define ACLK_RGA		183
+#define ACLK_GIC		184
+#define ACLK_DCF		186
+#define ACLK_DMAC		187
+
+/* hclk gates */
+#define HCLK_BUS_PRE		240
+#define HCLK_CRYPTO		241
+#define HCLK_VI_PRE		242
+#define HCLK_VO_PRE		243
+#define HCLK_VPU		244
+#define HCLK_PERI_PRE		245
+#define HCLK_MMC_NAND		246
+#define HCLK_SDMMC		247
+#define HCLK_USB		248
+#define HCLK_CIF		249
+#define HCLK_ISP		250
+#define HCLK_VOPB		251
+#define HCLK_VOPL		252
+#define HCLK_RGA		253
+#define HCLK_NANDC		254
+#define HCLK_SDIO		255
+#define HCLK_EMMC		256
+#define HCLK_SFC		257
+#define HCLK_OTG		258
+#define HCLK_HOST		259
+#define HCLK_HOST_ARB		260
+#define HCLK_PDM		261
+#define HCLK_I2S0		262
+#define HCLK_I2S1		263
+#define HCLK_I2S2		264
+
+/* pclk gates */
+#define PCLK_BUS_PRE		320
+#define PCLK_DDR		321
+#define PCLK_VO_PRE		322
+#define PCLK_GMAC		323
+#define PCLK_MIPI_DSI		324
+#define PCLK_MIPIDSIPHY		325
+#define PCLK_MIPICSIPHY		326
+#define PCLK_USB_GRF		327
+#define PCLK_DCF		328
+#define PCLK_UART1		329
+#define PCLK_UART2		330
+#define PCLK_UART3		331
+#define PCLK_UART4		332
+#define PCLK_UART5		333
+#define PCLK_I2C0		334
+#define PCLK_I2C1		335
+#define PCLK_I2C2		336
+#define PCLK_I2C3		337
+#define PCLK_I2C4		338
+#define PCLK_PWM0		339
+#define PCLK_PWM1		340
+#define PCLK_SPI0		341
+#define PCLK_SPI1		342
+#define PCLK_SARADC		343
+#define PCLK_TSADC		344
+#define PCLK_TIMER		345
+#define PCLK_OTP_NS		346
+#define PCLK_WDT_NS		347
+#define PCLK_GPIO1		348
+#define PCLK_GPIO2		349
+#define PCLK_GPIO3		350
+#define PCLK_ISP		351
+#define PCLK_CIF		352
+#define PCLK_OTP_PHY		353
+
+#define CLK_NR_CLKS		(PCLK_OTP_PHY + 1)
+
+/* pmu-clocks indices */
+
+#define PLL_GPLL		1
+
+#define SCLK_RTC32K_PMU		4
+#define SCLK_WIFI_PMU		5
+#define SCLK_UART0_PMU		6
+#define SCLK_PVTM_PMU		7
+#define PCLK_PMU_PRE		8
+#define SCLK_REF24M_PMU		9
+#define SCLK_USBPHY_REF		10
+#define SCLK_MIPIDSIPHY_REF	11
+
+#define XIN24M_DIV		12
+
+#define PCLK_GPIO0_PMU		20
+#define PCLK_UART0_PMU		21
+
+#define CLKPMU_NR_CLKS		(PCLK_UART0_PMU + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0_PO		0
+#define SRST_CORE1_PO		1
+#define SRST_CORE2_PO		2
+#define SRST_CORE3_PO		3
+#define SRST_CORE0		4
+#define SRST_CORE1		5
+#define SRST_CORE2		6
+#define SRST_CORE3		7
+#define SRST_CORE0_DBG		8
+#define SRST_CORE1_DBG		9
+#define SRST_CORE2_DBG		10
+#define SRST_CORE3_DBG		11
+#define SRST_TOPDBG		12
+#define SRST_CORE_NOC		13
+#define SRST_STRC_A		14
+#define SRST_L2C		15
+
+#define SRST_DAP		16
+#define SRST_CORE_PVTM		17
+#define SRST_GPU		18
+#define SRST_GPU_NIU		19
+#define SRST_UPCTL2		20
+#define SRST_UPCTL2_A		21
+#define SRST_UPCTL2_P		22
+#define SRST_MSCH		23
+#define SRST_MSCH_P		24
+#define SRST_DDRMON_P		25
+#define SRST_DDRSTDBY_P		26
+#define SRST_DDRSTDBY		27
+#define SRST_DDRGRF_p		28
+#define SRST_AXI_SPLIT_A	29
+#define SRST_AXI_CMD_A		30
+#define SRST_AXI_CMD_P		31
+
+#define SRST_DDRPHY		32
+#define SRST_DDRPHYDIV		33
+#define SRST_DDRPHY_P		34
+#define SRST_VPU_A		36
+#define SRST_VPU_NIU_A		37
+#define SRST_VPU_H		38
+#define SRST_VPU_NIU_H		39
+#define SRST_VI_NIU_A		40
+#define SRST_VI_NIU_H		41
+#define SRST_ISP_H		42
+#define SRST_ISP		43
+#define SRST_CIF_A		44
+#define SRST_CIF_H		45
+#define SRST_CIF_PCLKIN		46
+#define SRST_MIPICSIPHY_P	47
+
+#define SRST_VO_NIU_A		48
+#define SRST_VO_NIU_H		49
+#define SRST_VO_NIU_P		50
+#define SRST_VOPB_A		51
+#define SRST_VOPB_H		52
+#define SRST_VOPB		53
+#define SRST_PWM_VOPB		54
+#define SRST_VOPL_A		55
+#define SRST_VOPL_H		56
+#define SRST_VOPL		57
+#define SRST_RGA_A		58
+#define SRST_RGA_H		59
+#define SRST_RGA		60
+#define SRST_MIPIDSI_HOST_P	61
+#define SRST_MIPIDSIPHY_P	62
+#define SRST_VPU_CORE		63
+
+#define SRST_PERI_NIU_A		64
+#define SRST_USB_NIU_H		65
+#define SRST_USB2OTG_H		66
+#define SRST_USB2OTG		67
+#define SRST_USB2OTG_ADP	68
+#define SRST_USB2HOST_H		69
+#define SRST_USB2HOST_ARB_H	70
+#define SRST_USB2HOST_AUX_H	71
+#define SRST_USB2HOST_EHCI	72
+#define SRST_USB2HOST		73
+#define SRST_USBPHYPOR		74
+#define SRST_USBPHY_OTG_PORT	75
+#define SRST_USBPHY_HOST_PORT	76
+#define SRST_USBPHY_GRF		77
+#define SRST_CPU_BOOST_P	78
+#define SRST_CPU_BOOST		79
+
+#define SRST_MMC_NAND_NIU_H	80
+#define SRST_SDIO_H		81
+#define SRST_EMMC_H		82
+#define SRST_SFC_H		83
+#define SRST_SFC		84
+#define SRST_SDCARD_NIU_H	85
+#define SRST_SDMMC_H		86
+#define SRST_NANDC_H		89
+#define SRST_NANDC		90
+#define SRST_GMAC_NIU_A		92
+#define SRST_GMAC_NIU_P		93
+#define SRST_GMAC_A		94
+
+#define SRST_PMU_NIU_P		96
+#define SRST_PMU_SGRF_P		97
+#define SRST_PMU_GRF_P		98
+#define SRST_PMU		99
+#define SRST_PMU_MEM_P		100
+#define SRST_PMU_GPIO0_P	101
+#define SRST_PMU_UART0_P	102
+#define SRST_PMU_CRU_P		103
+#define SRST_PMU_PVTM		104
+#define SRST_PMU_UART		105
+#define SRST_PMU_NIU_H		106
+#define SRST_PMU_DDR_FAIL_SAVE	107
+#define SRST_PMU_CORE_PERF_A	108
+#define SRST_PMU_CORE_GRF_P	109
+#define SRST_PMU_GPU_PERF_A	110
+#define SRST_PMU_GPU_GRF_P	111
+
+#define SRST_CRYPTO_NIU_A	112
+#define SRST_CRYPTO_NIU_H	113
+#define SRST_CRYPTO_A		114
+#define SRST_CRYPTO_H		115
+#define SRST_CRYPTO		116
+#define SRST_CRYPTO_APK		117
+#define SRST_BUS_NIU_H		120
+#define SRST_USB_NIU_P		121
+#define SRST_BUS_TOP_NIU_P	122
+#define SRST_INTMEM_A		123
+#define SRST_GIC_A		124
+#define SRST_ROM_H		126
+#define SRST_DCF_A		127
+
+#define SRST_DCF_P		128
+#define SRST_PDM_H		129
+#define SRST_PDM		130
+#define SRST_I2S0_H		131
+#define SRST_I2S0_TX		132
+#define SRST_I2S1_H		133
+#define SRST_I2S1		134
+#define SRST_I2S2_H		135
+#define SRST_I2S2		136
+#define SRST_UART1_P		137
+#define SRST_UART1		138
+#define SRST_UART2_P		139
+#define SRST_UART2		140
+#define SRST_UART3_P		141
+#define SRST_UART3		142
+#define SRST_UART4_P		143
+
+#define SRST_UART4		144
+#define SRST_UART5_P		145
+#define SRST_UART5		146
+#define SRST_I2C0_P		147
+#define SRST_I2C0		148
+#define SRST_I2C1_P		149
+#define SRST_I2C1		150
+#define SRST_I2C2_P		151
+#define SRST_I2C2		152
+#define SRST_I2C3_P		153
+#define SRST_I2C3		154
+#define SRST_PWM0_P		157
+#define SRST_PWM0		158
+#define SRST_PWM1_P		159
+
+#define SRST_PWM1		160
+#define SRST_SPI0_P		161
+#define SRST_SPI0		162
+#define SRST_SPI1_P		163
+#define SRST_SPI1		164
+#define SRST_SARADC_P		165
+#define SRST_SARADC		166
+#define SRST_TSADC_P		167
+#define SRST_TSADC		168
+#define SRST_TIMER_P		169
+#define SRST_TIMER0		170
+#define SRST_TIMER1		171
+#define SRST_TIMER2		172
+#define SRST_TIMER3		173
+#define SRST_TIMER4		174
+#define SRST_TIMER5		175
+
+#define SRST_OTP_NS_P		176
+#define SRST_OTP_NS_SBPI	177
+#define SRST_OTP_NS_USR		178
+#define SRST_OTP_PHY_P		179
+#define SRST_OTP_PHY		180
+#define SRST_WDT_NS_P		181
+#define SRST_GPIO1_P		182
+#define SRST_GPIO2_P		183
+#define SRST_GPIO3_P		184
+#define SRST_SGRF_P		185
+#define SRST_GRF_P		186
+#define SRST_I2S0_RX		191
+
+#endif
diff --git a/include/dt-bindings/clock/rk3308-cru.h b/include/dt-bindings/clock/rk3308-cru.h
new file mode 100644
index 0000000000000000000000000000000000000000..d97840f9ee2e15e31cc2f93dcde4afe3c4a1e9e2
--- /dev/null
+++ b/include/dt-bindings/clock/rk3308-cru.h
@@ -0,0 +1,387 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+
+/* core clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_VPLL0		3
+#define PLL_VPLL1		4
+#define ARMCLK			5
+
+/* sclk (special clocks) */
+#define USB480M			14
+#define SCLK_RTC32K		15
+#define SCLK_PVTM_CORE		16
+#define SCLK_UART0		17
+#define SCLK_UART1		18
+#define SCLK_UART2		19
+#define SCLK_UART3		20
+#define SCLK_UART4		21
+#define SCLK_I2C0		22
+#define SCLK_I2C1		23
+#define SCLK_I2C2		24
+#define SCLK_I2C3		25
+#define SCLK_PWM0		26
+#define SCLK_SPI0		27
+#define SCLK_SPI1		28
+#define SCLK_SPI2		29
+#define SCLK_TIMER0		30
+#define SCLK_TIMER1		31
+#define SCLK_TIMER2		32
+#define SCLK_TIMER3		33
+#define SCLK_TIMER4		34
+#define SCLK_TIMER5		35
+#define SCLK_TSADC		36
+#define SCLK_SARADC		37
+#define SCLK_OTP		38
+#define SCLK_OTP_USR		39
+#define SCLK_CPU_BOOST		40
+#define SCLK_CRYPTO		41
+#define SCLK_CRYPTO_APK		42
+#define SCLK_NANDC_DIV		43
+#define SCLK_NANDC_DIV50	44
+#define SCLK_NANDC		45
+#define SCLK_SDMMC_DIV		46
+#define SCLK_SDMMC_DIV50	47
+#define SCLK_SDMMC		48
+#define SCLK_SDMMC_DRV		49
+#define SCLK_SDMMC_SAMPLE	50
+#define SCLK_SDIO_DIV		51
+#define SCLK_SDIO_DIV50		52
+#define SCLK_SDIO		53
+#define SCLK_SDIO_DRV		54
+#define SCLK_SDIO_SAMPLE	55
+#define SCLK_EMMC_DIV		56
+#define SCLK_EMMC_DIV50		57
+#define SCLK_EMMC		58
+#define SCLK_EMMC_DRV		59
+#define SCLK_EMMC_SAMPLE	60
+#define SCLK_SFC		61
+#define SCLK_OTG_ADP		62
+#define SCLK_MAC_SRC		63
+#define SCLK_MAC		64
+#define SCLK_MAC_REF		65
+#define SCLK_MAC_RX_TX		66
+#define SCLK_MAC_RMII		67
+#define SCLK_DDR_MON_TIMER	68
+#define SCLK_DDR_MON		69
+#define SCLK_DDRCLK		70
+#define SCLK_PMU		71
+#define SCLK_USBPHY_REF		72
+#define SCLK_WIFI		73
+#define SCLK_PVTM_PMU		74
+#define SCLK_PDM		75
+#define SCLK_I2S0_8CH_TX	76
+#define SCLK_I2S0_8CH_TX_OUT	77
+#define SCLK_I2S0_8CH_RX	78
+#define SCLK_I2S0_8CH_RX_OUT	79
+#define SCLK_I2S1_8CH_TX	80
+#define SCLK_I2S1_8CH_TX_OUT	81
+#define SCLK_I2S1_8CH_RX	82
+#define SCLK_I2S1_8CH_RX_OUT	83
+#define SCLK_I2S2_8CH_TX	84
+#define SCLK_I2S2_8CH_TX_OUT	85
+#define SCLK_I2S2_8CH_RX	86
+#define SCLK_I2S2_8CH_RX_OUT	87
+#define SCLK_I2S3_8CH_TX	88
+#define SCLK_I2S3_8CH_TX_OUT	89
+#define SCLK_I2S3_8CH_RX	90
+#define SCLK_I2S3_8CH_RX_OUT	91
+#define SCLK_I2S0_2CH		92
+#define SCLK_I2S0_2CH_OUT	93
+#define SCLK_I2S1_2CH		94
+#define SCLK_I2S1_2CH_OUT	95
+#define SCLK_SPDIF_TX_DIV	96
+#define SCLK_SPDIF_TX_DIV50	97
+#define SCLK_SPDIF_TX		98
+#define SCLK_SPDIF_RX_DIV	99
+#define SCLK_SPDIF_RX_DIV50	100
+#define SCLK_SPDIF_RX		101
+#define SCLK_I2S0_8CH_TX_MUX	102
+#define SCLK_I2S0_8CH_RX_MUX	103
+#define SCLK_I2S1_8CH_TX_MUX	104
+#define SCLK_I2S1_8CH_RX_MUX	105
+#define SCLK_I2S2_8CH_TX_MUX	106
+#define SCLK_I2S2_8CH_RX_MUX	107
+#define SCLK_I2S3_8CH_TX_MUX	108
+#define SCLK_I2S3_8CH_RX_MUX	109
+#define SCLK_I2S0_8CH_TX_SRC	110
+#define SCLK_I2S0_8CH_RX_SRC	111
+#define SCLK_I2S1_8CH_TX_SRC	112
+#define SCLK_I2S1_8CH_RX_SRC	113
+#define SCLK_I2S2_8CH_TX_SRC	114
+#define SCLK_I2S2_8CH_RX_SRC	115
+#define SCLK_I2S3_8CH_TX_SRC	116
+#define SCLK_I2S3_8CH_RX_SRC	117
+#define SCLK_I2S0_2CH_SRC	118
+#define SCLK_I2S1_2CH_SRC	119
+#define SCLK_PWM1		120
+#define SCLK_PWM2		121
+#define SCLK_OWIRE		122
+
+/* dclk */
+#define DCLK_VOP		125
+
+/* aclk */
+#define ACLK_BUS_SRC		130
+#define ACLK_BUS		131
+#define ACLK_PERI_SRC		132
+#define ACLK_PERI		133
+#define ACLK_MAC		134
+#define ACLK_CRYPTO		135
+#define ACLK_VOP		136
+#define ACLK_GIC		137
+#define ACLK_DMAC0		138
+#define ACLK_DMAC1		139
+
+/* hclk */
+#define HCLK_BUS		150
+#define HCLK_PERI		151
+#define HCLK_AUDIO		152
+#define HCLK_NANDC		153
+#define HCLK_SDMMC		154
+#define HCLK_SDIO		155
+#define HCLK_EMMC		156
+#define HCLK_SFC		157
+#define HCLK_OTG		158
+#define HCLK_HOST		159
+#define HCLK_HOST_ARB		160
+#define HCLK_PDM		161
+#define HCLK_SPDIFTX		162
+#define HCLK_SPDIFRX		163
+#define HCLK_I2S0_8CH		164
+#define HCLK_I2S1_8CH		165
+#define HCLK_I2S2_8CH		166
+#define HCLK_I2S3_8CH		167
+#define HCLK_I2S0_2CH		168
+#define HCLK_I2S1_2CH		169
+#define HCLK_VAD		170
+#define HCLK_CRYPTO		171
+#define HCLK_VOP		172
+
+/* pclk */
+#define PCLK_BUS		190
+#define PCLK_DDR		191
+#define PCLK_PERI		192
+#define PCLK_PMU		193
+#define PCLK_AUDIO		194
+#define PCLK_MAC		195
+#define PCLK_ACODEC		196
+#define PCLK_UART0		197
+#define PCLK_UART1		198
+#define PCLK_UART2		199
+#define PCLK_UART3		200
+#define PCLK_UART4		201
+#define PCLK_I2C0		202
+#define PCLK_I2C1		203
+#define PCLK_I2C2		204
+#define PCLK_I2C3		205
+#define PCLK_PWM0		206
+#define PCLK_SPI0		207
+#define PCLK_SPI1		208
+#define PCLK_SPI2		209
+#define PCLK_SARADC		210
+#define PCLK_TSADC		211
+#define PCLK_TIMER		212
+#define PCLK_OTP_NS		213
+#define PCLK_WDT		214
+#define PCLK_GPIO0		215
+#define PCLK_GPIO1		216
+#define PCLK_GPIO2		217
+#define PCLK_GPIO3		218
+#define PCLK_GPIO4		219
+#define PCLK_SGRF		220
+#define PCLK_GRF		221
+#define PCLK_USBSD_DET		222
+#define PCLK_DDR_UPCTL		223
+#define PCLK_DDR_MON		224
+#define PCLK_DDRPHY		225
+#define PCLK_DDR_STDBY		226
+#define PCLK_USB_GRF		227
+#define PCLK_CRU		228
+#define PCLK_OTP_PHY		229
+#define PCLK_CPU_BOOST		230
+#define PCLK_PWM1		231
+#define PCLK_PWM2		232
+#define PCLK_CAN		233
+#define PCLK_OWIRE		234
+
+#define CLK_NR_CLKS		(PCLK_OWIRE + 1)
+
+/* soft-reset indices */
+
+/* cru_softrst_con0 */
+#define SRST_CORE0_PO		0
+#define SRST_CORE1_PO		1
+#define SRST_CORE2_PO		2
+#define SRST_CORE3_PO		3
+#define SRST_CORE0		4
+#define SRST_CORE1		5
+#define SRST_CORE2		6
+#define SRST_CORE3		7
+#define SRST_CORE0_DBG		8
+#define SRST_CORE1_DBG		9
+#define SRST_CORE2_DBG		10
+#define SRST_CORE3_DBG		11
+#define SRST_TOPDBG		12
+#define SRST_CORE_NOC		13
+#define SRST_STRC_A		14
+#define SRST_L2C		15
+
+/* cru_softrst_con1 */
+#define SRST_DAP		16
+#define SRST_CORE_PVTM		17
+#define SRST_CORE_PRF		18
+#define SRST_CORE_GRF		19
+#define SRST_DDRUPCTL		20
+#define SRST_DDRUPCTL_P		22
+#define SRST_MSCH		23
+#define SRST_DDRMON_P		25
+#define SRST_DDRSTDBY_P		26
+#define SRST_DDRSTDBY		27
+#define SRST_DDRPHY		28
+#define SRST_DDRPHY_DIV		29
+#define SRST_DDRPHY_P		30
+
+/* cru_softrst_con2 */
+#define SRST_BUS_NIU_H		32
+#define SRST_USB_NIU_P		33
+#define SRST_CRYPTO_A		34
+#define SRST_CRYPTO_H		35
+#define SRST_CRYPTO		36
+#define SRST_CRYPTO_APK		37
+#define SRST_VOP_A		38
+#define SRST_VOP_H		39
+#define SRST_VOP_D		40
+#define SRST_INTMEM_A		41
+#define SRST_ROM_H		42
+#define SRST_GIC_A		43
+#define SRST_UART0_P		44
+#define SRST_UART0		45
+#define SRST_UART1_P		46
+#define SRST_UART1		47
+
+/* cru_softrst_con3 */
+#define SRST_UART2_P		48
+#define SRST_UART2		49
+#define SRST_UART3_P		50
+#define SRST_UART3		51
+#define SRST_UART4_P		52
+#define SRST_UART4		53
+#define SRST_I2C0_P		54
+#define SRST_I2C0		55
+#define SRST_I2C1_P		56
+#define SRST_I2C1		57
+#define SRST_I2C2_P		58
+#define SRST_I2C2		59
+#define SRST_I2C3_P		60
+#define SRST_I2C3		61
+#define SRST_PWM0_P		62
+#define SRST_PWM0		63
+
+/* cru_softrst_con4 */
+#define SRST_SPI0_P		64
+#define SRST_SPI0		65
+#define SRST_SPI1_P		66
+#define SRST_SPI1		67
+#define SRST_SPI2_P		68
+#define SRST_SPI2		69
+#define SRST_SARADC_P		70
+#define SRST_TSADC_P		71
+#define SRST_TSADC		72
+#define SRST_TIMER0_P		73
+#define SRST_TIMER0		74
+#define SRST_TIMER1		75
+#define SRST_TIMER2		76
+#define SRST_TIMER3		77
+#define SRST_TIMER4		78
+#define SRST_TIMER5		79
+
+/* cru_softrst_con5 */
+#define SRST_OTP_NS_P		80
+#define SRST_OTP_NS_SBPI	81
+#define SRST_OTP_NS_USR		82
+#define SRST_OTP_PHY_P		83
+#define SRST_OTP_PHY		84
+#define SRST_GPIO0_P		86
+#define SRST_GPIO1_P		87
+#define SRST_GPIO2_P		88
+#define SRST_GPIO3_P		89
+#define SRST_GPIO4_P		90
+#define SRST_GRF_P		91
+#define SRST_USBSD_DET_P	92
+#define SRST_PMU		93
+#define SRST_PMU_PVTM		94
+#define SRST_USB_GRF_P		95
+
+/* cru_softrst_con6 */
+#define SRST_CPU_BOOST		96
+#define SRST_CPU_BOOST_P	97
+#define SRST_PWM1_P		98
+#define SRST_PWM1		99
+#define SRST_PWM2_P		100
+#define SRST_PWM2		101
+#define SRST_PERI_NIU_A		104
+#define SRST_PERI_NIU_H		105
+#define SRST_PERI_NIU_p		106
+#define SRST_USB2OTG_H		107
+#define SRST_USB2OTG		108
+#define SRST_USB2OTG_ADP	109
+#define SRST_USB2HOST_H		110
+#define SRST_USB2HOST_ARB_H	111
+
+/* cru_softrst_con7 */
+#define SRST_USB2HOST_AUX_H	112
+#define SRST_USB2HOST_EHCI	113
+#define SRST_USB2HOST		114
+#define SRST_USBPHYPOR		115
+#define SRST_UTMI0		116
+#define SRST_UTMI1		117
+#define SRST_SDIO_H		118
+#define SRST_EMMC_H		119
+#define SRST_SFC_H		120
+#define SRST_SFC		121
+#define SRST_SD_H		122
+#define SRST_NANDC_H		123
+#define SRST_NANDC_N		124
+#define SRST_MAC_A		125
+#define SRST_CAN_P		126
+#define SRST_OWIRE_P		127
+
+/* cru_softrst_con8 */
+#define SRST_AUDIO_NIU_H	128
+#define SRST_AUDIO_NIU_P	129
+#define SRST_PDM_H		130
+#define SRST_PDM_M		131
+#define SRST_SPDIFTX_H		132
+#define SRST_SPDIFTX_M		133
+#define SRST_SPDIFRX_H		134
+#define SRST_SPDIFRX_M		135
+#define SRST_I2S0_8CH_H		136
+#define SRST_I2S0_8CH_TX_M	137
+#define SRST_I2S0_8CH_RX_M	138
+#define SRST_I2S1_8CH_H		139
+#define SRST_I2S1_8CH_TX_M	140
+#define SRST_I2S1_8CH_RX_M	141
+#define SRST_I2S2_8CH_H		142
+#define SRST_I2S2_8CH_TX_M	143
+
+/* cru_softrst_con9 */
+#define SRST_I2S2_8CH_RX_M	144
+#define SRST_I2S3_8CH_H		145
+#define SRST_I2S3_8CH_TX_M	146
+#define SRST_I2S3_8CH_RX_M	147
+#define SRST_I2S0_2CH_H		148
+#define SRST_I2S0_2CH_M		149
+#define SRST_I2S1_2CH_H		150
+#define SRST_I2S1_2CH_M		151
+#define SRST_VAD_H		152
+#define SRST_ACODEC_P		153
+
+#endif
diff --git a/include/dt-bindings/power/px30-power.h b/include/dt-bindings/power/px30-power.h
new file mode 100644
index 0000000000000000000000000000000000000000..30917a99ad208fcf82146b661335b5670659ad94
--- /dev/null
+++ b/include/dt-bindings/power/px30-power.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_POWER_PX30_POWER_H__
+#define __DT_BINDINGS_POWER_PX30_POWER_H__
+
+/* VD_CORE */
+#define PX30_PD_A35_0		0
+#define PX30_PD_A35_1		1
+#define PX30_PD_A35_2		2
+#define PX30_PD_A35_3		3
+#define PX30_PD_SCU		4
+
+/* VD_LOGIC */
+#define PX30_PD_USB		5
+#define PX30_PD_DDR		6
+#define PX30_PD_SDCARD		7
+#define PX30_PD_CRYPTO		8
+#define PX30_PD_GMAC		9
+#define PX30_PD_MMC_NAND	10
+#define PX30_PD_VPU		11
+#define PX30_PD_VO		12
+#define PX30_PD_VI		13
+#define PX30_PD_GPU		14
+
+/* VD_PMU */
+#define PX30_PD_PMU		15
+
+#endif
diff --git a/include/dt-bindings/soc/rockchip,boot-mode.h b/include/dt-bindings/soc/rockchip,boot-mode.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b0914c0989da653110b700fa90871e3f0046fb8
--- /dev/null
+++ b/include/dt-bindings/soc/rockchip,boot-mode.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ROCKCHIP_BOOT_MODE_H
+#define __ROCKCHIP_BOOT_MODE_H
+
+/*high 24 bits is tag, low 8 bits is type*/
+#define REBOOT_FLAG		0x5242C300
+/* normal boot */
+#define BOOT_NORMAL		(REBOOT_FLAG + 0)
+/* enter bootloader rockusb mode */
+#define BOOT_BL_DOWNLOAD	(REBOOT_FLAG + 1)
+/* enter recovery */
+#define BOOT_RECOVERY		(REBOOT_FLAG + 3)
+ /* enter fastboot mode */
+#define BOOT_FASTBOOT		(REBOOT_FLAG + 9)
+
+#endif
diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h
index a6c12212a9b0cabe4a86dc47114b4d6e33b8fceb..a2af381a6677d06f5cc85cfc96fad178980bc504 100644
--- a/include/usb/dwc2_udc.h
+++ b/include/usb/dwc2_udc.h
@@ -8,12 +8,14 @@
 #ifndef __DWC2_USB_GADGET
 #define __DWC2_USB_GADGET
 
+#include <dm/ofnode.h>
+
 #define PHY0_SLEEP              (1 << 5)
 #define DWC2_MAX_HW_ENDPOINTS	16
 
 struct dwc2_plat_otg_data {
 	void		*priv;
-	int		phy_of_node;
+	ofnode		phy_of_node;
 	int		(*phy_control)(int on);
 	uintptr_t	regs_phy;
 	uintptr_t	regs_otg;
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index f8ce7da2d281438066a2dd690be8510f9ed32846..314b02ba07dbee88e71aa9eeb352e9f6f5f70e30 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -71,7 +71,11 @@ HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makef
 libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
 libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 
+ifeq ($(CONFIG_TPL_BUILD),y)
+libs-$(CONFIG_TPL_FRAMEWORK) += common/spl/
+else
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
+endif
 libs-y += common/init/
 
 # Special handling for a few options which support SPL/TPL
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 831c2ad8207ac2ca2513cccb69f879769854d518..0d908daee8080c0e9c107c90e4234e43f372299a 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -67,11 +67,13 @@ struct spl_info {
 };
 
 static struct spl_info spl_infos[] = {
+	{ "px30", "RK33", 0x2800, false },
 	{ "rk3036", "RK30", 0x1000, false },
 	{ "rk3128", "RK31", 0x1800, false },
 	{ "rk3188", "RK31", 0x8000 - 0x800, true },
 	{ "rk322x", "RK32", 0x8000 - 0x1000, false },
 	{ "rk3288", "RK32", 0x8000, false },
+	{ "rk3308", "RK33", 0x40000 - 0x1000, false},
 	{ "rk3328", "RK32", 0x8000 - 0x1000, false },
 	{ "rk3368", "RK33", 0x8000 - 0x1000, false },
 	{ "rk3399", "RK33", 0x30000 - 0x2000, false },