Merge tag 'u-boot-rockchip-20230421' of https://source.denx.de/u-boot/custodians/u-boot-rockchip

- Add rk3588 evb support;
- Update pinctrl for rk3568 and rk3588;
- Update rk3288 dts;
- Update mmc support for rk3568 and rk3588;
- Add rng support for rk3588;
- Add DSI support for rk3568;
- Some other misc fixes in dts, config, driver;
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 2f69539..3385948 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -171,6 +171,7 @@
 
 dtb-$(CONFIG_ROCKCHIP_RK3588) += \
 	rk3588-edgeble-neu6a-io.dtb \
+	rk3588-evb1-v10.dtb \
 	rk3588-rock-5b.dtb
 
 dtb-$(CONFIG_ROCKCHIP_RV1108) += \
diff --git a/arch/arm/dts/rk3066a-mk808.dts b/arch/arm/dts/rk3066a-mk808.dts
index 667d57a..06790f0 100644
--- a/arch/arm/dts/rk3066a-mk808.dts
+++ b/arch/arm/dts/rk3066a-mk808.dts
@@ -32,7 +32,7 @@
 		keyup-threshold-microvolt = <2500000>;
 		poll-interval = <100>;
 
-		recovery {
+		button-recovery {
 			label = "recovery";
 			linux,code = <KEY_VENDOR>;
 			press-threshold-microvolt = <0>;
@@ -157,7 +157,32 @@
 	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
 	pinctrl-names = "default";
 	vmmc-supply = <&vcc_wifi>;
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
+
+	brcmf: wifi@1 {
+		compatible = "brcm,bcm4329-fmac";
+		reg = <1>;
+	};
+};
+
+&nfc {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	nand@0 {
+		reg = <0>;
+		label = "rk-nand";
+		nand-bus-width = <8>;
+		nand-ecc-mode = "hw";
+		nand-ecc-step-size = <1024>;
+		nand-ecc-strength = <40>;
+		nand-is-boot-medium;
+		rockchip,boot-blks = <8>;
+		rockchip,boot-ecc-strength = <24>;
+	};
 };
 
 &pinctrl {
diff --git a/arch/arm/dts/rk3066a-u-boot.dtsi b/arch/arm/dts/rk3066a-u-boot.dtsi
index bc6e609..06f405c 100644
--- a/arch/arm/dts/rk3066a-u-boot.dtsi
+++ b/arch/arm/dts/rk3066a-u-boot.dtsi
@@ -2,3 +2,28 @@
 
 #include "rockchip-u-boot.dtsi"
 #include "rk3xxx-u-boot.dtsi"
+
+&gpio0 {
+	gpio-ranges = <&pinctrl 0 0 32>;
+};
+
+&gpio1 {
+	gpio-ranges = <&pinctrl 0 32 32>;
+};
+
+&gpio2 {
+	gpio-ranges = <&pinctrl 0 64 32>;
+};
+
+&gpio3 {
+	gpio-ranges = <&pinctrl 0 96 32>;
+};
+
+&gpio4 {
+	gpio-ranges = <&pinctrl 0 128 32>;
+};
+
+&gpio6 {
+	status = "disabled";
+};
+
diff --git a/arch/arm/dts/rk3066a.dtsi b/arch/arm/dts/rk3066a.dtsi
index c25b969..de9915d 100644
--- a/arch/arm/dts/rk3066a.dtsi
+++ b/arch/arm/dts/rk3066a.dtsi
@@ -202,8 +202,9 @@
 	cru: clock-controller@20000000 {
 		compatible = "rockchip,rk3066a-cru";
 		reg = <0x20000000 0x1000>;
+		clocks = <&xin24m>;
+		clock-names = "xin24m";
 		rockchip,grf = <&grf>;
-
 		#clock-cells = <1>;
 		#reset-cells = <1>;
 		assigned-clocks = <&cru PLL_CPLL>, <&cru PLL_GPLL>,
diff --git a/arch/arm/dts/rk3188-radxarock.dts b/arch/arm/dts/rk3188-radxarock.dts
index e7138a4..118deac 100644
--- a/arch/arm/dts/rk3188-radxarock.dts
+++ b/arch/arm/dts/rk3188-radxarock.dts
@@ -6,7 +6,6 @@
 /dts-v1/;
 #include <dt-bindings/input/input.h>
 #include "rk3188.dtsi"
-#include "rk3188-radxarock-u-boot.dtsi"
 
 / {
 	model = "Radxa Rock";
@@ -25,7 +24,7 @@
 		compatible = "gpio-keys";
 		autorepeat;
 
-		power {
+		key-power {
 			gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
@@ -72,7 +71,7 @@
 		#sound-dai-cells = <0>;
 	};
 
-	ir_recv: gpio-ir-receiver {
+	ir_recv: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
@@ -127,18 +126,21 @@
 };
 
 &emac {
-	status = "okay";
-
+	phy = <&phy0>;
+	phy-supply = <&vcc_rmii>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&phy_int>;
+	status = "okay";
 
-	phy = <&phy0>;
-	phy-supply = <&vcc_rmii>;
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-	phy0: ethernet-phy@0 {
-		reg = <0>;
-		interrupt-parent = <&gpio3>;
-		interrupts = <RK_PD2 IRQ_TYPE_LEVEL_LOW>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			interrupt-parent = <&gpio3>;
+			interrupts = <RK_PD2 IRQ_TYPE_LEVEL_LOW>;
+		};
 	};
 };
 
diff --git a/arch/arm/dts/rk3188-u-boot.dtsi b/arch/arm/dts/rk3188-u-boot.dtsi
index 735776c..176f9e6 100644
--- a/arch/arm/dts/rk3188-u-boot.dtsi
+++ b/arch/arm/dts/rk3188-u-boot.dtsi
@@ -12,6 +12,19 @@
 
 &gpio0 {
 	compatible = "rockchip,gpio-bank";
+	gpio-ranges = <&pinctrl 0 0 32>;
+};
+
+&gpio1 {
+	gpio-ranges = <&pinctrl 0 32 32>;
+};
+
+&gpio2 {
+	gpio-ranges = <&pinctrl 0 64 32>;
+};
+
+&gpio3 {
+	gpio-ranges = <&pinctrl 0 96 32>;
 };
 
 &pmu {
diff --git a/arch/arm/dts/rk3188.dtsi b/arch/arm/dts/rk3188.dtsi
index 9a80f83..44b54af 100644
--- a/arch/arm/dts/rk3188.dtsi
+++ b/arch/arm/dts/rk3188.dtsi
@@ -54,7 +54,7 @@
 		};
 	};
 
-	cpu0_opp_table: opp_table0 {
+	cpu0_opp_table: opp-table-0 {
 		compatible = "operating-points-v2";
 		opp-shared;
 
@@ -195,8 +195,9 @@
 	cru: clock-controller@20000000 {
 		compatible = "rockchip,rk3188-cru";
 		reg = <0x20000000 0x1000>;
+		clocks = <&xin24m>;
+		clock-names = "xin24m";
 		rockchip,grf = <&grf>;
-
 		#clock-cells = <1>;
 		#reset-cells = <1>;
 	};
@@ -223,7 +224,7 @@
 		#size-cells = <1>;
 		ranges;
 
-		gpio0: gpio0@2000a000 {
+		gpio0: gpio@2000a000 {
 			compatible = "rockchip,rk3188-gpio-bank0";
 			reg = <0x2000a000 0x100>;
 			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
@@ -236,7 +237,7 @@
 			#interrupt-cells = <2>;
 		};
 
-		gpio1: gpio1@2003c000 {
+		gpio1: gpio@2003c000 {
 			compatible = "rockchip,gpio-bank";
 			reg = <0x2003c000 0x100>;
 			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
@@ -249,7 +250,7 @@
 			#interrupt-cells = <2>;
 		};
 
-		gpio2: gpio2@2003e000 {
+		gpio2: gpio@2003e000 {
 			compatible = "rockchip,gpio-bank";
 			reg = <0x2003e000 0x100>;
 			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
@@ -262,7 +263,7 @@
 			#interrupt-cells = <2>;
 		};
 
-		gpio3: gpio3@20080000 {
+		gpio3: gpio@20080000 {
 			compatible = "rockchip,gpio-bank";
 			reg = <0x20080000 0x100>;
 			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
@@ -275,15 +276,15 @@
 			#interrupt-cells = <2>;
 		};
 
-		pcfg_pull_up: pcfg_pull_up {
+		pcfg_pull_up: pcfg-pull-up {
 			bias-pull-up;
 		};
 
-		pcfg_pull_down: pcfg_pull_down {
+		pcfg_pull_down: pcfg-pull-down {
 			bias-pull-down;
 		};
 
-		pcfg_pull_none: pcfg_pull_none {
+		pcfg_pull_none: pcfg-pull-none {
 			bias-disable;
 		};
 
@@ -378,7 +379,7 @@
 				rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
 			};
 
-			lcdc1_rgb24: ldcd1-rgb24 {
+			lcdc1_rgb24: lcdc1-rgb24 {
 				rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>,
 						<2 RK_PA1 1 &pcfg_pull_none>,
 						<2 RK_PA2 1 &pcfg_pull_none>,
@@ -606,7 +607,6 @@
 
 &global_timer {
 	interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
-	status = "disabled";
 };
 
 &local_timer {
@@ -641,6 +641,11 @@
 &grf {
 	compatible = "rockchip,rk3188-grf", "syscon", "simple-mfd";
 
+	io_domains: io-domains {
+		compatible = "rockchip,rk3188-io-voltage-domain";
+		status = "disabled";
+	};
+
 	usbphy: usbphy {
 		compatible = "rockchip,rk3188-usb-phy";
 		#address-cells = <1>;
diff --git a/arch/arm/dts/rk3288-miqi.dtsi b/arch/arm/dts/rk3288-miqi.dtsi
index cb80cbf..00c8613 100644
--- a/arch/arm/dts/rk3288-miqi.dtsi
+++ b/arch/arm/dts/rk3288-miqi.dtsi
@@ -18,21 +18,6 @@
 		clock-output-names = "ext_gmac";
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcca_33>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vcc_lan>;
-		gpio30-supply = <&vcc_io>;
-		gpio1830-supply = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vcc_18>;
-	};
-
-
 	leds {
 		compatible = "gpio-leds";
 
@@ -277,6 +262,18 @@
 	status = "okay";
 };
 
+&io_domains {
+	audio-supply = <&vcca_33>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vcc_lan>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vcc_18>;
+	status = "okay";
+};
+
 &pinctrl {
 	pcfg_output_high: pcfg-output-high {
 		output-high;
diff --git a/arch/arm/dts/rk3288-phycore-som.dtsi b/arch/arm/dts/rk3288-phycore-som.dtsi
index 821525f..70c0030 100644
--- a/arch/arm/dts/rk3288-phycore-som.dtsi
+++ b/arch/arm/dts/rk3288-phycore-som.dtsi
@@ -71,22 +71,6 @@
 		clock-output-names = "ext_gmac";
 	};
 
-	io_domains: io_domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-
-		status = "okay";
-		sdcard-supply = <&vdd_io_sd>;
-		flash0-supply = <&vdd_emmc_io>;
-		flash1-supply = <&vdd_misc_1v8>;
-		gpio1830-supply = <&vdd_3v3_io>;
-		gpio30-supply = <&vdd_3v3_io>;
-		bb-supply = <&vdd_3v3_io>;
-		dvp-supply = <&vdd_3v3_io>;
-		lcdc-supply = <&vdd_3v3_io>;
-		wifi-supply = <&vdd_3v3_io>;
-		audio-supply = <&vdd_3v3_io>;
-	};
-
 	leds: user-leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -197,6 +181,20 @@
 	ddc-i2c-bus = <&i2c5>;
 };
 
+&io_domains {
+	audio-supply = <&vdd_3v3_io>;
+	bb-supply = <&vdd_3v3_io>;
+	dvp-supply = <&vdd_3v3_io>;
+	flash0-supply = <&vdd_emmc_io>;
+	flash1-supply = <&vdd_misc_1v8>;
+	gpio1830-supply = <&vdd_3v3_io>;
+	gpio30-supply = <&vdd_3v3_io>;
+	lcdc-supply = <&vdd_3v3_io>;
+	sdcard-supply = <&vdd_io_sd>;
+	wifi-supply = <&vdd_3v3_io>;
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
diff --git a/arch/arm/dts/rk3288-popmetal.dtsi b/arch/arm/dts/rk3288-popmetal.dtsi
index 0253933..d732a70 100644
--- a/arch/arm/dts/rk3288-popmetal.dtsi
+++ b/arch/arm/dts/rk3288-popmetal.dtsi
@@ -71,22 +71,6 @@
 		};
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcca_33>;
-		bb-supply = <&vcc_io>;
-		dvp-supply = <&vcc18_dvp>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vcc_lan>;
-		gpio30-supply = <&vcc_io>;
-		gpio1830-supply = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vccio_wl>;
-	};
-
 	ir: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
@@ -443,6 +427,20 @@
 	status = "okay";
 };
 
+&io_domains {
+	audio-supply = <&vcca_33>;
+	bb-supply = <&vcc_io>;
+	dvp-supply = <&vcc18_dvp>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vcc_lan>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vccio_wl>;
+	status = "okay";
+};
+
 &pinctrl {
 	ak8963 {
 		comp_int: comp-int {
diff --git a/arch/arm/dts/rk3288-u-boot.dtsi b/arch/arm/dts/rk3288-u-boot.dtsi
index 1894162..1920698 100644
--- a/arch/arm/dts/rk3288-u-boot.dtsi
+++ b/arch/arm/dts/rk3288-u-boot.dtsi
@@ -91,6 +91,11 @@
 	bootph-all;
 };
 
+&edp {
+	clocks = <&cru SCLK_EDP>, <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>;
+	clock-names = "clk_edp", "clk_edp_24m", "pclk_edp";
+};
+
 &gpio7 {
 	bootph-all;
 };
diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index 35db882..434b0d4 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -198,21 +198,6 @@
 		/* Faux input supply.  See bt_regulator description. */
 		vin-supply = <&bt_regulator>;
 	};
-
-	io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcc18_codec>;
-		bb-supply = <&vcc33_io>;
-		dvp-supply = <&vcc_18>;
-		flash0-supply = <&vcc18_flashio>;
-		gpio1830-supply = <&vcc33_io>;
-		gpio30-supply = <&vcc33_io>;
-		lcdc-supply = <&vcc33_lcd>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vcc18_wl>;
-	};
 };
 
 &cpu0 {
@@ -503,6 +488,19 @@
 	clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>, <&cru SCLK_I2S0_OUT>;
 };
 
+&io_domains {
+	audio-supply = <&vcc18_codec>;
+	bb-supply = <&vcc33_io>;
+	dvp-supply = <&vcc_18>;
+	flash0-supply = <&vcc18_flashio>;
+	gpio1830-supply = <&vcc33_io>;
+	gpio30-supply = <&vcc33_io>;
+	lcdc-supply = <&vcc33_lcd>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vcc18_wl>;
+	status = "okay";
+};
+
 &wdt {
 	status = "okay";
 };
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index 8c394c1..dd1d989 100644
--- a/arch/arm/dts/rk3288.dtsi
+++ b/arch/arm/dts/rk3288.dtsi
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -7,13 +7,16 @@
 #include <dt-bindings/clock/rk3288-cru.h>
 #include <dt-bindings/power/rk3288-power.h>
 #include <dt-bindings/thermal/thermal.h>
-#include <dt-bindings/video/rk3288.h>
-#include "skeleton.dtsi"
+#include <dt-bindings/soc/rockchip,boot-mode.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	compatible = "rockchip,rk3288";
 
 	interrupt-parent = <&gic>;
+
 	aliases {
 		ethernet0 = &gmac;
 		i2c0 = &i2c0;
@@ -672,9 +675,7 @@
 		#pwm-cells = <3>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm0_pin>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		rockchip,grf = <&grf>;
+		clocks = <&cru PCLK_RKPWM>;
 		status = "disabled";
 	};
 
@@ -684,9 +685,7 @@
 		#pwm-cells = <3>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm1_pin>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		rockchip,grf = <&grf>;
+		clocks = <&cru PCLK_RKPWM>;
 		status = "disabled";
 	};
 
@@ -696,21 +695,17 @@
 		#pwm-cells = <3>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm2_pin>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		rockchip,grf = <&grf>;
+		clocks = <&cru PCLK_RKPWM>;
 		status = "disabled";
 	};
 
 	pwm3: pwm@ff680030 {
 		compatible = "rockchip,rk3288-pwm";
 		reg = <0xff680030 0x10>;
-		#pwm-cells = <2>;
+		#pwm-cells = <3>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm3_pin>;
-		clocks = <&cru PCLK_PWM>;
-		clock-names = "pwm";
-		rockchip,grf = <&grf>;
+		clocks = <&cru PCLK_RKPWM>;
 		status = "disabled";
 	};
 
@@ -732,8 +727,128 @@
 	};
 
 	pmu: power-management@ff730000 {
-		compatible = "rockchip,rk3288-pmu", "syscon";
+		compatible = "rockchip,rk3288-pmu", "syscon", "simple-mfd";
 		reg = <0xff730000 0x100>;
+
+		power: power-controller {
+			compatible = "rockchip,rk3288-power-controller";
+			#power-domain-cells = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			assigned-clocks = <&cru SCLK_EDP_24M>;
+			assigned-clock-parents = <&xin24m>;
+
+			/*
+			 * Note: Although SCLK_* are the working clocks
+			 * of device without including on the NOC, needed for
+			 * synchronous reset.
+			 *
+			 * The clocks on the which NOC:
+			 * ACLK_IEP/ACLK_VIP/ACLK_VOP0 are on ACLK_VIO0_NIU.
+			 * ACLK_ISP/ACLK_VOP1 are on ACLK_VIO1_NIU.
+			 * ACLK_RGA is on ACLK_RGA_NIU.
+			 * The others (HCLK_*,PLCK_*) are on HCLK_VIO_NIU.
+			 *
+			 * Which clock are device clocks:
+			 *	clocks		devices
+			 *	*_IEP		IEP:Image Enhancement Processor
+			 *	*_ISP		ISP:Image Signal Processing
+			 *	*_VIP		VIP:Video Input Processor
+			 *	*_VOP*		VOP:Visual Output Processor
+			 *	*_RGA		RGA
+			 *	*_EDP*		EDP
+			 *	*_LVDS_*	LVDS
+			 *	*_HDMI		HDMI
+			 *	*_MIPI_*	MIPI
+			 */
+			power-domain@RK3288_PD_VIO {
+				reg = <RK3288_PD_VIO>;
+				clocks = <&cru ACLK_IEP>,
+					 <&cru ACLK_ISP>,
+					 <&cru ACLK_RGA>,
+					 <&cru ACLK_VIP>,
+					 <&cru ACLK_VOP0>,
+					 <&cru ACLK_VOP1>,
+					 <&cru DCLK_VOP0>,
+					 <&cru DCLK_VOP1>,
+					 <&cru HCLK_IEP>,
+					 <&cru HCLK_ISP>,
+					 <&cru HCLK_RGA>,
+					 <&cru HCLK_VIP>,
+					 <&cru HCLK_VOP0>,
+					 <&cru HCLK_VOP1>,
+					 <&cru PCLK_EDP_CTRL>,
+					 <&cru PCLK_HDMI_CTRL>,
+					 <&cru PCLK_LVDS_PHY>,
+					 <&cru PCLK_MIPI_CSI>,
+					 <&cru PCLK_MIPI_DSI0>,
+					 <&cru PCLK_MIPI_DSI1>,
+					 <&cru SCLK_EDP_24M>,
+					 <&cru SCLK_EDP>,
+					 <&cru SCLK_ISP_JPE>,
+					 <&cru SCLK_ISP>,
+					 <&cru SCLK_RGA>;
+				pm_qos = <&qos_vio0_iep>,
+					 <&qos_vio1_vop>,
+					 <&qos_vio1_isp_w0>,
+					 <&qos_vio1_isp_w1>,
+					 <&qos_vio0_vop>,
+					 <&qos_vio0_vip>,
+					 <&qos_vio2_rga_r>,
+					 <&qos_vio2_rga_w>,
+					 <&qos_vio1_isp_r>;
+				#power-domain-cells = <0>;
+			};
+
+			/*
+			 * Note: The following 3 are HEVC(H.265) clocks,
+			 * and on the ACLK_HEVC_NIU (NOC).
+			 */
+			power-domain@RK3288_PD_HEVC {
+				reg = <RK3288_PD_HEVC>;
+				clocks = <&cru ACLK_HEVC>,
+					 <&cru SCLK_HEVC_CABAC>,
+					 <&cru SCLK_HEVC_CORE>;
+				pm_qos = <&qos_hevc_r>,
+					 <&qos_hevc_w>;
+				#power-domain-cells = <0>;
+			};
+
+			/*
+			 * Note: ACLK_VCODEC/HCLK_VCODEC are VCODEC
+			 * (video endecoder & decoder) clocks that on the
+			 * ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC).
+			 */
+			power-domain@RK3288_PD_VIDEO {
+				reg = <RK3288_PD_VIDEO>;
+				clocks = <&cru ACLK_VCODEC>,
+					 <&cru HCLK_VCODEC>;
+				pm_qos = <&qos_video>;
+				#power-domain-cells = <0>;
+			};
+
+			/*
+			 * Note: ACLK_GPU is the GPU clock,
+			 * and on the ACLK_GPU_NIU (NOC).
+			 */
+			power-domain@RK3288_PD_GPU {
+				reg = <RK3288_PD_GPU>;
+				clocks = <&cru ACLK_GPU>;
+				pm_qos = <&qos_gpu_r>,
+					 <&qos_gpu_w>;
+				#power-domain-cells = <0>;
+			};
+		};
+
+		reboot-mode {
+			compatible = "syscon-reboot-mode";
+			offset = <0x94>;
+			mode-normal = <BOOT_NORMAL>;
+			mode-recovery = <BOOT_RECOVERY>;
+			mode-bootloader = <BOOT_FASTBOOT>;
+			mode-loader = <BOOT_BL_DOWNLOAD>;
+		};
 	};
 
 	sgrf: syscon@ff740000 {
@@ -760,8 +875,58 @@
 	};
 
 	grf: syscon@ff770000 {
-		compatible = "rockchip,rk3288-grf", "syscon";
+		compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
 		reg = <0xff770000 0x1000>;
+
+		edp_phy: edp-phy {
+			compatible = "rockchip,rk3288-dp-phy";
+			clocks = <&cru SCLK_EDP_24M>;
+			clock-names = "24m";
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		io_domains: io-domains {
+			compatible = "rockchip,rk3288-io-voltage-domain";
+			status = "disabled";
+		};
+
+		usbphy: usbphy {
+			compatible = "rockchip,rk3288-usb-phy";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			usbphy0: usb-phy@320 {
+				#phy-cells = <0>;
+				reg = <0x320>;
+				clocks = <&cru SCLK_OTGPHY0>;
+				clock-names = "phyclk";
+				#clock-cells = <0>;
+				resets = <&cru SRST_USBOTG_PHY>;
+				reset-names = "phy-reset";
+			};
+
+			usbphy1: usb-phy@334 {
+				#phy-cells = <0>;
+				reg = <0x334>;
+				clocks = <&cru SCLK_OTGPHY1>;
+				clock-names = "phyclk";
+				#clock-cells = <0>;
+				resets = <&cru SRST_USBHOST0_PHY>;
+				reset-names = "phy-reset";
+			};
+
+			usbphy2: usb-phy@348 {
+				#phy-cells = <0>;
+				reg = <0x348>;
+				clocks = <&cru SCLK_OTGPHY2>;
+				clock-names = "phyclk";
+				#clock-cells = <0>;
+				resets = <&cru SRST_USBHOST1_PHY>;
+				reset-names = "phy-reset";
+			};
+		};
 	};
 
 	wdt: watchdog@ff800000 {
@@ -848,7 +1013,7 @@
 
 	vopb: vop@ff930000 {
 		compatible = "rockchip,rk3288-vop";
-		reg = <0xff930000 0x19c>;
+		reg = <0xff930000 0x19c>, <0xff931000 0x1000>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
 		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
@@ -862,24 +1027,24 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 
-			vopb_out_edp: endpoint@0 {
+			vopb_out_hdmi: endpoint@0 {
 				reg = <0>;
-				remote-endpoint = <&edp_in_vopb>;
+				remote-endpoint = <&hdmi_in_vopb>;
 			};
 
-			vopb_out_hdmi: endpoint@1 {
+			vopb_out_edp: endpoint@1 {
 				reg = <1>;
-				remote-endpoint = <&hdmi_in_vopb>;
+				remote-endpoint = <&edp_in_vopb>;
 			};
 
-			vopb_out_lvds: endpoint@2 {
+			vopb_out_mipi: endpoint@2 {
 				reg = <2>;
-				remote-endpoint = <&lvds_in_vopb>;
+				remote-endpoint = <&mipi_in_vopb>;
 			};
 
-			vopb_out_mipi: endpoint@3 {
+			vopb_out_lvds: endpoint@3 {
 				reg = <3>;
-				remote-endpoint = <&mipi_in_vopb>;
+				remote-endpoint = <&lvds_in_vopb>;
 			};
 		};
 	};
@@ -897,7 +1062,7 @@
 
 	vopl: vop@ff940000 {
 		compatible = "rockchip,rk3288-vop";
-		reg = <0xff940000 0x19c>;
+		reg = <0xff940000 0x19c>, <0xff941000 0x1000>;
 		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
 		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
@@ -911,24 +1076,24 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 
-			vopl_out_edp: endpoint@0 {
+			vopl_out_hdmi: endpoint@0 {
 				reg = <0>;
-				remote-endpoint = <&edp_in_vopl>;
+				remote-endpoint = <&hdmi_in_vopl>;
 			};
 
-			vopl_out_hdmi: endpoint@1 {
+			vopl_out_edp: endpoint@1 {
 				reg = <1>;
-				remote-endpoint = <&hdmi_in_vopl>;
+				remote-endpoint = <&edp_in_vopl>;
 			};
 
-			vopl_out_lvds: endpoint@2 {
+			vopl_out_mipi: endpoint@2 {
 				reg = <2>;
-				remote-endpoint = <&lvds_in_vopl>;
+				remote-endpoint = <&mipi_in_vopl>;
 			};
 
-			vopl_out_mipi: endpoint@3 {
+			vopl_out_lvds: endpoint@3 {
 				reg = <3>;
-				remote-endpoint = <&mipi_in_vopl>;
+				remote-endpoint = <&lvds_in_vopl>;
 			};
 		};
 	};
@@ -945,11 +1110,11 @@
 	};
 
 	mipi_dsi: mipi@ff960000 {
-		compatible = "rockchip,rk3288_mipi_dsi";
+		compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi";
 		reg = <0xff960000 0x4000>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru PCLK_MIPI_DSI0>;
-		clock-names = "pclk_mipi";
+		clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>;
+		clock-names = "ref", "pclk";
 		power-domains = <&power RK3288_PD_VIO>;
 		rockchip,grf = <&grf>;
 		status = "disabled";
@@ -975,7 +1140,7 @@
 		reg = <0xff96c000 0x4000>;
 		clocks = <&cru PCLK_LVDS_PHY>;
 		clock-names = "pclk_lvds";
-		pinctrl-names = "default";
+		pinctrl-names = "lcdc";
 		pinctrl-0 = <&lcdc_ctl>;
 		power-domains = <&power RK3288_PD_VIO>;
 		rockchip,grf = <&grf>;
@@ -1004,19 +1169,24 @@
 	};
 
 	edp: dp@ff970000 {
-		compatible = "rockchip,rk3288-edp";
+		compatible = "rockchip,rk3288-dp";
 		reg = <0xff970000 0x4000>;
 		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru SCLK_EDP>, <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>;
-		clock-names = "clk_edp", "clk_edp_24m", "pclk_edp";
+		clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>;
+		clock-names = "dp", "pclk";
+		phys = <&edp_phy>;
+		phy-names = "dp";
+		power-domains = <&power RK3288_PD_VIO>;
 		resets = <&cru SRST_EDP>;
-		reset-names = "edp";
+		reset-names = "dp";
 		rockchip,grf = <&grf>;
-		power-domains = <&power RK3288_PD_VIO>;
 		status = "disabled";
 
 		ports {
-			edp_in: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			edp_in: port@0 {
+				reg = <0>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				edp_in_vopb: endpoint@0 {
@@ -1038,8 +1208,8 @@
 		#sound-dai-cells = <0>;
 		rockchip,grf = <&grf>;
 		interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru  PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>;
-		clock-names = "iahb", "isfr";
+		clocks = <&cru  PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
+		clock-names = "iahb", "isfr", "cec";
 		power-domains = <&power RK3288_PD_VIO>;
 		status = "disabled";
 
@@ -1241,39 +1411,6 @@
 		interrupts = <GIC_PPI 9 0xf04>;
 	};
 
-	cpuidle: cpuidle {
-		compatible = "rockchip,rk3288-cpuidle";
-	};
-
-	usbphy: phy {
-		compatible = "rockchip,rk3288-usb-phy";
-		rockchip,grf = <&grf>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		status = "disabled";
-
-		usbphy0: usb-phy0 {
-			#phy-cells = <0>;
-			reg = <0x320>;
-			clocks = <&cru SCLK_OTGPHY0>;
-			clock-names = "phyclk";
-		};
-
-		usbphy1: usb-phy1 {
-			#phy-cells = <0>;
-			reg = <0x334>;
-			clocks = <&cru SCLK_OTGPHY1>;
-			clock-names = "phyclk";
-		};
-
-		usbphy2: usb-phy2 {
-			#phy-cells = <0>;
-			reg = <0x348>;
-			clocks = <&cru SCLK_OTGPHY2>;
-			clock-names = "phyclk";
-		};
-	};
-
 	pinctrl: pinctrl {
 		compatible = "rockchip,rk3288-pinctrl";
 		rockchip,grf = <&grf>;
@@ -1860,62 +1997,4 @@
 			};
 		};
 	};
-
-	power: power-controller {
-		compatible = "rockchip,rk3288-power-controller";
-		#power-domain-cells = <1>;
-		rockchip,pmu = <&pmu>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		pd_gpu {
-			reg = <RK3288_PD_GPU>;
-			clocks = <&cru ACLK_GPU>;
-		};
-
-		pd_hevc {
-			reg = <RK3288_PD_HEVC>;
-			clocks = <&cru ACLK_HEVC>,
-				 <&cru SCLK_HEVC_CABAC>,
-				 <&cru SCLK_HEVC_CORE>,
-				 <&cru HCLK_HEVC>;
-		};
-
-		pd_vio {
-			reg = <RK3288_PD_VIO>;
-			clocks = <&cru ACLK_IEP>,
-				 <&cru ACLK_ISP>,
-				 <&cru ACLK_RGA>,
-				 <&cru ACLK_VIP>,
-				 <&cru ACLK_VOP0>,
-				 <&cru ACLK_VOP1>,
-				 <&cru DCLK_VOP0>,
-				 <&cru DCLK_VOP1>,
-				 <&cru HCLK_IEP>,
-				 <&cru HCLK_ISP>,
-				 <&cru HCLK_RGA>,
-				 <&cru HCLK_VIP>,
-				 <&cru HCLK_VOP0>,
-				 <&cru HCLK_VOP1>,
-				 <&cru PCLK_EDP_CTRL>,
-				 <&cru PCLK_HDMI_CTRL>,
-				 <&cru PCLK_LVDS_PHY>,
-				 <&cru PCLK_MIPI_CSI>,
-				 <&cru PCLK_MIPI_DSI0>,
-				 <&cru PCLK_MIPI_DSI1>,
-				 <&cru SCLK_EDP_24M>,
-				 <&cru SCLK_EDP>,
-				 <&cru SCLK_HDMI_CEC>,
-				 <&cru SCLK_HDMI_HDCP>,
-				 <&cru SCLK_ISP_JPE>,
-				 <&cru SCLK_ISP>,
-				 <&cru SCLK_RGA>;
-		};
-
-		pd_video {
-			reg = <RK3288_PD_VIDEO>;
-			clocks = <&cru ACLK_VCODEC>,
-				 <&cru HCLK_VCODEC>;
-		};
-	};
 };
diff --git a/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi b/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi
index 4e79173..d183e93 100644
--- a/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi
+++ b/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi
@@ -16,3 +16,7 @@
 	bootph-all;
 	status = "okay";
 };
+
+&vcc5v0_usb30 {
+	regulator-boot-on;
+};
diff --git a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi
index 9ef1e84..801c91a 100644
--- a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi
+++ b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi
@@ -13,6 +13,14 @@
 	};
 };
 
+&sdhci {
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+};
+
 &sdmmc2 {
 	status = "disabled";
 };
@@ -26,3 +34,11 @@
 	bootph-all;
 	status = "okay";
 };
+
+&vcc5v0_usb_host {
+	regulator-boot-on;
+};
+
+&vcc5v0_usb_hub {
+	regulator-boot-on;
+};
diff --git a/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi b/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi
index 3235bd3..373f369 100644
--- a/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi
+++ b/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi
@@ -18,7 +18,5 @@
 
 &sdmmc {
 	bus-width = <4>;
-	bootph-all;
-	u-boot,spl-fifo-mode;
 	status = "okay";
 };
diff --git a/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi b/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi
new file mode 100644
index 0000000..bd2e259
--- /dev/null
+++ b/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
+ */
+
+#include "rk3588-u-boot.dtsi"
+
+/ {
+	aliases {
+		mmc0 = &sdmmc;
+		mmc1 = &sdhci;
+	};
+
+	chosen {
+		u-boot,spl-boot-order = &sdhci;
+	};
+};
+
+&sdhci {
+	bootph-all;
+};
diff --git a/arch/arm/dts/rk3588-evb1-v10.dts b/arch/arm/dts/rk3588-evb1-v10.dts
new file mode 100644
index 0000000..b91af02
--- /dev/null
+++ b/arch/arm/dts/rk3588-evb1-v10.dts
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3588.dtsi"
+
+/ {
+	model = "Rockchip RK3588 EVB1 V10 Board";
+	compatible = "rockchip,rk3588-evb1-v10", "rockchip,rk3588";
+
+	aliases {
+		mmc0 = &sdhci;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		stdout-path = "serial2:1500000n8";
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		power-supply = <&vcc12v_dcin>;
+		pwms = <&pwm2 0 25000 0>;
+	};
+
+	vcc12v_dcin: vcc12v-dcin-regulator {
+		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-regulator {
+		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>;
+	};
+};
+
+&gmac0 {
+	clock_in_out = "output";
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-rxid";
+	pinctrl-0 = <&gmac0_miim
+		     &gmac0_tx_bus2
+		     &gmac0_rx_bus2
+		     &gmac0_rgmii_clk
+		     &gmac0_rgmii_bus>;
+	pinctrl-names = "default";
+	rx_delay = <0x00>;
+	tx_delay = <0x43>;
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+
+	hym8563: rtc@51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-output-names = "hym8563";
+		pinctrl-names = "default";
+		pinctrl-0 = <&hym8563_int>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PD4 IRQ_TYPE_LEVEL_LOW>;
+		wakeup-source;
+	};
+};
+
+&mdio0 {
+	rgmii_phy: ethernet-phy@1 {
+		/* RTL8211F */
+		compatible = "ethernet-phy-id001c.c916";
+		reg = <0x1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&rtl8211f_rst>;
+		reset-assert-us = <20000>;
+		reset-deassert-us = <100000>;
+		reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&pinctrl {
+	rtl8211f {
+		rtl8211f_rst: rtl8211f-rst {
+			rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+	};
+
+	hym8563 {
+		hym8563_int: hym8563-int {
+			rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	no-sdio;
+	no-sd;
+	non-removable;
+	max-frequency = <200000000>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-0 = <&uart2m0_xfer>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi
index bee4c32..85075bf 100644
--- a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi
+++ b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi
@@ -7,16 +7,23 @@
 
 / {
 	aliases {
-		mmc0 = &sdmmc;
+		mmc1 = &sdmmc;
 	};
 
 	chosen {
-		u-boot,spl-boot-order = &sdmmc;
+		u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdhci;
 	};
 };
 
 &sdmmc {
 	bus-width = <4>;
-	bootph-pre-ram;
 	status = "okay";
 };
+
+&sdhci {
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe &emmc_rstnout>;
+};
diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi
index 1e225d7..5201ba2 100644
--- a/arch/arm/dts/rk3588s-u-boot.dtsi
+++ b/arch/arm/dts/rk3588s-u-boot.dtsi
@@ -18,20 +18,6 @@
 		reg = <0x0 0xfd58a000 0x0 0x2000>;
 	};
 
-	sdmmc: mmc@fe2c0000 {
-		compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
-		reg = <0x0 0xfe2c0000 0x0 0x4000>;
-		interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
-		clocks = <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>,
-			 <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>;
-		clock-names = "ciu-drive", "ciu-sample", "biu", "ciu";
-		fifo-depth = <0x100>;
-		max-frequency = <200000000>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
-		status = "disabled";
-	};
-
 	otp: nvmem@fecc0000 {
 		compatible = "rockchip,rk3588-otp";
 		reg = <0x0 0xfecc0000 0x0 0x400>;
@@ -43,6 +29,12 @@
 			reg = <0x07 0x10>;
 		};
 	};
+
+	rng: rng@fe378000 {
+		compatible = "rockchip,trngv1";
+		reg = <0x0 0xfe378000 0x0 0x200>;
+		status = "disabled";
+	};
 };
 
 &xin24m {
@@ -60,6 +52,23 @@
 	status = "okay";
 };
 
+&scmi {
+	bootph-pre-ram;
+};
+
+&scmi_clk {
+	bootph-pre-ram;
+};
+
+&sdmmc {
+	bootph-pre-ram;
+	u-boot,spl-fifo-mode;
+};
+
+&sdhci {
+	bootph-pre-ram;
+};
+
 &uart2 {
 	clock-frequency = <24000000>;
 	bootph-pre-ram;
diff --git a/arch/arm/dts/rk3588s.dtsi b/arch/arm/dts/rk3588s.dtsi
index 005cde6..fca8503 100644
--- a/arch/arm/dts/rk3588s.dtsi
+++ b/arch/arm/dts/rk3588s.dtsi
@@ -1099,6 +1099,21 @@
 		};
 	};
 
+	sdmmc: mmc@fe2c0000 {
+		compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe2c0000 0x0 0x4000>;
+		interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <200000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
+		power-domains = <&power RK3588_PD_SDMMC>;
+		status = "disabled";
+	};
+
 	sdhci: mmc@fe2e0000 {
 		compatible = "rockchip,rk3588-dwcmshc";
 		reg = <0x0 0xfe2e0000 0x0 0x10000>;
diff --git a/arch/arm/dts/rk3xxx-u-boot.dtsi b/arch/arm/dts/rk3xxx-u-boot.dtsi
index f50bacd..6af6a45 100644
--- a/arch/arm/dts/rk3xxx-u-boot.dtsi
+++ b/arch/arm/dts/rk3xxx-u-boot.dtsi
@@ -33,3 +33,7 @@
 &uart2 {
 	clock-frequency = <24000000>;
 };
+
+&xin24m {
+	bootph-all;
+};
diff --git a/arch/arm/dts/rk3xxx.dtsi b/arch/arm/dts/rk3xxx.dtsi
index 616a828..cb4e42e 100644
--- a/arch/arm/dts/rk3xxx.dtsi
+++ b/arch/arm/dts/rk3xxx.dtsi
@@ -76,6 +76,13 @@
 		reg = <0x1013c200 0x20>;
 		interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&cru CORE_PERI>;
+		status = "disabled";
+		/* The clock source and the sched_clock provided by the arm_global_timer
+		 * on Rockchip rk3066a/rk3188 are quite unstable because their rates
+		 * depend on the CPU frequency.
+		 * Keep the arm_global_timer disabled in order to have the
+		 * DW_APB_TIMER (rk3066a) or ROCKCHIP_TIMER (rk3188) selected by default.
+		 */
 	};
 
 	local_timer: local-timer@1013c600 {
@@ -186,8 +193,6 @@
 		compatible = "snps,arc-emac";
 		reg = <0x10204000 0x3c>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-		#address-cells = <1>;
-		#size-cells = <0>;
 
 		rockchip,grf = <&grf>;
 
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
index 90e66c7..f002ebc 100644
--- a/arch/arm/include/asm/arch-rockchip/clock.h
+++ b/arch/arm/include/asm/arch-rockchip/clock.h
@@ -194,6 +194,5 @@
  * Return: 0 success, or error value
  */
 int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number);
-int rockchip_get_scmi_clk(struct udevice **devp);
 
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
index 3ea59e9..7f4a908 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
@@ -11,12 +11,12 @@
 #define KHz		1000
 #define OSC_HZ		(24 * MHz)
 
-#define CPU_PVTPLL_HZ	(1008 * MHz)
 #define LPLL_HZ		(816 * MHz)
 #define GPLL_HZ		(1188 * MHz)
 #define CPLL_HZ		(1500 * MHz)
 #define NPLL_HZ         (850 * MHz)
 #define PPLL_HZ		(1100 * MHz)
+#define SPLL_HZ		(702 * MHz)
 
 /* RK3588 pll id */
 enum rk3588_pll_id {
@@ -447,5 +447,22 @@
 	CLK_I2C0_SEL_MASK			= 1 << CLK_I2C0_SEL_SHIFT,
 	CLK_I2C_SEL_200M			= 0,
 	CLK_I2C_SEL_100M,
+
+	/* SECURECRU_CLKSEL_CON01 */
+	SCMI_HCLK_SD_SEL_SHIFT			= 2,
+	SCMI_HCLK_SD_SEL_MASK			= 3 << SCMI_HCLK_SD_SEL_SHIFT,
+	SCMI_HCLK_SD_SEL_150M			= 0,
+	SCMI_HCLK_SD_SEL_100M,
+	SCMI_HCLK_SD_SEL_50M,
+	SCMI_HCLK_SD_SEL_24M,
+
+	/* SECURECRU_CLKSEL_CON03 */
+	SCMI_CCLK_SD_SEL_SHIFT			= 12,
+	SCMI_CCLK_SD_SEL_MASK			= 3 << SCMI_CCLK_SD_SEL_SHIFT,
+	SCMI_CCLK_SD_SEL_GPLL			= 0,
+	SCMI_CCLK_SD_SEL_SPLL,
+	SCMI_CCLK_SD_SEL_24M,
+	SCMI_CCLK_SD_DIV_SHIFT			= 6,
+	SCMI_CCLK_SD_DIV_MASK			= 0x3f << SCMI_CCLK_SD_DIV_SHIFT,
 };
 #endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 0390431..327779a 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -119,7 +119,7 @@
 config ROCKCHIP_RK3288
 	bool "Support Rockchip RK3288"
 	select CPU_V7A
-	select OF_BOARD_SETUP
+	select OF_SYSTEM_SETUP
 	select SKIP_LOWLEVEL_INIT_ONLY
 	select SUPPORT_SPL
 	select SPL
@@ -288,7 +288,9 @@
 	select BOARD_LATE_INIT
 	select DM_REGULATOR_FIXED
 	select DM_RESET
+	imply SPL_ATF_NO_PLATFORM_PARAM if SPL_ATF
 	imply ROCKCHIP_COMMON_BOARD
+	imply OF_LIBFDT_OVERLAY
 	imply ROCKCHIP_OTP
 	imply MISC_INIT_R
 	help
@@ -309,9 +311,13 @@
 	select REGMAP
 	select SYSCON
 	select BOARD_LATE_INIT
+	imply SPL_ATF_NO_PLATFORM_PARAM if SPL_ATF
 	imply ROCKCHIP_COMMON_BOARD
+	imply OF_LIBFDT_OVERLAY
 	imply ROCKCHIP_OTP
 	imply MISC_INIT_R
+	imply CLK_SCMI
+	imply SCMI_FIRMWARE
 	help
 	  The Rockchip RK3588 is a ARM-based SoC with quad-core Cortex-A76 and
 	  quad-core Cortex-A55 including NEON and GPU, 6TOPS NPU, Mali-G610 MP4,
@@ -428,7 +434,7 @@
 
 config ROCKCHIP_EXTERNAL_TPL
 	bool "Use external TPL binary"
-	default y if ROCKCHIP_RK3568
+	default y if ROCKCHIP_RK3568 || ROCKCHIP_RK3588
 	help
 	  Some Rockchip SoCs require an external TPL to initialize DRAM.
 	  Enable this option and build with ROCKCHIP_TPL=/path/to/ddr.bin to
diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c
index 849014d..7d03f0c 100644
--- a/arch/arm/mach-rockchip/misc.c
+++ b/arch/arm/mach-rockchip/misc.c
@@ -83,7 +83,7 @@
 
 	/* read the cpu_id range from the efuses */
 	ret = misc_read(dev, cpuid_offset, cpuid, cpuid_length);
-	if (ret) {
+	if (ret < 0) {
 		debug("%s: reading cpuid from the efuses failed\n",
 		      __func__);
 		return -1;
diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c
index 3ad2887..26c7e41 100644
--- a/arch/arm/mach-rockchip/rk3288/rk3288.c
+++ b/arch/arm/mach-rockchip/rk3288/rk3288.c
@@ -138,7 +138,7 @@
 	return ret;
 }
 
-int ft_board_setup(void *blob, struct bd_info *bd)
+int ft_system_setup(void *blob, struct bd_info *bd)
 {
 	if (soc_is_rk3288w())
 		return ft_rk3288w_setup(blob);
diff --git a/arch/arm/mach-rockchip/rk3588/Kconfig b/arch/arm/mach-rockchip/rk3588/Kconfig
index aee71ca..3596b82 100644
--- a/arch/arm/mach-rockchip/rk3588/Kconfig
+++ b/arch/arm/mach-rockchip/rk3588/Kconfig
@@ -1,5 +1,11 @@
 if ROCKCHIP_RK3588
 
+config TARGET_EVB_RK3588
+	bool "Rockchip EVB1 v10"
+	select BOARD_LATE_INIT
+	help
+	  RK3588 EVB is a evaluation board for Rockchp RK3588.
+
 config TARGET_RK3588_NEU6
 	bool "Edgeble Neural Compute Module 6(Neu6) SoM"
 	select BOARD_LATE_INIT
@@ -51,6 +57,7 @@
 	default 0x80000
 
 source board/edgeble/neural-compute-module-6/Kconfig
+source board/rockchip/evb_rk3588/Kconfig
 source board/radxa/rock5b-rk3588/Kconfig
 
 endif
diff --git a/board/rockchip/evb_rk3588/Kconfig b/board/rockchip/evb_rk3588/Kconfig
new file mode 100644
index 0000000..d38efe6
--- /dev/null
+++ b/board/rockchip/evb_rk3588/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_EVB_RK3588
+
+config SYS_BOARD
+	default "evb_rk3588"
+
+config SYS_VENDOR
+	default "rockchip"
+
+config SYS_CONFIG_NAME
+	default "evb_rk3588"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rockchip/evb_rk3588/MAINTAINERS b/board/rockchip/evb_rk3588/MAINTAINERS
new file mode 100644
index 0000000..7b7df3c
--- /dev/null
+++ b/board/rockchip/evb_rk3588/MAINTAINERS
@@ -0,0 +1,7 @@
+EVB-RK3588
+M:	Kever Yang <kever.yang@rock-chips.com>
+S:	Maintained
+F:	board/rockchip/evb_rk3588
+F:	include/configs/evb_rk3588.h
+F:	configs/evb-rk3588_defconfig
+F:	arch/arm/dts/rk3588-evb-u-boot.dtsi
diff --git a/board/rockchip/evb_rk3588/Makefile b/board/rockchip/evb_rk3588/Makefile
new file mode 100644
index 0000000..240d2ec
--- /dev/null
+++ b/board/rockchip/evb_rk3588/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier:     GPL-2.0+
+#
+# Copyright (c) 2023 Rockchip Electronics Co,. Ltd.
+#
+
+obj-y += evb-rk3588.o
diff --git a/board/rockchip/evb_rk3588/evb-rk3588.c b/board/rockchip/evb_rk3588/evb-rk3588.c
new file mode 100644
index 0000000..caf94d8
--- /dev/null
+++ b/board/rockchip/evb_rk3588/evb-rk3588.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Rockchip Electronics Co,. Ltd.
+ */
+
+#include <fdtdec.h>
+#include <fdt_support.h>
+
+#ifdef CONFIG_OF_BOARD_SETUP
+static int rk3588_add_reserved_memory_fdt_nodes(void *new_blob)
+{
+	struct fdt_memory gap1 = {
+		.start = 0x3fc000000,
+		.end = 0x3fc4fffff,
+	};
+	struct fdt_memory gap2 = {
+		.start = 0x3fff00000,
+		.end = 0x3ffffffff,
+	};
+	unsigned long flags = FDTDEC_RESERVED_MEMORY_NO_MAP;
+	unsigned int ret;
+
+	/*
+	 * Inject the reserved-memory nodes into the DTS
+	 */
+	ret = fdtdec_add_reserved_memory(new_blob, "gap1", &gap1,  NULL, 0,
+					 NULL, flags);
+	if (ret)
+		return ret;
+
+	return fdtdec_add_reserved_memory(new_blob, "gap2", &gap2,  NULL, 0,
+					  NULL, flags);
+}
+
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+	return rk3588_add_reserved_memory_fdt_nodes(blob);
+}
+#endif
diff --git a/board/theobroma-systems/puma_rk3399/Kconfig b/board/theobroma-systems/puma_rk3399/Kconfig
index 15af555..cc745f5 100644
--- a/board/theobroma-systems/puma_rk3399/Kconfig
+++ b/board/theobroma-systems/puma_rk3399/Kconfig
@@ -11,6 +11,7 @@
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select ENV_IS_NOWHERE
 
 config ENV_SIZE
 	default 0x4000
diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
index 97f398b..614a60e 100644
--- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c
+++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
@@ -136,10 +136,6 @@
 	return CONFIG_SYS_MMC_ENV_DEV;
 }
 
-#if !IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
-#error Please enable CONFIG_ENV_IS_NOWHERE
-#endif
-
 enum env_location arch_env_get_location(enum env_operation op, int prio)
 {
 	const char *boot_device =
diff --git a/board/theobroma-systems/ringneck_px30/Kconfig b/board/theobroma-systems/ringneck_px30/Kconfig
index 24d9480..c33253b 100644
--- a/board/theobroma-systems/ringneck_px30/Kconfig
+++ b/board/theobroma-systems/ringneck_px30/Kconfig
@@ -11,6 +11,7 @@
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select ENV_IS_NOWHERE
 
 config ENV_SIZE
 	default 0x3000
diff --git a/board/theobroma-systems/ringneck_px30/ringneck-px30.c b/board/theobroma-systems/ringneck_px30/ringneck-px30.c
index 47d1a40..bb1bb4a 100644
--- a/board/theobroma-systems/ringneck_px30/ringneck-px30.c
+++ b/board/theobroma-systems/ringneck_px30/ringneck-px30.c
@@ -118,10 +118,6 @@
 	return CONFIG_SYS_MMC_ENV_DEV;
 }
 
-#if !IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
-#error Please enable CONFIG_ENV_IS_NOWHERE
-#endif
-
 enum env_location arch_env_get_location(enum env_operation op, int prio)
 {
 	const char *boot_device =
diff --git a/configs/evb-rk3588_defconfig b/configs/evb-rk3588_defconfig
new file mode 100644
index 0000000..ddeadb8
--- /dev/null
+++ b/configs/evb-rk3588_defconfig
@@ -0,0 +1,69 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x00a00000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000
+CONFIG_DEFAULT_DEVICE_TREE="rk3588-evb1-v10"
+CONFIG_DM_RESET=y
+CONFIG_ROCKCHIP_RK3588=y
+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_SPL_MMC=y
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_TARGET_EVB_RK3588=y
+CONFIG_SPL_STACK=0x400000
+CONFIG_DEBUG_UART_BASE=0xFEB50000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYS_LOAD_ADDR=0xc00800
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588-evb1-v10.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_MAX_SIZE=0x20000
+CONFIG_SPL_PAD_TO=0x7f8000
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x4000000
+CONFIG_SPL_BSS_MAX_SIZE=0x4000
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_ATF=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SPL_SYSCON=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_SUPPORT_EMMC_RPMB=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_SPL_RAM=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYSRESET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig
index c080706..b7dcd16 100644
--- a/configs/mk808_defconfig
+++ b/configs/mk808_defconfig
@@ -18,7 +18,7 @@
 CONFIG_DM_RESET=y
 CONFIG_ROCKCHIP_RK3066=y
 # CONFIG_ROCKCHIP_STIMER is not set
-CONFIG_TPL_TEXT_BASE=0x10080C04
+CONFIG_TPL_TEXT_BASE=0x10080c00
 CONFIG_TPL_STACK=0x1008FFFF
 CONFIG_TARGET_MK808=y
 CONFIG_SPL_STACK_R_ADDR=0x70000000
@@ -53,6 +53,9 @@
 # CONFIG_BOOTM_VXWORKS is not set
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_ROCKUSB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
@@ -78,6 +81,7 @@
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
 CONFIG_TPL_CLK=y
+CONFIG_FASTBOOT_BUF_ADDR=0x80000000
 CONFIG_ROCKCHIP_GPIO=y
 # CONFIG_SPL_DM_I2C is not set
 CONFIG_LED=y
@@ -106,6 +110,12 @@
 CONFIG_SPL_TIMER=y
 CONFIG_TPL_TIMER=y
 CONFIG_DESIGNWARE_APB_TIMER=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_FUNCTION_ROCKUSB=y
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_ERRNO_STR=y
 # CONFIG_TPL_OF_LIBFDT is not set
diff --git a/configs/neu6a-io-rk3588_defconfig b/configs/neu6a-io-rk3588_defconfig
index c9b2252..fb1ce4c 100644
--- a/configs/neu6a-io-rk3588_defconfig
+++ b/configs/neu6a-io-rk3588_defconfig
@@ -62,5 +62,4 @@
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYSRESET=y
-# CONFIG_BINMAN_FDT is not set
 CONFIG_ERRNO_STR=y
diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig
index 9e3e23f..59017b2 100644
--- a/configs/puma-rk3399_defconfig
+++ b/configs/puma-rk3399_defconfig
@@ -55,7 +55,6 @@
 CONFIG_OF_LIVE=y
 CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
 CONFIG_ENV_OVERWRITE=y
-CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_ENV_SPI_MAX_HZ=50000000
diff --git a/configs/radxa-cm3-io-rk3566_defconfig b/configs/radxa-cm3-io-rk3566_defconfig
index 2100cf2..1df9cab 100644
--- a/configs/radxa-cm3-io-rk3566_defconfig
+++ b/configs/radxa-cm3-io-rk3566_defconfig
@@ -37,9 +37,12 @@
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ATF=y
 CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
 # CONFIG_SPL_DOS_PARTITION is not set
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_LIVE=y
@@ -60,8 +63,9 @@
 CONFIG_GMAC_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
-CONFIG_REGULATOR_PWM=y
-CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_SPL_RAM=y
 CONFIG_BAUDRATE=1500000
@@ -73,5 +77,4 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
 CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GENERIC=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/ringneck-px30_defconfig b/configs/ringneck-px30_defconfig
index 91706d8..e9234ef 100644
--- a/configs/ringneck-px30_defconfig
+++ b/configs/ringneck-px30_defconfig
@@ -68,7 +68,6 @@
 CONFIG_OF_LIVE=y
 CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
 CONFIG_ENV_OVERWRITE=y
-CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig
index e753832..f0db15b 100644
--- a/configs/rock-3a-rk3568_defconfig
+++ b/configs/rock-3a-rk3568_defconfig
@@ -39,7 +39,10 @@
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
 # CONFIG_SPL_DOS_PARTITION is not set
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_LIVE=y
@@ -58,10 +61,11 @@
 CONFIG_MMC_SDHCI_ROCKCHIP=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
 CONFIG_SPL_PMIC_RK8XX=y
-CONFIG_REGULATOR_PWM=y
 CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_SPL_RAM=y
@@ -69,5 +73,12 @@
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550_MEM32=y
 CONFIG_SYSRESET=y
-# CONFIG_BINMAN_FDT is not set
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB_DWC3=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/rock5b-rk3588_defconfig b/configs/rock5b-rk3588_defconfig
index f3026c7..d3136ac 100644
--- a/configs/rock5b-rk3588_defconfig
+++ b/configs/rock5b-rk3588_defconfig
@@ -58,6 +58,7 @@
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
+# CONFIG_SPL_MMC_SDHCI_SDMA is not set
 CONFIG_MMC_SDHCI_ROCKCHIP=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_GMAC_ROCKCHIP=y
@@ -66,7 +67,5 @@
 CONFIG_SPL_RAM=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
-CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_SYSRESET=y
-# CONFIG_BINMAN_FDT is not set
 CONFIG_ERRNO_STR=y
diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst
index b5563b8..1dccb17 100644
--- a/doc/board/rockchip/rockchip.rst
+++ b/doc/board/rockchip/rockchip.rst
@@ -91,6 +91,7 @@
      - Rockchip Evb-RK3568 (evb-rk3568)
 
 * rk3588
+     - Rockchip EVB (evb-rk3588)
      - Edgeble Neural Compute Module 6 SoM - Neu6a (neu6a-io-rk3588)
      - Radxa ROCK 5B (rock5b-rk3588)
 
@@ -185,6 +186,15 @@
         make evb-rk3568_defconfig
         make CROSS_COMPILE=aarch64-linux-gnu-
 
+To build rk3588 boards:
+
+.. code-block:: bash
+
+        export BL31=../rkbin/bin/rk35/rk3588_bl31_v1.33.elf
+        export ROCKCHIP_TPL=../rkbin/bin/rk35/rk3588_ddr_lp4_2112MHz_lp5_2736MHz_v1.09.bin
+        make evb-rk3588_defconfig
+        make CROSS_COMPILE=aarch64-linux-gnu-
+
 Flashing
 --------
 
@@ -380,9 +390,8 @@
 
         #!/bin/sh
 
-        printf "RK30" > tplspl.bin
-        dd if=u-boot-tpl.bin >> tplspl.bin
-        truncate -s %2048 tplspl.bin
+        printf "RK30" | dd conv=notrunc bs=4 count=1 of=u-boot-tpl.bin
+        truncate -s %2048 u-boot-tpl.bin
         truncate -s %2048 u-boot-spl.bin
         ../tools/boot_merger --verbose config-flash.ini
         ../tools/upgrade_tool ul ./RK30xxLoader_uboot.bin
@@ -406,7 +415,7 @@
         NUM=2
         LOADER1=FlashData
         LOADER2=FlashBoot
-        FlashData=tplspl.bin
+        FlashData=u-boot-tpl.bin
         FlashBoot=u-boot-spl.bin
         [OUTPUT]
         PATH=RK30xxLoader_uboot.bin
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a2d4f0c..3ad5af9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -166,6 +166,14 @@
 	  by a SCMI agent based on SCMI clock protocol communication
 	  with a SCMI server.
 
+config SPL_CLK_SCMI
+	bool "Enable SCMI clock driver in SPL"
+	depends on SCMI_FIRMWARE && SPL_FIRMWARE
+	help
+	  Enable this option if you want to support clock devices exposed
+	  by a SCMI agent based on SCMI clock protocol communication
+	  with a SCMI server in SPL.
+
 config CLK_HSDK
 	bool "Enable cgu clock driver for HSDK boards"
 	depends on CLK && TARGET_HSDK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 66f5860..e22c8cf 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -40,7 +40,7 @@
 obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o
 obj-$(CONFIG_CLK_OWL) += owl/
 obj-$(CONFIG_CLK_RENESAS) += renesas/
-obj-$(CONFIG_CLK_SCMI) += clk_scmi.o
+obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o
 obj-$(CONFIG_CLK_SIFIVE) += sifive/
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 3b29992..ef744c0 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -778,6 +778,7 @@
 	case PCLK_I2C5:
 		return gclk_rate;
 	case PCLK_PWM:
+	case PCLK_RKPWM:
 		return PD_BUS_PCLK_HZ;
 	case SCLK_SARADC:
 		new_rate = rockchip_saradc_get_clk(priv->cru);
diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c
index 1c6adc5..cefc263 100644
--- a/drivers/clk/rockchip/clk_rk3568.c
+++ b/drivers/clk/rockchip/clk_rk3568.c
@@ -2838,6 +2838,8 @@
 	case ACLK_RKVDEC_PRE:
 	case CLK_RKVDEC_CORE:
 		return rk3568_rkvdec_set_parent(clk, parent);
+	case I2S1_MCLKOUT_TX:
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c
index a7df553..d0cc19b 100644
--- a/drivers/clk/rockchip/clk_rk3588.c
+++ b/drivers/clk/rockchip/clk_rk3588.c
@@ -9,6 +9,7 @@
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
+#include <scmi_protocols.h>
 #include <syscon.h>
 #include <asm/arch-rockchip/cru_rk3588.h>
 #include <asm/arch-rockchip/clock.h>
@@ -1552,6 +1553,7 @@
 	case DCLK_DECOM:
 		rate = rk3588_mmc_get_clk(priv, clk->id);
 		break;
+	case TMCLK_EMMC:
 	case TCLK_WDT0:
 		rate = OSC_HZ;
 		break;
@@ -1701,6 +1703,7 @@
 	case DCLK_DECOM:
 		ret = rk3588_mmc_set_clk(priv, clk->id, rate);
 		break;
+	case TMCLK_EMMC:
 	case TCLK_WDT0:
 		ret = OSC_HZ;
 		break;
@@ -1994,3 +1997,127 @@
 	.bind		= rk3588_clk_bind,
 	.probe		= rk3588_clk_probe,
 };
+
+#ifdef CONFIG_SPL_BUILD
+#define SCRU_BASE			0xfd7d0000
+
+static ulong rk3588_scru_clk_get_rate(struct clk *clk)
+{
+	u32 con, div, sel, parent;
+
+	switch (clk->id) {
+	case SCMI_CCLK_SD:
+		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
+		sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
+		div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
+		if (sel == SCMI_CCLK_SD_SEL_GPLL)
+			parent = GPLL_HZ;
+		else if (sel == SCMI_CCLK_SD_SEL_SPLL)
+			parent = SPLL_HZ;
+		else
+			parent = OSC_HZ;
+		return DIV_TO_RATE(parent, div);
+	case SCMI_HCLK_SD:
+		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
+		sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
+		if (sel == SCMI_HCLK_SD_SEL_150M)
+			return 150 * MHz;
+		else if (sel == SCMI_HCLK_SD_SEL_100M)
+			return 100 * MHz;
+		else if (sel == SCMI_HCLK_SD_SEL_50M)
+			return 50 * MHz;
+		else
+			return OSC_HZ;
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
+{
+	u32 div, sel;
+
+	switch (clk->id) {
+	case SCMI_CCLK_SD:
+		if ((OSC_HZ % rate) == 0) {
+			sel = SCMI_CCLK_SD_SEL_24M;
+			div = DIV_ROUND_UP(OSC_HZ, rate);
+		} else if ((SPLL_HZ % rate) == 0) {
+			sel = SCMI_CCLK_SD_SEL_SPLL;
+			div = DIV_ROUND_UP(SPLL_HZ, rate);
+		} else {
+			sel = SCMI_CCLK_SD_SEL_GPLL;
+			div = DIV_ROUND_UP(GPLL_HZ, rate);
+		}
+		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
+			     SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
+			     sel << SCMI_CCLK_SD_SEL_SHIFT |
+			     (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
+		break;
+	case SCMI_HCLK_SD:
+		if (rate >= 150 * MHz)
+			sel = SCMI_HCLK_SD_SEL_150M;
+		else if (rate >= 100 * MHz)
+			sel = SCMI_HCLK_SD_SEL_100M;
+		else if (rate >= 50 * MHz)
+			sel = SCMI_HCLK_SD_SEL_50M;
+		else
+			sel = SCMI_HCLK_SD_SEL_24M;
+		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
+			     SCMI_HCLK_SD_SEL_MASK,
+			     sel << SCMI_HCLK_SD_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rk3588_scru_clk_get_rate(clk);
+}
+
+static const struct clk_ops rk3588_scru_clk_ops = {
+	.get_rate = rk3588_scru_clk_get_rate,
+	.set_rate = rk3588_scru_clk_set_rate,
+};
+
+U_BOOT_DRIVER(rockchip_rk3588_scru) = {
+	.name = "rockchip_rk3588_scru",
+	.id = UCLASS_CLK,
+	.ops = &rk3588_scru_clk_ops,
+};
+
+static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
+{
+	ofnode node;
+	u32 protocol_id;
+	const char *name;
+
+	dev_for_each_subnode(node, dev) {
+		if (!ofnode_is_enabled(node))
+			continue;
+
+		if (ofnode_read_u32(node, "reg", &protocol_id))
+			continue;
+
+		if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
+			continue;
+
+		name = ofnode_get_name(node);
+		return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
+						  name, node, NULL);
+	}
+
+	return -ENOENT;
+}
+
+static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
+	{ .compatible = "arm,scmi-smc" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
+	.name		= "rk3588_scmi_spl_glue",
+	.id		= UCLASS_NOP,
+	.of_match	= rk3588_scmi_spl_glue_ids,
+	.bind		= rk3588_scmi_spl_glue_bind,
+};
+#endif
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 9a32678..54d563d 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -75,7 +75,7 @@
 		name = ofnode_get_name(node);
 		switch (protocol_id) {
 		case SCMI_PROTOCOL_ID_CLOCK:
-			if (IS_ENABLED(CONFIG_CLK_SCMI))
+			if (CONFIG_IS_ENABLED(CLK_SCMI))
 				drv = DM_DRIVER_GET(scmi_clock);
 			break;
 		case SCMI_PROTOCOL_ID_RESET_DOMAIN:
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
index f7ad4d6..4a6ae55 100644
--- a/drivers/gpio/rk_gpio.c
+++ b/drivers/gpio/rk_gpio.c
@@ -13,83 +13,118 @@
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
 #include <asm/arch-rockchip/gpio.h>
 #include <dm/pinctrl.h>
-#include <dt-bindings/clock/rk3288-cru.h>
+#include <dm/read.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+#define SWPORT_DR		0x0000
+#define SWPORT_DDR		0x0004
+#define EXT_PORT		0x0050
+#define SWPORT_DR_L		0x0000
+#define SWPORT_DR_H		0x0004
+#define SWPORT_DDR_L		0x0008
+#define SWPORT_DDR_H		0x000C
+#define EXT_PORT_V2		0x0070
+#define VER_ID_V2		0x0078
 
 enum {
 	ROCKCHIP_GPIOS_PER_BANK		= 32,
 };
 
-#define OFFSET_TO_BIT(bit)	(1UL << (bit))
-
 struct rockchip_gpio_priv {
-	struct rockchip_gpio_regs *regs;
+	void __iomem *regs;
 	struct udevice *pinctrl;
 	int bank;
 	char name[2];
+	u32 version;
 };
 
-static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
+static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
 {
 	struct rockchip_gpio_priv *priv = dev_get_priv(dev);
-	struct rockchip_gpio_regs *regs = priv->regs;
+	u32 mask = BIT(offset), data;
 
-	clrbits_le32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
+	if (priv->version)
+		data = readl(priv->regs + EXT_PORT_V2);
+	else
+		data = readl(priv->regs + EXT_PORT);
 
-	return 0;
+	return (data & mask) ? 1 : 0;
 }
 
-static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
-					  int value)
+static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
+				   int value)
 {
 	struct rockchip_gpio_priv *priv = dev_get_priv(dev);
-	struct rockchip_gpio_regs *regs = priv->regs;
-	int mask = OFFSET_TO_BIT(offset);
+	u32 mask = BIT(offset), data = value ? mask : 0;
 
-	clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
-	setbits_le32(&regs->swport_ddr, mask);
+	if (priv->version && offset >= 16)
+		rk_clrsetreg(priv->regs + SWPORT_DR_H, mask >> 16, data >> 16);
+	else if (priv->version)
+		rk_clrsetreg(priv->regs + SWPORT_DR_L, mask, data);
+	else
+		clrsetbits_le32(priv->regs + SWPORT_DR, mask, data);
 
 	return 0;
 }
 
-static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
+static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
 	struct rockchip_gpio_priv *priv = dev_get_priv(dev);
-	struct rockchip_gpio_regs *regs = priv->regs;
+	u32 mask = BIT(offset);
+
+	if (priv->version && offset >= 16)
+		rk_clrreg(priv->regs + SWPORT_DDR_H, mask >> 16);
+	else if (priv->version)
+		rk_clrreg(priv->regs + SWPORT_DDR_L, mask);
+	else
+		clrbits_le32(priv->regs + SWPORT_DDR, mask);
 
-	return readl(&regs->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0;
+	return 0;
 }
 
-static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
-				   int value)
+static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
+					  int value)
 {
 	struct rockchip_gpio_priv *priv = dev_get_priv(dev);
-	struct rockchip_gpio_regs *regs = priv->regs;
-	int mask = OFFSET_TO_BIT(offset);
+	u32 mask = BIT(offset);
+
+	rockchip_gpio_set_value(dev, offset, value);
 
-	clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
+	if (priv->version && offset >= 16)
+		rk_setreg(priv->regs + SWPORT_DDR_H, mask >> 16);
+	else if (priv->version)
+		rk_setreg(priv->regs + SWPORT_DDR_L, mask);
+	else
+		setbits_le32(priv->regs + SWPORT_DDR, mask);
 
 	return 0;
 }
 
 static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
 {
-#ifdef CONFIG_SPL_BUILD
-	return -ENODATA;
-#else
 	struct rockchip_gpio_priv *priv = dev_get_priv(dev);
-	struct rockchip_gpio_regs *regs = priv->regs;
-	bool is_output;
+	u32 mask = BIT(offset), data;
 	int ret;
 
+	if (CONFIG_IS_ENABLED(PINCTRL)) {
+		ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
+		if (ret < 0)
+			return ret;
+		else if (ret != RK_FUNC_GPIO)
+			return GPIOF_FUNC;
+	}
+
-	ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
-	if (ret)
-		return ret;
-	is_output = readl(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
+	if (priv->version && offset >= 16)
+		data = readl(priv->regs + SWPORT_DDR_H) << 16;
+	else if (priv->version)
+		data = readl(priv->regs + SWPORT_DDR_L);
+	else
+		data = readl(priv->regs + SWPORT_DDR);
 
-	return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
-#endif
+	return (data & mask) ? GPIOF_OUTPUT : GPIOF_INPUT;
 }
 
 /* Simple SPL interface to GPIOs */
@@ -147,9 +182,12 @@
 	int ret;
 
 	priv->regs = dev_read_addr_ptr(dev);
-	ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
-	if (ret)
-		return ret;
+
+	if (CONFIG_IS_ENABLED(PINCTRL)) {
+		ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
+		if (ret)
+			return ret;
+	}
 
 	/*
 	 * If "gpio-ranges" is present in the devicetree use it to parse
@@ -160,7 +198,7 @@
 					     0, &args);
 	if (!ret || ret != -ENOENT) {
 		uc_priv->gpio_count = args.args[2];
-		priv->bank = args.args[1] / args.args[2];
+		priv->bank = args.args[1] / ROCKCHIP_GPIOS_PER_BANK;
 	} else {
 		uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
 		end = strrchr(dev->name, '@');
@@ -170,6 +208,8 @@
 	priv->name[0] = 'A' + priv->bank;
 	uc_priv->bank_name = priv->name;
 
+	priv->version = readl(priv->regs + VER_ID_V2);
+
 	return 0;
 }
 
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c
index 60931a5..2f96b79 100644
--- a/drivers/misc/rockchip-efuse.c
+++ b/drivers/misc/rockchip-efuse.c
@@ -73,7 +73,7 @@
 
 	for (i = 0; true; i += sizeof(data)) {
 		ret = misc_read(dev, i, &data, sizeof(data));
-		if (ret < 0)
+		if (ret <= 0)
 			return 0;
 
 		print_buffer(i, data, 1, sizeof(data), sizeof(data));
@@ -238,8 +238,10 @@
 
 	offset += data->offset;
 
-	if (data->block_size <= 1)
-		return data->read(dev, offset, buf, size);
+	if (data->block_size <= 1) {
+		ret = data->read(dev, offset, buf, size);
+		goto done;
+	}
 
 	block_start = offset / data->block_size;
 	block_offset = offset % data->block_size;
@@ -255,7 +257,9 @@
 		memcpy(buf, buffer + block_offset, size);
 
 	free(buffer);
-	return ret;
+
+done:
+	return ret < 0 ? ret : size;
 }
 
 static const struct misc_ops rockchip_efuse_ops = {
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c
index c19cd5c..4814e0e 100644
--- a/drivers/misc/rockchip-otp.c
+++ b/drivers/misc/rockchip-otp.c
@@ -89,7 +89,7 @@
 
 	for (i = 0; true; i += sizeof(data)) {
 		ret = misc_read(dev, i, &data, sizeof(data));
-		if (ret < 0)
+		if (ret <= 0)
 			return 0;
 
 		print_buffer(i, data, 1, sizeof(data), sizeof(data));
@@ -249,8 +249,10 @@
 
 	offset += data->offset;
 
-	if (data->block_size <= 1)
-		return data->read(dev, offset, buf, size);
+	if (data->block_size <= 1) {
+		ret = data->read(dev, offset, buf, size);
+		goto done;
+	}
 
 	block_start = offset / data->block_size;
 	block_offset = offset % data->block_size;
@@ -266,7 +268,9 @@
 		memcpy(buf, buffer + block_offset, size);
 
 	free(buffer);
-	return ret;
+
+done:
+	return ret < 0 ? ret : size;
 }
 
 static const struct misc_ops rockchip_otp_ops = {
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 59fb0fb..de01b96 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -476,6 +476,14 @@
 	  This enables support for the SDMA (Single Operation DMA) defined
 	  in the SD Host Controller Standard Specification Version 1.00 .
 
+config SPL_MMC_SDHCI_SDMA
+	bool "Support SDHCI SDMA in SPL"
+	depends on SPL_MMC && MMC_SDHCI
+	default y if MMC_SDHCI_SDMA
+	help
+	  This enables support for the SDMA (Single Operation DMA) defined
+	  in the SD Host Controller Standard Specification Version 1.00 in SPL.
+
 config MMC_SDHCI_ADMA
 	bool "Support SDHCI ADMA2"
 	depends on MMC_SDHCI
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index e1409dd..4f11097 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -47,51 +47,51 @@
 #define ARASAN_VENDOR_REGISTER		0x78
 #define ARASAN_VENDOR_ENHANCED_STROBE	BIT(0)
 
-/* DWC IP vendor area 1 pointer */
-#define DWCMSHC_P_VENDOR_AREA1		0xe8
-#define DWCMSHC_AREA1_MASK		GENMASK(11, 0)
-/* Offset inside the vendor area 1 */
-#define DWCMSHC_EMMC_CONTROL		0x2c
+/* Rockchip specific Registers */
+#define DWCMSHC_EMMC_EMMC_CTRL		0x52c
 #define DWCMSHC_CARD_IS_EMMC		BIT(0)
 #define DWCMSHC_ENHANCED_STROBE		BIT(8)
-
-/* Rockchip specific Registers */
 #define DWCMSHC_EMMC_DLL_CTRL		0x800
 #define DWCMSHC_EMMC_DLL_CTRL_RESET	BIT(1)
 #define DWCMSHC_EMMC_DLL_RXCLK		0x804
 #define DWCMSHC_EMMC_DLL_TXCLK		0x808
 #define DWCMSHC_EMMC_DLL_STRBIN		0x80c
-#define DECMSHC_EMMC_DLL_CMDOUT		0x810
+#define DWCMSHC_EMMC_DLL_CMDOUT		0x810
 #define DWCMSHC_EMMC_DLL_STATUS0	0x840
 #define DWCMSHC_EMMC_DLL_STATUS1	0x844
 #define DWCMSHC_EMMC_DLL_START		BIT(0)
-#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL	29
+#define DWCMSHC_EMMC_DLL_LOCKED		BIT(8)
+#define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
 #define DWCMSHC_EMMC_DLL_START_POINT	16
 #define DWCMSHC_EMMC_DLL_START_DEFAULT	5
 #define DWCMSHC_EMMC_DLL_INC_VALUE	2
 #define DWCMSHC_EMMC_DLL_INC		8
 #define DWCMSHC_EMMC_DLL_BYPASS		BIT(24)
 #define DWCMSHC_EMMC_DLL_DLYENA		BIT(27)
-#define DLL_TXCLK_TAPNUM_DEFAULT	0xA
-
-#define DLL_STRBIN_TAPNUM_DEFAULT	0x8
+#define DLL_RXCLK_NO_INVERTER		BIT(29)
+#define DLL_RXCLK_ORI_GATE		BIT(31)
+#define DLL_TXCLK_TAPNUM_DEFAULT	0x10
+#define DLL_TXCLK_TAPNUM_90_DEGREES	0x9
+#define DLL_TXCLK_TAPNUM_FROM_SW	BIT(24)
+#define DLL_TXCLK_NO_INVERTER		BIT(29)
+#define DLL_STRBIN_TAPNUM_DEFAULT	0x4
 #define DLL_STRBIN_TAPNUM_FROM_SW	BIT(24)
 #define DLL_STRBIN_DELAY_NUM_SEL	BIT(26)
 #define DLL_STRBIN_DELAY_NUM_OFFSET	16
-#define DLL_STRBIN_DELAY_NUM_DEFAULT	0x16
+#define DLL_STRBIN_DELAY_NUM_DEFAULT	0x10
+#define DLL_CMDOUT_TAPNUM_90_DEGREES	0x8
+#define DLL_CMDOUT_TAPNUM_FROM_SW	BIT(24)
+#define DLL_CMDOUT_SRC_CLK_NEG		BIT(28)
+#define DLL_CMDOUT_EN_SRC_CLK_NEG	BIT(29)
+#define DLL_CMDOUT_BOTH_CLK_EDGE	BIT(30)
 
-#define DLL_TXCLK_TAPNUM_FROM_SW	BIT(24)
-#define DWCMSHC_EMMC_DLL_LOCKED		BIT(8)
-#define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
-#define DLL_RXCLK_NO_INVERTER		1
-#define DLL_RXCLK_INVERTER		0
-#define DLL_RXCLK_ORI_GATE		BIT(31)
-#define DWCMSHC_ENHANCED_STROBE		BIT(8)
 #define DLL_LOCK_WO_TMOUT(x) \
 	((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
 	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
 #define ROCKCHIP_MAX_CLKS		3
 
+#define FLAG_INVERTER_FLAG_IN_RXCLK	BIT(0)
+
 struct rockchip_sdhc_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
@@ -112,7 +112,6 @@
 };
 
 struct sdhci_data {
-	int (*emmc_phy_init)(struct udevice *dev);
 	int (*get_phy)(struct udevice *dev);
 
 	/**
@@ -140,6 +139,9 @@
 	 */
 	int (*set_ios_post)(struct sdhci_host *host);
 
+	void (*set_clock)(struct sdhci_host *host, u32 div);
+	int (*config_dll)(struct sdhci_host *host, u32 clock, bool enable);
+
 	/**
 	 * set_enhanced_strobe() - Set HS400 Enhanced Strobe config
 	 *
@@ -152,12 +154,11 @@
 	 * Return: 0 if successful, -ve on error
 	 */
 	int (*set_enhanced_strobe)(struct sdhci_host *host);
-};
 
-static int rk3399_emmc_phy_init(struct udevice *dev)
-{
-	return 0;
-}
+	u32 flags;
+	u8 hs200_txclk_tapnum;
+	u8 hs400_txclk_tapnum;
+};
 
 static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
 {
@@ -294,30 +295,27 @@
 	return 0;
 }
 
-static int rk3568_emmc_phy_init(struct udevice *dev)
+static void rk3568_sdhci_set_clock(struct sdhci_host *host, u32 div)
 {
-	struct rockchip_sdhc *prv = dev_get_priv(dev);
-	struct sdhci_host *host = &prv->host;
-	u32 extra;
-
-	extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
-	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+	struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+	struct mmc *mmc = host->mmc;
+	ulong rate;
 
-	return 0;
+	rate = clk_set_rate(&priv->emmc_clk, mmc->clock);
+	if (IS_ERR_VALUE(rate))
+		printf("%s: Set clock rate failed: %ld\n", __func__, (long)rate);
 }
 
-static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
+static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
 {
 	struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+	struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+	struct mmc *mmc = host->mmc;
 	int val, ret;
-	u32 extra;
-
-	if (clock > host->max_clk)
-		clock = host->max_clk;
-	if (clock)
-		clk_set_rate(&priv->emmc_clk, clock);
+	u32 extra, txclk_tapnum;
 
-	sdhci_set_clock(host->mmc, clock);
+	if (!enable)
+		return 0;
 
 	if (clock >= 100 * MHz) {
 		/* reset DLL */
@@ -337,13 +335,28 @@
 		if (ret)
 			return ret;
 
-		extra = DWCMSHC_EMMC_DLL_DLYENA |
-			DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+		extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
+		if (data->flags & FLAG_INVERTER_FLAG_IN_RXCLK)
+			extra |= DLL_RXCLK_NO_INVERTER;
 		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
 
+		txclk_tapnum = data->hs200_txclk_tapnum;
+		if (mmc->selected_mode == MMC_HS_400 ||
+		    mmc->selected_mode == MMC_HS_400_ES) {
+			txclk_tapnum = data->hs400_txclk_tapnum;
+
+			extra = DLL_CMDOUT_SRC_CLK_NEG |
+				DLL_CMDOUT_BOTH_CLK_EDGE |
+				DWCMSHC_EMMC_DLL_DLYENA |
+				DLL_CMDOUT_TAPNUM_90_DEGREES |
+				DLL_CMDOUT_TAPNUM_FROM_SW;
+			sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CMDOUT);
+		}
+
 		extra = DWCMSHC_EMMC_DLL_DLYENA |
-			DLL_TXCLK_TAPNUM_DEFAULT |
-			DLL_TXCLK_TAPNUM_FROM_SW;
+			DLL_TXCLK_TAPNUM_FROM_SW |
+			DLL_TXCLK_NO_INVERTER |
+			txclk_tapnum;
 		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
 
 		extra = DWCMSHC_EMMC_DLL_DLYENA |
@@ -355,11 +368,11 @@
 		 * Disable DLL and reset both of sample and drive clock.
 		 * The bypass bit and start bit need to be set if DLL is not locked.
 		 */
-		sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START,
-			     DWCMSHC_EMMC_DLL_CTRL);
+		extra = DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START;
+		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
 		sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
-		sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
 		sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+		sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CMDOUT);
 		/*
 		 * Before switching to hs400es mode, the driver will enable
 		 * enhanced strobe first. PHY needs to configure the parameters
@@ -371,59 +384,57 @@
 		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
 	}
 
-	return 0;
-}
-
-static int rk3568_emmc_get_phy(struct udevice *dev)
-{
 	return 0;
 }
 
-static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
 {
 	struct mmc *mmc = host->mmc;
-	u32 vendor;
-	int reg;
-
-	reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
-	      + DWCMSHC_EMMC_CONTROL;
+	u32 reg;
 
-	vendor = sdhci_readl(host, reg);
-	if (mmc->selected_mode == MMC_HS_400_ES)
-		vendor |= DWCMSHC_ENHANCED_STROBE;
-	else
-		vendor &= ~DWCMSHC_ENHANCED_STROBE;
-	sdhci_writel(host, vendor, reg);
+	reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	reg &= ~SDHCI_CTRL_UHS_MASK;
 
-	return 0;
-}
+	switch (mmc->selected_mode) {
+	case UHS_SDR25:
+	case MMC_HS:
+	case MMC_HS_52:
+		reg |= SDHCI_CTRL_UHS_SDR25;
+		break;
+	case UHS_SDR50:
+		reg |= SDHCI_CTRL_UHS_SDR50;
+		break;
+	case UHS_DDR50:
+	case MMC_DDR_52:
+		reg |= SDHCI_CTRL_UHS_DDR50;
+		break;
+	case UHS_SDR104:
+	case MMC_HS_200:
+		reg |= SDHCI_CTRL_UHS_SDR104;
+		break;
+	case MMC_HS_400:
+	case MMC_HS_400_ES:
+		reg |= DWCMSHC_CTRL_HS400;
+		break;
+	default:
+		reg |= SDHCI_CTRL_UHS_SDR12;
+	}
 
-static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
-{
-	struct mmc *mmc = host->mmc;
-	uint clock = mmc->tran_speed;
-	u32 reg, vendor_reg;
+	sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
 
-	if (!clock)
-		clock = mmc->clock;
+	reg = sdhci_readw(host, DWCMSHC_EMMC_EMMC_CTRL);
 
-	rk3568_sdhci_emmc_set_clock(host, clock);
+	if (IS_MMC(mmc))
+		reg |= DWCMSHC_CARD_IS_EMMC;
+	else
+		reg &= ~DWCMSHC_CARD_IS_EMMC;
 
-	if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
-		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-		reg &= ~SDHCI_CTRL_UHS_MASK;
-		reg |= DWCMSHC_CTRL_HS400;
-		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+	if (mmc->selected_mode == MMC_HS_400_ES)
+		reg |= DWCMSHC_ENHANCED_STROBE;
+	else
+		reg &= ~DWCMSHC_ENHANCED_STROBE;
 
-		vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
-			     + DWCMSHC_EMMC_CONTROL;
-		/* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
-		reg = sdhci_readw(host, vendor_reg);
-		reg |= DWCMSHC_CARD_IS_EMMC;
-		sdhci_writew(host, reg, vendor_reg);
-	} else {
-		sdhci_set_uhs_timing(host);
-	}
+	sdhci_writew(host, reg, DWCMSHC_EMMC_EMMC_CTRL);
 
 	return 0;
 }
@@ -448,23 +459,32 @@
 	return 0;
 }
 
+static void rockchip_sdhci_set_clock(struct sdhci_host *host, u32 div)
+{
+	struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+	struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+	if (data->set_clock)
+		data->set_clock(host, div);
+}
+
 static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 {
-	struct sdhci_host *host = dev_get_priv(mmc->dev);
+	struct rockchip_sdhc *priv = dev_get_priv(mmc->dev);
+	struct sdhci_host *host = &priv->host;
 	char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
 	struct mmc_cmd cmd;
 	u32 ctrl, blk_size;
-	int ret = 0;
+	int ret;
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
-	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
 
 	blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 64);
-	if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && host->mmc->bus_width == 8)
+	if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && mmc->bus_width == 8)
 		blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 128);
 	sdhci_writew(host, blk_size, SDHCI_BLOCK_SIZE);
 	sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
@@ -474,40 +494,39 @@
 	cmd.cmdarg = 0;
 
 	do {
-		if (tuning_loop_counter-- == 0)
-			break;
-
-		mmc_send_cmd(mmc, &cmd, NULL);
-
-		if (opcode == MMC_CMD_SEND_TUNING_BLOCK)
-			/*
-			 * For tuning command, do not do busy loop. As tuning
-			 * is happening (CLK-DATA latching for setup/hold time
-			 * requirements), give time to complete
-			 */
-			udelay(1);
-
+		ret = mmc_send_cmd(mmc, &cmd, NULL);
 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		if (ret || tuning_loop_counter-- == 0)
+			break;
 	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
 
-	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
-		printf("%s:Tuning failed\n", __func__);
-		ret = -EIO;
-	}
+	if (ret || tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+		if (!ret)
+			ret = -EIO;
+		printf("%s: Tuning failed: %d\n", __func__, ret);
 
-	if (tuning_loop_counter < 0) {
 		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
-		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
+		ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 	}
 
 	/* Enable only interrupts served by the SD controller */
 	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
-	/* Mask all sdhci interrupt sources */
-	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
 
 	return ret;
 }
 
+static int rockchip_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
+{
+	struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+	struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+	if (data->config_dll)
+		return data->config_dll(host, clock, enable);
+
+	return 0;
+}
+
 static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
 {
 	struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
@@ -516,13 +535,15 @@
 	if (data->set_enhanced_strobe)
 		return data->set_enhanced_strobe(host);
 
-	return -ENOTSUPP;
+	return 0;
 }
 
 static struct sdhci_ops rockchip_sdhci_ops = {
-	.set_ios_post	= rockchip_sdhci_set_ios_post,
-	.platform_execute_tuning = &rockchip_sdhci_execute_tuning,
 	.set_control_reg = rockchip_sdhci_set_control_reg,
+	.set_ios_post = rockchip_sdhci_set_ios_post,
+	.set_clock = rockchip_sdhci_set_clock,
+	.platform_execute_tuning = rockchip_sdhci_execute_tuning,
+	.config_dll = rockchip_sdhci_config_dll,
 	.set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
 };
 
@@ -531,9 +552,9 @@
 	struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
-	struct rockchip_sdhc *prv = dev_get_priv(dev);
+	struct rockchip_sdhc *priv = dev_get_priv(dev);
 	struct mmc_config *cfg = &plat->cfg;
-	struct sdhci_host *host = &prv->host;
+	struct sdhci_host *host = &priv->host;
 	struct clk clk;
 	int ret;
 
@@ -547,8 +568,8 @@
 		printf("%s fail to get clk\n", __func__);
 	}
 
-	prv->emmc_clk = clk;
-	prv->dev = dev;
+	priv->emmc_clk = clk;
+	priv->dev = dev;
 
 	if (data->get_phy) {
 		ret = data->get_phy(dev);
@@ -556,17 +577,11 @@
 			return ret;
 	}
 
-	if (data->emmc_phy_init) {
-		ret = data->emmc_phy_init(dev);
-		if (ret)
-			return ret;
-	}
-
 	host->ops = &rockchip_sdhci_ops;
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
 
 	host->mmc = &plat->mmc;
-	host->mmc->priv = &prv->host;
+	host->mmc->priv = &priv->host;
 	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
@@ -574,14 +589,23 @@
 	if (ret)
 		return ret;
 
+	/*
+	 * Reading more than 4 blocks with a single CMD18 command in PIO mode
+	 * triggers Data End Bit Error on RK3568 and RK3588. Limit to reading
+	 * max 4 blocks in one command when using PIO mode.
+	 */
+	if (!(host->flags & USE_DMA))
+		cfg->b_max = 4;
+
 	return sdhci_probe(dev);
 }
 
 static int rockchip_sdhci_of_to_plat(struct udevice *dev)
 {
 	struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
+	struct rockchip_sdhc *priv = dev_get_priv(dev);
 	struct mmc_config *cfg = &plat->cfg;
+	struct sdhci_host *host = &priv->host;
 	int ret;
 
 	host->name = dev->name;
@@ -603,19 +627,28 @@
 
 static const struct sdhci_data rk3399_data = {
 	.get_phy = rk3399_emmc_get_phy,
-	.emmc_phy_init = rk3399_emmc_phy_init,
 	.set_control_reg = rk3399_sdhci_set_control_reg,
 	.set_ios_post = rk3399_sdhci_set_ios_post,
 	.set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe,
 };
 
 static const struct sdhci_data rk3568_data = {
-	.get_phy = rk3568_emmc_get_phy,
-	.emmc_phy_init = rk3568_emmc_phy_init,
 	.set_ios_post = rk3568_sdhci_set_ios_post,
-	.set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe,
+	.set_clock = rk3568_sdhci_set_clock,
+	.config_dll = rk3568_sdhci_config_dll,
+	.flags = FLAG_INVERTER_FLAG_IN_RXCLK,
+	.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+	.hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
 };
 
+static const struct sdhci_data rk3588_data = {
+	.set_ios_post = rk3568_sdhci_set_ios_post,
+	.set_clock = rk3568_sdhci_set_clock,
+	.config_dll = rk3568_sdhci_config_dll,
+	.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+	.hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES,
+};
+
 static const struct udevice_id sdhci_ids[] = {
 	{
 		.compatible = "arasan,sdhci-5.1",
@@ -625,6 +658,10 @@
 		.compatible = "rockchip,rk3568-dwcmshc",
 		.data = (ulong)&rk3568_data,
 	},
+	{
+		.compatible = "rockchip,rk3588-dwcmshc",
+		.data = (ulong)&rk3588_data,
+	},
 	{ }
 };
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c6b250b..9cbe126 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -70,7 +70,7 @@
 	}
 }
 
-#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
+#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
 static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
 			      int *is_aligned, int trans_bytes)
 {
@@ -177,7 +177,7 @@
 		}
 	} while (!(stat & SDHCI_INT_DATA_END));
 
-#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
+#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
 	dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
 			 mmc_get_dma_dir(data));
 #endif
@@ -518,6 +518,10 @@
 	reg &= ~SDHCI_CTRL_UHS_MASK;
 
 	switch (mmc->selected_mode) {
+	case UHS_SDR25:
+	case MMC_HS:
+		reg |= SDHCI_CTRL_UHS_SDR25;
+		break;
 	case UHS_SDR50:
 	case MMC_HS_52:
 		reg |= SDHCI_CTRL_UHS_SDR50;
@@ -682,6 +686,7 @@
 	if (!no_hispd_bit) {
 		if (mmc->selected_mode == MMC_HS ||
 		    mmc->selected_mode == SD_HS ||
+		    mmc->selected_mode == MMC_HS_52 ||
 		    mmc->selected_mode == MMC_DDR_52 ||
 		    mmc->selected_mode == MMC_HS_200 ||
 		    mmc->selected_mode == MMC_HS_400 ||
@@ -872,7 +877,7 @@
 #endif
 	debug("%s, caps: 0x%x\n", __func__, caps);
 
-#ifdef CONFIG_MMC_SDHCI_SDMA
+#if CONFIG_IS_ENABLED(MMC_SDHCI_SDMA)
 	if ((caps & SDHCI_CAN_DO_SDMA)) {
 		host->flags |= USE_SDMA;
 	} else {
@@ -882,7 +887,7 @@
 #endif
 #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
 	if (!(caps & SDHCI_CAN_DO_ADMA2)) {
-		printf("%s: Your controller doesn't support SDMA!!\n",
+		printf("%s: Your controller doesn't support ADMA!!\n",
 		       __func__);
 		return -EINVAL;
 	}
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 1305763..f87ca8c 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -4,6 +4,14 @@
 
 menu "Rockchip PHY driver"
 
+config PHY_ROCKCHIP_INNO_DSIDPHY
+	bool "Rockchip INNO DSIDPHY Driver"
+	depends on ARCH_ROCKCHIP
+	select PHY
+	select MIPI_DPHY_HELPERS
+	help
+	  Support for Rockchip MIPI DPHY with Innosilicon IP block.
+
 config PHY_ROCKCHIP_INNO_USB2
 	bool "Rockchip INNO USB2PHY Driver"
 	depends on ARCH_ROCKCHIP
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index a236877..25a803a 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
 obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3)	+= phy-rockchip-snps-pcie3.o
 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY)	+= phy-rockchip-inno-dsidphy.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
new file mode 100644
index 0000000..9ed7af0
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
@@ -0,0 +1,680 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
+ *
+ * Author: Wyon Bi <bivvy.bi@rock-chips.com>
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <div64.h>
+#include <generic-phy.h>
+#include <linux/kernel.h>
+#include <linux/iopoll.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <phy-mipi-dphy.h>
+#include <reset.h>
+
+#define UPDATE(x, h, l)	(((x) << (l)) & GENMASK((h), (l)))
+
+/*
+ * The offset address[7:0] is distributed two parts, one from the bit7 to bit5
+ * is the first address, the other from the bit4 to bit0 is the second address.
+ * when you configure the registers, you must set both of them. The Clock Lane
+ * and Data Lane use the same registers with the same second address, but the
+ * first address is different.
+ */
+#define FIRST_ADDRESS(x)		(((x) & 0x7) << 5)
+#define SECOND_ADDRESS(x)		(((x) & 0x1f) << 0)
+#define PHY_REG(first, second)		(FIRST_ADDRESS(first) | \
+					 SECOND_ADDRESS(second))
+
+/* Analog Register Part: reg00 */
+#define BANDGAP_POWER_MASK			BIT(7)
+#define BANDGAP_POWER_DOWN			BIT(7)
+#define BANDGAP_POWER_ON			0
+#define LANE_EN_MASK				GENMASK(6, 2)
+#define LANE_EN_CK				BIT(6)
+#define LANE_EN_3				BIT(5)
+#define LANE_EN_2				BIT(4)
+#define LANE_EN_1				BIT(3)
+#define LANE_EN_0				BIT(2)
+#define POWER_WORK_MASK				GENMASK(1, 0)
+#define POWER_WORK_ENABLE			UPDATE(1, 1, 0)
+#define POWER_WORK_DISABLE			UPDATE(2, 1, 0)
+/* Analog Register Part: reg01 */
+#define REG_SYNCRST_MASK			BIT(2)
+#define REG_SYNCRST_RESET			BIT(2)
+#define REG_SYNCRST_NORMAL			0
+#define REG_LDOPD_MASK				BIT(1)
+#define REG_LDOPD_POWER_DOWN			BIT(1)
+#define REG_LDOPD_POWER_ON			0
+#define REG_PLLPD_MASK				BIT(0)
+#define REG_PLLPD_POWER_DOWN			BIT(0)
+#define REG_PLLPD_POWER_ON			0
+/* Analog Register Part: reg03 */
+#define REG_FBDIV_HI_MASK			BIT(5)
+#define REG_FBDIV_HI(x)				UPDATE((x >> 8), 5, 5)
+#define REG_PREDIV_MASK				GENMASK(4, 0)
+#define REG_PREDIV(x)				UPDATE(x, 4, 0)
+/* Analog Register Part: reg04 */
+#define REG_FBDIV_LO_MASK			GENMASK(7, 0)
+#define REG_FBDIV_LO(x)				UPDATE(x, 7, 0)
+/* Analog Register Part: reg05 */
+#define SAMPLE_CLOCK_PHASE_MASK			GENMASK(6, 4)
+#define SAMPLE_CLOCK_PHASE(x)			UPDATE(x, 6, 4)
+#define CLOCK_LANE_SKEW_PHASE_MASK		GENMASK(2, 0)
+#define CLOCK_LANE_SKEW_PHASE(x)		UPDATE(x, 2, 0)
+/* Analog Register Part: reg06 */
+#define DATA_LANE_3_SKEW_PHASE_MASK		GENMASK(6, 4)
+#define DATA_LANE_3_SKEW_PHASE(x)		UPDATE(x, 6, 4)
+#define DATA_LANE_2_SKEW_PHASE_MASK		GENMASK(2, 0)
+#define DATA_LANE_2_SKEW_PHASE(x)		UPDATE(x, 2, 0)
+/* Analog Register Part: reg07 */
+#define DATA_LANE_1_SKEW_PHASE_MASK		GENMASK(6, 4)
+#define DATA_LANE_1_SKEW_PHASE(x)		UPDATE(x, 6, 4)
+#define DATA_LANE_0_SKEW_PHASE_MASK		GENMASK(2, 0)
+#define DATA_LANE_0_SKEW_PHASE(x)		UPDATE(x, 2, 0)
+/* Analog Register Part: reg08 */
+#define PLL_POST_DIV_ENABLE_MASK		BIT(5)
+#define PLL_POST_DIV_ENABLE			BIT(5)
+#define SAMPLE_CLOCK_DIRECTION_MASK		BIT(4)
+#define SAMPLE_CLOCK_DIRECTION_REVERSE		BIT(4)
+#define SAMPLE_CLOCK_DIRECTION_FORWARD		0
+#define LOWFRE_EN_MASK				BIT(5)
+#define PLL_OUTPUT_FREQUENCY_DIV_BY_1		0
+#define PLL_OUTPUT_FREQUENCY_DIV_BY_2		1
+/* Analog Register Part: reg0b */
+#define CLOCK_LANE_VOD_RANGE_SET_MASK		GENMASK(3, 0)
+#define CLOCK_LANE_VOD_RANGE_SET(x)		UPDATE(x, 3, 0)
+#define VOD_MIN_RANGE				0x1
+#define VOD_MID_RANGE				0x3
+#define VOD_BIG_RANGE				0x7
+#define VOD_MAX_RANGE				0xf
+/* Analog Register Part: reg1E */
+#define PLL_MODE_SEL_MASK			GENMASK(6, 5)
+#define PLL_MODE_SEL_LVDS_MODE			0
+#define PLL_MODE_SEL_MIPI_MODE			BIT(5)
+/* Digital Register Part: reg00 */
+#define REG_DIG_RSTN_MASK			BIT(0)
+#define REG_DIG_RSTN_NORMAL			BIT(0)
+#define REG_DIG_RSTN_RESET			0
+/* Digital Register Part: reg01 */
+#define INVERT_TXCLKESC_MASK			BIT(1)
+#define INVERT_TXCLKESC_ENABLE			BIT(1)
+#define INVERT_TXCLKESC_DISABLE			0
+#define INVERT_TXBYTECLKHS_MASK			BIT(0)
+#define INVERT_TXBYTECLKHS_ENABLE		BIT(0)
+#define INVERT_TXBYTECLKHS_DISABLE		0
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg05 */
+#define T_LPX_CNT_MASK				GENMASK(5, 0)
+#define T_LPX_CNT(x)				UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */
+#define T_HS_ZERO_CNT_HI_MASK			BIT(7)
+#define T_HS_ZERO_CNT_HI(x)			UPDATE(x, 7, 7)
+#define T_HS_PREPARE_CNT_MASK			GENMASK(6, 0)
+#define T_HS_PREPARE_CNT(x)			UPDATE(x, 6, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */
+#define T_HS_ZERO_CNT_LO_MASK			GENMASK(5, 0)
+#define T_HS_ZERO_CNT_LO(x)			UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */
+#define T_HS_TRAIL_CNT_MASK			GENMASK(6, 0)
+#define T_HS_TRAIL_CNT(x)			UPDATE(x, 6, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */
+#define T_HS_EXIT_CNT_LO_MASK			GENMASK(4, 0)
+#define T_HS_EXIT_CNT_LO(x)			UPDATE(x, 4, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */
+#define T_CLK_POST_CNT_LO_MASK			GENMASK(3, 0)
+#define T_CLK_POST_CNT_LO(x)			UPDATE(x, 3, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */
+#define LPDT_TX_PPI_SYNC_MASK			BIT(2)
+#define LPDT_TX_PPI_SYNC_ENABLE			BIT(2)
+#define LPDT_TX_PPI_SYNC_DISABLE		0
+#define T_WAKEUP_CNT_HI_MASK			GENMASK(1, 0)
+#define T_WAKEUP_CNT_HI(x)			UPDATE(x, 1, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0d */
+#define T_WAKEUP_CNT_LO_MASK			GENMASK(7, 0)
+#define T_WAKEUP_CNT_LO(x)			UPDATE(x, 7, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0e */
+#define T_CLK_PRE_CNT_MASK			GENMASK(3, 0)
+#define T_CLK_PRE_CNT(x)			UPDATE(x, 3, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */
+#define T_CLK_POST_CNT_HI_MASK			GENMASK(7, 6)
+#define T_CLK_POST_CNT_HI(x)			UPDATE(x, 7, 6)
+#define T_TA_GO_CNT_MASK			GENMASK(5, 0)
+#define T_TA_GO_CNT(x)				UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */
+#define T_HS_EXIT_CNT_HI_MASK			BIT(6)
+#define T_HS_EXIT_CNT_HI(x)			UPDATE(x, 6, 6)
+#define T_TA_SURE_CNT_MASK			GENMASK(5, 0)
+#define T_TA_SURE_CNT(x)			UPDATE(x, 5, 0)
+/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */
+#define T_TA_WAIT_CNT_MASK			GENMASK(5, 0)
+#define T_TA_WAIT_CNT(x)			UPDATE(x, 5, 0)
+/* LVDS Register Part: reg00 */
+#define LVDS_DIGITAL_INTERNAL_RESET_MASK	BIT(2)
+#define LVDS_DIGITAL_INTERNAL_RESET_DISABLE	BIT(2)
+#define LVDS_DIGITAL_INTERNAL_RESET_ENABLE	0
+/* LVDS Register Part: reg01 */
+#define LVDS_DIGITAL_INTERNAL_ENABLE_MASK	BIT(7)
+#define LVDS_DIGITAL_INTERNAL_ENABLE		BIT(7)
+#define LVDS_DIGITAL_INTERNAL_DISABLE		0
+/* LVDS Register Part: reg03 */
+#define MODE_ENABLE_MASK			GENMASK(2, 0)
+#define TTL_MODE_ENABLE				BIT(2)
+#define LVDS_MODE_ENABLE			BIT(1)
+#define MIPI_MODE_ENABLE			BIT(0)
+/* LVDS Register Part: reg0b */
+#define LVDS_LANE_EN_MASK			GENMASK(7, 3)
+#define LVDS_DATA_LANE0_EN			BIT(7)
+#define LVDS_DATA_LANE1_EN			BIT(6)
+#define LVDS_DATA_LANE2_EN			BIT(5)
+#define LVDS_DATA_LANE3_EN			BIT(4)
+#define LVDS_CLK_LANE_EN			BIT(3)
+#define LVDS_PLL_POWER_MASK			BIT(2)
+#define LVDS_PLL_POWER_OFF			BIT(2)
+#define LVDS_PLL_POWER_ON			0
+#define LVDS_BANDGAP_POWER_MASK			BIT(0)
+#define LVDS_BANDGAP_POWER_DOWN			BIT(0)
+#define LVDS_BANDGAP_POWER_ON			0
+
+#define DSI_PHY_RSTZ				0xa0
+#define PHY_ENABLECLK				BIT(2)
+#define DSI_PHY_STATUS				0xb0
+#define PHY_LOCK				BIT(0)
+
+#define PSEC_PER_SEC				1000000000000LL
+
+#define msleep(a)				udelay(a * 1000)
+
+enum phy_max_rate {
+	MAX_1GHZ,
+	MAX_2_5GHZ,
+};
+
+struct clk_hw {
+	struct clk_core *core;
+	struct clk *clk;
+	const struct clk_init_data *init;
+};
+
+struct inno_video_phy_plat_data {
+	const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;
+	const unsigned int num_timings;
+	enum phy_max_rate max_rate;
+};
+
+struct inno_dsidphy {
+	struct udevice *dev;
+	struct clk *ref_clk;
+	struct clk *pclk_phy;
+	struct clk *pclk_host;
+	const struct inno_video_phy_plat_data *pdata;
+	void __iomem *phy_base;
+	void __iomem *host_base;
+	struct reset_ctl *rst;
+	struct phy_configure_opts_mipi_dphy dphy_cfg;
+
+	struct clk *pll_clk;
+	struct {
+		struct clk_hw hw;
+		u8 prediv;
+		u16 fbdiv;
+		unsigned long rate;
+	} pll;
+};
+
+enum {
+	REGISTER_PART_ANALOG,
+	REGISTER_PART_DIGITAL,
+	REGISTER_PART_CLOCK_LANE,
+	REGISTER_PART_DATA0_LANE,
+	REGISTER_PART_DATA1_LANE,
+	REGISTER_PART_DATA2_LANE,
+	REGISTER_PART_DATA3_LANE,
+	REGISTER_PART_LVDS,
+};
+
+struct inno_mipi_dphy_timing {
+	unsigned long rate;
+	u8 lpx;
+	u8 hs_prepare;
+	u8 clk_lane_hs_zero;
+	u8 data_lane_hs_zero;
+	u8 hs_trail;
+};
+
+static const
+struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {
+	{ 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},
+	{ 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},
+	{ 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},
+	{ 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},
+	{ 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},
+	{ 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},
+	{ 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},
+	{ 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},
+	{ 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},
+	{ 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},
+	{1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},
+};
+
+static const
+struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {
+	{ 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},
+	{ 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},
+	{ 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},
+	{ 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},
+	{ 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},
+	{ 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},
+	{ 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},
+	{ 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},
+	{ 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},
+	{ 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},
+	{1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},
+	{1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},
+	{1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},
+	{1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},
+	{1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},
+	{2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},
+	{2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},
+	{2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},
+	{2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},
+};
+
+static void phy_update_bits(struct inno_dsidphy *inno,
+			    u8 first, u8 second, u8 mask, u8 val)
+{
+	u32 reg = PHY_REG(first, second) << 2;
+	unsigned int tmp, orig;
+
+	orig = readl(inno->phy_base + reg);
+	tmp = orig & ~mask;
+	tmp |= val & mask;
+	writel(tmp, inno->phy_base + reg);
+}
+
+static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,
+						unsigned long rate)
+{
+	unsigned long prate;
+	unsigned long best_freq = 0;
+	unsigned long fref, fout;
+	u8 min_prediv, max_prediv;
+	u8 _prediv, best_prediv = 1;
+	u16 _fbdiv, best_fbdiv = 1;
+	u32 min_delta = UINT_MAX;
+
+	/*
+	 * Upstream Linux tries to read the ref_clk, while the BSP
+	 * U-Boot hard-codes this as 24MHz. Try the first, and if that
+	 * fails do the second.
+	 */
+	prate = clk_get_rate(inno->ref_clk);
+	if (IS_ERR_VALUE(prate))
+		prate = 24000000;
+
+	/*
+	 * The PLL output frequency can be calculated using a simple formula:
+	 * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2
+	 * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2
+	 */
+	fref = prate / 2;
+	if (rate > 1000000000UL)
+		fout = 1000000000UL;
+	else
+		fout = rate;
+
+	/* 5Mhz < Fref / prediv < 40MHz */
+	min_prediv = DIV_ROUND_UP(fref, 40000000);
+	max_prediv = fref / 5000000;
+
+	for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
+		u64 tmp;
+		u32 delta;
+
+		tmp = (u64)fout * _prediv;
+		do_div(tmp, fref);
+		_fbdiv = tmp;
+
+		/*
+		 * The possible settings of feedback divider are
+		 * 12, 13, 14, 16, ~ 511
+		 */
+		if (_fbdiv == 15)
+			continue;
+
+		if (_fbdiv < 12 || _fbdiv > 511)
+			continue;
+
+		tmp = (u64)_fbdiv * fref;
+		do_div(tmp, _prediv);
+
+		delta = abs(fout - tmp);
+		if (!delta) {
+			best_prediv = _prediv;
+			best_fbdiv = _fbdiv;
+			best_freq = tmp;
+			break;
+		} else if (delta < min_delta) {
+			best_prediv = _prediv;
+			best_fbdiv = _fbdiv;
+			best_freq = tmp;
+			min_delta = delta;
+		}
+	}
+
+	if (best_freq) {
+		inno->pll.prediv = best_prediv;
+		inno->pll.fbdiv = best_fbdiv;
+		inno->pll.rate = best_freq;
+	}
+
+	return best_freq;
+}
+
+static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
+{
+	struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;
+	const struct inno_mipi_dphy_timing *timings;
+	u32 t_txbyteclkhs, t_txclkesc;
+	u32 txbyteclkhs, txclkesc, esc_clk_div;
+	u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;
+	u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;
+	unsigned int i;
+
+	timings = inno->pdata->inno_mipi_dphy_timing_table;
+
+	inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);
+
+	/* Select MIPI mode */
+	phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
+			MODE_ENABLE_MASK, MIPI_MODE_ENABLE);
+	/* Configure PLL */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
+			REG_PREDIV_MASK, REG_PREDIV(inno->pll.prediv));
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
+			REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,
+			REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));
+	if (inno->pdata->max_rate == MAX_2_5GHZ) {
+		phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,
+				PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
+		phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,
+				CLOCK_LANE_VOD_RANGE_SET_MASK,
+				CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
+	}
+	/* Enable PLL and LDO */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+			REG_LDOPD_MASK | REG_PLLPD_MASK,
+			REG_LDOPD_POWER_ON | REG_PLLPD_POWER_ON);
+	/* Reset analog */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+			REG_SYNCRST_MASK, REG_SYNCRST_RESET);
+	udelay(1);
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+			REG_SYNCRST_MASK, REG_SYNCRST_NORMAL);
+	/* Reset digital */
+	phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
+			REG_DIG_RSTN_MASK, REG_DIG_RSTN_RESET);
+	udelay(1);
+	phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
+			REG_DIG_RSTN_MASK, REG_DIG_RSTN_NORMAL);
+
+	txbyteclkhs = inno->pll.rate / 8;
+	t_txbyteclkhs = div_u64(PSEC_PER_SEC, txbyteclkhs);
+
+	esc_clk_div = DIV_ROUND_UP(txbyteclkhs, 20000000);
+	txclkesc = txbyteclkhs / esc_clk_div;
+	t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc);
+
+	/*
+	 * The value of counter for HS Ths-exit
+	 * Ths-exit = Tpin_txbyteclkhs * value
+	 */
+	hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs);
+	/*
+	 * The value of counter for HS Tclk-post
+	 * Tclk-post = Tpin_txbyteclkhs * value
+	 */
+	clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs);
+	/*
+	 * The value of counter for HS Tclk-pre
+	 * Tclk-pre = Tpin_txbyteclkhs * value
+	 */
+	clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);
+
+	/*
+	 * The value of counter for HS Tta-go
+	 * Tta-go for turnaround
+	 * Tta-go = Ttxclkesc * value
+	 */
+	ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc);
+	/*
+	 * The value of counter for HS Tta-sure
+	 * Tta-sure for turnaround
+	 * Tta-sure = Ttxclkesc * value
+	 */
+	ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc);
+	/*
+	 * The value of counter for HS Tta-wait
+	 * Tta-wait for turnaround
+	 * Tta-wait = Ttxclkesc * value
+	 */
+	ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);
+
+	for (i = 0; i < inno->pdata->num_timings; i++)
+		if (inno->pll.rate <= timings[i].rate)
+			break;
+
+	if (i == inno->pdata->num_timings)
+		--i;
+
+	/*
+	 * The value of counter for HS Tlpx Time
+	 * Tlpx = Tpin_txbyteclkhs * (2 + value)
+	 */
+	if (inno->pdata->max_rate == MAX_1GHZ) {
+		lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);
+		if (lpx >= 2)
+			lpx -= 2;
+	} else {
+		lpx = timings[i].lpx;
+	}
+
+	hs_prepare = timings[i].hs_prepare;
+	hs_trail = timings[i].hs_trail;
+	clk_lane_hs_zero = timings[i].clk_lane_hs_zero;
+	data_lane_hs_zero = timings[i].data_lane_hs_zero;
+	wakeup = 0x3ff;
+
+	for (i = REGISTER_PART_CLOCK_LANE; i <= REGISTER_PART_DATA3_LANE; i++) {
+		if (i == REGISTER_PART_CLOCK_LANE)
+			hs_zero = clk_lane_hs_zero;
+		else
+			hs_zero = data_lane_hs_zero;
+
+		phy_update_bits(inno, i, 0x05, T_LPX_CNT_MASK,
+				T_LPX_CNT(lpx));
+		phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,
+				T_HS_PREPARE_CNT(hs_prepare));
+		if (inno->pdata->max_rate == MAX_2_5GHZ)
+			phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,
+					T_HS_ZERO_CNT_HI(hs_zero >> 6));
+		phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,
+				T_HS_ZERO_CNT_LO(hs_zero));
+		phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,
+				T_HS_TRAIL_CNT(hs_trail));
+		if (inno->pdata->max_rate == MAX_2_5GHZ)
+			phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,
+					T_HS_EXIT_CNT_HI(hs_exit >> 5));
+		phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,
+				T_HS_EXIT_CNT_LO(hs_exit));
+		if (inno->pdata->max_rate == MAX_2_5GHZ)
+			phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,
+					T_CLK_POST_CNT_HI(clk_post >> 4));
+		phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,
+				T_CLK_POST_CNT_LO(clk_post));
+		phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,
+				T_CLK_PRE_CNT(clk_pre));
+		phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,
+				T_WAKEUP_CNT_HI(wakeup >> 8));
+		phy_update_bits(inno, i, 0x0d, T_WAKEUP_CNT_LO_MASK,
+				T_WAKEUP_CNT_LO(wakeup));
+		phy_update_bits(inno, i, 0x10, T_TA_GO_CNT_MASK,
+				T_TA_GO_CNT(ta_go));
+		phy_update_bits(inno, i, 0x11, T_TA_SURE_CNT_MASK,
+				T_TA_SURE_CNT(ta_sure));
+		phy_update_bits(inno, i, 0x12, T_TA_WAIT_CNT_MASK,
+				T_TA_WAIT_CNT(ta_wait));
+	}
+
+	/* Enable all lanes on analog part */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+			LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 |
+			LANE_EN_1 | LANE_EN_0);
+}
+
+static int inno_dsidphy_power_on(struct phy *phy)
+{
+	struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+
+	clk_prepare_enable(inno->pclk_phy);
+	clk_prepare_enable(inno->ref_clk);
+
+	/* Bandgap power on */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+			BANDGAP_POWER_MASK, BANDGAP_POWER_ON);
+	/* Enable power work */
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+			POWER_WORK_MASK, POWER_WORK_ENABLE);
+
+	inno_dsidphy_mipi_mode_enable(inno);
+
+	return 0;
+}
+
+static int inno_dsidphy_power_off(struct phy *phy)
+{
+	struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, LANE_EN_MASK, 0);
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
+			REG_LDOPD_MASK | REG_PLLPD_MASK,
+			REG_LDOPD_POWER_DOWN | REG_PLLPD_POWER_DOWN);
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+			POWER_WORK_MASK, POWER_WORK_DISABLE);
+	phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
+			BANDGAP_POWER_MASK, BANDGAP_POWER_DOWN);
+
+	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b, LVDS_LANE_EN_MASK, 0);
+	phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,
+			LVDS_DIGITAL_INTERNAL_ENABLE_MASK,
+			LVDS_DIGITAL_INTERNAL_DISABLE);
+	phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,
+			LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,
+			LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);
+
+	clk_disable_unprepare(inno->ref_clk);
+	clk_disable_unprepare(inno->pclk_phy);
+
+	return 0;
+}
+
+static int inno_dsidphy_configure(struct phy *phy, void *params)
+{
+	struct inno_dsidphy *inno = dev_get_priv(phy->dev);
+	struct phy_configure_opts_mipi_dphy *config = params;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(config);
+	if (ret)
+		return ret;
+
+	memcpy(&inno->dphy_cfg, config, sizeof(inno->dphy_cfg));
+
+	return 0;
+}
+
+static const struct phy_ops inno_dsidphy_ops = {
+	.configure = inno_dsidphy_configure,
+	.power_on = inno_dsidphy_power_on,
+	.power_off = inno_dsidphy_power_off,
+};
+
+static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {
+	.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,
+	.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),
+	.max_rate = MAX_1GHZ,
+};
+
+static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {
+	.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,
+	.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),
+	.max_rate = MAX_2_5GHZ,
+};
+
+static int inno_dsidphy_probe(struct udevice *dev)
+{
+	struct inno_dsidphy *inno = dev_get_priv(dev);
+	int ret;
+
+	inno->dev = dev;
+	inno->pdata = (const struct inno_video_phy_plat_data *)dev_get_driver_data(dev);
+
+	inno->phy_base = dev_read_addr_ptr(dev);
+	if (IS_ERR(inno->phy_base))
+		return PTR_ERR(inno->phy_base);
+
+	inno->ref_clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(inno->ref_clk)) {
+		ret = PTR_ERR(inno->ref_clk);
+		dev_err(dev, "failed to get ref clock: %d\n", ret);
+		return ret;
+	}
+
+	inno->pclk_phy = devm_clk_get(dev, "pclk");
+	if (IS_ERR(inno->pclk_phy)) {
+		ret = PTR_ERR(inno->pclk_phy);
+		dev_err(dev, "failed to get phy pclk: %d\n", ret);
+		return ret;
+	}
+
+	inno->rst = devm_reset_control_get(dev, "apb");
+	if (IS_ERR(inno->rst)) {
+		ret = PTR_ERR(inno->rst);
+		dev_err(dev, "failed to get system reset control: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id inno_dsidphy_of_match[] = {
+	{
+		.compatible = "rockchip,px30-dsi-dphy",
+		.data = (long)&max_1ghz_video_phy_plat_data,
+	}, {
+		.compatible = "rockchip,rk3128-dsi-dphy",
+		.data = (long)&max_1ghz_video_phy_plat_data,
+	}, {
+		.compatible = "rockchip,rk3368-dsi-dphy",
+		.data = (long)&max_1ghz_video_phy_plat_data,
+	}, {
+		.compatible = "rockchip,rk3568-dsi-dphy",
+		.data = (long)&max_2_5ghz_video_phy_plat_data,
+	},
+	{}
+};
+
+U_BOOT_DRIVER(rockchip_inno_dsidphy) = {
+	.name = "rockchip-inno-dsidphy",
+	.id = UCLASS_PHY,
+	.of_match = inno_dsidphy_of_match,
+	.probe = inno_dsidphy_probe,
+	.ops = &inno_dsidphy_ops,
+	.priv_auto = sizeof(struct inno_dsidphy),
+};
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 90461ae..c91f650 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -15,5 +15,6 @@
 obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
 obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
index 935aed9..314edb5 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3568.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
@@ -13,6 +13,12 @@
 #include "pinctrl-rockchip.h"
 
 static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
+	MR_PMUGRF(RK_GPIO0, RK_PB7, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(1, 0, 0)), /* PWM0 IO mux selection M0 */
+	MR_PMUGRF(RK_GPIO0, RK_PC7, RK_FUNC_2, 0x0110, RK_GENMASK_VAL(1, 0, 1)), /* PWM0 IO mux selection M1 */
+	MR_PMUGRF(RK_GPIO0, RK_PC0, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(3, 2, 0)), /* PWM1 IO mux selection M0 */
+	MR_PMUGRF(RK_GPIO0, RK_PB5, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(3, 2, 1)), /* PWM1 IO mux selection M1 */
+	MR_PMUGRF(RK_GPIO0, RK_PC1, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(5, 4, 0)), /* PWM2 IO mux selection M0 */
+	MR_PMUGRF(RK_GPIO0, RK_PB6, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(5, 4, 1)), /* PWM2 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */
@@ -33,30 +39,22 @@
 	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)), /* PWM4 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)), /* PWM4 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)), /* PWM5 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)), /* PWM5 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)), /* PWM6 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)), /* PWM6 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)), /* PWM7 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)), /* PWM7 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_5, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PD6, RK_FUNC_4, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC0, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC0, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC6, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */
@@ -68,7 +66,7 @@
 	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */
@@ -81,7 +79,7 @@
 	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO4, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
 	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */
@@ -94,8 +92,11 @@
 	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */
-	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)), /* PDM IO mux selection M0 */
-	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)), /* PDM IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO1, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PA0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 2)), /* PDM IO mux selection M2 */
 	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */
 	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */
 	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */
@@ -237,6 +238,15 @@
 		return ret;
 	}
 
+	/*
+	 * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
+	 * where that pull up value becomes 3.
+	 */
+	if (bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
+		if (ret == 1)
+			ret = 3;
+	}
+
 	/* enable the write to the equivalent lower bits */
 	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3588.c b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
new file mode 100644
index 0000000..548cf09
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3588.c
@@ -0,0 +1,353 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+#include <dt-bindings/pinctrl/rockchip.h>
+
+static int rk3588_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	struct regmap *regmap;
+	int iomux_num = (pin / 8);
+	int reg, ret, mask;
+	u8 bit;
+	u32 data;
+
+	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+	regmap = priv->regmap_base;
+	reg = bank->iomux[iomux_num].offset;
+	if ((pin % 8) >= 4)
+		reg += 0x4;
+	bit = (pin % 4) * 4;
+	mask = 0xf;
+
+	if (bank->bank_num == 0) {
+		if (pin >= RK_PB4 && pin <= RK_PD7) {
+			if (mux < 8) {
+				reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */
+				data = (mask << (bit + 16));
+				data |= (mux & mask) << bit;
+				ret = regmap_write(regmap, reg, data);
+			} else {
+				u32 reg0 = 0;
+
+				reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */
+				data = (mask << (bit + 16));
+				data |= 8 << bit;
+				ret = regmap_write(regmap, reg0, data);
+
+				reg0 = reg + 0x8000; /* BUS_IOC_BASE */
+				data = (mask << (bit + 16));
+				data |= mux << bit;
+				regmap = priv->regmap_base;
+				regmap_write(regmap, reg0, data);
+			}
+		} else {
+			data = (mask << (bit + 16));
+			data |= (mux & mask) << bit;
+			ret = regmap_write(regmap, reg, data);
+		}
+		return ret;
+	} else if (bank->bank_num > 0) {
+		reg += 0x8000; /* BUS_IOC_BASE */
+	}
+
+	data = (mask << (bit + 16));
+	data |= (mux & mask) << bit;
+
+	return regmap_write(regmap, reg, data);
+}
+
+#define RK3588_PMU1_IOC_REG		(0x0000)
+#define RK3588_PMU2_IOC_REG		(0x4000)
+#define RK3588_BUS_IOC_REG		(0x8000)
+#define RK3588_VCCIO1_4_IOC_REG		(0x9000)
+#define RK3588_VCCIO3_5_IOC_REG		(0xA000)
+#define RK3588_VCCIO2_IOC_REG		(0xB000)
+#define RK3588_VCCIO6_IOC_REG		(0xC000)
+#define RK3588_EMMC_IOC_REG		(0xD000)
+
+static const u32 rk3588_ds_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010},
+	{RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018},
+	{RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018},
+	{RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020},
+	{RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020},
+	{RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028},
+	{RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030},
+	{RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038},
+	{RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040},
+	{RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048},
+	{RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050},
+	{RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058},
+	{RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060},
+	{RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068},
+	{RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070},
+	{RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078},
+	{RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080},
+	{RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088},
+	{RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090},
+	{RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098},
+	{RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C},
+};
+
+static const u32 rk3588_p_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024},
+	{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120},
+	{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C},
+};
+
+static const u32 rk3588_smt_regs[][2] = {
+	{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030},
+	{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034},
+	{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040},
+	{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044},
+	{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048},
+	{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210},
+	{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214},
+	{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218},
+	{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C},
+	{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220},
+	{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220},
+	{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224},
+	{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228},
+	{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C},
+	{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230},
+	{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234},
+	{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238},
+	{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C},
+	{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240},
+	{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244},
+	{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248},
+	{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248},
+	{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C},
+};
+
+#define RK3588_PULL_BITS_PER_PIN		2
+#define RK3588_PULL_PINS_PER_REG		8
+
+static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num, struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
+	int i;
+
+	for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_p_regs[i][0]) {
+			*reg = rk3588_p_regs[i][1];
+			break;
+		}
+	}
+
+	assert(i >= 0);
+
+	*regmap = info->regmap_base;
+	*bit = pin_num % RK3588_PULL_PINS_PER_REG;
+	*bit *= RK3588_PULL_BITS_PER_PIN;
+}
+
+#define RK3588_DRV_BITS_PER_PIN		4
+#define RK3588_DRV_PINS_PER_REG		4
+
+static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
+	int i;
+
+	for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_ds_regs[i][0]) {
+			*reg = rk3588_ds_regs[i][1];
+			break;
+		}
+	}
+
+	assert(i >= 0);
+
+	*regmap = info->regmap_base;
+	*bit = pin_num % RK3588_DRV_PINS_PER_REG;
+	*bit *= RK3588_DRV_BITS_PER_PIN;
+}
+
+#define RK3588_SMT_BITS_PER_PIN		1
+#define RK3588_SMT_PINS_PER_REG		8
+
+static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num, struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+	u8 bank_num = bank->bank_num;
+	u32 pin = bank_num * 32 + pin_num;
+	int i;
+
+	for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) {
+		if (pin >= rk3588_smt_regs[i][0]) {
+			*reg = rk3588_smt_regs[i][1];
+			break;
+		}
+	}
+
+	assert(i >= 0);
+
+	*regmap = info->regmap_base;
+	*bit = pin_num % RK3588_SMT_PINS_PER_REG;
+	*bit *= RK3588_SMT_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rk3588_set_pull(struct rockchip_pin_bank *bank,
+			   int pin_num, int pull)
+{
+	struct regmap *regmap;
+	int reg, translated_pull;
+	u8 bit, type;
+	u32 data;
+
+	rk3588_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	type = bank->pull_type[pin_num / 8];
+	translated_pull = rockchip_translate_pull_value(type, pull);
+	if (translated_pull < 0) {
+		debug("unsupported pull setting %d\n", pull);
+		return -EINVAL;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (translated_pull << bit);
+
+	return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_drive(struct rockchip_pin_bank *bank,
+			    int pin_num, int strength)
+{
+	struct regmap *regmap;
+	int reg;
+	u32 data;
+	u8 bit;
+
+	rk3588_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RK3588_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (strength << bit);
+
+	return regmap_write(regmap, reg, data);
+}
+
+static int rk3588_set_schmitt(struct rockchip_pin_bank *bank,
+			      int pin_num, int enable)
+{
+	struct regmap *regmap;
+	int reg;
+	u32 data;
+	u8 bit;
+
+	rk3588_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RK3588_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (enable << bit);
+
+	return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank rk3588_pin_banks[] = {
+	RK3588_PIN_BANK_FLAGS(0, 32, "gpio0",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(1, 32, "gpio1",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(2, 32, "gpio2",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(3, 32, "gpio3",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+	RK3588_PIN_BANK_FLAGS(4, 32, "gpio4",
+			      IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
+};
+
+static const struct rockchip_pin_ctrl rk3588_pin_ctrl = {
+	.pin_banks		= rk3588_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rk3588_pin_banks),
+	.nr_pins		= 160,
+	.set_mux		= rk3588_set_mux,
+	.set_pull		= rk3588_set_pull,
+	.set_drive		= rk3588_set_drive,
+	.set_schmitt		= rk3588_set_schmitt,
+};
+
+static const struct udevice_id rk3588_pinctrl_ids[] = {
+	{
+		.compatible = "rockchip,rk3588-pinctrl",
+		.data = (ulong)&rk3588_pin_ctrl
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3588) = {
+	.name		= "rockchip_rk3588_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rk3588_pinctrl_ids,
+	.priv_auto	= sizeof(struct rockchip_pinctrl_priv),
+	.ops		= &rockchip_pinctrl_ops,
+#if CONFIG_IS_ENABLED(OF_REAL)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
index 8dfaba5..df7bc68 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
@@ -9,6 +9,171 @@
 #include <linux/bitops.h>
 #include <linux/types.h>
 
+#define RK_GPIO0_A0	0
+#define RK_GPIO0_A1	1
+#define RK_GPIO0_A2	2
+#define RK_GPIO0_A3	3
+#define RK_GPIO0_A4	4
+#define RK_GPIO0_A5	5
+#define RK_GPIO0_A6	6
+#define RK_GPIO0_A7	7
+#define RK_GPIO0_B0	8
+#define RK_GPIO0_B1	9
+#define RK_GPIO0_B2	10
+#define RK_GPIO0_B3	11
+#define RK_GPIO0_B4	12
+#define RK_GPIO0_B5	13
+#define RK_GPIO0_B6	14
+#define RK_GPIO0_B7	15
+#define RK_GPIO0_C0	16
+#define RK_GPIO0_C1	17
+#define RK_GPIO0_C2	18
+#define RK_GPIO0_C3	19
+#define RK_GPIO0_C4	20
+#define RK_GPIO0_C5	21
+#define RK_GPIO0_C6	22
+#define RK_GPIO0_C7	23
+#define RK_GPIO0_D0	24
+#define RK_GPIO0_D1	25
+#define RK_GPIO0_D2	26
+#define RK_GPIO0_D3	27
+#define RK_GPIO0_D4	28
+#define RK_GPIO0_D5	29
+#define RK_GPIO0_D6	30
+#define RK_GPIO0_D7	31
+
+#define RK_GPIO1_A0	32
+#define RK_GPIO1_A1	33
+#define RK_GPIO1_A2	34
+#define RK_GPIO1_A3	35
+#define RK_GPIO1_A4	36
+#define RK_GPIO1_A5	37
+#define RK_GPIO1_A6	38
+#define RK_GPIO1_A7	39
+#define RK_GPIO1_B0	40
+#define RK_GPIO1_B1	41
+#define RK_GPIO1_B2	42
+#define RK_GPIO1_B3	43
+#define RK_GPIO1_B4	44
+#define RK_GPIO1_B5	45
+#define RK_GPIO1_B6	46
+#define RK_GPIO1_B7	47
+#define RK_GPIO1_C0	48
+#define RK_GPIO1_C1	49
+#define RK_GPIO1_C2	50
+#define RK_GPIO1_C3	51
+#define RK_GPIO1_C4	52
+#define RK_GPIO1_C5	53
+#define RK_GPIO1_C6	54
+#define RK_GPIO1_C7	55
+#define RK_GPIO1_D0	56
+#define RK_GPIO1_D1	57
+#define RK_GPIO1_D2	58
+#define RK_GPIO1_D3	59
+#define RK_GPIO1_D4	60
+#define RK_GPIO1_D5	61
+#define RK_GPIO1_D6	62
+#define RK_GPIO1_D7	63
+
+#define RK_GPIO2_A0	64
+#define RK_GPIO2_A1	65
+#define RK_GPIO2_A2	66
+#define RK_GPIO2_A3	67
+#define RK_GPIO2_A4	68
+#define RK_GPIO2_A5	69
+#define RK_GPIO2_A6	70
+#define RK_GPIO2_A7	71
+#define RK_GPIO2_B0	72
+#define RK_GPIO2_B1	73
+#define RK_GPIO2_B2	74
+#define RK_GPIO2_B3	75
+#define RK_GPIO2_B4	76
+#define RK_GPIO2_B5	77
+#define RK_GPIO2_B6	78
+#define RK_GPIO2_B7	79
+#define RK_GPIO2_C0	80
+#define RK_GPIO2_C1	81
+#define RK_GPIO2_C2	82
+#define RK_GPIO2_C3	83
+#define RK_GPIO2_C4	84
+#define RK_GPIO2_C5	85
+#define RK_GPIO2_C6	86
+#define RK_GPIO2_C7	87
+#define RK_GPIO2_D0	88
+#define RK_GPIO2_D1	89
+#define RK_GPIO2_D2	90
+#define RK_GPIO2_D3	91
+#define RK_GPIO2_D4	92
+#define RK_GPIO2_D5	93
+#define RK_GPIO2_D6	94
+#define RK_GPIO2_D7	95
+
+#define RK_GPIO3_A0	96
+#define RK_GPIO3_A1	97
+#define RK_GPIO3_A2	98
+#define RK_GPIO3_A3	99
+#define RK_GPIO3_A4	100
+#define RK_GPIO3_A5	101
+#define RK_GPIO3_A6	102
+#define RK_GPIO3_A7	103
+#define RK_GPIO3_B0	104
+#define RK_GPIO3_B1	105
+#define RK_GPIO3_B2	106
+#define RK_GPIO3_B3	107
+#define RK_GPIO3_B4	108
+#define RK_GPIO3_B5	109
+#define RK_GPIO3_B6	110
+#define RK_GPIO3_B7	111
+#define RK_GPIO3_C0	112
+#define RK_GPIO3_C1	113
+#define RK_GPIO3_C2	114
+#define RK_GPIO3_C3	115
+#define RK_GPIO3_C4	116
+#define RK_GPIO3_C5	117
+#define RK_GPIO3_C6	118
+#define RK_GPIO3_C7	119
+#define RK_GPIO3_D0	120
+#define RK_GPIO3_D1	121
+#define RK_GPIO3_D2	122
+#define RK_GPIO3_D3	123
+#define RK_GPIO3_D4	124
+#define RK_GPIO3_D5	125
+#define RK_GPIO3_D6	126
+#define RK_GPIO3_D7	127
+
+#define RK_GPIO4_A0	128
+#define RK_GPIO4_A1	129
+#define RK_GPIO4_A2	130
+#define RK_GPIO4_A3	131
+#define RK_GPIO4_A4	132
+#define RK_GPIO4_A5	133
+#define RK_GPIO4_A6	134
+#define RK_GPIO4_A7	135
+#define RK_GPIO4_B0	136
+#define RK_GPIO4_B1	137
+#define RK_GPIO4_B2	138
+#define RK_GPIO4_B3	139
+#define RK_GPIO4_B4	140
+#define RK_GPIO4_B5	141
+#define RK_GPIO4_B6	142
+#define RK_GPIO4_B7	143
+#define RK_GPIO4_C0	144
+#define RK_GPIO4_C1	145
+#define RK_GPIO4_C2	146
+#define RK_GPIO4_C3	147
+#define RK_GPIO4_C4	148
+#define RK_GPIO4_C5	149
+#define RK_GPIO4_C6	150
+#define RK_GPIO4_C7	151
+#define RK_GPIO4_D0	152
+#define RK_GPIO4_D1	153
+#define RK_GPIO4_D2	154
+#define RK_GPIO4_D3	155
+#define RK_GPIO4_D4	156
+#define RK_GPIO4_D5	157
+#define RK_GPIO4_D6	158
+#define RK_GPIO4_D7	159
+
 #define RK_GENMASK_VAL(h, l, v) \
 	(GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
 
@@ -178,6 +343,25 @@
 			{ .drv_type = type2, .offset = -1 },		\
 			{ .drv_type = type3, .offset = -1 },		\
 		},							\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1,	\
+					iom2, iom3, pull0, pull1,	\
+					pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
 	}
 
 #define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
@@ -274,6 +458,9 @@
 #define MR_PMUGRF(ID, PIN, FUNC, REG, VAL)	\
 	PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
 
+#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P)			\
+	PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
+
 /**
  * struct rockchip_mux_recalced_data: recalculate a pin iomux data.
  * @num: bank number.
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 963a05c..8993245 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -2749,6 +2749,8 @@
 	/* detect cs1 row */
 	sdram_detect_cs1_row(cap_info, params->base.dramtype);
 
+	sdram_detect_high_row(cap_info);
+
 	/* detect die bw */
 	sdram_detect_dbw(cap_info, params->base.dramtype);
 
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
index 5dcf681..5deb5db 100644
--- a/drivers/rng/Kconfig
+++ b/drivers/rng/Kconfig
@@ -58,8 +58,9 @@
 	bool "Enable random number generator for rockchip crypto rng"
 	depends on ARCH_ROCKCHIP && DM_RNG
 	help
-	  Enable random number generator for rockchip.This driver is
-	  support rng module of crypto v1 and crypto v2.
+	  Enable random number generator for rockchip. This driver
+	  supports the rng module of crypto v1, crypto v2, and the
+	  trng module of the rk3588 series.
 
 config RNG_IPROC200
 	bool "Broadcom iProc RNG200 random number generator"
diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c
index 800150f..705b424 100644
--- a/drivers/rng/rockchip_rng.c
+++ b/drivers/rng/rockchip_rng.c
@@ -43,9 +43,41 @@
 #define CRYPTO_V2_RNG_DOUT_0			0x0410
 /* end of CRYPTO V2 register define */
 
+/* start of TRNG V1 register define */
+#define TRNG_V1_CTRL				0x0000
+#define TRNG_V1_CTRL_NOP			_SBF(0, 0x00)
+#define TRNG_V1_CTRL_RAND			_SBF(0, 0x01)
+#define TRNG_V1_CTRL_SEED			_SBF(0, 0x02)
+
+#define TRNG_V1_MODE				0x0008
+#define TRNG_V1_MODE_128_BIT			_SBF(3, 0x00)
+#define TRNG_V1_MODE_256_BIT			_SBF(3, 0x01)
+
+#define TRNG_V1_IE				0x0010
+#define TRNG_V1_IE_GLBL_EN			BIT(31)
+#define TRNG_V1_IE_SEED_DONE_EN			BIT(1)
+#define TRNG_V1_IE_RAND_RDY_EN			BIT(0)
+
+#define TRNG_V1_ISTAT				0x0014
+#define TRNG_V1_ISTAT_RAND_RDY			BIT(0)
+
+/* RAND0 ~ RAND7 */
+#define TRNG_V1_RAND0				0x0020
+#define TRNG_V1_RAND7				0x003C
+
+#define TRNG_V1_AUTO_RQSTS			0x0060
+
+#define TRNG_V1_VERSION				0x00F0
+#define TRNG_v1_VERSION_CODE			0x46BC
+/* end of TRNG V1 register define */
+
 #define RK_RNG_TIME_OUT	50000  /* max 50ms */
 
+#define trng_write(pdata, pos, val)	writel(val, (pdata)->base + (pos))
+#define trng_read(pdata, pos)		readl((pdata)->base + (pos))
+
 struct rk_rng_soc_data {
+	int (*rk_rng_init)(struct udevice *dev);
 	int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
 };
 
@@ -75,7 +107,7 @@
 	return 0;
 }
 
-static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len)
+static int rk_cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
 {
 	struct rk_rng_plat *pdata = dev_get_priv(dev);
 	u32 reg = 0;
@@ -106,7 +138,7 @@
 	return 0;
 }
 
-static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len)
+static int rk_cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
 {
 	struct rk_rng_plat *pdata = dev_get_priv(dev);
 	u32 reg = 0;
@@ -140,6 +172,63 @@
 	return retval;
 }
 
+static int rk_trngv1_init(struct udevice *dev)
+{
+	u32 status, version;
+	u32 auto_reseed_cnt = 1000;
+	struct rk_rng_plat *pdata = dev_get_priv(dev);
+
+	version = trng_read(pdata, TRNG_V1_VERSION);
+	if (version != TRNG_v1_VERSION_CODE) {
+		printf("wrong trng version, expected = %08x, actual = %08x",
+		       TRNG_V1_VERSION, version);
+		return -EFAULT;
+	}
+
+	/* wait in case of RND_RDY triggered at firs power on */
+	readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
+			   (status & TRNG_V1_ISTAT_RAND_RDY),
+			   RK_RNG_TIME_OUT);
+
+	/* clear RAND_RDY flag for first power on */
+	trng_write(pdata, TRNG_V1_ISTAT, status);
+
+	/* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
+	trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
+
+	return 0;
+}
+
+static int rk_trngv1_rng_read(struct udevice *dev, void *data, size_t len)
+{
+	struct rk_rng_plat *pdata = dev_get_priv(dev);
+	u32 reg = 0;
+	int retval;
+
+	if (len > RK_HW_RNG_MAX)
+		return -EINVAL;
+
+	trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
+	trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
+
+	retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
+				    (reg & TRNG_V1_ISTAT_RAND_RDY),
+				    RK_RNG_TIME_OUT);
+	/* clear ISTAT */
+	trng_write(pdata, TRNG_V1_ISTAT, reg);
+
+	if (retval)
+		goto exit;
+
+	rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
+
+exit:
+	/* close TRNG */
+	trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
+
+	return retval;
+}
+
 static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
 {
 	unsigned char *buf = data;
@@ -184,18 +273,27 @@
 static int rockchip_rng_probe(struct udevice *dev)
 {
 	struct rk_rng_plat *pdata = dev_get_priv(dev);
+	int ret = 0;
 
 	pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
 
-	return 0;
+	if (pdata->soc_data->rk_rng_init)
+		ret = pdata->soc_data->rk_rng_init(dev);
+
+	return ret;
 }
 
+static const struct rk_rng_soc_data rk_cryptov1_soc_data = {
+	.rk_rng_read = rk_cryptov1_rng_read,
+};
+
-static const struct rk_rng_soc_data rk_rng_v1_soc_data = {
-	.rk_rng_read = rk_v1_rng_read,
+static const struct rk_rng_soc_data rk_cryptov2_soc_data = {
+	.rk_rng_read = rk_cryptov2_rng_read,
 };
 
-static const struct rk_rng_soc_data rk_rng_v2_soc_data = {
-	.rk_rng_read = rk_v2_rng_read,
+static const struct rk_rng_soc_data rk_trngv1_soc_data = {
+	.rk_rng_init = rk_trngv1_init,
+	.rk_rng_read = rk_trngv1_rng_read,
 };
 
 static const struct dm_rng_ops rockchip_rng_ops = {
@@ -205,11 +303,15 @@
 static const struct udevice_id rockchip_rng_match[] = {
 	{
 		.compatible = "rockchip,cryptov1-rng",
-		.data = (ulong)&rk_rng_v1_soc_data,
+		.data = (ulong)&rk_cryptov1_soc_data,
 	},
 	{
 		.compatible = "rockchip,cryptov2-rng",
-		.data = (ulong)&rk_rng_v2_soc_data,
+		.data = (ulong)&rk_cryptov2_soc_data,
+	},
+	{
+		.compatible = "rockchip,trngv1",
+		.data = (ulong)&rk_trngv1_soc_data,
 	},
 	{},
 };
diff --git a/drivers/video/dw_mipi_dsi.c b/drivers/video/dw_mipi_dsi.c
index 6d9c5a9..a460692 100644
--- a/drivers/video/dw_mipi_dsi.c
+++ b/drivers/video/dw_mipi_dsi.c
@@ -806,6 +806,15 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * The Rockchip based devices don't have px_clk, so simply move
+	 * on.
+	 */
+	if (IS_ENABLED(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI)) {
+		dw_mipi_dsi_bridge_set(dsi, timings);
+		return 0;
+	}
+
 	ret = clk_get_by_name(device->dev, "px_clk", &clk);
 	if (ret) {
 		dev_err(device->dev, "peripheral clock get error %d\n", ret);
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index b038663..01804dc 100644
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -69,4 +69,12 @@
 	  support. The mipi controller and dphy on rk3288& rk3399 support
 	  16,18, 24 bits per pixel with up to 2k resolution ratio.
 
+config DISPLAY_ROCKCHIP_DW_MIPI
+	bool "Rockchip Designware MIPI"
+	depends on VIDEO_ROCKCHIP
+	select VIDEO_DW_MIPI_DSI
+	help
+	  Select the Designware MIPI DSI controller in use on some Rockchip
+	  SOCs.
+
 endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 9aced5e..8128289 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -15,4 +15,5 @@
 obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
 obj-mipi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_mipi.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o $(obj-mipi-y)
+obj-$(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI) += dw_mipi_dsi_rockchip.o
 endif
diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
new file mode 100644
index 0000000..ca548a6
--- /dev/null
+++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author(s): Chris Morgan <macromorgan@hotmail.com>
+ *
+ * This MIPI DSI controller driver is heavily based on the Linux Kernel
+ * driver from drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c and the
+ * U-Boot driver from drivers/video/stm32/stm32_dsi.c.
+ */
+
+#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
+
+#include <clk.h>
+#include <dm.h>
+#include <div64.h>
+#include <dsi_host.h>
+#include <generic-phy.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <phy-mipi-dphy.h>
+#include <reset.h>
+#include <video_bridge.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <linux/iopoll.h>
+
+#include <common.h>
+#include <log.h>
+#include <video.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+#include <linux/bitops.h>
+
+#define USEC_PER_SEC	1000000L
+
+/*
+ * DSI wrapper registers & bit definitions
+ * Note: registers are named as in the Reference Manual
+ */
+#define DSI_WCR		0x0404		/* Wrapper Control Reg */
+#define WCR_DSIEN	BIT(3)		/* DSI ENable */
+
+#define DSI_PHY_TST_CTRL0		0xb4
+#define PHY_TESTCLK			BIT(1)
+#define PHY_UNTESTCLK			0
+#define PHY_TESTCLR			BIT(0)
+#define PHY_UNTESTCLR			0
+
+#define DSI_PHY_TST_CTRL1		0xb8
+#define PHY_TESTEN			BIT(16)
+#define PHY_UNTESTEN			0
+#define PHY_TESTDOUT(n)			(((n) & 0xff) << 8)
+#define PHY_TESTDIN(n)			(((n) & 0xff) << 0)
+
+#define BYPASS_VCO_RANGE	BIT(7)
+#define VCO_RANGE_CON_SEL(val)	(((val) & 0x7) << 3)
+#define VCO_IN_CAP_CON_DEFAULT	(0x0 << 1)
+#define VCO_IN_CAP_CON_LOW	(0x1 << 1)
+#define VCO_IN_CAP_CON_HIGH	(0x2 << 1)
+#define REF_BIAS_CUR_SEL	BIT(0)
+
+#define CP_CURRENT_3UA	0x1
+#define CP_CURRENT_4_5UA	0x2
+#define CP_CURRENT_7_5UA	0x6
+#define CP_CURRENT_6UA	0x9
+#define CP_CURRENT_12UA	0xb
+#define CP_CURRENT_SEL(val)	((val) & 0xf)
+#define CP_PROGRAM_EN		BIT(7)
+
+#define LPF_RESISTORS_15_5KOHM	0x1
+#define LPF_RESISTORS_13KOHM	0x2
+#define LPF_RESISTORS_11_5KOHM	0x4
+#define LPF_RESISTORS_10_5KOHM	0x8
+#define LPF_RESISTORS_8KOHM	0x10
+#define LPF_PROGRAM_EN		BIT(6)
+#define LPF_RESISTORS_SEL(val)	((val) & 0x3f)
+
+#define HSFREQRANGE_SEL(val)	(((val) & 0x3f) << 1)
+
+#define INPUT_DIVIDER(val)	(((val) - 1) & 0x7f)
+#define LOW_PROGRAM_EN		0
+#define HIGH_PROGRAM_EN		BIT(7)
+#define LOOP_DIV_LOW_SEL(val)	(((val) - 1) & 0x1f)
+#define LOOP_DIV_HIGH_SEL(val)	((((val) - 1) >> 5) & 0xf)
+#define PLL_LOOP_DIV_EN		BIT(5)
+#define PLL_INPUT_DIV_EN	BIT(4)
+
+#define POWER_CONTROL		BIT(6)
+#define INTERNAL_REG_CURRENT	BIT(3)
+#define BIAS_BLOCK_ON		BIT(2)
+#define BANDGAP_ON		BIT(0)
+
+#define TER_RESISTOR_HIGH	BIT(7)
+#define	TER_RESISTOR_LOW	0
+#define LEVEL_SHIFTERS_ON	BIT(6)
+#define TER_CAL_DONE		BIT(5)
+#define SETRD_MAX		(0x7 << 2)
+#define POWER_MANAGE		BIT(1)
+#define TER_RESISTORS_ON	BIT(0)
+
+#define BIASEXTR_SEL(val)	((val) & 0x7)
+#define BANDGAP_SEL(val)	((val) & 0x7)
+#define TLP_PROGRAM_EN		BIT(7)
+#define THS_PRE_PROGRAM_EN	BIT(7)
+#define THS_ZERO_PROGRAM_EN	BIT(6)
+
+#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL		0x10
+#define PLL_CP_CONTROL_PLL_LOCK_BYPASS			0x11
+#define PLL_LPF_AND_CP_CONTROL				0x12
+#define PLL_INPUT_DIVIDER_RATIO				0x17
+#define PLL_LOOP_DIVIDER_RATIO				0x18
+#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL	0x19
+#define BANDGAP_AND_BIAS_CONTROL			0x20
+#define TERMINATION_RESISTER_CONTROL			0x21
+#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY		0x22
+#define HS_RX_CONTROL_OF_LANE_CLK			0x34
+#define HS_RX_CONTROL_OF_LANE_0				0x44
+#define HS_RX_CONTROL_OF_LANE_1				0x54
+#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL	0x60
+#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL	0x61
+#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL	0x62
+#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL	0x63
+#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL	0x64
+#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL		0x65
+#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL	0x70
+#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL	0x71
+#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL	0x72
+#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL	0x73
+#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL		0x74
+#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL		0x75
+#define HS_RX_CONTROL_OF_LANE_2				0x84
+#define HS_RX_CONTROL_OF_LANE_3				0x94
+
+#define RK3568_GRF_VO_CON2		0x0368
+#define RK3568_DSI0_SKEWCALHS		(0x1f << 11)
+#define RK3568_DSI0_FORCETXSTOPMODE	(0xf << 4)
+#define RK3568_DSI0_TURNDISABLE		BIT(2)
+#define RK3568_DSI0_FORCERXMODE		BIT(0)
+
+/*
+ * Note these registers do not appear in the datasheet, they are
+ * however present in the BSP driver which is where these values
+ * come from. Name GRF_VO_CON3 is assumed.
+ */
+#define RK3568_GRF_VO_CON3		0x36c
+#define RK3568_DSI1_SKEWCALHS		(0x1f << 11)
+#define RK3568_DSI1_FORCETXSTOPMODE	(0xf << 4)
+#define RK3568_DSI1_TURNDISABLE		BIT(2)
+#define RK3568_DSI1_FORCERXMODE		BIT(0)
+
+#define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
+
+/* Timeout for regulator on/off, pll lock/unlock & fifo empty */
+#define TIMEOUT_US	200000
+
+enum {
+	BANDGAP_97_07,
+	BANDGAP_98_05,
+	BANDGAP_99_02,
+	BANDGAP_100_00,
+	BANDGAP_93_17,
+	BANDGAP_94_15,
+	BANDGAP_95_12,
+	BANDGAP_96_10,
+};
+
+enum {
+	BIASEXTR_87_1,
+	BIASEXTR_91_5,
+	BIASEXTR_95_9,
+	BIASEXTR_100,
+	BIASEXTR_105_94,
+	BIASEXTR_111_88,
+	BIASEXTR_118_8,
+	BIASEXTR_127_7,
+};
+
+struct rockchip_dw_dsi_chip_data {
+	u32 reg;
+
+	u32 lcdsel_grf_reg;
+	u32 lcdsel_big;
+	u32 lcdsel_lit;
+
+	u32 enable_grf_reg;
+	u32 enable;
+
+	u32 lanecfg1_grf_reg;
+	u32 lanecfg1;
+	u32 lanecfg2_grf_reg;
+	u32 lanecfg2;
+
+	unsigned int flags;
+	unsigned int max_data_lanes;
+};
+
+struct dw_rockchip_dsi_priv {
+	struct mipi_dsi_device device;
+	void __iomem *base;
+	struct udevice *panel;
+
+	/* Optional external dphy */
+	struct phy phy;
+	struct phy_configure_opts_mipi_dphy phy_opts;
+
+	struct clk *pclk;
+	struct clk *ref;
+	struct reset_ctl *rst;
+	unsigned int lane_mbps; /* per lane */
+	u16 input_div;
+	u16 feedback_div;
+	const struct rockchip_dw_dsi_chip_data *cdata;
+	struct udevice *dsi_host;
+};
+
+static inline void dsi_write(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 val)
+{
+	writel(val, dsi->base + reg);
+}
+
+static inline u32 dsi_read(struct dw_rockchip_dsi_priv *dsi, u32 reg)
+{
+	return readl(dsi->base + reg);
+}
+
+static inline void dsi_set(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
+{
+	dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);
+}
+
+static inline void dsi_clear(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
+{
+	dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);
+}
+
+static inline void dsi_update_bits(struct dw_rockchip_dsi_priv *dsi, u32 reg,
+				   u32 mask, u32 val)
+{
+	dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
+}
+
+static void dw_mipi_dsi_phy_write(struct dw_rockchip_dsi_priv *dsi,
+				  u8 test_code,
+				  u8 test_data)
+{
+	/*
+	 * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
+	 * is latched internally as the current test code. Test data is
+	 * programmed internally by rising edge on TESTCLK.
+	 */
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) |
+					  PHY_TESTDIN(test_code));
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR);
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
+					  PHY_TESTDIN(test_data));
+
+	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
+}
+
+struct dphy_pll_parameter_map {
+	unsigned int max_mbps;
+	u8 hsfreqrange;
+	u8 icpctrl;
+	u8 lpfctrl;
+};
+
+/* The table is based on 27MHz DPHY pll reference clock. */
+static const struct dphy_pll_parameter_map dppa_map[] = {
+	{  89, 0x00, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+	{  99, 0x10, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+	{ 109, 0x20, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
+	{ 129, 0x01, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 139, 0x11, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 149, 0x21, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 169, 0x02, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+	{ 179, 0x12, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+	{ 199, 0x22, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
+	{ 219, 0x03, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+	{ 239, 0x13, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+	{ 249, 0x23, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
+	{ 269, 0x04, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
+	{ 299, 0x14, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
+	{ 329, 0x05, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 359, 0x15, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 399, 0x25, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
+	{ 449, 0x06, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 499, 0x16, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 549, 0x07, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
+	{ 599, 0x17, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
+	{ 649, 0x08, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 699, 0x18, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 749, 0x09, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 799, 0x19, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 849, 0x29, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 899, 0x39, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
+	{ 949, 0x0a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+	{ 999, 0x1a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+	{1049, 0x2a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+	{1099, 0x3a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
+	{1149, 0x0b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1199, 0x1b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1249, 0x2b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1299, 0x3b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1349, 0x0c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1399, 0x1c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1449, 0x2c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
+	{1500, 0x3c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }
+};
+
+static int max_mbps_to_parameter(unsigned int max_mbps)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dppa_map); i++)
+		if (dppa_map[i].max_mbps >= max_mbps)
+			return i;
+
+	return -EINVAL;
+}
+
+/*
+ * ns2bc - Nanoseconds to byte clock cycles
+ */
+static inline unsigned int ns2bc(struct dw_rockchip_dsi_priv *dsi, int ns)
+{
+	return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
+}
+
+/*
+ * ns2ui - Nanoseconds to UI time periods
+ */
+static inline unsigned int ns2ui(struct dw_rockchip_dsi_priv *dsi, int ns)
+{
+	return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000);
+}
+
+static int dsi_phy_init(void *priv_data)
+{
+	struct mipi_dsi_device *device = priv_data;
+	struct udevice *dev = device->dev;
+	struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+	int ret, i, vco;
+
+	if (&dsi->phy) {
+		ret = generic_phy_configure(&dsi->phy, &dsi->phy_opts);
+		if (ret) {
+			dev_err(dsi->dsi_host,
+				"Configure external dphy fail %d\n",
+				ret);
+			return ret;
+		}
+
+		ret = generic_phy_power_on(&dsi->phy);
+		if (ret) {
+			dev_err(dsi->dsi_host,
+				"Generic phy power on fail %d\n", ret);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	/*
+	 * Get vco from frequency(lane_mbps)
+	 * vco	frequency table
+	 * 000 - between   80 and  200 MHz
+	 * 001 - between  200 and  300 MHz
+	 * 010 - between  300 and  500 MHz
+	 * 011 - between  500 and  700 MHz
+	 * 100 - between  700 and  900 MHz
+	 * 101 - between  900 and 1100 MHz
+	 * 110 - between 1100 and 1300 MHz
+	 * 111 - between 1300 and 1500 MHz
+	 */
+	vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
+
+	i = max_mbps_to_parameter(dsi->lane_mbps);
+	if (i < 0) {
+		dev_err(dsi->dsi_host,
+			"failed to get parameter for %dmbps clock\n",
+			dsi->lane_mbps);
+		return i;
+	}
+
+	dw_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL,
+			      BYPASS_VCO_RANGE |
+			      VCO_RANGE_CON_SEL(vco) |
+			      VCO_IN_CAP_CON_LOW |
+			      REF_BIAS_CUR_SEL);
+
+	dw_mipi_dsi_phy_write(dsi, PLL_CP_CONTROL_PLL_LOCK_BYPASS,
+			      CP_CURRENT_SEL(dppa_map[i].icpctrl));
+	dw_mipi_dsi_phy_write(dsi, PLL_LPF_AND_CP_CONTROL,
+			      CP_PROGRAM_EN | LPF_PROGRAM_EN |
+			      LPF_RESISTORS_SEL(dppa_map[i].lpfctrl));
+
+	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
+			      HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
+
+	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_DIVIDER_RATIO,
+			      INPUT_DIVIDER(dsi->input_div));
+	dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
+			      LOOP_DIV_LOW_SEL(dsi->feedback_div) |
+			      LOW_PROGRAM_EN);
+	/*
+	 * We need set PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL immediately
+	 * to make the configured LSB effective according to IP simulation
+	 * and lab test results.
+	 * Only in this way can we get correct mipi phy pll frequency.
+	 */
+	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
+			      PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+	dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
+			      LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
+			      HIGH_PROGRAM_EN);
+	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
+			      PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+
+	dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
+			      LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7));
+	dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
+			      HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10));
+
+	dw_mipi_dsi_phy_write(dsi, BANDGAP_AND_BIAS_CONTROL,
+			      POWER_CONTROL | INTERNAL_REG_CURRENT |
+			      BIAS_BLOCK_ON | BANDGAP_ON);
+
+	dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
+			      TER_RESISTOR_LOW | TER_CAL_DONE |
+			      SETRD_MAX | TER_RESISTORS_ON);
+	dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
+			      TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON |
+			      SETRD_MAX | POWER_MANAGE |
+			      TER_RESISTORS_ON);
+
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL,
+			      TLP_PROGRAM_EN | ns2bc(dsi, 500));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL,
+			      THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL,
+			      THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL,
+			      THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL,
+			      BIT(5) | ns2bc(dsi, 100));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL,
+			      BIT(5) | (ns2bc(dsi, 60) + 7));
+
+	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL,
+			      TLP_PROGRAM_EN | ns2bc(dsi, 500));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL,
+			      THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 20));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL,
+			      THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL,
+			      THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
+	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL,
+			      BIT(5) | ns2bc(dsi, 100));
+
+	return ret;
+}
+
+static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
+{
+	struct mipi_dsi_device *device = priv_data;
+	struct udevice *dev = device->dev;
+	struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+
+	dev_dbg(dev, "Set mode %p enable %ld\n", dsi,
+		mode_flags & MIPI_DSI_MODE_VIDEO);
+
+	if (!dsi)
+		return;
+
+	/*
+	 * DSI wrapper must be enabled in video mode & disabled in command mode.
+	 * If wrapper is enabled in command mode, the display controller
+	 * register access will hang. Note that this was carried over from the
+	 * stm32 dsi driver and is unknown if necessary for Rockchip.
+	 */
+
+	if (mode_flags & MIPI_DSI_MODE_VIDEO)
+		dsi_set(dsi, DSI_WCR, WCR_DSIEN);
+	else
+		dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
+}
+
+static int
+dw_mipi_dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
+			  u32 lanes, u32 format, unsigned int *lane_mbps)
+{
+	struct mipi_dsi_device *device = priv_data;
+	struct udevice *dev = device->dev;
+	struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
+	int bpp;
+	unsigned long mpclk, tmp;
+	unsigned int target_mbps = 1000;
+	unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps;
+	unsigned long best_freq = 0;
+	unsigned long fvco_min, fvco_max, fin, fout;
+	unsigned int min_prediv, max_prediv;
+	unsigned int _prediv, best_prediv;
+	unsigned long _fbdiv, best_fbdiv;
+	unsigned long min_delta = ULONG_MAX;
+	unsigned int pllref_clk;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(format);
+	if (bpp < 0) {
+		dev_err(dsi->dsi_host,
+			"failed to get bpp for pixel format %d\n",
+			format);
+		return bpp;
+	}
+
+	mpclk = DIV_ROUND_UP(timings->pixelclock.typ, 1000);
+	if (mpclk) {
+		/* take 1 / 0.8, since mbps must big than bandwidth of RGB */
+		tmp = (mpclk * (bpp / lanes) * 10 / 8) / 1000;
+		if (tmp < max_mbps)
+			target_mbps = tmp;
+		else
+			dev_err(dsi->dsi_host,
+				"DPHY clock frequency is out of range\n");
+	}
+
+	/* for external phy only the mipi_dphy_config is necessary */
+	if (&dsi->phy) {
+		phy_mipi_dphy_get_default_config(timings->pixelclock.typ  * 10 / 8,
+						 bpp, lanes,
+						 &dsi->phy_opts);
+		dsi->lane_mbps = target_mbps;
+		*lane_mbps = dsi->lane_mbps;
+
+		return 0;
+	}
+
+	pllref_clk = clk_get_rate(dsi->ref);
+	fout = target_mbps * USEC_PER_SEC;
+
+	/* constraint: 5Mhz <= Fref / N <= 40MHz */
+	min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC);
+	max_prediv = fin / (5 * USEC_PER_SEC);
+
+	/* constraint: 80MHz <= Fvco <= 1500Mhz */
+	fvco_min = 80 * USEC_PER_SEC;
+	fvco_max = 1500 * USEC_PER_SEC;
+
+	for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
+		u64 tmp;
+		u32 delta;
+		/* Fvco = Fref * M / N */
+		tmp = (u64)fout * _prediv;
+		do_div(tmp, fin);
+		_fbdiv = tmp;
+		/*
+		 * Due to the use of a "by 2 pre-scaler," the range of the
+		 * feedback multiplication value M is limited to even division
+		 * numbers, and m must be greater than 6, not bigger than 512.
+		 */
+		if (_fbdiv < 6 || _fbdiv > 512)
+			continue;
+
+		_fbdiv += _fbdiv % 2;
+
+		tmp = (u64)_fbdiv * fin;
+		do_div(tmp, _prediv);
+		if (tmp < fvco_min || tmp > fvco_max)
+			continue;
+
+		delta = abs(fout - tmp);
+		if (delta < min_delta) {
+			best_prediv = _prediv;
+			best_fbdiv = _fbdiv;
+			min_delta = delta;
+			best_freq = tmp;
+		}
+	}
+
+	if (best_freq) {
+		dsi->lane_mbps = DIV_ROUND_UP(best_freq, USEC_PER_SEC);
+		*lane_mbps = dsi->lane_mbps;
+		dsi->input_div = best_prediv;
+		dsi->feedback_div = best_fbdiv;
+	} else {
+		dev_err(dsi->dsi_host, "Can not find best_freq for DPHY\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct hstt {
+	unsigned int maxfreq;
+	struct mipi_dsi_phy_timing timing;
+};
+
+#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp)	\
+{					\
+	.maxfreq = _maxfreq,		\
+	.timing = {			\
+		.clk_lp2hs = _c_lp2hs,	\
+		.clk_hs2lp = _c_hs2lp,	\
+		.data_lp2hs = _d_lp2hs,	\
+		.data_hs2lp = _d_hs2lp,	\
+	}				\
+}
+
+/*
+ * Table A-3 High-Speed Transition Times
+ * (Note spacing is deliberate for readability).
+ */
+static struct hstt hstt_table[] = {
+	HSTT(  90,  32, 20,  26, 13),
+	HSTT( 100,  35, 23,  28, 14),
+	HSTT( 110,  32, 22,  26, 13),
+	HSTT( 130,  31, 20,  27, 13),
+	HSTT( 140,  33, 22,  26, 14),
+	HSTT( 150,  33, 21,  26, 14),
+	HSTT( 170,  32, 20,  27, 13),
+	HSTT( 180,  36, 23,  30, 15),
+	HSTT( 200,  40, 22,  33, 15),
+	HSTT( 220,  40, 22,  33, 15),
+	HSTT( 240,  44, 24,  36, 16),
+	HSTT( 250,  48, 24,  38, 17),
+	HSTT( 270,  48, 24,  38, 17),
+	HSTT( 300,  50, 27,  41, 18),
+	HSTT( 330,  56, 28,  45, 18),
+	HSTT( 360,  59, 28,  48, 19),
+	HSTT( 400,  61, 30,  50, 20),
+	HSTT( 450,  67, 31,  55, 21),
+	HSTT( 500,  73, 31,  59, 22),
+	HSTT( 550,  79, 36,  63, 24),
+	HSTT( 600,  83, 37,  68, 25),
+	HSTT( 650,  90, 38,  73, 27),
+	HSTT( 700,  95, 40,  77, 28),
+	HSTT( 750, 102, 40,  84, 28),
+	HSTT( 800, 106, 42,  87, 30),
+	HSTT( 850, 113, 44,  93, 31),
+	HSTT( 900, 118, 47,  98, 32),
+	HSTT( 950, 124, 47, 102, 34),
+	HSTT(1000, 130, 49, 107, 35),
+	HSTT(1050, 135, 51, 111, 37),
+	HSTT(1100, 139, 51, 114, 38),
+	HSTT(1150, 146, 54, 120, 40),
+	HSTT(1200, 153, 57, 125, 41),
+	HSTT(1250, 158, 58, 130, 42),
+	HSTT(1300, 163, 58, 135, 44),
+	HSTT(1350, 168, 60, 140, 45),
+	HSTT(1400, 172, 64, 144, 47),
+	HSTT(1450, 176, 65, 148, 48),
+	HSTT(1500, 181, 66, 153, 50)
+};
+
+static int dw_mipi_dsi_rockchip_get_timing(void *priv_data,
+					   unsigned int lane_mbps,
+					   struct mipi_dsi_phy_timing *timing)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
+		if (lane_mbps < hstt_table[i].maxfreq)
+			break;
+
+	if (i == ARRAY_SIZE(hstt_table))
+		i--;
+
+	*timing = hstt_table[i].timing;
+
+	return 0;
+}
+
+static const struct mipi_dsi_phy_ops dsi_rockchip_phy_ops = {
+	.init = dsi_phy_init,
+	.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
+	.get_timing = dw_mipi_dsi_rockchip_get_timing,
+	.post_set_mode = dsi_phy_post_set_mode,
+};
+
+static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
+{
+	struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_device *device = &priv->device;
+	struct mipi_dsi_panel_plat *mplat;
+	struct display_timing timings;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_PANEL, &priv->panel);
+	if (ret) {
+		dev_err(dev, "panel device error %d\n", ret);
+		return ret;
+	}
+
+	mplat = dev_get_plat(priv->panel);
+	mplat->device = &priv->device;
+	device->lanes = mplat->lanes;
+	device->format = mplat->format;
+	device->mode_flags = mplat->mode_flags;
+
+	ret = panel_get_display_timing(priv->panel, &timings);
+	if (ret) {
+		ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
+						   0, &timings);
+		if (ret) {
+			dev_err(dev, "decode display timing error %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
+	if (ret) {
+		dev_err(dev, "No video dsi host detected %d\n", ret);
+		return ret;
+	}
+
+	ret = dsi_host_init(priv->dsi_host, device, &timings, 4,
+			    &dsi_rockchip_phy_ops);
+	if (ret) {
+		dev_err(dev, "failed to initialize mipi dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_mipi_dsi_rockchip_set_bl(struct udevice *dev, int percent)
+{
+	struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	/*
+	 * Allow backlight to be optional, since this driver may be
+	 * used to simply detect a panel rather than bring one up.
+	 */
+	ret = panel_enable_backlight(priv->panel);
+	if ((ret) && (ret != -ENOSYS)) {
+		dev_err(dev, "panel %s enable backlight error %d\n",
+			priv->panel->name, ret);
+		return ret;
+	}
+
+	ret = dsi_host_enable(priv->dsi_host);
+	if (ret) {
+		dev_err(dev, "failed to enable mipi dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void dw_mipi_dsi_rockchip_config(struct dw_rockchip_dsi_priv *dsi)
+{
+	if (dsi->cdata->lanecfg1_grf_reg)
+		dsi_write(dsi, dsi->cdata->lanecfg1_grf_reg,
+			  dsi->cdata->lanecfg1);
+
+	if (dsi->cdata->lanecfg2_grf_reg)
+		dsi_write(dsi, dsi->cdata->lanecfg2_grf_reg,
+			  dsi->cdata->lanecfg2);
+
+	if (dsi->cdata->enable_grf_reg)
+		dsi_write(dsi, dsi->cdata->enable_grf_reg,
+			  dsi->cdata->enable);
+}
+
+static int dw_mipi_dsi_rockchip_bind(struct udevice *dev)
+{
+	int ret;
+
+	ret = device_bind_driver_to_node(dev, "dw_mipi_dsi", "dsihost",
+					 dev_ofnode(dev), NULL);
+	if (ret) {
+		dev_err(dev, "failed to bind driver to node\n");
+		return ret;
+	}
+
+	return dm_scan_fdt_dev(dev);
+}
+
+static int dw_mipi_dsi_rockchip_probe(struct udevice *dev)
+{
+	struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_device *device = &priv->device;
+	int ret, i;
+	const struct rockchip_dw_dsi_chip_data *cdata =
+			(const struct rockchip_dw_dsi_chip_data *)dev_get_driver_data(dev);
+
+	device->dev = dev;
+
+	priv->base = (void *)dev_read_addr(dev);
+	if ((fdt_addr_t)priv->base == FDT_ADDR_T_NONE) {
+		dev_err(dev, "dsi dt register address error\n");
+		return -EINVAL;
+	}
+
+	i = 0;
+	while (cdata[i].reg) {
+		if (cdata[i].reg == (fdt_addr_t)priv->base) {
+			priv->cdata = &cdata[i];
+			break;
+		}
+
+		i++;
+	}
+
+	if (!priv->cdata) {
+		dev_err(dev, "no dsi-config for %s node\n", dev->name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Get an optional external dphy. The external dphy stays as
+	 * NULL if it's not initialized.
+	 */
+	ret = generic_phy_get_by_name(dev, "dphy", &priv->phy);
+	if ((ret) && (ret != -ENODEV)) {
+		dev_err(dev, "failed to get mipi dphy: %d\n", ret);
+		return -EINVAL;
+	}
+
+	priv->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(priv->pclk)) {
+		dev_err(dev, "peripheral clock get error %d\n", ret);
+		return ret;
+	}
+
+	/* Get a ref clock only if not using an external phy. */
+	if (&priv->phy) {
+		dev_dbg(dev, "setting priv->ref to NULL\n");
+		priv->ref = NULL;
+
+	} else {
+		priv->ref = devm_clk_get(dev, "ref");
+		if (ret) {
+			dev_err(dev, "pll reference clock get error %d\n", ret);
+			return ret;
+		}
+	}
+
+	priv->rst = devm_reset_control_get_by_index(device->dev, 0);
+	if (IS_ERR(priv->rst)) {
+		dev_err(dev, "missing dsi hardware reset\n");
+		return ret;
+	}
+
+	/* Reset */
+	reset_deassert(priv->rst);
+
+	dw_mipi_dsi_rockchip_config(priv);
+
+	return 0;
+}
+
+struct video_bridge_ops dw_mipi_dsi_rockchip_ops = {
+	.attach = dw_mipi_dsi_rockchip_attach,
+	.set_backlight = dw_mipi_dsi_rockchip_set_bl,
+};
+
+static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
+	{
+		.reg = 0xfe060000,
+		.lanecfg1_grf_reg = RK3568_GRF_VO_CON2,
+		.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS |
+					  RK3568_DSI0_FORCETXSTOPMODE |
+					  RK3568_DSI0_TURNDISABLE |
+					  RK3568_DSI0_FORCERXMODE),
+		.max_data_lanes = 4,
+	},
+	{
+		.reg = 0xfe070000,
+		.lanecfg1_grf_reg = RK3568_GRF_VO_CON3,
+		.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS |
+					  RK3568_DSI1_FORCETXSTOPMODE |
+					  RK3568_DSI1_TURNDISABLE |
+					  RK3568_DSI1_FORCERXMODE),
+		.max_data_lanes = 4,
+	},
+	{ /* sentinel */ }
+};
+
+static const struct udevice_id dw_mipi_dsi_rockchip_dt_ids[] = {
+	{ .compatible = "rockchip,rk3568-mipi-dsi",
+	  .data = (long)&rk3568_chip_data,
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(dw_mipi_dsi_rockchip) = {
+	.name			= "dw-mipi-dsi-rockchip",
+	.id			= UCLASS_VIDEO_BRIDGE,
+	.of_match		= dw_mipi_dsi_rockchip_dt_ids,
+	.bind			= dw_mipi_dsi_rockchip_bind,
+	.probe			= dw_mipi_dsi_rockchip_probe,
+	.ops			= &dw_mipi_dsi_rockchip_ops,
+	.priv_auto		= sizeof(struct dw_rockchip_dsi_priv),
+};
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index bc98ab6..e21ac7e 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -307,7 +307,8 @@
 		      __func__, dev_read_name(dev));
 		return -EINVAL;
 	}
-	if (strstr(compat, "edp")) {
+	if (strstr(compat, "edp") ||
+	    strstr(compat, "rk3288-dp")) {
 		vop_id = VOP_MODE_EDP;
 	} else if (strstr(compat, "mipi")) {
 		vop_id = VOP_MODE_MIPI;
diff --git a/include/configs/evb_rk3588.h b/include/configs/evb_rk3588.h
new file mode 100644
index 0000000..4568e2c
--- /dev/null
+++ b/include/configs/evb_rk3588.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __EVB_RK3588_H
+#define __EVB_RK3588_H
+
+#include <configs/rk3588_common.h>
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
+
+#endif
diff --git a/include/configs/rk3568_common.h b/include/configs/rk3568_common.h
index a5e1dde..d6b5e7d 100644
--- a/include/configs/rk3568_common.h
+++ b/include/configs/rk3568_common.h
@@ -17,10 +17,15 @@
 
 #define ENV_MEM_LAYOUT_SETTINGS		\
 	"scriptaddr=0x00c00000\0"	\
+	"script_offset_f=0xffe000\0"	\
+	"script_size_f=0x2000\0"	\
 	"pxefile_addr_r=0x00e00000\0"	\
 	"fdt_addr_r=0x0a100000\0"	\
+	"fdtoverlay_addr_r=0x02000000\0"	\
 	"kernel_addr_r=0x02080000\0"	\
-	"ramdisk_addr_r=0x0a200000\0"
+	"ramdisk_addr_r=0x0a200000\0"	\
+	"kernel_comp_addr_r=0x08000000\0"	\
+	"kernel_comp_size=0x2000000\0"
 
 #include <config_distro_bootcmd.h>
 #define CFG_EXTRA_ENV_SETTINGS		\
diff --git a/include/configs/rk3588_common.h b/include/configs/rk3588_common.h
index abd2013..b9f4271 100644
--- a/include/configs/rk3588_common.h
+++ b/include/configs/rk3588_common.h
@@ -16,10 +16,15 @@
 
 #define ENV_MEM_LAYOUT_SETTINGS		\
 	"scriptaddr=0x00c00000\0"	\
+	"script_offset_f=0xffe000\0"	\
+	"script_size_f=0x2000\0"	\
 	"pxefile_addr_r=0x00e00000\0"	\
 	"fdt_addr_r=0x0a100000\0"	\
+	"fdtoverlay_addr_r=0x02000000\0"	\
 	"kernel_addr_r=0x02080000\0"	\
-	"ramdisk_addr_r=0x0a200000\0"
+	"ramdisk_addr_r=0x0a200000\0"	\
+	"kernel_comp_addr_r=0x08000000\0"	\
+	"kernel_comp_size=0x2000000\0"
 
 #include <config_distro_bootcmd.h>
 #define CFG_EXTRA_ENV_SETTINGS \