Merge branch 'master' of git://git.denx.de/u-boot-usb

- DaVinci USB updates
- Various OHCI fixes
- Gadget fixes
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index ad4d235..7c806ee 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -108,6 +108,9 @@
 	rk3399-ficus.dtb \
 	rk3399-firefly.dtb \
 	rk3399-gru-bob.dtb \
+	rk3399-khadas-edge.dtb \
+	rk3399-khadas-edge-captain.dtb \
+	rk3399-khadas-edge-v.dtb \
 	rk3399-nanopc-t4.dtb \
 	rk3399-nanopi-m4.dtb \
 	rk3399-nanopi-neo4.dtb \
diff --git a/arch/arm/dts/rk3328-evb-u-boot.dtsi b/arch/arm/dts/rk3328-evb-u-boot.dtsi
new file mode 100644
index 0000000..58ebf52
--- /dev/null
+++ b/arch/arm/dts/rk3328-evb-u-boot.dtsi
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
+#include "rk3328-sdram-ddr3-666.dtsi"
+
+/ {
+	aliases {
+		mmc0 = &emmc;
+		mmc1 = &sdmmc;
+	};
+
+	chosen {
+		u-boot,spl-boot-order = &emmc, &sdmmc;
+	};
+};
+
+&cru {
+	u-boot,dm-pre-reloc;
+};
+
+&uart2 {
+	u-boot,dm-pre-reloc;
+};
+
+&emmc {
+	u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3328-rock64-u-boot.dtsi b/arch/arm/dts/rk3328-rock64-u-boot.dtsi
index b077436..dbcce6a 100644
--- a/arch/arm/dts/rk3328-rock64-u-boot.dtsi
+++ b/arch/arm/dts/rk3328-rock64-u-boot.dtsi
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
+#include "rk3328-sdram-lpddr3-1600.dtsi"
+
 / {
 	aliases {
 		mmc0 = &emmc;
@@ -25,10 +27,8 @@
 
 &emmc {
 	u-boot,dm-pre-reloc;
-	fifo-mode;
 };
 
 &sdmmc {
 	u-boot,dm-pre-reloc;
-	fifo-mode;
 };
diff --git a/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi b/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi
new file mode 100644
index 0000000..d99e7e0
--- /dev/null
+++ b/arch/arm/dts/rk3328-sdram-ddr3-666.dtsi
@@ -0,0 +1,215 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+&dmc {
+	rockchip,sdram-params = <
+		0x1
+		0xC
+		0x3
+		0x1
+		0x0
+		0x0
+		0x10
+		0x10
+		0
+
+		0x9028b189
+		0x00000000
+		0x00000021
+		0x00000482
+		0x00000015
+		0x00000222
+		0x000000ff
+
+		333
+		3
+		0
+
+		0x00000000
+		0x43041001
+		0x00000064
+		0x0028003b
+		0x000000d0
+		0x00020053
+		0x000000d4
+		0x00020000
+		0x000000d8
+		0x00000100
+		0x000000dc
+		0x03200000
+		0x000000e0
+		0x00000000
+		0x000000e4
+		0x00090000
+		0x000000f4
+		0x000f011f
+		0x00000100
+		0x07090b06
+		0x00000104
+		0x00050209
+		0x00000108
+		0x03030407
+		0x0000010c
+		0x00202006
+		0x00000110
+		0x03020204
+		0x00000114
+		0x03030202
+		0x00000120
+		0x00000903
+		0x00000180
+		0x00800020
+		0x00000184
+		0x00000000
+		0x00000190
+		0x07010001
+		0x00000198
+		0x05001100
+		0x000001a0
+		0xc0400003
+		0x00000240
+		0x06000604
+		0x00000244
+		0x00000201
+		0x00000250
+		0x00000f00
+		0x00000490
+		0x00000001
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+
+		0x00000004
+		0x0000000a
+		0x00000028
+		0x00000006
+		0x0000002c
+		0x00000000
+		0x00000030
+		0x00000005
+		0xffffffff
+		0xffffffff
+
+		0x77
+		0x88
+		0x79
+		0x79
+		0x87
+		0x97
+		0x87
+		0x78
+		0x77
+		0x78
+		0x87
+		0x88
+		0x87
+		0x87
+		0x77
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+	>;
+};
diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi
new file mode 100644
index 0000000..cc0011c
--- /dev/null
+++ b/arch/arm/dts/rk3328-sdram-lpddr3-1600.dtsi
@@ -0,0 +1,215 @@
+/*
+ * (C) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+&dmc {
+	rockchip,sdram-params = <
+		0x1
+		0xC
+		0x3
+		0x1
+		0x0
+		0x0
+		0x10
+		0x10
+		0
+
+		0x98899459
+		0x00000000
+		0x0000002e
+		0x00000544
+		0x00000015
+		0x00000432
+		0x000000ff
+
+		800
+		6
+		1
+
+		0x00000000
+		0x43041008
+		0x00000064
+		0x00300054
+		0x000000d0
+		0x00500002
+		0x000000d4
+		0x00010000
+		0x000000d8
+		0x00000e03
+		0x000000dc
+		0x0043001a
+		0x000000e0
+		0x00010000
+		0x000000e4
+		0x000e0005
+		0x000000f4
+		0x000f011f
+		0x00000100
+		0x0b141b11
+		0x00000104
+		0x0003031a
+		0x00000108
+		0x03060809
+		0x0000010c
+		0x00606000
+		0x00000110
+		0x08020409
+		0x00000114
+		0x01010606
+		0x00000118
+		0x02020004
+		0x00000120
+		0x00000404
+		0x00000138
+		0x00000058
+		0x00000180
+		0x00900024
+		0x00000184
+		0x01400000
+		0x00000190
+		0x07050002
+		0x00000198
+		0x05001100
+		0x000001a0
+		0xc0400003
+		0x00000240
+		0x0a020b28
+		0x00000244
+		0x00000101
+		0x00000250
+		0x00000f00
+		0x00000490
+		0x00000001
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+
+		0x00000004
+		0x0000000b
+		0x00000028
+		0x0000000c
+		0x0000002c
+		0x00000000
+		0x00000030
+		0x00000006
+		0xffffffff
+		0xffffffff
+
+		0x77
+		0x88
+		0x79
+		0x79
+		0x87
+		0x97
+		0x87
+		0x78
+		0x77
+		0x78
+		0x87
+		0x88
+		0x87
+		0x87
+		0x77
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+	>;
+};
diff --git a/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi b/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi
new file mode 100644
index 0000000..62d809e
--- /dev/null
+++ b/arch/arm/dts/rk3328-sdram-lpddr3-666.dtsi
@@ -0,0 +1,215 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+&dmc {
+	rockchip,sdram-params = <
+		0x1
+		0xC
+		0x3
+		0x1
+		0x0
+		0x0
+		0x10
+		0x10
+		0
+
+		0x0c48a18a
+		0x00000000
+		0x00000021
+		0x00000482
+		0x00000015
+		0x0000021a
+		0x000000ff
+
+		333
+		6
+		0
+
+		0x00000000
+		0xc3040008
+		0x00000064
+		0x00140023
+		0x000000d0
+		0x00220002
+		0x000000d4
+		0x00010000
+		0x000000d8
+		0x00000703
+		0x000000dc
+		0x00830004
+		0x000000e0
+		0x00010000
+		0x000000e4
+		0x00070003
+		0x00000100
+		0x06090b07
+		0x00000104
+		0x0002020b
+		0x00000108
+		0x02030506
+		0x0000010c
+		0x00505000
+		0x00000110
+		0x03020204
+		0x00000114
+		0x01010303
+		0x00000118
+		0x02020003
+		0x00000120
+		0x00000303
+		0x00000138
+		0x00000025
+		0x00000180
+		0x003c000f
+		0x00000184
+		0x00900000
+		0x00000190
+		0x07020000
+		0x00000198
+		0x05001100
+		0x000001a0
+		0xc0400003
+		0x00000240
+		0x0900090c
+		0x00000244
+		0x00000101
+		0x00000250
+		0x00000f00
+		0x00000490
+		0x00000001
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+		0xffffffff
+
+		0x00000004
+		0x0000000b
+		0x00000028
+		0x00000006
+		0x0000002c
+		0x00000000
+		0x00000030
+		0x00000003
+		0xffffffff
+		0xffffffff
+
+		0x77
+		0x88
+		0x79
+		0x79
+		0x87
+		0x97
+		0x87
+		0x78
+		0x77
+		0x78
+		0x87
+		0x88
+		0x87
+		0x87
+		0x77
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x78
+		0x77
+		0x79
+		0x9
+
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x78
+		0x69
+		0x9
+
+		0x77
+		0x78
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x77
+		0x79
+		0x9
+	>;
+};
diff --git a/arch/arm/dts/rk3328.dtsi b/arch/arm/dts/rk3328.dtsi
index 2d80add..a080ae8 100644
--- a/arch/arm/dts/rk3328.dtsi
+++ b/arch/arm/dts/rk3328.dtsi
@@ -351,10 +351,15 @@
 		status = "disabled";
 	};
 
-	dmc: dmc@ff400000 {
+	dmc: dmc {
 		u-boot,dm-pre-reloc;
-		compatible = "rockchip,rk3328-dmc", "syscon";
-		reg = <0x0 0xff400000 0x0 0x1000>;
+		compatible = "rockchip,rk3328-dmc";
+		reg = <0x0 0xff400000 0x0 0x1000
+		       0x0 0xff780000 0x0 0x3000
+		       0x0 0xff100000 0x0 0x1000
+		       0x0 0xff440000 0x0 0x1000
+		       0x0 0xff720000 0x0 0x1000
+		       0x0 0xff798000 0x0 0x1000>;
 	};
 
 	cru: clock-controller@ff440000 {
diff --git a/arch/arm/dts/rk3399-ficus-u-boot.dtsi b/arch/arm/dts/rk3399-ficus-u-boot.dtsi
index eab86bd..f3f7aa7 100644
--- a/arch/arm/dts/rk3399-ficus-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-ficus-u-boot.dtsi
@@ -3,4 +3,11 @@
  * Copyright (C) 2019 Jagan Teki <jagan@amarulasolutions.com>
  */
 
+#include "rk3399-u-boot.dtsi"
 #include "rk3399-sdram-ddr3-1600.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/rk3399-khadas-edge-captain-u-boot.dtsi b/arch/arm/dts/rk3399-khadas-edge-captain-u-boot.dtsi
new file mode 100644
index 0000000..ca1bbff
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge-captain-u-boot.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Nick Xie <nick@khadas.com>
+ */
+
+#include "rk3399-khadas-edge-u-boot.dtsi"
diff --git a/arch/arm/dts/rk3399-khadas-edge-captain.dts b/arch/arm/dts/rk3399-khadas-edge-captain.dts
new file mode 100644
index 0000000..8302e51
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge-captain.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Shenzhen Wesion Technology Co., Ltd.
+ * (https://www.khadas.com)
+ */
+
+/dts-v1/;
+#include "rk3399-khadas-edge.dtsi"
+
+/ {
+	model = "Khadas Edge-Captain";
+	compatible = "khadas,edge-captain", "rockchip,rk3399";
+};
+
+&gmac {
+	status = "okay";
+};
+
+&pcie_phy {
+	status = "okay";
+};
+
+&pcie0 {
+	ep-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+	num-lanes = <4>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi b/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
new file mode 100644
index 0000000..35b9fdd
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Nick Xie <nick@khadas.com>
+ */
+
+#include "rk3399-u-boot.dtsi"
+#include "rk3399-sdram-lpddr4-100.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/rk3399-khadas-edge-v-u-boot.dtsi b/arch/arm/dts/rk3399-khadas-edge-v-u-boot.dtsi
new file mode 100644
index 0000000..ca1bbff
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge-v-u-boot.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Nick Xie <nick@khadas.com>
+ */
+
+#include "rk3399-khadas-edge-u-boot.dtsi"
diff --git a/arch/arm/dts/rk3399-khadas-edge-v.dts b/arch/arm/dts/rk3399-khadas-edge-v.dts
new file mode 100644
index 0000000..f5dcb99
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge-v.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Shenzhen Wesion Technology Co., Ltd.
+ * (https://www.khadas.com)
+ */
+
+/dts-v1/;
+#include "rk3399-khadas-edge.dtsi"
+
+/ {
+	model = "Khadas Edge-V";
+	compatible = "khadas,edge-v", "rockchip,rk3399";
+};
+
+&gmac {
+	status = "okay";
+};
+
+&pcie_phy {
+	status = "okay";
+};
+
+&pcie0 {
+	ep-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+	num-lanes = <4>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-khadas-edge.dts b/arch/arm/dts/rk3399-khadas-edge.dts
new file mode 100644
index 0000000..31616e7
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Shenzhen Wesion Technology Co., Ltd.
+ * (https://www.khadas.com)
+ */
+
+/dts-v1/;
+#include "rk3399-khadas-edge.dtsi"
+
+/ {
+	model = "Khadas Edge";
+	compatible = "khadas,edge", "rockchip,rk3399";
+};
diff --git a/arch/arm/dts/rk3399-khadas-edge.dtsi b/arch/arm/dts/rk3399-khadas-edge.dtsi
new file mode 100644
index 0000000..4944d78
--- /dev/null
+++ b/arch/arm/dts/rk3399-khadas-edge.dtsi
@@ -0,0 +1,804 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Shenzhen Wesion Technology Co., Ltd.
+ * (https://www.khadas.com)
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+	chosen {
+		stdout-path = "serial2:1500000n8";
+	};
+
+	clkin_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "clkin_gmac";
+		#clock-cells = <0>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&rk808 1>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_enable_h>;
+
+		/*
+		 * On the module itself this is one of these (depending
+		 * on the actual card populated):
+		 * - SDIO_RESET_L_WL_REG_ON
+		 * - PDN (power down when low)
+		 */
+		reset-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_LOW>;
+	};
+
+	/* switched by pmic_sleep */
+	vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc1v8_s3";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_1v8>;
+	};
+
+	vcc3v3_pcie: vcc3v3-pcie-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_pcie";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vsys_3v3>;
+	};
+
+	/* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */
+	vcc5v0_host: vcc5v0-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vcc5v0_host_en>;
+		regulator-name = "vcc5v0_host";
+		regulator-always-on;
+		vin-supply = <&vsys_5v0>;
+	};
+
+	vdd_log: vdd-log {
+		compatible = "pwm-regulator";
+		pwms = <&pwm2 0 25000 1>;
+		regulator-name = "vdd_log";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1400000>;
+		vin-supply = <&vsys_3v3>;
+	};
+
+	vsys: vsys {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: vsys-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vsys>;
+	};
+
+	vsys_5v0: vsys-5v0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vsys>;
+	};
+
+	adc-keys {
+		compatible = "adc-keys";
+		io-channels = <&saradc 1>;
+		io-channel-names = "buttons";
+		keyup-threshold-microvolt = <1800000>;
+		poll-interval = <100>;
+
+		recovery {
+			label = "Recovery";
+			linux,code = <KEY_VENDOR>;
+			press-threshold-microvolt = <18000>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwrbtn>;
+
+		power {
+			debounce-interval = <100>;
+			gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
+			label = "GPIO Key Power";
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sys_led_gpio>, <&user_led_gpio>;
+
+		sys-led {
+			label = "sys_led";
+			linux,default-trigger = "heartbeat";
+			gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+		};
+
+		user-led {
+			label = "user_led";
+			default-state = "off";
+			gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	fan: pwm-fan {
+		compatible = "pwm-fan";
+		cooling-levels = <0 150 200 255>;
+		#cooling-cells = <2>;
+		fan-supply = <&vsys_5v0>;
+		pwms = <&pwm0 0 40000 0>;
+	};
+};
+
+&cpu_l0 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+	cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+	cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+	cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_thermal {
+	trips {
+		cpu_warm: cpu_warm {
+			temperature = <55000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+
+		cpu_hot: cpu_hot {
+			temperature = <65000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+	};
+
+	cooling-maps {
+		map2 {
+			trip = <&cpu_warm>;
+			cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+		};
+
+		map3 {
+			trip = <&cpu_hot>;
+			cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+		};
+	};
+};
+
+&emmc_phy {
+	status = "okay";
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_RMII_SRC>;
+	assigned-clock-parents = <&clkin_gmac>;
+	clock_in_out = "input";
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rgmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+	tx_delay = <0x28>;
+	rx_delay = <0x11>;
+};
+
+&gpu {
+	mali-supply = <&vdd_gpu>;
+	status = "okay";
+};
+
+&gpu_thermal {
+	trips {
+		gpu_warm: gpu_warm {
+			temperature = <55000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+
+		gpu_hot: gpu_hot {
+			temperature = <65000>;
+			hysteresis = <2000>;
+			type = "active";
+		};
+	};
+
+	cooling-maps {
+		map1 {
+			trip = <&gpu_warm>;
+			cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+		};
+
+		map2 {
+			trip = <&gpu_hot>;
+			cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+		};
+	};
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_cec>;
+	status = "okay";
+};
+
+&hdmi_sound {
+	status = "okay";
+};
+
+&i2c3 {
+	i2c-scl-rising-time-ns = <450>;
+	i2c-scl-falling-time-ns = <15>;
+	status = "okay";
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+	i2c-scl-rising-time-ns = <168>;
+	i2c-scl-falling-time-ns = <4>;
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <RK_PC6 IRQ_TYPE_LEVEL_LOW>;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int_l>;
+		rockchip,system-power-controller;
+		wakeup-source;
+
+		vcc1-supply = <&vsys_3v3>;
+		vcc2-supply = <&vsys_3v3>;
+		vcc3-supply = <&vsys_3v3>;
+		vcc4-supply = <&vsys_3v3>;
+		vcc6-supply = <&vsys_3v3>;
+		vcc7-supply = <&vsys_3v3>;
+		vcc8-supply = <&vsys_3v3>;
+		vcc9-supply = <&vsys_3v3>;
+		vcc10-supply = <&vsys_3v3>;
+		vcc11-supply = <&vsys_3v3>;
+		vcc12-supply = <&vsys_3v3>;
+		vddio-supply = <&vcc_1v8>;
+
+		regulators {
+			vdd_center: DCDC_REG1 {
+				regulator-name = "vdd_center";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_cpu_l: DCDC_REG2 {
+				regulator-name = "vdd_cpu_l";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <6001>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-name = "vcc_ddr";
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_1v8: DCDC_REG4 {
+				regulator-name = "vcc_1v8";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc1v8_apio2: LDO_REG1 {
+				regulator-name = "vcc1v8_apio2";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_vldo2: LDO_REG2 {
+				regulator-name = "vcc_vldo2";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc1v8_pmupll: LDO_REG3 {
+				regulator-name = "vcc1v8_pmupll";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vccio_sd: LDO_REG4 {
+				regulator-name = "vccio_sd";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3000000>;
+				};
+			};
+
+			vcc_vldo5: LDO_REG5 {
+				regulator-name = "vcc_vldo5";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_1v5: LDO_REG6 {
+				regulator-name = "vcc_1v5";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1500000>;
+				};
+			};
+
+			vcc1v8_codec: LDO_REG7 {
+				regulator-name = "vcc1v8_codec";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc_3v0: LDO_REG8 {
+				regulator-name = "vcc_3v0";
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3000000>;
+				};
+			};
+
+			vcc3v3_s3: vcc_lan: SWITCH_REG1 {
+				regulator-name = "vcc3v3_s3";
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vcc3v3_s0: SWITCH_REG2 {
+				regulator-name = "vcc3v3_s0";
+				regulator-always-on;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+		};
+	};
+
+	vdd_cpu_b: regulator@40 {
+		compatible = "silergy,syr827";
+		reg = <0x40>;
+		fcs,suspend-voltage-selector = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&cpu_b_sleep>;
+		regulator-name = "vdd_cpu_b";
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <1000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vsys_3v3>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+
+	vdd_gpu: regulator@41 {
+		compatible = "silergy,syr828";
+		reg = <0x41>;
+		fcs,suspend-voltage-selector = <1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpu_sleep>;
+		regulator-name = "vdd_gpu";
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <1000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vsys_3v3>;
+
+		regulator-state-mem {
+			regulator-off-in-suspend;
+		};
+	};
+};
+
+&i2c8 {
+	clock-frequency = <400000>;
+	i2c-scl-rising-time-ns = <160>;
+	i2c-scl-falling-time-ns = <30>;
+	status = "okay";
+};
+
+&i2s0 {
+	rockchip,playback-channels = <8>;
+	rockchip,capture-channels = <8>;
+	status = "okay";
+};
+
+&i2s1 {
+	rockchip,playback-channels = <2>;
+	rockchip,capture-channels = <2>;
+	status = "okay";
+};
+
+&i2s2 {
+	status = "okay";
+};
+
+&io_domains {
+	bt656-supply = <&vcc1v8_apio2>;
+	audio-supply = <&vcc1v8_codec>;
+	sdmmc-supply = <&vccio_sd>;
+	gpio1830-supply = <&vcc_3v0>;
+	status = "okay";
+};
+
+&pmu_io_domains {
+	pmu1830-supply = <&vcc_1v8>;
+	status = "okay";
+};
+
+&pinctrl {
+	bt {
+		bt_host_wake_l: bt-host-wake-l {
+			rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_reg_on_h: bt-reg-on-h {
+			rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_wake_l: bt-wake-l {
+			rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	buttons {
+		pwrbtn: pwrbtn {
+			rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	leds {
+		sys_led_gpio: sys_led-gpio {
+			rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		user_led_gpio: user_led-gpio {
+			rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_int_l: pmic-int-l {
+			rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		cpu_b_sleep: cpu-b-sleep {
+			rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+
+		gpu_sleep: gpu-sleep {
+			rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+
+	sdio-pwrseq {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb2 {
+		vcc5v0_host_en: vcc5v0-host-en {
+			rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	wifi {
+		wifi_host_wake_l: wifi-host-wake-l {
+			rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&saradc {
+	vref-supply = <&vcca1v8_s3>;
+	status = "okay";
+};
+
+&sdio0 {
+	/* WiFi & BT combo module Ampak AP6356S */
+	bus-width = <4>;
+	cap-sdio-irq;
+	cap-sd-highspeed;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+	sd-uhs-sdr104;
+	vqmmc-supply = <&vcc1v8_s3>;
+	vmmc-supply = <&vccio_sd>;
+	status = "okay";
+
+	brcmf: wifi@1 {
+		compatible = "brcm,bcm4329-fmac";
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+		interrupt-names = "host-wake";
+		brcm,drive-strength = <5>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_host_wake_l>;
+	};
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+	disable-wp;
+	max-frequency = <150000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
+&tcphy0 {
+	status = "okay";
+};
+
+&tcphy1 {
+	status = "okay";
+};
+
+&tsadc {
+	/* tshut mode 0:CRU 1:GPIO */
+	rockchip,hw-tshut-mode = <1>;
+	/* tshut polarity 0:LOW 1:HIGH */
+	rockchip,hw-tshut-polarity = <1>;
+	status = "okay";
+};
+
+&u2phy0 {
+	status = "okay";
+
+	u2phy0_otg: otg-port {
+		status = "okay";
+	};
+
+	u2phy0_host: host-port {
+		phy-supply = <&vcc5v0_host>;
+		status = "okay";
+	};
+};
+
+&u2phy1 {
+	status = "okay";
+
+	u2phy1_otg: otg-port {
+		status = "okay";
+	};
+
+	u2phy1_host: host-port {
+		phy-supply = <&vcc5v0_host>;
+		status = "okay";
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer &uart0_rts &uart0_cts>;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm43438-bt";
+		clocks = <&rk808 1>;
+		clock-names = "lpo";
+		device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
+		host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
+		max-speed = <4000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bt_reg_on_h &bt_host_wake_l &bt_wake_l>;
+		vbat-supply = <&vsys_3v3>;
+		vddio-supply = <&vcc_1v8>;
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&usb_host1_ehci {
+	status = "okay";
+};
+
+&usb_host1_ohci {
+	status = "okay";
+};
+
+&usbdrd3_0 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	status = "okay";
+	dr_mode = "otg";
+};
+
+&usbdrd3_1 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-rock960-u-boot.dtsi b/arch/arm/dts/rk3399-rock960-u-boot.dtsi
index 5256f6d..4850deb 100644
--- a/arch/arm/dts/rk3399-rock960-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-rock960-u-boot.dtsi
@@ -3,4 +3,11 @@
  * Copyright (C) 2019 Jagan Teki <jagan@amarulasolutions.com>
  */
 
+#include "rk3399-u-boot.dtsi"
 #include "rk3399-sdram-lpddr3-2GB-1600.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = &sdhci, &sdmmc;
+	};
+};
diff --git a/arch/arm/dts/tegra124-apalis.dts b/arch/arm/dts/tegra124-apalis.dts
index a962c0a..08184ab 100644
--- a/arch/arm/dts/tegra124-apalis.dts
+++ b/arch/arm/dts/tegra124-apalis.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Toradex AG
+ * Copyright 2016-2019 Toradex AG
  *
  * This file is dual-licensed: you can use it either under the terms
  * of the GPL or the X11 license, at your option. Note that this dual
@@ -230,19 +230,21 @@
 			};
 
 			/* Apalis GPIO */
-			ddc_scl_pv4 {
-				nvidia,pins = "ddc_scl_pv4";
+			usb_vbus_en0_pn4 {
+				nvidia,pins = "usb_vbus_en0_pn4";
 				nvidia,function = "rsvd2";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
 			};
-			ddc_sda_pv5 {
-				nvidia,pins = "ddc_sda_pv5";
+			usb_vbus_en1_pn5 {
+				nvidia,pins = "usb_vbus_en1_pn5";
 				nvidia,function = "rsvd2";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
 			};
 			pex_l0_rst_n_pdd1 {
 				nvidia,pins = "pex_l0_rst_n_pdd1";
@@ -333,40 +335,40 @@
 				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
 			};
 
-			/* Apalis I2C2 (DDC) */
-			gen2_i2c_scl_pt5 {
-				nvidia,pins = "gen2_i2c_scl_pt5";
-				nvidia,function = "i2c2";
+			/* Apalis I2C3 (CAM) */
+			cam_i2c_scl_pbb1 {
+				nvidia,pins = "cam_i2c_scl_pbb1";
+				nvidia,function = "i2c3";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
 			};
-			gen2_i2c_sda_pt6 {
-				nvidia,pins = "gen2_i2c_sda_pt6";
-				nvidia,function = "i2c2";
+			cam_i2c_sda_pbb2 {
+				nvidia,pins = "cam_i2c_sda_pbb2";
+				nvidia,function = "i2c3";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
 				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
 			};
 
-			/* Apalis I2C3 (CAM) */
-			cam_i2c_scl_pbb1 {
-				nvidia,pins = "cam_i2c_scl_pbb1";
-				nvidia,function = "i2c3";
+			/* Apalis I2C4 (DDC) */
+			ddc_scl_pv4 {
+				nvidia,pins = "ddc_scl_pv4";
+				nvidia,function = "i2c4";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
 			};
-			cam_i2c_sda_pbb2 {
-				nvidia,pins = "cam_i2c_sda_pbb2";
-				nvidia,function = "i2c3";
+			ddc_sda_pv5 {
+				nvidia,pins = "ddc_sda_pv5";
+				nvidia,function = "i2c4";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-				nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+				nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
 			};
 
 			/* Apalis MMC1 */
@@ -470,12 +472,12 @@
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
 			};
-			/* PWM3 active on pu6 being Apalis BKL1_PWM */
+			/* PWM3 active on pu6 being Apalis BKL1_PWM as well */
 			ph3 {
 				nvidia,pins = "ph3";
-				nvidia,function = "gmi";
-				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,function = "pwm3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
 			};
 
@@ -736,8 +738,8 @@
 			};
 
 			/* Apalis USBH_EN */
-			usb_vbus_en1_pn5 {
-				nvidia,pins = "usb_vbus_en1_pn5";
+			gen2_i2c_sda_pt6 {
+				nvidia,pins = "gen2_i2c_sda_pt6";
 				nvidia,function = "rsvd2";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
@@ -755,8 +757,8 @@
 			};
 
 			/* Apalis USBO1_EN */
-			usb_vbus_en0_pn4 {
-				nvidia,pins = "usb_vbus_en0_pn4";
+			gen2_i2c_scl_pt5 {
+				nvidia,pins = "gen2_i2c_scl_pt5";
 				nvidia,function = "rsvd2";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
@@ -1501,10 +1503,14 @@
 				nvidia,tristate = <TEGRA_PIN_ENABLE>;
 				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
 			};
-			pv0 { /* NC */
+			/*
+			 * PCB Version Indication: V1.2 and later have GPIO_PV0
+			 * wired to GND, was NC before
+			 */
+			pv0 {
 				nvidia,pins = "pv0";
 				nvidia,function = "rsvd1";
-				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
 				nvidia,tristate = <TEGRA_PIN_ENABLE>;
 				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
 			};
@@ -1630,13 +1636,7 @@
 		};
 	};
 
-	/*
-	 * GEN2_I2C: I2C2_SDA/SCL (DDC) on MXM3 pin 205/207 (e.g. display EDID)
-	 */
-	hdmi_ddc: i2c@7000c400 {
-		status = "okay";
-		clock-frequency = <10000>;
-	};
+	/* GEN2_I2C: unused */
 
 	/*
 	 * CAM_I2C: I2C3_SDA/SCL (CAM) on MXM3 pin 201/203 (e.g. camera sensor
@@ -1647,7 +1647,14 @@
 		clock-frequency = <400000>;
 	};
 
-	/* I2C4 (DDC): unused */
+	/*
+	 * I2C4 (DDC): I2C4_SDA/SCL (DDC) on MXM3 pin 205/207
+	 * (e.g. display EDID)
+	 */
+	hdmi_ddc: i2c@7000c700 {
+		status = "okay";
+		clock-frequency = <10000>;
+	};
 
 	/* PWR_I2C: power I2C to audio codec, PMIC and temperature sensor */
 	i2c@7000d000 {
@@ -2112,7 +2119,7 @@
 		regulator-name = "VCC_USBO1";
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
-		gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+		gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 		vin-supply = <&reg_5v0>;
 	};
@@ -2123,7 +2130,7 @@
 		regulator-name = "VCC_USBH(2A|2C|2D|3|4)";
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
-		gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
+		gpio = <&gpio TEGRA_GPIO(T, 6) GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 		vin-supply = <&reg_5v0>;
 	};
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h
new file mode 100644
index 0000000..11411ea
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk3328.h
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2016-2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK3328_H
+#define _ASM_ARCH_SDRAM_RK3328_H
+
+#define SR_IDLE		93
+#define PD_IDLE		13
+#define SDRAM_ADDR	0x00000000
+#define PATTERN		(0x5aa5f00f)
+
+/* ddr pctl registers define */
+#define DDR_PCTL2_MSTR			0x0
+#define DDR_PCTL2_STAT			0x4
+#define DDR_PCTL2_MSTR1			0x8
+#define DDR_PCTL2_MRCTRL0		0x10
+#define DDR_PCTL2_MRCTRL1		0x14
+#define DDR_PCTL2_MRSTAT		0x18
+#define DDR_PCTL2_MRCTRL2		0x1c
+#define DDR_PCTL2_DERATEEN		0x20
+#define DDR_PCTL2_DERATEINT		0x24
+#define DDR_PCTL2_PWRCTL		0x30
+#define DDR_PCTL2_PWRTMG		0x34
+#define DDR_PCTL2_HWLPCTL		0x38
+#define DDR_PCTL2_RFSHCTL0		0x50
+#define DDR_PCTL2_RFSHCTL1		0x54
+#define DDR_PCTL2_RFSHCTL2		0x58
+#define DDR_PCTL2_RFSHCTL4		0x5c
+#define DDR_PCTL2_RFSHCTL3		0x60
+#define DDR_PCTL2_RFSHTMG		0x64
+#define DDR_PCTL2_RFSHTMG1		0x68
+#define DDR_PCTL2_RFSHCTL5		0x6c
+#define DDR_PCTL2_INIT0			0xd0
+#define DDR_PCTL2_INIT1			0xd4
+#define DDR_PCTL2_INIT2			0xd8
+#define DDR_PCTL2_INIT3			0xdc
+#define DDR_PCTL2_INIT4			0xe0
+#define DDR_PCTL2_INIT5			0xe4
+#define DDR_PCTL2_INIT6			0xe8
+#define DDR_PCTL2_INIT7			0xec
+#define DDR_PCTL2_DIMMCTL		0xf0
+#define DDR_PCTL2_RANKCTL		0xf4
+#define DDR_PCTL2_CHCTL			0xfc
+#define DDR_PCTL2_DRAMTMG0		0x100
+#define DDR_PCTL2_DRAMTMG1		0x104
+#define DDR_PCTL2_DRAMTMG2		0x108
+#define DDR_PCTL2_DRAMTMG3		0x10c
+#define DDR_PCTL2_DRAMTMG4		0x110
+#define DDR_PCTL2_DRAMTMG5		0x114
+#define DDR_PCTL2_DRAMTMG6		0x118
+#define DDR_PCTL2_DRAMTMG7		0x11c
+#define DDR_PCTL2_DRAMTMG8		0x120
+#define DDR_PCTL2_DRAMTMG9		0x124
+#define DDR_PCTL2_DRAMTMG10		0x128
+#define DDR_PCTL2_DRAMTMG11		0x12c
+#define DDR_PCTL2_DRAMTMG12		0x130
+#define DDR_PCTL2_DRAMTMG13		0x134
+#define DDR_PCTL2_DRAMTMG14		0x138
+#define DDR_PCTL2_DRAMTMG15		0x13c
+#define DDR_PCTL2_DRAMTMG16		0x140
+#define DDR_PCTL2_ZQCTL0		0x180
+#define DDR_PCTL2_ZQCTL1		0x184
+#define DDR_PCTL2_ZQCTL2		0x188
+#define DDR_PCTL2_ZQSTAT		0x18c
+#define DDR_PCTL2_DFITMG0		0x190
+#define DDR_PCTL2_DFITMG1		0x194
+#define DDR_PCTL2_DFILPCFG0		0x198
+#define DDR_PCTL2_DFILPCFG1		0x19c
+#define DDR_PCTL2_DFIUPD0		0x1a0
+#define DDR_PCTL2_DFIUPD1		0x1a4
+#define DDR_PCTL2_DFIUPD2		0x1a8
+#define DDR_PCTL2_DFIMISC		0x1b0
+#define DDR_PCTL2_DFITMG2		0x1b4
+#define DDR_PCTL2_DFITMG3		0x1b8
+#define DDR_PCTL2_DFISTAT		0x1bc
+#define DDR_PCTL2_DBICTL		0x1c0
+#define DDR_PCTL2_ADDRMAP0		0x200
+#define DDR_PCTL2_ADDRMAP1		0x204
+#define DDR_PCTL2_ADDRMAP2		0x208
+#define DDR_PCTL2_ADDRMAP3		0x20c
+#define DDR_PCTL2_ADDRMAP4		0x210
+#define DDR_PCTL2_ADDRMAP5		0x214
+#define DDR_PCTL2_ADDRMAP6		0x218
+#define DDR_PCTL2_ADDRMAP7		0x21c
+#define DDR_PCTL2_ADDRMAP8		0x220
+#define DDR_PCTL2_ADDRMAP9		0x224
+#define DDR_PCTL2_ADDRMAP10		0x228
+#define DDR_PCTL2_ADDRMAP11		0x22c
+#define DDR_PCTL2_ODTCFG		0x240
+#define DDR_PCTL2_ODTMAP		0x244
+#define DDR_PCTL2_SCHED			0x250
+#define DDR_PCTL2_SCHED1		0x254
+#define DDR_PCTL2_PERFHPR1		0x25c
+#define DDR_PCTL2_PERFLPR1		0x264
+#define DDR_PCTL2_PERFWR1		0x26c
+#define DDR_PCTL2_DQMAP0		0x280
+#define DDR_PCTL2_DQMAP1		0x284
+#define DDR_PCTL2_DQMAP2		0x288
+#define DDR_PCTL2_DQMAP3		0x28c
+#define DDR_PCTL2_DQMAP4		0x290
+#define DDR_PCTL2_DQMAP5		0x294
+#define DDR_PCTL2_DBG0			0x300
+#define DDR_PCTL2_DBG1			0x304
+#define DDR_PCTL2_DBGCAM		0x308
+#define DDR_PCTL2_DBGCMD		0x30c
+#define DDR_PCTL2_DBGSTAT		0x310
+#define DDR_PCTL2_SWCTL			0x320
+#define DDR_PCTL2_SWSTAT		0x324
+#define DDR_PCTL2_POISONCFG		0x36c
+#define DDR_PCTL2_POISONSTAT		0x370
+#define DDR_PCTL2_ADVECCINDEX		0x374
+#define DDR_PCTL2_ADVECCSTAT		0x378
+#define DDR_PCTL2_PSTAT			0x3fc
+#define DDR_PCTL2_PCCFG			0x400
+#define DDR_PCTL2_PCFGR_n		0x404
+#define DDR_PCTL2_PCFGW_n		0x408
+#define DDR_PCTL2_PCTRL_n		0x490
+
+/* PCTL2_MRSTAT */
+#define MR_WR_BUSY			BIT(0)
+
+/* PHY_REG0 */
+#define DIGITAL_DERESET			BIT(3)
+#define ANALOG_DERESET			BIT(2)
+#define DIGITAL_RESET			(0 << 3)
+#define ANALOG_RESET			(0 << 2)
+
+/* PHY_REG1 */
+#define PHY_DDR2			(0)
+#define PHY_LPDDR2			(1)
+#define PHY_DDR3			(2)
+#define PHY_LPDDR3			(3)
+#define PHY_DDR4			(4)
+#define PHY_BL_4			(0 << 2)
+#define PHY_BL_8			BIT(2)
+
+/* PHY_REG2 */
+#define PHY_DTT_EN			BIT(0)
+#define PHY_DTT_DISB			(0 << 0)
+#define PHY_WRITE_LEVELING_EN		BIT(2)
+#define PHY_WRITE_LEVELING_DISB		(0 << 2)
+#define PHY_SELECT_CS0			(2)
+#define PHY_SELECT_CS1			(1)
+#define PHY_SELECT_CS0_1		(0)
+#define PHY_WRITE_LEVELING_SELECTCS(n)	(n << 6)
+#define PHY_DATA_TRAINING_SELECTCS(n)	(n << 4)
+
+#define PHY_DDR3_RON_RTT_DISABLE	(0)
+#define PHY_DDR3_RON_RTT_451ohm		(1)
+#define PHY_DDR3_RON_RTT_225ohm		(2)
+#define PHY_DDR3_RON_RTT_150ohm		(3)
+#define PHY_DDR3_RON_RTT_112ohm		(4)
+#define PHY_DDR3_RON_RTT_90ohm		(5)
+#define PHY_DDR3_RON_RTT_75ohm		(6)
+#define PHY_DDR3_RON_RTT_64ohm		(7)
+#define PHY_DDR3_RON_RTT_56ohm		(16)
+#define PHY_DDR3_RON_RTT_50ohm		(17)
+#define PHY_DDR3_RON_RTT_45ohm		(18)
+#define PHY_DDR3_RON_RTT_41ohm		(19)
+#define PHY_DDR3_RON_RTT_37ohm		(20)
+#define PHY_DDR3_RON_RTT_34ohm		(21)
+#define PHY_DDR3_RON_RTT_33ohm		(22)
+#define PHY_DDR3_RON_RTT_30ohm		(23)
+#define PHY_DDR3_RON_RTT_28ohm		(24)
+#define PHY_DDR3_RON_RTT_26ohm		(25)
+#define PHY_DDR3_RON_RTT_25ohm		(26)
+#define PHY_DDR3_RON_RTT_23ohm		(27)
+#define PHY_DDR3_RON_RTT_22ohm		(28)
+#define PHY_DDR3_RON_RTT_21ohm		(29)
+#define PHY_DDR3_RON_RTT_20ohm		(30)
+#define PHY_DDR3_RON_RTT_19ohm		(31)
+
+#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE	(0)
+#define PHY_DDR4_LPDDR3_RON_RTT_480ohm	(1)
+#define PHY_DDR4_LPDDR3_RON_RTT_240ohm	(2)
+#define PHY_DDR4_LPDDR3_RON_RTT_160ohm	(3)
+#define PHY_DDR4_LPDDR3_RON_RTT_120ohm	(4)
+#define PHY_DDR4_LPDDR3_RON_RTT_96ohm	(5)
+#define PHY_DDR4_LPDDR3_RON_RTT_80ohm	(6)
+#define PHY_DDR4_LPDDR3_RON_RTT_68ohm	(7)
+#define PHY_DDR4_LPDDR3_RON_RTT_60ohm	(16)
+#define PHY_DDR4_LPDDR3_RON_RTT_53ohm	(17)
+#define PHY_DDR4_LPDDR3_RON_RTT_48ohm	(18)
+#define PHY_DDR4_LPDDR3_RON_RTT_43ohm	(19)
+#define PHY_DDR4_LPDDR3_RON_RTT_40ohm	(20)
+#define PHY_DDR4_LPDDR3_RON_RTT_37ohm	(21)
+#define PHY_DDR4_LPDDR3_RON_RTT_34ohm	(22)
+#define PHY_DDR4_LPDDR3_RON_RTT_32ohm	(23)
+#define PHY_DDR4_LPDDR3_RON_RTT_30ohm	(24)
+#define PHY_DDR4_LPDDR3_RON_RTT_28ohm	(25)
+#define PHY_DDR4_LPDDR3_RON_RTT_26ohm	(26)
+#define PHY_DDR4_LPDDR3_RON_RTT_25ohm	(27)
+#define PHY_DDR4_LPDDR3_RON_RTT_24ohm	(28)
+#define PHY_DDR4_LPDDR3_RON_RTT_22ohm	(29)
+#define PHY_DDR4_LPDDR3_RON_RTT_21ohm	(30)
+#define PHY_DDR4_LPDDR3_RON_RTT_20ohm	(31)
+
+/* noc registers define */
+#define DDRCONF				0x8
+#define DDRTIMING			0xc
+#define DDRMODE				0x10
+#define READLATENCY			0x14
+#define AGING0				0x18
+#define AGING1				0x1c
+#define AGING2				0x20
+#define AGING3				0x24
+#define AGING4				0x28
+#define AGING5				0x2c
+#define ACTIVATE			0x38
+#define DEVTODEV			0x3c
+#define DDR4TIMING			0x40
+
+/* DDR GRF */
+#define DDR_GRF_CON(n)		(0 + (n) * 4)
+#define DDR_GRF_STATUS_BASE	(0X100)
+#define DDR_GRF_STATUS(n)	(DDR_GRF_STATUS_BASE + (n) * 4)
+
+/* CRU_SOFTRESET_CON5 */
+#define ddrphy_psrstn_req(n)    (((0x1 << 15) << 16) | (n << 15))
+#define ddrphy_srstn_req(n)     (((0x1 << 14) << 16) | (n << 14))
+#define ddrctrl_psrstn_req(n)	(((0x1 << 13) << 16) | (n << 13))
+#define ddrctrl_srstn_req(n)	(((0x1 << 12) << 16) | (n << 12))
+#define ddrmsch_srstn_req(n)	(((0x1 << 11) << 16) | (n << 11))
+#define msch_srstn_req(n)		(((0x1 << 9) << 16) | (n << 9))
+#define dfimon_srstn_req(n)		(((0x1 << 8) << 16) | (n << 8))
+#define grf_ddr_srstn_req(n)	(((0x1 << 7) << 16) | (n << 7))
+/* CRU_SOFTRESET_CON9 */
+#define ddrctrl_asrstn_req(n)		(((0x1 << 9) << 16) | (n << 9))
+
+/* CRU register */
+#define CRU_PLL_CON(pll_id, n)	((pll_id)  * 0x20 + (n) * 4)
+#define CRU_MODE				(0x80)
+#define CRU_GLB_CNT_TH			(0x90)
+#define CRU_CLKSEL_CON_BASE		0x100
+#define CRU_CLKSELS_CON(i)		(CRU_CLKSEL_CON_BASE + ((i) * 4))
+#define CRU_CLKGATE_CON_BASE		0x200
+#define CRU_CLKGATE_CON(i)		(CRU_CLKGATE_CON_BASE + ((i) * 4))
+#define CRU_CLKSFTRST_CON_BASE	0x300
+#define CRU_CLKSFTRST_CON(i)	(CRU_CLKSFTRST_CON_BASE + ((i) * 4))
+
+/* CRU_PLL_CON0 */
+#define PB(n)         ((0x1 << (15 + 16)) | ((n) << 15))
+#define POSTDIV1(n)   ((0x7 << (12 + 16)) | ((n) << 12))
+#define FBDIV(n)      ((0xFFF << 16) | (n))
+
+/* CRU_PLL_CON1 */
+#define RSTMODE(n)    ((0x1 << (15 + 16)) | ((n) << 15))
+#define RST(n)        ((0x1 << (14 + 16)) | ((n) << 14))
+#define PD(n)         ((0x1 << (13 + 16)) | ((n) << 13))
+#define DSMPD(n)      ((0x1 << (12 + 16)) | ((n) << 12))
+#define LOCK(n)       (((n) >> 10) & 0x1)
+#define POSTDIV2(n)   ((0x7 << (6 + 16)) | ((n) << 6))
+#define REFDIV(n)     ((0x3F << 16) | (n))
+
+union noc_ddrtiming {
+	u32 d32;
+	struct {
+		unsigned acttoact:6;
+		unsigned rdtomiss:6;
+		unsigned wrtomiss:6;
+		unsigned burstlen:3;
+		unsigned rdtowr:5;
+		unsigned wrtord:5;
+		unsigned bwratio:1;
+	} b;
+} NOC_TIMING_T;
+
+union noc_activate {
+	u32 d32;
+	struct {
+		unsigned rrd:4;
+		unsigned faw:6;
+		unsigned fawbank:1;
+		unsigned reserved1:21;
+	} b;
+};
+
+union noc_devtodev {
+	u32 d32;
+	struct {
+		unsigned busrdtord:2;
+		unsigned busrdtowr:2;
+		unsigned buswrtord:2;
+		unsigned reserved2:26;
+	} b;
+};
+
+union noc_ddr4timing {
+	u32 d32;
+	struct {
+		unsigned ccdl:3;
+		unsigned wrtordl:5;
+		unsigned rrdl:4;
+		unsigned reserved2:20;
+	} b;
+};
+
+union noc_ddrmode {
+	u32 d32;
+	struct {
+		unsigned autoprecharge:1;
+		unsigned bwratioextended:1;
+		unsigned reserved3:30;
+	} b;
+};
+
+u32 addrmap[21][9] = {
+	/* map0  map1  map2  map3  map4  map5  map6  map7  map8 */
+	{22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000f0f, 0x3f3f},
+	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f0f, 0x3f3f},
+	{23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+		0x0f080808, 0x00000f0f, 0x3f3f},
+	{24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+		0x08080808, 0x00000f0f, 0x3f3f},
+	{24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
+		0x0f090909, 0x00000f0f, 0x3f3f},
+	{6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f0f, 0x3f3f},
+	{7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
+		0x08080808, 0x00000f0f, 0x3f3f},
+	{8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
+		0x0f090909, 0x00000f0f, 0x3f3f},
+	{22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000f0f, 0x3f3f},
+	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+		0x0f070707, 0x00000f0f, 0x3f3f},
+
+	{24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+		0x08080808, 0x00000f0f, 0x0801},
+	{23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+		0x0f080808, 0x00000f0f, 0x0801},
+	{24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x0700},
+	{23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f0f, 0x0700},
+	{24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x3f01},
+	{23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f0f, 0x3f01},
+	{24, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
+		0x06060606, 0x00000f06, 0x3f00},
+	{8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
+		0x0f090909, 0x00000f0f, 0x0801},
+	{7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
+		0x08080808, 0x00000f0f, 0x0700},
+	{7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+		0x08080808, 0x00000f0f, 0x3f01},
+
+	{6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+		0x07070707, 0x00000f07, 0x3f00}
+};
+
+struct rk3328_msch_timings {
+	union noc_ddrtiming ddrtiming;
+	union noc_ddrmode ddrmode;
+	u32 readlatency;
+	union noc_activate activate;
+	union noc_devtodev devtodev;
+	union noc_ddr4timing ddr4timing;
+	u32 agingx0;
+};
+
+struct rk3328_msch_regs {
+	u32 coreid;
+	u32 revisionid;
+	u32 ddrconf;
+	u32 ddrtiming;
+	u32 ddrmode;
+	u32 readlatency;
+	u32 aging0;
+	u32 aging1;
+	u32 aging2;
+	u32 aging3;
+	u32 aging4;
+	u32 aging5;
+	u32 reserved[2];
+	u32 activate;
+	u32 devtodev;
+	u32 ddr4_timing;
+};
+
+struct rk3328_ddr_grf_regs {
+	u32 ddr_grf_con[4];
+	u32 reserved[(0x100 - 0x10) / 4];
+	u32 ddr_grf_status[11];
+};
+
+struct rk3328_ddr_pctl_regs {
+	u32 pctl[30][2];
+};
+
+struct rk3328_ddr_phy_regs {
+	u32 phy[5][2];
+};
+
+struct rk3328_ddr_skew {
+	u32 a0_a1_skew[15];
+	u32 cs0_dm0_skew[11];
+	u32 cs0_dm1_skew[11];
+	u32 cs0_dm2_skew[11];
+	u32 cs0_dm3_skew[11];
+	u32 cs1_dm0_skew[11];
+	u32 cs1_dm1_skew[11];
+	u32 cs1_dm2_skew[11];
+	u32 cs1_dm3_skew[11];
+};
+
+struct rk3328_sdram_channel {
+	unsigned int rank;
+	unsigned int col;
+	/* 3:8bank, 2:4bank */
+	unsigned int bk;
+	/* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int bw;
+	/* die buswidth, 2:32bit, 1:16bit, 0:8bit */
+	unsigned int dbw;
+	unsigned int row_3_4;
+	unsigned int cs0_row;
+	unsigned int cs1_row;
+	unsigned int ddrconfig;
+	struct rk3328_msch_timings noc_timings;
+};
+
+struct rk3328_sdram_params {
+	struct rk3328_sdram_channel ch;
+	unsigned int ddr_freq;
+	unsigned int dramtype;
+	unsigned int odt;
+	struct rk3328_ddr_pctl_regs pctl_regs;
+	struct rk3328_ddr_phy_regs phy_regs;
+	struct rk3328_ddr_skew skew;
+};
+
+#define PHY_REG(base, n)		(base + 4 * (n))
+
+#endif
diff --git a/arch/arm/mach-bcm283x/reset.c b/arch/arm/mach-bcm283x/reset.c
index 7712d46..b3da0c7 100644
--- a/arch/arm/mach-bcm283x/reset.c
+++ b/arch/arm/mach-bcm283x/reset.c
@@ -23,11 +23,7 @@
 /* max ticks timeout */
 #define BCM2835_WDOG_MAX_TIMEOUT	0x000fffff
 
-#ifdef CONFIG_BCM2835_WDT
-extern void hw_watchdog_disable(void);
-#else
 void hw_watchdog_disable(void) {}
-#endif
 
 __efi_runtime_data struct bcm2835_wdog_regs *wdog_regs =
 	(struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index e337d06..f5a80b4 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -110,9 +110,14 @@
 	select ARM64
 	select SUPPORT_SPL
 	select SPL
+	select SUPPORT_TPL
+	select TPL
+	select TPL_NEEDS_SEPARATE_TEXT_BASE if TPL
+	select TPL_NEEDS_SEPARATE_STACK if TPL
 	imply ROCKCHIP_COMMON_BOARD
 	imply SPL_ROCKCHIP_COMMON_BOARD
 	imply SPL_SERIAL_SUPPORT
+	imply TPL_SERIAL_SUPPORT
 	imply SPL_SEPARATE_BSS
 	select ENABLE_ARM_SOC_BOOT0_HOOK
 	select DEBUG_UART_BOARD_INIT
diff --git a/arch/arm/mach-rockchip/rk3328/Kconfig b/arch/arm/mach-rockchip/rk3328/Kconfig
index f8e1528..d13a169 100644
--- a/arch/arm/mach-rockchip/rk3328/Kconfig
+++ b/arch/arm/mach-rockchip/rk3328/Kconfig
@@ -27,6 +27,18 @@
 config SPL_LIBGENERIC_SUPPORT
 	default y
 
+config TPL_LDSCRIPT
+	default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds"
+
+config TPL_TEXT_BASE
+	default 0xff091000
+
+config TPL_MAX_SIZE
+	default 28672
+
+config TPL_STACK
+	default 0xff098000
+
 source "board/rockchip/evb_rk3328/Kconfig"
 
 endif
diff --git a/arch/arm/mach-rockchip/rk3328/rk3328.c b/arch/arm/mach-rockchip/rk3328/rk3328.c
index 592f287..c2448d7 100644
--- a/arch/arm/mach-rockchip/rk3328/rk3328.c
+++ b/arch/arm/mach-rockchip/rk3328/rk3328.c
@@ -16,6 +16,7 @@
 #define CRU_BASE		0xFF440000
 #define GRF_BASE		0xFF100000
 #define UART2_BASE		0xFF130000
+#define FW_DDR_CON_REG		0xFF7C0040
 
 const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
 	[BROM_BOOTSOURCE_EMMC] = "rksdmmc@ff520000",
@@ -46,8 +47,12 @@
 
 int arch_cpu_init(void)
 {
+#ifdef CONFIG_SPL_BUILD
 	/* We do some SoC one time setting here. */
 
+	/* Disable the ddr secure region setting to make it non-secure */
+	rk_setreg(FW_DDR_CON_REG, 0x200);
+#endif
 	return 0;
 }
 
diff --git a/arch/arm/mach-tegra/sys_info.c b/arch/arm/mach-tegra/sys_info.c
index 9975f33..5dc998a 100644
--- a/arch/arm/mach-tegra/sys_info.c
+++ b/arch/arm/mach-tegra/sys_info.c
@@ -6,24 +6,36 @@
 
 #include <common.h>
 #include <linux/ctype.h>
+#if defined(CONFIG_TEGRA124) || defined(CONFIG_TEGRA30)
+#include <asm/arch-tegra/pmc.h>
 
-static void upstring(char *s)
+static char *get_reset_cause(void)
 {
-	while (*s) {
-		*s = toupper(*s);
-		s++;
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+
+	switch (pmc->pmc_reset_status) {
+	case 0x00:
+		return "POR";
+	case 0x01:
+		return "WATCHDOG";
+	case 0x02:
+		return "SENSOR";
+	case 0x03:
+		return "SW_MAIN";
+	case 0x04:
+		return "LP0";
 	}
+	return "UNKNOWN";
 }
+#endif
 
 /* Print CPU information */
 int print_cpuinfo(void)
 {
-	char soc_name[10];
-
-	strncpy(soc_name, CONFIG_SYS_SOC, 10);
-	upstring(soc_name);
-	puts(soc_name);
-	puts("\n");
+	printf("SoC: %s\n", CONFIG_SYS_SOC);
+#if defined(CONFIG_TEGRA124) || defined(CONFIG_TEGRA30)
+	printf("Reset cause: %s\n", get_reset_cause());
+#endif
 
 	/* TBD: Add printf of major/minor rev info, stepping, etc. */
 	return 0;
diff --git a/arch/arm/mach-tegra/tegra124/cpu.c b/arch/arm/mach-tegra/tegra124/cpu.c
index 992c0be..abc050c 100644
--- a/arch/arm/mach-tegra/tegra124/cpu.c
+++ b/arch/arm/mach-tegra/tegra124/cpu.c
@@ -238,6 +238,45 @@
 	return !!(reg & (1 << partid));
 }
 
+static void unpower_partition(u32 partid)
+{
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+
+	debug("%s: part ID = %08X\n", __func__, partid);
+	/* Is the partition on? */
+	if (is_partition_powered(partid)) {
+		/* Yes, toggle the partition power state (ON -> OFF) */
+		debug("power_partition, toggling state\n");
+		writel(START_CP | partid, &pmc->pmc_pwrgate_toggle);
+
+		/* Wait for the power to come down */
+		while (is_partition_powered(partid))
+			;
+
+		/* Give I/O signals time to stabilize */
+		udelay(IO_STABILIZATION_DELAY);
+	}
+}
+
+void unpower_cpus(void)
+{
+	debug("%s entry: G cluster\n", __func__);
+
+	/* Power down the fast cluster rail partition */
+	debug("%s: CRAIL\n", __func__);
+	unpower_partition(CRAIL);
+
+	/* Power down the fast cluster non-CPU partition */
+	debug("%s: C0NC\n", __func__);
+	unpower_partition(C0NC);
+
+	/* Power down the fast cluster CPU0 partition */
+	debug("%s: CE0\n", __func__);
+	unpower_partition(CE0);
+
+	debug("%s: done\n", __func__);
+}
+
 static void power_partition(u32 partid)
 {
 	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
@@ -284,6 +323,12 @@
 
 	debug("%s entry, reset_vector = %x\n", __func__, reset_vector);
 
+	/*
+	 * High power clusters are on after software reset,
+	 * it may interfere with tegra124_ram_repair.
+	 * unpower them.
+	 */
+	unpower_cpus();
 	tegra124_init_clocks();
 
 	/* Set power-gating timer multiplier */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70f9398..218e817 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -115,6 +115,7 @@
 source "arch/x86/cpu/qemu/Kconfig"
 source "arch/x86/cpu/quark/Kconfig"
 source "arch/x86/cpu/queensbay/Kconfig"
+source "arch/x86/cpu/slimbootloader/Kconfig"
 source "arch/x86/cpu/tangier/Kconfig"
 
 # architecture-specific options below
@@ -344,9 +345,17 @@
 	  The filename of the file to use as Intel Management Engine in the
 	  board directory.
 
+config USE_HOB
+	bool "Use HOB (Hand-Off Block)"
+	help
+	  Select this option to access HOB (Hand-Off Block) data structures
+	  and parse HOBs. This HOB infra structure can be reused with
+	  different solutions across different platforms.
+
 config HAVE_FSP
 	bool "Add an Firmware Support Package binary"
 	depends on !EFI
+	select USE_HOB
 	help
 	  Select this option to add an Firmware Support Package binary to
 	  the resulting U-Boot image. It is a binary blob which U-Boot uses
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 85fd5e6..3f1f62d 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_INTEL_BRASWELL) += braswell/
 obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_SYS_SLIMBOOTLOADER) += slimbootloader/
 obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_QEMU) += qemu/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
diff --git a/arch/x86/cpu/slimbootloader/Kconfig b/arch/x86/cpu/slimbootloader/Kconfig
new file mode 100644
index 0000000..3ea4c99
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+config SYS_SLIMBOOTLOADER
+	bool
+	select USE_HOB
+	imply SYS_NS16550
+	imply AHCI_PCI
+	imply SCSI
+	imply SCSI_AHCI
+	imply MMC
+	imply MMC_PCI
+	imply MMC_SDHCI
+	imply MMC_SDHCI_SDMA
+	imply USB
+	imply USB_EHCI_HCD
+	imply USB_XHCI_HCD
+	imply E1000
diff --git a/arch/x86/cpu/slimbootloader/Makefile b/arch/x86/cpu/slimbootloader/Makefile
new file mode 100644
index 0000000..aac9fa3
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+obj-y += car.o slimbootloader.o sdram.o serial.o
diff --git a/arch/x86/cpu/slimbootloader/car.S b/arch/x86/cpu/slimbootloader/car.S
new file mode 100644
index 0000000..6e03043
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/car.S
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <generated/asm-offsets.h>
+
+.section .text
+
+.globl car_init
+car_init:
+	/* Get hob pointer parameter from previous stage's stack */
+	mov	0x4(%esp), %esi
+	jmp	car_init_ret
diff --git a/arch/x86/cpu/slimbootloader/sdram.c b/arch/x86/cpu/slimbootloader/sdram.c
new file mode 100644
index 0000000..05d40d1
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/sdram.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <asm/e820.h>
+#include <asm/arch/slimbootloader.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This returns a data pointer of memory map info from the guid hob.
+ *
+ * @return: A data pointer of memory map info hob
+ */
+static struct sbl_memory_map_info *get_memory_map_info(void)
+{
+	struct sbl_memory_map_info *data;
+	const efi_guid_t guid = SBL_MEMORY_MAP_INFO_GUID;
+
+	if (!gd->arch.hob_list)
+		return NULL;
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data)
+		panic("memory map info hob not found\n");
+	if (!data->count)
+		panic("invalid number of memory map entries\n");
+
+	return data;
+}
+
+#define for_each_if(condition) if (!(condition)) {} else
+
+#define for_each_memory_map_entry_reversed(iter, entries) \
+	for (iter = entries->count - 1; iter >= 0; iter--) \
+		for_each_if(entries->entry[iter].type == E820_RAM)
+
+/**
+ * This is to give usable memory region information for u-boot relocation.
+ * so search usable memory region lower than 4GB.
+ * The memory map entries from Slim Bootloader hob are already sorted.
+ *
+ * @total_size: The memory size that u-boot occupies
+ * @return    : The top available memory address lower than 4GB
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	struct sbl_memory_map_info *data;
+	int i;
+	u64 addr_start;
+	u64 addr_end;
+	ulong ram_top;
+
+	data = get_memory_map_info();
+
+	/**
+	 * sorted memory map entries from Slim Bootloader based on physical
+	 * start memory address, from low to high. So do reversed search to
+	 * get highest usable, suitable size, 4KB aligned available memory
+	 * under 4GB.
+	 */
+	ram_top = 0;
+	for_each_memory_map_entry_reversed(i, data) {
+		addr_start = data->entry[i].addr;
+		addr_end = addr_start + data->entry[i].size;
+
+		if (addr_start > SZ_4G)
+			continue;
+
+		if (addr_end > SZ_4G)
+			addr_end = SZ_4G;
+
+		if (addr_end < total_size)
+			continue;
+
+		/* to relocate u-boot at 4K aligned memory */
+		addr_end = rounddown(addr_end - total_size, SZ_4K);
+		if (addr_end >= addr_start) {
+			ram_top = (ulong)addr_end + total_size;
+			break;
+		}
+	}
+
+	if (!ram_top)
+		panic("failed to find available memory for relocation!");
+
+	return ram_top;
+}
+
+/**
+ * The memory initialization has already been done in previous Slim Bootloader
+ * stage thru FSP-M. Instead, this sets the ram_size from the memory map info
+ * hob.
+ */
+int dram_init(void)
+{
+	struct sbl_memory_map_info *data;
+	int i;
+	u64 ram_size;
+
+	data = get_memory_map_info();
+
+	/**
+	 * sorted memory map entries from Slim Bootloader based on physical
+	 * start memory address, from low to high. So do reversed search to
+	 * simply get highest usable memory address as RAM size
+	 */
+	ram_size = 0;
+	for_each_memory_map_entry_reversed(i, data) {
+		/* simply use the highest usable memory address as RAM size */
+		ram_size = data->entry[i].addr + data->entry[i].size;
+		break;
+	}
+
+	if (!ram_size)
+		panic("failed to detect memory size");
+
+	gd->ram_size = ram_size;
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	if (!CONFIG_NR_DRAM_BANKS)
+		return 0;
+
+	/* simply use a single bank to have whole size for now */
+	gd->bd->bi_dram[0].start = 0;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+	return 0;
+}
+
+unsigned int install_e820_map(unsigned int max_entries,
+			      struct e820_entry *entries)
+{
+	struct sbl_memory_map_info *data;
+	unsigned int i;
+
+	data = get_memory_map_info();
+
+	for (i = 0; i < data->count; i++) {
+		entries[i].addr = data->entry[i].addr;
+		entries[i].size = data->entry[i].size;
+		entries[i].type = data->entry[i].type;
+	}
+
+	return i;
+}
diff --git a/arch/x86/cpu/slimbootloader/serial.c b/arch/x86/cpu/slimbootloader/serial.c
new file mode 100644
index 0000000..7b44a59
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/serial.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/slimbootloader.h>
+
+/**
+ * The serial port info hob is generated by Slim Bootloader, so eligible for
+ * Slim Bootloader based boards only.
+ */
+static int slimbootloader_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	const efi_guid_t guid = SBL_SERIAL_PORT_INFO_GUID;
+	struct sbl_serial_port_info *data;
+	struct ns16550_platdata *plat = dev->platdata;
+
+	if (!gd->arch.hob_list)
+		panic("hob list not found!");
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data) {
+		debug("failed to get serial port information\n");
+		return -ENOENT;
+	}
+	debug("type:%d base=0x%08x baudrate=%d stride=%d clk=%d\n",
+	      data->type,
+	      data->base,
+	      data->baud,
+	      data->stride,
+	      data->clk);
+
+	/*
+	 * The data->type provides port io or mmio access type info,
+	 * but the access type will be controlled by
+	 * CONFIG_SYS_NS16550_PORT_MAPPED or CONFIG_SYS_NS16550_MEM32.
+	 *
+	 * TBD: ns16550 access type configuration in runtime.
+	 *      ex) plat->access_type = data->type
+	 */
+	plat->base = data->base;
+	/* ns16550 uses reg_shift, then covert stride to shift */
+	plat->reg_shift = data->stride >> 1;
+	plat->clock = data->clk;
+
+	return 0;
+}
+
+static const struct udevice_id slimbootloader_serial_ids[] = {
+	{ .compatible = "intel,slimbootloader-uart" },
+	{}
+};
+
+U_BOOT_DRIVER(serial_slimbootloader) = {
+	.name	= "serial_slimbootloader",
+	.id	= UCLASS_SERIAL,
+	.of_match = slimbootloader_serial_ids,
+	.ofdata_to_platdata = slimbootloader_serial_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.probe	= ns16550_serial_probe,
+	.ops	= &ns16550_serial_ops,
+};
diff --git a/arch/x86/cpu/slimbootloader/slimbootloader.c b/arch/x86/cpu/slimbootloader/slimbootloader.c
new file mode 100644
index 0000000..e6b174c
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/slimbootloader.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/slimbootloader.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This sets tsc_base and clock_rate for early_timer and tsc_timer.
+ * The performance info guid hob has all performance timestamp data, but
+ * the only tsc frequency info is used for the timer driver for now.
+ *
+ * Slim Bootloader already calibrated TSC and provides it to U-Boot.
+ * Therefore, U-Boot does not have to re-calibrate TSC.
+ * Configuring tsc_base and clock_rate here makes x86 tsc_timer driver
+ * bypass TSC calibration and use the provided TSC frequency.
+ */
+static void tsc_init(void)
+{
+	struct sbl_performance_info *data;
+	const efi_guid_t guid = SBL_PERFORMANCE_INFO_GUID;
+
+	if (!gd->arch.hob_list)
+		panic("hob list not found!");
+
+	gd->arch.tsc_base = rdtsc();
+	debug("tsc_base=0x%llx\n", gd->arch.tsc_base);
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data) {
+		debug("performance info hob not found\n");
+		return;
+	}
+
+	/* frequency is in KHz, so to Hz */
+	gd->arch.clock_rate = data->frequency * 1000;
+	debug("freq=0x%lx\n", gd->arch.clock_rate);
+}
+
+int arch_cpu_init(void)
+{
+	tsc_init();
+
+	return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	return default_print_cpuinfo();
+}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 4a82add..71cd70f 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -97,7 +97,7 @@
 	jmp	car_init
 .globl car_init_ret
 car_init_ret:
-#ifndef CONFIG_HAVE_FSP
+#ifndef CONFIG_USE_HOB
 	/*
 	 * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
 	 * or fully initialised SDRAM - we really don't care which)
@@ -137,12 +137,13 @@
 
 	/* Get address of global_data */
 	mov	%fs:0, %edx
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	/* Store the HOB list if we have one */
 	test	%esi, %esi
 	jz	skip_hob
 	movl	%esi, GD_HOB_LIST(%edx)
 
+#ifdef CONFIG_HAVE_FSP
 	/*
 	 * After fsp_init() returns, the stack has already been switched to a
 	 * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR.
@@ -151,6 +152,7 @@
 	 */
 	subl	$CONFIG_FSP_SYS_MALLOC_F_LEN, %esp
 	movl	%esp, GD_MALLOC_BASE(%edx)
+#endif
 skip_hob:
 #else
 	/* Store table pointer */
diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c
index 0e4f961..61b2642 100644
--- a/arch/x86/cpu/tangier/acpi.c
+++ b/arch/x86/cpu/tangier/acpi.c
@@ -68,6 +68,44 @@
 	return current;
 }
 
+static u32 acpi_fill_csrt_dma(struct acpi_csrt_group *grp)
+{
+	struct acpi_csrt_shared_info *si = (struct acpi_csrt_shared_info *)&grp[1];
+
+	/* Fill the Resource Group with Shared Information attached */
+	memset(grp, 0, sizeof(*grp));
+	grp->shared_info_length = sizeof(struct acpi_csrt_shared_info);
+	grp->length = sizeof(struct acpi_csrt_group) + grp->shared_info_length;
+	/* TODO: All values below should come from U-Boot DT somehow */
+	sprintf((char *)&grp->vendor_id, "%04X", 0x8086);
+	grp->device_id = 0x11a2;
+
+	/* Fill the Resource Group Shared Information */
+	memset(si, 0, sizeof(*si));
+	si->major_version = 1;
+	si->minor_version = 0;
+	/* TODO: All values below should come from U-Boot DT somehow */
+	si->mmio_base_low = 0xff192000;
+	si->mmio_base_high = 0;
+	si->gsi_interrupt = 32;
+	si->interrupt_polarity = 1;
+	si->interrupt_mode = 0;
+	si->num_channels = 8;
+	si->dma_address_width = 32;
+	si->base_request_line = 0;
+	si->num_handshake_signals = 16;
+	si->max_block_size = 0x20000;
+
+	return grp->length;
+}
+
+u32 acpi_fill_csrt(u32 current)
+{
+	current += acpi_fill_csrt_dma((struct acpi_csrt_group *)current);
+
+	return current;
+}
+
 void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
 {
 	struct udevice *dev;
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index fa717bc..d4bdf62 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -18,6 +18,7 @@
 	qemu-x86_i440fx.dtb \
 	qemu-x86_q35.dtb \
 	theadorable-x86-dfi-bt700.dtb \
+	slimbootloader.dtb \
 	baytrail_som-db5800-som-6867.dtb
 
 targets += $(dtb-y)
diff --git a/arch/x86/dts/edison.dts b/arch/x86/dts/edison.dts
index c048765..df24aa0 100644
--- a/arch/x86/dts/edison.dts
+++ b/arch/x86/dts/edison.dts
@@ -84,15 +84,10 @@
 		reg = <0xff3fc000 0x1000>;
 	};
 
-/*
- * FIXME: For now U-Boot DM model doesn't allow to power up this controller.
- * Enabling it will make U-Boot hang.
- *
 	sdcard: mmc@ff3fa000 {
 		compatible = "intel,sdhci-tangier";
 		reg = <0xff3fa000 0x1000>;
 	};
- */
 
 	pmu: power@ff00b000 {
 		compatible = "intel,pmu-mid";
diff --git a/arch/x86/dts/slimbootloader.dts b/arch/x86/dts/slimbootloader.dts
new file mode 100644
index 0000000..d04095c
--- /dev/null
+++ b/arch/x86/dts/slimbootloader.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+/include/ "reset.dtsi"
+/include/ "tsc_timer.dtsi"
+
+/ {
+	model = "slimbootloader x86 payload";
+	compatible = "slimbootloader,x86-payload";
+
+	chosen {
+		stdout-path = &serial;
+	};
+
+	serial: serial {
+		compatible = "intel,slimbootloader-uart";
+	};
+
+	pci {
+		compatible = "pci-x86";
+	};
+};
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index e3b65cf..02aea12 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -303,6 +303,37 @@
 /* ACPI global NVS structure */
 struct acpi_global_nvs;
 
+/* CSRT (Core System Resource Table) */
+struct acpi_csrt {
+	struct acpi_table_header header;
+};
+
+struct acpi_csrt_group {
+	u32 length;
+	u32 vendor_id;
+	u32 subvendor_id;
+	u16 device_id;
+	u16 subdevice_id;
+	u16 revision;
+	u16 reserved;
+	u32 shared_info_length;
+};
+
+struct acpi_csrt_shared_info {
+	u16 major_version;
+	u16 minor_version;
+	u32 mmio_base_low;
+	u32 mmio_base_high;
+	u32 gsi_interrupt;
+	u8 interrupt_polarity;
+	u8 interrupt_mode;
+	u8 num_channels;
+	u8 dma_address_width;
+	u16 base_request_line;
+	u16 num_handshake_signals;
+	u32 max_block_size;
+};
+
 /* DBG2 definitions are partially used for SPCR interface_type */
 
 /* Types for port_type field */
@@ -370,6 +401,7 @@
 int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
 			      u16 seg_nr, u8 start, u8 end);
 u32 acpi_fill_mcfg(u32 current);
+u32 acpi_fill_csrt(u32 current);
 void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
 ulong write_acpi_tables(ulong start);
 
diff --git a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h
new file mode 100644
index 0000000..05dd1b2
--- /dev/null
+++ b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#ifndef __SLIMBOOTLOADER_ARCH_H__
+#define __SLIMBOOTLOADER_ARCH_H__
+
+#include <common.h>
+#include <asm/hob.h>
+
+/**
+ * A GUID to get MemoryMap info hob which is provided by Slim Bootloader
+ */
+#define SBL_MEMORY_MAP_INFO_GUID \
+	EFI_GUID(0xa1ff7424, 0x7a1a, 0x478e, \
+		0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32)
+
+/**
+ * A GUID to get SerialPort info hob which is provided by Slim Bootloader
+ */
+#define SBL_SERIAL_PORT_INFO_GUID \
+	EFI_GUID(0x6c6872fe, 0x56a9, 0x4403, \
+		0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1)
+
+/**
+ * A GUID to get boot performance info hob which is provided by Slim Bootloader
+ */
+#define SBL_PERFORMANCE_INFO_GUID \
+	EFI_GUID(0x868204be, 0x23d0, 0x4ff9, \
+		0xac, 0x34, 0xb9, 0x95, 0xac, 0x04, 0xb1, 0xb9)
+
+/**
+ * A single entry of memory map information
+ *
+ * @addr: start address of a memory map entry
+ * @size: size of a memory map entry
+ * @type: usable:1, reserved:2, acpi:3, nvs:4, unusable:5
+ * @flag: only used in Slim Bootloader
+ * @rsvd: padding for alignment
+ */
+struct sbl_memory_map_entry {
+	u64	addr;
+	u64	size;
+	u8	type;
+	u8	flag;
+	u8	rsvd[6];
+};
+
+/**
+ * This includes all memory map entries which is sorted based on physical start
+ * address, from low to high, and carved out reserved, acpi nvs, acpi reclaim
+ * and usable memory.
+ *
+ * @rev  : revision of memory_map_info structure. currently 1.
+ * @rsvd : padding for alignment
+ * @count: the number of memory map entries
+ * @entry: array of all memory map entries
+ */
+struct sbl_memory_map_info {
+	u8	rev;
+	u8	rsvd[3];
+	u32	count;
+	struct sbl_memory_map_entry	entry[0];
+};
+
+/**
+ * This includes serial port info which has already been initialized in previous
+ * Slim Bootloader stage.
+ * The Slim Bootloader initializes serial port regardless of debug/release build
+ * modes, and it passes the information to a payload thru hob. So, a payload can
+ * re-use the serial information without re-initializing serial port.
+ *
+ * @rev   : revision of serial_port_info structure. currently 1.
+ * @rsvd  : padding for alignment
+ * @type  : port io: 1, mmio: 2
+ * @base  : io base address. ex) 0x3f8, 0x80001000
+ * @baud  : uart baud rate
+ * @stride: register stride in Bytes
+ * @clk   : uart frequency in Hz
+ * @rsvd1 : reserved
+ */
+struct sbl_serial_port_info {
+	u8      rev;
+	u8      rsvd[3];
+	u32     type;
+	u32     base;
+	u32     baud;
+	u32     stride;
+	u32     clk;
+	u32     rsvd1;
+};
+
+/**
+ * This includes timestamp data which has been collected in Slim Bootloader
+ * stages from the reset vector. In addition, this has TSC frequency in KHz to
+ * calculate each timestamp.
+ *
+ * @rev   : revision of performance_info structure. currently 1.
+ * @rsvd  : padding for alignment
+ * @count : the number of collected timestamp data
+ * @flags : only used in Slim Bootloader
+ * @frequency: tsc frequency in KHz
+ * @timestamp: the array of timestamp data which has 64-bit tsc value
+ */
+struct sbl_performance_info {
+	u8      rev;
+	u8      rsvd[3];
+	u16     count;
+	u16     flags;
+	u32     frequency;
+	u64     timestamp[0];
+};
+
+#endif /* __SLIMBOOTLOADER_ARCH_H__ */
diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
index 8b5b709..b8b783b 100644
--- a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
+++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
@@ -421,6 +421,28 @@
             }
         }
     }
+
+    Device (GDMA)
+    {
+        Name (_ADR, 0x00150000)
+        Name (_HID, "808611A2")
+        Name (_UID, Zero)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Method (_CRS, 0, Serialized)
+        {
+            Name (RBUF, ResourceTemplate ()
+            {
+                    Memory32Fixed(ReadWrite, 0xFF192000, 0x00001000)
+                    Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, ,, ) { 32 }
+            })
+            Return (RBUF)
+        }
+    }
 }
 
 Device (FLIS)
diff --git a/arch/x86/include/asm/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp/fsp_ffs.h
index 61ce63c..b7558e5 100644
--- a/arch/x86/include/asm/fsp/fsp_ffs.h
+++ b/arch/x86/include/asm/fsp/fsp_ffs.h
@@ -45,7 +45,7 @@
 	 * This GUID is the file name.
 	 * It is used to uniquely identify the file.
 	 */
-	struct efi_guid		name;
+	efi_guid_t		name;
 	/* Used to verify the integrity of the file */
 	union ffs_integrity	integrity;
 	/* Identifies the type of file */
@@ -68,7 +68,7 @@
 	 * Name in any given firmware volume, except if the file type is
 	 * EFI_FV_FILE_TYPE_FFS_PAD.
 	 */
-	struct efi_guid		name;
+	efi_guid_t		name;
 	/* Used to verify the integrity of the file */
 	union ffs_integrity	integrity;
 	/* Identifies the type of file */
diff --git a/arch/x86/include/asm/fsp/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h
index 190aedc..511dfb7 100644
--- a/arch/x86/include/asm/fsp/fsp_fv.h
+++ b/arch/x86/include/asm/fsp/fsp_fv.h
@@ -80,7 +80,7 @@
 	 * Declares the file system with which the firmware volume
 	 * is formatted.
 	 */
-	struct efi_guid		fs_guid;
+	efi_guid_t		fs_guid;
 	/*
 	 * Length in bytes of the complete firmware volume, including
 	 * the header.
@@ -128,7 +128,7 @@
 /* Extension header pointed by ExtHeaderOffset of volume header */
 struct fv_ext_header {
 	/* firmware volume name */
-	struct efi_guid		fv_name;
+	efi_guid_t		fv_name;
 	/* Size of the rest of the extension header including this structure */
 	u32			ext_hdr_size;
 };
diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h
index 00657b6..3bb79c4 100644
--- a/arch/x86/include/asm/fsp/fsp_hob.h
+++ b/arch/x86/include/asm/fsp/fsp_hob.h
@@ -7,124 +7,7 @@
 #ifndef __FSP_HOB_H__
 #define __FSP_HOB_H__
 
-#include <efi.h>
-
-/* Type of HOB Header */
-#define HOB_TYPE_MEM_ALLOC	0x0002
-#define HOB_TYPE_RES_DESC	0x0003
-#define HOB_TYPE_GUID_EXT	0x0004
-#define HOB_TYPE_UNUSED		0xFFFE
-#define HOB_TYPE_EOH		0xFFFF
-
-/*
- * Describes the format and size of the data inside the HOB.
- * All HOBs must contain this generic HOB header.
- */
-struct hob_header {
-	u16	type;		/* HOB type */
-	u16	len;		/* HOB length */
-	u32	reserved;	/* always zero */
-};
-
-/*
- * Describes all memory ranges used during the HOB producer phase that
- * exist outside the HOB list. This HOB type describes how memory is used,
- * not the physical attributes of memory.
- */
-struct hob_mem_alloc {
-	struct hob_header	hdr;
-	/*
-	 * A GUID that defines the memory allocation region's type and purpose,
-	 * as well as other fields within the memory allocation HOB. This GUID
-	 * is used to define the additional data within the HOB that may be
-	 * present for the memory allocation HOB. Type efi_guid is defined in
-	 * InstallProtocolInterface() in the UEFI 2.0 specification.
-	 */
-	struct efi_guid		name;
-	/*
-	 * The base address of memory allocated by this HOB.
-	 * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0
-	 * specification.
-	 */
-	phys_addr_t		mem_base;
-	/* The length in bytes of memory allocated by this HOB */
-	phys_size_t		mem_len;
-	/*
-	 * Defines the type of memory allocated by this HOB.
-	 * The memory type definition follows the EFI_MEMORY_TYPE definition.
-	 * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0
-	 * specification.
-	 */
-	enum efi_mem_type	mem_type;
-	/* padding */
-	u8			reserved[4];
-};
-
-/* Value of ResourceType in HOB_RES_DESC */
-#define RES_SYS_MEM		0x00000000
-#define RES_MMAP_IO		0x00000001
-#define RES_IO			0x00000002
-#define RES_FW_DEVICE		0x00000003
-#define RES_MMAP_IO_PORT	0x00000004
-#define RES_MEM_RESERVED	0x00000005
-#define RES_IO_RESERVED		0x00000006
-#define RES_MAX_MEM_TYPE	0x00000007
-
-/*
- * These types can be ORed together as needed.
- *
- * The first three enumerations describe settings
- * The rest of the settings describe capabilities
- */
-#define RES_ATTR_PRESENT			0x00000001
-#define RES_ATTR_INITIALIZED			0x00000002
-#define RES_ATTR_TESTED				0x00000004
-#define RES_ATTR_SINGLE_BIT_ECC			0x00000008
-#define RES_ATTR_MULTIPLE_BIT_ECC		0x00000010
-#define RES_ATTR_ECC_RESERVED_1			0x00000020
-#define RES_ATTR_ECC_RESERVED_2			0x00000040
-#define RES_ATTR_READ_PROTECTED			0x00000080
-#define RES_ATTR_WRITE_PROTECTED		0x00000100
-#define RES_ATTR_EXECUTION_PROTECTED		0x00000200
-#define RES_ATTR_UNCACHEABLE			0x00000400
-#define RES_ATTR_WRITE_COMBINEABLE		0x00000800
-#define RES_ATTR_WRITE_THROUGH_CACHEABLE	0x00001000
-#define RES_ATTR_WRITE_BACK_CACHEABLE		0x00002000
-#define RES_ATTR_16_BIT_IO			0x00004000
-#define RES_ATTR_32_BIT_IO			0x00008000
-#define RES_ATTR_64_BIT_IO			0x00010000
-#define RES_ATTR_UNCACHED_EXPORTED		0x00020000
-
-/*
- * Describes the resource properties of all fixed, nonrelocatable resource
- * ranges found on the processor host bus during the HOB producer phase.
- */
-struct hob_res_desc {
-	struct hob_header	hdr;
-	/*
-	 * A GUID representing the owner of the resource. This GUID is
-	 * used by HOB consumer phase components to correlate device
-	 * ownership of a resource.
-	 */
-	struct efi_guid		owner;
-	u32			type;
-	u32			attr;
-	/* The physical start address of the resource region */
-	phys_addr_t		phys_start;
-	/* The number of bytes of the resource region */
-	phys_size_t		len;
-};
-
-/*
- * Allows writers of executable content in the HOB producer phase to
- * maintain and manage HOBs with specific GUID.
- */
-struct hob_guid {
-	struct hob_header	hdr;
-	/* A GUID that defines the contents of this HOB */
-	struct efi_guid		name;
-	/* GUID specific data goes here */
-};
+#include <asm/hob.h>
 
 enum pixel_format {
 	pixel_rgbx_8bpc,	/* RGB 8 bit per color */
@@ -146,70 +29,6 @@
 	u32 pixels_per_scanline;
 };
 
-/**
- * get_next_hob() - return a pointer to the next HOB in the HOB list
- *
- * This macro returns a pointer to HOB that follows the HOB specified by hob
- * in the HOB List.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: A pointer to the next HOB in the HOB list.
- */
-static inline const struct hob_header *get_next_hob(const struct hob_header *hdr)
-{
-	return (const struct hob_header *)((uintptr_t)hdr + hdr->len);
-}
-
-/**
- * end_of_hob() - determine if a HOB is the last HOB in the HOB list
- *
- * This macro determine if the HOB specified by hob is the last HOB in the
- * HOB list.  If hob is last HOB in the HOB list, then true is returned.
- * Otherwise, false is returned.
- *
- * @hdr:          A pointer to a HOB.
- *
- * @retval true:  The HOB specified by hdr is the last HOB in the HOB list.
- * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
- */
-static inline bool end_of_hob(const struct hob_header *hdr)
-{
-	return hdr->type == HOB_TYPE_EOH;
-}
-
-/**
- * get_guid_hob_data() - return a pointer to data buffer from a HOB of
- *                       type HOB_TYPE_GUID_EXT
- *
- * This macro returns a pointer to the data buffer in a HOB specified by hob.
- * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: A pointer to the data buffer in a HOB.
- */
-static inline void *get_guid_hob_data(const struct hob_header *hdr)
-{
-	return (void *)((uintptr_t)hdr + sizeof(struct hob_guid));
-}
-
-/**
- * get_guid_hob_data_size() - return the size of the data buffer from a HOB
- *                            of type HOB_TYPE_GUID_EXT
- *
- * This macro returns the size, in bytes, of the data buffer in a HOB
- * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: The size of the data buffer.
- */
-static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
-{
-	return hdr->len - sizeof(struct hob_guid);
-}
-
 /* FSP specific GUID HOB definitions */
 #define FSP_GUID_DATA1		0x912740be
 #define FSP_GUID_DATA2		0x2284
@@ -223,56 +42,57 @@
 #define FSP_GUID_DATA4_6	0x3f
 #define FSP_GUID_DATA4_7	0x0c
 
+#define FSP_GUID_BYTE0		0xbe
+#define FSP_GUID_BYTE1		0x40
+#define FSP_GUID_BYTE2		0x27
+#define FSP_GUID_BYTE3		0x91
+#define FSP_GUID_BYTE4		0x84
+#define FSP_GUID_BYTE5		0x22
+#define FSP_GUID_BYTE6		0x34
+#define FSP_GUID_BYTE7		0x47
+#define FSP_GUID_BYTE8		FSP_GUID_DATA4_0
+#define FSP_GUID_BYTE9		FSP_GUID_DATA4_1
+#define FSP_GUID_BYTE10		FSP_GUID_DATA4_2
+#define FSP_GUID_BYTE11		FSP_GUID_DATA4_3
+#define FSP_GUID_BYTE12		FSP_GUID_DATA4_4
+#define FSP_GUID_BYTE13		FSP_GUID_DATA4_5
+#define FSP_GUID_BYTE14		FSP_GUID_DATA4_6
+#define FSP_GUID_BYTE15		FSP_GUID_DATA4_7
+
 #define FSP_HEADER_GUID \
-	{ \
-	FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \
-	{ FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \
-	  FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \
-	  FSP_GUID_DATA4_6, FSP_GUID_DATA4_7 } \
-	}
+	EFI_GUID(FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \
+		FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \
+		FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \
+		FSP_GUID_DATA4_6, FSP_GUID_DATA4_7)
 
 #define FSP_NON_VOLATILE_STORAGE_HOB_GUID \
-	{ \
-	0x721acf02, 0x4d77, 0x4c2a, \
-	{ 0xb3, 0xdc, 0x27, 0xb, 0x7b, 0xa9, 0xe4, 0xb0 } \
-	}
+	EFI_GUID(0x721acf02, 0x4d77, 0x4c2a, \
+		0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0)
 
 #define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \
-	{ \
-	0xbbcff46c, 0xc8d3, 0x4113, \
-	{ 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } \
-	}
+	EFI_GUID(0xbbcff46c, 0xc8d3, 0x4113, \
+		0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e)
 
 #define FSP_HOB_RESOURCE_OWNER_FSP_GUID \
-	{ \
-	0x69a79759, 0x1373, 0x4367, \
-	{ 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } \
-	}
+	EFI_GUID(0x69a79759, 0x1373, 0x4367, \
+		0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e)
 
 #define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \
-	{ \
-	0xd038747c, 0xd00c, 0x4980, \
-	{ 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55 } \
-	}
+	EFI_GUID(0xd038747c, 0xd00c, 0x4980, \
+		0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55)
 
 #define FSP_HOB_RESOURCE_OWNER_GRAPHICS_GUID \
-	{ \
-	0x9c7c3aa7, 0x5332, 0x4917, \
-	{ 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07 } \
-	}
+	EFI_GUID(0x9c7c3aa7, 0x5332, 0x4917, \
+		0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07)
 
 /* The following GUIDs are newly introduced in FSP spec 1.1 */
 
 #define FSP_HOB_RESOURCE_OWNER_BOOTLOADER_TOLUM_GUID \
-	{ \
-	0x73ff4f56, 0xaa8e, 0x4451, \
-	{ 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44 } \
-	}
+	EFI_GUID(0x73ff4f56, 0xaa8e, 0x4451, \
+		0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44)
 
 #define FSP_GRAPHICS_INFO_HOB_GUID \
-	{ \
-	0x39f62cce, 0x6825, 0x4669, \
-	{ 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07 } \
-	}
+	EFI_GUID(0x39f62cce, 0x6825, 0x4669, \
+		0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07)
 
 #endif
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
index 7e51f24..7b92392 100644
--- a/arch/x86/include/asm/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -8,10 +8,10 @@
 #define __FSP_SUPPORT_H__
 
 #include "fsp_types.h"
+#include "fsp_hob.h"
 #include "fsp_fv.h"
 #include "fsp_ffs.h"
 #include "fsp_api.h"
-#include "fsp_hob.h"
 #include "fsp_infoheader.h"
 #include "fsp_bootmode.h"
 #include "fsp_azalia.h"
@@ -106,7 +106,7 @@
  *            0 if this region does not exist.
  */
 u64 fsp_get_reserved_mem_from_guid(const void *hob_list,
-				   u64 *len, struct efi_guid *guid);
+				   u64 *len, const efi_guid_t *guid);
 
 /**
  * This function retrieves the FSP reserved normal memory.
@@ -132,41 +132,6 @@
 u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len);
 
 /**
- * Returns the next instance of a HOB type from the starting HOB.
- *
- * @type:     HOB type to search
- * @hob_list: A pointer to the HOB list
- *
- * @retval:   A HOB object with matching type; Otherwise NULL.
- */
-const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list);
-
-/**
- * Returns the next instance of the matched GUID HOB from the starting HOB.
- *
- * @guid:     GUID to search
- * @hob_list: A pointer to the HOB list
- *
- * @retval:   A HOB object with matching GUID; Otherwise NULL.
- */
-const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
-					       const void *hob_list);
-
-/**
- * This function retrieves a GUID HOB data buffer and size.
- *
- * @hob_list:      A HOB list pointer.
- * @len:           A pointer to the GUID HOB data buffer length.
- *                 If the GUID HOB is located, the length will be updated.
- * @guid           A pointer to HOB GUID.
- *
- * @retval NULL:   Failed to find the GUID HOB.
- * @retval others: GUID HOB data buffer pointer.
- */
-void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
-			    struct efi_guid *guid);
-
-/**
  * This function retrieves FSP Non-volatile Storage HOB buffer and size.
  *
  * @hob_list:      A HOB list pointer.
diff --git a/arch/x86/include/asm/fsp/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h
index 5247102..3d5b17e 100644
--- a/arch/x86/include/asm/fsp/fsp_types.h
+++ b/arch/x86/include/asm/fsp/fsp_types.h
@@ -7,14 +7,6 @@
 #ifndef __FSP_TYPES_H__
 #define __FSP_TYPES_H__
 
-/* 128 bit buffer containing a unique identifier value */
-struct efi_guid {
-	u32	data1;
-	u16	data2;
-	u16	data3;
-	u8	data4[8];
-};
-
 /**
  * Returns a 16-bit signature built from 2 ASCII characters.
  *
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 9398ec3..797397e 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -83,7 +83,7 @@
 	const struct pch_gpio_map *gpio_map;	/* board GPIO map */
 	struct memory_info meminfo;	/* Memory information */
 	struct pei_memory_info pei_meminfo;	/* PEI memory information */
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	void *hob_list;			/* FSP HOB list */
 #endif
 	struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h
new file mode 100644
index 0000000..b423982
--- /dev/null
+++ b/arch/x86/include/asm/hob.h
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef __HOB_H__
+#define __HOB_H__
+
+#include <efi.h>
+#include <efi_loader.h>
+
+/* Type of HOB Header */
+#define HOB_TYPE_MEM_ALLOC	0x0002
+#define HOB_TYPE_RES_DESC	0x0003
+#define HOB_TYPE_GUID_EXT	0x0004
+#define HOB_TYPE_UNUSED		0xFFFE
+#define HOB_TYPE_EOH		0xFFFF
+
+/* Value of ResourceType in HOB_RES_DESC */
+#define RES_SYS_MEM		0x00000000
+#define RES_MMAP_IO		0x00000001
+#define RES_IO			0x00000002
+#define RES_FW_DEVICE		0x00000003
+#define RES_MMAP_IO_PORT	0x00000004
+#define RES_MEM_RESERVED	0x00000005
+#define RES_IO_RESERVED		0x00000006
+#define RES_MAX_MEM_TYPE	0x00000007
+
+/*
+ * These types can be ORed together as needed.
+ *
+ * The first three enumerations describe settings
+ * The rest of the settings describe capabilities
+ */
+#define RES_ATTR_PRESENT			0x00000001
+#define RES_ATTR_INITIALIZED			0x00000002
+#define RES_ATTR_TESTED				0x00000004
+#define RES_ATTR_SINGLE_BIT_ECC			0x00000008
+#define RES_ATTR_MULTIPLE_BIT_ECC		0x00000010
+#define RES_ATTR_ECC_RESERVED_1			0x00000020
+#define RES_ATTR_ECC_RESERVED_2			0x00000040
+#define RES_ATTR_READ_PROTECTED			0x00000080
+#define RES_ATTR_WRITE_PROTECTED		0x00000100
+#define RES_ATTR_EXECUTION_PROTECTED		0x00000200
+#define RES_ATTR_UNCACHEABLE			0x00000400
+#define RES_ATTR_WRITE_COMBINEABLE		0x00000800
+#define RES_ATTR_WRITE_THROUGH_CACHEABLE	0x00001000
+#define RES_ATTR_WRITE_BACK_CACHEABLE		0x00002000
+#define RES_ATTR_16_BIT_IO			0x00004000
+#define RES_ATTR_32_BIT_IO			0x00008000
+#define RES_ATTR_64_BIT_IO			0x00010000
+#define RES_ATTR_UNCACHED_EXPORTED		0x00020000
+
+/*
+ * Describes the format and size of the data inside the HOB.
+ * All HOBs must contain this generic HOB header.
+ */
+struct hob_header {
+	u16	type;		/* HOB type */
+	u16	len;		/* HOB length */
+	u32	reserved;	/* always zero */
+};
+
+/*
+ * Describes all memory ranges used during the HOB producer phase that
+ * exist outside the HOB list. This HOB type describes how memory is used,
+ * not the physical attributes of memory.
+ */
+struct hob_mem_alloc {
+	struct hob_header	hdr;
+	/*
+	 * A GUID that defines the memory allocation region's type and purpose,
+	 * as well as other fields within the memory allocation HOB. This GUID
+	 * is used to define the additional data within the HOB that may be
+	 * present for the memory allocation HOB. Type efi_guid_t is defined in
+	 * InstallProtocolInterface() in the UEFI 2.0 specification.
+	 */
+	efi_guid_t		name;
+	/*
+	 * The base address of memory allocated by this HOB.
+	 * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0
+	 * specification.
+	 */
+	phys_addr_t		mem_base;
+	/* The length in bytes of memory allocated by this HOB */
+	phys_size_t		mem_len;
+	/*
+	 * Defines the type of memory allocated by this HOB.
+	 * The memory type definition follows the EFI_MEMORY_TYPE definition.
+	 * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0
+	 * specification.
+	 */
+	enum efi_mem_type	mem_type;
+	/* padding */
+	u8			reserved[4];
+};
+
+/*
+ * Describes the resource properties of all fixed, nonrelocatable resource
+ * ranges found on the processor host bus during the HOB producer phase.
+ */
+struct hob_res_desc {
+	struct hob_header	hdr;
+	/*
+	 * A GUID representing the owner of the resource. This GUID is
+	 * used by HOB consumer phase components to correlate device
+	 * ownership of a resource.
+	 */
+	efi_guid_t		owner;
+	u32			type;
+	u32			attr;
+	/* The physical start address of the resource region */
+	phys_addr_t		phys_start;
+	/* The number of bytes of the resource region */
+	phys_size_t		len;
+};
+
+/*
+ * Allows writers of executable content in the HOB producer phase to
+ * maintain and manage HOBs with specific GUID.
+ */
+struct hob_guid {
+	struct hob_header	hdr;
+	/* A GUID that defines the contents of this HOB */
+	efi_guid_t		name;
+	/* GUID specific data goes here */
+};
+
+/**
+ * get_next_hob() - return a pointer to the next HOB in the HOB list
+ *
+ * This macro returns a pointer to HOB that follows the HOB specified by hob
+ * in the HOB List.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: A pointer to the next HOB in the HOB list.
+ */
+static inline const struct hob_header *get_next_hob(const struct hob_header
+						    *hdr)
+{
+	return (const struct hob_header *)((uintptr_t)hdr + hdr->len);
+}
+
+/**
+ * end_of_hob() - determine if a HOB is the last HOB in the HOB list
+ *
+ * This macro determine if the HOB specified by hob is the last HOB in the
+ * HOB list.  If hob is last HOB in the HOB list, then true is returned.
+ * Otherwise, false is returned.
+ *
+ * @hdr:          A pointer to a HOB.
+ *
+ * @retval true:  The HOB specified by hdr is the last HOB in the HOB list.
+ * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
+ */
+static inline bool end_of_hob(const struct hob_header *hdr)
+{
+	return hdr->type == HOB_TYPE_EOH;
+}
+
+/**
+ * get_guid_hob_data() - return a pointer to data buffer from a HOB of
+ *                       type HOB_TYPE_GUID_EXT
+ *
+ * This macro returns a pointer to the data buffer in a HOB specified by hob.
+ * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: A pointer to the data buffer in a HOB.
+ */
+static inline void *get_guid_hob_data(const struct hob_header *hdr)
+{
+	return (void *)((uintptr_t)hdr + sizeof(struct hob_guid));
+}
+
+/**
+ * get_guid_hob_data_size() - return the size of the data buffer from a HOB
+ *                            of type HOB_TYPE_GUID_EXT
+ *
+ * This macro returns the size, in bytes, of the data buffer in a HOB
+ * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: The size of the data buffer.
+ */
+static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
+{
+	return hdr->len - sizeof(struct hob_guid);
+}
+
+/**
+ * Returns the next instance of a HOB type from the starting HOB.
+ *
+ * @type:     HOB type to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching type; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
+
+/**
+ * Returns the next instance of the matched GUID HOB from the starting HOB.
+ *
+ * @guid:     GUID to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching GUID; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
+					       const void *hob_list);
+
+/**
+ * This function retrieves a GUID HOB data buffer and size.
+ *
+ * @hob_list:      A HOB list pointer.
+ * @len:           A pointer to the GUID HOB data buffer length.
+ *                 If the GUID HOB is located, the length will be updated.
+ * @guid           A pointer to HOB GUID.
+ *
+ * @retval NULL:   Failed to find the GUID HOB.
+ * @retval others: GUID HOB data buffer pointer.
+ */
+void *hob_get_guid_hob_data(const void *hob_list, u32 *len,
+			    const efi_guid_t *guid);
+
+#endif /* __HOB_H__ */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 436252d..906be5e 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -42,6 +42,7 @@
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZBOOT)	+= zimage.o
 endif
+obj-$(CONFIG_USE_HOB) += hob.o
 obj-$(CONFIG_HAVE_FSP) += fsp/
 
 ifdef CONFIG_SPL_BUILD
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 270274f..0d69cf2 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -337,6 +337,30 @@
 	header->checksum = table_compute_checksum((void *)mcfg, header->length);
 }
 
+__weak u32 acpi_fill_csrt(u32 current)
+{
+	return current;
+}
+
+static void acpi_create_csrt(struct acpi_csrt *csrt)
+{
+	struct acpi_table_header *header = &(csrt->header);
+	u32 current = (u32)csrt + sizeof(struct acpi_csrt);
+
+	memset((void *)csrt, 0, sizeof(struct acpi_csrt));
+
+	/* Fill out header fields */
+	acpi_fill_header(header, "CSRT");
+	header->length = sizeof(struct acpi_csrt);
+	header->revision = 0;
+
+	current = acpi_fill_csrt(current);
+
+	/* (Re)calculate length and checksum */
+	header->length = current - (u32)csrt;
+	header->checksum = table_compute_checksum((void *)csrt, header->length);
+}
+
 static void acpi_create_spcr(struct acpi_spcr *spcr)
 {
 	struct acpi_table_header *header = &(spcr->header);
@@ -464,6 +488,7 @@
 	struct acpi_fadt *fadt;
 	struct acpi_mcfg *mcfg;
 	struct acpi_madt *madt;
+	struct acpi_csrt *csrt;
 	struct acpi_spcr *spcr;
 	int i;
 
@@ -553,6 +578,13 @@
 	acpi_add_table(rsdp, mcfg);
 	current = ALIGN(current, 16);
 
+	debug("ACPI:    * CSRT\n");
+	csrt = (struct acpi_csrt *)current;
+	acpi_create_csrt(csrt);
+	current += csrt->header.length;
+	acpi_add_table(rsdp, csrt);
+	current = ALIGN(current, 16);
+
 	debug("ACPI:    * SPCR\n");
 	spcr = (struct acpi_spcr *)current;
 	acpi_create_spcr(spcr);
diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c
index 90dce22..47b38cd 100644
--- a/arch/x86/lib/asm-offsets.c
+++ b/arch/x86/lib/asm-offsets.c
@@ -17,7 +17,7 @@
 int main(void)
 {
 	DEFINE(GD_BIST, offsetof(gd_t, arch.bist));
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list));
 #endif
 	DEFINE(GD_TABLE, offsetof(gd_t, arch.table));
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 90e4e7d..0eaa9b2 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -8,27 +8,6 @@
 #include <asm/fsp/fsp_support.h>
 #include <asm/post.h>
 
-/**
- * Compares two GUIDs
- *
- * If the GUIDs are identical then true is returned.
- * If there are any bit differences in the two GUIDs, then false is returned.
- *
- * @guid1:        A pointer to a 128 bit GUID.
- * @guid2:        A pointer to a 128 bit GUID.
- *
- * @retval true:  guid1 and guid2 are identical.
- * @retval false: guid1 and guid2 are not identical.
- */
-static bool compare_guid(const struct efi_guid *guid1,
-			 const struct efi_guid *guid2)
-{
-	if (memcmp(guid1, guid2, sizeof(struct efi_guid)) == 0)
-		return true;
-	else
-		return false;
-}
-
 struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
 {
 	/*
@@ -58,17 +37,22 @@
 
 	/* Check the FFS GUID */
 	if (fsp &&
-	    ((struct ffs_file_header *)fsp)->name.data1 == FSP_GUID_DATA1 &&
-	    ((struct ffs_file_header *)fsp)->name.data2 == FSP_GUID_DATA2 &&
-	    ((struct ffs_file_header *)fsp)->name.data3 == FSP_GUID_DATA3 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[0] == FSP_GUID_DATA4_0 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[1] == FSP_GUID_DATA4_1 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[2] == FSP_GUID_DATA4_2 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[3] == FSP_GUID_DATA4_3 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[4] == FSP_GUID_DATA4_4 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[5] == FSP_GUID_DATA4_5 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[6] == FSP_GUID_DATA4_6 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[7] == FSP_GUID_DATA4_7) {
+	    ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 &&
+	    ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 &&
+	    ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 &&
+	    ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 &&
+	    ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 &&
+	    ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 &&
+	    ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 &&
+	    ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 &&
+	    ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 &&
+	    ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 &&
+	    ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 &&
+	    ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 &&
+	    ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 &&
+	    ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 &&
+	    ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 &&
+	    ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) {
 		/* Add the FFS header size to find the raw section header */
 		fsp += sizeof(struct ffs_file_header);
 	} else {
@@ -305,7 +289,7 @@
 }
 
 u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
-				   struct efi_guid *guid)
+				   const efi_guid_t *guid)
 {
 	const struct hob_header *hdr;
 	struct hob_res_desc *res_desc;
@@ -318,7 +302,7 @@
 		if (hdr->type == HOB_TYPE_RES_DESC) {
 			res_desc = (struct hob_res_desc *)hdr;
 			if (res_desc->type == RES_MEM_RESERVED) {
-				if (compare_guid(&res_desc->owner, guid)) {
+				if (!guidcmp(&res_desc->owner, guid)) {
 					if (len)
 						*len = (u32)(res_desc->len);
 
@@ -334,12 +318,12 @@
 
 u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
+	const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
 	u64 length;
 	u32 base;
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
-			&length, (struct efi_guid *)&guid);
+			&length, &guid);
 	if ((len != 0) && (base != 0))
 		*len = (u32)length;
 
@@ -348,86 +332,35 @@
 
 u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID;
+	const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID;
 	u64 length;
 	u32 base;
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
-			&length, (struct efi_guid *)&guid);
+			&length, &guid);
 	if ((len != 0) && (base != 0))
 		*len = (u32)length;
 
 	return base;
 }
 
-const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
-{
-	const struct hob_header *hdr;
-
-	hdr = hob_list;
-
-	/* Parse the HOB list until end of list or matching type is found */
-	while (!end_of_hob(hdr)) {
-		if (hdr->type == type)
-			return hdr;
-
-		hdr = get_next_hob(hdr);
-	}
-
-	return NULL;
-}
-
-const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
-					       const void *hob_list)
-{
-	const struct hob_header *hdr;
-	struct hob_guid *guid_hob;
-
-	hdr = hob_list;
-	while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
-			hdr)) != NULL) {
-		guid_hob = (struct hob_guid *)hdr;
-		if (compare_guid(guid, &(guid_hob->name)))
-			break;
-		hdr = get_next_hob(hdr);
-	}
-
-	return hdr;
-}
-
-void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
-			    struct efi_guid *guid)
-{
-	const struct hob_header *guid_hob;
-
-	guid_hob = fsp_get_next_guid_hob(guid, hob_list);
-	if (guid_hob == NULL) {
-		return NULL;
-	} else {
-		if (len)
-			*len = get_guid_hob_data_size(guid_hob);
-
-		return get_guid_hob_data(guid_hob);
-	}
-}
-
 void *fsp_get_nvs_data(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
+	const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
 
 void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;
+	const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
 
 void *fsp_get_graphics_info(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_GRAPHICS_INFO_HOB_GUID;
+	const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c
new file mode 100644
index 0000000..dcee29b
--- /dev/null
+++ b/arch/x86/lib/hob.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/hob.h>
+
+/**
+ * Returns the next instance of a HOB type from the starting HOB.
+ *
+ * @type:     HOB type to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching type; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_hob(uint type, const void *hob_list)
+{
+	const struct hob_header *hdr;
+
+	hdr = hob_list;
+
+	/* Parse the HOB list until end of list or matching type is found */
+	while (!end_of_hob(hdr)) {
+		if (hdr->type == type)
+			return hdr;
+
+		hdr = get_next_hob(hdr);
+	}
+
+	return NULL;
+}
+
+/**
+ * Returns the next instance of the matched GUID HOB from the starting HOB.
+ *
+ * @guid:     GUID to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching GUID; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
+					       const void *hob_list)
+{
+	const struct hob_header *hdr;
+	struct hob_guid *guid_hob;
+
+	hdr = hob_list;
+	while ((hdr = hob_get_next_hob(HOB_TYPE_GUID_EXT, hdr))) {
+		guid_hob = (struct hob_guid *)hdr;
+		if (!guidcmp(guid, &guid_hob->name))
+			break;
+		hdr = get_next_hob(hdr);
+	}
+
+	return hdr;
+}
+
+/**
+ * This function retrieves a GUID HOB data buffer and size.
+ *
+ * @hob_list:      A HOB list pointer.
+ * @len:           A pointer to the GUID HOB data buffer length.
+ *                 If the GUID HOB is located, the length will be updated.
+ * @guid           A pointer to HOB GUID.
+ *
+ * @retval NULL:   Failed to find the GUID HOB.
+ * @retval others: GUID HOB data buffer pointer.
+ */
+void *hob_get_guid_hob_data(const void *hob_list, u32 *len,
+			    const efi_guid_t *guid)
+{
+	const struct hob_header *guid_hob;
+
+	guid_hob = hob_get_next_guid_hob(guid, hob_list);
+	if (!guid_hob)
+		return NULL;
+
+	if (len)
+		*len = get_guid_hob_data_size(guid_hob);
+
+	return get_guid_hob_data(guid_hob);
+}
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 0481f45..5e19f13 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -18,7 +18,8 @@
 
 int init_cache_f_r(void)
 {
-#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP)
+#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) && \
+		!defined(CONFIG_SYS_SLIMBOOTLOADER)
 	int ret;
 
 	ret = mtrr_commit(false);
diff --git a/board/intel/Kconfig b/board/intel/Kconfig
index 5131836..7b16ec4 100644
--- a/board/intel/Kconfig
+++ b/board/intel/Kconfig
@@ -73,6 +73,19 @@
 	  Note that PCIE_ECAM_BASE is set up by the FSP so the value used
 	  by U-Boot matches that value.
 
+config TARGET_SLIMBOOTLOADER
+	bool "slimbootloader"
+	help
+	  This target is used for running U-Boot on top of Slim Bootloader
+	  boot firmware as a payload. Slim Bootloader does memory initialization
+	  and silicon initialization, and it passes necessary information in
+	  HOB (Hand Off Block) to a payload. The payload consumes HOB data
+	  which is generated by Slim Bootloader for its driver initialization.
+	  Slim Bootloader consumes FSP and its HOB, but FSP HOB is cleared
+	  Before launching a payload. Instead, Slim Bootloader generates its
+	  HOB data such as memory info, serial port info and so on.
+	  Refer to doc/board/intel/slimbootloader.rst for the details.
+
 endchoice
 
 source "board/intel/bayleybay/Kconfig"
@@ -82,5 +95,6 @@
 source "board/intel/edison/Kconfig"
 source "board/intel/galileo/Kconfig"
 source "board/intel/minnowmax/Kconfig"
+source "board/intel/slimbootloader/Kconfig"
 
 endif
diff --git a/board/intel/edison/edison.c b/board/intel/edison/edison.c
index 5faf3c5..d80ee3a 100644
--- a/board/intel/edison/edison.c
+++ b/board/intel/edison/edison.c
@@ -13,9 +13,19 @@
 #include <linux/usb/gadget.h>
 
 #include <asm/cache.h>
+#include <asm/pmu.h>
 #include <asm/scu.h>
 #include <asm/u-boot-x86.h>
 
+/* List of Intel Tangier LSSs */
+#define PMU_LSS_TANGIER_SDIO0_01	1
+
+int board_early_init_r(void)
+{
+	pmu_turn_power(PMU_LSS_TANGIER_SDIO0_01, true);
+	return 0;
+}
+
 static struct dwc3_device dwc3_device_data = {
 	.maximum_speed = USB_SPEED_HIGH,
 	.base = CONFIG_SYS_USB_OTG_BASE,
diff --git a/board/intel/slimbootloader/Kconfig b/board/intel/slimbootloader/Kconfig
new file mode 100644
index 0000000..8c7e22c
--- /dev/null
+++ b/board/intel/slimbootloader/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+if TARGET_SLIMBOOTLOADER
+
+config SYS_BOARD
+	default "slimbootloader"
+
+config SYS_VENDOR
+	default "intel"
+
+config SYS_SOC
+	default "slimbootloader"
+
+config SYS_CONFIG_NAME
+	default "slimbootloader"
+
+config SYS_TEXT_BASE
+	default 0x00100000
+
+config BOARD_SPECIFIC_OPTIONS
+	def_bool y
+	select SYS_SLIMBOOTLOADER
+	select USB_STORAGE
+	select USB_KEYBOARD
+
+endif
diff --git a/board/intel/slimbootloader/MAINTAINERS b/board/intel/slimbootloader/MAINTAINERS
new file mode 100644
index 0000000..e693551
--- /dev/null
+++ b/board/intel/slimbootloader/MAINTAINERS
@@ -0,0 +1,6 @@
+Intel Slim Bootloader Payload
+M:	Aiden Park <aiden.park@intel.com>
+S:	Maintained
+F:	board/intel/slimbootloader
+F:	include/configs/slimbootloader.h
+F:	configs/slimbootloader_defconfig
diff --git a/board/intel/slimbootloader/Makefile b/board/intel/slimbootloader/Makefile
new file mode 100644
index 0000000..fd8fa98
--- /dev/null
+++ b/board/intel/slimbootloader/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+obj-y	+= start.o slimbootloader.o
diff --git a/board/intel/slimbootloader/slimbootloader.c b/board/intel/slimbootloader/slimbootloader.c
new file mode 100644
index 0000000..f50eeb8
--- /dev/null
+++ b/board/intel/slimbootloader/slimbootloader.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+
+int board_early_init_r(void)
+{
+	/*
+	 * Make sure PCI bus is enumerated so that peripherals on the PCI bus
+	 * can be discovered by their drivers.
+	 *
+	 * Slim Bootloader has already done PCI bus enumeration before loading
+	 * U-Boot, so U-Boot needs to preserve PCI configuration.
+	 * Therefore, '# CONFIG_PCI_PNP is not set' is included in defconfig.
+	 */
+	pci_init();
+
+	return 0;
+}
diff --git a/board/intel/slimbootloader/start.S b/board/intel/slimbootloader/start.S
new file mode 100644
index 0000000..5c3f3df
--- /dev/null
+++ b/board/intel/slimbootloader/start.S
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+/* board early initialization */
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/board/rockchip/evb_rk3399/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS
index 3308b35..d9711ab 100644
--- a/board/rockchip/evb_rk3399/MAINTAINERS
+++ b/board/rockchip/evb_rk3399/MAINTAINERS
@@ -6,6 +6,24 @@
 F:      configs/evb-rk3399_defconfig
 F:      configs/firefly-rk3399_defconfig
 
+KHADAS-EDGE
+M:	Nick Xie <nick@khadas.com>
+S:	Maintained
+F:	configs/khadas-edge-rk3399_defconfig
+F:	arch/arm/dts/rk3399-khadas-edge-u-boot.dtsi
+
+KHADAS-EDGE-CAPTAIN
+M:	Nick Xie <nick@khadas.com>
+S:	Maintained
+F:	configs/khadas-edge-captain-rk3399_defconfig
+F:	arch/arm/dts/rk3399-khadas-edge-captain-u-boot.dtsi
+
+KHADAS-EDGE-V
+M:	Nick Xie <nick@khadas.com>
+S:	Maintained
+F:	configs/khadas-edge-v-rk3399_defconfig
+F:	arch/arm/dts/rk3399-khadas-edge-v-u-boot.dtsi
+
 NANOPC-T4
 M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
diff --git a/board/toradex/apalis-tk1/apalis-tk1.c b/board/toradex/apalis-tk1/apalis-tk1.c
index b87e9e7..beb7e10 100644
--- a/board/toradex/apalis-tk1/apalis-tk1.c
+++ b/board/toradex/apalis-tk1/apalis-tk1.c
@@ -10,6 +10,7 @@
 #include <asm/io.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+#include <environment.h>
 #include <pci_tegra.h>
 #include <power/as3722.h>
 #include <power/pmic.h>
@@ -19,11 +20,16 @@
 
 #define LAN_DEV_OFF_N	TEGRA_GPIO(O, 6)
 #define LAN_RESET_N	TEGRA_GPIO(S, 2)
+#define FAN_EN		TEGRA_GPIO(DD, 2)
 #define LAN_WAKE_N	TEGRA_GPIO(O, 5)
 #ifdef CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT
 #define PEX_PERST_N	TEGRA_GPIO(DD, 1) /* Apalis GPIO7 */
 #define RESET_MOCI_CTRL	TEGRA_GPIO(U, 4)
 #endif /* CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT */
+#define VCC_USBH	TEGRA_GPIO(T, 6)
+#define VCC_USBH_V1_0	TEGRA_GPIO(N, 5)
+#define VCC_USBO1	TEGRA_GPIO(T, 5)
+#define VCC_USBO1_V1_0	TEGRA_GPIO(N, 4)
 
 int arch_misc_init(void)
 {
@@ -31,6 +37,38 @@
 	    NVBOOTTYPE_RECOVERY)
 		printf("USB recovery mode\n");
 
+	/* PCB Version Indication: V1.2 and later have GPIO_PV0 wired to GND */
+	gpio_request(TEGRA_GPIO(V, 0), "PCB Version Indication");
+	gpio_direction_input(TEGRA_GPIO(V, 0));
+	if (gpio_get_value(TEGRA_GPIO(V, 0))) {
+		/*
+		 * if using the default device tree for new V1.2 and later HW,
+		 * use version for older V1.0 and V1.1 HW
+		 */
+		char *fdt_env = env_get("fdt_module");
+
+		if (fdt_env && !strcmp(FDT_MODULE, fdt_env)) {
+			env_set("fdt_module", FDT_MODULE_V1_0);
+			printf("patching fdt_module to " FDT_MODULE_V1_0
+			       " for older V1.0 and V1.1 HW\n");
+#ifndef CONFIG_ENV_IS_NOWHERE
+			env_save();
+#endif
+		}
+
+		/* activate USB power enable GPIOs */
+		gpio_request(VCC_USBH_V1_0, "VCC_USBH");
+		gpio_direction_output(VCC_USBH_V1_0, 1);
+		gpio_request(VCC_USBO1_V1_0, "VCC_USBO1");
+		gpio_direction_output(VCC_USBO1_V1_0, 1);
+	} else {
+		/* activate USB power enable GPIOs */
+		gpio_request(VCC_USBH, "VCC_USBH");
+		gpio_direction_output(VCC_USBH, 1);
+		gpio_request(VCC_USBO1, "VCC_USBO1");
+		gpio_direction_output(VCC_USBO1, 1);
+	}
+
 	return 0;
 }
 
@@ -242,6 +280,15 @@
 #endif /* CONFIG_PCI_TEGRA */
 
 /*
+ * Enable/start PWM CPU fan
+ */
+void start_cpu_fan(void)
+{
+	gpio_request(FAN_EN, "FAN_EN");
+	gpio_direction_output(FAN_EN, 1);
+}
+
+/*
  * Backlight off before OS handover
  */
 void board_preboot_os(void)
diff --git a/board/toradex/apalis-tk1/as3722_init.c b/board/toradex/apalis-tk1/as3722_init.c
index bd754e5..15f8dce 100644
--- a/board/toradex/apalis-tk1/as3722_init.c
+++ b/board/toradex/apalis-tk1/as3722_init.c
@@ -43,6 +43,29 @@
 	udelay(10 * 1000);
 #endif
 
+	/*
+	 * Make sure all non-fused regulators are down.
+	 * That way we're in known state after software reboot from linux
+	 */
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x0003, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x0004, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x001b, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x0014, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x001a, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+	tegra_i2c_ll_write_addr(AS3722_I2C_ADDR, 2);
+	tegra_i2c_ll_write_data(0x0019, I2C_SEND_2_BYTES);
+	udelay(10 * 1000);
+
 	debug("%s: Setting VDD_CPU to 1.0V via AS3722 reg 0/4D\n", __func__);
 	/*
 	 * Bring up VDD_CPU via the AS3722 PMIC on the PWR I2C bus.
diff --git a/board/toradex/apalis-tk1/pinmux-config-apalis-tk1.h b/board/toradex/apalis-tk1/pinmux-config-apalis-tk1.h
index 1584d9b..6778a41 100644
--- a/board/toradex/apalis-tk1/pinmux-config-apalis-tk1.h
+++ b/board/toradex/apalis-tk1/pinmux-config-apalis-tk1.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright (c) 2016, Toradex, Inc.
+ * Copyright (c) 2016-2019, Toradex, Inc.
  */
 
 #ifndef _PINMUX_CONFIG_APALIS_TK1_H_
@@ -24,8 +24,6 @@
 	GPIO_INIT(K,    2,   IN),
 	GPIO_INIT(K,    7,   IN),
 	GPIO_INIT(N,    2,   OUT1),
-	GPIO_INIT(N,    4,   OUT1),
-	GPIO_INIT(N,    5,   OUT1),
 	GPIO_INIT(N,    7,   IN),
 	GPIO_INIT(O,    5,   IN),
 	GPIO_INIT(Q,    0,   OUT0), /* Shift_CTRL_OE[0] */
@@ -39,7 +37,8 @@
 	GPIO_INIT(R,    1,   OUT0), /* Shift_CTRL_Dir_In[1] */
 	GPIO_INIT(R,    2,   OUT0), /* Shift_CTRL_OE[3] */
 	GPIO_INIT(S,    3,   OUT0), /* Shift_CTRL_Dir_In[2] */
-	GPIO_INIT(U,    4,   OUT1),
+	GPIO_INIT(U,    4,   OUT0), /* RESET_MOCI_CTRL */
+	GPIO_INIT(V,    0,   IN),
 	GPIO_INIT(W,    3,   IN),
 	GPIO_INIT(W,    5,   IN),
 	GPIO_INIT(BB,   0,  IN),
@@ -130,8 +129,8 @@
 	PINCFG(DAP1_DIN_PN1,           RSVD4,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(DAP1_DOUT_PN2,          SATA,         NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(DAP1_SCLK_PN3,          RSVD4,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
-	PINCFG(USB_VBUS_EN0_PN4,       RSVD2,        NORMAL, NORMAL,   OUTPUT,  DISABLE, DEFAULT),
-	PINCFG(USB_VBUS_EN1_PN5,       RSVD2,        NORMAL, NORMAL,   OUTPUT,  DISABLE, DEFAULT),
+	PINCFG(USB_VBUS_EN0_PN4,       RSVD2,        NORMAL, NORMAL,   INPUT,   DISABLE, DEFAULT),
+	PINCFG(USB_VBUS_EN1_PN5,       RSVD2,        NORMAL, NORMAL,   INPUT,   DISABLE, DEFAULT),
 	PINCFG(HDMI_INT_PN7,           RSVD1,        DOWN,   TRISTATE, INPUT,   DEFAULT, NORMAL),
 	PINCFG(ULPI_DATA7_PO0,         ULPI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(ULPI_DATA0_PO1,         ULPI,         DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
@@ -175,8 +174,8 @@
 	PINCFG(KB_ROW15_PS7,           RSVD2,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(KB_ROW16_PT0,           RSVD2,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(KB_ROW17_PT1,           RSVD2,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
-	PINCFG(GEN2_I2C_SCL_PT5,       I2C2,         NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
-	PINCFG(GEN2_I2C_SDA_PT6,       I2C2,         NORMAL, NORMAL,   INPUT,   ENABLE,  DEFAULT),
+	PINCFG(GEN2_I2C_SCL_PT5,       RSVD2,        NORMAL, NORMAL,   OUTPUT,  DISABLE, DEFAULT),
+	PINCFG(GEN2_I2C_SDA_PT6,       RSVD2,        NORMAL, NORMAL,   OUTPUT,  DISABLE, DEFAULT),
 	PINCFG(SDMMC4_CMD_PT7,         SDMMC4,       UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
 	PINCFG(PU0,                    UARTA,        NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(PU1,                    UARTA,        NORMAL, TRISTATE, INPUT,   DEFAULT, DEFAULT),
@@ -185,12 +184,12 @@
 	PINCFG(PU4,                    GMI,          NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(PU5,                    GMI,          DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(PU6,                    PWM3,         NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
-	PINCFG(PV0,                    RSVD1,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
+	PINCFG(PV0,                    RSVD1,        UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
 	PINCFG(PV1,                    RSVD1,        DOWN,   TRISTATE, OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(SDMMC3_CD_N_PV2,        RSVD3,        UP,     TRISTATE, INPUT,   DEFAULT, DEFAULT),
 	PINCFG(SDMMC1_WP_N_PV3,        SDMMC1,       UP,     TRISTATE, INPUT,   DEFAULT, DEFAULT),
-	PINCFG(DDC_SCL_PV4,            RSVD2,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
-	PINCFG(DDC_SDA_PV5,            RSVD2,        NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
+	PINCFG(DDC_SCL_PV4,            I2C4,         NORMAL, NORMAL,   INPUT,   DEFAULT, NORMAL),
+	PINCFG(DDC_SDA_PV5,            I2C4,         NORMAL, NORMAL,   INPUT,   DEFAULT, NORMAL),
 	PINCFG(GPIO_W2_AUD_PW2,        SPI2,         NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
 	PINCFG(GPIO_W3_AUD_PW3,        SPI6,         NORMAL, TRISTATE, INPUT,   DEFAULT, DEFAULT),
 	PINCFG(DAP_MCLK1_PW4,          EXTPERIPH1,   NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile
index 7071614..144b1cf 100644
--- a/cmd/x86/Makefile
+++ b/cmd/x86/Makefile
@@ -2,4 +2,5 @@
 
 obj-y += mtrr.o
 obj-$(CONFIG_CMD_EXCEPTION) += exception.o
+obj-$(CONFIG_USE_HOB) += hob.o
 obj-$(CONFIG_HAVE_FSP) += fsp.o
diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c
index 9f94ca9..efa1838 100644
--- a/cmd/x86/fsp.c
+++ b/cmd/x86/fsp.c
@@ -9,21 +9,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static char *hob_type[] = {
-	"reserved",
-	"Hand-off",
-	"Mem Alloc",
-	"Res Desc",
-	"GUID Ext",
-	"FV",
-	"CPU",
-	"Mem Pool",
-	"reserved",
-	"FV2",
-	"Load PEIM",
-	"Capsule",
-};
-
 static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	struct fsp_header *hdr = find_fsp_header();
@@ -72,57 +57,8 @@
 	return 0;
 }
 
-static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	const struct hob_header *hdr;
-	uint type;
-	char *desc;
-	int i = 0;
-
-	hdr = gd->arch.hob_list;
-
-	printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
-
-	printf("#  | Address  | Type      | Len  | ");
-	printf("%42s\n", "GUID");
-	printf("---|----------|-----------|------|-");
-	printf("------------------------------------------\n");
-	while (!end_of_hob(hdr)) {
-		printf("%02x | %08x | ", i, (unsigned int)hdr);
-		type = hdr->type;
-		if (type == HOB_TYPE_UNUSED)
-			desc = "*Unused*";
-		else if (type == HOB_TYPE_EOH)
-			desc = "*EOH*";
-		else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
-			desc = hob_type[type];
-		else
-			desc = "*Invalid*";
-		printf("%-9s | %04x | ", desc, hdr->len);
-
-		if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
-		    type == HOB_TYPE_GUID_EXT) {
-			struct efi_guid *guid = (struct efi_guid *)(hdr + 1);
-			int j;
-
-			printf("%08x-%04x-%04x", guid->data1,
-			       guid->data2, guid->data3);
-			for (j = 0; j < ARRAY_SIZE(guid->data4); j++)
-				printf("-%02x", guid->data4[j]);
-		} else {
-			printf("%42s", "Not Available");
-		}
-		printf("\n");
-		hdr = get_next_hob(hdr);
-		i++;
-	}
-
-	return 0;
-}
-
 static cmd_tbl_t fsp_commands[] = {
 	U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""),
-	U_BOOT_CMD_MKENT(hob, 0, 1, do_hob, "", ""),
 };
 
 static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -146,6 +82,5 @@
 U_BOOT_CMD(
 	fsp,	2,	1,	do_fsp,
 	"Show Intel Firmware Support Package (FSP) related information",
-	"hdr - Print FSP header information\n"
-	"fsp hob - Print FSP Hand-Off Block (HOB) information"
+	"hdr - Print FSP header information"
 );
diff --git a/cmd/x86/hob.c b/cmd/x86/hob.c
new file mode 100644
index 0000000..3967a7c
--- /dev/null
+++ b/cmd/x86/hob.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi.h>
+#include <asm/hob.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *hob_type[] = {
+	"reserved",
+	"Hand-off",
+	"Mem Alloc",
+	"Res Desc",
+	"GUID Ext",
+	"FV",
+	"CPU",
+	"Mem Pool",
+	"reserved",
+	"FV2",
+	"Load PEIM",
+	"Capsule",
+};
+
+static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const struct hob_header *hdr;
+	uint type;
+	char *desc;
+	int i = 0;
+	efi_guid_t *guid;
+	char uuid[UUID_STR_LEN + 1];
+
+	hdr = gd->arch.hob_list;
+
+	printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
+
+	printf("#  | Address  | Type      | Len  | ");
+	printf("%36s\n", "GUID");
+	printf("---|----------|-----------|------|-");
+	printf("------------------------------------\n");
+	while (!end_of_hob(hdr)) {
+		printf("%02x | %08x | ", i, (unsigned int)hdr);
+		type = hdr->type;
+		if (type == HOB_TYPE_UNUSED)
+			desc = "*Unused*";
+		else if (type == HOB_TYPE_EOH)
+			desc = "*EOH*";
+		else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
+			desc = hob_type[type];
+		else
+			desc = "*Invalid*";
+		printf("%-9s | %04x | ", desc, hdr->len);
+
+		if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
+		    type == HOB_TYPE_GUID_EXT) {
+			guid = (efi_guid_t *)(hdr + 1);
+			uuid_bin_to_str(guid->b, uuid, UUID_STR_FORMAT_GUID);
+			printf("%s", uuid);
+		} else {
+			printf("%36s", "Not Available");
+		}
+		printf("\n");
+		hdr = get_next_hob(hdr);
+		i++;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(hob, 1, 1, do_hob,
+	   "Print Hand-Off Block (HOB) information",
+	   ""
+);
diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig
index 41f3aff..be0554b 100644
--- a/configs/apalis-tk1_defconfig
+++ b/configs/apalis-tk1_defconfig
@@ -8,7 +8,7 @@
 CONFIG_FIT=y
 CONFIG_OF_SYSTEM_SETUP=y
 CONFIG_BOOTDELAY=1
-CONFIG_BOOTCOMMAND="run emmcboot; setenv fdtfile ${soc}-apalis-${fdt_board}.dtb && run distro_bootcmd"
+CONFIG_BOOTCOMMAND="run emmcboot; setenv fdtfile ${soc}-${fdt-module}-${fdt_board}.dtb && run distro_bootcmd"
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_VERSION_VARIABLE=y
@@ -17,7 +17,6 @@
 CONFIG_SPL_TEXT_BASE=0x80108000
 CONFIG_SYS_PROMPT="Apalis TK1 # "
 # CONFIG_CMD_IMI is not set
-CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -34,8 +33,6 @@
 CONFIG_IP_DEFRAG=y
 CONFIG_TFTP_BLOCKSIZE=16352
 CONFIG_SPL_DM=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
 CONFIG_SYS_I2C_TEGRA=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_TEGRA124_MMC_DISABLE_EXT_LOOPBACK=y
@@ -56,7 +53,7 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Toradex"
 CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
-CONFIG_USB_GADGET_PRODUCT_NUM=0xffff
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig
index cf4d144..75b5a1d 100644
--- a/configs/apalis_t30_defconfig
+++ b/configs/apalis_t30_defconfig
@@ -14,7 +14,6 @@
 CONFIG_SPL_TEXT_BASE=0x80108000
 CONFIG_SYS_PROMPT="Apalis T30 # "
 # CONFIG_CMD_IMI is not set
-CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -31,8 +30,6 @@
 CONFIG_IP_DEFRAG=y
 CONFIG_TFTP_BLOCKSIZE=16352
 CONFIG_SPL_DM=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
 CONFIG_SYS_I2C_TEGRA=y
 CONFIG_E1000=y
 CONFIG_PCI=y
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig
index 170a1b0..73d13bb 100644
--- a/configs/colibri_t20_defconfig
+++ b/configs/colibri_t20_defconfig
@@ -13,7 +13,6 @@
 CONFIG_SPL_TEXT_BASE=0x00108000
 CONFIG_SYS_PROMPT="Colibri T20 # "
 # CONFIG_CMD_IMI is not set
-CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -39,8 +38,6 @@
 CONFIG_IP_DEFRAG=y
 CONFIG_TFTP_BLOCKSIZE=1536
 CONFIG_SPL_DM=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
 CONFIG_SYS_I2C_TEGRA=y
 CONFIG_MTD=y
 CONFIG_MTD_UBI_FASTMAP=y
diff --git a/configs/colibri_t30_defconfig b/configs/colibri_t30_defconfig
index 769f6f3..1e2268a 100644
--- a/configs/colibri_t30_defconfig
+++ b/configs/colibri_t30_defconfig
@@ -14,7 +14,6 @@
 CONFIG_SPL_TEXT_BASE=0x80108000
 CONFIG_SYS_PROMPT="Colibri T30 # "
 # CONFIG_CMD_IMI is not set
-CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -30,8 +29,6 @@
 CONFIG_IP_DEFRAG=y
 CONFIG_TFTP_BLOCKSIZE=16352
 CONFIG_SPL_DM=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
 CONFIG_SYS_I2C_TEGRA=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
diff --git a/configs/edison_defconfig b/configs/edison_defconfig
index 4687544..cac6e42 100644
--- a/configs/edison_defconfig
+++ b/configs/edison_defconfig
@@ -4,6 +4,7 @@
 CONFIG_VENDOR_INTEL=y
 CONFIG_TARGET_EDISON=y
 CONFIG_SMP=y
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index fcc04f2..12be1de 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -1,5 +1,11 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_TPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800
 CONFIG_SYS_TEXT_BASE=0x00200000
 CONFIG_ROCKCHIP_RK3328=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
@@ -9,31 +15,50 @@
 CONFIG_DEBUG_UART=y
 # CONFIG_ANDROID_BOOT_IMAGE is not set
 CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-evb.dtb"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_ATF_SUPPORT=y
+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_TPL_BOOTROM_SUPPORT=y
+CONFIG_TPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_TPL_SERIAL_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_TPL_SERIAL_PRESENT=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x40000
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_DEFAULT_DEVICE_TREE="rk3328-evb"
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TIME=y
-CONFIG_DEFAULT_DEVICE_TREE="rk3328-evb"
 CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_TPL_DM=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
+CONFIG_TPL_CLK=y
 CONFIG_FASTBOOT_BUF_ADDR=0x800800
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_ROCKCHIP_GPIO=y
+CONFIG_TPL_OF_PLATDATA=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
@@ -44,6 +69,7 @@
 CONFIG_GMAC_ROCKCHIP=y
 CONFIG_PHY=y
 CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
 CONFIG_REGULATOR_PWM=y
@@ -51,9 +77,14 @@
 CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_SYSRESET=y
+CONFIG_SPL_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
@@ -69,4 +100,6 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0x330a
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/khadas-edge-captain-rk3399_defconfig b/configs/khadas-edge-captain-rk3399_defconfig
new file mode 100644
index 0000000..11ec2da
--- /dev/null
+++ b/configs/khadas-edge-captain-rk3399_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-khadas-edge-captain.dtbi"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_TPL=y
+CONFIG_SYS_PROMPT="kedge# "
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-khadas-edge-captain"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/khadas-edge-rk3399_defconfig b/configs/khadas-edge-rk3399_defconfig
new file mode 100644
index 0000000..c31360a
--- /dev/null
+++ b/configs/khadas-edge-rk3399_defconfig
@@ -0,0 +1,59 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-khadas-edge.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_TPL=y
+CONFIG_SYS_PROMPT="kedge# "
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-khadas-edge"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/khadas-edge-v-rk3399_defconfig b/configs/khadas-edge-v-rk3399_defconfig
new file mode 100644
index 0000000..8c9e9fc
--- /dev/null
+++ b/configs/khadas-edge-v-rk3399_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_TEXT_BASE=0x00200000
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x50000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL_STACK_R_ADDR=0x80000
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-khadas-edge-v.dtbi"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_TPL=y
+CONFIG_SYS_PROMPT="kedge# "
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-khadas-edge-v"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 532611f..53d9c8c 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -12,6 +12,7 @@
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BUILD_ROM=y
 CONFIG_FIT=y
 CONFIG_SPL_LOAD_FIT=y
diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig
index ef85c52..ad56135 100644
--- a/configs/qemu-x86_defconfig
+++ b/configs/qemu-x86_defconfig
@@ -6,6 +6,7 @@
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BUILD_ROM=y
 CONFIG_FIT=y
 CONFIG_BOOTSTAGE=y
diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig
index ef453e7..6484845 100644
--- a/configs/rock64-rk3328_defconfig
+++ b/configs/rock64-rk3328_defconfig
@@ -34,15 +34,20 @@
 CONFIG_CMD_TIME=y
 CONFIG_DEFAULT_DEVICE_TREE="rk3328-rock64"
 CONFIG_SPL_OF_CONTROL=y
+CONFIG_TPL_OF_CONTROL=y
 CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_TPL_OF_PLATDATA=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_REGMAP=y
 CONFIG_SPL_REGMAP=y
+CONFIG_TPL_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_SPL_SYSCON=y
+CONFIG_TPL_SYSCON=y
 CONFIG_CLK=y
 CONFIG_SPL_CLK=y
+CONFIG_TPL_CLK=y
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
@@ -65,6 +70,7 @@
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
 CONFIG_DM_RESET=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
@@ -85,4 +91,12 @@
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
 CONFIG_ERRNO_STR=y
+CONFIG_TPL_DM=y
+CONFIG_TPL_LIBCOMMON_SUPPORT=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_TPL_BOOTROM_SUPPORT=y
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800
+CONFIG_TPL_SYS_MALLOC_SIMPLE=y
diff --git a/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig
new file mode 100644
index 0000000..b16ed71
--- /dev/null
+++ b/configs/slimbootloader_defconfig
@@ -0,0 +1,22 @@
+CONFIG_X86=y
+CONFIG_VENDOR_INTEL=y
+CONFIG_TARGET_SLIMBOOTLOADER=y
+CONFIG_DEFAULT_DEVICE_TREE="slimbootloader"
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_LAST_STAGE_INIT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_USB=y
+CONFIG_DOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTDELAY=10
+CONFIG_CONSOLE_SCROLL_LINES=5
+# CONFIG_PCI_PNP is not set
diff --git a/doc/README.rockchip b/doc/README.rockchip
index 8ccbb87..7d4dc1b 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -309,17 +309,11 @@
 =================================================
 
 For Rock64 rk3328 board the following three parts are required:
-TPL, SPL, and the u-boot image tree blob. While u-boot-spl.bin and
-u-boot.itb are to be compiled as usual, TPL is currently not
-implemented in u-boot, so you need to pick one from rkbin:
-
-  - Get the rkbin
-
-    => git clone https://github.com/rockchip-linux/rkbin.git
+TPL, SPL, and the u-boot image tree blob.
 
   - Create TPL/SPL image
 
-    => tools/mkimage -n rk3328 -T rksd -d rkbin/bin/rk33/rk3328_ddr_333MHz_v1.16.bin idbloader.img
+    => tools/mkimage -n rk3328 -T rksd -d tpl/u-boot-tpl.bin idbloader.img
     => cat spl/u-boot-spl.bin >> idbloader.img
 
   - Write TPL/SPL image at 64 sector
diff --git a/doc/board/emulation/qemu-x86.rst b/doc/board/emulation/qemu-x86.rst
index c2e704a..db842f2 100644
--- a/doc/board/emulation/qemu-x86.rst
+++ b/doc/board/emulation/qemu-x86.rst
@@ -54,6 +54,23 @@
 Multicore is also supported by QEMU via '-smp n' where n is the number of cores
 to instantiate. Note, the maximum supported CPU number in QEMU is 255.
 
+U-Boot uses 'distro_bootcmd' by default when booting on x86 QEMU. This tries to
+load a boot script, kernel, and ramdisk from several different interfaces. For
+the default boot order, see 'qemu-x86.h'. For more information, see
+'README.distro'. Most Linux distros can be booted by writing a uboot script.
+For example, Debian (stretch) can be booted by creating a script file named
+'boot.txt' with the contents::
+
+   setenv bootargs root=/dev/sda1 ro
+   load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} /vmlinuz
+   load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} /initrd.img
+   zboot ${kernel_addr_r} - ${ramdisk_addr_r} ${filesize}
+
+Then compile and install it with::
+
+   $ apt install u-boot-tools && \
+     mkimage -T script -C none -n "Boot script" -d boot.txt /boot/boot.scr
+
 The fw_cfg interface in QEMU also provides information about kernel data,
 initrd, command-line arguments and more. U-Boot supports directly accessing
 these informtion from fw_cfg interface, which saves the time of loading them
diff --git a/doc/board/intel/index.rst b/doc/board/intel/index.rst
index f416801..f545dee 100644
--- a/doc/board/intel/index.rst
+++ b/doc/board/intel/index.rst
@@ -13,3 +13,4 @@
    edison
    galileo
    minnowmax
+   slimbootloader
diff --git a/doc/board/intel/slimbootloader.rst b/doc/board/intel/slimbootloader.rst
new file mode 100644
index 0000000..4a46fed
--- /dev/null
+++ b/doc/board/intel/slimbootloader.rst
@@ -0,0 +1,174 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Aiden Park <aiden.park@intel.com>
+
+Slim Bootloader
+===============
+
+Introduction
+------------
+
+This target is to enable U-Boot_ as a payload of `Slim Bootloader`_ (a.k.a SBL)
+boot firmware which currently supports QEMU, Apollolake, Whiskeylake,
+Coffeelake-R platforms.
+
+The `Slim Bootloader`_ is designed with multi-stages (Stage1A/B, Stage2, Payload)
+architecture to cover from reset vector to OS booting and it consumes
+`Intel FSP`_ for silicon initialization.
+
+* Stage1A: Reset vector, CAR init with FSP-T
+* Stage1B: Memory init with FSP-M, CAR teardown, Continue execution in memory
+* Stage2 : Rest of Silicon init with FSP-S, Create HOB, Hand-off to Payload
+* Payload: Payload init with HOB, Load OS from media, Booting OS
+
+The Slim Bootloader stages (Stage1A/B, Stage2) focus on chipset, hardware and
+platform specific initialization, and it provides useful information to a
+payload in a HOB (Hand-Off Block) which has serial port, memory map, performance
+data info and so on. This is Slim Bootloader architectural design to make a
+payload light-weight, platform independent and more generic across different
+boot solutions or payloads, and to minimize hardware re-initialization in a
+payload.
+
+Build Instruction for U-Boot as a Slim Bootloader payload
+---------------------------------------------------------
+
+Build U-Boot and obtain u-boot-dtb.bin::
+
+   $ make distclean
+   $ make slimbootloader_defconfig
+   $ make all
+
+Prepare Slim Bootloader
+-----------------------
+
+1. Setup Build Environment for Slim Bootloader.
+
+   Refer to `Getting Started`_ page in `Slim Bootloader`_ document site.
+
+2. Get source code. Let's simply clone the repo::
+
+   $ git clone https://github.com/slimbootloader/slimbootloader.git
+
+3. Copy u-boot-dtb.bin to Slim Bootloader.
+   Slim Bootloader looks for a payload from the specific location.
+   Copy the build u-boot-dtb.bin to the expected location::
+
+   $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/
+   $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin
+
+Build Instruction for Slim Bootloader for QEMU target
+-----------------------------------------------------
+
+Slim Bootloader supports multiple payloads, and a board of Slim Bootloader
+detects its target payload by PayloadId in board configuration.
+The PayloadId can be any 4 Bytes value.
+
+1. Update PayloadId. Let's use 'U-BT' as an example::
+
+    $ vi Platform/QemuBoardPkg/CfgData/CfgDataExt_Brd1.dlt
+    -GEN_CFG_DATA.PayloadId                     | 'AUTO'
+    +GEN_CFG_DATA.PayloadId                     | 'U-BT'
+
+2. Update payload text base. PAYLOAD_EXE_BASE must be the same as U-Boot
+   CONFIG_SYS_TEXT_BASE in board/intel/slimbootloader/Kconfig.
+   PAYLOAD_LOAD_HIGH must be 0::
+
+    $ vi Platform/QemuBoardPkg/BoardConfig.py
+    +               self.PAYLOAD_LOAD_HIGH    = 0
+    +               self.PAYLOAD_EXE_BASE     = 0x00100000
+
+3. Build QEMU target. Make sure u-boot-dtb.bin and U-BT PayloadId
+   in build command. The output is Outputs/qemu/SlimBootloader.bin::
+
+   $ python BuildLoader.py build qemu -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma"
+
+4. Launch Slim Bootloader on QEMU.
+   You should reach at U-Boot serial console::
+
+   $ qemu-system-x86_64 -machine q35 -nographic -serial mon:stdio -pflash Outputs/qemu/SlimBootloader.bin
+
+Build Instruction for Slim Bootloader for LeafHill (APL) target
+--------------------------------------------------------------
+
+LeafHill is using PCI UART2 device as a serial port.
+For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot.
+
+1. Enable CONFIG_SYS_NS16550_MEM32 in U-Boot::
+
+    $ vi include/configs/slimbootloader.h
+    +#define CONFIG_SYS_NS16550_MEM32
+     #ifdef CONFIG_SYS_NS16550_MEM3
+
+2. Build U-Boot::
+
+   $ make disclean
+   $ make slimbootloader_defconfig
+   $ make all
+
+3. Copy u-boot-dtb.bin to Slim Bootloader.
+   Slim Bootloader looks for a payload from the specific location.
+   Copy the build u-boot-dtb.bin to the expected location::
+
+   $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/
+   $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin
+
+4. Update PayloadId. Let's use 'U-BT' as an example::
+
+    $ vi Platform/ApollolakeBoardPkg/CfgData/CfgData_Int_LeafHill.dlt
+    -GEN_CFG_DATA.PayloadId                     | 'AUTO
+    +GEN_CFG_DATA.PayloadId                     | 'U-BT'
+
+5. Update payload text base.
+
+* PAYLOAD_EXE_BASE must be the same as U-Boot CONFIG_SYS_TEXT_BASE
+  in board/intel/slimbootloader/Kconfig.
+* PAYLOAD_LOAD_HIGH must be 0::
+
+    $ vi Platform/ApollolakeBoardPkg/BoardConfig.py
+    +               self.PAYLOAD_LOAD_HIGH    = 0
+    +               self.PAYLOAD_EXE_BASE     = 0x00100000
+
+6. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId
+   in build command. The output is Outputs/apl/Stitch_Components.zip::
+
+   $ python BuildLoader.py build apl -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma"
+
+7. Stitch IFWI.
+
+   Refer to Apollolake_ page in Slim Bootloader document site::
+
+   $ python Platform/ApollolakeBoardPkg/Script/StitchLoader.py -i <Existing IFWI> -s Outputs/apl/Stitch_Components.zip -o <Output IFWI>
+
+8. Flash IFWI.
+
+   Use DediProg to flash IFWI. You should reach at U-Boot serial console.
+
+
+Build Instruction to use ELF U-Boot
+-----------------------------------
+
+1. Enable CONFIG_OF_EMBED::
+
+    $ vi configs/slimbootloader_defconfig
+    +CONFIG_OF_EMBED=y
+
+2. Build U-Boot::
+
+   $ make disclean
+   $ make slimbootloader_defconfig
+   $ make all
+   $ strip u-boot (removing symbol for reduced size)
+
+3. Do same steps as above
+
+* Copy u-boot (ELF) to PayloadBins directory
+* Update PayloadId 'U-BT' as above.
+* No need to set PAYLOAD_LOAD_HIGH and PAYLOAD_EXE_BASE.
+* Build Slim Bootloader. Use u-boot instead of u-boot-dtb.bin::
+
+   $ python BuildLoader.py build <qemu or apl> -p "OsLoader.efi:LLDR:Lz4;u-boot:U-BT:Lzma"
+
+.. _U-Boot: https://gitlab.denx.de/
+.. _`Slim Bootloader`: https://github.com/slimbootloader/
+.. _`Intel FSP`: https://github.com/IntelFsp/
+.. _`Getting Started`: https://slimbootloader.github.io/getting-started/
+.. _Apollolake: https://slimbootloader.github.io/supported-hardware/apollo-lake-crb.html#stitching
diff --git a/doc/device-tree-bindings/sound/intel-hda.txt b/doc/device-tree-bindings/sound/intel-hda.txt
index fb2ce55..aa96be0 100644
--- a/doc/device-tree-bindings/sound/intel-hda.txt
+++ b/doc/device-tree-bindings/sound/intel-hda.txt
@@ -12,6 +12,7 @@
 
 Optional properties
 - intel,beep-nid: Node ID to use for beep (will be detected if not provided)
+- codec-enable-gpio : The GPIO used to enable the audio codec
 
 Required subnodes:
 - codecs: Contains a list of codec nodes
diff --git a/doc/device-tree-bindings/sound/nvidia,tegra-audio-max98090.txt b/doc/device-tree-bindings/sound/nvidia,tegra-audio-max98090.txt
new file mode 100644
index 0000000..25c63ea
--- /dev/null
+++ b/doc/device-tree-bindings/sound/nvidia,tegra-audio-max98090.txt
@@ -0,0 +1,54 @@
+NVIDIA Tegra audio complex, with MAX98090 CODEC
+
+Required properties:
+- compatible : "nvidia,tegra-audio-max98090"
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the MAX98090's pins (as documented in its binding), and the jacks
+  on the board:
+
+  * Headphones
+  * Speakers
+  * Mic Jack
+  * Int Mic
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
+  connected to the CODEC.
+- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
+
+Optional properties:
+- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
+- nvidia,mic-det-gpios : The GPIO that detect microphones are plugged in
+- codec-enable-gpio : The GPIO used to enable the audio codec
+
+Example:
+
+sound {
+	compatible = "nvidia,tegra-audio-max98090-venice2",
+		     "nvidia,tegra-audio-max98090";
+	nvidia,model = "NVIDIA Tegra Venice2";
+
+	nvidia,audio-routing =
+		"Headphones", "HPR",
+		"Headphones", "HPL",
+		"Speakers", "SPKR",
+		"Speakers", "SPKL",
+		"Mic Jack", "MICBIAS",
+		"IN34", "Mic Jack";
+
+	nvidia,i2s-controller = <&tegra_i2s1>;
+	nvidia,audio-codec = <&acodec>;
+
+	clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+		 <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+		 <&tegra_car TEGRA124_CLK_EXTERN1>;
+	clock-names = "pll_a", "pll_a_out0", "mclk";
+};
diff --git a/doc/device-tree-bindings/sound/snow.txt b/doc/device-tree-bindings/sound/snow.txt
new file mode 100644
index 0000000..fa06956
--- /dev/null
+++ b/doc/device-tree-bindings/sound/snow.txt
@@ -0,0 +1,32 @@
+Audio Binding for Snow boards
+
+Required properties:
+- compatible : Can be one of the following,
+			"google,snow-audio-max98090" or
+			"google,snow-audio-max98091" or
+			"google,snow-audio-max98095"
+- samsung,i2s-controller (deprecated): The phandle of the Samsung I2S controller
+- samsung,audio-codec (deprecated): The phandle of the audio codec
+
+Required sub-nodes:
+
+ - 'cpu' subnode with a 'sound-dai' property containing the phandle of the I2S
+    controller
+ - 'codec' subnode with a 'sound-dai' property containing list of phandles
+    to the CODEC nodes, first entry must be the phandle of the MAX98090,
+    MAX98091 or MAX98095 CODEC (exact device type is indicated by the compatible
+    string) and the second entry must be the phandle of the HDMI IP block node
+
+Optional:
+- samsung,model: The name of the sound-card
+- codec-enable-gpio : The GPIO used to enable the audio codec
+
+Example:
+
+sound {
+		compatible = "google,snow-audio-max98095";
+
+		samsung,model = "Snow-I2S-MAX98095";
+		samsung,i2s-controller = <&i2s0>;
+		samsung,audio-codec = <&max98095>;
+};
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
index 4f362d1..fb806b5 100644
--- a/drivers/bios_emulator/atibios.c
+++ b/drivers/bios_emulator/atibios.c
@@ -136,7 +136,6 @@
 		bool linear_ok;
 		int attr;
 
-		break;
 		debug("Mode %x: ", mode);
 		memset(buffer, '\0', sizeof(struct vbe_mode_info));
 		regs->e.eax = VESA_GET_MODE_INFO;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4cdae41..c6812f6 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -156,6 +156,7 @@
 
 config SPL_MMC_HS400_SUPPORT
 	bool "enable HS400 support in SPL"
+	select SPL_MMC_HS200_SUPPORT
 	help
 	  The HS400 mode is support by some eMMC. The bus frequency is up to
 	  200MHz. This mode requires tuning the IO.
@@ -591,6 +592,17 @@
 
 	  If unsure, say N.
 
+config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
+	bool "Disable external clock loopback"
+	depends on MMC_SDHCI_TEGRA && TEGRA124
+	help
+	  Disable the external clock loopback and use the internal one on SDMMC3
+	  as per the SDMMC_VENDOR_MISC_CNTRL_0 register's SDMMC_SPARE1 bits
+	  being set to 0xfffd according to the TRM.
+
+	  TODO(marcel.ziswiler@toradex.com): Move to device tree controlled
+	  approach once proper kernel integration made it mainline.
+
 config MMC_SDHCI_ZYNQ
 	bool "Arasan SDHCI controller support"
 	depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL
@@ -670,17 +682,6 @@
 
 endif
 
-config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
-	bool "Disable external clock loopback"
-	depends on MMC_SDHCI_TEGRA && TEGRA124
-	help
-	  Disable the external clock loopback and use the internal one on SDMMC3
-	  as per the SDMMC_VENDOR_MISC_CNTRL_0 register's SDMMC_SPARE1 bits
-	  being set to 0xfffd according to the TRM.
-
-	  TODO(marcel.ziswiler@toradex.com): Move to device tree controlled
-	  approach once proper kernel integration made it mainline.
-
 config FSL_ESDHC
 	bool "Freescale/NXP eSDHC controller support"
 	help
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 4be47ba..d930ed8 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -88,13 +88,13 @@
 		return -EINVAL;
 
 	host->max_clk = max_clk;
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, ATMEL_SDHC_MIN_FREQ);
 	if (ret)
 		return ret;
 
-	host->mmc = &plat->mmc;
-	host->mmc->dev = dev;
 	host->mmc->priv = host;
 	upriv->mmc = host->mmc;
 
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index 08bddd4..bf3304c 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -214,6 +214,9 @@
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	host->ops = &bcm2835_ops;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+
 	ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ);
 	if (ret) {
 		debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret);
@@ -221,7 +224,6 @@
 	}
 
 	upriv->mmc = &plat->mmc;
-	host->mmc = &plat->mmc;
 	host->mmc->priv = host;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
index eef46f3..c14f828 100644
--- a/drivers/mmc/bcmstb_sdhci.c
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -73,6 +73,8 @@
 	if (ret)
 		return ret;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host,
 			      BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY,
 			      BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY);
@@ -80,7 +82,6 @@
 		return ret;
 
 	upriv->mmc = &plat->mmc;
-	host->mmc = &plat->mmc;
 	host->mmc->priv = host;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 1992d61..22f6c7e 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -13,6 +13,7 @@
 #include <mmc.h>
 #include <dwmmc.h>
 #include <wait_bit.h>
+#include <power/regulator.h>
 
 #define PAGE_SIZE 4096
 
@@ -493,6 +494,21 @@
 	if (host->clksel)
 		host->clksel(host);
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	if (mmc->vqmmc_supply) {
+		int ret;
+
+		if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+			regulator_set_value(mmc->vqmmc_supply, 1800000);
+		else
+			regulator_set_value(mmc->vqmmc_supply, 3300000);
+
+		ret = regulator_set_enable_if_allowed(mmc->vqmmc_supply, true);
+		if (ret)
+			return ret;
+	}
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 51f9e0e..cae42ec 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -141,12 +141,12 @@
 		writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
 	}
 
-	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
 	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
 	if (ret)
 		return ret;
 	host->mmc->priv = &prv->host;
-	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index 182d416..404264a 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -33,12 +33,12 @@
 	host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
 					      PCI_REGION_MEM);
 	host->name = dev->name;
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
 	if (ret)
 		return ret;
-	host->mmc = &plat->mmc;
 	host->mmc->priv = &priv->host;
-	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 9dd0b86..53efa96 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -204,13 +204,13 @@
 	if (ret)
 		return ret;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 400000);
 	if (ret)
 		return ret;
 
-	host->mmc = &plat->mmc;
 	host->mmc->priv = host;
-	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c
index 4f9338f..4736263 100644
--- a/drivers/mmc/sdhci-cadence.c
+++ b/drivers/mmc/sdhci-cadence.c
@@ -269,12 +269,13 @@
 	if (ret)
 		return ret;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
 	if (ret)
 		return ret;
 
 	upriv->mmc = &plat->mmc;
-	host->mmc = &plat->mmc;
 	host->mmc->priv = host;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/tangier_sdhci.c b/drivers/mmc/tangier_sdhci.c
index 4c33356..0d6e5d6 100644
--- a/drivers/mmc/tangier_sdhci.c
+++ b/drivers/mmc/tangier_sdhci.c
@@ -51,13 +51,14 @@
 	/* MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 */
 	host->voltages = MMC_VDD_165_195;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
 	ret = sdhci_setup_cfg(&plat->cfg, host, SDHCI_TANGIER_FMAX,
 			SDHCI_TANGIER_FMIN);
 	if (ret)
 		return ret;
 
 	upriv->mmc = &plat->mmc;
-	host->mmc = &plat->mmc;
 	host->mmc->priv = host;
 
 	return sdhci_probe(dev);
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index c525084..3225a7a 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -242,13 +242,14 @@
 
 	host->max_clk = clock;
 
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+	host->mmc->priv = host;
+
 	ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
 			      CONFIG_ZYNQ_SDHCI_MIN_FREQ);
-	host->mmc = &plat->mmc;
 	if (ret)
 		return ret;
-	host->mmc->priv = host;
-	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
 	return sdhci_probe(dev);
diff --git a/drivers/ram/rockchip/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c
index f4e0b18..656696a 100644
--- a/drivers/ram/rockchip/sdram_rk3328.c
+++ b/drivers/ram/rockchip/sdram_rk3328.c
@@ -2,22 +2,1029 @@
 /*
  * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
  */
-
 #include <common.h>
+#include <clk.h>
+#include <debug_uart.h>
 #include <dm.h>
+#include <dt-structs.h>
 #include <ram.h>
+#include <regmap.h>
 #include <syscon.h>
+#include <asm/io.h>
 #include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rk3328.h>
 #include <asm/arch-rockchip/grf_rk3328.h>
 #include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rk3328.h>
+#include <asm/arch-rockchip/uart.h>
 
 struct dram_info {
+#ifdef CONFIG_TPL_BUILD
+	struct rk3328_ddr_pctl_regs *pctl;
+	struct rk3328_ddr_phy_regs *phy;
+	struct clk ddr_clk;
+	struct rk3328_cru *cru;
+	struct rk3328_msch_regs *msch;
+	struct rk3328_ddr_grf_regs *ddr_grf;
+#endif
 	struct ram_info info;
 	struct rk3328_grf_regs *grf;
 };
 
+#ifdef CONFIG_TPL_BUILD
+
+struct rk3328_sdram_channel sdram_ch;
+
+struct rockchip_dmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3328_dmc dtplat;
+#else
+	struct rk3328_sdram_params sdram_params;
+#endif
+	struct regmap *map;
+};
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3328_dmc *dtplat = &plat->dtplat;
+	int ret;
+
+	ret = regmap_init_mem_platdata(dev, dtplat->reg,
+				       ARRAY_SIZE(dtplat->reg) / 2,
+				       &plat->map);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static void rkclk_ddr_reset(struct dram_info *dram,
+			    u32 ctl_srstn, u32 ctl_psrstn,
+			    u32 phy_srstn, u32 phy_psrstn)
+{
+	writel(ddrctrl_srstn_req(ctl_srstn) | ddrctrl_psrstn_req(ctl_psrstn) |
+		ddrphy_srstn_req(phy_srstn) | ddrphy_psrstn_req(phy_psrstn),
+		&dram->cru->softrst_con[5]);
+	writel(ddrctrl_asrstn_req(ctl_srstn), &dram->cru->softrst_con[9]);
+}
+
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int mhz)
+{
+	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
+	int delay = 1000;
+
+	refdiv = 1;
+	if (mhz <= 300) {
+		postdiv1 = 4;
+		postdiv2 = 2;
+	} else if (mhz <= 400) {
+		postdiv1 = 6;
+		postdiv2 = 1;
+	} else if (mhz <= 600) {
+		postdiv1 = 4;
+		postdiv2 = 1;
+	} else if (mhz <= 800) {
+		postdiv1 = 3;
+		postdiv2 = 1;
+	} else if (mhz <= 1600) {
+		postdiv1 = 2;
+		postdiv2 = 1;
+	} else {
+		postdiv1 = 1;
+		postdiv2 = 1;
+	}
+	fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
+
+	writel(((0x1 << 4) << 16) | (0 << 4), &dram->cru->mode_con);
+	writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->dpll_con[0]);
+	writel(DSMPD(1) | POSTDIV2(postdiv2) | REFDIV(refdiv),
+	       &dram->cru->dpll_con[1]);
+
+	while (delay > 0) {
+		udelay(1);
+		if (LOCK(readl(&dram->cru->dpll_con[1])))
+			break;
+		delay--;
+	}
+
+	writel(((0x1 << 4) << 16) | (1 << 4), &dram->cru->mode_con);
+}
+
+static void rkclk_configure_ddr(struct dram_info *dram,
+				struct rk3328_sdram_params *sdram_params)
+{
+	void __iomem *phy_base = dram->phy;
+
+	/* choose DPLL for ddr clk source */
+	clrbits_le32(PHY_REG(phy_base, 0xef), 1 << 7);
+
+	/* for inno ddr phy need 2*freq */
+	rkclk_set_dpll(dram,  sdram_params->ddr_freq * 2);
+}
+
+static void phy_soft_reset(struct dram_info *dram)
+{
+	void __iomem *phy_base = dram->phy;
+
+	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
+	udelay(1);
+	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
+	udelay(5);
+	setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
+	udelay(1);
+}
+
+static int pctl_cfg(struct dram_info *dram,
+		    struct rk3328_sdram_params *sdram_params)
+{
+	u32 i;
+	void __iomem *pctl_base = dram->pctl;
+
+	for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
+		writel(sdram_params->pctl_regs.pctl[i][1],
+		       pctl_base + sdram_params->pctl_regs.pctl[i][0]);
+	}
+	clrsetbits_le32(pctl_base + DDR_PCTL2_PWRTMG,
+			(0xff << 16) | 0x1f,
+			((SR_IDLE & 0xff) << 16) | (PD_IDLE & 0x1f));
+	/*
+	 * dfi_lp_en_pd=1,dfi_lp_wakeup_pd=2
+	 * hw_lp_idle_x32=1
+	 */
+	if (sdram_params->dramtype == LPDDR3) {
+		setbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0, 1);
+		clrsetbits_le32(pctl_base + DDR_PCTL2_DFILPCFG0,
+				0xf << 4,
+				2 << 4);
+	}
+	clrsetbits_le32(pctl_base + DDR_PCTL2_HWLPCTL,
+			0xfff << 16,
+			1 << 16);
+	/* disable zqcs */
+	setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1u << 31);
+	setbits_le32(pctl_base + 0x2000 + DDR_PCTL2_ZQCTL0, 1u << 31);
+
+	return 0;
+}
+
+/* return ddrconfig value
+ *       (-1), find ddrconfig fail
+ *       other, the ddrconfig value
+ * only support cs0_row >= cs1_row
+ */
+static unsigned int calculate_ddrconfig(struct rk3328_sdram_params *sdram_params)
+{
+	static const u16 ddr_cfg_2_rbc[] = {
+		/***************************
+		 * [5:4]  row(13+n)
+		 * [3]    cs(0:0 cs, 1:2 cs)
+		 * [2]  bank(0:0bank,1:8bank)
+		 * [1:0]    col(11+n)
+		 ****************************/
+		/* row,        cs,       bank,   col */
+		((3 << 4) | (0 << 3) | (1 << 2) | 0),
+		((3 << 4) | (0 << 3) | (1 << 2) | 1),
+		((2 << 4) | (0 << 3) | (1 << 2) | 2),
+		((3 << 4) | (0 << 3) | (1 << 2) | 2),
+		((2 << 4) | (0 << 3) | (1 << 2) | 3),
+		((3 << 4) | (1 << 3) | (1 << 2) | 0),
+		((3 << 4) | (1 << 3) | (1 << 2) | 1),
+		((2 << 4) | (1 << 3) | (1 << 2) | 2),
+		((3 << 4) | (0 << 3) | (0 << 2) | 1),
+		((2 << 4) | (0 << 3) | (1 << 2) | 1),
+	};
+
+	static const u16 ddr4_cfg_2_rbc[] = {
+		/***************************
+		 * [6]	cs 0:0cs 1:2 cs
+		 * [5:3]  row(13+n)
+		 * [2]  cs(0:0 cs, 1:2 cs)
+		 * [1]  bw    0: 16bit 1:32bit
+		 * [0]  diebw 0:8bit 1:16bit
+		 ***************************/
+		/*  cs,       row,        cs,       bw,   diebw */
+		((0 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 0),
+		((1 << 6) | (2 << 3) | (0 << 2) | (1 << 1) | 0),
+		((0 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 0),
+		((1 << 6) | (3 << 3) | (0 << 2) | (0 << 1) | 0),
+		((0 << 6) | (4 << 3) | (0 << 2) | (1 << 1) | 1),
+		((1 << 6) | (3 << 3) | (0 << 2) | (1 << 1) | 1),
+		((1 << 6) | (4 << 3) | (0 << 2) | (0 << 1) | 1),
+		((0 << 6) | (2 << 3) | (1 << 2) | (1 << 1) | 0),
+		((0 << 6) | (3 << 3) | (1 << 2) | (0 << 1) | 0),
+		((0 << 6) | (3 << 3) | (1 << 2) | (1 << 1) | 1),
+		((0 << 6) | (4 << 3) | (1 << 2) | (0 << 1) | 1),
+	};
+
+	u32 cs, bw, die_bw, col, row, bank;
+	u32 i, tmp;
+	u32 ddrconf = -1;
+
+	cs = sdram_ch.rank;
+	bw = sdram_ch.bw;
+	die_bw = sdram_ch.dbw;
+	col = sdram_ch.col;
+	row = sdram_ch.cs0_row;
+	bank = sdram_ch.bk;
+
+	if (sdram_params->dramtype == DDR4) {
+		tmp = ((cs - 1) << 6) | ((row - 13) << 3) | (bw & 0x2) | die_bw;
+		for (i = 10; i < 17; i++) {
+			if (((tmp & 0x7) == (ddr4_cfg_2_rbc[i - 10] & 0x7)) &&
+			    ((tmp & 0x3c) <= (ddr4_cfg_2_rbc[i - 10] & 0x3c)) &&
+			    ((tmp & 0x40) <= (ddr4_cfg_2_rbc[i - 10] & 0x40))) {
+				ddrconf = i;
+				goto out;
+			}
+		}
+	} else {
+		if (bank == 2) {
+			ddrconf = 8;
+			goto out;
+		}
+
+		tmp = ((row - 13) << 4) | (1 << 2) | ((bw + col - 11) << 0);
+		for (i = 0; i < 5; i++)
+			if (((tmp & 0xf) == (ddr_cfg_2_rbc[i] & 0xf)) &&
+			    ((tmp & 0x30) <= (ddr_cfg_2_rbc[i] & 0x30))) {
+				ddrconf = i;
+				goto out;
+			}
+	}
+
+out:
+	if (ddrconf > 20)
+		printf("calculate_ddrconfig error\n");
+
+	return ddrconf;
+}
+
+/* n: Unit bytes */
+static void copy_to_reg(u32 *dest, u32 *src, u32 n)
+{
+	int i;
+
+	for (i = 0; i < n / sizeof(u32); i++) {
+		writel(*src, dest);
+		src++;
+		dest++;
+	}
+}
+
+/*******
+ * calculate controller dram address map, and setting to register.
+ * argument sdram_ch.ddrconf must be right value before
+ * call this function.
+ *******/
+static void set_ctl_address_map(struct dram_info *dram,
+				struct rk3328_sdram_params *sdram_params)
+{
+	void __iomem *pctl_base = dram->pctl;
+
+	copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
+		    &addrmap[sdram_ch.ddrconfig][0], 9 * 4);
+	if (sdram_params->dramtype == LPDDR3 && sdram_ch.row_3_4)
+		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
+	if (sdram_params->dramtype == DDR4 && sdram_ch.bw == 0x1)
+		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
+
+	if (sdram_ch.rank == 1)
+		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
+}
+
+static void phy_dll_bypass_set(struct dram_info *dram, u32 freq)
+{
+	u32 tmp;
+	void __iomem *phy_base = dram->phy;
+
+	setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
+	setbits_le32(PHY_REG(phy_base, 0x26), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x27), 1 << 3);
+	setbits_le32(PHY_REG(phy_base, 0x36), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x37), 1 << 3);
+	setbits_le32(PHY_REG(phy_base, 0x46), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x47), 1 << 3);
+	setbits_le32(PHY_REG(phy_base, 0x56), 1 << 4);
+	clrbits_le32(PHY_REG(phy_base, 0x57), 1 << 3);
+
+	if (freq <= (400 * MHz))
+		/* DLL bypass */
+		setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+	else
+		clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
+	if (freq <= (680 * MHz))
+		tmp = 2;
+	else
+		tmp = 1;
+	writel(tmp, PHY_REG(phy_base, 0x28));
+	writel(tmp, PHY_REG(phy_base, 0x38));
+	writel(tmp, PHY_REG(phy_base, 0x48));
+	writel(tmp, PHY_REG(phy_base, 0x58));
+}
+
+static void set_ds_odt(struct dram_info *dram,
+		       struct rk3328_sdram_params *sdram_params)
+{
+	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
+	void __iomem *phy_base = dram->phy;
+
+	if (sdram_params->dramtype == DDR3) {
+		cmd_drv = PHY_DDR3_RON_RTT_34ohm;
+		clk_drv = PHY_DDR3_RON_RTT_45ohm;
+		dqs_drv = PHY_DDR3_RON_RTT_34ohm;
+		dqs_odt = PHY_DDR3_RON_RTT_225ohm;
+	} else {
+		cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+		clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
+		dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
+		dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
+	}
+	/* DS */
+	writel(cmd_drv, PHY_REG(phy_base, 0x11));
+	clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
+	writel(clk_drv, PHY_REG(phy_base, 0x16));
+	writel(clk_drv, PHY_REG(phy_base, 0x18));
+	writel(dqs_drv, PHY_REG(phy_base, 0x20));
+	writel(dqs_drv, PHY_REG(phy_base, 0x2f));
+	writel(dqs_drv, PHY_REG(phy_base, 0x30));
+	writel(dqs_drv, PHY_REG(phy_base, 0x3f));
+	writel(dqs_drv, PHY_REG(phy_base, 0x40));
+	writel(dqs_drv, PHY_REG(phy_base, 0x4f));
+	writel(dqs_drv, PHY_REG(phy_base, 0x50));
+	writel(dqs_drv, PHY_REG(phy_base, 0x5f));
+	/* ODT */
+	writel(dqs_odt, PHY_REG(phy_base, 0x21));
+	writel(dqs_odt, PHY_REG(phy_base, 0x2e));
+	writel(dqs_odt, PHY_REG(phy_base, 0x31));
+	writel(dqs_odt, PHY_REG(phy_base, 0x3e));
+	writel(dqs_odt, PHY_REG(phy_base, 0x41));
+	writel(dqs_odt, PHY_REG(phy_base, 0x4e));
+	writel(dqs_odt, PHY_REG(phy_base, 0x51));
+	writel(dqs_odt, PHY_REG(phy_base, 0x5e));
+}
+
+static void phy_cfg(struct dram_info *dram,
+		    struct rk3328_sdram_params *sdram_params)
+{
+	u32 i;
+	void __iomem *phy_base = dram->phy;
+
+	phy_dll_bypass_set(dram, sdram_params->ddr_freq);
+	for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
+		writel(sdram_params->phy_regs.phy[i][1],
+		       phy_base + sdram_params->phy_regs.phy[i][0]);
+	}
+	if (sdram_ch.bw == 2) {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
+	} else {
+		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
+		/* disable DQS2,DQS3 tx dll  for saving power */
+		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
+		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
+	}
+	set_ds_odt(dram, sdram_params);
+	/* deskew */
+	setbits_le32(PHY_REG(phy_base, 2), 8);
+	copy_to_reg(PHY_REG(phy_base, 0xb0),
+		    &sdram_params->skew.a0_a1_skew[0], 15 * 4);
+	copy_to_reg(PHY_REG(phy_base, 0x70),
+		    &sdram_params->skew.cs0_dm0_skew[0], 44 * 4);
+	copy_to_reg(PHY_REG(phy_base, 0xc0),
+		    &sdram_params->skew.cs0_dm1_skew[0], 44 * 4);
+}
+
+static int update_refresh_reg(struct dram_info *dram)
+{
+	void __iomem *pctl_base = dram->pctl;
+	u32 ret;
+
+	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
+	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
+
+	return 0;
+}
+
+static int data_training(struct dram_info *dram, u32 cs, u32 dramtype)
+{
+	u32 ret;
+	u32 dis_auto_zq = 0;
+	void __iomem *pctl_base = dram->pctl;
+	void __iomem *phy_base = dram->phy;
+
+	/* disable zqcs */
+	if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
+		(1ul << 31))) {
+		dis_auto_zq = 1;
+		setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+	}
+	/* disable auto refresh */
+	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+	update_refresh_reg(dram);
+
+	if (dramtype == DDR4) {
+		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
+		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
+	}
+	/* choose training cs */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
+	/* enable gate training */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
+	udelay(50);
+	ret = readl(PHY_REG(phy_base, 0xff));
+	/* disable gate training */
+	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
+	/* restore zqcs */
+	if (dis_auto_zq)
+		clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+	/* restore auto refresh */
+	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+	update_refresh_reg(dram);
+
+	if (dramtype == DDR4) {
+		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
+		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
+	}
+
+	if (ret & 0x10) {
+		ret = -1;
+	} else {
+		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
+		ret = (ret == 0) ? 0 : -1;
+	}
+	return ret;
+}
+
+/* rank = 1: cs0
+ * rank = 2: cs1
+ * rank = 3: cs0 & cs1
+ * note: be careful of keep mr original val
+ */
+static int write_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 arg,
+		    u32 dramtype)
+{
+	void __iomem *pctl_base = dram->pctl;
+
+	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+		continue;
+	if (dramtype == DDR3 || dramtype == DDR4) {
+		writel((mr_num << 12) | (rank << 4) | (0 << 0),
+		       pctl_base + DDR_PCTL2_MRCTRL0);
+		writel(arg, pctl_base + DDR_PCTL2_MRCTRL1);
+	} else {
+		writel((rank << 4) | (0 << 0),
+		       pctl_base + DDR_PCTL2_MRCTRL0);
+		writel((mr_num << 8) | (arg & 0xff),
+		       pctl_base + DDR_PCTL2_MRCTRL1);
+	}
+
+	setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
+	while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
+		continue;
+	while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+		continue;
+
+	return 0;
+}
+
+/*
+ * rank : 1:cs0, 2:cs1, 3:cs0&cs1
+ * vrefrate: 4500: 45%,
+ */
+static int write_vrefdq(struct dram_info *dram, u32 rank, u32 vrefrate,
+			u32 dramtype)
+{
+	u32 tccd_l, value;
+	u32 dis_auto_zq = 0;
+	void __iomem *pctl_base = dram->pctl;
+
+	if (dramtype != DDR4 || vrefrate < 4500 || vrefrate > 9200)
+		return -1;
+
+	tccd_l = (readl(pctl_base + DDR_PCTL2_DRAMTMG4) >> 16) & 0xf;
+	tccd_l = (tccd_l - 4) << 10;
+
+	if (vrefrate > 7500) {
+		/* range 1 */
+		value = ((vrefrate - 6000) / 65) | tccd_l;
+	} else {
+		/* range 2 */
+		value = ((vrefrate - 4500) / 65) | tccd_l | (1 << 6);
+	}
+
+	/* disable zqcs */
+	if (!(readl(pctl_base + DDR_PCTL2_ZQCTL0) &
+		(1ul << 31))) {
+		dis_auto_zq = 1;
+		setbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+	}
+	/* disable auto refresh */
+	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+	update_refresh_reg(dram);
+
+	/* enable vrefdq calibratin */
+	write_mr(dram, rank, 6, value | (1 << 7), dramtype);
+	udelay(1);/* tvrefdqe */
+	/* write vrefdq value */
+	write_mr(dram, rank, 6, value | (1 << 7), dramtype);
+	udelay(1);/* tvref_time */
+	write_mr(dram, rank, 6, value | (0 << 7), dramtype);
+	udelay(1);/* tvrefdqx */
+
+	/* restore zqcs */
+	if (dis_auto_zq)
+		clrbits_le32(pctl_base + DDR_PCTL2_ZQCTL0, 1 << 31);
+	/* restore auto refresh */
+	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3, 1);
+	update_refresh_reg(dram);
+
+	return 0;
+}
+
+#define _MAX_(x, y) ((x) > (y) ? (x) : (y))
+
+static void rx_deskew_switch_adjust(struct dram_info *dram)
+{
+	u32 i, deskew_val;
+	u32 gate_val = 0;
+	void __iomem *phy_base = dram->phy;
+
+	for (i = 0; i < 4; i++)
+		gate_val = _MAX_(readl(PHY_REG(phy_base, 0xfb + i)), gate_val);
+
+	deskew_val = (gate_val >> 3) + 1;
+	deskew_val = (deskew_val > 0x1f) ? 0x1f : deskew_val;
+	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xc, (deskew_val & 0x3) << 2);
+	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x7 << 4,
+			(deskew_val & 0x1c) << 2);
+}
+
+#undef _MAX_
+
+static void tx_deskew_switch_adjust(struct dram_info *dram)
+{
+	void __iomem *phy_base = dram->phy;
+
+	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0x3, 1);
+}
+
+static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
+{
+	writel(ddrconfig, &dram->msch->ddrconf);
+}
+
+static void dram_all_config(struct dram_info *dram,
+			    struct rk3328_sdram_params *sdram_params)
+{
+	u32 sys_reg = 0, tmp = 0;
+
+	set_ddrconfig(dram, sdram_ch.ddrconfig);
+
+	sys_reg |= SYS_REG_ENC_DDRTYPE(sdram_params->dramtype);
+	sys_reg |= SYS_REG_ENC_ROW_3_4(sdram_ch.row_3_4, 0);
+	sys_reg |= SYS_REG_ENC_RANK(sdram_ch.rank, 0);
+	sys_reg |= SYS_REG_ENC_COL(sdram_ch.col, 0);
+	sys_reg |= SYS_REG_ENC_BK(sdram_ch.bk, 0);
+	SYS_REG_ENC_CS0_ROW(sdram_ch.cs0_row, sys_reg, tmp, 0);
+	if (sdram_ch.cs1_row)
+		SYS_REG_ENC_CS1_ROW(sdram_ch.cs1_row, sys_reg, tmp, 0);
+	sys_reg |= SYS_REG_ENC_BW(sdram_ch.bw, 0);
+	sys_reg |= SYS_REG_ENC_DBW(sdram_ch.dbw, 0);
+
+	writel(sys_reg, &dram->grf->os_reg[2]);
+
+	writel(sdram_ch.noc_timings.ddrtiming.d32, &dram->msch->ddrtiming);
+
+	writel(sdram_ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
+	writel(sdram_ch.noc_timings.readlatency, &dram->msch->readlatency);
+
+	writel(sdram_ch.noc_timings.activate.d32, &dram->msch->activate);
+	writel(sdram_ch.noc_timings.devtodev.d32, &dram->msch->devtodev);
+	writel(sdram_ch.noc_timings.ddr4timing.d32, &dram->msch->ddr4_timing);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging0);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging1);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging2);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging3);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging4);
+	writel(sdram_ch.noc_timings.agingx0, &dram->msch->aging5);
+}
+
+static void enable_low_power(struct dram_info *dram,
+			     struct rk3328_sdram_params *sdram_params)
+{
+	void __iomem *pctl_base = dram->pctl;
+
+	/* enable upctl2 axi clock auto gating */
+	writel(0x00800000, &dram->ddr_grf->ddr_grf_con[0]);
+	writel(0x20012001, &dram->ddr_grf->ddr_grf_con[2]);
+	/* enable upctl2 core clock auto gating */
+	writel(0x001e001a, &dram->ddr_grf->ddr_grf_con[2]);
+	/* enable sr, pd */
+	if (PD_IDLE == 0)
+		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+	else
+		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+	if (SR_IDLE == 0)
+		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL,	1);
+	else
+		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
+}
+
+static int sdram_init(struct dram_info *dram,
+		      struct rk3328_sdram_params *sdram_params, u32 pre_init)
+{
+	void __iomem *pctl_base = dram->pctl;
+
+	rkclk_ddr_reset(dram, 1, 1, 1, 1);
+	udelay(10);
+	/*
+	 * dereset ddr phy psrstn to config pll,
+	 * if using phy pll psrstn must be dereset
+	 * before config pll
+	 */
+	rkclk_ddr_reset(dram, 1, 1, 1, 0);
+	rkclk_configure_ddr(dram, sdram_params);
+	if (pre_init == 0) {
+		switch (sdram_params->dramtype) {
+		case DDR3:
+			printf("DDR3\n");
+			break;
+		case DDR4:
+			printf("DDR4\n");
+			break;
+		case LPDDR3:
+		default:
+			printf("LPDDR3\n");
+			break;
+		}
+	}
+	/* release phy srst to provide clk to ctrl */
+	rkclk_ddr_reset(dram, 1, 1, 0, 0);
+	udelay(10);
+	phy_soft_reset(dram);
+	/* release ctrl presetn, and config ctl registers */
+	rkclk_ddr_reset(dram, 1, 0, 0, 0);
+	pctl_cfg(dram, sdram_params);
+	sdram_ch.ddrconfig = calculate_ddrconfig(sdram_params);
+	set_ctl_address_map(dram, sdram_params);
+	phy_cfg(dram, sdram_params);
+
+	/* enable dfi_init_start to init phy after ctl srstn deassert */
+	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
+	rkclk_ddr_reset(dram, 0, 0, 0, 0);
+	/* wait for dfi_init_done and dram init complete */
+	while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
+		continue;
+
+	/* do ddr gate training */
+	if (data_training(dram, 0, sdram_params->dramtype) != 0) {
+		printf("data training error\n");
+		return -1;
+	}
+
+	if (sdram_params->dramtype == DDR4)
+		write_vrefdq(dram, 0x3, 5670, sdram_params->dramtype);
+
+	if (pre_init == 0) {
+		rx_deskew_switch_adjust(dram);
+		tx_deskew_switch_adjust(dram);
+	}
+
+	dram_all_config(dram, sdram_params);
+	enable_low_power(dram, sdram_params);
+
+	return 0;
+}
+
+static u64 dram_detect_cap(struct dram_info *dram,
+			   struct rk3328_sdram_params *sdram_params,
+			   unsigned char channel)
+{
+	void __iomem *pctl_base = dram->pctl;
+
+	/*
+	 * for ddr3: ddrconf = 3
+	 * for ddr4: ddrconf = 12
+	 * for lpddr3: ddrconf = 3
+	 * default bw = 1
+	 */
+	u32 bk, bktmp;
+	u32 col, coltmp;
+	u32 row, rowtmp, row_3_4;
+	void __iomem *test_addr, *test_addr1;
+	u32 dbw;
+	u32 cs;
+	u32 bw = 1;
+	u64 cap = 0;
+	u32 dram_type = sdram_params->dramtype;
+	u32 pwrctl;
+
+	if (dram_type != DDR4) {
+		/* detect col and bk for ddr3/lpddr3 */
+		coltmp = 12;
+		bktmp = 3;
+		rowtmp = 16;
+
+		for (col = coltmp; col >= 9; col -= 1) {
+			writel(0, SDRAM_ADDR);
+			test_addr = (void __iomem *)(SDRAM_ADDR +
+					(1ul << (col + bw - 1ul)));
+			writel(PATTERN, test_addr);
+			if ((readl(test_addr) == PATTERN) &&
+			    (readl(SDRAM_ADDR) == 0))
+				break;
+		}
+		if (col == 8) {
+			printf("col error\n");
+			goto cap_err;
+		}
+
+		test_addr = (void __iomem *)(SDRAM_ADDR +
+				(1ul << (coltmp + bktmp + bw - 1ul)));
+		writel(0, SDRAM_ADDR);
+		writel(PATTERN, test_addr);
+		if ((readl(test_addr) == PATTERN) &&
+		    (readl(SDRAM_ADDR) == 0))
+			bk = 3;
+		else
+			bk = 2;
+		if (dram_type == LPDDR3)
+			dbw = 2;
+		else
+			dbw = 1;
+	} else {
+		/* detect bg for ddr4 */
+		coltmp = 10;
+		bktmp = 4;
+		rowtmp = 17;
+
+		col = 10;
+		bk = 2;
+		test_addr = (void __iomem *)(SDRAM_ADDR +
+				(1ul << (coltmp + bw + 1ul)));
+		writel(0, SDRAM_ADDR);
+		writel(PATTERN, test_addr);
+		if ((readl(test_addr) == PATTERN) &&
+		    (readl(SDRAM_ADDR) == 0))
+			dbw = 0;
+		else
+			dbw = 1;
+	}
+	/* detect row */
+	for (row = rowtmp; row > 12; row--) {
+		writel(0, SDRAM_ADDR);
+		test_addr = (void __iomem *)(SDRAM_ADDR +
+				(1ul << (row + bktmp + coltmp + bw - 1ul)));
+		writel(PATTERN, test_addr);
+		if ((readl(test_addr) == PATTERN) &&
+		    (readl(SDRAM_ADDR) == 0))
+			break;
+	}
+	if (row == 12) {
+		printf("row error");
+		goto cap_err;
+	}
+	/* detect row_3_4 */
+	test_addr = SDRAM_ADDR;
+	test_addr1 = (void __iomem *)(SDRAM_ADDR +
+			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
+
+	writel(0, test_addr);
+	writel(PATTERN, test_addr1);
+	if ((readl(test_addr) == 0) &&
+	    (readl(test_addr1) == PATTERN))
+		row_3_4 = 0;
+	else
+		row_3_4 = 1;
+
+	/* disable auto low-power */
+	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+
+	/* bw and cs detect using phy read gate training */
+	if (data_training(dram, 1, dram_type) == 0)
+		cs = 1;
+	else
+		cs = 0;
+
+	bw = 2;
+
+	/* restore auto low-power */
+	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
+
+	sdram_ch.rank = cs + 1;
+	sdram_ch.col = col;
+	sdram_ch.bk = bk;
+	sdram_ch.dbw = dbw;
+	sdram_ch.bw = bw;
+	sdram_ch.cs0_row = row;
+	if (cs)
+		sdram_ch.cs1_row = row;
+	else
+		sdram_ch.cs1_row = 0;
+	sdram_ch.row_3_4 = row_3_4;
+
+	if (dram_type == DDR4)
+		cap = 1llu << (cs + row + bk + col + ((dbw == 0) ? 2 : 1) + bw);
+	else
+		cap = 1llu << (cs + row + bk + col + bw);
+
+	return cap;
+
+cap_err:
+	return 0;
+}
+
+static u32 remodify_sdram_params(struct rk3328_sdram_params *sdram_params)
+{
+	u32 tmp = 0, tmp_adr = 0, i;
+
+	for (i = 0; sdram_params->pctl_regs.pctl[i][0] != 0xFFFFFFFF; i++) {
+		if (sdram_params->pctl_regs.pctl[i][0] == 0) {
+			tmp = sdram_params->pctl_regs.pctl[i][1];/* MSTR */
+			tmp_adr = i;
+		}
+	}
+
+	tmp &= ~((3ul << 30) | (3ul << 24) | (3ul << 12));
+
+	switch (sdram_ch.dbw) {
+	case 2:
+		tmp |= (3ul << 30);
+		break;
+	case 1:
+		tmp |= (2ul << 30);
+		break;
+	case 0:
+	default:
+		tmp |= (1ul << 30);
+		break;
+	}
+
+	if (sdram_ch.rank == 2)
+		tmp |= 3 << 24;
+	else
+		tmp |= 1 << 24;
+
+	tmp |= (2 - sdram_ch.bw) << 12;
+
+	sdram_params->pctl_regs.pctl[tmp_adr][1] = tmp;
+
+	if (sdram_ch.bw == 2)
+		sdram_ch.noc_timings.ddrtiming.b.bwratio = 0;
+	else
+		sdram_ch.noc_timings.ddrtiming.b.bwratio = 1;
+
+	return 0;
+}
+
+static int dram_detect_cs1_row(struct rk3328_sdram_params *sdram_params,
+			       unsigned char channel)
+{
+	u32 ret = 0;
+	u32 cs1_bit;
+	void __iomem *test_addr, *cs1_addr;
+	u32 row, bktmp, coltmp, bw;
+	u32 ddrconf = sdram_ch.ddrconfig;
+
+	if (sdram_ch.rank == 2) {
+		cs1_bit = addrmap[ddrconf][0] + 8;
+
+		if (cs1_bit > 31)
+			goto out;
+
+		cs1_addr = (void __iomem *)(1ul << cs1_bit);
+		if (cs1_bit < 20)
+			cs1_bit = 1;
+		else
+			cs1_bit = 0;
+
+		if (sdram_params->dramtype == DDR4) {
+			if (sdram_ch.dbw == 0)
+				bktmp = sdram_ch.bk + 2;
+			else
+				bktmp = sdram_ch.bk + 1;
+		} else {
+			bktmp = sdram_ch.bk;
+		}
+		bw = sdram_ch.bw;
+		coltmp = sdram_ch.col;
+
+		/* detect cs1 row */
+		for (row = sdram_ch.cs0_row; row > 12; row--) {
+			test_addr = (void __iomem *)(SDRAM_ADDR + cs1_addr +
+					(1ul << (row + cs1_bit + bktmp +
+					 coltmp + bw - 1ul)));
+			writel(0, SDRAM_ADDR + cs1_addr);
+			writel(PATTERN, test_addr);
+			if ((readl(test_addr) == PATTERN) &&
+			    (readl(SDRAM_ADDR + cs1_addr) == 0)) {
+				ret = row;
+				break;
+			}
+		}
+	}
+
+out:
+	return ret;
+}
+
+static int sdram_init_detect(struct dram_info *dram,
+			     struct rk3328_sdram_params *sdram_params)
+{
+	debug("Starting SDRAM initialization...\n");
+
+	memcpy(&sdram_ch, &sdram_params->ch,
+	       sizeof(struct rk3328_sdram_channel));
+
+	sdram_init(dram, sdram_params, 1);
+	dram_detect_cap(dram, sdram_params, 0);
+
+	/* modify bw, cs related timing */
+	remodify_sdram_params(sdram_params);
+	/* reinit sdram by real dram cap */
+	sdram_init(dram, sdram_params, 0);
+
+	/* redetect cs1 row */
+	sdram_ch.cs1_row =
+		dram_detect_cs1_row(sdram_params, 0);
+
+	return 0;
+}
+
+static int rk3328_dmc_init(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3328_sdram_params *params = &plat->sdram_params;
+#else
+	struct dtd_rockchip_rk3328_dmc *dtplat = &plat->dtplat;
+	struct rk3328_sdram_params *params =
+					(void *)dtplat->rockchip_sdram_params;
+
+	ret = conv_of_platdata(dev);
+	if (ret)
+		return ret;
+#endif
+	priv->phy = regmap_get_range(plat->map, 0);
+	priv->pctl = regmap_get_range(plat->map, 1);
+	priv->grf = regmap_get_range(plat->map, 2);
+	priv->cru = regmap_get_range(plat->map, 3);
+	priv->msch = regmap_get_range(plat->map, 4);
+	priv->ddr_grf = regmap_get_range(plat->map, 5);
+
+	debug("%s phy %p pctrl %p grf %p cru %p msch %p ddr_grf %p\n",
+	      __func__, priv->phy, priv->pctl, priv->grf, priv->cru,
+	      priv->msch, priv->ddr_grf);
+	ret = sdram_init_detect(priv, params);
+	if (ret < 0) {
+		printf("%s DRAM init failed%d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rk3328_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = dev_read_u32_array(dev, "rockchip,sdram-params",
+				 (u32 *)&plat->sdram_params,
+				 sizeof(plat->sdram_params) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,sdram-params %d\n",
+		       __func__, ret);
+		return ret;
+	}
+	ret = regmap_init_mem(dev, &plat->map);
+	if (ret)
+		printf("%s: regmap failed %d\n", __func__, ret);
+#endif
+	return 0;
+}
+
+#endif
+
 static int rk3328_dmc_probe(struct udevice *dev)
 {
+#ifdef CONFIG_TPL_BUILD
+	if (rk3328_dmc_init(dev))
+		return 0;
+#else
 	struct dram_info *priv = dev_get_priv(dev);
 
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
@@ -25,7 +1032,7 @@
 	priv->info.base = CONFIG_SYS_SDRAM_BASE;
 	priv->info.size = rockchip_sdram_size(
 				(phys_addr_t)&priv->grf->os_reg[2]);
-
+#endif
 	return 0;
 }
 
@@ -42,7 +1049,6 @@
 	.get_info = rk3328_dmc_get_info,
 };
 
-
 static const struct udevice_id rk3328_dmc_ids[] = {
 	{ .compatible = "rockchip,rk3328-dmc" },
 	{ }
@@ -53,6 +1059,12 @@
 	.id = UCLASS_RAM,
 	.of_match = rk3328_dmc_ids,
 	.ops = &rk3328_dmc_ops,
+#ifdef CONFIG_TPL_BUILD
+	.ofdata_to_platdata = rk3328_dmc_ofdata_to_platdata,
+#endif
 	.probe = rk3328_dmc_probe,
 	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_TPL_BUILD
+	.platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat),
+#endif
 };
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 03531a8..fbb58c7 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -14,6 +14,8 @@
 #include <pci_ids.h>
 #include <spi.h>
 #include <asm/io.h>
+#include <spi-mem.h>
+#include <div64.h>
 
 #include "ich.h"
 
@@ -171,18 +173,6 @@
 	return 0;
 }
 
-static inline void spi_use_out(struct spi_trans *trans, unsigned bytes)
-{
-	trans->out += bytes;
-	trans->bytesout -= bytes;
-}
-
-static inline void spi_use_in(struct spi_trans *trans, unsigned bytes)
-{
-	trans->in += bytes;
-	trans->bytesin -= bytes;
-}
-
 static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
 {
 	if (plat->ich_version == ICHV_7) {
@@ -213,47 +203,12 @@
 	return lock != 0;
 }
 
-static void spi_setup_type(struct spi_trans *trans, int data_bytes)
-{
-	trans->type = 0xFF;
-
-	/* Try to guess spi type from read/write sizes */
-	if (trans->bytesin == 0) {
-		if (trans->bytesout + data_bytes > 4)
-			/*
-			 * If bytesin = 0 and bytesout > 4, we presume this is
-			 * a write data operation, which is accompanied by an
-			 * address.
-			 */
-			trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
-		else
-			trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
-		return;
-	}
-
-	if (trans->bytesout == 1) {	/* and bytesin is > 0 */
-		trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
-		return;
-	}
-
-	if (trans->bytesout == 4)	/* and bytesin is > 0 */
-		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
-
-	/* Fast read command is called with 5 bytes instead of 4 */
-	if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
-		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
-		--trans->bytesout;
-	}
-}
-
 static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
 			    bool lock)
 {
 	uint16_t optypes;
 	uint8_t opmenu[ctlr->menubytes];
 
-	trans->opcode = trans->out[0];
-	spi_use_out(trans, 1);
 	if (!lock) {
 		/* The lock is off, so just use index 0. */
 		ich_writeb(ctlr, trans->opcode, ctlr->opmenu);
@@ -285,12 +240,7 @@
 
 		optypes = ich_readw(ctlr, ctlr->optype);
 		optype = (optypes >> (opcode_index * 2)) & 0x3;
-		if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
-		    optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
-		    trans->bytesout >= 3) {
-			/* We guessed wrong earlier. Fix it up. */
-			trans->type = optype;
-		}
+
 		if (optype != trans->type) {
 			printf("ICH SPI: Transaction doesn't fit type %d\n",
 			       optype);
@@ -300,26 +250,6 @@
 	}
 }
 
-static int spi_setup_offset(struct spi_trans *trans)
-{
-	/* Separate the SPI address and data */
-	switch (trans->type) {
-	case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
-	case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
-		return 0;
-	case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
-	case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
-		trans->offset = ((uint32_t)trans->out[0] << 16) |
-				((uint32_t)trans->out[1] << 8) |
-				((uint32_t)trans->out[2] << 0);
-		spi_use_out(trans, 3);
-		return 1;
-	default:
-		printf("Unrecognized SPI transaction type %#x\n", trans->type);
-		return -EPROTO;
-	}
-}
-
 /*
  * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set
  * below is true) or 0. In case the wait was for the bit(s) to set - write
@@ -350,7 +280,7 @@
 	return -ETIMEDOUT;
 }
 
-void ich_spi_config_opcode(struct udevice *dev)
+static void ich_spi_config_opcode(struct udevice *dev)
 {
 	struct ich_spi_priv *ctlr = dev_get_priv(dev);
 
@@ -365,72 +295,48 @@
 	ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
 }
 
-static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
-			const void *dout, void *din, unsigned long flags)
+static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 {
-	struct udevice *bus = dev_get_parent(dev);
+	struct udevice *bus = dev_get_parent(slave->dev);
 	struct ich_spi_platdata *plat = dev_get_platdata(bus);
 	struct ich_spi_priv *ctlr = dev_get_priv(bus);
 	uint16_t control;
 	int16_t opcode_index;
 	int with_address;
 	int status;
-	int bytes = bitlen / 8;
 	struct spi_trans *trans = &ctlr->trans;
-	unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END);
-	int using_cmd = 0;
 	bool lock = spi_lock_status(plat, ctlr->base);
-	int ret;
-
-	/* We don't support writing partial bytes */
-	if (bitlen % 8) {
-		debug("ICH SPI: Accessing partial bytes not supported\n");
-		return -EPROTONOSUPPORT;
-	}
+	int ret = 0;
 
-	/* An empty end transaction can be ignored */
-	if (type == SPI_XFER_END && !dout && !din)
-		return 0;
-
-	if (type & SPI_XFER_BEGIN)
-		memset(trans, '\0', sizeof(*trans));
+	trans->in = NULL;
+	trans->out = NULL;
+	trans->type = 0xFF;
 
-	/* Dp we need to come back later to finish it? */
-	if (dout && type == SPI_XFER_BEGIN) {
-		if (bytes > ICH_MAX_CMD_LEN) {
-			debug("ICH SPI: Command length limit exceeded\n");
-			return -ENOSPC;
+	if (op->data.nbytes) {
+		if (op->data.dir == SPI_MEM_DATA_IN) {
+			trans->in = op->data.buf.in;
+			trans->bytesin = op->data.nbytes;
+		} else {
+			trans->out = op->data.buf.out;
+			trans->bytesout = op->data.nbytes;
 		}
-		memcpy(trans->cmd, dout, bytes);
-		trans->cmd_len = bytes;
-		debug_trace("ICH SPI: Saved %d bytes\n", bytes);
-		return 0;
 	}
 
-	/*
-	 * We process a 'middle' spi_xfer() call, which has no
-	 * SPI_XFER_BEGIN/END, as an independent transaction as if it had
-	 * an end. We therefore repeat the command. This is because ICH
-	 * seems to have no support for this, or because interest (in digging
-	 * out the details and creating a special case in the code) is low.
-	 */
-	if (trans->cmd_len) {
-		trans->out = trans->cmd;
-		trans->bytesout = trans->cmd_len;
-		using_cmd = 1;
-		debug_trace("ICH SPI: Using %d bytes\n", trans->cmd_len);
-	} else {
-		trans->out = dout;
-		trans->bytesout = dout ? bytes : 0;
-	}
+	if (trans->opcode != op->cmd.opcode)
+		trans->opcode = op->cmd.opcode;
 
-	trans->in = din;
-	trans->bytesin = din ? bytes : 0;
+	if (lock && trans->opcode == SPI_OPCODE_WRDIS)
+		return 0;
 
-	/* There has to always at least be an opcode */
-	if (!trans->bytesout) {
-		debug("ICH SPI: No opcode for transfer\n");
-		return -EPROTO;
+	if (trans->opcode == SPI_OPCODE_WREN) {
+		/*
+		 * Treat Write Enable as Atomic Pre-Op if possible
+		 * in order to prevent the Management Engine from
+		 * issuing a transaction between WREN and DATA.
+		 */
+		if (!lock)
+			ich_writew(ctlr, trans->opcode, ctlr->preop);
+		return 0;
 	}
 
 	ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
@@ -442,23 +348,29 @@
 	else
 		ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
 
+	/* Try to guess spi transaction type */
+	if (op->data.dir == SPI_MEM_DATA_OUT) {
+		if (op->addr.nbytes)
+			trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+		else
+			trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
+	} else {
+		if (op->addr.nbytes)
+			trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+		else
+			trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
+	}
+	/* Special erase case handling */
+	if (op->addr.nbytes && !op->data.buswidth)
+		trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+
-	spi_setup_type(trans, using_cmd ? bytes : 0);
 	opcode_index = spi_setup_opcode(ctlr, trans, lock);
 	if (opcode_index < 0)
 		return -EINVAL;
-	with_address = spi_setup_offset(trans);
-	if (with_address < 0)
-		return -EINVAL;
 
-	if (trans->opcode == SPI_OPCODE_WREN) {
-		/*
-		 * Treat Write Enable as Atomic Pre-Op if possible
-		 * in order to prevent the Management Engine from
-		 * issuing a transaction between WREN and DATA.
-		 */
-		if (!lock)
-			ich_writew(ctlr, trans->opcode, ctlr->preop);
-		return 0;
+	if (op->addr.nbytes) {
+		trans->offset = op->addr.val;
+		with_address = 1;
 	}
 
 	if (ctlr->speed && ctlr->max_speed >= 33000000) {
@@ -472,13 +384,6 @@
 		ich_writeb(ctlr, byte, ctlr->speed);
 	}
 
-	/* See if we have used up the command data */
-	if (using_cmd && dout && bytes) {
-		trans->out = dout;
-		trans->bytesout = bytes;
-		debug_trace("ICH SPI: Moving to data, %d bytes\n", bytes);
-	}
-
 	/* Preset control fields */
 	control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
 
@@ -513,22 +418,6 @@
 		return 0;
 	}
 
-	/*
-	 * Check if this is a write command atempting to transfer more bytes
-	 * than the controller can handle. Iterations for writes are not
-	 * supported here because each SPI write command needs to be preceded
-	 * and followed by other SPI commands, and this sequence is controlled
-	 * by the SPI chip driver.
-	 */
-	if (trans->bytesout > ctlr->databytes) {
-		debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n");
-		return -EPROTO;
-	}
-
-	/*
-	 * Read or write up to databytes bytes at a time until everything has
-	 * been sent.
-	 */
 	while (trans->bytesout || trans->bytesin) {
 		uint32_t data_length;
 
@@ -543,9 +432,7 @@
 		/* Program data into FDATA0 to N */
 		if (trans->bytesout) {
 			write_reg(ctlr, trans->out, ctlr->data, data_length);
-			spi_use_out(trans, data_length);
-			if (with_address)
-				trans->offset += data_length;
+			trans->bytesout -= data_length;
 		}
 
 		/* Add proper control fields' values */
@@ -568,9 +455,7 @@
 
 		if (trans->bytesin) {
 			read_reg(ctlr, ctlr->data, trans->in, data_length);
-			spi_use_in(trans, data_length);
-			if (with_address)
-				trans->offset += data_length;
+			trans->bytesin -= data_length;
 		}
 	}
 
@@ -581,6 +466,40 @@
 	return 0;
 }
 
+static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
+{
+	unsigned int page_offset;
+	int addr = op->addr.val;
+	unsigned int byte_count = op->data.nbytes;
+
+	if (hweight32(ICH_BOUNDARY) == 1) {
+		page_offset = addr & (ICH_BOUNDARY - 1);
+	} else {
+		u64 aux = addr;
+
+		page_offset = do_div(aux, ICH_BOUNDARY);
+	}
+
+	if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
+		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
+				      slave->max_read_size);
+	} else if (slave->max_write_size) {
+		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
+				      slave->max_write_size);
+	}
+
+	op->data.nbytes = min(op->data.nbytes, byte_count);
+
+	return 0;
+}
+
+static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			const void *dout, void *din, unsigned long flags)
+{
+	printf("ICH SPI: Only supports memory operations\n");
+	return -1;
+}
+
 static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
@@ -686,10 +605,17 @@
 	return ret;
 }
 
+static const struct spi_controller_mem_ops ich_controller_mem_ops = {
+	.adjust_op_size	= ich_spi_adjust_size,
+	.supports_op	= NULL,
+	.exec_op	= ich_spi_exec_op,
+};
+
 static const struct dm_spi_ops ich_spi_ops = {
 	.xfer		= ich_spi_xfer,
 	.set_speed	= ich_spi_set_speed,
 	.set_mode	= ich_spi_set_mode,
+	.mem_ops	= &ich_controller_mem_ops,
 	/*
 	 * cs_info is not needed, since we require all chip selects to be
 	 * in the device tree explicitly
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index a974241..3dfb2aa 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -100,13 +100,8 @@
 	HSFC_FSMIE =		0x8000
 };
 
-enum {
-	ICH_MAX_CMD_LEN		= 5,
-};
-
 struct spi_trans {
-	uint8_t cmd[ICH_MAX_CMD_LEN];
-	int cmd_len;
+	uint8_t cmd;
 	const uint8_t *out;
 	uint32_t bytesout;
 	uint8_t *in;
@@ -166,6 +161,8 @@
 #define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
 			  (SPI_OPMENU_1 <<  8) | (SPI_OPMENU_0 <<  0))
 
+#define ICH_BOUNDARY	0x1000
+
 enum ich_version {
 	ICHV_7,
 	ICHV_9,
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index ccda432..1e5d14c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -17,15 +17,6 @@
 	   Disable reset watchdog, which can let WATCHDOG_RESET invalid, so
 	   that the watchdog will not be fed in u-boot.
 
-config BCM2835_WDT
-	bool "Enable BCM2835/2836 watchdog driver"
-	select HW_WATCHDOG
-	help
-	  Say Y here to enable the BCM2835/2836 watchdog
-
-	  This provides basic infrastructure to support BCM2835/2836 watchdog
-	  hardware, with a max timeout of ~15secs.
-
 config IMX_WATCHDOG
 	bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
 	select HW_WATCHDOG if !WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 97aa6a8..414ba24 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -20,7 +20,6 @@
 obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
 obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
-obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
 obj-$(CONFIG_WDT_ORION) += orion_wdt.o
 obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
 obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
deleted file mode 100644
index 6cffcb1..0000000
--- a/drivers/watchdog/bcm2835_wdt.c
+++ /dev/null
@@ -1,34 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Watchdog driver for Broadcom BCM2835
- *
- * Copyright (C) 2017 Paolo Pisati <p.pisati@gmail.com>
- */
-
-#include <common.h>
-#include <efi_loader.h>
-#include <asm/io.h>
-#include <asm/arch/wdog.h>
-
-#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
-#define MAX_TIMEOUT   0xf /* ~15s */
-
-static __efi_runtime_data bool enabled = true;
-
-extern void reset_cpu(ulong ticks);
-
-void hw_watchdog_reset(void)
-{
-	if (enabled)
-		reset_cpu(SECS_TO_WDOG_TICKS(MAX_TIMEOUT));
-}
-
-void hw_watchdog_init(void)
-{
-	hw_watchdog_reset();
-}
-
-void __efi_runtime hw_watchdog_disable(void)
-{
-	enabled = false;
-}
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index a7d4c7a..dafd2b5 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -70,9 +70,12 @@
 	return 0;
 }
 
-static void mtk_wdt_set_timeout(struct udevice *dev, unsigned int timeout_ms)
+static void mtk_wdt_set_timeout(struct udevice *dev, u64 timeout_ms)
 {
 	struct mtk_wdt_priv *priv = dev_get_priv(dev);
+	u64 timeout_us;
+	u32 timeout_cc;
+	u32 length;
 
 	/*
 	 * One WDT_LENGTH count is 512 ticks of the wdt clock
@@ -88,21 +91,25 @@
 	 *  The MediaTek docs lack details to know if this is the case here.
 	 *  So we enforce a minimum of 1 to guarantee operation.
 	 */
-	if(timeout_ms > 15984) timeout_ms = 15984;
-	u64 timeout_us = timeout_ms * 1000;
-	u32 timeout_cc = (u32) ( (15624 + timeout_us) / 15625 );
-	if(timeout_cc == 0) timeout_cc = 1;
-	u32 length = WDT_LENGTH_TIMEOUT(timeout_cc) | WDT_LENGTH_KEY;
+	if (timeout_ms > 15984)
+		timeout_ms = 15984;
+
+	timeout_us = timeout_ms * 1000;
+	timeout_cc = (15624 + timeout_us) / 15625;
+	if (timeout_cc == 0)
+		timeout_cc = 1;
+
+	length = WDT_LENGTH_TIMEOUT(timeout_cc) | WDT_LENGTH_KEY;
 	writel(length, priv->base + MTK_WDT_LENGTH);
 }
 
-static int mtk_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+static int mtk_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
 	struct mtk_wdt_priv *priv = dev_get_priv(dev);
 
-	mtk_wdt_set_timeout(dev, timeout);
+	mtk_wdt_set_timeout(dev, timeout_ms);
 
-        mtk_wdt_reset(dev);
+	mtk_wdt_reset(dev);
 
 	/* Enable watchdog reset signal */
 	setbits_le32(priv->base + MTK_WDT_MODE,
diff --git a/include/configs/apalis-tk1.h b/include/configs/apalis-tk1.h
index b4ddd1b..dacf36b 100644
--- a/include/configs/apalis-tk1.h
+++ b/include/configs/apalis-tk1.h
@@ -18,6 +18,9 @@
 #define CONFIG_TEGRA_ENABLE_UARTA
 #define CONFIG_SYS_NS16550_COM1		NV_PA_APB_UARTA_BASE
 
+#define FDT_MODULE			"apalis-v1.2"
+#define FDT_MODULE_V1_0			"apalis"
+
 /* Environment in eMMC, before config block at the end of 1st "boot sector" */
 #define CONFIG_ENV_OFFSET		(-CONFIG_ENV_SIZE + \
 					 CONFIG_TDX_CFG_BLOCK_OFFSET)
@@ -42,7 +45,7 @@
 #define DFU_ALT_EMMC_INFO	"apalis-tk1.img raw 0x0 0x500 mmcpart 1; " \
 				"boot part 0 1 mmcpart 0; " \
 				"rootfs part 0 2 mmcpart 0; " \
-				"uImage fat 0 1 mmcpart 0; " \
+				"zImage fat 0 1 mmcpart 0; " \
 				"tegra124-apalis-eval.dtb fat 0 1 mmcpart 0"
 
 #define EMMC_BOOTCMD \
@@ -54,11 +57,11 @@
 		"run emmcdtbload; " \
 		"load mmc ${emmcdev}:${emmcbootpart} ${kernel_addr_r} " \
 		"${boot_file} && run fdt_fixup && " \
-		"bootm ${kernel_addr_r} - ${dtbparam}\0" \
+		"bootz ${kernel_addr_r} - ${dtbparam}\0" \
 	"emmcbootpart=1\0" \
 	"emmcdev=0\0" \
 	"emmcdtbload=setenv dtbparam; load mmc ${emmcdev}:${emmcbootpart} " \
-		"${fdt_addr_r} ${soc}-apalis-${fdt_board}.dtb && " \
+		"${fdt_addr_r} ${soc}-${fdt_module}-${fdt_board}.dtb && " \
 		"setenv dtbparam ${fdt_addr_r}\0" \
 	"emmcfinduuid=part uuid mmc ${mmcdev}:${emmcrootpart} uuid\0" \
 	"emmcrootpart=2\0"
@@ -68,9 +71,9 @@
 	"nfsboot=pci enum; run setup; setenv bootargs ${defargs} ${nfsargs} " \
 		"${setupargs} ${vidargs}; echo Booting via DHCP/TFTP/NFS...; " \
 		"run nfsdtbload; dhcp ${kernel_addr_r} " \
-		"&& run fdt_fixup && bootm ${kernel_addr_r} - ${dtbparam}\0" \
+		"&& run fdt_fixup && bootz ${kernel_addr_r} - ${dtbparam}\0" \
 	"nfsdtbload=setenv dtbparam; tftp ${fdt_addr_r} " \
-		"${soc}-apalis-${fdt_board}.dtb " \
+		"${soc}-${fdt_module}-${fdt_board}.dtb " \
 		"&& setenv dtbparam ${fdt_addr_r}\0"
 
 #define SD_BOOTCMD \
@@ -81,44 +84,28 @@
 		"${vidargs}; echo Booting from SD card in 8bit slot...; " \
 		"run sddtbload; load mmc ${sddev}:${sdbootpart} " \
 		"${kernel_addr_r} ${boot_file} && run fdt_fixup && " \
-		"bootm ${kernel_addr_r} - ${dtbparam}\0" \
+		"bootz ${kernel_addr_r} - ${dtbparam}\0" \
 	"sdbootpart=1\0" \
 	"sddev=1\0" \
 	"sddtbload=setenv dtbparam; load mmc ${sddev}:${sdbootpart} " \
-		"${fdt_addr_r} ${soc}-apalis-${fdt_board}.dtb " \
+		"${fdt_addr_r} ${soc}-${fdt_module}-${fdt_board}.dtb " \
 		"&& setenv dtbparam ${fdt_addr_r}\0" \
 	"sdfinduuid=part uuid mmc ${sddev}:${sdrootpart} uuid\0" \
 	"sdrootpart=2\0"
 
-#define USB_BOOTCMD \
-	"set_usbargs=setenv usbargs ip=off root=PARTUUID=${uuid} ro " \
-		"rootfstype=ext4 rootwait\0" \
-	"usbboot=run setup; usb start; run usbfinduuid; run set_usbargs; " \
-		"setenv bootargs ${defargs} ${setupargs} " \
-		"${usbargs} ${vidargs}; echo Booting from USB stick...; " \
-		"run usbdtbload; load usb ${usbdev}:${usbbootpart} " \
-		"${kernel_addr_r} ${boot_file} && run fdt_fixup && " \
-		"bootm ${kernel_addr_r} - ${dtbparam}\0" \
-	"usbbootpart=1\0" \
-	"usbdev=0\0" \
-	"usbdtbload=setenv dtbparam; load usb ${usbdev}:${usbbootpart} " \
-		"${fdt_addr_r} ${soc}-apalis-${fdt_board}.dtb " \
-		"&& setenv dtbparam ${fdt_addr_r}\0" \
-	"usbfinduuid=part uuid usb ${usbdev}:${usbrootpart} uuid\0" \
-	"usbrootpart=2\0"
-
 #define BOARD_EXTRA_ENV_SETTINGS \
-	"boot_file=uImage\0" \
+	"boot_file=zImage\0" \
 	"console=ttyS0\0" \
 	"defargs=lp0_vec=2064@0xf46ff000 core_edp_mv=1150 core_edp_ma=4000 " \
-		"usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0\0" \
+		"usb_port_owner_info=2 lane_owner_info=6 emc_max_dvfs=0 " \
+		"user_debug=30 pcie_aspm=off\0" \
 	"dfu_alt_info=" DFU_ALT_EMMC_INFO "\0" \
 	EMMC_BOOTCMD \
 	"fdt_board=eval\0" \
 	"fdt_fixup=;\0" \
+	"fdt_module=" FDT_MODULE "\0" \
 	NFS_BOOTCMD \
 	SD_BOOTCMD \
-	USB_BOOTCMD \
 	"setethupdate=if env exists ethaddr; then; else setenv ethaddr " \
 		"00:14:2d:00:00:00; fi; pci enum && tftpboot ${loadaddr} " \
 		"flash_eth.img && source ${loadaddr}\0" \
@@ -135,8 +122,7 @@
 	"setusbupdate=usb start && setenv interface usb; setenv drive 0; " \
 		"load ${interface} ${drive}:1 ${loadaddr} flash_blk.img && " \
 		"source ${loadaddr}\0" \
-	USB_BOOTCMD \
-	"vidargs=video=tegrafb0:640x480-16@60 fbcon=map:1\0"
+	"vidargs=fbcon=map:1\0"
 
 /* Increase console I/O buffer size */
 #undef CONFIG_SYS_CBSIZE
diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h
index 64e7a60..c557420 100644
--- a/include/configs/qemu-x86.h
+++ b/include/configs/qemu-x86.h
@@ -10,8 +10,23 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#include <linux/sizes.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(USB, usb, 0) \
+	func(SCSI, scsi, 0) \
+	func(VIRTIO, virtio, 0) \
+	func(IDE, ide, 0) \
+	func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
 #include <configs/x86-common.h>
 
+#undef CONFIG_ENV_SIZE
+#define CONFIG_ENV_SIZE			SZ_256K
+
+#define CONFIG_PREBOOT "pci enum"
+
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 
 #define CONFIG_STD_DEVICES_SETTINGS	"stdin=serial,i8042-kbd\0" \
diff --git a/include/configs/slimbootloader.h b/include/configs/slimbootloader.h
new file mode 100644
index 0000000..e0011ed
--- /dev/null
+++ b/include/configs/slimbootloader.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#ifndef __SLIMBOOTLOADER_CONFIG_H__
+#define __SLIMBOOTLOADER_CONFIG_H__
+
+#include <configs/x86-common.h>
+
+/*
+ * By default, CONFIG_SYS_NS16550_PORT_MAPPED is enabled for port io serial.
+ * To use mmio base serial, enable CONFIG_SYS_NS16550_MEM32 and disable
+ * CONFIG_SYS_NS16550_PORT_MAPPED until ns16550 driver supports serial port
+ * configuration in run-time.
+ *
+ * #define CONFIG_SYS_NS16550_MEM32
+ * #undef CONFIG_SYS_NS16550_PORT_MAPPED
+ */
+#ifdef CONFIG_SYS_NS16550_MEM32
+#undef CONFIG_SYS_NS16550_PORT_MAPPED
+#endif
+
+#define CONFIG_STD_DEVICES_SETTINGS		\
+	"stdin=serial,i8042-kbd,usbkbd\0"	\
+	"stdout=serial\0"			\
+	"stderr=serial\0"
+
+/*
+ * Override CONFIG_EXTRA_ENV_SETTINGS in x86-common.h
+ */
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	CONFIG_STD_DEVICES_SETTINGS		\
+	"netdev=eth0\0"				\
+	"consoledev=ttyS0\0"			\
+	"ramdiskaddr=0x4000000\0"		\
+	"ramdiskfile=initrd\0"			\
+	"bootdev=usb\0"				\
+	"bootdevnum=0\0"			\
+	"bootdevpart=0\0"			\
+	"bootfsload=fatload\0"			\
+	"bootusb=setenv bootdev usb; boot\0"	\
+	"bootscsi=setenv bootdev scsi; boot\0"	\
+	"bootmmc=setenv bootdev mmc; boot\0"	\
+	"bootargs=console=ttyS0,115200 console=tty0\0"
+
+/*
+ * Override CONFIG_BOOTCOMMAND in x86-common.h
+ */
+#undef CONFIG_BOOTCOMMAND
+#define CONFIG_BOOTCOMMAND						\
+	"if test ${bootdev} = \"usb\"; then ${bootdev} start; fi; "	\
+	"if test ${bootdev} = \"scsi\"; then ${bootdev} scan; fi; "	\
+	"${bootdev} info; "						\
+	"${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} "	\
+	"${loadaddr} ${bootfile}; "					\
+	"${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} "	\
+	"${ramdiskaddr} ${ramdiskfile}; "				\
+	"zboot ${loadaddr} 0 ${ramdiskaddr} ${filesize}"
+
+#endif /* __SLIMBOOTLOADER_CONFIG_H__ */
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index c4deef8..ca27a4f 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -105,30 +105,37 @@
 #define CONFIG_OTHBOOTARGS	"othbootargs=acpi=off\0"
 #endif
 
+#ifndef CONFIG_DISTRO_DEFAULTS
+#define BOOTENV
+#endif
+
 #define CONFIG_EXTRA_ENV_SETTINGS			\
 	CONFIG_STD_DEVICES_SETTINGS			\
 	"pciconfighost=1\0"				\
 	"netdev=eth0\0"					\
 	"consoledev=ttyS0\0"				\
 	CONFIG_OTHBOOTARGS				\
-	"ramdiskaddr=0x4000000\0"			\
-	"ramdiskfile=initramfs.gz\0"
+	"scriptaddr=0x7000000\0"			\
+	"kernel_addr_r=0x1000000\0"			\
+	"ramdisk_addr_r=0x4000000\0"			\
+	"ramdiskfile=initramfs.gz\0"			\
+	BOOTENV
 
 #define CONFIG_RAMBOOTCOMMAND				\
 	"setenv bootargs root=/dev/ram rw "		\
 	"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \
 	"console=$consoledev,$baudrate $othbootargs;"	\
-	"tftpboot $loadaddr $bootfile;"			\
-	"tftpboot $ramdiskaddr $ramdiskfile;"		\
-	"zboot $loadaddr 0 $ramdiskaddr $filesize"
+	"tftpboot $kernel_addr_r $bootfile;"		\
+	"tftpboot $ramdisk_addr_r $ramdiskfile;"	\
+	"zboot $kernel_addr_r 0 $ramdisk_addr_r $filesize"
 
 #define CONFIG_NFSBOOTCOMMAND				\
 	"setenv bootargs root=/dev/nfs rw "		\
 	"nfsroot=$serverip:$rootpath "			\
 	"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \
 	"console=$consoledev,$baudrate $othbootargs;"	\
-	"tftpboot $loadaddr $bootfile;"			\
-	"zboot $loadaddr"
+	"tftpboot $kernel_addr_r $bootfile;"		\
+	"zboot $kernel_addr_r"
 
 
 #endif	/* __CONFIG_H */
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 2f5e28c..ef116e0 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -395,11 +395,22 @@
 
 # ACPI
 # ---------------------------------------------------------------------------
+#
+# This first sends the file (typically dsdt.asl) through the preprocessor
+# resolve includes and any CONFIG options used. This produces dsdt.asl.tmp
+# which is pure ASL code. The Intel ASL (ACPI (Advanced Configuration and Power
+# Interface) Source Language compiler (iasl) then converts this ASL code into a
+# C file containing the hex data to build into U-Boot. This file is called
+# dsdt.hex (despite us setting the prefix to .../dsdt.asl.tmp) so must be
+# renamed to dsdt.c for consumption by the build system.
+ASL_TMP = $(patsubst %.c,%.asl.tmp,$@)
+
 quiet_cmd_acpi_c_asl= ASL     $<
 cmd_acpi_c_asl=         \
-	$(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) -o $<.tmp $<; \
-	iasl -p $< -tc $<.tmp $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \
-	mv $(patsubst %.asl,%.hex,$<) $@
+	$(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) \
+		-o $(ASL_TMP) $< && \
+	iasl -p $@ -tc $(ASL_TMP) $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \
+	mv $(patsubst %.c,%.hex,$@) $@
 
 $(obj)/dsdt.c:    $(src)/dsdt.asl
 	$(call cmd,acpi_c_asl)
diff --git a/test/py/tests/test_mmc_wr.py b/test/py/tests/test_mmc_wr.py
index 601279a..7678c3c 100644
--- a/test/py/tests/test_mmc_wr.py
+++ b/test/py/tests/test_mmc_wr.py
@@ -35,7 +35,7 @@
 
 """
 
-@pytest.mark.buildconfigspec('cmd_mmc','cmd_memory')
+@pytest.mark.buildconfigspec('cmd_mmc','cmd_random')
 def test_mmc_wr(u_boot_console, env__mmc_wr_config):
     """Test the "mmc write" command.