Merge tag 'dm-pull-30oct20' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm

of-platdata and dtoc improvements
sandbox SPL tests
binman support for compressed sections
diff --git a/MAINTAINERS b/MAINTAINERS
index 857e236..874cf2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -546,6 +546,7 @@
 S:	Maintained
 T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/mach-zynq/
+F:	doc/board/xilinx/
 F:	drivers/clk/clk_zynq.c
 F:	drivers/fpga/zynqpl.c
 F:	drivers/gpio/zynq_gpio.c
@@ -757,6 +758,7 @@
 F:	common/log*
 F:	cmd/log.c
 F:	doc/develop/logging.rst
+F:	lib/getopt.c
 F:	test/log/
 F:	test/py/tests/test_log.py
 
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index d8b0a91..bd97604 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -279,6 +279,7 @@
 	zynq-zc770-xm013.dtb \
 	zynq-zed.dtb \
 	zynq-zturn.dtb \
+	zynq-zturn-v5.dtb \
 	zynq-zybo.dtb \
 	zynq-zybo-z7.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += \
diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
index cd5c974..7d0d31d 100644
--- a/arch/arm/dts/armada-cp110-master.dtsi
+++ b/arch/arm/dts/armada-cp110-master.dtsi
@@ -285,15 +285,18 @@
 			};
 
 			cpm_nand: nand@720000 {
-				compatible = "marvell,mvebu-pxa3xx-nand";
-				reg = <0x720000 0x100>;
+				compatible = "marvell,armada-8k-nand-controller",
+					"marvell,armada370-nand-controller";
+				reg = <0x720000 0x54>;
 				#address-cells = <1>;
-
-				clocks = <&cpm_syscon0 1 2>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+				clock-names = "core", "reg";
+				clocks = <&cpm_syscon0 1 2>,
+					 <&cpm_syscon0 1 17>;
+				marvell,system-controller = <&cpm_syscon0>;
 				nand-enable-arbiter;
 				num-cs = <1>;
-				nand-ecc-strength = <4>;
-				nand-ecc-step-size = <512>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi
index b426a4e..6cf2177 100644
--- a/arch/arm/dts/armada-cp110-slave.dtsi
+++ b/arch/arm/dts/armada-cp110-slave.dtsi
@@ -267,6 +267,22 @@
 				utmi-port = <UTMI_PHY_TO_USB3_HOST0>;
 				status = "disabled";
 			};
+
+			cps_nand: nand@720000 {
+				compatible = "marvell,armada-8k-nand-controller",
+					"marvell,armada370-nand-controller";
+				reg = <0x720000 0x54>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+				clock-names = "core", "reg";
+				clocks = <&cps_syscon0 1 2>,
+					 <&cps_syscon0 1 17>;
+				marvell,system-controller = <&cps_syscon0>;
+				nand-enable-arbiter;
+				num-cs = <1>;
+				status = "disabled";
+			};
 		};
 
 		cps_pcie0: pcie@f4600000 {
diff --git a/arch/arm/dts/versal-mini-emmc0.dts b/arch/arm/dts/versal-mini-emmc0.dts
index 7826a28..6a6e746 100644
--- a/arch/arm/dts/versal-mini-emmc0.dts
+++ b/arch/arm/dts/versal-mini-emmc0.dts
@@ -16,10 +16,10 @@
 	#size-cells = <2>;
 	model = "Xilinx Versal MINI eMMC0";
 
-	clk25: clk25 {
+	clk200: clk200 {
 		compatible = "fixed-clock";
 		#clock-cells = <0x0>;
-		clock-frequency = <25000000>;
+		clock-frequency = <200000000>;
 	};
 
 	dcc: dcc {
@@ -38,9 +38,12 @@
 		sdhci0: sdhci@f1040000 {
 			compatible = "xlnx,versal-8.9a", "arasan,sdhci-8.9a";
 			status = "okay";
+			non-removable;
+			disable-wp;
+			bus-width = <8>;
 			reg = <0x0 0xf1040000 0x0 0x10000>;
 			clock-names = "clk_xin", "clk_ahb";
-			clocks = <&clk25 &clk25>;
+			clocks = <&clk200 &clk200>;
 			xlnx,device_id = <0>;
 			no-1-8-v;
 			xlnx,mio-bank = <0>;
diff --git a/arch/arm/dts/versal-mini-emmc1.dts b/arch/arm/dts/versal-mini-emmc1.dts
index 2f28f85..c342e6b 100644
--- a/arch/arm/dts/versal-mini-emmc1.dts
+++ b/arch/arm/dts/versal-mini-emmc1.dts
@@ -16,10 +16,10 @@
 	#size-cells = <2>;
 	model = "Xilinx Versal MINI eMMC1";
 
-	clk25: clk25 {
+	clk200: clk200 {
 		compatible = "fixed-clock";
 		#clock-cells = <0x0>;
-		clock-frequency = <25000000>;
+		clock-frequency = <200000000>;
 	};
 
 	dcc: dcc {
@@ -38,9 +38,12 @@
 		sdhci1: sdhci@f1050000 {
 			compatible = "xlnx,versal-8.9a", "arasan,sdhci-8.9a";
 			status = "okay";
+			non-removable;
+			disable-wp;
+			bus-width = <8>;
 			reg = <0x0 0xf1050000 0x0 0x10000>;
 			clock-names = "clk_xin", "clk_ahb";
-			clocks = <&clk25 &clk25>;
+			clocks = <&clk200 &clk200>;
 			xlnx,device_id = <1>;
 			no-1-8-v;
 			xlnx,mio-bank = <0>;
diff --git a/arch/arm/dts/zynq-zturn-common.dtsi b/arch/arm/dts/zynq-zturn-common.dtsi
new file mode 100644
index 0000000..1d7af02
--- /dev/null
+++ b/arch/arm/dts/zynq-zturn-common.dtsi
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2015 Andrea Merello <adnrea.merello@gmail.com>
+ *  Copyright (C) 2017 Alexander Graf <agraf@suse.de>
+ *
+ *  Based on zynq-zed.dts which is:
+ *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ *
+ */
+
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+	compatible = "xlnx,zynq-7000";
+
+	aliases {
+		ethernet0 = &gem0;
+		serial0 = &uart1;
+		serial1 = &uart0;
+		mmc0 = &sdhci0;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		usr-led1 {
+			label = "usr-led1";
+			gpios = <&gpio0 0x0 0x1>;
+			default-state = "off";
+		};
+
+		usr-led2 {
+			label = "usr-led2";
+			gpios = <&gpio0 0x9 0x1>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+		K1 {
+			label = "K1";
+			gpios = <&gpio0 0x32 0x1>;
+			linux,code = <0x66>;
+			wakeup-source;
+			autorepeat;
+		};
+	};
+};
+
+&clkc {
+	ps-clk-frequency = <33333333>;
+};
+
+&qspi {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&gem0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+
+	ethernet_phy: ethernet-phy@0 {
+	};
+};
+
+&sdhci0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&uart1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&can0 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	stlm75@49 {
+		status = "okay";
+		compatible = "lm75";
+		reg = <0x49>;
+	};
+
+	accelerometer@53 {
+		compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x";
+		reg = <0x53>;
+		interrupt-parent = <&intc>;
+		interrupts = <0x0 0x1e 0x4>;
+	};
+};
diff --git a/arch/arm/dts/zynq-zturn-v5.dts b/arch/arm/dts/zynq-zturn-v5.dts
new file mode 100644
index 0000000..536632a
--- /dev/null
+++ b/arch/arm/dts/zynq-zturn-v5.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+/include/ "zynq-zturn-common.dtsi"
+
+/ {
+	model = "Zynq Z-Turn MYIR Board V5";
+	compatible = "myir,zynq-zturn-v5", "xlnx,zynq-7000";
+};
+
+&gem0 {
+	ethernet_phy: ethernet-phy@0 {
+		reg = <0x3>;
+	};
+};
diff --git a/arch/arm/dts/zynq-zturn.dts b/arch/arm/dts/zynq-zturn.dts
index 600e8ee..620b24a 100644
--- a/arch/arm/dts/zynq-zturn.dts
+++ b/arch/arm/dts/zynq-zturn.dts
@@ -1,122 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- *  Copyright (C) 2015 Andrea Merello <adnrea.merello@gmail.com>
- *  Copyright (C) 2017 Alexander Graf <agraf@suse.de>
- *
- *  Based on zynq-zed.dts which is:
- *  Copyright (C) 2011 - 2014 Xilinx
- *  Copyright (C) 2012 National Instruments Corp.
- *
- */
 
 /dts-v1/;
-/include/ "zynq-7000.dtsi"
+/include/ "zynq-zturn-common.dtsi"
 
 / {
 	model = "Zynq Z-Turn MYIR Board";
 	compatible = "myir,zynq-zturn", "xlnx,zynq-7000";
-
-	aliases {
-		ethernet0 = &gem0;
-		serial0 = &uart1;
-		serial1 = &uart0;
-		mmc0 = &sdhci0;
-	};
-
-	memory@0 {
-		device_type = "memory";
-		reg = <0x0 0x40000000>;
-	};
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	gpio-leds {
-		compatible = "gpio-leds";
-		usr-led1 {
-			label = "usr-led1";
-			gpios = <&gpio0 0x0 0x1>;
-			default-state = "off";
-		};
-
-		usr-led2 {
-			label = "usr-led2";
-			gpios = <&gpio0 0x9 0x1>;
-			default-state = "off";
-		};
-	};
-
-	gpio-keys {
-		compatible = "gpio-keys";
-		autorepeat;
-		K1 {
-			label = "K1";
-			gpios = <&gpio0 0x32 0x1>;
-			linux,code = <0x66>;
-			wakeup-source;
-			autorepeat;
-		};
-	};
 };
 
-&clkc {
-	ps-clk-frequency = <33333333>;
-};
-
-&qspi {
-	u-boot,dm-pre-reloc;
-	status = "okay";
-};
-
 &gem0 {
-	status = "okay";
-	phy-mode = "rgmii-id";
-	phy-handle = <&ethernet_phy>;
-
 	ethernet_phy: ethernet-phy@0 {
 		reg = <0x0>;
 	};
 };
-
-&sdhci0 {
-	u-boot,dm-pre-reloc;
-	status = "okay";
-};
-
-&uart0 {
-	u-boot,dm-pre-reloc;
-	status = "okay";
-};
-
-&uart1 {
-	u-boot,dm-pre-reloc;
-	status = "okay";
-};
-
-&usb0 {
-	status = "okay";
-	dr_mode = "host";
-};
-
-&can0 {
-	status = "okay";
-};
-
-&i2c0 {
-	status = "okay";
-	clock-frequency = <400000>;
-
-	stlm75@49 {
-		status = "okay";
-		compatible = "lm75";
-		reg = <0x49>;
-	};
-
-	accelerometer@53 {
-		compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x";
-		reg = <0x53>;
-		interrupt-parent = <&intc>;
-		interrupts = <0x0 0x1e 0x4>;
-	};
-};
diff --git a/arch/arm/dts/zynqmp-mini-qspi.dts b/arch/arm/dts/zynqmp-mini-qspi.dts
index a76e640..9b4320f 100644
--- a/arch/arm/dts/zynqmp-mini-qspi.dts
+++ b/arch/arm/dts/zynqmp-mini-qspi.dts
@@ -70,7 +70,7 @@
 		reg = <0x0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
-		spi-max-frequency = <108000000>;
+		spi-max-frequency = <40000000>;
 	};
 };
 
diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index cb8cfd2..d09141c 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -9,7 +9,6 @@
 #include <init.h>
 #include <log.h>
 #include <spl.h>
-#include <generated/dt.h>
 
 #include <asm/io.h>
 #include <asm/spl.h>
@@ -86,16 +85,3 @@
 	ps7_post_config();
 	debug("SPL bye\n");
 }
-
-#ifdef CONFIG_SPL_LOAD_FIT
-int board_fit_config_name_match(const char *name)
-{
-	/* Just empty function now - can't decide what to choose */
-	debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE);
-
-	if (!strcmp(name, DEVICE_TREE))
-		return 0;
-
-	return -1;
-}
-#endif
diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
index f2b3cea..1c12eac 100644
--- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
@@ -9,6 +9,16 @@
 
 #define ZYNQMP_CSU_SILICON_VER_MASK	0xF
 #define KEY_PTR_LEN	32
+#define IV_SIZE		12
+#define RSA_KEY_SIZE	512
+#define MODULUS_LEN	512
+#define PRIV_EXPO_LEN	512
+#define PUB_EXPO_LEN	4
+
+#define ZYNQMP_SHA3_INIT	1
+#define ZYNQMP_SHA3_UPDATE	2
+#define ZYNQMP_SHA3_FINAL	4
+#define ZYNQMP_SHA3_SIZE	48
 
 #define ZYNQMP_FPGA_BIT_AUTH_DDR	1
 #define ZYNQMP_FPGA_BIT_AUTH_OCM	2
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index 9dd61e2..88386b2 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -119,13 +119,3 @@
 	return 0;
 }
 #endif
-
-#ifdef CONFIG_SPL_LOAD_FIT
-int board_fit_config_name_match(const char *name)
-{
-	/* Just empty function now - can't decide what to choose */
-	debug("%s: %s\n", __func__, name);
-
-	return -1;
-}
-#endif
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index ff6b3c7..99a17bc 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -16,10 +16,14 @@
 	select OF_CONTROL
 	select SUPPORT_SPL
 	select SYSRESET
+	select DM_SPI
+	select DM_SPI_FLASH
+	select SPI
 	imply CMD_DM
 
 endchoice
 
+source "board/xilinx/Kconfig"
 source "board/xilinx/microblaze-generic/Kconfig"
 
 endmenu
diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S
index cbec299..9479737 100644
--- a/arch/microblaze/cpu/start.S
+++ b/arch/microblaze/cpu/start.S
@@ -13,31 +13,108 @@
 	.text
 	.global _start
 _start:
-	/*
-	 * reserve registers:
-	 * r10: Stores little/big endian offset for vectors
-	 * r2: Stores imm opcode
-	 * r3: Stores brai opcode
-	 */
-
 	mts	rmsr, r0	/* disable cache */
 
 	addi	r8, r0, __end
 	mts	rslr, r8
-	/* TODO: Redo this code to call board_init_f_*() */
+
 #if defined(CONFIG_SPL_BUILD)
 	addi	r1, r0, CONFIG_SPL_STACK_ADDR
-	mts	rshr, r1
-	addi	r1, r1, -4	/* Decrement SP to top of memory */
-#else
-#if CONFIG_VAL(SYS_MALLOC_F_LEN)
-	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN)
 #else
 	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
 #endif
-	mts	rshr, r1
+
 	addi	r1, r1, -4	/* Decrement SP to top of memory */
 
+	/* Call board_init_f_alloc_reserve with the current stack pointer as
+	 * parameter. */
+	add	r5, r0, r1
+	bralid	r15, board_init_f_alloc_reserve
+	nop
+
+	/* board_init_f_alloc_reserve returns a pointer to the allocated area
+	 * in r3. Set the new stack pointer below this area. */
+	add	r1, r0, r3
+	mts	rshr, r1
+	addi	r1, r1, -4
+
+	/* Call board_init_f_init_reserve with the address returned by
+	 * board_init_f_alloc_reserve as parameter. */
+	add	r5, r0, r3
+	bralid	r15, board_init_f_init_reserve
+	nop
+
+#if !defined(CONFIG_SPL_BUILD)
+	/* Setup vectors with pre-relocation symbols */
+	or	r5, r0, r0
+	bralid	r15, __setup_exceptions
+	nop
+#endif
+
+	/* Flush cache before enable cache */
+	addik	r5, r0, 0
+	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
+	bralid	r15, flush_cache
+	nop
+
+	/* enable instruction and data cache */
+	mfs	r12, rmsr
+	ori	r12, r12, 0x1a0
+	mts	rmsr, r12
+
+clear_bss:
+	/* clear BSS segments */
+	addi	r5, r0, __bss_start
+	addi	r4, r0, __bss_end
+	cmp	r6, r5, r4
+	beqi	r6, 3f
+2:
+	swi     r0, r5, 0 /* write zero to loc */
+	addi    r5, r5, 4 /* increment to next loc */
+	cmp     r6, r5, r4 /* check if we have reach the end */
+	bnei    r6, 2b
+3:	/* jumping to board_init */
+#ifdef CONFIG_DEBUG_UART
+	bralid	r15, debug_uart_init
+	nop
+#endif
+#ifndef CONFIG_SPL_BUILD
+	or	r5, r0, r0	/* flags - empty */
+	brai	board_init_f
+#else
+	brai	board_init_r
+#endif
+1:	bri	1b
+
+#ifndef CONFIG_SPL_BUILD
+	.text
+	.ent	__setup_exceptions
+	.align	2
+/*
+ * Set up reset, interrupt, user exception and hardware exception vectors.
+ *
+ * Parameters:
+ * r5 - relocation offset (zero when setting up vectors before
+ *      relocation, and gd->reloc_off when setting up vectors after
+ *      relocation)
+ *    - the relocation offset is added to the _exception_handler,
+ *      _interrupt_handler and _hw_exception_handler symbols to reflect the
+ *      post-relocation memory addresses
+ *
+ * Reserve registers:
+ * r10: Stores little/big endian offset for vectors
+ * r2: Stores imm opcode
+ * r3: Stores brai opcode
+ */
+__setup_exceptions:
+	addik	r1, r1, -28
+	swi	r2, r1, 4
+	swi	r3, r1, 8
+	swi	r6, r1, 12
+	swi	r7, r1, 16
+	swi	r8, r1, 20
+	swi	r10, r1, 24
+
 	/* Find-out if u-boot is running on BIG/LITTLE endian platform
 	 * There are some steps which is necessary to keep in mind:
 	 * 1. Setup offset value to r6
@@ -76,7 +153,7 @@
 	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
 	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
 
-	addik	r6, r0, _exception_handler
+	addik	r6, r5, _exception_handler
 	sw	r6, r1, r0
 	/*
 	 * BIG ENDIAN memory map for user exception
@@ -109,7 +186,7 @@
 	swi	r2, r0, 0x10	/* interrupt - imm opcode */
 	swi	r3, r0, 0x14	/* interrupt - brai opcode */
 
-	addik	r6, r0, _interrupt_handler
+	addik	r6, r5, _interrupt_handler
 	sw	r6, r1, r0
 	lhu	r7, r1, r10
 	rsubi	r8, r10, 0x12
@@ -121,67 +198,26 @@
 	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
 	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
 
-	addik	r6, r0, _hw_exception_handler
+	addik	r6, r5, _hw_exception_handler
 	sw	r6, r1, r0
 	lhu	r7, r1, r10
 	rsubi	r8, r10, 0x22
 	sh	r7, r0, r8
 	rsubi	r8, r10, 0x26
 	sh	r6, r0, r8
-#endif /* CONFIG_SPL_BUILD */
 
-	/* Flush cache before enable cache */
-	addik	r5, r0, 0
-	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
-	bralid r15, flush_cache
-	nop
+	lwi	r10, r1, 24
+	lwi	r8, r1, 20
+	lwi	r7, r1, 16
+	lwi	r6, r1, 12
+	lwi	r3, r1, 8
+	lwi	r2, r1, 4
+	addik	r1, r1, 28
 
-	/* enable instruction and data cache */
-	mfs	r12, rmsr
-	ori	r12, r12, 0x1a0
-	mts	rmsr, r12
-
-	/* TODO: Redo this code to call board_init_f_*() */
-clear_bss:
-	/* clear BSS segments */
-	addi	r5, r0, __bss_start
-	addi	r4, r0, __bss_end
-	cmp	r6, r5, r4
-	beqi	r6, 3f
-2:
-	swi     r0, r5, 0 /* write zero to loc */
-	addi    r5, r5, 4 /* increment to next loc */
-	cmp     r6, r5, r4 /* check if we have reach the end */
-	bnei    r6, 2b
-3:	/* jumping to board_init */
-#ifdef CONFIG_DEBUG_UART
-	bralid	r15, debug_uart_init
-	nop
-#endif
-#ifndef CONFIG_SPL_BUILD
-	or	r5, r0, r0	/* flags - empty */
-	addi    r31, r0, _gd
-#if CONFIG_VAL(SYS_MALLOC_F_LEN)
-	addi	r6, r0, CONFIG_SYS_INIT_SP_OFFSET
-	swi	r6, r31, GD_MALLOC_BASE
-#endif
-	brai	board_init_f
-#else
-	addi	r31, r0, _gd
-#if CONFIG_VAL(SYS_MALLOC_F_LEN)
-	addi	r6, r0, CONFIG_SPL_STACK_ADDR
-	swi	r6, r31, GD_MALLOC_BASE
-#endif
-	brai	board_init_r
-#endif
-1:	bri	1b
-
- .section .bss
-.align 4
-_gd:
-         .space  GENERATED_GBL_DATA_SIZE
+	rtsd	r15, 8
+	or	r0, r0, r0
+	.end	__setup_exceptions
 
-#ifndef CONFIG_SPL_BUILD
 /*
  * Read 16bit little endian
  */
@@ -249,39 +285,10 @@
 	addi	r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
 	rsub	r23, r24, r23 /* keep - this is already here gd->reloc_off */
 
-	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
-	lwi	r7, r0, 0x28
-	swi	r6, r0, 0x28 /* used first unused MB vector */
-	lbui	r10, r0, 0x28 /* used first unused MB vector */
-	swi	r7, r0, 0x28
-
-#ifdef CONFIG_SYS_USR_EXCEP
-	addik	r6, r0, _exception_handler
-	addk	r6, r6, r23 /* add offset */
-	sw	r6, r1, r0
-	lhu	r7, r1, r10
-	rsubi	r8, r10, 0xa
-	sh	r7, r0, r8
-	rsubi	r8, r10, 0xe
-	sh	r6, r0, r8
-#endif
-	addik	r6, r0, _hw_exception_handler
-	addk	r6, r6, r23 /* add offset */
-	sw	r6, r1, r0
-	lhu	r7, r1, r10
-	rsubi	r8, r10, 0x22
-	sh	r7, r0, r8
-	rsubi	r8, r10, 0x26
-	sh	r6, r0, r8
-
-	addik	r6, r0, _interrupt_handler
-	addk	r6, r6, r23 /* add offset */
-	sw	r6, r1, r0
-	lhu	r7, r1, r10
-	rsubi	r8, r10, 0x12
-	sh	r7, r0, r8
-	rsubi	r8, r10, 0x16
-	sh	r6, r0, r8
+	/* Setup vectors with post-relocation symbols */
+	add	r5, r0, r23 /* load gd->reloc_off to r5 */
+	bralid	r15, __setup_exceptions
+	nop
 
 	/* Check if GOT exist */
 	addik	r21, r23, _got_start
diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig
index c80d0a8..64507b5 100644
--- a/board/xilinx/Kconfig
+++ b/board/xilinx/Kconfig
@@ -50,9 +50,34 @@
 
 config BOOT_SCRIPT_OFFSET
 	hex "Boot script offset"
-	depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL
-	default 0xFC0000 if ARCH_ZYNQ
+	depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || MICROBLAZE
+	default 0xFC0000 if ARCH_ZYNQ || MICROBLAZE
 	default 0x3E80000 if ARCH_ZYNQMP
 	default 0x7F80000 if ARCH_VERSAL
 	help
-	   Specifies distro boot script offset in NAND/NOR flash.
+	   Specifies distro boot script offset in NAND/QSPI/NOR flash.
+
+config ZYNQ_MAC_IN_EEPROM
+	bool "Reading MAC address from EEPROM"
+	help
+	  Enable this option if your MAC address is saved in eeprom and
+	  xlnx,eeprom DT property in chosen node points to it.
+
+if ZYNQ_MAC_IN_EEPROM
+
+config ZYNQ_GEM_I2C_MAC_OFFSET
+	hex "Set the I2C MAC offset"
+	default 0x0
+	depends on DM_I2C
+	help
+	  Set the MAC offset for i2C.
+
+endif
+
+config CMD_FRU
+	bool "FRU information for product"
+	help
+	  This option enables FRU commands to capture and display FRU
+	  information present in the device. The FRU Information is used
+	  to primarily to provide "inventory" information about the boards
+	  that the FRU Information Device is located on.
diff --git a/board/xilinx/common/Makefile b/board/xilinx/common/Makefile
new file mode 100644
index 0000000..2120284
--- /dev/null
+++ b/board/xilinx/common/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# (C) Copyright 2020 Xilinx, Inc.
+# Michal Simek <michal.simek@xilinx.com>
+#
+
+obj-y	+= board.o
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o
+endif
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index b0f60c4..cdc06a3 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * (C) Copyright 2014 - 2019 Xilinx, Inc.
+ * (C) Copyright 2014 - 2020 Xilinx, Inc.
  * Michal Simek <michal.simek@xilinx.com>
  */
 
@@ -11,7 +11,14 @@
 #include <dm/uclass.h>
 #include <i2c.h>
 #include <linux/sizes.h>
+#include <malloc.h>
 #include "board.h"
+#include <dm.h>
+#include <i2c_eeprom.h>
+#include <net.h>
+#include <generated/dt.h>
+
+#include "fru.h"
 
 #if defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET)
 int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
@@ -41,6 +48,277 @@
 }
 #endif
 
+#define EEPROM_HEADER_MAGIC		0xdaaddeed
+#define EEPROM_HDR_MANUFACTURER_LEN	16
+#define EEPROM_HDR_NAME_LEN		16
+#define EEPROM_HDR_REV_LEN		8
+#define EEPROM_HDR_SERIAL_LEN		20
+#define EEPROM_HDR_NO_OF_MAC_ADDR	4
+#define EEPROM_HDR_ETH_ALEN		ETH_ALEN
+
+struct xilinx_board_description {
+	u32 header;
+	char manufacturer[EEPROM_HDR_MANUFACTURER_LEN + 1];
+	char name[EEPROM_HDR_NAME_LEN + 1];
+	char revision[EEPROM_HDR_REV_LEN + 1];
+	char serial[EEPROM_HDR_SERIAL_LEN + 1];
+	u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1];
+};
+
+static int highest_id = -1;
+static struct xilinx_board_description **board_info;
+
+#define XILINX_I2C_DETECTION_BITS	sizeof(struct fru_common_hdr)
+
+/* Variable which stores pointer to array which stores eeprom content */
+struct xilinx_legacy_format {
+	char board_sn[18]; /* 0x0 */
+	char unused0[14]; /* 0x12 */
+	char eth_mac[6]; /* 0x20 */
+	char unused1[170]; /* 0x26 */
+	char board_name[11]; /* 0xd0 */
+	char unused2[5]; /* 0xdc */
+	char board_revision[3]; /* 0xe0 */
+	char unused3[29]; /* 0xe3 */
+};
+
+static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
+{
+	int i;
+	char byte;
+
+	for (i = 0; i < size; i++) {
+		byte = eeprom[i];
+
+		/* Remove all ffs and spaces */
+		if (byte == 0xff || byte == ' ')
+			eeprom[i] = 0;
+
+		/* Convert strings to lower case */
+		if (byte >= 'A' && byte <= 'Z')
+			eeprom[i] = byte + 'a' - 'A';
+	}
+}
+
+static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name,
+				     struct xilinx_board_description *desc)
+{
+	int ret, size;
+	struct xilinx_legacy_format *eeprom_content;
+	bool eth_valid = false;
+
+	size = sizeof(*eeprom_content);
+
+	eeprom_content = calloc(1, size);
+	if (!eeprom_content)
+		return -ENOMEM;
+
+	debug("%s: I2C EEPROM read pass data at %p\n", __func__,
+	      eeprom_content);
+
+	ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size);
+	if (ret) {
+		debug("%s: I2C EEPROM read failed\n", __func__);
+		free(eeprom_content);
+		return ret;
+	}
+
+	xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size);
+
+	printf("Xilinx I2C Legacy format at %s:\n", name);
+	printf(" Board name:\t%s\n", eeprom_content->board_name);
+	printf(" Board rev:\t%s\n", eeprom_content->board_revision);
+	printf(" Board SN:\t%s\n", eeprom_content->board_sn);
+
+	eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac);
+	if (eth_valid)
+		printf(" Ethernet mac:\t%pM\n", eeprom_content->eth_mac);
+
+	/* Terminating \0 chars ensure end of string */
+	strcpy(desc->name, eeprom_content->board_name);
+	strcpy(desc->revision, eeprom_content->board_revision);
+	strcpy(desc->serial, eeprom_content->board_sn);
+	if (eth_valid)
+		memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN);
+
+	desc->header = EEPROM_HEADER_MAGIC;
+
+	free(eeprom_content);
+
+	return ret;
+}
+
+static bool xilinx_detect_legacy(u8 *buffer)
+{
+	int i;
+	char c;
+
+	for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) {
+		c = buffer[i];
+
+		if (c < '0' || c > '9')
+			return false;
+	}
+
+	return true;
+}
+
+static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
+				  struct xilinx_board_description *desc)
+{
+	int ret, eeprom_size;
+	u8 *fru_content;
+
+	/* FIXME this is shortcut - if eeprom type is wrong it will fail */
+	eeprom_size = i2c_eeprom_size(dev);
+
+	fru_content = calloc(1, eeprom_size);
+	if (!fru_content)
+		return -ENOMEM;
+
+	debug("%s: I2C EEPROM read pass data at %p\n", __func__,
+	      fru_content);
+
+	ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
+			  eeprom_size);
+	if (ret) {
+		debug("%s: I2C EEPROM read failed\n", __func__);
+		free(fru_content);
+		return ret;
+	}
+
+	printf("Xilinx I2C FRU format at %s:\n", name);
+	fru_capture((unsigned long)fru_content);
+	ret = fru_display(0);
+	if (ret) {
+		printf("FRU format decoding failed.\n");
+		return ret;
+	}
+
+	if (desc->header == EEPROM_HEADER_MAGIC) {
+		debug("Information already filled\n");
+		return -EINVAL;
+	}
+
+	/* It is clear that FRU was captured and structures were filled */
+	strncpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
+		sizeof(desc->manufacturer));
+	strncpy(desc->name, (char *)fru_data.brd.product_name,
+		sizeof(desc->name));
+	strncpy(desc->revision, (char *)fru_data.brd.rev,
+		sizeof(desc->revision));
+	strncpy(desc->serial, (char *)fru_data.brd.serial_number,
+		sizeof(desc->serial));
+	desc->header = EEPROM_HEADER_MAGIC;
+
+	return 0;
+}
+
+static bool xilinx_detect_fru(u8 *buffer)
+{
+	u8 checksum = 0;
+	int i;
+
+	checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
+	if (checksum) {
+		debug("%s Common header CRC FAIL\n", __func__);
+		return false;
+	}
+
+	bool all_zeros = true;
+	/* Checksum over all zeros is also zero that's why detect this case */
+	for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
+		if (buffer[i] != 0)
+			all_zeros = false;
+	}
+
+	if (all_zeros)
+		return false;
+
+	debug("%s Common header CRC PASS\n", __func__);
+	return true;
+}
+
+static int xilinx_read_eeprom_single(char *name,
+				     struct xilinx_board_description *desc)
+{
+	int ret;
+	struct udevice *dev;
+	ofnode eeprom;
+	u8 buffer[XILINX_I2C_DETECTION_BITS];
+
+	eeprom = ofnode_get_aliases_node(name);
+	if (!ofnode_valid(eeprom))
+		return -ENODEV;
+
+	ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
+	if (ret)
+		return ret;
+
+	ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer));
+	if (ret) {
+		debug("%s: I2C EEPROM read failed\n", __func__);
+		return ret;
+	}
+
+	debug("%s: i2c memory detected: %s\n", __func__, name);
+
+	if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer))
+		return xilinx_read_eeprom_fru(dev, name, desc);
+
+	if (xilinx_detect_legacy(buffer))
+		return xilinx_read_eeprom_legacy(dev, name, desc);
+
+	return -ENODEV;
+}
+
+__maybe_unused int xilinx_read_eeprom(void)
+{
+	int id, ret;
+	char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
+	struct xilinx_board_description *desc;
+
+	highest_id = dev_read_alias_highest_id("nvmem");
+	/* No nvmem aliases present */
+	if (highest_id < 0)
+		return -EINVAL;
+
+	board_info = calloc(1, sizeof(desc) * highest_id);
+	if (!board_info)
+		return -ENOMEM;
+
+	debug("%s: Highest ID %d, board_info %p\n", __func__,
+	      highest_id, board_info);
+
+	for (id = 0; id <= highest_id; id++) {
+		snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
+
+		/* Alloc structure */
+		desc = board_info[id];
+		if (!desc) {
+			desc = calloc(1, sizeof(*desc));
+			if (!desc)
+				return -ENOMEM;
+
+			board_info[id] = desc;
+		}
+
+		/* Ignoring return value for supporting multiple chips */
+		ret = xilinx_read_eeprom_single(name_buf, desc);
+		if (ret) {
+			free(desc);
+			board_info[id] = NULL;
+		}
+	}
+
+	/*
+	 * Consider to clean board_info structure when board/cards are not
+	 * detected.
+	 */
+
+	return 0;
+}
+
 #if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
 void *board_fdt_blob_setup(void)
 {
@@ -75,12 +353,36 @@
 }
 #endif
 
+#if defined(CONFIG_BOARD_LATE_INIT)
+static int env_set_by_index(const char *name, int index, char *data)
+{
+	char var[32];
+
+	if (!index)
+		sprintf(var, "board_%s", name);
+	else
+		sprintf(var, "card%d_%s", index, name);
+
+	return env_set(var, data);
+}
+
 int board_late_init_xilinx(void)
 {
 	u32 ret = 0;
+	int i, id, macid = 0;
+	struct xilinx_board_description *desc;
 	phys_size_t bootm_size = gd->ram_size;
+	struct bd_info *bd = gd->bd;
+
+	if (!CONFIG_IS_ENABLED(MICROBLAZE) && bd->bi_dram[0].start) {
+		ulong scriptaddr;
 
-	if (CONFIG_IS_ENABLED(ARCH_ZYNQ))
+		scriptaddr = env_get_hex("scriptaddr", 0);
+		ret |= env_set_hex("scriptaddr",
+				   bd->bi_dram[0].start + scriptaddr);
+	}
+
+	if (CONFIG_IS_ENABLED(ARCH_ZYNQ) || CONFIG_IS_ENABLED(MICROBLAZE))
 		bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M));
 
 	ret |= env_set_hex("script_offset_f", CONFIG_BOOT_SCRIPT_OFFSET);
@@ -88,8 +390,49 @@
 	ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
 	ret |= env_set_addr("bootm_size", (void *)bootm_size);
 
+	for (id = 0; id <= highest_id; id++) {
+		desc = board_info[id];
+		if (desc && desc->header == EEPROM_HEADER_MAGIC) {
+			if (desc->manufacturer[0])
+				ret |= env_set_by_index("manufacturer", id,
+							desc->manufacturer);
+			if (desc->name[0])
+				ret |= env_set_by_index("name", id,
+							desc->name);
+			if (desc->revision[0])
+				ret |= env_set_by_index("rev", id,
+							desc->revision);
+			if (desc->serial[0])
+				ret |= env_set_by_index("serial", id,
+							desc->serial);
+
+			if (!CONFIG_IS_ENABLED(NET))
+				continue;
+
+			for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
+				if (!desc->mac_addr[i])
+					continue;
+
+				if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
+					ret |= eth_env_set_enetaddr_by_index("eth",
+							macid++, desc->mac_addr[i]);
+			}
+		}
+	}
+
 	if (ret)
 		printf("%s: Saving run time variables FAILED\n", __func__);
 
 	return 0;
 }
+#endif
+
+int __maybe_unused board_fit_config_name_match(const char *name)
+{
+	debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE);
+
+	if (!strcmp(name, DEVICE_TREE))
+		return 0;
+
+	return -1;
+}
diff --git a/board/xilinx/common/board.h b/board/xilinx/common/board.h
index 180dfbc..69e6424 100644
--- a/board/xilinx/common/board.h
+++ b/board/xilinx/common/board.h
@@ -9,4 +9,6 @@
 
 int board_late_init_xilinx(void);
 
+int xilinx_read_eeprom(void);
+
 #endif /* BOARD_XILINX_COMMON_BOARD_H */
diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c
new file mode 100644
index 0000000..ccf4872
--- /dev/null
+++ b/board/xilinx/common/fru.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 - 2020 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fdtdec.h>
+#include <malloc.h>
+
+#include "fru.h"
+
+static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	unsigned long addr;
+	char *endp;
+
+	if (argc < cmdtp->maxargs)
+		return CMD_RET_USAGE;
+
+	addr = simple_strtoul(argv[2], &endp, 16);
+	if (*argv[1] == 0 || *endp != 0)
+		return -1;
+
+	return fru_capture(addr);
+}
+
+static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	fru_display(1);
+	return CMD_RET_SUCCESS;
+}
+
+static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc,
+			   char *const argv[])
+{
+	unsigned long addr;
+
+	if (argc < cmdtp->maxargs)
+		return CMD_RET_USAGE;
+
+	addr = simple_strtoul(argv[2], NULL, 16);
+
+	return fru_generate(addr, argv[3], argv[4], argv[5], argv[6], argv[7]);
+}
+
+static struct cmd_tbl cmd_fru_sub[] = {
+	U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""),
+	U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""),
+	U_BOOT_CMD_MKENT(board_gen, 8, 0, do_fru_generate, "", ""),
+};
+
+static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc,
+		  char *const argv[])
+{
+	struct cmd_tbl *c;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	c = find_cmd_tbl(argv[1], &cmd_fru_sub[0],
+			 ARRAY_SIZE(cmd_fru_sub));
+	if (!c)
+		return CMD_RET_USAGE;
+
+	ret = c->cmd(c, flag, argc, argv);
+
+	return cmd_process_error(c, ret);
+}
+
+/***************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char fru_help_text[] =
+	"capture <addr> - Parse and capture FRU table present at address.\n"
+	"fru display - Displays content of FRU table that was captured using\n"
+	"              fru capture command\n"
+	"fru board_gen <addr> <manufacturer> <board name> <serial number>\n"
+	"              <part number> <revision> - Generate FRU format with\n"
+	"              board info area filled based on parameters. <addr> is\n"
+	"              pointing to place where FRU is generated.\n"
+	;
+#endif
+
+U_BOOT_CMD(
+	fru, 8, 1, do_fru,
+	"FRU table info",
+	fru_help_text
+)
diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h
new file mode 100644
index 0000000..a3e6520
--- /dev/null
+++ b/board/xilinx/common/fru.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Xilinx, Inc.
+ * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
+ */
+
+#ifndef __FRU_H
+#define __FRU_H
+
+struct fru_common_hdr {
+	u8 version;
+	u8 off_internal;
+	u8 off_chassis;
+	u8 off_board;
+	u8 off_product;
+	u8 off_multirec;
+	u8 pad;
+	u8 crc;
+};
+
+#define FRU_BOARD_MAX_LEN	32
+
+struct __packed fru_board_info_header {
+	u8 ver;
+	u8 len;
+	u8 lang_code;
+	u8 time[3];
+};
+
+struct __packed fru_board_info_member {
+	u8 type_len;
+	u8 *name;
+};
+
+struct fru_board_data {
+	u8 ver;
+	u8 len;
+	u8 lang_code;
+	u8 time[3];
+	u8 manufacturer_type_len;
+	u8 manufacturer_name[FRU_BOARD_MAX_LEN];
+	u8 product_name_type_len;
+	u8 product_name[FRU_BOARD_MAX_LEN];
+	u8 serial_number_type_len;
+	u8 serial_number[FRU_BOARD_MAX_LEN];
+	u8 part_number_type_len;
+	u8 part_number[FRU_BOARD_MAX_LEN];
+	u8 file_id_type_len;
+	u8 file_id[FRU_BOARD_MAX_LEN];
+	/* Xilinx custom fields */
+	u8 rev_type_len;
+	u8 rev[FRU_BOARD_MAX_LEN];
+};
+
+struct fru_table {
+	bool captured;
+	struct fru_common_hdr hdr;
+	struct fru_board_data brd;
+};
+
+#define FRU_TYPELEN_CODE_MASK	0xC0
+#define FRU_TYPELEN_LEN_MASK	0x3F
+#define FRU_COMMON_HDR_VER_MASK		0xF
+#define FRU_COMMON_HDR_LEN_MULTIPLIER	8
+#define FRU_LANG_CODE_ENGLISH		0
+#define FRU_LANG_CODE_ENGLISH_1		25
+#define FRU_TYPELEN_EOF			0xC1
+
+/* This should be minimum of fields */
+#define FRU_BOARD_AREA_TOTAL_FIELDS	5
+#define FRU_TYPELEN_TYPE_SHIFT		6
+#define FRU_TYPELEN_TYPE_BINARY		0
+#define FRU_TYPELEN_TYPE_ASCII8		3
+
+int fru_display(int verbose);
+int fru_capture(unsigned long addr);
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+		 char *serial_no, char *part_no, char *revision);
+u8 fru_checksum(u8 *addr, u8 len);
+
+extern struct fru_table fru_data;
+
+#endif /* FRU_H */
diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c
new file mode 100644
index 0000000..fc3add7
--- /dev/null
+++ b/board/xilinx/common/fru_ops.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 - 2020 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <env.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#include "fru.h"
+
+struct fru_table fru_data __section(.data);
+
+static u16 fru_cal_area_len(u8 len)
+{
+	return len * FRU_COMMON_HDR_LEN_MULTIPLIER;
+}
+
+static u8 fru_version(u8 ver)
+{
+	return ver & FRU_COMMON_HDR_VER_MASK;
+}
+
+static int fru_check_language(u8 code)
+{
+	if (code != FRU_LANG_CODE_ENGLISH && code != FRU_LANG_CODE_ENGLISH_1) {
+		printf("FRU_ERROR: Only English Language is supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+u8 fru_checksum(u8 *addr, u8 len)
+{
+	u8 checksum = 0;
+
+	while (len--) {
+		checksum += *addr;
+		addr++;
+	}
+
+	return checksum;
+}
+
+static int fru_check_type_len(u8 type_len, u8 language, u8 *type)
+{
+	int len;
+
+	if (type_len == FRU_TYPELEN_EOF)
+		return -EINVAL;
+
+	*type = (type_len & FRU_TYPELEN_CODE_MASK) >> FRU_TYPELEN_TYPE_SHIFT;
+
+	len = type_len & FRU_TYPELEN_LEN_MASK;
+
+	return len;
+}
+
+/* Return len */
+static u8 fru_gen_type_len(u8 *addr, char *name)
+{
+	int len = strlen(name);
+	struct fru_board_info_member *member;
+
+	member = (struct fru_board_info_member *)addr;
+	member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT;
+	member->type_len |= len;
+
+	debug("%lx/%lx: Add %s to 0x%lx (len 0x%x)\n", (ulong)addr,
+	      (ulong)&member->type_len,  name, (ulong)&member->name, len);
+	memcpy(&member->name, name, len);
+
+	/* Add +1 for type_len parameter */
+	return 1 + len;
+}
+
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+		 char *serial_no, char *part_no, char *revision)
+{
+	struct fru_common_hdr *header = (struct fru_common_hdr *)addr;
+	struct fru_board_info_header *board_info;
+	u8 *member;
+	u8 len, pad, modulo;
+
+	header->version = 1; /* Only version 1.0 is supported now */
+	header->off_internal = 0; /* not present */
+	header->off_chassis = 0; /* not present */
+	header->off_board = (sizeof(*header)) / 8; /* Starting offset 8 */
+	header->off_product = 0; /* not present */
+	header->off_multirec = 0; /* not present */
+	header->pad = 0;
+	/*
+	 * This unsigned byte can be used to calculate a zero checksum
+	 * for the data area following the header. I.e. the modulo 256 sum of
+	 * the record data bytes plus the checksum byte equals zero.
+	 */
+	header->crc = 0; /* Clear before calculation */
+	header->crc = 0 - fru_checksum((u8 *)header, sizeof(*header));
+
+	/* board info is just right after header */
+	board_info = (void *)((u8 *)header + sizeof(*header));
+
+	debug("header %lx, board_info %lx\n", (ulong)header, (ulong)board_info);
+
+	board_info->ver = 1; /* 1.0 spec */
+	board_info->lang_code = 0; /* English */
+	board_info->time[0] = 0; /* unspecified */
+	board_info->time[1] = 0; /* unspecified */
+	board_info->time[2] = 0; /* unspecified */
+
+	/* Member fields are just after board_info header */
+	member = (u8 *)board_info + sizeof(*board_info);
+
+	len = fru_gen_type_len(member, manufacturer); /* Board Manufacturer */
+	member += len;
+	len = fru_gen_type_len(member, board_name); /* Board Product name */
+	member += len;
+	len = fru_gen_type_len(member, serial_no); /* Board Serial number */
+	member += len;
+	len = fru_gen_type_len(member, part_no); /* Board part number */
+	member += len;
+	len = fru_gen_type_len(member, "U-Boot generator"); /* File ID */
+	member += len;
+	len = fru_gen_type_len(member, revision); /* Revision */
+	member += len;
+
+	*member++ = 0xc1; /* Indication of no more fields */
+
+	len = member - (u8 *)board_info; /* Find current length */
+	len += 1; /* Add checksum there too for calculation */
+
+	modulo = len % 8;
+
+	if (modulo) {
+		/* Do not fill last item which is checksum */
+		for (pad = 0; pad < 8 - modulo; pad++)
+			*member++ = 0;
+
+		/* Increase structure size */
+		len += 8 - modulo;
+	}
+
+	board_info->len = len / 8; /* Size in multiples of 8 bytes */
+
+	*member = 0; /* Clear before calculation */
+	*member = 0 - fru_checksum((u8 *)board_info, len);
+
+	debug("checksum %x(addr %x)\n", *member, len);
+
+	env_set_hex("fru_addr", addr);
+	env_set_hex("filesize", (unsigned long)member - addr + 1);
+
+	return 0;
+}
+
+static int fru_parse_board(unsigned long addr)
+{
+	u8 i, type;
+	int len;
+	u8 *data, *term;
+
+	memcpy(&fru_data.brd.ver, (void *)addr, 6);
+	addr += 6;
+	data = (u8 *)&fru_data.brd.manufacturer_type_len;
+
+	for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) {
+		len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code,
+					 &type);
+		/*
+		 * Stop cature if it end of fields
+		 */
+		if (len == -EINVAL)
+			break;
+
+		/* This record type/len field */
+		*data++ = *(u8 *)addr;
+
+		/* Add offset to match data */
+		addr += 1;
+
+		/* If len is 0 it means empty field that's why skip writing */
+		if (!len)
+			continue;
+
+		/* Record data field */
+		memcpy(data, (u8 *)addr, len);
+		term = data + (u8)len;
+		*term = 0;
+		addr += len;
+	}
+
+	if (i < FRU_BOARD_AREA_TOTAL_FIELDS) {
+		printf("Board area require minimum %d fields\n",
+		       FRU_BOARD_AREA_TOTAL_FIELDS);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int fru_capture(unsigned long addr)
+{
+	struct fru_common_hdr *hdr;
+	u8 checksum = 0;
+
+	checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr));
+	if (checksum) {
+		printf("%s Common header CRC error\n", __func__);
+		return -EINVAL;
+	}
+
+	hdr = (struct fru_common_hdr *)addr;
+
+	memcpy((void *)&fru_data.hdr, (void *)hdr,
+	       sizeof(struct fru_common_hdr));
+
+	fru_data.captured = true;
+
+	if (hdr->off_board) {
+		addr += fru_cal_area_len(hdr->off_board);
+		fru_parse_board(addr);
+	}
+
+	env_set_hex("fru_addr", addr);
+
+	return 0;
+}
+
+static int fru_display_board(struct fru_board_data *brd, int verbose)
+{
+	u32 time = 0;
+	u8 type;
+	int len;
+	u8 *data;
+	static const char * const typecode[] = {
+		"Binary/Unspecified",
+		"BCD plus",
+		"6-bit ASCII",
+		"8-bit ASCII",
+		"2-byte UNICODE"
+	};
+	static const char * const boardinfo[] = {
+		"Manufacturer Name",
+		"Product Name",
+		"Serial No",
+		"Part Number",
+		"File ID",
+		/* Xilinx spec */
+		"Revision Number",
+	};
+
+	if (verbose) {
+		printf("*****BOARD INFO*****\n");
+		printf("Version:%d\n", fru_version(brd->ver));
+		printf("Board Area Length:%d\n", fru_cal_area_len(brd->len));
+	}
+
+	if (fru_check_language(brd->lang_code))
+		return -EINVAL;
+
+	time = brd->time[2] << 16 | brd->time[1] << 8 |
+	       brd->time[0];
+
+	if (verbose)
+		printf("Time in Minutes from 0:00hrs 1/1/96: %d\n", time);
+
+	data = (u8 *)&brd->manufacturer_type_len;
+
+	for (u8 i = 0; i < (sizeof(boardinfo) / sizeof(*boardinfo)); i++) {
+		len = fru_check_type_len(*data++, brd->lang_code,
+					 &type);
+		if (len == -EINVAL) {
+			printf("**** EOF for Board Area ****\n");
+			break;
+		}
+
+		if (type <= FRU_TYPELEN_TYPE_ASCII8 &&
+		    (brd->lang_code == FRU_LANG_CODE_ENGLISH ||
+		     brd->lang_code == FRU_LANG_CODE_ENGLISH_1))
+			debug("Type code: %s\n", typecode[type]);
+		else
+			debug("Type code: %s\n", typecode[type + 1]);
+
+		if (!len) {
+			debug("%s not found\n", boardinfo[i]);
+			continue;
+		}
+
+		switch (type) {
+		case FRU_TYPELEN_TYPE_BINARY:
+			debug("Length: %d\n", len);
+			printf(" %s: 0x%x\n", boardinfo[i], *data);
+			break;
+		case FRU_TYPELEN_TYPE_ASCII8:
+			debug("Length: %d\n", len);
+			printf(" %s: %s\n", boardinfo[i], data);
+			break;
+		default:
+			debug("Unsupported type %x\n", type);
+		}
+
+		data += FRU_BOARD_MAX_LEN;
+	}
+
+	return 0;
+}
+
+static void fru_display_common_hdr(struct fru_common_hdr *hdr, int verbose)
+{
+	if (!verbose)
+		return;
+
+	printf("*****COMMON HEADER*****\n");
+	printf("Version:%d\n", fru_version(hdr->version));
+	if (hdr->off_internal)
+		printf("Internal Use Area Offset:%d\n",
+		       fru_cal_area_len(hdr->off_internal));
+	else
+		printf("*** No Internal Area ***\n");
+
+	if (hdr->off_chassis)
+		printf("Chassis Info Area Offset:%d\n",
+		       fru_cal_area_len(hdr->off_chassis));
+	else
+		printf("*** No Chassis Info Area ***\n");
+
+	if (hdr->off_board)
+		printf("Board Area Offset:%d\n",
+		       fru_cal_area_len(hdr->off_board));
+	else
+		printf("*** No Board Area ***\n");
+
+	if (hdr->off_product)
+		printf("Product Info Area Offset:%d\n",
+		       fru_cal_area_len(hdr->off_product));
+	else
+		printf("*** No Product Info Area ***\n");
+
+	if (hdr->off_multirec)
+		printf("MultiRecord Area Offset:%d\n",
+		       fru_cal_area_len(hdr->off_multirec));
+	else
+		printf("*** No MultiRecord Area ***\n");
+}
+
+int fru_display(int verbose)
+{
+	if (!fru_data.captured) {
+		printf("FRU data not available please run fru parse\n");
+		return -EINVAL;
+	}
+
+	fru_display_common_hdr(&fru_data.hdr, verbose);
+
+	return fru_display_board(&fru_data.brd, verbose);
+}
diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c
index 4e569e9..e590999 100644
--- a/board/xilinx/microblaze-generic/microblaze-generic.c
+++ b/board/xilinx/microblaze-generic/microblaze-generic.c
@@ -18,6 +18,7 @@
 #include <dm/lists.h>
 #include <fdtdec.h>
 #include <linux/sizes.h>
+#include "../common/board.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -36,7 +37,8 @@
 
 int board_late_init(void)
 {
-	ulong max_size, lowmem_size;
+	ulong max_size;
+	u32 status = 0;
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SYSRESET_MICROBLAZE)
 	int ret;
@@ -55,12 +57,19 @@
 	max_size = gd->start_addr_sp - CONFIG_STACK_SIZE;
 	max_size = round_down(max_size, SZ_16M);
 
-	/* Linux default LOWMEM_SIZE is 0x30000000 = 768MB */
-	lowmem_size = gd->ram_base + 768 * 1024 * 1024;
+	status |= env_set_hex("scriptaddr", max_size + SZ_2M);
 
-	env_set_addr("initrd_high", (void *)min_t(ulong, max_size,
-						  lowmem_size));
-	env_set_addr("fdt_high", (void *)min_t(ulong, max_size, lowmem_size));
+	status |= env_set_hex("pxefile_addr_r", max_size + SZ_1M);
 
-	return 0;
+	status |= env_set_hex("kernel_addr_r", gd->ram_base + SZ_32M);
+
+	status |= env_set_hex("fdt_addr_r", gd->ram_base + SZ_32M - SZ_1M);
+
+	status |= env_set_hex("ramdisk_addr_r",
+			       gd->ram_base + SZ_32M + SZ_4M + SZ_2M);
+
+	if (status)
+		printf("%s: Saving run time variables FAILED\n", __func__);
+
+	return board_late_init_xilinx();
 }
diff --git a/board/xilinx/versal/Makefile b/board/xilinx/versal/Makefile
index 90e0343..4a46ca0 100644
--- a/board/xilinx/versal/Makefile
+++ b/board/xilinx/versal/Makefile
@@ -6,4 +6,3 @@
 
 obj-y	:= board.o
 obj-$(CONFIG_CMD_VERSAL)	+= cmds.o
-obj-y	+= ../common/board.o
diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c
index a5ca4ca..912c114 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -36,6 +36,9 @@
 	fpga_add(fpga_xilinx, &versalpl);
 #endif
 
+	if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
+		xilinx_read_eeprom();
+
 	return 0;
 }
 
diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
index 096a7ac..8566171 100644
--- a/board/xilinx/zynq/Makefile
+++ b/board/xilinx/zynq/Makefile
@@ -4,7 +4,6 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
 obj-y	:= board.o
-obj-y	+= ../common/board.o
 
 ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"")
 PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE))
diff --git a/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
new file mode 100644
index 0000000..5d57386
--- /dev/null
+++ b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Xilinx, Inc.
+ */
+
+#include <asm/arch/ps7_init_gpl.h>
+
+static unsigned long ps7_pll_init_data[] = {
+	EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+	EMIT_MASKWRITE(0xF8000110, 0x003FFFF0U, 0x000FA220U),
+	EMIT_MASKWRITE(0xF8000100, 0x0007F000U, 0x00028000U),
+	EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000010U),
+	EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000000U),
+	EMIT_MASKPOLL(0xF800010C, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000000U),
+	EMIT_MASKWRITE(0xF8000120, 0x1F003F30U, 0x1F000200U),
+	EMIT_MASKWRITE(0xF8000114, 0x003FFFF0U, 0x0012C220U),
+	EMIT_MASKWRITE(0xF8000104, 0x0007F000U, 0x00020000U),
+	EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000010U),
+	EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000000U),
+	EMIT_MASKPOLL(0xF800010C, 0x00000002U),
+	EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000000U),
+	EMIT_MASKWRITE(0xF8000124, 0xFFF00003U, 0x0C200003U),
+	EMIT_MASKWRITE(0xF8000118, 0x003FFFF0U, 0x001452C0U),
+	EMIT_MASKWRITE(0xF8000108, 0x0007F000U, 0x0001E000U),
+	EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000010U),
+	EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000000U),
+	EMIT_MASKPOLL(0xF800010C, 0x00000004U),
+	EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000000U),
+	EMIT_WRITE(0xF8000004, 0x0000767BU),
+	EMIT_EXIT(),
+};
+
+static unsigned long ps7_clock_init_data[] = {
+	EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+	EMIT_MASKWRITE(0xF8000128, 0x03F03F01U, 0x00700F01U),
+	EMIT_MASKWRITE(0xF8000138, 0x00000011U, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000140, 0x03F03F71U, 0x00100801U),
+	EMIT_MASKWRITE(0xF800014C, 0x00003F31U, 0x00000501U),
+	EMIT_MASKWRITE(0xF8000150, 0x00003F33U, 0x00001401U),
+	EMIT_MASKWRITE(0xF8000154, 0x00003F33U, 0x00000A03U),
+	EMIT_MASKWRITE(0xF800015C, 0x03F03F33U, 0x00200501U),
+	EMIT_MASKWRITE(0xF8000160, 0x007F007FU, 0x00000000U),
+	EMIT_MASKWRITE(0xF8000168, 0x00003F31U, 0x00000501U),
+	EMIT_MASKWRITE(0xF8000170, 0x03F03F30U, 0x00200500U),
+	EMIT_MASKWRITE(0xF8000180, 0x03F03F30U, 0x00400500U),
+	EMIT_MASKWRITE(0xF80001C4, 0x00000001U, 0x00000001U),
+	EMIT_MASKWRITE(0xF800012C, 0x01FFCCCDU, 0x01FD044DU),
+	EMIT_WRITE(0xF8000004, 0x0000767BU),
+	EMIT_EXIT(),
+};
+
+static unsigned long ps7_ddr_init_data[] = {
+	EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000080U),
+	EMIT_MASKWRITE(0xF8006004, 0x0007FFFFU, 0x00001082U),
+	EMIT_MASKWRITE(0xF8006008, 0x03FFFFFFU, 0x03C0780FU),
+	EMIT_MASKWRITE(0xF800600C, 0x03FFFFFFU, 0x02001001U),
+	EMIT_MASKWRITE(0xF8006010, 0x03FFFFFFU, 0x00014001U),
+	EMIT_MASKWRITE(0xF8006014, 0x001FFFFFU, 0x0004285BU),
+	EMIT_MASKWRITE(0xF8006018, 0xF7FFFFFFU, 0x44E458D3U),
+	EMIT_MASKWRITE(0xF800601C, 0xFFFFFFFFU, 0x7282BCE5U),
+	EMIT_MASKWRITE(0xF8006020, 0x7FDFFFFCU, 0x270872D0U),
+	EMIT_MASKWRITE(0xF8006024, 0x0FFFFFC3U, 0x00000000U),
+	EMIT_MASKWRITE(0xF8006028, 0x00003FFFU, 0x00002007U),
+	EMIT_MASKWRITE(0xF800602C, 0xFFFFFFFFU, 0x00000008U),
+	EMIT_MASKWRITE(0xF8006030, 0xFFFFFFFFU, 0x00040B30U),
+	EMIT_MASKWRITE(0xF8006034, 0x13FF3FFFU, 0x000116D4U),
+	EMIT_MASKWRITE(0xF8006038, 0x00000003U, 0x00000000U),
+	EMIT_MASKWRITE(0xF800603C, 0x000FFFFFU, 0x00000777U),
+	EMIT_MASKWRITE(0xF8006040, 0xFFFFFFFFU, 0xFFF00000U),
+	EMIT_MASKWRITE(0xF8006044, 0x0FFFFFFFU, 0x0F666666U),
+	EMIT_MASKWRITE(0xF8006048, 0x0003F03FU, 0x0003C008U),
+	EMIT_MASKWRITE(0xF8006050, 0xFF0F8FFFU, 0x77010800U),
+	EMIT_MASKWRITE(0xF8006058, 0x00010000U, 0x00000000U),
+	EMIT_MASKWRITE(0xF800605C, 0x0000FFFFU, 0x00005003U),
+	EMIT_MASKWRITE(0xF8006060, 0x000017FFU, 0x0000003EU),
+	EMIT_MASKWRITE(0xF8006064, 0x00021FE0U, 0x00020000U),
+	EMIT_MASKWRITE(0xF8006068, 0x03FFFFFFU, 0x00284141U),
+	EMIT_MASKWRITE(0xF800606C, 0x0000FFFFU, 0x00001610U),
+	EMIT_MASKWRITE(0xF8006078, 0x03FFFFFFU, 0x00466111U),
+	EMIT_MASKWRITE(0xF800607C, 0x000FFFFFU, 0x00032222U),
+	EMIT_MASKWRITE(0xF80060A4, 0xFFFFFFFFU, 0x10200802U),
+	EMIT_MASKWRITE(0xF80060A8, 0x0FFFFFFFU, 0x0690CB73U),
+	EMIT_MASKWRITE(0xF80060AC, 0x000001FFU, 0x000001FEU),
+	EMIT_MASKWRITE(0xF80060B0, 0x1FFFFFFFU, 0x1CFFFFFFU),
+	EMIT_MASKWRITE(0xF80060B4, 0x00000200U, 0x00000200U),
+	EMIT_MASKWRITE(0xF80060B8, 0x01FFFFFFU, 0x00200066U),
+	EMIT_MASKWRITE(0xF80060C4, 0x00000003U, 0x00000000U),
+	EMIT_MASKWRITE(0xF80060C8, 0x000000FFU, 0x00000000U),
+	EMIT_MASKWRITE(0xF80060DC, 0x00000001U, 0x00000000U),
+	EMIT_MASKWRITE(0xF80060F0, 0x0000FFFFU, 0x00000000U),
+	EMIT_MASKWRITE(0xF80060F4, 0x0000000FU, 0x00000008U),
+	EMIT_MASKWRITE(0xF8006114, 0x000000FFU, 0x00000000U),
+	EMIT_MASKWRITE(0xF8006118, 0x7FFFFFCFU, 0x40000001U),
+	EMIT_MASKWRITE(0xF800611C, 0x7FFFFFCFU, 0x40000001U),
+	EMIT_MASKWRITE(0xF8006120, 0x7FFFFFCFU, 0x40000001U),
+	EMIT_MASKWRITE(0xF8006124, 0x7FFFFFCFU, 0x40000001U),
+	EMIT_MASKWRITE(0xF800612C, 0x000FFFFFU, 0x0002A81FU),
+	EMIT_MASKWRITE(0xF8006130, 0x000FFFFFU, 0x00029822U),
+	EMIT_MASKWRITE(0xF8006134, 0x000FFFFFU, 0x00026C10U),
+	EMIT_MASKWRITE(0xF8006138, 0x000FFFFFU, 0x00026013U),
+	EMIT_MASKWRITE(0xF8006140, 0x000FFFFFU, 0x00000035U),
+	EMIT_MASKWRITE(0xF8006144, 0x000FFFFFU, 0x00000035U),
+	EMIT_MASKWRITE(0xF8006148, 0x000FFFFFU, 0x00000035U),
+	EMIT_MASKWRITE(0xF800614C, 0x000FFFFFU, 0x00000035U),
+	EMIT_MASKWRITE(0xF8006154, 0x000FFFFFU, 0x0000009FU),
+	EMIT_MASKWRITE(0xF8006158, 0x000FFFFFU, 0x000000A2U),
+	EMIT_MASKWRITE(0xF800615C, 0x000FFFFFU, 0x00000090U),
+	EMIT_MASKWRITE(0xF8006160, 0x000FFFFFU, 0x00000093U),
+	EMIT_MASKWRITE(0xF8006168, 0x001FFFFFU, 0x000000FFU),
+	EMIT_MASKWRITE(0xF800616C, 0x001FFFFFU, 0x000000FBU),
+	EMIT_MASKWRITE(0xF8006170, 0x001FFFFFU, 0x000000F0U),
+	EMIT_MASKWRITE(0xF8006174, 0x001FFFFFU, 0x000000EDU),
+	EMIT_MASKWRITE(0xF800617C, 0x000FFFFFU, 0x000000DFU),
+	EMIT_MASKWRITE(0xF8006180, 0x000FFFFFU, 0x000000E2U),
+	EMIT_MASKWRITE(0xF8006184, 0x000FFFFFU, 0x000000D0U),
+	EMIT_MASKWRITE(0xF8006188, 0x000FFFFFU, 0x000000D3U),
+	EMIT_MASKWRITE(0xF8006190, 0x6FFFFEFEU, 0x00040080U),
+	EMIT_MASKWRITE(0xF8006194, 0x000FFFFFU, 0x0001FC82U),
+	EMIT_MASKWRITE(0xF8006204, 0xFFFFFFFFU, 0x00000000U),
+	EMIT_MASKWRITE(0xF8006208, 0x000703FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF800620C, 0x000703FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF8006210, 0x000703FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF8006214, 0x000703FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF8006218, 0x000F03FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF800621C, 0x000F03FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF8006220, 0x000F03FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF8006224, 0x000F03FFU, 0x000003FFU),
+	EMIT_MASKWRITE(0xF80062A8, 0x00000FF5U, 0x00000000U),
+	EMIT_MASKWRITE(0xF80062AC, 0xFFFFFFFFU, 0x00000000U),
+	EMIT_MASKWRITE(0xF80062B0, 0x003FFFFFU, 0x00005125U),
+	EMIT_MASKWRITE(0xF80062B4, 0x0003FFFFU, 0x000012A8U),
+	EMIT_MASKPOLL(0xF8000B74, 0x00002000U),
+	EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000081U),
+	EMIT_MASKPOLL(0xF8006054, 0x00000007U),
+	EMIT_EXIT(),
+};
+
+static unsigned long ps7_mio_init_data[] = {
+	EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+	EMIT_MASKWRITE(0xF8000B40, 0x00000FFFU, 0x00000600U),
+	EMIT_MASKWRITE(0xF8000B44, 0x00000FFFU, 0x00000600U),
+	EMIT_MASKWRITE(0xF8000B48, 0x00000FFFU, 0x00000672U),
+	EMIT_MASKWRITE(0xF8000B4C, 0x00000FFFU, 0x00000672U),
+	EMIT_MASKWRITE(0xF8000B50, 0x00000FFFU, 0x00000674U),
+	EMIT_MASKWRITE(0xF8000B54, 0x00000FFFU, 0x00000674U),
+	EMIT_MASKWRITE(0xF8000B58, 0x00000FFFU, 0x00000600U),
+	EMIT_MASKWRITE(0xF8000B5C, 0xFFFFFFFFU, 0x0018C61CU),
+	EMIT_MASKWRITE(0xF8000B60, 0xFFFFFFFFU, 0x00F9861CU),
+	EMIT_MASKWRITE(0xF8000B64, 0xFFFFFFFFU, 0x00F9861CU),
+	EMIT_MASKWRITE(0xF8000B68, 0xFFFFFFFFU, 0x00F9861CU),
+	EMIT_MASKWRITE(0xF8000B6C, 0x00007FFFU, 0x00000260U),
+	EMIT_MASKWRITE(0xF8000B70, 0x00000001U, 0x00000001U),
+	EMIT_MASKWRITE(0xF8000B70, 0x00000021U, 0x00000020U),
+	EMIT_MASKWRITE(0xF8000B70, 0x07FEFFFFU, 0x00000823U),
+	EMIT_MASKWRITE(0xF8000700, 0x00003FFFU, 0x00001600U),
+	EMIT_MASKWRITE(0xF8000704, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF8000708, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF800070C, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF8000710, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF8000714, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF8000718, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF800071C, 0x00003FFFU, 0x00000600U),
+	EMIT_MASKWRITE(0xF8000720, 0x00003FFFU, 0x00000602U),
+	EMIT_MASKWRITE(0xF8000724, 0x00003FFFU, 0x00000600U),
+	EMIT_MASKWRITE(0xF8000728, 0x00003FFFU, 0x000016E1U),
+	EMIT_MASKWRITE(0xF800072C, 0x00003FFFU, 0x000016E0U),
+	EMIT_MASKWRITE(0xF8000730, 0x00003FFFU, 0x00001640U),
+	EMIT_MASKWRITE(0xF8000734, 0x00003FFFU, 0x00001640U),
+	EMIT_MASKWRITE(0xF8000738, 0x00003FFFU, 0x00001621U),
+	EMIT_MASKWRITE(0xF800073C, 0x00003FFFU, 0x00001620U),
+	EMIT_MASKWRITE(0xF8000740, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF8000744, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF8000748, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF800074C, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF8000750, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF8000754, 0x00003FFFU, 0x00001202U),
+	EMIT_MASKWRITE(0xF8000758, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF800075C, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF8000760, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF8000764, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF8000768, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF800076C, 0x00003FFFU, 0x00001203U),
+	EMIT_MASKWRITE(0xF8000770, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF8000774, 0x00003FFFU, 0x00001205U),
+	EMIT_MASKWRITE(0xF8000778, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF800077C, 0x00003FFFU, 0x00001205U),
+	EMIT_MASKWRITE(0xF8000780, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF8000784, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF8000788, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF800078C, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF8000790, 0x00003FFFU, 0x00001205U),
+	EMIT_MASKWRITE(0xF8000794, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF8000798, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF800079C, 0x00003FFFU, 0x00001204U),
+	EMIT_MASKWRITE(0xF80007A0, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007A4, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007A8, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007AC, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007B0, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007B4, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007B8, 0x00003F01U, 0x00000201U),
+	EMIT_MASKWRITE(0xF80007BC, 0x00003F01U, 0x00000201U),
+	EMIT_MASKWRITE(0xF80007C0, 0x00003FFFU, 0x000012E0U),
+	EMIT_MASKWRITE(0xF80007C4, 0x00003FFFU, 0x000012E1U),
+	EMIT_MASKWRITE(0xF80007C8, 0x00003FFFU, 0x00000200U),
+	EMIT_MASKWRITE(0xF80007CC, 0x00003FFFU, 0x00000200U),
+	EMIT_MASKWRITE(0xF80007D0, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF80007D4, 0x00003FFFU, 0x00001280U),
+	EMIT_MASKWRITE(0xF8000830, 0x003F003FU, 0x002E002FU),
+	EMIT_WRITE(0xF8000004, 0x0000767BU),
+	EMIT_EXIT(),
+};
+
+static unsigned long ps7_peripherals_init_data[] = {
+	EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+	EMIT_MASKWRITE(0xF8000B48, 0x00000180U, 0x00000180U),
+	EMIT_MASKWRITE(0xF8000B4C, 0x00000180U, 0x00000180U),
+	EMIT_MASKWRITE(0xF8000B50, 0x00000180U, 0x00000180U),
+	EMIT_MASKWRITE(0xF8000B54, 0x00000180U, 0x00000180U),
+	EMIT_WRITE(0xF8000004, 0x0000767BU),
+	EMIT_MASKWRITE(0xE000D000, 0x00080000U, 0x00080000U),
+	EMIT_MASKWRITE(0xF8007000, 0x20000000U, 0x00000000U),
+	EMIT_MASKWRITE(0xE000A244, 0x003FFFFFU, 0x00080000U),
+	EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U),
+	EMIT_MASKWRITE(0xE000A248, 0x003FFFFFU, 0x00080000U),
+	EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370000U),
+	EMIT_MASKDELAY(0xF8F00200, 1),
+	EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U),
+	EMIT_EXIT(),
+};
+
+static unsigned long ps7_post_config_0[] = {
+	EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+	EMIT_MASKWRITE(0xF8000900, 0x0000000FU, 0x0000000FU),
+	EMIT_MASKWRITE(0xF8000240, 0xFFFFFFFFU, 0x00000000U),
+	EMIT_WRITE(0xF8000004, 0x0000767BU),
+	EMIT_EXIT(),
+};
+
+int ps7_post_config(void)
+{
+	return ps7_config(ps7_post_config_0);
+}
+
+int ps7_init(void)
+{
+	int ret;
+
+	ret = ps7_config(ps7_mio_init_data);
+	if (ret != PS7_INIT_SUCCESS)
+		return ret;
+
+	ret = ps7_config(ps7_pll_init_data);
+	if (ret != PS7_INIT_SUCCESS)
+		return ret;
+
+	ret = ps7_config(ps7_clock_init_data);
+	if (ret != PS7_INIT_SUCCESS)
+		return ret;
+
+	ret = ps7_config(ps7_ddr_init_data);
+	if (ret != PS7_INIT_SUCCESS)
+		return ret;
+
+	ret = ps7_config(ps7_peripherals_init_data);
+	if (ret != PS7_INIT_SUCCESS)
+		return ret;
+	return PS7_INIT_SUCCESS;
+}
diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS
index 04fc7f3..9cd4f3f 100644
--- a/board/xilinx/zynqmp/MAINTAINERS
+++ b/board/xilinx/zynqmp/MAINTAINERS
@@ -3,6 +3,7 @@
 S:	Maintained
 F:	arch/arm/dts/zynqmp-*
 F:	arch/arm/dts/avnet-ultra96*
+F:	board/xilinx/common/
 F:	board/xilinx/zynqmp/
 F:	include/configs/xilinx_zynqmp*
 F:	configs/xilinx_zynqmp*
diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 398c6aa..7d8277c 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -4,7 +4,6 @@
 # Michal Simek <michal.simek@xilinx.com>
 
 obj-y	:= zynqmp.o
-obj-y	+= ../common/board.o
 
 ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"")
 PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE))
diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c
index c0d28a7..cf63ad9 100644
--- a/board/xilinx/zynqmp/cmds.c
+++ b/board/xilinx/zynqmp/cmds.c
@@ -9,11 +9,22 @@
 #include <cpu_func.h>
 #include <env.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <zynqmp_firmware.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
 
+struct aes {
+	u64 srcaddr;
+	u64 ivaddr;
+	u64 keyaddr;
+	u64 dstaddr;
+	u64 len;
+	u64 op;
+	u64 keysrc;
+};
+
 static int do_zynqmp_verify_secure(struct cmd_tbl *cmdtp, int flag, int argc,
 				   char *const argv[])
 {
@@ -107,6 +118,66 @@
 	return ret;
 }
 
+static int do_zynqmp_aes(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct aes, aes, 1);
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+		puts("ERR: PMUFW v1.0 or less is detected\n");
+		puts("ERR: Encrypt/Decrypt feature is not supported\n");
+		puts("ERR: Please upgrade PMUFW\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (argc < cmdtp->maxargs - 1)
+		return CMD_RET_USAGE;
+
+	aes->srcaddr = simple_strtoul(argv[2], NULL, 16);
+	aes->ivaddr = simple_strtoul(argv[3], NULL, 16);
+	aes->len = simple_strtoul(argv[4], NULL, 16);
+	aes->op = simple_strtoul(argv[5], NULL, 16);
+	aes->keysrc = simple_strtoul(argv[6], NULL, 16);
+	aes->dstaddr = simple_strtoul(argv[7], NULL, 16);
+
+	flush_dcache_range((ulong)aes, (ulong)(aes) +
+			   roundup(sizeof(struct aes), ARCH_DMA_MINALIGN));
+
+	if (aes->srcaddr && aes->ivaddr && aes->dstaddr) {
+		flush_dcache_range(aes->srcaddr,
+				   (aes->srcaddr +
+				    roundup(aes->len, ARCH_DMA_MINALIGN)));
+		flush_dcache_range(aes->ivaddr,
+				   (aes->ivaddr +
+				    roundup(IV_SIZE, ARCH_DMA_MINALIGN)));
+		flush_dcache_range(aes->dstaddr,
+				   (aes->dstaddr +
+				    roundup(aes->len, ARCH_DMA_MINALIGN)));
+	}
+
+	if (aes->keysrc == 0) {
+		if (argc < cmdtp->maxargs)
+			return CMD_RET_USAGE;
+
+		aes->keyaddr = simple_strtoul(argv[8], NULL, 16);
+		if (aes->keyaddr)
+			flush_dcache_range(aes->keyaddr,
+					   (aes->keyaddr +
+					    roundup(KEY_PTR_LEN,
+						    ARCH_DMA_MINALIGN)));
+	}
+
+	ret = xilinx_pm_request(PM_SECURE_AES, upper_32_bits((ulong)aes),
+				lower_32_bits((ulong)aes), 0, 0, ret_payload);
+	if (ret || ret_payload[1])
+		printf("Failed: AES op status:0x%x, errcode:0x%x\n",
+		       ret, ret_payload[1]);
+
+	return ret;
+}
+
 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP
 static int do_zynqmp_tcm_init(struct cmd_tbl *cmdtp, int flag, int argc,
 			      char *const argv[])
@@ -148,11 +219,145 @@
 	return 0;
 }
 
+static int do_zynqmp_rsa(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	u64 srcaddr, mod, exp;
+	u32 srclen, rsaop, size, ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (argc != cmdtp->maxargs)
+		return CMD_RET_USAGE;
+
+	if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+		puts("ERR: PMUFW v1.0 or less is detected\n");
+		puts("ERR: Encrypt/Decrypt feature is not supported\n");
+		puts("ERR: Please upgrade PMUFW\n");
+		return CMD_RET_FAILURE;
+	}
+
+	srcaddr = simple_strtoul(argv[2], NULL, 16);
+	srclen = simple_strtoul(argv[3], NULL, 16);
+	if (srclen != RSA_KEY_SIZE) {
+		puts("ERR: srclen should be equal to 0x200(512 bytes)\n");
+		return CMD_RET_USAGE;
+	}
+
+	mod = simple_strtoul(argv[4], NULL, 16);
+	exp = simple_strtoul(argv[5], NULL, 16);
+	rsaop = simple_strtoul(argv[6], NULL, 16);
+	if (!(rsaop == 0 || rsaop == 1)) {
+		puts("ERR: rsaop should be either 0 or 1\n");
+		return CMD_RET_USAGE;
+	}
+
+	memcpy((void *)srcaddr + srclen, (void *)mod, MODULUS_LEN);
+
+	/*
+	 * For encryption we load public exponent (key size 4096-bits),
+	 * for decryption we load private exponent (32-bits)
+	 */
+	if (rsaop) {
+		memcpy((void *)srcaddr + srclen + MODULUS_LEN,
+		       (void *)exp, PUB_EXPO_LEN);
+		size = srclen + MODULUS_LEN + PUB_EXPO_LEN;
+	} else {
+		memcpy((void *)srcaddr + srclen + MODULUS_LEN,
+		       (void *)exp, PRIV_EXPO_LEN);
+		size = srclen + MODULUS_LEN + PRIV_EXPO_LEN;
+	}
+
+	flush_dcache_range((ulong)srcaddr,
+			   (ulong)(srcaddr) + roundup(size, ARCH_DMA_MINALIGN));
+
+	ret = xilinx_pm_request(PM_SECURE_RSA, upper_32_bits((ulong)srcaddr),
+				lower_32_bits((ulong)srcaddr), srclen, rsaop,
+				ret_payload);
+	if (ret || ret_payload[1]) {
+		printf("Failed: RSA status:0x%x, errcode:0x%x\n",
+		       ret, ret_payload[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_zynqmp_sha3(struct cmd_tbl *cmdtp, int flag,
+			  int argc, char * const argv[])
+{
+	u64 srcaddr, hashaddr;
+	u32 srclen, ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+		return CMD_RET_USAGE;
+
+	if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+		puts("ERR: PMUFW v1.0 or less is detected\n");
+		puts("ERR: Encrypt/Decrypt feature is not supported\n");
+		puts("ERR: Please upgrade PMUFW\n");
+		return CMD_RET_FAILURE;
+	}
+
+	srcaddr = simple_strtoul(argv[2], NULL, 16);
+	srclen = simple_strtoul(argv[3], NULL, 16);
+
+	if (argc == 5) {
+		hashaddr = simple_strtoul(argv[4], NULL, 16);
+		flush_dcache_range(hashaddr,
+				   hashaddr + roundup(ZYNQMP_SHA3_SIZE,
+						      ARCH_DMA_MINALIGN));
+	} else {
+		hashaddr = srcaddr;
+	}
+
+	/* Check srcaddr or srclen != 0 */
+	if (!srcaddr || !srclen) {
+		puts("ERR: srcaddr & srclen should not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	flush_dcache_range(srcaddr,
+			   srcaddr + roundup(srclen, ARCH_DMA_MINALIGN));
+
+	ret = xilinx_pm_request(PM_SECURE_SHA, 0, 0, 0,
+				ZYNQMP_SHA3_INIT, ret_payload);
+	if (ret || ret_payload[1]) {
+		printf("Failed: SHA INIT status:0x%x, errcode:0x%x\n",
+		       ret, ret_payload[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)srcaddr),
+				lower_32_bits((ulong)srcaddr),
+				srclen, ZYNQMP_SHA3_UPDATE, ret_payload);
+	if (ret || ret_payload[1]) {
+		printf("Failed: SHA UPDATE status:0x%x, errcode:0x%x\n",
+		       ret, ret_payload[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)hashaddr),
+				lower_32_bits((ulong)hashaddr),
+				ZYNQMP_SHA3_SIZE, ZYNQMP_SHA3_FINAL,
+				ret_payload);
+	if (ret || ret_payload[1]) {
+		printf("Failed: SHA FINAL status:0x%x, errcode:0x%x\n",
+		       ret, ret_payload[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
 static struct cmd_tbl cmd_zynqmp_sub[] = {
 	U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""),
 	U_BOOT_CMD_MKENT(pmufw, 4, 0, do_zynqmp_pmufw, "", ""),
 	U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""),
 	U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""),
+	U_BOOT_CMD_MKENT(aes, 9, 0, do_zynqmp_aes, "", ""),
+	U_BOOT_CMD_MKENT(rsa, 7, 0, do_zynqmp_rsa, "", ""),
+	U_BOOT_CMD_MKENT(sha3, 5, 0, do_zynqmp_sha3, "", ""),
 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP
 	U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""),
 #endif
@@ -196,6 +401,14 @@
 	"zynqmp mmio_read address - read from address\n"
 	"zynqmp mmio_write address mask value - write value after masking to\n"
 	"					address\n"
+	"zynqmp aes srcaddr ivaddr len aesop keysrc dstaddr [keyaddr] -\n"
+	"	Encrypts or decrypts blob of data at src address and puts it\n"
+	"	back to dstaddr using key and iv at keyaddr and ivaddr\n"
+	"	respectively. keysrc value specifies from which source key\n"
+	"	has to be used, it can be User/Device/PUF key. A value of 0\n"
+	"	for KUP(user key),1 for DeviceKey and 2 for PUF key. The\n"
+	"	aesop value specifies the operation which can be 0 for\n"
+	"	decrypt and 1 for encrypt operation\n"
 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP
 	"zynqmp tcminit mode - Initialize the TCM with zeros. TCM needs to be\n"
 	"		       initialized before accessing to avoid ECC\n"
@@ -204,11 +417,24 @@
 	"		       lock(0)/split(1)\n"
 #endif
 	"zynqmp pmufw address size - load PMU FW configuration object\n"
+	"zynqmp rsa srcaddr srclen mod exp rsaop -\n"
+	"	Performs RSA encryption and RSA decryption on blob of data\n"
+	"	at srcaddr and puts it back in srcaddr using modulus and\n"
+	"	public or private exponent\n"
+	"	srclen : must be key size(4096 bits)\n"
+	"	exp :	private key exponent for RSA decryption(4096 bits)\n"
+	"		public key exponent for RSA encryption(32 bits)\n"
+	"	rsaop :	0 for RSA Decryption, 1 for RSA Encryption\n"
+	"zynqmp sha3 srcaddr srclen [key_addr] -\n"
+	"	Generates sha3 hash value for data blob at srcaddr and puts\n"
+	"	48 bytes hash value into srcaddr\n"
+	"	Optional key_addr can be specified for saving sha3 hash value\n"
+	"	Note: srcaddr/srclen should not be 0\n"
 	;
 #endif
 
 U_BOOT_CMD(
-	zynqmp, 5, 1, do_zynqmp,
+	zynqmp, 9, 1, do_zynqmp,
 	"ZynqMP sub-system",
 	zynqmp_help_text
 )
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index 5fde0ae..1cab25f 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -6,8 +6,10 @@
  */
 
 #include <common.h>
+#include <zynqmp_tap_delay.h>
 #include <asm/arch/sys_proto.h>
 #include <linux/delay.h>
+#include <mmc.h>
 
 #define SD_DLL_CTRL			0xFF180358
 #define SD_ITAP_DLY			0xFF180314
@@ -25,43 +27,9 @@
 #define SD1_ITAPDLYENA_MASK		0x01000000
 #define SD1_ITAPDLYENA			0x01000000
 #define SD0_ITAPDLYSEL_MASK		0x000000FF
-#define SD0_ITAPDLYSEL_HSD		0x00000015
-#define SD0_ITAPDLYSEL_SD_DDR50		0x0000003D
-#define SD0_ITAPDLYSEL_MMC_DDR50	0x00000012
-
 #define SD1_ITAPDLYSEL_MASK		0x00FF0000
-#define SD1_ITAPDLYSEL_HSD		0x00150000
-#define SD1_ITAPDLYSEL_SD_DDR50		0x003D0000
-#define SD1_ITAPDLYSEL_MMC_DDR50	0x00120000
-
 #define SD0_OTAPDLYSEL_MASK		0x0000003F
-#define SD0_OTAPDLYSEL_MMC_HSD		0x00000006
-#define SD0_OTAPDLYSEL_SD_HSD		0x00000005
-#define SD0_OTAPDLYSEL_SDR50		0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B0	0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B2	0x00000002
-#define SD0_OTAPDLYSEL_SD_DDR50		0x00000004
-#define SD0_OTAPDLYSEL_MMC_DDR50	0x00000006
-
 #define SD1_OTAPDLYSEL_MASK		0x003F0000
-#define SD1_OTAPDLYSEL_MMC_HSD		0x00060000
-#define SD1_OTAPDLYSEL_SD_HSD		0x00050000
-#define SD1_OTAPDLYSEL_SDR50		0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B0	0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B2	0x00020000
-#define SD1_OTAPDLYSEL_SD_DDR50		0x00040000
-#define SD1_OTAPDLYSEL_MMC_DDR50	0x00060000
-
-#define MMC_BANK2		0x2
-
-#define MMC_TIMING_UHS_SDR25		1
-#define MMC_TIMING_UHS_SDR50		2
-#define MMC_TIMING_UHS_SDR104		3
-#define MMC_TIMING_UHS_DDR50		4
-#define MMC_TIMING_MMC_HS200		5
-#define MMC_TIMING_SD_HS		6
-#define MMC_TIMING_MMC_DDR52		7
-#define MMC_TIMING_MMC_HS		8
 
 void zynqmp_dll_reset(u8 deviceid)
 {
@@ -82,149 +50,49 @@
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
 }
 
-static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
-		/* Program OTAP */
-		if (bank == MMC_BANK2)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SDR104_B2);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SDR104_B0);
-	} else {
-		/* Program OTAP */
-		if (bank == MMC_BANK2)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SDR104_B2);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SDR104_B0);
-	}
-}
-
-static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay)
 {
 	if (deviceid == 0) {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
-				  SD0_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
-				  SD0_ITAPDLYENA);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-				  SD0_ITAPDLYSEL_HSD);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_MMC_HS)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_MMC_HSD);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SD_HSD);
-	} else {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
-				  SD1_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
-				  SD1_ITAPDLYENA);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-				  SD1_ITAPDLYSEL_HSD);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_MMC_HS)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_MMC_HSD);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SD_HSD);
-	}
-}
-
-static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
 		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
-				  SD0_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
-				  SD0_ITAPDLYENA);
-		if (timing == MMC_TIMING_UHS_DDR50)
+		if (itap_delay) {
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+					  SD0_ITAPCHGWIN);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+					  SD0_ITAPDLYENA);
 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-					  SD0_ITAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-					  SD0_ITAPDLYSEL_MMC_DDR50);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+					  itap_delay);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+					  0x0);
+		}
+
 		/* Program OTAP */
-		if (timing == MMC_TIMING_UHS_DDR50)
+		if (otap_delay)
 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_MMC_DDR50);
-	} else {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
-				  SD1_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
-				  SD1_ITAPDLYENA);
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-					  SD1_ITAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-					  SD1_ITAPDLYSEL_MMC_DDR50);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_MMC_DDR50);
-	}
-}
+					  otap_delay);
 
-static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
-		/* Program OTAP */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-				  SD0_OTAPDLYSEL_SDR50);
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
 	} else {
-		/* Program OTAP */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-				  SD1_OTAPDLYSEL_SDR50);
-	}
-}
-
-void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0)
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
-				  SD0_DLL_RST);
-	else
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
 				  SD1_DLL_RST);
+		/* Program ITAP */
+		if (itap_delay) {
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+					  SD1_ITAPCHGWIN);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+					  SD1_ITAPDLYENA);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  (itap_delay << 16));
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+					  0x0);
+		}
 
-	switch (timing) {
-	case MMC_TIMING_UHS_SDR25:
-		arasan_zynqmp_tap_hs(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_SDR50:
-		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_SDR104:
-	case MMC_TIMING_MMC_HS200:
-		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_DDR50:
-		arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
-		break;
-	}
+		/* Program OTAP */
+		if (otap_delay)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  (otap_delay << 16));
 
-	if (deviceid == 0)
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
-	else
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+	}
 }
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 28f067a..731285a 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -40,12 +40,12 @@
 #include "pm_cfg_obj.h"
 
 #define ZYNQMP_VERSION_SIZE	7
-#define EFUSE_VCU_DIS_MASK     0x100
-#define EFUSE_VCU_DIS_SHIFT    8
-#define EFUSE_GPU_DIS_MASK     0x20
-#define EFUSE_GPU_DIS_SHIFT    5
-#define IDCODE2_PL_INIT_MASK   0x200
-#define IDCODE2_PL_INIT_SHIFT  9
+#define EFUSE_VCU_DIS_MASK	0x100
+#define EFUSE_VCU_DIS_SHIFT	8
+#define EFUSE_GPU_DIS_MASK	0x20
+#define EFUSE_GPU_DIS_SHIFT	5
+#define IDCODE2_PL_INIT_MASK	0x200
+#define IDCODE2_PL_INIT_SHIFT	9
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -100,7 +100,7 @@
 	{
 		.id = 0x04738093,
 		.device = 9,
-		.variants = ZYNQMP_VARIANT_EG,
+		.variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
 	},
 	{
 		.id = 0x04740093,
@@ -190,8 +190,13 @@
 	u32 idcode, idcode2;
 	char name[ZYNQMP_VERSION_SIZE];
 	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
 
-	xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+	ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+	if (ret) {
+		debug("%s: Getting chipid failed\n", __func__);
+		return "unknown";
+	}
 
 	/*
 	 * Firmware returns:
@@ -204,7 +209,7 @@
 
 	idcode  = ret_payload[1];
 	idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
-	debug("%s, IDCODE: 0x%0X, IDCODE2: 0x%0X\r\n", __func__, idcode,
+	debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode,
 	      idcode2);
 
 	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
@@ -216,8 +221,10 @@
 		return "unknown";
 
 	/* Add device prefix to the name */
-	strncpy(name, "zu", ZYNQMP_VERSION_SIZE);
-	strncat(&name[2], simple_itoa(zynqmp_devices[i].device), 2);
+	ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d",
+		       zynqmp_devices[i].device);
+	if (ret < 0)
+		return "unknown";
 
 	if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) {
 		/* Devices with EV variant might be EG/CG/EV family */
@@ -321,6 +328,9 @@
 	if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
 		zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
 						zynqmp_pm_cfg_obj_size);
+#else
+	if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
+		xilinx_read_eeprom();
 #endif
 
 	printf("EL Level:\tEL%d\n", current_el());
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 9f36290..1595de9 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2239,6 +2239,7 @@
 config CMD_LOG
 	bool "log - Generation, control and access to logging"
 	select LOG
+	select GETOPT
 	help
 	  This provides access to logging features. It allows the output of
 	  log data to be controlled to a limited extent (setting up the default
diff --git a/cmd/log.c b/cmd/log.c
index 6afe6ea..ca1c51e 100644
--- a/cmd/log.c
+++ b/cmd/log.c
@@ -7,29 +7,300 @@
 #include <common.h>
 #include <command.h>
 #include <dm.h>
+#include <getopt.h>
 #include <log.h>
+#include <malloc.h>
 
 static char log_fmt_chars[LOGF_COUNT] = "clFLfm";
 
+static enum log_level_t parse_log_level(char *const arg)
+{
+	enum log_level_t ret;
+	ulong level;
+
+	if (!strict_strtoul(arg, 10, &level)) {
+		if (level > _LOG_MAX_LEVEL) {
+			printf("Only log levels <= %d are supported\n",
+			       _LOG_MAX_LEVEL);
+			return LOGL_NONE;
+		}
+		return level;
+	}
+
+	ret = log_get_level_by_name(arg);
+	if (ret == LOGL_NONE)
+		printf("Unknown log level \"%s\"\n", arg);
+	return ret;
+}
+
 static int do_log_level(struct cmd_tbl *cmdtp, int flag, int argc,
 			char *const argv[])
 {
+	enum log_level_t log_level;
+
 	if (argc > 1) {
-		long log_level = simple_strtol(argv[1], NULL, 10);
+		log_level = parse_log_level(argv[1]);
 
-		if (log_level < 0 || log_level > _LOG_MAX_LEVEL) {
-			printf("Only log levels <= %d are supported\n",
-			       _LOG_MAX_LEVEL);
+		if (log_level == LOGL_NONE)
 			return CMD_RET_FAILURE;
-		}
 		gd->default_log_level = log_level;
 	} else {
-		printf("Default log level: %d\n", gd->default_log_level);
+		for (log_level = LOGL_FIRST; log_level <= _LOG_MAX_LEVEL;
+		     log_level++)
+			printf("%s%s\n", log_get_level_name(log_level),
+			       log_level == gd->default_log_level ?
+			       " (default)" : "");
 	}
 
-	return 0;
+	return CMD_RET_SUCCESS;
+}
+
+static int do_log_categories(struct cmd_tbl *cmdtp, int flag, int argc,
+			     char *const argv[])
+{
+	enum log_category_t cat;
+	const char *name;
+
+	for (cat = LOGC_FIRST; cat < LOGC_COUNT; cat++) {
+		name = log_get_cat_name(cat);
+		/*
+		 * Invalid category names (e.g. <invalid> or <missing>) begin
+		 * with '<'.
+		 */
+		if (name[0] == '<')
+			continue;
+		printf("%s\n", name);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_log_drivers(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	struct log_device *ldev;
+
+	list_for_each_entry(ldev, &gd->log_head, sibling_node)
+		printf("%s\n", ldev->drv->name);
+
+	return CMD_RET_SUCCESS;
 }
 
+static int do_log_filter_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	int opt;
+	const char *drv_name = "console";
+	struct getopt_state gs;
+	struct log_filter *filt;
+	struct log_device *ldev;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "d:")) > 0) {
+		switch (opt) {
+		case 'd':
+			drv_name = gs.arg;
+			break;
+		default:
+			return CMD_RET_USAGE;
+		}
+	}
+
+	if (gs.index != argc)
+		return CMD_RET_USAGE;
+
+	ldev = log_device_find_by_name(drv_name);
+	if (!ldev) {
+		printf("Could not find log device for \"%s\"\n", drv_name);
+		return CMD_RET_FAILURE;
+	}
+
+	/*      <3> < 6  > <2+1 + 7 > <      16      > < unbounded... */
+	printf("num policy level            categories files\n");
+	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
+		printf("%3d %6.6s %s %-7.7s ", filt->filter_num,
+		       filt->flags & LOGFF_DENY ? "deny" : "allow",
+		       filt->flags & LOGFF_LEVEL_MIN ? ">=" : "<=",
+		       log_get_level_name(filt->level));
+
+		if (filt->flags & LOGFF_HAS_CAT) {
+			int i;
+
+			if (filt->cat_list[0] != LOGC_END)
+				printf("%16.16s %s\n",
+				       log_get_cat_name(filt->cat_list[0]),
+				       filt->file_list ? filt->file_list : "");
+
+			for (i = 1; i < LOGF_MAX_CATEGORIES &&
+				    filt->cat_list[i] != LOGC_END; i++)
+				printf("%21c %16.16s\n", ' ',
+				       log_get_cat_name(filt->cat_list[i]));
+		} else {
+			printf("%16c %s\n", ' ',
+			       filt->file_list ? filt->file_list : "");
+		}
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc,
+			     char *const argv[])
+{
+	bool level_set = false;
+	bool print_num = false;
+	bool type_set = false;
+	char *file_list = NULL;
+	const char *drv_name = "console";
+	int opt, err;
+	int cat_count = 0;
+	int flags = 0;
+	enum log_category_t cat_list[LOGF_MAX_CATEGORIES + 1];
+	enum log_level_t level = LOGL_MAX;
+	struct getopt_state gs;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "Ac:d:Df:l:L:p")) > 0) {
+		switch (opt) {
+		case 'A':
+#define do_type() do { \
+			if (type_set) { \
+				printf("Allow or deny set twice\n"); \
+				return CMD_RET_USAGE; \
+			} \
+			type_set = true; \
+} while (0)
+			do_type();
+			break;
+		case 'c': {
+			enum log_category_t cat;
+
+			if (cat_count >= LOGF_MAX_CATEGORIES) {
+				printf("Too many categories\n");
+				return CMD_RET_FAILURE;
+			}
+
+			cat = log_get_cat_by_name(gs.arg);
+			if (cat == LOGC_NONE) {
+				printf("Unknown category \"%s\"\n", gs.arg);
+				return CMD_RET_FAILURE;
+			}
+
+			cat_list[cat_count++] = cat;
+			break;
+		}
+		case 'd':
+			drv_name = gs.arg;
+			break;
+		case 'D':
+			do_type();
+			flags |= LOGFF_DENY;
+			break;
+		case 'f':
+			file_list = gs.arg;
+			break;
+		case 'l':
+#define do_level() do { \
+			if (level_set) { \
+				printf("Log level set twice\n"); \
+				return CMD_RET_USAGE; \
+			} \
+			level = parse_log_level(gs.arg); \
+			if (level == LOGL_NONE) \
+				return CMD_RET_FAILURE; \
+			level_set = true; \
+} while (0)
+			do_level();
+			break;
+		case 'L':
+			do_level();
+			flags |= LOGFF_LEVEL_MIN;
+			break;
+		case 'p':
+			print_num = true;
+			break;
+		default:
+			return CMD_RET_USAGE;
+		}
+	}
+
+	if (gs.index != argc)
+		return CMD_RET_USAGE;
+
+	cat_list[cat_count] = LOGC_END;
+	err = log_add_filter_flags(drv_name, cat_count ? cat_list : NULL, level,
+				   file_list, flags);
+	if (err < 0) {
+		printf("Could not add filter (err = %d)\n", err);
+		return CMD_RET_FAILURE;
+	} else if (print_num) {
+		printf("%d\n", err);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_log_filter_remove(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	bool all = false;
+	int opt, err;
+	ulong filter_num;
+	const char *drv_name = "console";
+	struct getopt_state gs;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "ad:")) > 0) {
+		switch (opt) {
+		case 'a':
+			all = true;
+			break;
+		case 'd':
+			drv_name = gs.arg;
+			break;
+		default:
+			return CMD_RET_USAGE;
+		}
+	}
+
+	if (all) {
+		struct log_filter *filt, *tmp_filt;
+		struct log_device *ldev;
+
+		if (gs.index != argc)
+			return CMD_RET_USAGE;
+
+		ldev = log_device_find_by_name(drv_name);
+		if (!ldev) {
+			printf("Could not find log device for \"%s\"\n",
+			       drv_name);
+			return CMD_RET_FAILURE;
+		}
+
+		list_for_each_entry_safe(filt, tmp_filt, &ldev->filter_head,
+					 sibling_node) {
+			list_del(&filt->sibling_node);
+			free(filt);
+		}
+	} else {
+		if (gs.index + 1 != argc)
+			return CMD_RET_USAGE;
+
+		if (strict_strtoul(argv[gs.index], 10, &filter_num)) {
+			printf("Invalid filter number \"%s\"\n", argv[gs.index]);
+			return CMD_RET_FAILURE;
+		}
+
+		err = log_remove_filter(drv_name, filter_num);
+		if (err) {
+			printf("Could not remove filter (err = %d)\n", err);
+			return CMD_RET_FAILURE;
+		}
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
 static int do_log_format(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
 {
@@ -103,39 +374,31 @@
 	return 0;
 }
 
-static struct cmd_tbl log_sub[] = {
-	U_BOOT_CMD_MKENT(level, CONFIG_SYS_MAXARGS, 1, do_log_level, "", ""),
-#ifdef CONFIG_LOG_TEST
-	U_BOOT_CMD_MKENT(test, 2, 1, do_log_test, "", ""),
-#endif
-	U_BOOT_CMD_MKENT(format, CONFIG_SYS_MAXARGS, 1, do_log_format, "", ""),
-	U_BOOT_CMD_MKENT(rec, CONFIG_SYS_MAXARGS, 1, do_log_rec, "", ""),
-};
-
-static int do_log(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	struct cmd_tbl *cp;
-
-	if (argc < 2)
-		return CMD_RET_USAGE;
-
-	/* drop initial "log" arg */
-	argc--;
-	argv++;
-
-	cp = find_cmd_tbl(argv[0], log_sub, ARRAY_SIZE(log_sub));
-	if (cp)
-		return cp->cmd(cmdtp, flag, argc, argv);
-
-	return CMD_RET_USAGE;
-}
-
 #ifdef CONFIG_SYS_LONGHELP
 static char log_help_text[] =
-	"level - get/set log level\n"
-#ifdef CONFIG_LOG_TEST
-	"log test - run log tests\n"
-#endif
+	"level [<level>] - get/set log level\n"
+	"categories - list log categories\n"
+	"drivers - list log drivers\n"
+	"log filter-list [OPTIONS] - list all filters for a log driver\n"
+	"\t-d <driver> - Specify the log driver to list filters from; defaults\n"
+	"\t              to console\n"
+	"log filter-add [OPTIONS] - add a new filter to a driver\n"
+	"\t-A - Allow messages matching this filter; mutually exclusive with -D\n"
+	"\t     This is the default.\n"
+	"\t-c <category> - Category to match; may be specified multiple times\n"
+	"\t-d <driver> - Specify the log driver to add the filter to; defaults\n"
+	"\t              to console\n"
+	"\t-D - Deny messages matching this filter; mutually exclusive with -A\n"
+	"\t-f <files_list> - A comma-separated list of files to match\n"
+	"\t-l <level> - Match log levels less than or equal to <level>;\n"
+	"\t             mutually-exclusive with -L\n"
+	"\t-L <level> - Match log levels greather than or equal to <level>;\n"
+	"\t             mutually-exclusive with -l\n"
+	"\t-p - Print the filter number on success\n"
+	"log filter-remove [OPTIONS] [<num>] - Remove filter number <num>\n"
+	"\t-a - Remove ALL filters\n"
+	"\t-d <driver> - Specify the log driver to remove the filter from;\n"
+	"\t              defaults to console\n"
 	"log format <fmt> - set log output format. <fmt> is a string where\n"
 	"\teach letter indicates something that should be displayed:\n"
 	"\tc=category, l=level, F=file, L=line number, f=function, m=msg\n"
@@ -145,7 +408,14 @@
 	;
 #endif
 
-U_BOOT_CMD(
-	log, CONFIG_SYS_MAXARGS, 1, do_log,
-	"log system", log_help_text
+U_BOOT_CMD_WITH_SUBCMDS(log, "log system", log_help_text,
+	U_BOOT_SUBCMD_MKENT(level, 2, 1, do_log_level),
+	U_BOOT_SUBCMD_MKENT(categories, 1, 1, do_log_categories),
+	U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_log_drivers),
+	U_BOOT_SUBCMD_MKENT(filter-list, 3, 1, do_log_filter_list),
+	U_BOOT_SUBCMD_MKENT(filter-add, CONFIG_SYS_MAXARGS, 1,
+			    do_log_filter_add),
+	U_BOOT_SUBCMD_MKENT(filter-remove, 4, 1, do_log_filter_remove),
+	U_BOOT_SUBCMD_MKENT(format, 2, 1, do_log_format),
+	U_BOOT_SUBCMD_MKENT(rec, 7, 1, do_log_rec),
 );
diff --git a/common/fdt_support.c b/common/fdt_support.c
index a565b47..5ae75df 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -611,14 +611,9 @@
 	if (node < 0)
 		return node;
 
-	/*
-	 * We record these as 32bit entities, possibly truncating addresses.
-	 * However, spl_fit.c is not 64bit safe either: i.e. we should not
-	 * have an issue here.
-	 */
-	fdt_setprop_u32(blob, node, "load-addr", load_addr);
+	fdt_setprop_u64(blob, node, "load", load_addr);
 	if (entry_point != -1)
-		fdt_setprop_u32(blob, node, "entry-point", entry_point);
+		fdt_setprop_u64(blob, node, "entry", entry_point);
 	fdt_setprop_u32(blob, node, "size", size);
 	if (type)
 		fdt_setprop_string(blob, node, "type", type);
diff --git a/common/image-fit.c b/common/image-fit.c
index d54eff9..c82d4d8 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -791,17 +791,18 @@
 		return -1;
 	}
 
-	if (len > sizeof(ulong)) {
-		printf("Unsupported %s address size\n", name);
-		return -1;
-	}
-
 	cell_len = len >> 2;
 	/* Use load64 to avoid compiling warning for 32-bit target */
 	while (cell_len--) {
 		load64 = (load64 << 32) | uimage_to_cpu(*cell);
 		cell++;
 	}
+
+	if (len > sizeof(ulong) && (uint32_t)(load64 >> 32)) {
+		printf("Unsupported %s address size\n", name);
+		return -1;
+	}
+
 	*load = (ulong)load64;
 
 	return 0;
diff --git a/common/log.c b/common/log.c
index 9f98e9a..4b6f3fc 100644
--- a/common/log.c
+++ b/common/log.c
@@ -13,7 +13,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static const char *log_cat_name[] = {
+static const char *const log_cat_name[] = {
 	"none",
 	"arch",
 	"board",
@@ -31,7 +31,7 @@
 _Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE,
 	       "log_cat_name size");
 
-static const char *log_level_name[] = {
+static const char *const log_level_name[] = {
 	"EMERG",
 	"ALERT",
 	"CRIT",
@@ -99,7 +99,7 @@
 	return LOGL_NONE;
 }
 
-static struct log_device *log_device_find_by_name(const char *drv_name)
+struct log_device *log_device_find_by_name(const char *drv_name)
 {
 	struct log_device *ldev;
 
@@ -111,15 +111,7 @@
 	return NULL;
 }
 
-/**
- * log_has_cat() - check if a log category exists within a list
- *
- * @cat_list: List of categories to check, at most LOGF_MAX_CATEGORIES entries
- *	long, terminated by LC_END if fewer
- * @cat: Category to search for
- * @return true if @cat is in @cat_list, else false
- */
-static bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat)
+bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat)
 {
 	int i;
 
@@ -131,16 +123,7 @@
 	return false;
 }
 
-/**
- * log_has_file() - check if a file is with a list
- *
- * @file_list: List of files to check, separated by comma
- * @file: File to check for. This string is matched against the end of each
- *	file in the list, i.e. ignoring any preceding path. The list is
- *	intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c
- * @return true if @file is in @file_list, else false
- */
-static bool log_has_file(const char *file_list, const char *file)
+bool log_has_file(const char *file_list, const char *file)
 {
 	int file_len = strlen(file);
 	const char *s, *p;
@@ -179,15 +162,25 @@
 	}
 
 	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
-		if (rec->level > filt->max_level)
+		if (filt->flags & LOGFF_LEVEL_MIN) {
+			if (rec->level < filt->level)
+				continue;
+		} else if (rec->level > filt->level) {
 			continue;
+		}
+
 		if ((filt->flags & LOGFF_HAS_CAT) &&
 		    !log_has_cat(filt->cat_list, rec->cat))
 			continue;
+
 		if (filt->file_list &&
 		    !log_has_file(filt->file_list, rec->file))
 			continue;
-		return true;
+
+		if (filt->flags & LOGFF_DENY)
+			return false;
+		else
+			return true;
 	}
 
 	return false;
@@ -263,8 +256,9 @@
 	return 0;
 }
 
-int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
-		   enum log_level_t max_level, const char *file_list)
+int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[],
+			 enum log_level_t level, const char *file_list,
+			 int flags)
 {
 	struct log_filter *filt;
 	struct log_device *ldev;
@@ -278,6 +272,7 @@
 	if (!filt)
 		return -ENOMEM;
 
+	filt->flags = flags;
 	if (cat_list) {
 		filt->flags |= LOGFF_HAS_CAT;
 		for (i = 0; ; i++) {
@@ -290,16 +285,20 @@
 				break;
 		}
 	}
-	filt->max_level = max_level;
+	filt->level = level;
 	if (file_list) {
 		filt->file_list = strdup(file_list);
 		if (!filt->file_list) {
-			ret = ENOMEM;
+			ret = -ENOMEM;
 			goto err;
 		}
 	}
 	filt->filter_num = ldev->next_filter_num++;
-	list_add_tail(&filt->sibling_node, &ldev->filter_head);
+	/* Add deny filters to the beginning of the list */
+	if (flags & LOGFF_DENY)
+		list_add(&filt->sibling_node, &ldev->filter_head);
+	else
+		list_add_tail(&filt->sibling_node, &ldev->filter_head);
 
 	return filt->filter_num;
 
diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c
index b54b4f0..9bd25f6 100644
--- a/common/spl/spl_atf.c
+++ b/common/spl/spl_atf.c
@@ -132,10 +132,11 @@
 uintptr_t spl_fit_images_get_entry(void *blob, int node)
 {
 	ulong  val;
+	int ret;
 
-	val = fdt_getprop_u32(blob, node, "entry-point");
-	if (val == FDT_ERROR)
-		val = fdt_getprop_u32(blob, node, "load-addr");
+	ret = fit_image_get_entry(blob, node, &val);
+	if (ret)
+		ret = fit_image_get_load(blob, node, &val);
 
 	debug("%s: entry point 0x%lx\n", __func__, val);
 	return val;
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index fd6086a..f5109e8 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -332,9 +332,15 @@
 	}
 
 	if (image_info) {
+		ulong entry_point;
+
 		image_info->load_addr = load_addr;
 		image_info->size = length;
-		image_info->entry_point = fdt_getprop_u32(fit, node, "entry");
+
+		if (!fit_image_get_entry(fit, node, &entry_point))
+			image_info->entry_point = entry_point;
+		else
+			image_info->entry_point = FDT_ERROR;
 	}
 
 	return 0;
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
index 14f335f..41e0746 100644
--- a/common/spl/spl_opensbi.c
+++ b/common/spl/spl_opensbi.c
@@ -61,11 +61,9 @@
 	}
 
 	/* Get U-Boot entry point */
-	uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
-				      "entry-point");
-	if (uboot_entry == FDT_ERROR)
-		uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
-					      "load-addr");
+	ret = fit_image_get_entry(spl_image->fdt_addr, uboot_node, &uboot_entry);
+	if (ret)
+		ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry);
 
 	/* Prepare obensbi_info object */
 	opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE;
diff --git a/configs/aristainetos2_defconfig b/configs/aristainetos2_defconfig
index 81863f6..35e4b09 100644
--- a/configs/aristainetos2_defconfig
+++ b/configs/aristainetos2_defconfig
@@ -58,6 +58,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SPI_EARLY=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
diff --git a/configs/aristainetos2b_defconfig b/configs/aristainetos2b_defconfig
index 2e59c30..d47a074 100644
--- a/configs/aristainetos2b_defconfig
+++ b/configs/aristainetos2b_defconfig
@@ -56,6 +56,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SPI_EARLY=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
diff --git a/configs/aristainetos2bcsl_defconfig b/configs/aristainetos2bcsl_defconfig
index 8e6d299..3013962 100644
--- a/configs/aristainetos2bcsl_defconfig
+++ b/configs/aristainetos2bcsl_defconfig
@@ -56,6 +56,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SPI_EARLY=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
diff --git a/configs/aristainetos2c_defconfig b/configs/aristainetos2c_defconfig
index 372d705..50cadb7 100644
--- a/configs/aristainetos2c_defconfig
+++ b/configs/aristainetos2c_defconfig
@@ -56,6 +56,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_SPI_EARLY=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
diff --git a/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig b/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig
index 25282ba..2426179 100644
--- a/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig
+++ b/configs/avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig
@@ -8,6 +8,8 @@
 CONFIG_DEBUG_UART_CLOCK=100000000
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_ZYNQ_MAC_IN_EEPROM=y
+CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xfa
 CONFIG_DEFAULT_DEVICE_TREE="avnet-ultrazedev-cc-v1.0-ultrazedev-som-v1.0"
 CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -42,7 +44,6 @@
 CONFIG_I2C_MUX_PCA954x=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
-CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xfa
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ZYNQ=y
 CONFIG_SPI_FLASH_BAR=y
diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig
index bfbdb49..08c8885 100644
--- a/configs/microblaze-generic_defconfig
+++ b/configs/microblaze-generic_defconfig
@@ -12,6 +12,7 @@
 CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
 CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=1
 CONFIG_DEFAULT_DEVICE_TREE="microblaze-generic"
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTDELAY=-1
@@ -21,13 +22,12 @@
 CONFIG_PREBOOT="echo U-BOOT for ${hostname};setenv preboot;echo"
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SYS_OS_BASE=0x2c060000
-CONFIG_HUSH_PARSER=y
-# CONFIG_AUTO_COMPLETE is not set
 CONFIG_SYS_PROMPT="U-Boot-mONStR> "
 CONFIG_CMD_IMLS=y
 CONFIG_CMD_SPL=y
@@ -35,10 +35,7 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SAVES=y
 # CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_DHCP=y
 CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_JFFS2=y
 CONFIG_SPL_OF_CONTROL=y
@@ -47,6 +44,7 @@
 CONFIG_NETCONSOLE=y
 CONFIG_SPL_DM=y
 CONFIG_XILINX_GPIO=y
+CONFIG_DM_I2C=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_MTD=y
@@ -56,6 +54,12 @@
 CONFIG_FLASH_CFI_MTD=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHY_ATHEROS=y
 CONFIG_PHY_BROADCOM=y
 CONFIG_PHY_DAVICOM=y
@@ -71,6 +75,7 @@
 CONFIG_XILINX_EMACLITE=y
 CONFIG_SYS_NS16550=y
 CONFIG_XILINX_UARTLITE=y
+CONFIG_XILINX_SPI=y
 CONFIG_SYSRESET_GPIO=y
 CONFIG_SYSRESET_MICROBLAZE=y
 CONFIG_WDT=y
diff --git a/configs/octeontx2_95xx_defconfig b/configs/octeontx2_95xx_defconfig
index e37c837..591caa7 100644
--- a/configs/octeontx2_95xx_defconfig
+++ b/configs/octeontx2_95xx_defconfig
@@ -86,6 +86,8 @@
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_DM_ETH=y
+CONFIG_NET_OCTEONTX2=y
+CONFIG_OCTEONTX_SMI=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
diff --git a/configs/octeontx2_96xx_defconfig b/configs/octeontx2_96xx_defconfig
index 403ea51..0a8888a 100644
--- a/configs/octeontx2_96xx_defconfig
+++ b/configs/octeontx2_96xx_defconfig
@@ -99,6 +99,8 @@
 CONFIG_E1000=y
 CONFIG_E1000_SPI=y
 CONFIG_CMD_E1000=y
+CONFIG_NET_OCTEONTX2=y
+CONFIG_OCTEONTX_SMI=y
 CONFIG_NVME=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/configs/octeontx_81xx_defconfig b/configs/octeontx_81xx_defconfig
index 78efcf5..c006a14 100644
--- a/configs/octeontx_81xx_defconfig
+++ b/configs/octeontx_81xx_defconfig
@@ -100,6 +100,8 @@
 CONFIG_E1000=y
 CONFIG_E1000_SPI=y
 CONFIG_CMD_E1000=y
+CONFIG_NET_OCTEONTX=y
+CONFIG_OCTEONTX_SMI=y
 CONFIG_NVME=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/configs/octeontx_83xx_defconfig b/configs/octeontx_83xx_defconfig
index f5b0528..86b4bc5 100644
--- a/configs/octeontx_83xx_defconfig
+++ b/configs/octeontx_83xx_defconfig
@@ -97,6 +97,8 @@
 CONFIG_E1000=y
 CONFIG_E1000_SPI=y
 CONFIG_CMD_E1000=y
+CONFIG_NET_OCTEONTX=y
+CONFIG_OCTEONTX_SMI=y
 CONFIG_NVME=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/configs/syzygy_hub_defconfig b/configs/syzygy_hub_defconfig
index 8f69006..276c476 100644
--- a/configs/syzygy_hub_defconfig
+++ b/configs/syzygy_hub_defconfig
@@ -9,6 +9,8 @@
 CONFIG_SPL=y
 CONFIG_DEBUG_UART_BASE=0xe0000000
 CONFIG_DEBUG_UART_CLOCK=50000000
+CONFIG_ZYNQ_MAC_IN_EEPROM=y
+CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xFA
 CONFIG_DEFAULT_DEVICE_TREE="zynq-syzygy-hub"
 CONFIG_DEBUG_UART=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -40,7 +42,6 @@
 CONFIG_FPGA_ZYNQPL=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
-CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xFA
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ZYNQ=y
 CONFIG_PHY_MARVELL=y
diff --git a/configs/xilinx_versal_mini_defconfig b/configs/xilinx_versal_mini_defconfig
index e72cef9..427268b 100644
--- a/configs/xilinx_versal_mini_defconfig
+++ b/configs/xilinx_versal_mini_defconfig
@@ -7,7 +7,7 @@
 CONFIG_ENV_SIZE=0x80
 CONFIG_SYS_MALLOC_LEN=0x2000
 CONFIG_SYS_MEM_RSVD_FOR_MMU=y
-CONFIG_COUNTER_FREQUENCY=2720000
+CONFIG_COUNTER_FREQUENCY=100000000
 # CONFIG_PSCI_RESET is not set
 CONFIG_DEFAULT_DEVICE_TREE="versal-mini"
 # CONFIG_EXPERT is not set
diff --git a/configs/xilinx_versal_mini_emmc0_defconfig b/configs/xilinx_versal_mini_emmc0_defconfig
index b5c3ae4..8837987 100644
--- a/configs/xilinx_versal_mini_emmc0_defconfig
+++ b/configs/xilinx_versal_mini_emmc0_defconfig
@@ -6,7 +6,7 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
 CONFIG_SYS_MALLOC_LEN=0x80000
-CONFIG_COUNTER_FREQUENCY=2720000
+CONFIG_COUNTER_FREQUENCY=100000000
 # CONFIG_PSCI_RESET is not set
 CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc0"
 # CONFIG_EXPERT is not set
diff --git a/configs/xilinx_versal_mini_emmc1_defconfig b/configs/xilinx_versal_mini_emmc1_defconfig
index 871f8cc..b07dc04 100644
--- a/configs/xilinx_versal_mini_emmc1_defconfig
+++ b/configs/xilinx_versal_mini_emmc1_defconfig
@@ -6,7 +6,7 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x80
 CONFIG_SYS_MALLOC_LEN=0x80000
-CONFIG_COUNTER_FREQUENCY=2720000
+CONFIG_COUNTER_FREQUENCY=100000000
 # CONFIG_PSCI_RESET is not set
 CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc1"
 # CONFIG_EXPERT is not set
diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig
index 5175571..7291c51 100644
--- a/configs/xilinx_versal_virt_defconfig
+++ b/configs/xilinx_versal_virt_defconfig
@@ -4,8 +4,9 @@
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_SYS_MALLOC_F_LEN=0x100000
 CONFIG_DM_GPIO=y
+CONFIG_CMD_FRU=y
 CONFIG_DEFINE_TCM_OCM_MMAP=y
-CONFIG_COUNTER_FREQUENCY=62500000
+CONFIG_COUNTER_FREQUENCY=100000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
@@ -27,6 +28,7 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MTD=y
+CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
@@ -51,6 +53,7 @@
 CONFIG_I2C_EEPROM=y
 CONFIG_SYS_I2C_EEPROM_ADDR=0x0
 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW=0x0
+CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS400_SUPPORT=y
@@ -83,6 +86,7 @@
 CONFIG_XILINX_UARTLITE=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_ZYNQ_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig
index b127945..da84c01 100644
--- a/configs/xilinx_zynq_virt_defconfig
+++ b/configs/xilinx_zynq_virt_defconfig
@@ -6,6 +6,8 @@
 CONFIG_DM_GPIO=y
 CONFIG_SPL_STACK_R_ADDR=0x200000
 CONFIG_SPL=y
+CONFIG_CMD_FRU=y
+CONFIG_CMD_ZYNQ_AES=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_CUSTOM_LDSCRIPT=y
@@ -40,6 +42,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_NAND_LOCK_UNLOCK=y
+CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
@@ -49,7 +52,7 @@
 CONFIG_CMD_MTDPARTS_SPREAD=y
 CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y
 CONFIG_CMD_UBI=y
-CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0"
+CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zturn-v5 zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0"
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
@@ -88,6 +91,8 @@
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHY_MARVELL=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_PHY_REALTEK=y
 CONFIG_PHY_XILINX=y
 CONFIG_MII=y
diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig
index 264b662..0c816de 100644
--- a/configs/xilinx_zynqmp_virt_defconfig
+++ b/configs/xilinx_zynqmp_virt_defconfig
@@ -7,6 +7,9 @@
 CONFIG_SPL=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_ZYNQ_MAC_IN_EEPROM=y
+CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20
+CONFIG_CMD_FRU=y
 CONFIG_ZYNQMP_USB=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu100-revC"
 CONFIG_AHCI=y
@@ -19,6 +22,7 @@
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SPL_FPGA=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
@@ -45,10 +49,12 @@
 CONFIG_CMD_NAND_LOCK_UNLOCK=y
 CONFIG_CMD_POWEROFF=y
 CONFIG_CMD_SDRAM=y
+CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_EXT4_WRITE=y
@@ -58,6 +64,7 @@
 CONFIG_CMD_UBI=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_LIST="avnet-ultra96-rev1 zynqmp-a2197-revA zynqmp-e-a2197-00-revA zynqmp-g-a2197-00-revA zynqmp-m-a2197-01-revA zynqmp-m-a2197-02-revA zynqmp-m-a2197-03-revA zynqmp-p-a2197-00-revA zynqmp-zc1232-revA zynqmp-zc1254-revA zynqmp-zc1751-xm015-dc1 zynqmp-zc1751-xm016-dc2 zynqmp-zc1751-xm017-dc3 zynqmp-zc1751-xm018-dc4 zynqmp-zc1751-xm019-dc5 zynqmp-zcu100-revC zynqmp-zcu102-rev1.1 zynqmp-zcu102-rev1.0 zynqmp-zcu102-revA zynqmp-zcu102-revB zynqmp-zcu104-revA zynqmp-zcu104-revC zynqmp-zcu106-revA zynqmp-zcu111-revA zynqmp-zcu1275-revA zynqmp-zcu1275-revB zynqmp-zcu1285-revA zynqmp-zcu208-revA zynqmp-zcu216-revA zynqmp-topic-miamimp-xilinx-xdp-v1r1"
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent interrupts iommus power-domains"
 CONFIG_ENV_IS_NOWHERE=y
 CONFIG_ENV_IS_IN_FAT=y
 CONFIG_ENV_IS_IN_NAND=y
@@ -88,7 +95,6 @@
 CONFIG_LED_GPIO=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
-CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20
 CONFIG_SYS_I2C_EEPROM_ADDR=0x0
 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW=0x0
 CONFIG_SUPPORT_EMMC_BOOT=y
diff --git a/doc/api/getopt.rst b/doc/api/getopt.rst
new file mode 100644
index 0000000..773f79a
--- /dev/null
+++ b/doc/api/getopt.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+
+Option Parsing
+==============
+
+.. kernel-doc:: include/getopt.h
+   :internal:
diff --git a/doc/api/index.rst b/doc/api/index.rst
index 787b677..ae4a1b6 100644
--- a/doc/api/index.rst
+++ b/doc/api/index.rst
@@ -8,6 +8,7 @@
 
    dfu
    efi
+   getopt
    linker_lists
    pinctrl
    rng
diff --git a/doc/board/xilinx/index.rst b/doc/board/xilinx/index.rst
index 47f0929..2e31fe3 100644
--- a/doc/board/xilinx/index.rst
+++ b/doc/board/xilinx/index.rst
@@ -8,3 +8,5 @@
 
    xilinx
    zynq
+   zynqmp
+   zynqmp-r5
diff --git a/doc/board/xilinx/xilinx.rst b/doc/board/xilinx/xilinx.rst
index f6ea5db..8c9afb4 100644
--- a/doc/board/xilinx/xilinx.rst
+++ b/doc/board/xilinx/xilinx.rst
@@ -10,18 +10,28 @@
 
 * ata
 	- Documentation/devicetree/bindings/ata/ahci-ceva.txt
+* clock
+	- Documentation/devicetree/bindings/clock/xlnx,zynqmp-clk.txt
+* firmware
+	- Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
+* fpga
+	- Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt
 * gpio
 	- Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
 	- Documentation/devicetree/bindings/gpio/gpio-zynq.txt
 * i2c
-	- Documentation/devicetree/bindings/i2c/i2c-xiic.txt
-	- Documentation/devicetree/bindings/i2c/i2c-cadence.txt
+	- Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
+	- Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
 * mmc
-	- Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
+	- Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml
 * net
 	- Documentation/devicetree/bindings/net/macb.txt
 	- Documentation/devicetree/bindings/net/xilinx_axienet.txt
 	- Documentation/devicetree/bindings/net/xilinx_emaclite.txt
+* nvmem
+	- Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
+* power
+	- Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
 * serial
 	- Documentation/devicetree/bindings/serial/cdns,uart.txt
 	- Documentation/devicetree/bindings/serial/xlnx,opb-uartlite.txt
diff --git a/doc/board/xilinx/zynq.rst b/doc/board/xilinx/zynq.rst
index f564434..438912f 100644
--- a/doc/board/xilinx/zynq.rst
+++ b/doc/board/xilinx/zynq.rst
@@ -83,7 +83,7 @@
 ---------------
 
 - Added basic board configurations support.
-- Added zynq u-boot bsp code - arch/arm/cpu/armv7/zynq
+- Added zynq u-boot bsp code - arch/arm/mach-zynq
 - Added zynq boards named - zc70x, zed, microzed, zc770_xm010/xm011/xm012/xm013
 - Added zynq drivers:
 
@@ -99,11 +99,6 @@
 - Added basic FDT support for zynq boards
 - d-cache support for zynq_gem.c
 
-TODO
-----
-
-Add FDT support on individual drivers
-
 * [1] http://www.xilinx.com/products/boards-and-kits/EK-Z7-ZC702-G.htm
 * [2] http://www.xilinx.com/products/boards-and-kits/EK-Z7-ZC706-G.htm
 * [3] http://zedboard.org/product/zedboard
diff --git a/doc/board/xilinx/zynqmp-r5.rst b/doc/board/xilinx/zynqmp-r5.rst
new file mode 100644
index 0000000..2cd368b
--- /dev/null
+++ b/doc/board/xilinx/zynqmp-r5.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+..  (C) Copyright 2020 Xilinx, Inc.
+
+ZYNQMP-R5
+=========
+
+About this
+----------
+
+This document describes the information about Xilinx Zynq UltraScale+ MPSOC
+U-Boot Cortex R5 support.
+
+ZynqMP R5 boards
+----------------
+
+* zynqmp-r5 - U-Boot running on RPU Cortex-R5
+
+Building
+--------
+
+configure and build armv7 toolchain::
+
+   $ make xilinx_zynqmp_r5_defconfig
+   $ make
+
+Notes
+^^^^^
+
+Output fragment is u-boot.
+
+Loading
+-------
+
+ZynqMP R5 U-Boot was created for supporting loading OS on RPU. There are two
+ways how to start U-Boot on R5.
+
+Bootgen
+^^^^^^^
+
+The first way is to use Xilinx FSBL (First stage
+bootloader) to load u-boot and start it. The following bif can be used for boot
+image generation via Xilinx bootgen utility::
+
+
+  the_ROM_image:
+  {
+  	[bootloader,destination_cpu=r5-0] fsbl_rpu.elf
+  	[destination_cpu=r5-0]u-boot.elf
+  }
+
+Bootgen command for building boot.bin::
+
+  bootgen -image <bif>.bif -r -w -o i boot.bin
+
+
+U-Boot cpu command
+^^^^^^^^^^^^^^^^^^
+
+The second way to load U-Boot to Cortex R5 is from U-Boot running on A53 as is
+visible from the following log::
+
+  U-Boot SPL 2020.10-rc4-00090-g801b3d5c5757 (Sep 15 2020 - 14:07:24 +0200)
+  PMUFW:	v1.1
+  Loading new PMUFW cfg obj (2024 bytes)
+  EL Level:	EL3
+  Multiboot:	0
+  Trying to boot from MMC2
+  spl: could not initialize mmc. error: -19
+  Trying to boot from MMC1
+  spl_load_image_fat_os: error reading image u-boot.bin, err - -2
+  NOTICE:  ATF running on XCZU7EG/EV/silicon v4/RTL5.1 at 0xfffea000
+  NOTICE:  BL31: v2.2(release):v2.2-614-ged9dc512fb9c
+  NOTICE:  BL31: Built : 09:32:09, Mar 13 2020
+
+
+  U-Boot 2020.10-rc4-00090-g801b3d5c5757 (Sep 15 2020 - 14:07:24 +0200)
+
+  Model: ZynqMP ZCU104 RevC
+  Board: Xilinx ZynqMP
+  DRAM:  2 GiB
+  PMUFW:	v1.1
+  EL Level:	EL2
+  Chip ID:	zu7e
+  WDT:   Started with servicing (60s timeout)
+  NAND:  0 MiB
+  MMC:   mmc@ff170000: 0
+  Loading Environment from FAT... *** Warning - bad CRC, using default environment
+
+  In:    serial
+  Out:   serial
+  Err:   serial
+  Bootmode: LVL_SHFT_SD_MODE1
+  Reset reason:	SOFT
+  Net:
+  ZYNQ GEM: ff0e0000, mdio bus ff0e0000, phyaddr 12, interface rgmii-id
+  eth0: ethernet@ff0e0000
+  Hit any key to stop autoboot:  0
+  ZynqMP> setenv autoload no
+  ZynqMP> dhcp
+  BOOTP broadcast 1
+  DHCP client bound to address 192.168.0.167 (8 ms)
+  ZynqMP> tftpboot 20000000 192.168.0.105:u-boot-r5-2.elf
+  Using ethernet@ff0e0000 device
+  TFTP from server 192.168.0.105; our IP address is 192.168.0.167
+  Filename 'u-boot-r5-2.elf'.
+  Load address: 0x20000000
+  Loading: #################################################################
+  	 #################################################################
+  	 #################################################################
+  	 #################################################################
+  	 #################################################################
+  	 #################################################################
+  	 ################
+  	 376 KiB/s
+  done
+  Bytes transferred = 2075464 (1fab48 hex)
+  ZynqMP> setenv autostart no
+  ZynqMP> bootelf -p 20000000
+  ZynqMP> cpu 4 release 10000000 lockstep
+  Using TCM jump trampoline for address 0x10000000
+  R5 lockstep mode
+  ZynqMP>
+
+Then on second uart you can see U-Boot up and running on R5::
+
+  U-Boot 2020.10-rc4-00071-g7045622cc9ba (Sep 16 2020 - 13:38:53 +0200)
+
+  Model: Xilinx ZynqMP R5
+  DRAM:  512 MiB
+  MMC:
+  In:    serial@ff010000
+  Out:   serial@ff010000
+  Err:   serial@ff010000
+  Net:   No ethernet found.
+  ZynqMP r5>
+
+Please make sure MIO pins for uart are properly configured to see output.
diff --git a/doc/board/xilinx/zynqmp.rst b/doc/board/xilinx/zynqmp.rst
new file mode 100644
index 0000000..a035cff
--- /dev/null
+++ b/doc/board/xilinx/zynqmp.rst
@@ -0,0 +1,115 @@
+.. SPDX-License-Identifier: GPL-2.0
+..  (C) Copyright 2020 Xilinx, Inc.
+
+ZYNQMP
+======
+
+About this
+----------
+
+This document describes the information about Xilinx Zynq UltraScale+ MPSOC
+U-Boot support. Core support is available in arch/arm/mach-zynqmp folder.
+
+ZynqMP boards
+-------------
+
+* zcu100 (ultra96 v1), zcu102, zcu104, zcu106 - Evaluation boards
+* zc1232 - Characterization boards
+* zcu111, zcu208, zcu216 - RFSOC evaluation boards
+* zcu1254, zcu1275, zcu1285 - RFSOC characterization boards
+* a2197 - System Controller on Versal boards
+* mini - Mini U-Boot running out of OCM
+* zc1751 - Characterization Processor boards
+     - zc1751-xm015-dc1
+     - zc1751-xm016-dc2
+     - zc1751-xm017-dc3
+     - zc1751-xm018-dc4
+     - zc1751-xm019-dc5
+
+Building
+--------
+
+Configure and build for zcu102 board::
+
+   $ source arm64 toolchain
+   $ export DEVICE_TREE=zynqmp-zcu102-revA
+   $ make xilinx_zynqmp_virt_defconfig
+   $ make
+
+U-Boot SPL flow
+---------------
+
+For getting U-Boot SPL flow up and running it is necessary to do some additional
+steps because booting device requires external images which are not the part of
+U-Boot repository.
+
+PMU firmware
+^^^^^^^^^^^^
+The Platform Management Unit (PMU) RAM can be loaded with a firmware (PMU
+Firmware) at run-time and can be used to extend or customize the functionality
+of PMU. The PMU firmware is the part of boot image (boot.bin) and it is
+automatically loaded by BootROM. boot.bin can be directly generated by mkimage
+tool as the part of make. If you want to create boot.bin with PMU Firmware
+include please point CONFIG_PMUFW_INIT_FILE to PMU firmware binary. For example:::
+
+  CONFIG_PMUFW_INIT_FILE="<path>/pmu.bin"
+
+If you see below message you need to load PMU Firmware::
+
+  PMUFW is not found - Please load it!
+
+The second external blob is PMU Configuration object which is object which is
+passed from U-Boot SPL to PMU Firmware for initial system configuration. PMU
+configuration object is the part of U-Boot SPL image. For pointing to this
+object please use CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE symbol. For example:::
+
+  CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE="<path>/pmu_obj.bin"
+
+
+PMU configuration object
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Object can be obtain in several ways. The easiest way is to take pm_cfg_obj.c
+from SDK/Vitis design and build it:::
+
+  $ git clone https://github.com/Xilinx/embeddedsw.git
+  $ export EMBEDDED_SW=$PWD/embeddedsw
+  $ gcc -c pm_cfg_obj.c -I ${EMBEDDED_SW}/lib/bsp/standalone/src/common/ -I ${EMBEDDED_SW}/lib/sw_services/xilpm/src/zynqmp/client/common/
+  $ objcopy -O binary pm_cfg_obj.o pmu_obj.bin
+
+The second way is to use tools/zynqmp_pm_cfg_obj_convert.py. For more
+information about this tool please run it with -h parameter.
+
+The third way is to extract it from Xilinx FSBL elf file. Object is starting at
+XPm_ConfigObject symbol.
+
+
+Arm Trusted Firmware (ATF)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+U-Boot itself can run from EL3 to EL1. Without ATF U-Boot runs in EL3. Boot flow
+is U-Boot SPL->U-Boot in EL3. When ATF is used U-Boot normally runs in EL2. Boot
+flow is U-Boot SPL->ATF->U-Boot in EL2. As the part of build process u-boot.itb
+is generated. When BL31 shell variable is present u-boot.itb is generated with
+ATF included. You can point to it by:::
+
+  $ export BL31=<path>/bl31.bin
+
+Flashing
+--------
+
+SD Card
+^^^^^^^
+
+To write an image that boots from a SD card first create a FAT32 partition
+and a FAT32 filesystem on the SD card::
+
+        sudo fdisk /dev/sdx
+        sudo mkfs.vfat -F 32 /dev/sdx1
+
+Mount the SD card and copy the SPL and U-Boot to the root directory of the
+SD card::
+
+        sudo mount -t vfat /dev/sdx1 /mnt
+        sudo cp spl/boot.bin /mnt
+        sudo cp u-boot.itb /mnt
diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst
index 528280c..7fdd113 100644
--- a/doc/develop/logging.rst
+++ b/doc/develop/logging.rst
@@ -21,26 +21,13 @@
 U-Boot's logging feature aims to satisfy this goal for both users and
 developers.
 
-
 Logging levels
 --------------
 
-There are a number logging levels available, in increasing order of verbosity:
-
-* LOGL_EMERG - Printed before U-Boot halts
-* LOGL_ALERT - Indicates action must be taken immediate or U-Boot will crash
-* LOGL_CRIT - Indicates a critical error that will cause boot failure
-* LOGL_ERR - Indicates an error that may cause boot failure
-* LOGL_WARNING - Warning about an unexpected condition
-* LOGL_NOTE - Important information about progress
-* LOGL_INFO - Information about normal boot progress
-* LOGL_DEBUG - Debug information (useful for debugging a driver or subsystem)
-* LOGL_DEBUG_CONTENT - Debug message showing full message content
-* LOGL_DEBUG_IO - Debug message showing hardware I/O access
+There are a number logging levels available.
 
-To continue a log message in a separate call of function log() use
-
-* LOGL_CONT - Use same log level as in previous call
+.. kernel-doc:: include/log.h
+   :identifiers: log_level_t
 
 Logging category
 ----------------
@@ -49,19 +36,8 @@
 has a category which is intended to allow messages to be filtered according to
 their source.
 
-The following main categories are defined:
-
-* LOGC_NONE - Unknown category (e.g. a debug() statement)
-* UCLASS\_... - Related to a particular uclass (e.g. UCLASS_USB)
-* LOGC_ARCH - Related to architecture-specific code
-* LOGC_BOARD - Related to board-specific code
-* LOGC_CORE - Related to core driver-model support
-* LOGC_DT - Related to device tree control
-* LOGC_EFI - Related to EFI implementation
-
-To continue a log message in a separate call of function log() use
-
-* LOGC_CONT - Use same category as in previous call
+.. kernel-doc:: include/log.h
+   :identifiers: log_category_t
 
 Enabling logging
 ----------------
@@ -78,7 +54,6 @@
 The above have SPL and TPL versions also, e.g. CONFIG_SPL_LOG_MAX_LEVEL and
 CONFIG_TPL_LOG_MAX_LEVEL.
 
-
 Temporary logging within a single file
 --------------------------------------
 
@@ -89,12 +64,52 @@
    #define LOG_DEBUG
 
 to enable building in of all logging statements in a single file. Put it at
-the top of the file, before any #includes. This overrides any log-level setting
-in U-Boot, including CONFIG_LOG_DEFAULT_LEVEL, but just for that file.
+the top of the file, before any #includes.
+
+To actually get U-Boot to output this you need to also set the default logging
+level - e.g. set CONFIG_LOG_DEFAULT_LEVEL to 7 (:c:type:`LOGL_DEBUG`) or more.
+Otherwise debug output is suppressed and will not be generated.
+
+Using DEBUG
+-----------
+
+U-Boot has traditionally used a #define called DEBUG to enable debugging on a
+file-by-file basis. The debug() macro compiles to a printf() statement if
+DEBUG is enabled, and an empty statement if not.
+
+With logging enabled, debug() statements are interpreted as logging output
+with a level of LOGL_DEBUG and a category of LOGC_NONE.
+
+The logging facilities are intended to replace DEBUG, but if DEBUG is defined
+at the top of a file, then it takes precedence. This means that debug()
+statements will result in output to the console and this output will not be
+logged.
+
+Logging statements
+------------------
+
+The main logging function is:
 
+.. code-block:: c
+
+   log(category, level, format_string, ...)
+
+Also debug() and error() will generate log records  - these use LOG_CATEGORY
+as the category, so you should #define this right at the top of the source
+file to ensure the category is correct.
+
+You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
+can be used whenever your function returns an error value:
+
+.. code-block:: c
+
+   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+
+This will write a log record when an error code is detected (a value < 0). This
+can make it easier to trace errors that are generated deep in the call stack.
 
 Convenience functions
----------------------
+~~~~~~~~~~~~~~~~~~~~~
 
 A number of convenience functions are available to shorten the code needed
 for logging:
@@ -122,36 +137,6 @@
 
 Remember that all uclasses IDs are log categories too.
 
-
-Log command
------------
-
-The 'log' command provides access to several features:
-
-* level - access the default log level
-* format - access the console log format
-* rec - output a log record
-* test - run tests
-
-Type 'help log' for details.
-
-
-Using DEBUG
------------
-
-U-Boot has traditionally used a #define called DEBUG to enable debugging on a
-file-by-file basis. The debug() macro compiles to a printf() statement if
-DEBUG is enabled, and an empty statement if not.
-
-With logging enabled, debug() statements are interpreted as logging output
-with a level of LOGL_DEBUG and a category of LOGC_NONE.
-
-The logging facilities are intended to replace DEBUG, but if DEBUG is defined
-at the top of a file, then it takes precedence. This means that debug()
-statements will result in output to the console and this output will not be
-logged.
-
-
 Logging destinations
 --------------------
 
@@ -165,60 +150,84 @@
 The syslog driver sends the value of environmental variable 'log_hostname' as
 HOSTNAME if available.
 
-
-Log format
-----------
-
-You can control the log format using the 'log format' command. The basic
-format is::
-
-   LEVEL.category,file.c:123-func() message
-
-In the above, file.c:123 is the filename where the log record was generated and
-func() is the function name. By default ('log format default') only the
-function name and message are displayed on the console. You can control which
-fields are present, but not the field order.
-
-
 Filters
 -------
 
-Filters are attached to log drivers to control what those drivers emit. Only
-records that pass through the filter make it to the driver.
+Filters are attached to log drivers to control what those drivers emit. FIlters
+can either allow or deny a log message when they match it. Only records which
+are allowed by a filter make it to the driver.
 
 Filters can be based on several criteria:
 
-* maximum log level
+* minimum or maximum log level
 * in a set of categories
 * in a set of files
 
 If no filters are attached to a driver then a default filter is used, which
 limits output to records with a level less than CONFIG_MAX_LOG_LEVEL.
 
+Log command
+-----------
 
-Logging statements
-------------------
+The 'log' command provides access to several features:
 
-The main logging function is:
+* level - list log levels or set the default log level
+* categories - list log categories
+* drivers - list log drivers
+* filter-list - list filters
+* filter-add - add a new filter
+* filter-remove - remove filters
+* format - access the console log format
+* rec - output a log record
 
-.. code-block:: c
+Type 'help log' for details.
 
-   log(category, level, format_string, ...)
+Log format
+~~~~~~~~~~
 
-Also debug() and error() will generate log records  - these use LOG_CATEGORY
-as the category, so you should #define this right at the top of the source
-file to ensure the category is correct.
+You can control the log format using the 'log format' command. The basic
+format is::
 
-You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
-can be used whenever your function returns an error value:
+   LEVEL.category,file.c:123-func() message
 
-.. code-block:: c
+In the above, file.c:123 is the filename where the log record was generated and
+func() is the function name. By default ('log format default') only the message
+is displayed on the console. You can control which fields are present, but not
+the field order.
 
-   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+Adding Filters
+~~~~~~~~~~~~~~
 
-This will write a log record when an error code is detected (a value < 0). This
-can make it easier to trace errors that are generated deep in the call stack.
+To add new filters at runtime, use the 'log filter-add' command. For example, to
+suppress messages from the SPI and MMC subsystems, run::
 
+    log filter-add -D -c spi -c mmc
+
+You will also need to add another filter to allow other messages (because the
+default filter no longer applies)::
+
+    log filter-add -A -l info
+
+Log levels may be either symbolic names (like above) or numbers. For example, to
+disable all debug and above (log level 7) messages from ``drivers/core/lists.c``
+and ``drivers/core/ofnode.c``, run::
+
+    log filter-add -D -f drivers/core/lists.c,drivers/core/ofnode.c -L 7
+
+To view active filters, use the 'log filter-list' command. Some example output
+is::
+
+    => log filter-list
+    num policy level            categories files
+      2   deny >= DEBUG                    drivers/core/lists.c,drivers/core/ofnode.c
+      0   deny <= IO                   spi
+                                       mmc
+      1  allow <= INFO
+
+Note that filters are processed in-order from top to bottom, not in the order of
+their filter number. Filters are added to the top of the list if they deny when
+they match, and to the bottom if they allow when they match. For more
+information, consult the usage of the 'log' command, by running 'help log'.
 
 Code size
 ---------
@@ -235,13 +244,12 @@
 bloats the code hugely. The advantage is that it is then possible to enable
 all logging within U-Boot.
 
-
 To Do
 -----
 
 There are lots of useful additions that could be made. None of the below is
-implemented! If you do one, please add a test in test/py/tests/test_log.py
-
+implemented! If you do one, please add a test in test/log/log_test.c
+log filter-add -D -f drivers/core/lists.c,drivers/core/ofnode.c -l 6
 Convenience functions to support setting the category:
 
 * log_arch(level, format_string, ...) - category LOGC_ARCH
@@ -262,25 +270,15 @@
 
 Figure out what to do with BUG(), BUG_ON() and warn_non_spl()
 
-Figure out what to do with assert()
-
 Add a way to browse log records
 
 Add a way to record log records for browsing using an external tool
 
-Add commands to add and remove filters
-
 Add commands to add and remove log devices
 
 Allow sharing of printf format strings in log records to reduce storage size
 for large numbers of log records
 
-Add a command-line option to sandbox to set the default logging level
-
-Convert core driver model code to use logging
-
-Convert uclasses to use logging with the correct category
-
 Consider making log() calls emit an automatic newline, perhaps with a logn()
 function to avoid that
 
@@ -291,9 +289,9 @@
 
 Add a printf() format string pragma so that log statements are checked properly
 
-Enhance the log console driver to show level / category / file / line
-information
+Add a command to delete existing log records.
 
-Add a command to add new log records and delete existing records.
-
-Provide additional log() functions - e.g. logc() to specify the category
+Logging API
+-----------
+.. kernel-doc:: include/log.h
+   :internal:
diff --git a/doc/uImage.FIT/howto.txt b/doc/uImage.FIT/howto.txt
index 8592719..019dda2 100644
--- a/doc/uImage.FIT/howto.txt
+++ b/doc/uImage.FIT/howto.txt
@@ -66,6 +66,90 @@
 the build process. It gets passed a list of device tree files (taken from the
 CONFIG_OF_LIST symbol).
 
+The SPL also records to a DT all additional images (called loadables) which are
+loaded. The information about loadables locations is passed via the DT node with
+fit-images name.
+
+Loadables Example
+-----------------
+Consider the following case for an ARM64 platform where U-Boot runs in EL2
+started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware).
+
+/dts-v1/;
+
+/ {
+	description = "Configuration to load ATF before U-Boot";
+
+	images {
+		uboot {
+			description = "U-Boot (64-bit)";
+			data = /incbin/("u-boot-nodtb.bin");
+			type = "firmware";
+			os = "u-boot";
+			arch = "arm64";
+			compression = "none";
+			load = <0x8 0x8000000>;
+			entry = <0x8 0x8000000>;
+			hash {
+				algo = "md5";
+			};
+		};
+		atf {
+			description = "ARM Trusted Firmware";
+			data = /incbin/("bl31.bin");
+			type = "firmware";
+			os = "arm-trusted-firmware";
+			arch = "arm64";
+			compression = "none";
+			load = <0xfffea000>;
+			entry = <0xfffea000>;
+			hash {
+				algo = "md5";
+			};
+		};
+		fdt_1 {
+			description = "zynqmp-zcu102-revA";
+			data = /incbin/("arch/arm/dts/zynqmp-zcu102-revA.dtb");
+			type = "flat_dt";
+			arch = "arm64";
+			compression = "none";
+			load = <0x100000>;
+			hash {
+				algo = "md5";
+			};
+		};
+	};
+	configurations {
+		default = "config_1";
+
+		config_1 {
+			description = "zynqmp-zcu102-revA";
+			firmware = "atf";
+			loadables = "uboot";
+			fdt = "fdt_1";
+		};
+	};
+};
+
+In this case the SPL records via fit-images DT node the information about
+loadables U-Boot image.
+
+ZynqMP> fdt addr $fdtcontroladdr
+ZynqMP> fdt print /fit-images
+fit-images {
+	uboot {
+		os = "u-boot";
+		type = "firmware";
+		size = <0x001017c8>;
+		entry = <0x00000008 0x08000000>;
+		load = <0x00000008 0x08000000>;
+	};
+};
+
+As you can see entry and load properties are 64bit wide to support loading
+images above 4GB (in past entry and load properties where just 32bit).
+
+
 Example 1 -- old-style (non-FDT) kernel booting
 -----------------------------------------------
 
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 7d1b895..a68076b 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -476,6 +476,28 @@
 	return ofnode_path(prop);
 }
 
+const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
+{
+	ofnode node;
+
+	node = ofnode_path("/aliases");
+
+	return ofnode_read_prop(node, propname, sizep);
+}
+
+ofnode ofnode_get_aliases_node(const char *name)
+{
+	const char *prop;
+
+	prop = ofnode_read_aliases_prop(name, NULL);
+	if (!prop)
+		return ofnode_null();
+
+	debug("%s: node_path: %s\n", __func__, prop);
+
+	return ofnode_path(prop);
+}
+
 int ofnode_get_child_count(ofnode parent)
 {
 	ofnode child;
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index 7583f24a..d4dc856 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -165,6 +165,14 @@
 		 */
 		u32 regs[] = {api_id, arg0, arg1, arg2, arg3};
 
+		if (api_id == PM_FPGA_LOAD) {
+			/* Swap addr_hi/low because of incompatibility */
+			u32 temp = regs[1];
+
+			regs[1] = regs[2];
+			regs[2] = temp;
+		}
+
 		ipi_req(regs, PAYLOAD_ARG_CNT, ret_payload, PAYLOAD_ARG_CNT);
 #else
 		return -EPERM;
diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c
index 9483ed9..847a036 100644
--- a/drivers/mailbox/zynqmp-ipi.c
+++ b/drivers/mailbox/zynqmp-ipi.c
@@ -56,7 +56,7 @@
 
 	/* Wait until observation bit is cleared */
 	ret = wait_for_bit_le32(&ipi_int_apu->obs, IPI_BIT_MASK_PMU0, false,
-				100, false);
+				1000, false);
 
 	debug("%s, send %ld bytes\n", __func__, msg->len);
 	return ret;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b67e906..29432ae 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -376,13 +376,6 @@
 	  This option is an SPL-variant of the I2C_EEPROM option.
 	  See the help of I2C_EEPROM for details.
 
-config ZYNQ_GEM_I2C_MAC_OFFSET
-	hex "Set the I2C MAC offset"
-	default 0x0
-	depends on DM_I2C
-	help
-	  Set the MAC offset for i2C.
-
 if I2C_EEPROM
 
 config SYS_I2C_EEPROM_ADDR
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d549a26..0628934 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -812,7 +812,8 @@
 		cfg->host_caps &= ~MMC_MODE_HS_52MHz;
 	}
 
-	if (!(cfg->voltages & MMC_VDD_165_195))
+	if (!(cfg->voltages & MMC_VDD_165_195) ||
+	    (host->quirks & SDHCI_QUIRK_NO_1_8_V))
 		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
 			    SDHCI_SUPPORT_DDR50);
 
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 775c17b..147ecc0 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -19,6 +19,20 @@
 #include <sdhci.h>
 #include <zynqmp_tap_delay.h>
 
+#define SDHCI_ARASAN_ITAPDLY_REGISTER   0xF0F8
+#define SDHCI_ARASAN_OTAPDLY_REGISTER   0xF0FC
+#define SDHCI_ITAPDLY_CHGWIN            0x200
+#define SDHCI_ITAPDLY_ENABLE            0x100
+#define SDHCI_OTAPDLY_ENABLE            0x40
+
+#define SDHCI_TUNING_LOOP_COUNT		40
+#define MMC_BANK2			0x2
+
+struct arasan_sdhci_clk_data {
+	int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
+	int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
+};
+
 struct arasan_sdhci_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
@@ -26,29 +40,35 @@
 
 struct arasan_sdhci_priv {
 	struct sdhci_host *host;
+	struct arasan_sdhci_clk_data clk_data;
 	u8 deviceid;
 	u8 bank;
+	u8 no_1p8;
 };
 
+#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
+/* Default settings for ZynqMP Clock Phases */
+const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0};
+const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
+
-#if defined(CONFIG_ARCH_ZYNQMP)
-#define MMC_HS200_BUS_SPEED	5
+/* Default settings for Versal Clock Phases */
+const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0};
+const u32 versal_oclk_phases[] = {0,  60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
 
 static const u8 mode2timing[] = {
-	[MMC_LEGACY] = UHS_SDR12_BUS_SPEED,
-	[MMC_HS] = HIGH_SPEED_BUS_SPEED,
-	[SD_HS] = HIGH_SPEED_BUS_SPEED,
-	[MMC_HS_52] = HIGH_SPEED_BUS_SPEED,
-	[MMC_DDR_52] = HIGH_SPEED_BUS_SPEED,
-	[UHS_SDR12] = UHS_SDR12_BUS_SPEED,
-	[UHS_SDR25] = UHS_SDR25_BUS_SPEED,
-	[UHS_SDR50] = UHS_SDR50_BUS_SPEED,
-	[UHS_DDR50] = UHS_DDR50_BUS_SPEED,
-	[UHS_SDR104] = UHS_SDR104_BUS_SPEED,
-	[MMC_HS_200] = MMC_HS200_BUS_SPEED,
+	[MMC_LEGACY] = MMC_TIMING_LEGACY,
+	[MMC_HS] = MMC_TIMING_MMC_HS,
+	[SD_HS] = MMC_TIMING_SD_HS,
+	[MMC_HS_52] = MMC_TIMING_UHS_SDR50,
+	[MMC_DDR_52] = MMC_TIMING_UHS_DDR50,
+	[UHS_SDR12] = MMC_TIMING_UHS_SDR12,
+	[UHS_SDR25] = MMC_TIMING_UHS_SDR25,
+	[UHS_SDR50] = MMC_TIMING_UHS_SDR50,
+	[UHS_DDR50] = MMC_TIMING_UHS_DDR50,
+	[UHS_SDR104] = MMC_TIMING_UHS_SDR104,
+	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
-#define SDHCI_TUNING_LOOP_COUNT	40
-
 static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
 {
 	u16 clk;
@@ -156,17 +176,352 @@
 	return 0;
 }
 
+/**
+ * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees:		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	arasan_zynqmp_set_tapdelay(priv->deviceid, 0, tap_delay);
+
+	return ret;
+}
+
+/**
+ * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees:		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	arasan_zynqmp_set_tapdelay(priv->deviceid, tap_delay, 0);
+
+	return ret;
+}
+
+/**
+ * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval |= SDHCI_OTAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+	}
+
+	return ret;
+}
+
+/**
+ * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval &= ~SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+	}
+
+	return ret;
+}
+
 static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 {
 	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
 	struct mmc *mmc = (struct mmc *)host->mmc;
-	u8 uhsmode;
+	struct udevice *dev = mmc->dev;
+	u8 timing = mode2timing[mmc->selected_mode];
+	u32 iclk_phase = clk_data->clk_phase_in[timing];
+	u32 oclk_phase = clk_data->clk_phase_out[timing];
+
+	dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
+
+	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
+	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+		sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
+		sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
+	} else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
+		   device_is_compatible(dev, "xlnx,versal-8.9a")) {
+		sdhci_versal_sampleclk_set_phase(host, iclk_phase);
+		sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
+	}
+}
 
-	uhsmode = mode2timing[mmc->selected_mode];
+static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
+				     const char *prop)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
+	u32 clk_phase[2] = {0};
+
+	/*
+	 * Read Tap Delay values from DT, if the DT does not contain the
+	 * Tap Values then use the pre-defined values
+	 */
+	if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
+		dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
+			prop, clk_data->clk_phase_in[timing],
+			clk_data->clk_phase_out[timing]);
+		return;
+	}
+
+	/* The values read are Input and Output Clock Delays in order */
+	clk_data->clk_phase_in[timing] = clk_phase[0];
+	clk_data->clk_phase_out[timing] = clk_phase[1];
+}
+
+/**
+ * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
+ *
+ * Called at initialization to parse the values of Tap Delays.
+ *
+ * @dev:                Pointer to our struct udevice.
+ */
+static void arasan_dt_parse_clk_phases(struct udevice *dev)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
+	int i;
 
-	if (uhsmode >= UHS_SDR25_BUS_SPEED)
-		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
-					   priv->bank);
+	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
+	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
+			clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
+		}
+
+		if (priv->bank == MMC_BANK2) {
+			clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
+			clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
+	    device_is_compatible(dev, "xlnx,versal-8.9a")) {
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = versal_iclk_phases[i];
+			clk_data->clk_phase_out[i] = versal_oclk_phases[i];
+		}
+	}
+
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
+				 "clk-phase-legacy");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
+				 "clk-phase-mmc-hs");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
+				 "clk-phase-sd-hs");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
+				 "clk-phase-uhs-sdr12");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
+				 "clk-phase-uhs-sdr25");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
+				 "clk-phase-uhs-sdr50");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
+				 "clk-phase-uhs-sdr104");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
+				 "clk-phase-uhs-ddr50");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
+				 "clk-phase-mmc-ddr52");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
+				 "clk-phase-mmc-hs200");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
+				 "clk-phase-mmc-hs400");
 }
 
 static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
@@ -184,12 +539,10 @@
 	}
 
 	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= UHS_DDR50)
+	    mmc->selected_mode <= MMC_HS_200)
 		sdhci_set_uhs_timing(host);
 }
-#endif
 
-#if defined(CONFIG_ARCH_ZYNQMP)
 const struct sdhci_ops arasan_ops = {
 	.platform_execute_tuning = &arasan_sdhci_execute_tuning,
 	.set_delay = &arasan_sdhci_set_tapdelay,
@@ -236,6 +589,9 @@
 	host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
 #endif
 
+	if (priv->no_1p8)
+		host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+
 	plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
 
 	ret = mmc_of_parse(dev, &plat->cfg);
@@ -267,8 +623,9 @@
 
 	priv->host->name = dev->name;
 
-#if defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
 	priv->host->ops = &arasan_ops;
+	arasan_dt_parse_clk_phases(dev);
 #endif
 
 	priv->host->ioaddr = (void *)dev_read_addr(dev);
@@ -277,6 +634,7 @@
 
 	priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
 	priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
+	priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index cd7e598..3cf3b14 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -195,6 +195,9 @@
 config NAND_PXA3XX
 	bool "Support for NAND on PXA3xx and Armada 370/XP/38x"
 	select SYS_NAND_SELF_INIT
+	select DM_MTD
+	select REGMAP
+	select SYSCON
 	imply CMD_NAND
 	help
 	  This enables the driver for the NAND flash device found on
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index 5fb3081..361a9e3 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -22,6 +22,10 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/types.h>
+#include <syscon.h>
+#include <regmap.h>
+#include <dm/uclass.h>
+#include <dm/read.h>
 
 #include "pxa3xx_nand.h"
 
@@ -117,6 +121,10 @@
 #define EXT_CMD_TYPE_LAST_RW	1 /* Last naked read/write */
 #define EXT_CMD_TYPE_MONO	0 /* Monolithic read/write */
 
+/* System control register and bit to enable NAND on some SoCs */
+#define GENCONF_SOC_DEVICE_MUX	0x208
+#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0)
+
 /*
  * This should be large enough to read 'ONFI' and 'JEDEC'.
  * Let's use 7 bytes, which is the maximum ID count supported
@@ -157,6 +165,7 @@
 enum pxa3xx_nand_variant {
 	PXA3XX_NAND_VARIANT_PXA,
 	PXA3XX_NAND_VARIANT_ARMADA370,
+	PXA3XX_NAND_VARIANT_ARMADA_8K,
 };
 
 struct pxa3xx_nand_host {
@@ -417,10 +426,21 @@
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
+static const struct udevice_id pxa3xx_nand_dt_ids[] = {
+	{
+		.compatible = "marvell,mvebu-pxa3xx-nand",
+		.data = PXA3XX_NAND_VARIANT_ARMADA370,
+	},
+	{
+		.compatible = "marvell,armada-8k-nand-controller",
+		.data = PXA3XX_NAND_VARIANT_ARMADA_8K,
+	},
+	{}
+};
+
-static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void)
+static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(struct udevice *dev)
 {
-	/* We only support the Armada 370/XP/38x for now */
-	return PXA3XX_NAND_VARIANT_ARMADA370;
+	return dev_get_driver_data(dev);
 }
 
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
@@ -697,7 +717,8 @@
 		info->retcode = ERR_UNCORERR;
 	if (status & NDSR_CORERR) {
 		info->retcode = ERR_CORERR;
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
+		if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+			 info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) &&
 		    info->ecc_bch)
 			info->ecc_err_cnt = NDSR_ERR_CNT(status);
 		else
@@ -752,7 +773,8 @@
 		nand_writel(info, NDCB0, info->ndcb2);
 
 		/* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+			info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
 			nand_writel(info, NDCB0, info->ndcb3);
 	}
 
@@ -1666,7 +1688,8 @@
 	}
 
 	/* Device detection must be done with ECC disabled */
-	if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+	if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+		info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
 		nand_writel(info, NDECCCTRL, 0x0);
 
 	if (nand_scan_ident(mtd, 1, NULL))
@@ -1716,7 +1739,8 @@
 	 * (aka split) command handling,
 	 */
 	if (mtd->writesize > info->chunk_size) {
-		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
+		if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
+			info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) {
 			chip->cmdfunc = nand_cmdfunc_extended;
 		} else {
 			dev_err(mtd->dev,
@@ -1752,19 +1776,19 @@
 	return nand_scan_tail(mtd);
 }
 
-static int alloc_nand_resource(struct pxa3xx_nand_info *info)
+static int alloc_nand_resource(struct udevice *dev, struct pxa3xx_nand_info *info)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_host *host;
 	struct nand_chip *chip = NULL;
 	struct mtd_info *mtd;
-	int ret, cs;
+	int cs;
 
 	pdata = info->pdata;
 	if (pdata->num_cs <= 0)
 		return -ENODEV;
 
-	info->variant = pxa3xx_nand_get_variant();
+	info->variant = pxa3xx_nand_get_variant(dev);
 	for (cs = 0; cs < pdata->num_cs; cs++) {
 		chip = (struct nand_chip *)
 			((u8 *)&info[1] + sizeof(*host) * cs);
@@ -1794,97 +1818,87 @@
 	/* Allocate a buffer to allow flash detection */
 	info->buf_size = INIT_BUFFER_SIZE;
 	info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
-	if (info->data_buff == NULL) {
-		ret = -ENOMEM;
-		goto fail_disable_clk;
-	}
+	if (info->data_buff == NULL)
+		return -ENOMEM;
 
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
 
-	return 0;
+	/*
+	 * Some SoCs like A7k/A8k need to enable manually the NAND
+	 * controller to avoid being bootloader dependent. This is done
+	 * through the use of a single bit in the System Functions registers.
+	 */
+	if (pxa3xx_nand_get_variant(dev) == PXA3XX_NAND_VARIANT_ARMADA_8K) {
+		struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle(
+				dev, "marvell,system-controller");
+		u32 reg;
 
-	kfree(info->data_buff);
-fail_disable_clk:
-	return ret;
+		if (IS_ERR(sysctrl_base))
+			return PTR_ERR(sysctrl_base);
+
+		regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, &reg);
+		reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN;
+		regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg);
+	}
+
+	return 0;
 }
 
-static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *info)
 {
 	struct pxa3xx_nand_platform_data *pdata;
-	const void *blob = gd->fdt_blob;
-	int node = -1;
 
 	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	/* Get address decoding nodes from the FDT blob */
-	do {
-		node = fdt_node_offset_by_compatible(blob, node,
-						     "marvell,mvebu-pxa3xx-nand");
-		if (node < 0)
-			break;
-
-		/* Bypass disabeld nodes */
-		if (!fdtdec_get_is_enabled(blob, node))
-			continue;
-
-		/* Get the first enabled NAND controler base address */
-		info->mmio_base =
-			(void __iomem *)fdtdec_get_addr_size_auto_noparent(
-					blob, node, "reg", 0, NULL, true);
+	info->mmio_base = dev_read_addr_ptr(dev);
 
-		pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1);
-		if (pdata->num_cs != 1) {
-			pr_err("pxa3xx driver supports single CS only\n");
-			break;
-		}
-
-		if (fdtdec_get_bool(blob, node, "nand-enable-arbiter"))
-			pdata->enable_arbiter = 1;
-
-		if (fdtdec_get_bool(blob, node, "nand-keep-config"))
-			pdata->keep_config = 1;
+	pdata->num_cs = dev_read_u32_default(dev, "num-cs", 1);
+	if (pdata->num_cs != 1) {
+		pr_err("pxa3xx driver supports single CS only\n");
+		return -EINVAL;
+	}
 
-		/*
-		 * ECC parameters.
-		 * If these are not set, they will be selected according
-		 * to the detected flash type.
-		 */
-		/* ECC strength */
-		pdata->ecc_strength = fdtdec_get_int(blob, node,
-						     "nand-ecc-strength", 0);
+	if (dev_read_bool(dev, "nand-enable-arbiter"))
+		pdata->enable_arbiter = 1;
 
-		/* ECC step size */
-		pdata->ecc_step_size = fdtdec_get_int(blob, node,
-						      "nand-ecc-step-size", 0);
+	if (dev_read_bool(dev, "nand-keep-config"))
+		pdata->keep_config = 1;
 
-		info->pdata = pdata;
+	/*
+	 * ECC parameters.
+	 * If these are not set, they will be selected according
+	 * to the detected flash type.
+	 */
+	/* ECC strength */
+	pdata->ecc_strength = dev_read_u32_default(dev, "nand-ecc-strength", 0);
 
-		/* Currently support only a single NAND controller */
-		return 0;
+	/* ECC step size */
+	pdata->ecc_step_size = dev_read_u32_default(dev, "nand-ecc-step-size",
+			0);
 
-	} while (node >= 0);
+	info->pdata = pdata;
 
-	return -EINVAL;
+	return 0;
 }
 
-static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_probe(struct udevice *dev)
 {
-	struct mtd_info *mtd = &info->controller.active->mtd;
 	struct pxa3xx_nand_platform_data *pdata;
 	int ret, cs, probe_success;
+	struct pxa3xx_nand_info *info = dev_get_priv(dev);
 
-	ret = pxa3xx_nand_probe_dt(info);
+	ret = pxa3xx_nand_probe_dt(dev, info);
 	if (ret)
 		return ret;
 
 	pdata = info->pdata;
 
-	ret = alloc_nand_resource(info);
+	ret = alloc_nand_resource(dev, info);
 	if (ret) {
-		dev_err(mtd->dev, "alloc nand resource failed\n");
+		dev_err(dev, "alloc nand resource failed\n");
 		return ret;
 	}
 
@@ -1918,22 +1932,24 @@
 	return 0;
 }
 
-/*
- * Main initialization routine
- */
+U_BOOT_DRIVER(pxa3xx_nand) = {
+	.name = "pxa3xx-nand",
+	.id = UCLASS_MTD,
+	.of_match = pxa3xx_nand_dt_ids,
+	.probe = pxa3xx_nand_probe,
+	.priv_auto_alloc_size = sizeof(struct pxa3xx_nand_info) +
+		sizeof(struct pxa3xx_nand_host) * CONFIG_SYS_MAX_NAND_DEVICE,
+};
+
 void board_nand_init(void)
 {
-	struct pxa3xx_nand_info *info;
-	struct pxa3xx_nand_host *host;
+	struct udevice *dev;
 	int ret;
 
-	info = kzalloc(sizeof(*info) +
-		       sizeof(*host) * CONFIG_SYS_MAX_NAND_DEVICE,
-		       GFP_KERNEL);
-	if (!info)
-		return;
-
-	ret = pxa3xx_nand_probe(info);
-	if (ret)
-		return;
+	ret = uclass_get_device_by_driver(UCLASS_MTD,
+			DM_GET_DRIVER(pxa3xx_nand), &dev);
+	if (ret && ret != -ENODEV) {
+		pr_err("Failed to initialize %s. (error %d)\n", dev->name,
+			   ret);
+	}
 }
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index dabd40a..9ceff0e 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -67,7 +67,7 @@
 #define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */
 #define USE_CLSR		BIT(14)	/* use CLSR command */
 #define SPI_NOR_HAS_SST26LOCK	BIT(15)	/* Flash supports lock/unlock via BPR */
-#define SPI_NOR_OCTAL_READ      BIT(16) /* Flash supports Octal Read */
+#define SPI_NOR_OCTAL_READ	BIT(16)	/* Flash supports Octal Read */
 };
 
 extern const struct flash_info spi_nor_ids[];
diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c
index 15e8004..b0fcb13 100644
--- a/drivers/phy/marvell/comphy_cp110.c
+++ b/drivers/phy/marvell/comphy_cp110.c
@@ -7,6 +7,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <asm/io.h>
+#include <asm/ptrace.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 #include <linux/delay.h>
@@ -22,6 +23,40 @@
 #define HPIPE_ADDR(base, lane)			(SD_ADDR(base, lane) + 0x800)
 #define COMPHY_ADDR(base, lane)			(base + 0x28 * lane)
 
+/* Firmware related definitions used for SMC calls */
+#define MV_SIP_COMPHY_POWER_ON	0x82000001
+#define MV_SIP_COMPHY_POWER_OFF	0x82000002
+#define MV_SIP_COMPHY_PLL_LOCK	0x82000003
+
+/* Used to distinguish between different possible callers (U-boot/Linux) */
+#define COMPHY_CALLER_UBOOT			(0x1 << 21)
+
+#define COMPHY_FW_MODE_FORMAT(mode)		((mode) << 12)
+#define COMPHY_FW_FORMAT(mode, idx, speeds)	\
+			(((mode) << 12) | ((idx) << 8) | ((speeds) << 2))
+
+#define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds)	\
+			(COMPHY_CALLER_UBOOT | ((pcie_width) << 18) |	\
+			((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds))
+
+#define COMPHY_SATA_MODE	0x1
+#define COMPHY_SGMII_MODE	0x2	/* SGMII 1G */
+#define COMPHY_HS_SGMII_MODE	0x3	/* SGMII 2.5G */
+#define COMPHY_USB3H_MODE	0x4
+#define COMPHY_USB3D_MODE	0x5
+#define COMPHY_PCIE_MODE	0x6
+#define COMPHY_RXAUI_MODE	0x7
+#define COMPHY_XFI_MODE		0x8
+#define COMPHY_SFI_MODE		0x9
+#define COMPHY_USB3_MODE	0xa
+#define COMPHY_AP_MODE		0xb
+
+/* Comphy unit index macro */
+#define COMPHY_UNIT_ID0		0
+#define COMPHY_UNIT_ID1		1
+#define COMPHY_UNIT_ID2		2
+#define COMPHY_UNIT_ID3		3
+
 struct utmi_phy_data {
 	void __iomem *utmi_base_addr;
 	void __iomem *usb_cfg_addr;
@@ -85,441 +120,6 @@
 	return 0;
 }
 
-static int comphy_pcie_power_up(u32 lane, u32 pcie_width, bool clk_src,
-				bool is_end_point, void __iomem *hpipe_base,
-				void __iomem *comphy_base)
-{
-	u32 mask, data, ret = 1;
-	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
-	void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
-	void __iomem *addr;
-	u32 pcie_clk = 0; /* set input by default */
-
-	debug_enter();
-
-	/*
-	 * ToDo:
-	 * Add SAR (Sample-At-Reset) configuration for the PCIe clock
-	 * direction. SAR code is currently not ported from Marvell
-	 * U-Boot to mainline version.
-	 *
-	 * SerDes Lane 4/5 got the PCIe ref-clock #1,
-	 * and SerDes Lane 0 got PCIe ref-clock #0
-	 */
-	debug("PCIe clock = %x\n", pcie_clk);
-	debug("PCIe RC    = %d\n", !is_end_point);
-	debug("PCIe width = %d\n", pcie_width);
-
-	/* enable PCIe by4 and by2 */
-	if (lane == 0) {
-		if (pcie_width == 4) {
-			reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
-				0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET,
-				COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK);
-		} else if (pcie_width == 2) {
-			reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
-				0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET,
-				COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK);
-		}
-	}
-
-	/*
-	 * If PCIe clock is output and clock source from SerDes lane 5,
-	 * we need to configure the clock-source MUX.
-	 * By default, the clock source is from lane 4
-	 */
-	if (pcie_clk && clk_src && (lane == 5)) {
-		reg_set((void __iomem *)DFX_DEV_GEN_CTRL12,
-			0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET,
-			DFX_DEV_GEN_PCIE_CLK_SRC_MASK);
-	}
-
-	debug("stage: RFU configurations - hard reset comphy\n");
-	/* RFU configurations - hard reset comphy */
-	mask = COMMON_PHY_CFG1_PWR_UP_MASK;
-	data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
-	mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
-	data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
-	mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
-	mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
-	mask |= COMMON_PHY_PHY_MODE_MASK;
-	data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET;
-	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
-
-	/* release from hard reset */
-	mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
-	data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
-	mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
-	data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
-	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
-
-	/* Wait 1ms - until band gap and ref clock ready */
-	mdelay(1);
-	/* Start comphy Configuration */
-	debug("stage: Comphy configuration\n");
-	/* Set PIPE soft reset */
-	mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK;
-	data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET;
-	/* Set PHY datapath width mode for V0 */
-	mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK;
-	data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET;
-	/* Set Data bus width USB mode for V0 */
-	mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK;
-	data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET;
-	/* Set CORE_CLK output frequency for 250Mhz */
-	mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK;
-	data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask);
-	/* Set PLL ready delay for 0x2 */
-	data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET;
-	mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK;
-	if (pcie_width != 1) {
-		data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET;
-		mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK;
-		data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET;
-		mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK;
-	}
-	reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask);
-
-	/* Set PIPE mode interface to PCIe3 - 0x1  & set lane order */
-	data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET;
-	mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK;
-	if (pcie_width != 1) {
-		mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK;
-		mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK;
-		mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK;
-		if (lane == 0) {
-			data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET;
-			data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET;
-		} else if (lane == (pcie_width - 1)) {
-			data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET;
-		}
-	}
-	reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask);
-	/* Config update polarity equalization */
-	reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG,
-		0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET,
-		HPIPE_CFG_UPDATE_POLARITY_MASK);
-	/* Set PIPE version 4 to mode enable */
-	reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG,
-		0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET,
-		HPIPE_DFE_CTRL_28_PIPE4_MASK);
-	/* TODO: check if pcie clock is output/input - for bringup use input*/
-	/* Enable PIN clock 100M_125M */
-	mask = 0;
-	data = 0;
-	/* Only if clock is output, configure the clock-source mux */
-	if (pcie_clk) {
-		mask |= HPIPE_MISC_CLK100M_125M_MASK;
-		data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET;
-	}
-	/*
-	 * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz
-	 * clock
-	 */
-	mask |= HPIPE_MISC_TXDCLK_2X_MASK;
-	data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET;
-	/* Enable 500MHz Clock */
-	mask |= HPIPE_MISC_CLK500_EN_MASK;
-	data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET;
-	if (pcie_clk) { /* output */
-		/* Set reference clock comes from group 1 */
-		mask |= HPIPE_MISC_REFCLK_SEL_MASK;
-		data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
-	} else {
-		/* Set reference clock comes from group 2 */
-		mask |= HPIPE_MISC_REFCLK_SEL_MASK;
-		data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET;
-	}
-	mask |= HPIPE_MISC_ICP_FORCE_MASK;
-	data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
-	if (pcie_clk) { /* output */
-		/* Set reference frequcency select - 0x2 for 25MHz*/
-		mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
-		data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
-	} else {
-		/* Set reference frequcency select - 0x0 for 100MHz*/
-		mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
-		data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
-	}
-	/* Set PHY mode to PCIe */
-	mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
-	data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
-
-	/* ref clock alignment */
-	if (pcie_width != 1) {
-		mask = HPIPE_LANE_ALIGN_OFF_MASK;
-		data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET;
-		reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask);
-	}
-
-	/*
-	 * Set the amount of time spent in the LoZ state - set for 0x7 only if
-	 * the PCIe clock is output
-	 */
-	if (pcie_clk) {
-		reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL,
-			0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET,
-			HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK);
-	}
-
-	/* Set Maximal PHY Generation Setting(8Gbps) */
-	mask = HPIPE_INTERFACE_GEN_MAX_MASK;
-	data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET;
-	/* Bypass frame detection and sync detection for RX DATA */
-	mask = HPIPE_INTERFACE_DET_BYPASS_MASK;
-	data = 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET;
-	/* Set Link Train Mode (Tx training control pins are used) */
-	mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK;
-	data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask);
-
-	/* Set Idle_sync enable */
-	mask = HPIPE_PCIE_IDLE_SYNC_MASK;
-	data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET;
-	/* Select bits for PCIE Gen3(32bit) */
-	mask |= HPIPE_PCIE_SEL_BITS_MASK;
-	data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask);
-
-	/* Enable Tx_adapt_g1 */
-	mask = HPIPE_TX_TRAIN_CTRL_G1_MASK;
-	data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET;
-	/* Enable Tx_adapt_gn1 */
-	mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK;
-	data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET;
-	/* Disable Tx_adapt_g0 */
-	mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK;
-	data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
-
-	/* Set reg_tx_train_chk_init */
-	mask = HPIPE_TX_TRAIN_CHK_INIT_MASK;
-	data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET;
-	/* Enable TX_COE_FM_PIN_PCIE3_EN */
-	mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK;
-	data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
-
-	debug("stage: TRx training parameters\n");
-	/* Set Preset sweep configurations */
-	mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK;
-	data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET;
-
-	mask |= HPIPE_TX_NUM_OF_PRESET_MASK;
-	data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET;
-
-	mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK;
-	data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask);
-
-	/* Tx train start configuration */
-	mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK;
-	data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET;
-
-	mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK;
-	data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET;
-
-	mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK;
-	data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET;
-
-	mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK;
-	data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
-
-	/* Enable Tx train P2P */
-	mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
-	data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
-
-	/* Configure Tx train timeout */
-	mask = HPIPE_TRX_TRAIN_TIMER_MASK;
-	data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask);
-
-	/* Disable G0/G1/GN1 adaptation */
-	mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK
-		| HPIPE_TX_TRAIN_CTRL_G0_OFFSET;
-	data = 0;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask);
-
-	/* Disable DTL frequency loop */
-	mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
-	data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
-
-	/* Configure G3 DFE */
-	mask = HPIPE_G3_DFE_RES_MASK;
-	data = 0x3 << HPIPE_G3_DFE_RES_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
-
-	/* Use TX/RX training result for DFE */
-	mask = HPIPE_DFE_RES_FORCE_MASK;
-	data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_REG0,  data, mask);
-
-	/* Configure initial and final coefficient value for receiver */
-	mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
-	data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
-
-	mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
-	data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
-
-	mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
-	data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SET_1_REG,  data, mask);
-
-	/* Trigger sampler enable pulse */
-	mask = HPIPE_SMAPLER_MASK;
-	data = 0x1 << HPIPE_SMAPLER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
-	udelay(5);
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask);
-
-	/* FFE resistor tuning for different bandwidth  */
-	mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
-	data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
-
-	mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
-	data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
-
-	/* Pattern lock lost timeout disable */
-	mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
-	data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
-
-	/* Configure DFE adaptations */
-	mask = HPIPE_CDR_MAX_DFE_ADAPT_1_MASK;
-	data = 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET;
-	mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK;
-	data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET;
-	mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK;
-	data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET;
-	reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
-	mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK;
-	data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask);
-
-	/* Genration 2 setting 1*/
-	mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
-	data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK;
-	data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
-	data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
-
-	/* DFE enable */
-	mask = HPIPE_G2_DFE_RES_MASK;
-	data = 0x3 << HPIPE_G2_DFE_RES_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask);
-
-	/* Configure DFE Resolution */
-	mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK;
-	data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask);
-
-	/* VDD calibration control */
-	mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
-	data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
-
-	/* Set PLL Charge-pump Current Control */
-	mask = HPIPE_G3_SETTING_5_G3_ICP_MASK;
-	data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask);
-
-	/* Set lane rqualization remote setting */
-	mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK;
-	data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET;
-	mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK;
-	data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET;
-	mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK;
-	data |= 0x2 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET;
-	reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask);
-
-	if (!is_end_point) {
-		/* Set phy in root complex mode */
-		mask = HPIPE_CFG_PHY_RC_EP_MASK;
-		data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET;
-		reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask);
-	}
-
-	debug("stage: Comphy power up\n");
-
-	/*
-	 * For PCIe by4 or by2 - release from reset only after finish to
-	 * configure all lanes
-	 */
-	if ((pcie_width == 1) || (lane == (pcie_width - 1))) {
-		u32 i, start_lane, end_lane;
-
-		if (pcie_width != 1) {
-			/* allows writing to all lanes in one write */
-			reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
-				0x0 <<
-				COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
-				COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
-			start_lane = 0;
-			end_lane = pcie_width;
-
-			/*
-			 * Release from PIPE soft reset
-			 * for PCIe by4 or by2 - release from soft reset
-			 * all lanes - can't use read modify write
-			 */
-			reg_set(HPIPE_ADDR(hpipe_base, 0) +
-				HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff);
-		} else {
-			start_lane = lane;
-			end_lane = lane + 1;
-
-			/*
-			 * Release from PIPE soft reset
-			 * for PCIe by4 or by2 - release from soft reset
-			 * all lanes
-			 */
-			reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG,
-				0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET,
-				HPIPE_RST_CLK_CTRL_PIPE_RST_MASK);
-		}
-
-
-		if (pcie_width != 1) {
-			/* disable writing to all lanes with one write */
-			reg_set(comphy_base + COMMON_PHY_SD_CTRL1,
-				0x3210 <<
-				COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET,
-				COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK);
-		}
-
-		debug("stage: Check PLL\n");
-		/* Read lane status */
-		for (i = start_lane; i < end_lane; i++) {
-			addr = HPIPE_ADDR(hpipe_base, i) +
-				HPIPE_LANE_STATUS1_REG;
-			data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
-			mask = data;
-			data = polling_with_timeout(addr, data, mask, 15000);
-			if (data != 0) {
-				debug("Read from reg = %p - value = 0x%x\n",
-				      hpipe_addr + HPIPE_LANE_STATUS1_REG,
-				      data);
-				pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
-				ret = 0;
-			}
-		}
-	}
-
-	debug_exit();
-	return ret;
-}
-
 static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base,
 				void __iomem *comphy_base)
 {
@@ -642,15 +242,31 @@
 	return ret;
 }
 
+static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr,
+		      u32 lane, u32 mode)
+{
+	struct pt_regs pregs = {0};
+
+	pregs.regs[0] = function_id;
+	pregs.regs[1] = (unsigned long)comphy_base_addr;
+	pregs.regs[2] = lane;
+	pregs.regs[3] = mode;
+
+	smc_call(&pregs);
+
+	/*
+	 * TODO: Firmware return 0 on success, temporary map it to u-boot
+	 * convention, but after all comphy will be reworked the convention in
+	 * u-boot should be change and this conversion removed
+	 */
+	return pregs.regs[0] ? 0 : 1;
+}
+
 static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base,
-				void __iomem *comphy_base, int cp_index,
-				u32 invert)
+				void __iomem *comphy_base_addr, int cp_index,
+				u32 type)
 {
 	u32 mask, data, i, ret = 1;
-	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
-	void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
-	void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
-	void __iomem *addr;
 	void __iomem *sata_base = NULL;
 	int sata_node = -1; /* Set to -1 in order to read the first sata node */
 
@@ -703,255 +319,8 @@
 	data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET;
 	reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
 
-	debug("stage: RFU configurations - hard reset comphy\n");
-	/* RFU configurations - hard reset comphy */
-	mask = COMMON_PHY_CFG1_PWR_UP_MASK;
-	data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
-	mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
-	mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET;
-	mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET;
-	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
-
-	/* Set select data  width 40Bit - SATA mode only */
-	reg_set(comphy_addr + COMMON_PHY_CFG6_REG,
-		0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET,
-		COMMON_PHY_CFG6_IF_40_SEL_MASK);
-
-	/* release from hard reset in SD external */
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	/* Wait 1ms - until band gap and ref clock ready */
-	mdelay(1);
-
-	debug("stage: Comphy configuration\n");
-	/* Start comphy Configuration */
-	/* Set reference clock to comes from group 1 - choose 25Mhz */
-	reg_set(hpipe_addr + HPIPE_MISC_REG,
-		0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET,
-		HPIPE_MISC_REFCLK_SEL_MASK);
-	/* Reference frequency select set 1 (for SATA = 25Mhz) */
-	mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
-	data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
-	/* PHY mode select (set SATA = 0x0 */
-	mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
-	data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
-	/* Set max PHY generation setting - 6Gbps */
-	reg_set(hpipe_addr + HPIPE_INTERFACE_REG,
-		0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET,
-		HPIPE_INTERFACE_GEN_MAX_MASK);
-	/* Set select data  width 40Bit (SEL_BITS[2:0]) */
-	reg_set(hpipe_addr + HPIPE_LOOPBACK_REG,
-		0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK);
-
-	debug("stage: Analog paramters from ETP(HW)\n");
-	/* Set analog parameters from ETP(HW) */
-	/* G1 settings */
-	mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
-	data = 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
-	mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK;
-	data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET;
-	mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
-	data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
-	mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
-	data |= 0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
-	mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
-	data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
-
-	mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
-	data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
-	mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
-	data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
-	mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
-	data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
-	mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK;
-	data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET;
-	mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK;
-	data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
-
-	/* G2 settings */
-	mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK;
-	data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK;
-	data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK;
-	data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK;
-	data |= 0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET;
-	mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK;
-	data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask);
-
-	/* G3 settings */
-	mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK;
-	data = 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK;
-	data |= 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK;
-	data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK;
-	data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK;
-	data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK;
-	data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET;
-	mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK;
-	data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask);
-
-	/* DTL Control */
-	mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK;
-	data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET;
-	mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK;
-	data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
-
-	/* Trigger sampler enable pulse (by toggleing the bit) */
-	mask = HPIPE_SMAPLER_MASK;
-	data = 0x1 << HPIPE_SMAPLER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
-	mask = HPIPE_SMAPLER_MASK;
-	data = 0x0 << HPIPE_SMAPLER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
-
-	/* VDD Calibration Control 3 */
-	mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
-	data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
-
-	/* DFE Resolution Control */
-	mask = HPIPE_DFE_RES_FORCE_MASK;
-	data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
-
-	/* DFE F3-F5 Coefficient Control */
-	mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
-	data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
-	mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
-	data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
-
-	/* G3 Setting 3 */
-	mask = HPIPE_G3_FFE_CAP_SEL_MASK;
-	data = 0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET;
-	mask |= HPIPE_G3_FFE_RES_SEL_MASK;
-	data |= 0x4 << HPIPE_G3_FFE_RES_SEL_OFFSET;
-	mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK;
-	data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET;
-	mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK;
-	data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET;
-	mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK;
-	data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask);
-
-	/* G3 Setting 4 */
-	mask = HPIPE_G3_DFE_RES_MASK;
-	data = 0x2 << HPIPE_G3_DFE_RES_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask);
+	ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type);
 
-	/* Offset Phase Control */
-	mask = HPIPE_OS_PH_OFFSET_MASK;
-	data = 0x5c << HPIPE_OS_PH_OFFSET_OFFSET;
-	mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK;
-	data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
-	mask = HPIPE_OS_PH_VALID_MASK;
-	data = 0x1 << HPIPE_OS_PH_VALID_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
-	mask = HPIPE_OS_PH_VALID_MASK;
-	data = 0x0 << HPIPE_OS_PH_VALID_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask);
-
-	/* Set G1 TX amplitude and TX post emphasis value */
-	mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
-	data = 0x8 << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
-	mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK;
-	data |= 0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET;
-	mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
-	data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
-	mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK;
-	data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
-
-	/* Set G2 TX amplitude and TX post emphasis value */
-	mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK;
-	data = 0xa << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET;
-	mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK;
-	data |= 0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET;
-	mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK;
-	data |= 0x2 << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET;
-	mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK;
-	data |= 0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask);
-
-	/* Set G3 TX amplitude and TX post emphasis value */
-	mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK;
-	data = 0xe << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET;
-	mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK;
-	data |= 0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET;
-	mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK;
-	data |= 0x6 << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET;
-	mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK;
-	data |= 0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET;
-	mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK;
-	data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET;
-	mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK;
-	data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask);
-
-	/* SERDES External Configuration 2 register */
-	mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
-
-	/* DFE reset sequence */
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
-		0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
-		HPIPE_PWR_CTR_RST_DFE_MASK);
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
-		0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET,
-		HPIPE_PWR_CTR_RST_DFE_MASK);
-
-	/* Set RX / TX swaps */
-	data = mask = 0;
-	if (invert & PHY_POLARITY_TXD_INVERT) {
-		data |= (1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET);
-		mask |= HPIPE_SYNC_PATTERN_TXD_SWAP_MASK;
-	}
-	if (invert & PHY_POLARITY_RXD_INVERT) {
-		data |= (1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET);
-		mask |= HPIPE_SYNC_PATTERN_RXD_SWAP_MASK;
-	}
-	reg_set(hpipe_addr + HPIPE_SYNC_PATTERN_REG, data, mask);
-
-	/* SW reset for interupt logic */
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
-		0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
-		HPIPE_PWR_CTR_SFT_RST_MASK);
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_REG,
-		0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET,
-		HPIPE_PWR_CTR_SFT_RST_MASK);
-
-	debug("stage: Comphy power up\n");
 	/*
 	 * MAC configuration power up comphy - power up PLL/TX/RX
 	 * use indirect address for vendor spesific SATA control register
@@ -981,469 +350,7 @@
 	reg_set(sata_base + SATA3_VENDOR_DATA,
 		0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK);
 
-	debug("stage: Check PLL\n");
-
-	addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
-	data = SD_EXTERNAL_STATUS0_PLL_TX_MASK &
-		SD_EXTERNAL_STATUS0_PLL_RX_MASK;
-	mask = data;
-	data = polling_with_timeout(addr, data, mask, 15000);
-	if (data != 0) {
-		debug("Read from reg = %p - value = 0x%x\n",
-		      hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
-		pr_err("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n",
-		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK),
-		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK));
-		ret = 0;
-	}
-
-	debug_exit();
-	return ret;
-}
-
-static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed,
-				 void __iomem *hpipe_base,
-				 void __iomem *comphy_base)
-{
-	u32 mask, data, ret = 1;
-	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
-	void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
-	void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
-	void __iomem *addr;
-
-	debug_enter();
-	debug("stage: RFU configurations - hard reset comphy\n");
-	/* RFU configurations - hard reset comphy */
-	mask = COMMON_PHY_CFG1_PWR_UP_MASK;
-	data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
-	mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
-	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
-
-	/* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
-	mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
-	if (sgmii_speed == PHY_SPEED_1_25G) {
-		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
-		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
-	} else {
-		/* 3.125G */
-		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
-		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
-	}
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
-	data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
-	data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
-	data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
-
-	/* release from hard reset */
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	/* release from hard reset */
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-
-	/* Wait 1ms - until band gap and ref clock ready */
-	mdelay(1);
-
-	/* Start comphy Configuration */
-	debug("stage: Comphy configuration\n");
-	/* set reference clock */
-	mask = HPIPE_MISC_REFCLK_SEL_MASK;
-	data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
-	/* Power and PLL Control */
-	mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
-	data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
-	mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
-	data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
-	/* Loopback register */
-	mask = HPIPE_LOOPBACK_SEL_MASK;
-	data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
-	/* rx control 1 */
-	mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
-	data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
-	mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
-	data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
-	/* DTL Control */
-	mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
-	data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
-
-	/* Set analog paramters from ETP(HW) - for now use the default datas */
-	debug("stage: Analog paramters from ETP(HW)\n");
-
-	reg_set(hpipe_addr + HPIPE_G1_SET_0_REG,
-		0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET,
-		HPIPE_G1_SET_0_G1_TX_EMPH1_MASK);
-
-	debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
-	/* SERDES External Configuration */
-	mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
-
-	/* check PLL rx & tx ready */
-	addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
-	data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
-		SD_EXTERNAL_STATUS0_PLL_TX_MASK;
-	mask = data;
-	data = polling_with_timeout(addr, data, mask, 15000);
-	if (data != 0) {
-		debug("Read from reg = %p - value = 0x%x\n",
-		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
-		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
-		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
-		ret = 0;
-	}
-
-	/* RX init */
-	mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	/* check that RX init done */
-	addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
-	data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
-	mask = data;
-	data = polling_with_timeout(addr, data, mask, 100);
-	if (data != 0) {
-		debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
-		ret = 0;
-	}
-
-	debug("stage: RF Reset\n");
-	/* RF Reset */
-	mask =  SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	debug_exit();
-	return ret;
-}
-
-static int comphy_sfi_power_up(u32 lane, void __iomem *hpipe_base,
-			       void __iomem *comphy_base, u32 speed)
-{
-	u32 mask, data, ret = 1;
-	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane);
-	void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane);
-	void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane);
-	void __iomem *addr;
-
-	debug_enter();
-	debug("stage: RFU configurations - hard reset comphy\n");
-	/* RFU configurations - hard reset comphy */
-	mask = COMMON_PHY_CFG1_PWR_UP_MASK;
-	data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET;
-	mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK;
-	data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET;
-	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
-
-	/* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */
-	mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK;
-	data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK;
-	data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
-	data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
-	data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK;
-	data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
-
-	/* release from hard reset */
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-
-	/* Wait 1ms - until band gap and ref clock ready */
-	mdelay(1);
-
-	/* Start comphy Configuration */
-	debug("stage: Comphy configuration\n");
-	/* set reference clock */
-	mask = HPIPE_MISC_ICP_FORCE_MASK;
-	data = (speed == PHY_SPEED_5_15625G) ?
-		(0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) :
-		(0x1 << HPIPE_MISC_ICP_FORCE_OFFSET);
-	mask |= HPIPE_MISC_REFCLK_SEL_MASK;
-	data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask);
-	/* Power and PLL Control */
-	mask = HPIPE_PWR_PLL_REF_FREQ_MASK;
-	data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET;
-	mask |= HPIPE_PWR_PLL_PHY_MODE_MASK;
-	data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask);
-	/* Loopback register */
-	mask = HPIPE_LOOPBACK_SEL_MASK;
-	data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
-	/* rx control 1 */
-	mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK;
-	data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET;
-	mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK;
-	data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask);
-	/* DTL Control */
-	mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK;
-	data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask);
-
-	/* Transmitter/Receiver Speed Divider Force */
-	if (speed == PHY_SPEED_5_15625G) {
-		mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK;
-		data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET;
-		mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK;
-		data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET;
-		mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK;
-		data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET;
-		mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK;
-		data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET;
-	} else {
-		mask = HPIPE_TXDIGCK_DIV_FORCE_MASK;
-		data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET;
-	}
-	reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask);
-
-	/* Set analog paramters from ETP(HW) */
-	debug("stage: Analog paramters from ETP(HW)\n");
-	/* SERDES External Configuration 2 */
-	mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask);
-	/* 0x7-DFE Resolution control */
-	mask = HPIPE_DFE_RES_FORCE_MASK;
-	data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
-	/* 0xd-G1_Setting_0 */
-	if (speed == PHY_SPEED_5_15625G) {
-		mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
-		data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
-	} else {
-		mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK;
-		data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET;
-		mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK;
-		data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET;
-	}
-	reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask);
-	/* Genration 1 setting 2 (G1_Setting_2) */
-	mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK;
-	data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET;
-	mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK;
-	data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask);
-	/* Transmitter Slew Rate Control register (tx_reg1) */
-	mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK;
-	data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET;
-	mask |= HPIPE_TX_REG1_SLC_EN_MASK;
-	data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask);
-	/* Impedance Calibration Control register (cal_reg1) */
-	mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK;
-	data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
-	mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK;
-	data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask);
-	/* Generation 1 Setting 5 (g1_setting_5) */
-	mask = HPIPE_G1_SETTING_5_G1_ICP_MASK;
-	data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask);
-	/* 0xE-G1_Setting_1 */
-	mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK;
-	data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET;
-	if (speed == PHY_SPEED_5_15625G) {
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
-		data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK;
-		data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET;
-	} else {
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK;
-		data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET;
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK;
-		data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET;
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK;
-		data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET;
-		mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK;
-		data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET;
-		mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK;
-		data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET;
-	}
-	reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask);
-
-	/* 0xA-DFE_Reg3 */
-	mask = HPIPE_DFE_F3_F5_DFE_EN_MASK;
-	data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET;
-	mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK;
-	data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask);
-
-	/* 0x111-G1_Setting_4 */
-	mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
-	data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
-	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
-	/* Genration 1 setting 3 (G1_Setting_3) */
-	mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK;
-	data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET;
-	if (speed == PHY_SPEED_5_15625G) {
-		/* Force FFE (Feed Forward Equalization) to 5G */
-		mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
-		data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
-		mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
-		data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
-		mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
-		data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
-	}
-	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
-
-	/* Connfigure RX training timer */
-	mask = HPIPE_RX_TRAIN_TIMER_MASK;
-	data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask);
-
-	/* Enable TX train peak to peak hold */
-	mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK;
-	data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask);
-
-	/* Configure TX preset index */
-	mask = HPIPE_TX_PRESET_INDEX_MASK;
-	data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask);
-
-	/* Disable pattern lock lost timeout */
-	mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK;
-	data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask);
-
-	/* Configure TX training pattern and TX training 16bit auto */
-	mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK;
-	data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET;
-	mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK;
-	data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask);
-
-	/* Configure Training patten number */
-	mask = HPIPE_TRAIN_PAT_NUM_MASK;
-	data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET;
-	reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask);
-
-	/* Configure differencial manchester encoter to ethernet mode */
-	mask = HPIPE_DME_ETHERNET_MODE_MASK;
-	data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_DME_REG, data, mask);
-
-	/* Configure VDD Continuous Calibration */
-	mask = HPIPE_CAL_VDD_CONT_MODE_MASK;
-	data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask);
-
-	/* Trigger sampler enable pulse (by toggleing the bit) */
-	mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK;
-	data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET;
-	mask |= HPIPE_SMAPLER_MASK;
-	data |= 0x1 << HPIPE_SMAPLER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
-	mask = HPIPE_SMAPLER_MASK;
-	data = 0x0 << HPIPE_SMAPLER_OFFSET;
-	reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask);
-
-	/* Set External RX Regulator Control */
-	mask = HPIPE_EXT_SELLV_RXSAMPL_MASK;
-	data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask);
-
-	debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n");
-	/* SERDES External Configuration */
-	mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask);
-
-
-	/* check PLL rx & tx ready */
-	addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
-	data = SD_EXTERNAL_STATUS0_PLL_RX_MASK |
-		SD_EXTERNAL_STATUS0_PLL_TX_MASK;
-	mask = data;
-	data = polling_with_timeout(addr, data, mask, 15000);
-	if (data != 0) {
-		debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
-		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
-		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
-		ret = 0;
-	}
-
-	/* RX init */
-	mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-
-	/* check that RX init done */
-	addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG;
-	data = SD_EXTERNAL_STATUS0_RX_INIT_MASK;
-	mask = data;
-	data = polling_with_timeout(addr, data, mask, 100);
-	if (data != 0) {
-		debug("Read from reg = %p - value = 0x%x\n",
-		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
-		ret = 0;
-	}
-
-	debug("stage: RF Reset\n");
-	/* RF Reset */
-	mask =  SD_EXTERNAL_CONFIG1_RX_INIT_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+	ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type);
 
 	debug_exit();
 	return ret;
@@ -1973,6 +880,7 @@
 	void __iomem *comphy_base_addr, *hpipe_base_addr;
 	u32 comphy_max_count, lane, ret = 0;
 	u32 pcie_width = 0;
+	u32 mode;
 
 	debug_enter();
 
@@ -2011,19 +919,23 @@
 		case PHY_TYPE_PEX1:
 		case PHY_TYPE_PEX2:
 		case PHY_TYPE_PEX3:
-			ret = comphy_pcie_power_up(
-				lane, pcie_width, ptr_comphy_map->clk_src,
-				serdes_map->end_point,
-				hpipe_base_addr, comphy_base_addr);
+			mode = COMPHY_FW_PCIE_FORMAT(pcie_width,
+						     ptr_comphy_map->clk_src,
+						     COMPHY_PCIE_MODE,
+						     ptr_comphy_map->speed);
+			ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+					 ptr_chip_cfg->comphy_base_addr, lane,
+					 mode);
 			break;
 		case PHY_TYPE_SATA0:
 		case PHY_TYPE_SATA1:
 		case PHY_TYPE_SATA2:
 		case PHY_TYPE_SATA3:
-			ret = comphy_sata_power_up(
-				lane, hpipe_base_addr, comphy_base_addr,
-				ptr_chip_cfg->cp_index,
-				serdes_map[lane].invert);
+			mode =  COMPHY_FW_MODE_FORMAT(COMPHY_SATA_MODE);
+			ret = comphy_sata_power_up(lane, hpipe_base_addr,
+						   comphy_base_addr,
+						   ptr_chip_cfg->cp_index,
+						   mode);
 			break;
 		case PHY_TYPE_USB3_HOST0:
 		case PHY_TYPE_USB3_HOST1:
@@ -2033,6 +945,25 @@
 			break;
 		case PHY_TYPE_SGMII0:
 		case PHY_TYPE_SGMII1:
+			if (ptr_comphy_map->speed == PHY_SPEED_INVALID) {
+				debug("Warning: ");
+				debug("SGMII PHY speed in lane %d is invalid,",
+				      lane);
+				debug(" set PHY speed to 1.25G\n");
+				ptr_comphy_map->speed = PHY_SPEED_1_25G;
+			}
+
+			/*
+			 * UINIT_ID not relevant for SGMII0 and SGMII1 - will be
+			 * ignored by firmware
+			 */
+			mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE,
+						COMPHY_UNIT_ID0,
+						ptr_comphy_map->speed);
+			ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+					 ptr_chip_cfg->comphy_base_addr, lane,
+					 mode);
+			break;
 		case PHY_TYPE_SGMII2:
 		case PHY_TYPE_SGMII3:
 			if (ptr_comphy_map->speed == PHY_SPEED_INVALID) {
@@ -2040,14 +971,21 @@
 				      lane);
 				ptr_comphy_map->speed = PHY_SPEED_1_25G;
 			}
-			ret = comphy_sgmii_power_up(
-				lane, ptr_comphy_map->speed, hpipe_base_addr,
-				comphy_base_addr);
+
+			mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE,
+						COMPHY_UNIT_ID2,
+						ptr_comphy_map->speed);
+			ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+					 ptr_chip_cfg->comphy_base_addr, lane,
+					 mode);
 			break;
 		case PHY_TYPE_SFI:
-			ret = comphy_sfi_power_up(lane, hpipe_base_addr,
-						  comphy_base_addr,
-						  ptr_comphy_map->speed);
+			mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE,
+						COMPHY_UNIT_ID0,
+						ptr_comphy_map->speed);
+			ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
+					 ptr_chip_cfg->comphy_base_addr, lane,
+					 mode);
 			break;
 		case PHY_TYPE_RXAUI0:
 		case PHY_TYPE_RXAUI1:
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 2772c25..d9e35c6 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -19,6 +19,7 @@
 #include <watchdog.h>
 #include <asm/io.h>
 #include <serial.h>
+#include <dm/device_compat.h>
 #include <dm/platform_data/serial_pl01x.h>
 #include <linux/compiler.h>
 #include "serial_pl01x_internal.h"
@@ -362,8 +363,18 @@
 	plat->clock = dev_read_u32_default(dev, "clock", CONFIG_PL011_CLOCK);
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (!ret) {
-		clk_enable(&clk);
+		ret = clk_enable(&clk);
+		if (ret && ret != -ENOSYS) {
+			dev_err(dev, "failed to enable clock\n");
+			return ret;
+		}
+
 		plat->clock = clk_get_rate(&clk);
+		if (IS_ERR_VALUE(plat->clock)) {
+			dev_err(dev, "failed to get rate\n");
+			return plat->clock;
+		}
+		debug("%s: CLK %d\n", __func__, plat->clock);
 	}
 	plat->type = dev_get_driver_data(dev);
 	plat->skip_init = dev_read_bool(dev, "skip-init");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 348630f..47a5571 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -214,7 +214,7 @@
 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 	const unsigned char *txp = dout;
 	unsigned char *rxp = din;
-	u32 reg, count;
+	u32 reg;
 	u32 txbytes = bytes;
 	u32 rxbytes = bytes;
 
@@ -224,10 +224,10 @@
 	 * it sets txp to the initial value for the normal operation.
 	 */
 	for ( ; priv->startup < 2; priv->startup++) {
-		count = xilinx_spi_fill_txfifo(bus, txp, txbytes);
+		xilinx_spi_fill_txfifo(bus, txp, txbytes);
 		reg = readl(&regs->spicr) & ~SPICR_MASTER_INHIBIT;
 		writel(reg, &regs->spicr);
-		count = xilinx_spi_read_rxfifo(bus, rxp, rxbytes);
+		xilinx_spi_read_rxfifo(bus, rxp, rxbytes);
 		txp = din;
 
 		if (priv->startup) {
@@ -251,7 +251,7 @@
 	unsigned char *rxp = din;
 	u32 txbytes = bytes;
 	u32 rxbytes = bytes;
-	u32 reg, count, timeout;
+	u32 reg, count;
 	int ret;
 
 	debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n",
diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index 3f39ef0..f2eddec 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -6,8 +6,10 @@
  * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only)
  */
 
+#include <clk.h>
 #include <common.h>
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <log.h>
 #include <malloc.h>
 #include <spi.h>
@@ -105,17 +107,29 @@
 	plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob,
 							      node, "reg");
 
-	/* FIXME: Use 166MHz as a suitable default */
-	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
-					166666666);
-	plat->speed_hz = plat->frequency / 2;
-
-	debug("%s: regs=%p max-frequency=%d\n", __func__,
-	      plat->regs, plat->frequency);
-
 	return 0;
 }
 
+/**
+ * zynq_qspi_init_hw - Initialize the hardware
+ * @priv:	Pointer to the zynq_qspi_priv structure
+ *
+ * The default settings of the QSPI controller's configurable parameters on
+ * reset are
+ *	- Master mode
+ *	- Baud rate divisor is set to 2
+ *	- Threshold value for TX FIFO not full interrupt is set to 1
+ *	- Flash memory interface mode enabled
+ *	- Size of the word to be transferred as 8 bit
+ * This function performs the following actions
+ *	- Disable and clear all the interrupts
+ *	- Enable manual slave select
+ *	- Enable auto start
+ *	- Deselect all the chip select lines
+ *	- Set the size of the word to be transferred as 32 bit
+ *	- Set the little endian mode of TX FIFO and
+ *	- Enable the QSPI controller
+ */
 static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
 {
 	struct zynq_qspi_regs *regs = priv->regs;
@@ -159,19 +173,45 @@
 {
 	struct zynq_qspi_platdata *plat = dev_get_platdata(bus);
 	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct clk clk;
+	unsigned long clock;
+	int ret;
 
 	priv->regs = plat->regs;
 	priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
 
+	ret = clk_get_by_name(bus, "ref_clk", &clk);
+	if (ret < 0) {
+		dev_err(bus, "failed to get clock\n");
+		return ret;
+	}
+
+	clock = clk_get_rate(&clk);
+	if (IS_ERR_VALUE(clock)) {
+		dev_err(bus, "failed to get rate\n");
+		return clock;
+	}
+
+	ret = clk_enable(&clk);
+	if (ret && ret != -ENOSYS) {
+		dev_err(bus, "failed to enable clock\n");
+		return ret;
+	}
+
 	/* init the zynq spi hw */
 	zynq_qspi_init_hw(priv);
 
+	plat->frequency = clock;
+	plat->speed_hz = plat->frequency / 2;
+
+	debug("%s: max-frequency=%d\n", __func__, plat->speed_hz);
+
 	return 0;
 }
 
-/*
+/**
  * zynq_qspi_read_data - Copy data to RX buffer
- * @zqspi:	Pointer to the zynq_qspi structure
+ * @priv:	Pointer to the zynq_qspi_priv structure
  * @data:	The 32 bit variable where data is stored
  * @size:	Number of bytes to be copied from data to RX buffer
  */
@@ -214,9 +254,9 @@
 		priv->bytes_to_receive = 0;
 }
 
-/*
+/**
  * zynq_qspi_write_data - Copy data from TX buffer
- * @zqspi:	Pointer to the zynq_qspi structure
+ * @priv:	Pointer to the zynq_qspi_priv structure
  * @data:	Pointer to the 32 bit variable where data is to be copied
  * @size:	Number of bytes to be copied from TX buffer to data
  */
@@ -263,6 +303,11 @@
 		priv->bytes_to_transfer = 0;
 }
 
+/**
+ * zynq_qspi_chipselect - Select or deselect the chip select line
+ * @priv:	Pointer to the zynq_qspi_priv structure
+ * @is_on:	Select(1) or deselect (0) the chip select line
+ */
 static void zynq_qspi_chipselect(struct  zynq_qspi_priv *priv, int is_on)
 {
 	u32 confr;
@@ -282,9 +327,10 @@
 	writel(confr, &regs->cr);
 }
 
-/*
+/**
  * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
- * @zqspi:	Pointer to the zynq_qspi structure
+ * @priv:	Pointer to the zynq_qspi_priv structure
+ * @size:	Number of bytes to be copied to fifo
  */
 static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size)
 {
@@ -322,9 +368,9 @@
 	}
 }
 
-/*
+/**
  * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
- * @zqspi:	Pointer to the zynq_qspi structure
+ * @priv:	Pointer to the zynq_qspi structure
  *
  * This function handles TX empty and Mode Fault interrupts only.
  * On TX empty interrupt this function reads the received data from RX FIFO and
@@ -410,11 +456,9 @@
 	return 0;
 }
 
-/*
+/**
  * zynq_qspi_start_transfer - Initiates the QSPI transfer
- * @qspi:	Pointer to the spi_device structure
- * @transfer:	Pointer to the spi_transfer structure which provide information
- *		about next transfer parameters
+ * @priv:	Pointer to the zynq_qspi_priv structure
  *
  * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
  * transfer to be completed.
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 9923931..cb911c3 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -8,10 +8,12 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <log.h>
 #include <malloc.h>
 #include <spi.h>
 #include <time.h>
+#include <clk.h>
 #include <asm/io.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -79,17 +81,10 @@
 
 	plat->regs = dev_read_addr_ptr(bus);
 
-	/* FIXME: Use 250MHz as a suitable default */
-	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
-					250000000);
 	plat->deactivate_delay_us = fdtdec_get_int(blob, node,
 					"spi-deactivate-delay", 0);
 	plat->activate_delay_us = fdtdec_get_int(blob, node,
 						 "spi-activate-delay", 0);
-	plat->speed_hz = plat->frequency / 2;
-
-	debug("%s: regs=%p max-frequency=%d\n", __func__,
-	      plat->regs, plat->frequency);
 
 	return 0;
 }
@@ -128,13 +123,39 @@
 {
 	struct zynq_spi_platdata *plat = dev_get_platdata(bus);
 	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct clk clk;
+	unsigned long clock;
+	int ret;
 
 	priv->regs = plat->regs;
 	priv->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
 
+	ret = clk_get_by_name(bus, "ref_clk", &clk);
+	if (ret < 0) {
+		dev_err(bus, "failed to get clock\n");
+		return ret;
+	}
+
+	clock = clk_get_rate(&clk);
+	if (IS_ERR_VALUE(clock)) {
+		dev_err(bus, "failed to get rate\n");
+		return clock;
+	}
+
+	ret = clk_enable(&clk);
+	if (ret && ret != -ENOSYS) {
+		dev_err(bus, "failed to enable clock\n");
+		return ret;
+	}
+
 	/* init the zynq spi hw */
 	zynq_spi_init_hw(priv);
 
+	plat->frequency = clock;
+	plat->speed_hz = plat->frequency / 2;
+
+	debug("%s: max-frequency=%d\n", __func__, plat->speed_hz);
+
 	return 0;
 }
 
diff --git a/env/Kconfig b/env/Kconfig
index aa63fae..67ce930 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -376,6 +376,14 @@
 	  Value of the SPI work mode for environment.
 	  See include/spi.h for value.
 
+config ENV_SPI_EARLY
+	bool "Access Environment in SPI flashes before relocation"
+	depends on ENV_IS_IN_SPI_FLASH
+	help
+	  Enable this if you want to use Environment in SPI flash
+	  before relocation. Call env_init() and than you can use
+	  env_get_f() for accessing Environment variables.
+
 config ENV_IS_IN_UBI
 	bool "Environment in a UBI volume"
 	depends on !CHAIN_OF_TRUST
diff --git a/env/common.c b/env/common.c
index ed18378..6c32a9b4 100644
--- a/env/common.c
+++ b/env/common.c
@@ -141,12 +141,11 @@
 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
 static unsigned char env_flags;
 
-int env_import_redund(const char *buf1, int buf1_read_fail,
-		      const char *buf2, int buf2_read_fail,
-		      int flags)
+int env_check_redund(const char *buf1, int buf1_read_fail,
+		     const char *buf2, int buf2_read_fail)
 {
 	int crc1_ok, crc2_ok;
-	env_t *ep, *tmp_env1, *tmp_env2;
+	env_t *tmp_env1, *tmp_env2;
 
 	tmp_env1 = (env_t *)buf1;
 	tmp_env2 = (env_t *)buf2;
@@ -159,14 +158,13 @@
 	}
 
 	if (buf1_read_fail && buf2_read_fail) {
-		env_set_default("bad env area", 0);
 		return -EIO;
 	} else if (!buf1_read_fail && buf2_read_fail) {
 		gd->env_valid = ENV_VALID;
-		return env_import((char *)tmp_env1, 1, flags);
+		return -EINVAL;
 	} else if (buf1_read_fail && !buf2_read_fail) {
 		gd->env_valid = ENV_REDUND;
-		return env_import((char *)tmp_env2, 1, flags);
+		return -ENOENT;
 	}
 
 	crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
@@ -175,7 +173,6 @@
 			tmp_env2->crc;
 
 	if (!crc1_ok && !crc2_ok) {
-		env_set_default("bad CRC", 0);
 		return -ENOMSG; /* needed for env_load() */
 	} else if (crc1_ok && !crc2_ok) {
 		gd->env_valid = ENV_VALID;
@@ -195,12 +192,37 @@
 			gd->env_valid = ENV_VALID;
 	}
 
+	return 0;
+}
+
+int env_import_redund(const char *buf1, int buf1_read_fail,
+		      const char *buf2, int buf2_read_fail,
+		      int flags)
+{
+	env_t *ep;
+	int ret;
+
+	ret = env_check_redund(buf1, buf1_read_fail, buf2, buf2_read_fail);
+
+	if (ret == -EIO) {
+		env_set_default("bad env area", 0);
+		return -EIO;
+	} else if (ret == -EINVAL) {
+		return env_import((char *)buf1, 1, flags);
+	} else if (ret == -ENOENT) {
+		return env_import((char *)buf2, 1, flags);
+	} else if (ret == -ENOMSG) {
+		env_set_default("bad CRC", 0);
+		return -ENOMSG;
+	}
+
 	if (gd->env_valid == ENV_VALID)
-		ep = tmp_env1;
+		ep = (env_t *)buf1;
 	else
-		ep = tmp_env2;
+		ep = (env_t *)buf2;
 
 	env_flags = ep->flags;
+
 	return env_import((char *)ep, 0, flags);
 }
 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
diff --git a/env/sf.c b/env/sf.c
index 937778a..2eb2de1 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -287,7 +287,10 @@
 #endif
 
 #if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
-static int env_sf_init(void)
+/*
+ * check if Environment on CONFIG_ENV_ADDR is valid.
+ */
+static int env_sf_init_addr(void)
 {
 	env_t *env_ptr = (env_t *)env_sf_get_env_addr();
 
@@ -303,12 +306,103 @@
 }
 #endif
 
+#if defined(CONFIG_ENV_SPI_EARLY)
+/*
+ * early load environment from SPI flash (before relocation)
+ * and check if it is valid.
+ */
+static int env_sf_init_early(void)
+{
+	int ret;
+	int read1_fail;
+	int read2_fail;
+	int crc1_ok;
+	env_t *tmp_env2 = NULL;
+	env_t *tmp_env1;
+
+	/*
+	 * if malloc is not ready yet, we cannot use
+	 * this part yet.
+	 */
+	if (!gd->malloc_limit)
+		return -ENOENT;
+
+	tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN,
+			CONFIG_ENV_SIZE);
+	if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
+		tmp_env2 = (env_t *)memalign(ARCH_DMA_MINALIGN,
+					     CONFIG_ENV_SIZE);
+
+	if (!tmp_env1 || !tmp_env2)
+		goto out;
+
+	ret = setup_flash_device();
+	if (ret)
+		goto out;
+
+	read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
+				    CONFIG_ENV_SIZE, tmp_env1);
+
+	if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
+		read2_fail = spi_flash_read(env_flash,
+					    CONFIG_ENV_OFFSET_REDUND,
+					    CONFIG_ENV_SIZE, tmp_env2);
+		ret = env_check_redund((char *)tmp_env1, read1_fail,
+				       (char *)tmp_env2, read2_fail);
+
+		if (ret == -EIO || ret == -ENOMSG)
+			goto err_read;
+
+		if (gd->env_valid == ENV_VALID)
+			gd->env_addr = (unsigned long)&tmp_env1->data;
+		else
+			gd->env_addr = (unsigned long)&tmp_env2->data;
+	} else {
+		if (read1_fail)
+			goto err_read;
+
+		crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) ==
+				tmp_env1->crc;
+		if (!crc1_ok)
+			goto err_read;
+
+		/* if valid -> this is our env */
+		gd->env_valid = ENV_VALID;
+		gd->env_addr = (unsigned long)&tmp_env1->data;
+	}
+
+	return 0;
+err_read:
+	spi_flash_free(env_flash);
+	env_flash = NULL;
+	free(tmp_env1);
+	if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
+		free(tmp_env2);
+out:
+	/* env is not valid. always return 0 */
+	gd->env_valid = ENV_INVALID;
+	return 0;
+}
+#endif
+
+static int env_sf_init(void)
+{
+#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
+	return env_sf_init_addr();
+#elif defined(CONFIG_ENV_SPI_EARLY)
+	return env_sf_init_early();
+#endif
+	/*
+	 * we must return with 0 if there is nothing done,
+	 * else env_set_inited() get not called in env_init()
+	 */
+	return 0;
+}
+
 U_BOOT_ENV_LOCATION(sf) = {
 	.location	= ENVL_SPI_FLASH,
 	ENV_NAME("SPIFlash")
 	.load		= env_sf_load,
 	.save		= CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL,
-#if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0)
 	.init		= env_sf_init,
-#endif
 };
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 0aa1144..f392043 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -384,7 +384,7 @@
 	 */
 	int logc_prev;
 	/**
-	 * @logl_pref: logging level of the previous message
+	 * @logl_prev: logging level of the previous message
 	 *
 	 * This value is used as logging level for continuation messages.
 	 */
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index 8ca0e83..2b41242 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -125,21 +125,67 @@
 #define	CONFIG_SYS_LOAD_ADDR	0
 
 #define	CONFIG_HOSTNAME		"microblaze-generic"
-#define	CONFIG_BOOTCOMMAND	"base 0;tftp 11000000 image.img;bootm"
 
 /* architecture dependent code */
 #define	CONFIG_SYS_USR_EXCEP	/* user exception */
 
+#if defined(CONFIG_CMD_PXE) && defined(CONFIG_CMD_DHCP)
+#define BOOT_TARGET_DEVICES_PXE(func)	func(PXE, pxe, na)
+#else
+#define BOOT_TARGET_DEVICES_PXE(func)
+#endif
+
+#if defined(CONFIG_CMD_DHCP)
+#define BOOT_TARGET_DEVICES_DHCP(func)	func(DHCP, dhcp, na)
+#else
+#define BOOT_TARGET_DEVICES_DHCP(func)
+#endif
+
+#if defined(CONFIG_SPI_FLASH)
+# define BOOT_TARGET_DEVICES_QSPI(func) func(QSPI, qspi, na)
+#else
+# define BOOT_TARGET_DEVICES_QSPI(func)
+#endif
+
+#define BOOTENV_DEV_QSPI(devtypeu, devtypel, instance) \
+	"bootcmd_qspi=sf probe 0 0 0 && " \
+	"sf read ${scriptaddr} ${script_offset_f} ${script_size_f} && " \
+	"echo QSPI: Trying to boot script at ${scriptaddr} && " \
+	"source ${scriptaddr}; echo QSPI: SCRIPT FAILED: continuing...;\0"
+
+#define BOOTENV_DEV_NAME_QSPI(devtypeu, devtypel, instance) \
+	"qspi "
+
+#define BOOT_TARGET_DEVICES_JTAG(func)	func(JTAG, jtag, na)
+
+#define BOOTENV_DEV_JTAG(devtypeu, devtypel, instance) \
+	"bootcmd_jtag=echo JTAG: Trying to boot script at ${scriptaddr} && " \
+		"source ${scriptaddr}; echo JTAG: SCRIPT FAILED: continuing...;\0"
+
+#define BOOTENV_DEV_NAME_JTAG(devtypeu, devtypel, instance) \
+	"jtag "
+
+#define BOOT_TARGET_DEVICES(func) \
+	BOOT_TARGET_DEVICES_JTAG(func) \
+	BOOT_TARGET_DEVICES_QSPI(func)  \
+	BOOT_TARGET_DEVICES_DHCP(func) \
+	BOOT_TARGET_DEVICES_PXE(func)
+
+#include <config_distro_bootcmd.h>
+
 #ifndef CONFIG_EXTRA_ENV_SETTINGS
-#define	CONFIG_EXTRA_ENV_SETTINGS	"unlock=yes\0" \
-					"nor0=flash-0\0"\
-					"mtdparts=mtdparts=flash-0:"\
-					"256k(u-boot),256k(env),3m(kernel),"\
-					"1m(romfs),1m(cramfs),-(jffs2)\0"\
-					"nc=setenv stdout nc;"\
-					"setenv stdin nc\0" \
-					"serial=setenv stdout serial;"\
-					"setenv stdin serial\0"
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"unlock=yes\0"\
+	"nor0=flash-0\0"\
+	"mtdparts=mtdparts=flash-0:"\
+	"256k(u-boot),256k(env),3m(kernel),"\
+	"1m(romfs),1m(cramfs),-(jffs2)\0"\
+	"nc=setenv stdout nc;"\
+	"setenv stdin nc\0" \
+	"serial=setenv stdout serial;"\
+	"setenv stdin serial\0"\
+	"script_size_f=0x40000\0"\
+	BOOTENV
 #endif
 
 #if defined(CONFIG_XILINX_AXIEMAC)
@@ -167,8 +213,7 @@
 #define CONFIG_SYS_INIT_RAM_SIZE	0x100000
 
 # define CONFIG_SPL_STACK_ADDR		(CONFIG_SYS_INIT_RAM_ADDR + \
-					 CONFIG_SYS_INIT_RAM_SIZE - \
-					 CONFIG_SYS_MALLOC_F_LEN)
+					 CONFIG_SYS_INIT_RAM_SIZE)
 
 /* Just for sure that there is a space for stack */
 #define CONFIG_SPL_STACK_SIZE		0x100
diff --git a/include/configs/xilinx_versal.h b/include/configs/xilinx_versal.h
index 8b41632..f1d2594 100644
--- a/include/configs/xilinx_versal.h
+++ b/include/configs/xilinx_versal.h
@@ -18,7 +18,6 @@
 #define GICD_BASE	0xF9000000
 #define GICR_BASE	0xF9080000
 
-
 #define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_TEXT_BASE
 
 /* Generic Timer Definitions - setup in EL3. Setup by ATF for other cases */
diff --git a/include/configs/xilinx_versal_mini.h b/include/configs/xilinx_versal_mini.h
index 0b201a2..00c9718 100644
--- a/include/configs/xilinx_versal_mini.h
+++ b/include/configs/xilinx_versal_mini.h
@@ -10,7 +10,6 @@
 #ifndef __CONFIG_VERSAL_MINI_H
 #define __CONFIG_VERSAL_MINI_H
 
-
 #define CONFIG_EXTRA_ENV_SETTINGS
 
 #include <configs/xilinx_versal.h>
diff --git a/include/configs/xilinx_zynqmp_mini.h b/include/configs/xilinx_zynqmp_mini.h
index 3f57423b..ef9c768 100644
--- a/include/configs/xilinx_zynqmp_mini.h
+++ b/include/configs/xilinx_zynqmp_mini.h
@@ -10,7 +10,6 @@
 #ifndef __CONFIG_ZYNQMP_MINI_H
 #define __CONFIG_ZYNQMP_MINI_H
 
-
 #define CONFIG_EXTRA_ENV_SETTINGS
 
 #include <configs/xilinx_zynqmp.h>
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 4b7af37..ced7f6f 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -605,6 +605,28 @@
  */
 ofnode ofnode_get_chosen_node(const char *propname);
 
+/**
+ * ofnode_read_aliases_prop() - get the value of a aliases property
+ *
+ * This looks for a property within the /aliases node and returns its value
+ *
+ * @propname: Property name to look for
+ * @sizep: Returns size of property, or FDT_ERR_... error code if function
+ *	returns NULL
+ * @return property value if found, else NULL
+ */
+const void *ofnode_read_aliases_prop(const char *propname, int *sizep);
+
+/**
+ * ofnode_get_aliases_node() - get a referenced node from the aliases node
+ *
+ * This looks up a named property in the aliases node and uses that as a path to
+ * look up a code.
+ *
+ * @return the referenced node if present, else ofnode_null()
+ */
+ofnode ofnode_get_aliases_node(const char *propname);
+
 struct display_timing;
 /**
  * ofnode_decode_display_timing() - decode display timings
diff --git a/include/dt-bindings/clock/xlnx-versal-clk.h b/include/dt-bindings/clock/xlnx-versal-clk.h
new file mode 100644
index 0000000..264d634
--- /dev/null
+++ b/include/dt-bindings/clock/xlnx-versal-clk.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2019 Xilinx Inc.
+ *
+ */
+
+#ifndef _DT_BINDINGS_CLK_VERSAL_H
+#define _DT_BINDINGS_CLK_VERSAL_H
+
+#define PMC_PLL					1
+#define APU_PLL					2
+#define RPU_PLL					3
+#define CPM_PLL					4
+#define NOC_PLL					5
+#define PLL_MAX					6
+#define PMC_PRESRC				7
+#define PMC_POSTCLK				8
+#define PMC_PLL_OUT				9
+#define PPLL					10
+#define NOC_PRESRC				11
+#define NOC_POSTCLK				12
+#define NOC_PLL_OUT				13
+#define NPLL					14
+#define APU_PRESRC				15
+#define APU_POSTCLK				16
+#define APU_PLL_OUT				17
+#define APLL					18
+#define RPU_PRESRC				19
+#define RPU_POSTCLK				20
+#define RPU_PLL_OUT				21
+#define RPLL					22
+#define CPM_PRESRC				23
+#define CPM_POSTCLK				24
+#define CPM_PLL_OUT				25
+#define CPLL					26
+#define PPLL_TO_XPD				27
+#define NPLL_TO_XPD				28
+#define APLL_TO_XPD				29
+#define RPLL_TO_XPD				30
+#define EFUSE_REF				31
+#define SYSMON_REF				32
+#define IRO_SUSPEND_REF				33
+#define USB_SUSPEND				34
+#define SWITCH_TIMEOUT				35
+#define RCLK_PMC				36
+#define RCLK_LPD				37
+#define WDT					38
+#define TTC0					39
+#define TTC1					40
+#define TTC2					41
+#define TTC3					42
+#define GEM_TSU					43
+#define GEM_TSU_LB				44
+#define MUXED_IRO_DIV2				45
+#define MUXED_IRO_DIV4				46
+#define PSM_REF					47
+#define GEM0_RX					48
+#define GEM0_TX					49
+#define GEM1_RX					50
+#define GEM1_TX					51
+#define CPM_CORE_REF				52
+#define CPM_LSBUS_REF				53
+#define CPM_DBG_REF				54
+#define CPM_AUX0_REF				55
+#define CPM_AUX1_REF				56
+#define QSPI_REF				57
+#define OSPI_REF				58
+#define SDIO0_REF				59
+#define SDIO1_REF				60
+#define PMC_LSBUS_REF				61
+#define I2C_REF					62
+#define TEST_PATTERN_REF			63
+#define DFT_OSC_REF				64
+#define PMC_PL0_REF				65
+#define PMC_PL1_REF				66
+#define PMC_PL2_REF				67
+#define PMC_PL3_REF				68
+#define CFU_REF					69
+#define SPARE_REF				70
+#define NPI_REF					71
+#define HSM0_REF				72
+#define HSM1_REF				73
+#define SD_DLL_REF				74
+#define FPD_TOP_SWITCH				75
+#define FPD_LSBUS				76
+#define ACPU					77
+#define DBG_TRACE				78
+#define DBG_FPD					79
+#define LPD_TOP_SWITCH				80
+#define ADMA					81
+#define LPD_LSBUS				82
+#define CPU_R5					83
+#define CPU_R5_CORE				84
+#define CPU_R5_OCM				85
+#define CPU_R5_OCM2				86
+#define IOU_SWITCH				87
+#define GEM0_REF				88
+#define GEM1_REF				89
+#define GEM_TSU_REF				90
+#define USB0_BUS_REF				91
+#define UART0_REF				92
+#define UART1_REF				93
+#define SPI0_REF				94
+#define SPI1_REF				95
+#define CAN0_REF				96
+#define CAN1_REF				97
+#define I2C0_REF				98
+#define I2C1_REF				99
+#define DBG_LPD					100
+#define TIMESTAMP_REF				101
+#define DBG_TSTMP				102
+#define CPM_TOPSW_REF				103
+#define USB3_DUAL_REF				104
+#define OUTCLK_MAX				105
+#define REF_CLK					106
+#define PL_ALT_REF_CLK				107
+#define MUXED_IRO				108
+#define PL_EXT					109
+#define PL_LB					110
+#define MIO_50_OR_51				111
+#define MIO_24_OR_25				112
+
+#endif
diff --git a/include/dt-bindings/power/xlnx-versal-power.h b/include/dt-bindings/power/xlnx-versal-power.h
new file mode 100644
index 0000000..1b75175
--- /dev/null
+++ b/include/dt-bindings/power/xlnx-versal-power.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2019 - 2020 Xilinx, Inc.
+ */
+
+#ifndef _DT_BINDINGS_VERSAL_POWER_H
+#define _DT_BINDINGS_VERSAL_POWER_H
+
+#define PM_DEV_USB_0				(0x18224018U)
+#define PM_DEV_GEM_0				(0x18224019U)
+#define PM_DEV_GEM_1				(0x1822401aU)
+#define PM_DEV_SPI_0				(0x1822401bU)
+#define PM_DEV_SPI_1				(0x1822401cU)
+#define PM_DEV_I2C_0				(0x1822401dU)
+#define PM_DEV_I2C_1				(0x1822401eU)
+#define PM_DEV_CAN_FD_0				(0x1822401fU)
+#define PM_DEV_CAN_FD_1				(0x18224020U)
+#define PM_DEV_UART_0				(0x18224021U)
+#define PM_DEV_UART_1				(0x18224022U)
+#define PM_DEV_GPIO				(0x18224023U)
+#define PM_DEV_TTC_0				(0x18224024U)
+#define PM_DEV_TTC_1				(0x18224025U)
+#define PM_DEV_TTC_2				(0x18224026U)
+#define PM_DEV_TTC_3				(0x18224027U)
+#define PM_DEV_SWDT_FPD				(0x18224029U)
+#define PM_DEV_OSPI				(0x1822402aU)
+#define PM_DEV_QSPI				(0x1822402bU)
+#define PM_DEV_GPIO_PMC				(0x1822402cU)
+#define PM_DEV_SDIO_0				(0x1822402eU)
+#define PM_DEV_SDIO_1				(0x1822402fU)
+#define PM_DEV_RTC				(0x18224034U)
+#define PM_DEV_ADMA_0				(0x18224035U)
+#define PM_DEV_ADMA_1				(0x18224036U)
+#define PM_DEV_ADMA_2				(0x18224037U)
+#define PM_DEV_ADMA_3				(0x18224038U)
+#define PM_DEV_ADMA_4				(0x18224039U)
+#define PM_DEV_ADMA_5				(0x1822403aU)
+#define PM_DEV_ADMA_6				(0x1822403bU)
+#define PM_DEV_ADMA_7				(0x1822403cU)
+#define PM_DEV_AI				(0x18224072U)
+
+#endif
diff --git a/include/env.h b/include/env.h
index af40595..c15339a 100644
--- a/include/env.h
+++ b/include/env.h
@@ -319,6 +319,24 @@
 int env_export(struct environment_s *env_out);
 
 /**
+ * env_check_redund() - check the two redundant environments
+ *   and find out, which is the valid one.
+ *
+ * @buf1: First environment (struct environemnt_s *)
+ * @buf1_read_fail: 0 if buf1 is valid, non-zero if invalid
+ * @buf2: Second environment (struct environemnt_s *)
+ * @buf2_read_fail: 0 if buf2 is valid, non-zero if invalid
+ * @return 0 if OK,
+ *	-EIO if no environment is valid,
+ *	-EINVAL if read of second entry is good
+ *	-ENOENT if read of first entry is good
+ *	-ENOMSG if the CRC was bad
+ */
+
+int env_check_redund(const char *buf1, int buf1_read_fail,
+		     const char *buf2, int buf2_read_fail);
+
+/**
  * env_import_redund() - Select and import one of two redundant environments
  *
  * @buf1: First environment (struct environemnt_s *)
diff --git a/include/getopt.h b/include/getopt.h
new file mode 100644
index 0000000..6f5811e
--- /dev/null
+++ b/include/getopt.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * getopt.h - a simple getopt(3) implementation.
+ *
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ */
+
+#ifndef __GETOPT_H
+#define __GETOPT_H
+
+/**
+ * struct getopt_state - Saved state across getopt() calls
+ */
+struct getopt_state {
+	/**
+	 * @index: Index of the next unparsed argument of @argv. If getopt() has
+	 * parsed all of @argv, then @index will equal @argc.
+	 */
+	int index;
+	/* private: */
+	/** @arg_index: Index within the current argument */
+	int arg_index;
+	union {
+		/* public: */
+		/**
+		 * @opt: Option being parsed when an error occurs. @opt is only
+		 * valid when getopt() returns ``?`` or ``:``.
+		 */
+		int opt;
+		/**
+		 * @arg: The argument to an option, NULL if there is none. @arg
+		 * is only valid when getopt() returns an option character.
+		 */
+		char *arg;
+	/* private: */
+	};
+};
+
+/**
+ * getopt_init_state() - Initialize a &struct getopt_state
+ * @gs: The state to initialize
+ *
+ * This must be called before using @gs with getopt().
+ */
+void getopt_init_state(struct getopt_state *gs);
+
+int __getopt(struct getopt_state *gs, int argc, char *const argv[],
+	     const char *optstring, bool silent);
+
+/**
+ * getopt() - Parse short command-line options
+ * @gs: Internal state and out-of-band return arguments. This must be
+ *      initialized with getopt_init_context() beforehand.
+ * @argc: Number of arguments, not including the %NULL terminator
+ * @argv: Argument list, terminated by %NULL
+ * @optstring: Option specification, as described below
+ *
+ * getopt() parses short options. Short options are single characters. They may
+ * be followed by a required argument or an optional argument. Arguments to
+ * options may occur in the same argument as an option (like ``-larg``), or
+ * in the following argument (like ``-l arg``). An argument containing
+ * options begins with a ``-``. If an option expects no arguments, then it may
+ * be immediately followed by another option (like ``ls -alR``).
+ *
+ * @optstring is a list of accepted options. If an option is followed by ``:``
+ * in @optstring, then it expects a mandatory argument. If an option is followed
+ * by ``::`` in @optstring, it expects an optional argument. @gs.arg points
+ * to the argument, if one is parsed.
+ *
+ * getopt() stops parsing options when it encounters the first non-option
+ * argument, when it encounters the argument ``--``, or when it runs out of
+ * arguments. For example, in ``ls -l foo -R``, option parsing will stop when
+ * getopt() encounters ``foo``, if ``l`` does not expect an argument. However,
+ * the whole list of arguments would be parsed if ``l`` expects an argument.
+ *
+ * An example invocation of getopt() might look like::
+ *
+ *     char *argv[] = { "program", "-cbx", "-a", "foo", "bar", 0 };
+ *     int opt, argc = ARRAY_SIZE(argv) - 1;
+ *     struct getopt_state gs;
+ *
+ *     getopt_init_state(&gs);
+ *     while ((opt = getopt(&gs, argc, argv, "a::b:c")) != -1)
+ *         printf("opt = %c, index = %d, arg = \"%s\"\n", opt, gs.index, gs.arg);
+ *     printf("%d argument(s) left\n", argc - gs.index);
+ *
+ * and would produce an output of::
+ *
+ *     opt = c, index = 1, arg = "<NULL>"
+ *     opt = b, index = 2, arg = "x"
+ *     opt = a, index = 4, arg = "foo"
+ *     1 argument(s) left
+ *
+ * For further information, refer to the getopt(3) man page.
+ *
+ * Return:
+ * * An option character if an option is found. @gs.arg is set to the
+ *   argument if there is one, otherwise it is set to ``NULL``.
+ * * ``-1`` if there are no more options, if a non-option argument is
+ *   encountered, or if an ``--`` argument is encountered.
+ * * ``'?'`` if we encounter an option not in @optstring. @gs.opt is set to
+ *   the unknown option.
+ * * ``':'`` if an argument is required, but no argument follows the
+ *   option. @gs.opt is set to the option missing its argument.
+ *
+ * @gs.index is always set to the index of the next unparsed argument in @argv.
+ */
+static inline int getopt(struct getopt_state *gs, int argc,
+			 char *const argv[], const char *optstring)
+{
+	return __getopt(gs, argc, argv, optstring, false);
+}
+
+/**
+ * getopt_silent() - Parse short command-line options silently
+ * @gs: State
+ * @argc: Argument count
+ * @argv: Argument list
+ * @optstring: Option specification
+ *
+ * Same as getopt(), except no error messages are printed.
+ */
+static inline int getopt_silent(struct getopt_state *gs, int argc,
+				char *const argv[], const char *optstring)
+{
+	return __getopt(gs, argc, argv, optstring, true);
+}
+
+#endif /* __GETOPT_H */
diff --git a/include/log.h b/include/log.h
index 58787a3..4d0692f 100644
--- a/include/log.h
+++ b/include/log.h
@@ -17,56 +17,92 @@
 
 struct cmd_tbl;
 
-/** Log levels supported, ranging from most to least important */
+/**
+ * enum log_level_t - Log levels supported, ranging from most to least important
+ */
 enum log_level_t {
-	LOGL_EMERG = 0,		/* U-Boot is unstable */
-	LOGL_ALERT,		/* Action must be taken immediately */
-	LOGL_CRIT,		/* Critical conditions */
-	LOGL_ERR,		/* Error that prevents something from working */
-	LOGL_WARNING,		/* Warning may prevent optimial operation */
-	LOGL_NOTICE,		/* Normal but significant condition, printf() */
-	LOGL_INFO,		/* General information message */
-	LOGL_DEBUG,		/* Basic debug-level message */
-	LOGL_DEBUG_CONTENT,	/* Debug message showing full message content */
-	LOGL_DEBUG_IO,		/* Debug message showing hardware I/O access */
+	/** @LOGL_EMERG: U-Boot is unstable */
+	LOGL_EMERG = 0,
+	/** @LOGL_ALERT: Action must be taken immediately */
+	LOGL_ALERT,
+	/** @LOGL_CRIT: Critical conditions */
+	LOGL_CRIT,
+	/** @LOGL_ERR: Error that prevents something from working */
+	LOGL_ERR,
+	/** @LOGL_WARNING: Warning may prevent optimial operation */
+	LOGL_WARNING,
+	/** @LOGL_NOTICE: Normal but significant condition, printf() */
+	LOGL_NOTICE,
+	/** @LOGL_INFO: General information message */
+	LOGL_INFO,
+	/** @LOGL_DEBUG: Basic debug-level message */
+	LOGL_DEBUG,
+	/** @LOGL_DEBUG_CONTENT: Debug message showing full message content */
+	LOGL_DEBUG_CONTENT,
+	/** @LOGL_DEBUG_IO: Debug message showing hardware I/O access */
+	LOGL_DEBUG_IO,
 
+	/** @LOGL_COUNT: Total number of valid log levels */
 	LOGL_COUNT,
+	/** @LOGL_NONE: Used to indicate that there is no valid log level */
 	LOGL_NONE,
 
-	LOGL_LEVEL_MASK = 0xf,	/* Mask for valid log levels */
-	LOGL_FORCE_DEBUG = 0x10, /* Mask to force output due to LOG_DEBUG */
+	/** @LOGL_LEVEL_MASK: Mask for valid log levels */
+	LOGL_LEVEL_MASK = 0xf,
+	/** @LOGL_FORCE_DEBUG: Mask to force output due to LOG_DEBUG */
+	LOGL_FORCE_DEBUG = 0x10,
 
+	/** @LOGL_FIRST: The first, most-important log level */
 	LOGL_FIRST = LOGL_EMERG,
+	/** @LOGL_MAX: The last, least-important log level */
 	LOGL_MAX = LOGL_DEBUG_IO,
-	LOGL_CONT = -1,		/* Use same log level as in previous call */
+	/** @LOGL_CONT: Use same log level as in previous call */
+	LOGL_CONT = -1,
 };
 
 /**
- * Log categories supported. Most of these correspond to uclasses (i.e.
- * enum uclass_id) but there are also some more generic categories.
+ * enum log_category_t - Log categories supported.
+ *
+ * Log categories between %LOGC_FIRST and %LOGC_NONE correspond to uclasses
+ * (i.e. &enum uclass_id), but there are also some more generic categories.
  *
  * Remember to update log_cat_name[] after adding a new category.
  */
 enum log_category_t {
+	/** @LOGC_FIRST: First log category */
 	LOGC_FIRST = 0,	/* First part mirrors UCLASS_... */
 
+	/** @LOGC_NONE: Default log category */
 	LOGC_NONE = UCLASS_COUNT,	/* First number is after all uclasses */
-	LOGC_ARCH,	/* Related to arch-specific code */
-	LOGC_BOARD,	/* Related to board-specific code */
-	LOGC_CORE,	/* Related to core features (non-driver-model) */
-	LOGC_DM,	/* Core driver-model */
-	LOGC_DT,	/* Device-tree */
-	LOGC_EFI,	/* EFI implementation */
-	LOGC_ALLOC,	/* Memory allocation */
-	LOGC_SANDBOX,	/* Related to the sandbox board */
-	LOGC_BLOBLIST,	/* Bloblist */
-	LOGC_DEVRES,	/* Device resources (devres_... functions) */
-	/* Advanced Configuration and Power Interface (ACPI) */
+	/** @LOGC_ARCH: Related to arch-specific code */
+	LOGC_ARCH,
+	/** @LOGC_BOARD: Related to board-specific code */
+	LOGC_BOARD,
+	/** @LOGC_CORE: Related to core features (non-driver-model) */
+	LOGC_CORE,
+	/** @LOGC_DM: Core driver-model */
+	LOGC_DM,
+	/** @LOGC_DT: Device-tree */
+	LOGC_DT,
+	/** @LOGC_EFI: EFI implementation */
+	LOGC_EFI,
+	/** @LOGC_ALLOC: Memory allocation */
+	LOGC_ALLOC,
+	/** @LOGC_SANDBOX: Related to the sandbox board */
+	LOGC_SANDBOX,
+	/** @LOGC_BLOBLIST: Bloblist */
+	LOGC_BLOBLIST,
+	/** @LOGC_DEVRES: Device resources (``devres_...`` functions) */
+	LOGC_DEVRES,
+	/** @LOGC_ACPI: Advanced Configuration and Power Interface (ACPI) */
 	LOGC_ACPI,
 
-	LOGC_COUNT,	/* Number of log categories */
-	LOGC_END,	/* Sentinel value for a list of log categories */
-	LOGC_CONT = -1,	/* Use same category as in previous call */
+	/** @LOGC_COUNT: Number of log categories */
+	LOGC_COUNT,
+	/** @LOGC_END: Sentinel value for lists of log categories */
+	LOGC_END,
+	/** @LOGC_CONT: Use same category as in previous call */
+	LOGC_CONT = -1,
 };
 
 /* Helper to cast a uclass ID to a log category */
@@ -85,7 +121,7 @@
  * @func: Function where log record was generated
  * @fmt: printf() format string for log record
  * @...: Optional parameters, according to the format string @fmt
- * @return 0 if log record was emitted, -ve on error
+ * Return: 0 if log record was emitted, -ve on error
  */
 int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 	 int line, const char *func, const char *fmt, ...)
@@ -240,7 +276,7 @@
  * full pathname as it may be huge. Only use this when the user should be
  * warning, similar to BUG_ON() in linux.
  *
- * @return true if assertion succeeded (condition is true), else false
+ * Return: true if assertion succeeded (condition is true), else false
  */
 #define assert_noisy(x) \
 	({ bool _val = (x); \
@@ -324,8 +360,9 @@
  */
 struct log_driver {
 	const char *name;
+
 	/**
-	 * emit() - emit a log record
+	 * @emit: emit a log record
 	 *
 	 * Called by the log system to pass a log record to a particular driver
 	 * for processing. The filter is checked before calling this function.
@@ -361,21 +398,32 @@
 	LOGF_MAX_CATEGORIES = 5,	/* maximum categories per filter */
 };
 
+/**
+ * enum log_filter_flags - Flags which modify a filter
+ */
 enum log_filter_flags {
-	LOGFF_HAS_CAT		= 1 << 0,	/* Filter has a category list */
+	/** @LOGFF_HAS_CAT: Filter has a category list */
+	LOGFF_HAS_CAT	= 1 << 0,
+	/** @LOGFF_DENY: Filter denies matching messages */
+	LOGFF_DENY	= 1 << 1,
+	/** @LOGFF_LEVEL_MIN: Filter's level is a minimum, not a maximum */
+	LOGFF_LEVEL_MIN = 1 << 2,
 };
 
 /**
  * struct log_filter - criterial to filter out log messages
  *
+ * If a message matches all criteria, then it is allowed. If LOGFF_DENY is set,
+ * then it is denied instead.
+ *
  * @filter_num: Sequence number of this filter.  This is returned when adding a
  *	new filter, and must be provided when removing a previously added
  *	filter.
- * @flags: Flags for this filter (LOGFF_...)
- * @cat_list: List of categories to allow (terminated by LOGC_none). If empty
- *	then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries
+ * @flags: Flags for this filter (``LOGFF_...``)
+ * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty
+ *	then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries
  *	can be provided
- * @max_level: Maximum log level to allow
+ * @level: Maximum (or minimum, if %LOGFF_MIN_LEVEL) log level to allow
  * @file_list: List of files to allow, separated by comma. If NULL then all
  *	files are permitted
  * @sibling_node: Next filter in the list of filters for this log device
@@ -384,7 +432,7 @@
 	int filter_num;
 	int flags;
 	enum log_category_t cat_list[LOGF_MAX_CATEGORIES];
-	enum log_level_t max_level;
+	enum log_level_t level;
 	const char *file_list;
 	struct list_head sibling_node;
 };
@@ -400,8 +448,9 @@
  * log_get_cat_name() - Get the name of a category
  *
  * @cat: Category to look up
- * @return category name (which may be a uclass driver name) if found, or
- *	 "<invalid>" if invalid, or "<missing>" if not found
+ * Return: category name (which may be a uclass driver name) if found, or
+ *	   "<invalid>" if invalid, or "<missing>" if not found. All error
+ *	   responses begin with '<'.
  */
 const char *log_get_cat_name(enum log_category_t cat);
 
@@ -409,7 +458,7 @@
  * log_get_cat_by_name() - Look up a category by name
  *
  * @name: Name to look up
- * @return category ID, or LOGC_NONE if not found
+ * Return: Category, or %LOGC_NONE if not found
  */
 enum log_category_t log_get_cat_by_name(const char *name);
 
@@ -417,7 +466,7 @@
  * log_get_level_name() - Get the name of a log level
  *
  * @level: Log level to look up
- * @return log level name (in ALL CAPS)
+ * Return: Log level name (in ALL CAPS)
  */
 const char *log_get_level_name(enum log_level_t level);
 
@@ -425,10 +474,41 @@
  * log_get_level_by_name() - Look up a log level by name
  *
  * @name: Name to look up
- * @return log level ID, or LOGL_NONE if not found
+ * Return: Log level, or %LOGL_NONE if not found
  */
 enum log_level_t log_get_level_by_name(const char *name);
 
+/**
+ * log_device_find_by_name() - Look up a log device by its driver's name
+ *
+ * @drv_name: Name of the driver
+ * Return: the log device, or %NULL if not found
+ */
+struct log_device *log_device_find_by_name(const char *drv_name);
+
+/**
+ * log_has_cat() - check if a log category exists within a list
+ *
+ * @cat_list: List of categories to check, at most %LOGF_MAX_CATEGORIES entries
+ *	long, terminated by %LC_END if fewer
+ * @cat: Category to search for
+ *
+ * Return: ``true`` if @cat is in @cat_list, else ``false``
+ */
+bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat);
+
+/**
+ * log_has_file() - check if a file is with a list
+ *
+ * @file_list: List of files to check, separated by comma
+ * @file: File to check for. This string is matched against the end of each
+ *	file in the list, i.e. ignoring any preceding path. The list is
+ *	intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c
+ *
+ * Return: ``true`` if @file is in @file_list, else ``false``
+ */
+bool log_has_file(const char *file_list, const char *file);
+
 /* Log format flags (bit numbers) for gd->log_fmt. See log_fmt_chars */
 enum log_fmt {
 	LOGF_CAT	= 0,
@@ -446,21 +526,48 @@
 int do_log_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 /**
+ * log_add_filter_flags() - Add a new filter to a log device, specifying flags
+ *
+ * @drv_name: Driver name to add the filter to (since each driver only has a
+ *	single device)
+ * @flags: Flags for this filter (``LOGFF_...``)
+ * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty
+ *	then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries
+ *	can be provided
+ * @level: Maximum (or minimum, if %LOGFF_LEVEL_MIN) log level to allow
+ * @file_list: List of files to allow, separated by comma. If NULL then all
+ *	files are permitted
+ * Return:
+ *   the sequence number of the new filter (>=0) if the filter was added, or a
+ *   -ve value on error
+ */
+int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[],
+			 enum log_level_t level, const char *file_list,
+			 int flags);
+
+/**
  * log_add_filter() - Add a new filter to a log device
  *
  * @drv_name: Driver name to add the filter to (since each driver only has a
  *	single device)
- * @cat_list: List of categories to allow (terminated by LOGC_none). If empty
- *	then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries
+ * @cat_list: List of categories to allow (terminated by %LOGC_END). If empty
+ *	then all categories are permitted. Up to %LOGF_MAX_CATEGORIES entries
  *	can be provided
  * @max_level: Maximum log level to allow
- * @file_list: List of files to allow, separated by comma. If NULL then all
+ * @file_list: List of files to allow, separated by comma. If %NULL then all
  *	files are permitted
- * @return the sequence number of the new filter (>=0) if the filter was added,
- *	or a -ve value on error
+ * Return:
+ *   the sequence number of the new filter (>=0) if the filter was added, or a
+ *   -ve value on error
  */
-int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
-		   enum log_level_t max_level, const char *file_list);
+static inline int log_add_filter(const char *drv_name,
+				 enum log_category_t cat_list[],
+				 enum log_level_t max_level,
+				 const char *file_list)
+{
+	return log_add_filter_flags(drv_name, cat_list, max_level, file_list,
+				    0);
+}
 
 /**
  * log_remove_filter() - Remove a filter from a log device
@@ -468,8 +575,9 @@
  * @drv_name: Driver name to remove the filter from (since each driver only has
  *	a single device)
  * @filter_num: Filter number to remove (as returned by log_add_filter())
- * @return 0 if the filter was removed, -ENOENT if either the driver or the
- *	filter number was not found
+ * Return:
+ *   0 if the filter was removed, -%ENOENT if either the driver or the filter
+ *   number was not found
  */
 int log_remove_filter(const char *drv_name, int filter_num);
 
@@ -490,7 +598,7 @@
 /**
  * log_init() - Set up the log system ready for use
  *
- * @return 0 if OK, -ENOMEM if out of memory
+ * Return: 0 if OK, -%ENOMEM if out of memory
  */
 int log_init(void);
 #else
@@ -504,7 +612,7 @@
  * log_get_default_format() - get default log format
  *
  * The default log format is configurable via
- * CONFIG_LOGF_FILE, CONFIG_LOGF_LINE, CONFIG_LOGF_FUNC.
+ * %CONFIG_LOGF_FILE, %CONFIG_LOGF_LINE, and %CONFIG_LOGF_FUNC.
  *
  * Return:	default log format
  */
diff --git a/include/mmc.h b/include/mmc.h
index ac7b54f..1d377e0 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -360,6 +360,19 @@
 #define MMC_NUM_BOOT_PARTITION	2
 #define MMC_PART_RPMB           3       /* RPMB partition number */
 
+/* timing specification used */
+#define MMC_TIMING_LEGACY	0
+#define MMC_TIMING_MMC_HS	1
+#define MMC_TIMING_SD_HS	2
+#define MMC_TIMING_UHS_SDR12	3
+#define MMC_TIMING_UHS_SDR25	4
+#define MMC_TIMING_UHS_SDR50	5
+#define MMC_TIMING_UHS_SDR104	6
+#define MMC_TIMING_UHS_DDR50	7
+#define MMC_TIMING_MMC_DDR52	8
+#define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+
 /* Driver model support */
 
 /**
diff --git a/include/sdhci.h b/include/sdhci.h
index f69d5f8..1fd20ec 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -244,6 +244,7 @@
 #define SDHCI_QUIRK_BROKEN_HISPD_MODE	BIT(5)
 #define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 6)
 #define SDHCI_QUIRK_USE_WIDE8		(1 << 8)
+#define SDHCI_QUIRK_NO_1_8_V		(1 << 9)
 
 /* to make gcc happy */
 struct sdhci_host;
diff --git a/include/test/log.h b/include/test/log.h
index c661cde..e902891 100644
--- a/include/test/log.h
+++ b/include/test/log.h
@@ -10,7 +10,10 @@
 
 #include <test/test.h>
 
+#define LOGF_TEST (BIT(LOGF_FUNC) | BIT(LOGF_MSG))
+
 /* Declare a new logging test */
 #define LOG_TEST(_name) UNIT_TEST(_name, 0, log_test)
+#define LOG_TEST_FLAGS(_name, _flags) UNIT_TEST(_name, _flags, log_test)
 
 #endif /* __TEST_LOG_H__ */
diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h
index 1da8af1..7b7c291 100644
--- a/include/u-boot/rsa-mod-exp.h
+++ b/include/u-boot/rsa-mod-exp.h
@@ -66,7 +66,7 @@
 		struct key_prop *node, uint8_t *out);
 
 #if defined(CONFIG_CMD_ZYNQ_RSA)
-int zynq_pow_mod(u32 *keyptr, u32 *inout);
+int zynq_pow_mod(uint32_t *keyptr, uint32_t *inout);
 #endif
 
 /**
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
index b07e3e0..7b71343 100644
--- a/include/zynqmp_tap_delay.h
+++ b/include/zynqmp_tap_delay.h
@@ -10,10 +10,11 @@
 
 #ifdef CONFIG_ARCH_ZYNQMP
 void zynqmp_dll_reset(u8 deviceid);
-void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank);
+void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay, u32 otap_delay);
 #else
 inline void zynqmp_dll_reset(u8 deviceid) {}
-inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {}
+inline void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay,
+				       u32 otap_delay) {}
 #endif
 
 #endif
diff --git a/lib/Kconfig b/lib/Kconfig
index 37aae73..79651ea 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -550,6 +550,11 @@
 	  This enables functions for printing dumps of binary data in
 	  SPL.
 
+config GETOPT
+	bool "Enable getopt"
+	help
+	  This enables functions for parsing command-line options.
+
 config OF_LIBFDT
 	bool "Enable the FDT library"
 	default y if OF_CONTROL
diff --git a/lib/Makefile b/lib/Makefile
index 0cd7bea..7c7fb9a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -106,6 +106,7 @@
 obj-y += tables_csum.o
 obj-y += time.o
 obj-y += hexdump.o
+obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_TRACE) += trace.o
 obj-$(CONFIG_LIB_UUID) += uuid.o
 obj-$(CONFIG_LIB_RAND) += rand.o
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644
index 0000000..8b4515d
--- /dev/null
+++ b/lib/getopt.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation.
+ *
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ */
+
+#define LOG_CATEGORY LOGC_CORE
+
+#include <common.h>
+#include <getopt.h>
+#include <log.h>
+
+void getopt_init_state(struct getopt_state *gs)
+{
+	gs->index = 1;
+	gs->arg_index = 1;
+}
+
+int __getopt(struct getopt_state *gs, int argc, char *const argv[],
+	     const char *optstring, bool silent)
+{
+	char curopt;   /* current option character */
+	const char *curoptp; /* pointer to the current option in optstring */
+
+	while (1) {
+		log_debug("arg_index: %d index: %d\n", gs->arg_index,
+			  gs->index);
+
+		/* `--` indicates the end of options */
+		if (gs->arg_index == 1 && argv[gs->index] &&
+		    !strcmp(argv[gs->index], "--")) {
+			gs->index++;
+			return -1;
+		}
+
+		/* Out of arguments */
+		if (gs->index >= argc)
+			return -1;
+
+		/* Can't parse non-options */
+		if (*argv[gs->index] != '-')
+			return -1;
+
+		/* We have found an option */
+		curopt = argv[gs->index][gs->arg_index];
+		if (curopt)
+			break;
+		/*
+		 * no more options in current argv[] element; try the next one
+		 */
+		gs->index++;
+		gs->arg_index = 1;
+	}
+
+	/* look up current option in optstring */
+	curoptp = strchr(optstring, curopt);
+
+	if (!curoptp) {
+		if (!silent)
+			printf("%s: invalid option -- %c\n", argv[0], curopt);
+		gs->opt = curopt;
+		gs->arg_index++;
+		return '?';
+	}
+
+	if (*(curoptp + 1) != ':') {
+		/* option with no argument. Just return it */
+		gs->arg = NULL;
+		gs->arg_index++;
+		return curopt;
+	}
+
+	if (*(curoptp + 1) && *(curoptp + 2) == ':') {
+		/* optional argument */
+		if (argv[gs->index][gs->arg_index + 1]) {
+			/* optional argument with directly following arg */
+			gs->arg = argv[gs->index++] + gs->arg_index + 1;
+			gs->arg_index = 1;
+			return curopt;
+		}
+		if (gs->index + 1 == argc) {
+			/* We are at the last argv[] element */
+			gs->arg = NULL;
+			gs->index++;
+			return curopt;
+		}
+		if (*argv[gs->index + 1] != '-') {
+			/*
+			 * optional argument with arg in next argv[] element
+			 */
+			gs->index++;
+			gs->arg = argv[gs->index++];
+			gs->arg_index = 1;
+			return curopt;
+		}
+
+		/* no optional argument found */
+		gs->arg = NULL;
+		gs->arg_index = 1;
+		gs->index++;
+		return curopt;
+	}
+
+	if (argv[gs->index][gs->arg_index + 1]) {
+		/* required argument with directly following arg */
+		gs->arg = argv[gs->index++] + gs->arg_index + 1;
+		gs->arg_index = 1;
+		return curopt;
+	}
+
+	gs->index++;
+	gs->arg_index = 1;
+
+	if (gs->index >= argc || argv[gs->index][0] == '-') {
+		if (!silent)
+			printf("option requires an argument -- %c\n", curopt);
+		gs->opt = curopt;
+		return ':';
+	}
+
+	gs->arg = argv[gs->index++];
+	return curopt;
+}
diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c
index 78c688d..74f9eb1 100644
--- a/lib/rsa/rsa-mod-exp.c
+++ b/lib/rsa/rsa-mod-exp.c
@@ -321,7 +321,7 @@
  *        pow_mod calculation required for zynq is bit different from
  *        pw_mod above here, hence defined zynq specific routine.
  */
-int zynq_pow_mod(u32 *keyptr, u32 *inout)
+int zynq_pow_mod(uint32_t *keyptr, uint32_t *inout)
 {
 	u32 *result, *ptr;
 	uint i;
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 01ac3c2..fb1ceb1 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -207,6 +207,28 @@
 }
 DM_TEST(dm_test_ofnode_read_chosen, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
+static int dm_test_ofnode_read_aliases(struct unit_test_state *uts)
+{
+	const void *val;
+	ofnode node;
+	int size;
+
+	node = ofnode_get_aliases_node("eth3");
+	ut_assert(ofnode_valid(node));
+	ut_asserteq_str("sbe5", ofnode_get_name(node));
+
+	node = ofnode_get_aliases_node("unknown");
+	ut_assert(!ofnode_valid(node));
+
+	val = ofnode_read_aliases_prop("spi0", &size);
+	ut_assertnonnull(val);
+	ut_asserteq(7, size);
+	ut_asserteq_str("/spi@0", (const char *)val);
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_read_aliases, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
 static int dm_test_ofnode_get_child_count(struct unit_test_state *uts)
 {
 	ofnode node, child_node;
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 15cd512..98a9abf 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -14,3 +14,4 @@
 obj-$(CONFIG_UT_LIB_ASN1) += asn1.o
 obj-$(CONFIG_UT_LIB_RSA) += rsa.o
 obj-$(CONFIG_AES) += test_aes.o
+obj-$(CONFIG_GETOPT) += getopt.o
diff --git a/test/lib/getopt.c b/test/lib/getopt.c
new file mode 100644
index 0000000..3c68b93
--- /dev/null
+++ b/test/lib/getopt.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ *
+ * Portions of these tests were inspired by glibc's posix/bug-getopt1.c and
+ * posix/tst-getopt-cancel.c
+ */
+
+#include <common.h>
+#include <getopt.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int do_test_getopt(struct unit_test_state *uts, int line,
+			  struct getopt_state *gs, const char *optstring,
+			  int args, char *argv[], int expected_count,
+			  int expected[])
+{
+	int opt;
+
+	getopt_init_state(gs);
+	for (int i = 0; i < expected_count; i++) {
+		opt = getopt_silent(gs, args, argv, optstring);
+		if (expected[i] != opt) {
+			/*
+			 * Fudge the line number so we can tell which test
+			 * failed
+			 */
+			ut_failf(uts, __FILE__, line, __func__,
+				 "expected[i] == getopt()",
+				 "Expected '%c' (%d) with i=%d, got '%c' (%d)",
+				 expected[i], expected[i], i, opt, opt);
+			return CMD_RET_FAILURE;
+		}
+	}
+
+	opt = getopt_silent(gs, args, argv, optstring);
+	if (opt != -1) {
+		ut_failf(uts, __FILE__, line, __func__,
+			 "getopt() != -1",
+			 "Expected -1, got '%c' (%d)", opt, opt);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
+#define test_getopt(optstring, argv, expected) do { \
+	int ret = do_test_getopt(uts, __LINE__, &gs, optstring, \
+				 ARRAY_SIZE(argv) - 1, argv, \
+				 ARRAY_SIZE(expected), expected); \
+	if (ret) \
+		return ret; \
+} while (0)
+
+static int lib_test_getopt(struct unit_test_state *uts)
+{
+	struct getopt_state gs;
+
+	/* Happy path */
+	test_getopt("ab:c",
+		    ((char *[]){ "program", "-cb", "x", "-a", "foo", 0 }),
+		    ((int []){ 'c', 'b', 'a' }));
+	ut_asserteq(4, gs.index);
+
+	/* Make sure we pick up the optional argument */
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-cbx", "-a", "foo", 0 }),
+		    ((int []){ 'c', 'b', 'a' }));
+	ut_asserteq(4, gs.index);
+
+	/* Test required arguments */
+	test_getopt("a:b", ((char *[]){ "program", "-a", 0 }),
+		    ((int []){ ':' }));
+	ut_asserteq('a', gs.opt);
+	test_getopt("a:b", ((char *[]){ "program", "-b", "-a", 0 }),
+		    ((int []){ 'b', ':' }));
+	ut_asserteq('a', gs.opt);
+
+	/* Test invalid arguments */
+	test_getopt("ab:c", ((char *[]){ "program", "-d", 0 }),
+		    ((int []){ '?' }));
+	ut_asserteq('d', gs.opt);
+
+	/* Test arg */
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-a", 0 }),
+		    ((int []){ 'a' }));
+	ut_asserteq(2, gs.index);
+	ut_assertnull(gs.arg);
+
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-afoo", 0 }),
+		    ((int []){ 'a' }));
+	ut_asserteq(2, gs.index);
+	ut_assertnonnull(gs.arg);
+	ut_asserteq_str("foo", gs.arg);
+
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-a", "foo", 0 }),
+		    ((int []){ 'a' }));
+	ut_asserteq(3, gs.index);
+	ut_assertnonnull(gs.arg);
+	ut_asserteq_str("foo", gs.arg);
+
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-bfoo", 0 }),
+		    ((int []){ 'b' }));
+	ut_asserteq(2, gs.index);
+	ut_assertnonnull(gs.arg);
+	ut_asserteq_str("foo", gs.arg);
+
+	test_getopt("a::b:c",
+		    ((char *[]){ "program", "-b", "foo", 0 }),
+		    ((int []){ 'b' }));
+	ut_asserteq(3, gs.index);
+	ut_assertnonnull(gs.arg);
+	ut_asserteq_str("foo", gs.arg);
+
+	return 0;
+}
+LIB_TEST(lib_test_getopt, 0);
diff --git a/test/log/Makefile b/test/log/Makefile
index fdf5295..88bc573 100644
--- a/test/log/Makefile
+++ b/test/log/Makefile
@@ -3,6 +3,7 @@
 # Copyright (c) 2017 Google, Inc
 
 obj-$(CONFIG_LOG_TEST) += log_test.o
+obj-$(CONFIG_CMD_LOG) += log_filter.o
 
 ifdef CONFIG_UT_LOG
 
diff --git a/test/log/log_filter.c b/test/log/log_filter.c
new file mode 100644
index 0000000..e8a6e01
--- /dev/null
+++ b/test/log/log_filter.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <log.h>
+#include <test/log.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Test invalid options */
+static int log_test_filter_invalid(struct unit_test_state *uts)
+{
+	ut_asserteq(1, run_command("log filter-add -AD", 0));
+	ut_asserteq(1, run_command("log filter-add -l1 -L1", 0));
+	ut_asserteq(1, run_command("log filter-add -l1 -L1", 0));
+	ut_asserteq(1, run_command("log filter-add -lfoo", 0));
+	ut_asserteq(1, run_command("log filter-add -cfoo", 0));
+	ut_asserteq(1, run_command("log filter-add -ccore -ccore -ccore -ccore "
+				   "-ccore -ccore", 0));
+
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_filter_invalid, UT_TESTF_CONSOLE_REC);
+
+/* Test adding and removing filters */
+static int log_test_filter(struct unit_test_state *uts)
+{
+	bool any_found = false;
+	bool filt1_found = false;
+	bool filt2_found = false;
+	char cmd[32];
+	struct log_filter *filt;
+	struct log_device *ldev;
+	ulong filt1, filt2;
+
+#define create_filter(args, filter_num) do {\
+	ut_assertok(console_record_reset_enable()); \
+	ut_assertok(run_command("log filter-add -p " args, 0)); \
+	ut_assert_skipline(); \
+	ut_assertok(strict_strtoul(uts->actual_str, 10, &(filter_num))); \
+	ut_assert_console_end(); \
+} while (0)
+
+	create_filter("", filt1);
+	create_filter("-DL warning -cmmc -cspi -ffile", filt2);
+
+	ldev = log_device_find_by_name("console");
+	ut_assertnonnull(ldev);
+	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
+		if (filt->filter_num == filt1) {
+			filt1_found = true;
+			ut_asserteq(0, filt->flags);
+			ut_asserteq(LOGL_MAX, filt->level);
+			ut_assertnull(filt->file_list);
+		} else if (filt->filter_num == filt2) {
+			filt2_found = true;
+			ut_asserteq(LOGFF_HAS_CAT | LOGFF_DENY |
+				    LOGFF_LEVEL_MIN, filt->flags);
+			ut_asserteq(true, log_has_cat(filt->cat_list,
+						      log_uc_cat(UCLASS_MMC)));
+			ut_asserteq(true, log_has_cat(filt->cat_list,
+						      log_uc_cat(UCLASS_SPI)));
+			ut_asserteq(LOGL_WARNING, filt->level);
+			ut_asserteq_str("file", filt->file_list);
+		}
+	}
+	ut_asserteq(true, filt1_found);
+	ut_asserteq(true, filt2_found);
+
+#define remove_filter(filter_num) do { \
+	ut_assertok(console_record_reset_enable()); \
+	snprintf(cmd, sizeof(cmd), "log filter-remove %lu", filter_num); \
+	ut_assertok(run_command(cmd, 0)); \
+	ut_assert_console_end(); \
+} while (0)
+
+	remove_filter(filt1);
+	remove_filter(filt2);
+
+	filt1_found = false;
+	filt2_found = false;
+	list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
+		if (filt->filter_num == filt1)
+			filt1_found = true;
+		else if (filt->filter_num == filt2)
+			filt2_found = true;
+	}
+	ut_asserteq(false, filt1_found);
+	ut_asserteq(false, filt2_found);
+
+	create_filter("", filt1);
+	create_filter("", filt2);
+
+	ut_assertok(console_record_reset_enable());
+	ut_assertok(run_command("log filter-remove -a", 0));
+	ut_assert_console_end();
+
+	list_for_each_entry(filt, &ldev->filter_head, sibling_node)
+		any_found = true;
+	ut_asserteq(false, any_found);
+
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_filter, UT_TESTF_CONSOLE_REC);
diff --git a/test/log/log_test.c b/test/log/log_test.c
index 6a60ff6..ea4fc6b 100644
--- a/test/log/log_test.c
+++ b/test/log/log_test.c
@@ -9,12 +9,17 @@
 #include <common.h>
 #include <command.h>
 #include <log.h>
+#include <test/log.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 /* emit some sample log records in different ways, for testing */
-static int log_run(enum uclass_id cat, const char *file)
+static int do_log_run(int cat, const char *file)
 {
 	int i;
 
+	gd->log_fmt = LOGF_TEST;
 	debug("debug\n");
 	for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
 		log(cat, i, "log %d\n", i);
@@ -22,203 +27,358 @@
 		     i);
 	}
 
+	gd->log_fmt = log_get_default_format();
 	return 0;
 }
 
-static int log_test(int testnum)
-{
-	int ret;
+#define log_run_cat(cat) do_log_run(cat, "file")
+#define log_run_file(file) do_log_run(UCLASS_SPI, file)
+#define log_run() do_log_run(UCLASS_SPI, "file")
 
-	printf("test %d\n", testnum);
-	switch (testnum) {
-	case 0: {
-		/* Check a category filter using the first category */
-		enum log_category_t cat_list[] = {
-			log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI),
-			LOGC_NONE, LOGC_END
-		};
+#define EXPECT_LOG BIT(0)
+#define EXPECT_DIRECT BIT(1)
+#define EXPECT_EXTRA BIT(2)
 
-		ret = log_add_filter("console", cat_list, LOGL_MAX, NULL);
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_MMC, "file");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 1: {
-		/* Check a category filter using the second category */
-		enum log_category_t cat_list[] = {
-			log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), LOGC_END
-		};
+static int do_check_log_entries(struct unit_test_state *uts, int flags, int min,
+				int max)
+{
+	int i;
 
-		ret = log_add_filter("console", cat_list, LOGL_MAX, NULL);
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
+	for (i = min; i <= max; i++) {
+		if (flags & EXPECT_LOG)
+			ut_assert_nextline("do_log_run() log %d", i);
+		if (flags & EXPECT_DIRECT)
+			ut_assert_nextline("func() _log %d", i);
 	}
-	case 2: {
-		/* Check a category filter that should block log entries */
-		enum log_category_t cat_list[] = {
-			log_uc_cat(UCLASS_MMC),  LOGC_NONE, LOGC_END
-		};
+	if (flags & EXPECT_EXTRA)
+		for (; i <= LOGL_MAX ; i++)
+			ut_assert_nextline("func() _log %d", i);
 
-		ret = log_add_filter("console", cat_list, LOGL_MAX, NULL);
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 3: {
-		/* Check a passing file filter */
-		ret = log_add_filter("console", NULL, LOGL_MAX, "file");
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 4: {
-		/* Check a failing file filter */
-		ret = log_add_filter("console", NULL, LOGL_MAX, "file");
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file2");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 5: {
-		/* Check a passing file filter (second in list) */
-		ret = log_add_filter("console", NULL, LOGL_MAX, "file,file2");
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file2");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 6: {
-		/* Check a passing file filter */
-		ret = log_add_filter("console", NULL, LOGL_MAX,
-				     "file,file2,log/log_test.c");
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file2");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 7: {
-		/* Check a log level filter */
-		ret = log_add_filter("console", NULL, LOGL_WARNING, NULL);
-		if (ret < 0)
-			return ret;
-		log_run(UCLASS_SPI, "file");
-		ret = log_remove_filter("console", ret);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 8: {
-		/* Check two filters, one of which passes everything */
-		int filt1, filt2;
+	ut_assert_console_end();
+	return 0;
+}
 
-		ret = log_add_filter("console", NULL, LOGL_WARNING, NULL);
-		if (ret < 0)
-			return ret;
-		filt1 = ret;
-		ret = log_add_filter("console", NULL, LOGL_MAX, NULL);
-		if (ret < 0)
-			return ret;
-		filt2 = ret;
-		log_run(UCLASS_SPI, "file");
-		ret = log_remove_filter("console", filt1);
-		if (ret < 0)
-			return ret;
-		ret = log_remove_filter("console", filt2);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 9: {
-		/* Check three filters, which together pass everything */
-		int filt1, filt2, filt3;
+#define check_log_entries_flags_levels(flags, min, max) do {\
+	int ret = do_check_log_entries(uts, flags, min, max); \
+	if (ret) \
+		return ret; \
+} while (0)
 
-		ret = log_add_filter("console", NULL, LOGL_MAX, "file)");
-		if (ret < 0)
-			return ret;
-		filt1 = ret;
-		ret = log_add_filter("console", NULL, LOGL_MAX, "file2");
-		if (ret < 0)
-			return ret;
-		filt2 = ret;
-		ret = log_add_filter("console", NULL, LOGL_MAX,
-				     "log/log_test.c");
-		if (ret < 0)
-			return ret;
-		filt3 = ret;
-		log_run(UCLASS_SPI, "file2");
-		ret = log_remove_filter("console", filt1);
-		if (ret < 0)
-			return ret;
-		ret = log_remove_filter("console", filt2);
-		if (ret < 0)
-			return ret;
-		ret = log_remove_filter("console", filt3);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	case 10: {
-		log_err("level %d\n", LOGL_EMERG);
-		log_err("level %d\n", LOGL_ALERT);
-		log_err("level %d\n", LOGL_CRIT);
-		log_err("level %d\n", LOGL_ERR);
-		log_warning("level %d\n", LOGL_WARNING);
-		log_notice("level %d\n", LOGL_NOTICE);
-		log_info("level %d\n", LOGL_INFO);
-		log_debug("level %d\n", LOGL_DEBUG);
-		log_content("level %d\n", LOGL_DEBUG_CONTENT);
-		log_io("level %d\n", LOGL_DEBUG_IO);
-		break;
-	}
-	case 11:
-		log_err("default\n");
-		ret = log_device_set_enable(LOG_GET_DRIVER(console), false);
-		log_err("disabled\n");
-		ret = log_device_set_enable(LOG_GET_DRIVER(console), true);
-		log_err("enabled\n");
-		break;
-	}
+#define check_log_entries_flags(flags) \
+	check_log_entries_flags_levels(flags, LOGL_FIRST, _LOG_MAX_LEVEL)
+#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT)
+#define check_log_entries_extra() \
+	check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA)
+#define check_log_entries_none() check_log_entries_flags(0)
+
+/* Check a category filter using the first category */
+int log_test_cat_allow(struct unit_test_state *uts)
+{
+	enum log_category_t cat_list[] = {
+		log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI),
+		LOGC_NONE, LOGC_END
+	};
+	int filt;
+
+	filt = log_add_filter("console", cat_list, LOGL_MAX, NULL);
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_cat(UCLASS_MMC);
+	check_log_entries_extra();
+
+	ut_assertok(console_record_reset_enable());
+	log_run_cat(UCLASS_SPI);
+	check_log_entries_extra();
+
+	ut_assertok(log_remove_filter("console", filt));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_cat_allow, UT_TESTF_CONSOLE_REC);
+
+/* Check a category filter that should block log entries */
+int log_test_cat_deny_implicit(struct unit_test_state *uts)
+{
+	enum log_category_t cat_list[] = {
+		log_uc_cat(UCLASS_MMC),  LOGC_NONE, LOGC_END
+	};
+	int filt;
+
+	filt = log_add_filter("console", cat_list, LOGL_MAX, NULL);
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_cat(UCLASS_SPI);
+	check_log_entries_none();
 
+	ut_assertok(log_remove_filter("console", filt));
 	return 0;
 }
+LOG_TEST_FLAGS(log_test_cat_deny_implicit, UT_TESTF_CONSOLE_REC);
 
-int do_log_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+/* Check passing and failing file filters */
+int log_test_file(struct unit_test_state *uts)
 {
-	int testnum = 0;
+	int filt;
+
+	filt = log_add_filter("console", NULL, LOGL_MAX, "file");
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file");
+	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file2");
+	check_log_entries_none();
+
+	ut_assertok(log_remove_filter("console", filt));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_file, UT_TESTF_CONSOLE_REC);
+
+/* Check a passing file filter (second in list) */
+int log_test_file_second(struct unit_test_state *uts)
+{
+	int filt;
+
+	filt = log_add_filter("console", NULL, LOGL_MAX, "file,file2");
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file2");
+	check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
+
+	ut_assertok(log_remove_filter("console", filt));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_file_second, UT_TESTF_CONSOLE_REC);
+
+/* Check a passing file filter (middle of list) */
+int log_test_file_mid(struct unit_test_state *uts)
+{
+	int filt;
+
+	filt = log_add_filter("console", NULL, LOGL_MAX,
+			      "file,file2,log/log_test.c");
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file2");
+	check_log_entries_extra();
+
+	ut_assertok(log_remove_filter("console", filt));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_file_mid, UT_TESTF_CONSOLE_REC);
+
+/* Check a log level filter */
+int log_test_level(struct unit_test_state *uts)
+{
+	int filt;
+
+	filt = log_add_filter("console", NULL, LOGL_WARNING, NULL);
+	ut_assert(filt >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run();
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, LOGL_FIRST,
+				       LOGL_WARNING);
+
+	ut_assertok(log_remove_filter("console", filt));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_level, UT_TESTF_CONSOLE_REC);
+
+/* Check two filters, one of which passes everything */
+int log_test_double(struct unit_test_state *uts)
+{
+	int filt1, filt2;
+
+	filt1 = log_add_filter("console", NULL, LOGL_WARNING, NULL);
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter("console", NULL, LOGL_MAX, NULL);
+	ut_assert(filt2 >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run();
+	check_log_entries_extra();
+
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_double, UT_TESTF_CONSOLE_REC);
+
+/* Check three filters, which together pass everything */
+int log_test_triple(struct unit_test_state *uts)
+{
+	int filt1, filt2, filt3;
+
+	filt1 = log_add_filter("console", NULL, LOGL_MAX, "file)");
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter("console", NULL, LOGL_MAX, "file2");
+	ut_assert(filt2 >= 0);
+	filt3 = log_add_filter("console", NULL, LOGL_MAX, "log/log_test.c");
+	ut_assert(filt3 >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file2");
+	check_log_entries_extra();
+
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	ut_assertok(log_remove_filter("console", filt3));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_triple, UT_TESTF_CONSOLE_REC);
+
+int do_log_test_helpers(struct unit_test_state *uts)
+{
+	int i;
+
+	ut_assertok(console_record_reset_enable());
+	log_err("level %d\n", LOGL_EMERG);
+	log_err("level %d\n", LOGL_ALERT);
+	log_err("level %d\n", LOGL_CRIT);
+	log_err("level %d\n", LOGL_ERR);
+	log_warning("level %d\n", LOGL_WARNING);
+	log_notice("level %d\n", LOGL_NOTICE);
+	log_info("level %d\n", LOGL_INFO);
+	log_debug("level %d\n", LOGL_DEBUG);
+	log_content("level %d\n", LOGL_DEBUG_CONTENT);
+	log_io("level %d\n", LOGL_DEBUG_IO);
+
+	for (i = LOGL_EMERG; i <= _LOG_MAX_LEVEL; i++)
+		ut_assert_nextline("%s() level %d", __func__, i);
+	ut_assert_console_end();
+	return 0;
+}
+
+int log_test_helpers(struct unit_test_state *uts)
+{
+	int ret;
+
+	gd->log_fmt = LOGF_TEST;
+	ret = do_log_test_helpers(uts);
+	gd->log_fmt = log_get_default_format();
+	return ret;
+}
+LOG_TEST_FLAGS(log_test_helpers, UT_TESTF_CONSOLE_REC);
+
+int do_log_test_disable(struct unit_test_state *uts)
+{
+	ut_assertok(console_record_reset_enable());
+	log_err("default\n");
+	ut_assert_nextline("%s() default", __func__);
+
+	ut_assertok(log_device_set_enable(LOG_GET_DRIVER(console), false));
+	log_err("disabled\n");
+
+	ut_assertok(log_device_set_enable(LOG_GET_DRIVER(console), true));
+	log_err("enabled\n");
+	ut_assert_nextline("%s() enabled", __func__);
+	ut_assert_console_end();
+	return 0;
+}
+
+int log_test_disable(struct unit_test_state *uts)
+{
 	int ret;
 
+	gd->log_fmt = LOGF_TEST;
+	ret = do_log_test_disable(uts);
+	gd->log_fmt = log_get_default_format();
+	return ret;
+}
+LOG_TEST_FLAGS(log_test_disable, UT_TESTF_CONSOLE_REC);
+
+/* Check denying based on category */
+int log_test_cat_deny(struct unit_test_state *uts)
+{
+	int filt1, filt2;
+	enum log_category_t cat_list[] = {
+		log_uc_cat(UCLASS_SPI), LOGC_END
+	};
+
-	if (argc > 1)
-		testnum = simple_strtoul(argv[1], NULL, 10);
+	filt1 = log_add_filter("console", cat_list, LOGL_MAX, NULL);
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter_flags("console", cat_list, LOGL_MAX, NULL,
+				     LOGFF_DENY);
+	ut_assert(filt2 >= 0);
 
-	ret = log_test(testnum);
-	if (ret)
-		printf("Test failure (err=%d)\n", ret);
+	ut_assertok(console_record_reset_enable());
+	log_run_cat(UCLASS_SPI);
+	check_log_entries_none();
 
-	return ret ? CMD_RET_FAILURE : 0;
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_cat_deny, UT_TESTF_CONSOLE_REC);
+
+/* Check denying based on file */
+int log_test_file_deny(struct unit_test_state *uts)
+{
+	int filt1, filt2;
+
+	filt1 = log_add_filter("console", NULL, LOGL_MAX, "file");
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter_flags("console", NULL, LOGL_MAX, "file",
+				     LOGFF_DENY);
+	ut_assert(filt2 >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run_file("file");
+	check_log_entries_none();
+
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_file_deny, UT_TESTF_CONSOLE_REC);
+
+/* Check denying based on level */
+int log_test_level_deny(struct unit_test_state *uts)
+{
+	int filt1, filt2;
+
+	filt1 = log_add_filter("console", NULL, LOGL_INFO, NULL);
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL,
+				     LOGFF_DENY);
+	ut_assert(filt2 >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run();
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
+				       LOGL_WARNING + 1, _LOG_MAX_LEVEL);
+
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	return 0;
+}
+LOG_TEST_FLAGS(log_test_level_deny, UT_TESTF_CONSOLE_REC);
+
+/* Check matching based on minimum level */
+int log_test_min(struct unit_test_state *uts)
+{
+	int filt1, filt2;
+
+	filt1 = log_add_filter_flags("console", NULL, LOGL_WARNING, NULL,
+				     LOGFF_LEVEL_MIN);
+	ut_assert(filt1 >= 0);
+	filt2 = log_add_filter_flags("console", NULL, LOGL_INFO, NULL,
+				     LOGFF_DENY | LOGFF_LEVEL_MIN);
+	ut_assert(filt2 >= 0);
+
+	ut_assertok(console_record_reset_enable());
+	log_run();
+	check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
+				       LOGL_WARNING, LOGL_INFO - 1);
+
+	ut_assertok(log_remove_filter("console", filt1));
+	ut_assertok(log_remove_filter("console", filt2));
+	return 0;
 }
+LOG_TEST_FLAGS(log_test_min, UT_TESTF_CONSOLE_REC);
diff --git a/test/log/syslog_test.h b/test/log/syslog_test.h
index 1310257..bfaa6da 100644
--- a/test/log/syslog_test.h
+++ b/test/log/syslog_test.h
@@ -8,8 +8,6 @@
 #ifndef __SYSLOG_TEST_H
 #define __SYSLOG_TEST_H
 
-#define LOGF_TEST (BIT(LOGF_FUNC) | BIT(LOGF_MSG))
-
 /**
  * struct sb_log_env - private data for sandbox ethernet driver
  *
diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py
index 275f938..387b392 100644
--- a/test/py/tests/test_log.py
+++ b/test/py/tests/test_log.py
@@ -10,110 +10,6 @@
 
 import pytest
 
-LOGL_FIRST, LOGL_WARNING, LOGL_INFO = (0, 4, 6)
-
-@pytest.mark.buildconfigspec('cmd_log')
-def test_log(u_boot_console):
-    """Test that U-Boot logging works correctly."""
-    def check_log_entries(lines, mask, max_level=LOGL_INFO):
-        """Check that the expected log records appear in the output
-
-        Args:
-            lines: iterator containing lines to check
-            mask: bit mask to select which lines to check for:
-                bit 0: standard log line
-                bit 1: _log line
-            max_level: maximum log level to expect in the output
-        """
-        for i in range(max_level):
-            if mask & 1:
-                assert 'log_run() log %d' % i == next(lines)
-            if mask & 3:
-                assert 'func() _log %d' % i == next(lines)
-
-    def run_test(testnum):
-        """Run a particular test number (the 'log test' command)
-
-        Args:
-            testnum: Test number to run
-        Returns:
-            iterator containing the lines output from the command
-        """
-        output = u_boot_console.run_command('log format fm')
-        assert output == ''
-        with cons.log.section('basic'):
-           output = u_boot_console.run_command('log test %d' % testnum)
-        split = output.replace('\r', '').splitlines()
-        lines = iter(split)
-        assert 'test %d' % testnum == next(lines)
-        return lines
-
-    def test0():
-        lines = run_test(0)
-        check_log_entries(lines, 3)
-
-    def test1():
-        lines = run_test(1)
-        check_log_entries(lines, 3)
-
-    def test2():
-        lines = run_test(2)
-
-    def test3():
-        lines = run_test(3)
-        check_log_entries(lines, 2)
-
-    def test4():
-        lines = run_test(4)
-        assert next(lines, None) == None
-
-    def test5():
-        lines = run_test(5)
-        check_log_entries(lines, 2)
-
-    def test6():
-        lines = run_test(6)
-        check_log_entries(lines, 3)
-
-    def test7():
-        lines = run_test(7)
-        check_log_entries(lines, 3, LOGL_WARNING)
-
-    def test8():
-        lines = run_test(8)
-        check_log_entries(lines, 3)
-
-    def test9():
-        lines = run_test(9)
-        check_log_entries(lines, 3)
-
-    def test10():
-        lines = run_test(10)
-        for i in range(7):
-            assert 'log_test() level %d' % i == next(lines)
-
-    def test11():
-        """Test use of log_device_set_enable()"""
-        lines = run_test(11)
-        assert 'log_test() default'
-        # disabled should not be displayed
-        assert 'log_test() enabled'
-
-    # TODO(sjg@chromium.org): Consider structuring this as separate tests
-    cons = u_boot_console
-    test0()
-    test1()
-    test2()
-    test3()
-    test4()
-    test5()
-    test6()
-    test7()
-    test8()
-    test9()
-    test10()
-    test11()
-
 @pytest.mark.buildconfigspec('cmd_log')
 def test_log_format(u_boot_console):
     """Test the 'log format' and 'log rec' commands"""