Merge https://gitlab.denx.de/u-boot/custodians/u-boot-sh
diff --git a/MAINTAINERS b/MAINTAINERS
index 776ff70..4cf0c33 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -546,6 +546,7 @@
 T:	git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/mach-versal/
 F:	drivers/net/xilinx_axi_mrmac.*
+F:	drivers/soc/soc_xilinx_versal.c
 F:	drivers/watchdog/xilinx_wwdt.c
 N:	(?<!uni)versal
 
@@ -600,6 +601,9 @@
 F:	drivers/net/phy/xilinx_phy.c
 F:	drivers/net/zynq_gem.c
 F:	drivers/serial/serial_zynq.c
+F:	drivers/reset/reset-zynqmp.c
+F:	drivers/rtc/zynqmp_rtc.c
+F:	drivers/soc/soc_xilinx_zynqmp.c
 F:	drivers/spi/zynq_qspi.c
 F:	drivers/spi/zynq_spi.c
 F:	drivers/timer/cadence-ttc.c
diff --git a/Makefile b/Makefile
index 3c8437d..39fd103 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 VERSION = 2021
 PATCHLEVEL = 10
 SUBLEVEL =
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME =
 
 # *DOCUMENTATION*
@@ -1169,6 +1169,8 @@
 	-a 0 -e 0 -E \
 	$(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) -d /dev/null
 
+MKIMAGEFLAGS_fit-dtb.blob += -B 0x8
+
 ifneq ($(EXT_DTB),)
 u-boot-fit-dtb.bin: u-boot-nodtb.bin $(EXT_DTB)
 		$(call if_changed,cat)
@@ -1431,6 +1433,7 @@
 else
 MKIMAGEFLAGS_u-boot.itb = -E
 endif
+MKIMAGEFLAGS_u-boot.itb += -B 0x8
 
 ifdef U_BOOT_ITS
 u-boot.itb: u-boot-nodtb.bin \
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d692139..2d59562 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1064,6 +1064,7 @@
 	select DM_SERIAL
 	select GPIO_EXTRA_HEADER
 	select OF_CONTROL
+	select SOC_DEVICE
 	imply BOARD_LATE_INIT
 	imply ENV_VARS_UBOOT_RUNTIME_CONFIG
 
@@ -1142,6 +1143,7 @@
 	select SPL_SEPARATE_BSS if SPL
 	select SUPPORT_SPL
 	select ZYNQMP_IPI
+	select SOC_DEVICE
 	imply BOARD_LATE_INIT
 	imply CMD_DM
 	imply ENV_VARS_UBOOT_RUNTIME_CONFIG
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index c42715e..fc16a57 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -400,6 +400,7 @@
 	socfpga_cyclone5_socrates.dtb			\
 	socfpga_cyclone5_sr1500.dtb			\
 	socfpga_cyclone5_vining_fpga.dtb		\
+	socfpga_n5x_socdk.dtb				\
 	socfpga_stratix10_socdk.dtb
 
 dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb	\
@@ -1132,7 +1133,7 @@
 targets += $(dtb-y)
 
 # Add any required device tree compiler flags here
-DTC_FLAGS +=
+DTC_FLAGS += -a 0x8
 
 PHONY += dtbs
 dtbs: $(addprefix $(obj)/, $(dtb-y))
diff --git a/arch/arm/dts/socfpga_n5x-u-boot.dtsi b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
new file mode 100644
index 0000000..d377ae5
--- /dev/null
+++ b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include "socfpga_soc64_fit-u-boot.dtsi"
+#include <dt-bindings/clock/n5x-clock.h>
+
+/{
+	memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+	};
+
+	soc {
+		u-boot,dm-pre-reloc;
+
+		ccu: cache-controller@f7000000 {
+			compatible = "arteris,ncore-ccu";
+			reg = <0xf7000000 0x100900>;
+			u-boot,dm-pre-reloc;
+		};
+
+		clocks {
+			dram_eosc_clk: dram-eosc-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+			};
+		};
+
+		memclkmgr: mem-clock-controller@f8040000 {
+			compatible = "intel,n5x-mem-clkmgr";
+			reg = <0xf8040000 0x1000>;
+			#clock-cells = <0>;
+			clocks = <&dram_eosc_clk>, <&f2s_free_clk>;
+		};
+	};
+};
+
+&clkmgr {
+	compatible = "intel,n5x-clkmgr";
+	u-boot,dm-pre-reloc;
+};
+
+&gmac0 {
+	clocks = <&clkmgr N5X_EMAC0_CLK>;
+};
+
+&gmac1 {
+	altr,sysmgr-syscon = <&sysmgr 0x48 0>;
+	clocks = <&clkmgr N5X_EMAC1_CLK>;
+};
+
+&gmac2 {
+	altr,sysmgr-syscon = <&sysmgr 0x4c 0>;
+	clocks = <&clkmgr N5X_EMAC2_CLK>;
+};
+
+&i2c0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c2 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c3 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c4 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&memclkmgr {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc {
+	clocks = <&clkmgr N5X_L4_MP_CLK>,
+		 <&clkmgr N5X_SDMMC_CLK>;
+	resets = <&rst SDMMC_RESET>, <&rst SDMMC_OCP_RESET>;
+};
+
+&pdma {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&porta {
+	bank-name = "porta";
+};
+
+&portb {
+	bank-name = "portb";
+};
+
+&qspi {
+	u-boot,dm-pre-reloc;
+};
+
+&rst {
+	compatible = "altr,rst-mgr";
+	altr,modrst-offset = <0x20>;
+	u-boot,dm-pre-reloc;
+};
+
+&sdr {
+	compatible = "intel,sdr-ctl-n5x";
+	resets = <&rst DDRSCH_RESET>;
+	clocks = <&memclkmgr>;
+	clock-names = "mem_clk";
+	u-boot,dm-pre-reloc;
+};
+
+&spi0 {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&spi1 {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&sysmgr {
+	compatible = "altr,sys-mgr", "syscon";
+	u-boot,dm-pre-reloc;
+};
+
+&timer0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer2 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer3 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&uart0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&uart1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&usb0 {
+	clocks = <&clkmgr N5X_USB_CLK>;
+	disable-over-current;
+	u-boot,dm-pre-reloc;
+};
+
+&usb1 {
+	clocks = <&clkmgr N5X_USB_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&watchdog0 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&watchdog1 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
+
+&watchdog2 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
+
+&watchdog3 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
diff --git a/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
new file mode 100644
index 0000000..502da36
--- /dev/null
+++ b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include "socfpga_n5x-u-boot.dtsi"
+
+/{
+	aliases {
+		spi0 = &qspi;
+		i2c0 = &i2c1;
+	};
+
+	memory {
+		/*
+		 * Memory type: DDR4 (non-interleaving mode)
+		 * 16GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <4 0x80000000 3 0x80000000>;
+		 *
+		 * 8GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <2 0x80000000 1 0x80000000>;
+		 *
+		 * 4GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <1 0x80000000 0 0x80000000>;
+		 *
+		 * Memory type: LPDDR4 (non-interleaving mode)
+		 * Total memory size 3GB, usable = 2.5GB, 0.5GB trade off for secure
+		 * region.
+		 */
+		reg = <0 0x00000000 0 0x60000000>,
+			  <0x10 0x00100000 0 0x40000000>;
+	};
+};
+
+&flash0 {
+	compatible = "jedec,spi-nor";
+	spi-tx-bus-width = <4>;
+	spi-rx-bus-width = <4>;
+	u-boot,dm-pre-reloc;
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&mmc {
+	drvsel = <3>;
+	smplsel = <0>;
+	u-boot,dm-pre-reloc;
+};
+
+&qspi {
+	status = "okay";
+};
+
+&watchdog0 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/socfpga_n5x_socdk.dts b/arch/arm/dts/socfpga_n5x_socdk.dts
new file mode 100644
index 0000000..915b8f6
--- /dev/null
+++ b/arch/arm/dts/socfpga_n5x_socdk.dts
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier:     GPL-2.0
+/*
+ * Copyright (C) 2020-2021, Intel Corporation
+ */
+#include "socfpga_agilex.dtsi"
+
+/ {
+	model = "eASIC N5X SoCDK";
+
+	aliases {
+		serial0 = &uart0;
+		ethernet0 = &gmac0;
+		ethernet1 = &gmac1;
+		ethernet2 = &gmac2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		/* We expect the bootloader to fill in the reg */
+		reg = <0 0 0 0>;
+	};
+
+	soc {
+		clocks {
+			osc1 {
+				clock-frequency = <25000000>;
+			};
+		};
+	};
+};
+
+&gmac0 {
+	status = "okay";
+	phy-mode = "rgmii";
+	phy-handle = <&phy0>;
+	max-frame-size = <9000>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy0: ethernet-phy@0 {
+			reg = <4>;
+
+			txd0-skew-ps = <0>; /* -420ps */
+			txd1-skew-ps = <0>; /* -420ps */
+			txd2-skew-ps = <0>; /* -420ps */
+			txd3-skew-ps = <0>; /* -420ps */
+			rxd0-skew-ps = <420>; /* 0ps */
+			rxd1-skew-ps = <420>; /* 0ps */
+			rxd2-skew-ps = <420>; /* 0ps */
+			rxd3-skew-ps = <420>; /* 0ps */
+			txen-skew-ps = <0>; /* -420ps */
+			txc-skew-ps = <900>; /* 0ps */
+			rxdv-skew-ps = <420>; /* 0ps */
+			rxc-skew-ps = <1680>; /* 780ps */
+		};
+	};
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&mmc {
+	status = "okay";
+	cap-sd-highspeed;
+	broken-cd;
+	bus-width = <4>;
+};
+
+&qspi {
+	status = "okay";
+	flash0: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "mt25qu02g";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <3>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			qspi_boot: partition@0 {
+				label = "Boot and fpga data";
+				reg = <0x0 0x034B0000>;
+			};
+
+			qspi_rootfs: partition@34B0000 {
+				label = "Root Filesystem - JFFS2";
+				reg = <0x034B0000 0x0EB50000>;
+			};
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/zynq-cc108.dts b/arch/arm/dts/zynq-cc108.dts
index 64d73ec..036106e 100644
--- a/arch/arm/dts/zynq-cc108.dts
+++ b/arch/arm/dts/zynq-cc108.dts
@@ -58,7 +58,7 @@
 	is-dual = <0>;
 	num-cs = <1>;
 	flash@0 { /* 16 MB */
-		compatible = "n25q128a11";
+		compatible = "n25q128a11", "jedec,spi-nor";
 		reg = <0x0>;
 		spi-max-frequency = <50000000>;
 		spi-tx-bus-width = <1>;
diff --git a/arch/arm/dts/zynq-cse-qspi.dtsi b/arch/arm/dts/zynq-cse-qspi.dtsi
index eb0e29e..38410ee 100644
--- a/arch/arm/dts/zynq-cse-qspi.dtsi
+++ b/arch/arm/dts/zynq-cse-qspi.dtsi
@@ -60,7 +60,7 @@
 			#size-cells = <0>;
 			num-cs = <1>;
 			flash0: flash@0 {
-				compatible = "n25q128a11";
+				compatible = "n25q128a11", "jedec,spi-nor";
 				reg = <0x0>;
 				spi-tx-bus-width = <1>;
 				spi-rx-bus-width = <4>;
diff --git a/arch/arm/dts/zynq-topic-miami.dts b/arch/arm/dts/zynq-topic-miami.dts
index ab6bde9..c4ec561 100644
--- a/arch/arm/dts/zynq-topic-miami.dts
+++ b/arch/arm/dts/zynq-topic-miami.dts
@@ -36,7 +36,7 @@
 	is-dual = <0>;
 	num-cs = <1>;
 	flash@0 {
-		compatible = "st,m25p80", "n25q256a";
+		compatible = "st,m25p80", "n25q256a", "jedec,spi-nor";
 		m25p,fast-read;
 		reg = <0x0>;
 		spi-tx-bus-width = <1>;
diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts
index 4474f4b..f2e05a5 100644
--- a/arch/arm/dts/zynq-zc702.dts
+++ b/arch/arm/dts/zynq-zc702.dts
@@ -213,7 +213,7 @@
 		conf {
 			groups = "can0_9_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-rx {
@@ -236,7 +236,7 @@
 		conf {
 			groups = "ethernet0_0_grp";
 			slew-rate = <0>;
-			io-standard = <4>;
+			power-source = <4>;
 		};
 
 		conf-rx {
@@ -259,7 +259,7 @@
 		conf-mdio {
 			groups = "mdio0_0_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 			bias-disable;
 		};
 	};
@@ -277,7 +277,7 @@
 				 "gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp",
 				 "gpio0_13_grp", "gpio0_14_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-pull-up {
@@ -301,7 +301,7 @@
 			groups = "i2c0_10_grp";
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 	};
 
@@ -314,7 +314,7 @@
 		conf {
 			groups = "gpio0_50_grp", "gpio0_51_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 	};
 
@@ -327,7 +327,7 @@
 		conf {
 			groups = "sdio0_2_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 			bias-disable;
 		};
 
@@ -341,7 +341,7 @@
 			bias-high-impedance;
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		mux-wp {
@@ -354,7 +354,7 @@
 			bias-high-impedance;
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 	};
 
@@ -367,7 +367,7 @@
 		conf {
 			groups = "uart1_10_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-rx {
@@ -390,7 +390,7 @@
 		conf {
 			groups = "usb0_0_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-rx {
@@ -409,6 +409,14 @@
 &qspi {
 	u-boot,dm-pre-reloc;
 	status = "okay";
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11", "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+	};
 };
 
 &sdhci0 {
diff --git a/arch/arm/dts/zynq-zc706.dts b/arch/arm/dts/zynq-zc706.dts
index 84729e9..cb919e4 100644
--- a/arch/arm/dts/zynq-zc706.dts
+++ b/arch/arm/dts/zynq-zc706.dts
@@ -151,7 +151,7 @@
 		conf {
 			groups = "ethernet0_0_grp";
 			slew-rate = <0>;
-			io-standard = <4>;
+			power-source = <4>;
 		};
 
 		conf-rx {
@@ -174,7 +174,7 @@
 		conf-mdio {
 			groups = "mdio0_0_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 			bias-disable;
 		};
 	};
@@ -188,7 +188,7 @@
 		conf {
 			groups = "gpio0_7_grp", "gpio0_46_grp", "gpio0_47_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-pull-up {
@@ -212,7 +212,7 @@
 			groups = "i2c0_10_grp";
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 	};
 
@@ -225,7 +225,7 @@
 		conf {
 			groups = "sdio0_2_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 			bias-disable;
 		};
 
@@ -239,7 +239,7 @@
 			bias-high-impedance;
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		mux-wp {
@@ -252,7 +252,7 @@
 			bias-high-impedance;
 			bias-pull-up;
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 	};
 
@@ -265,7 +265,7 @@
 		conf {
 			groups = "uart1_10_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-rx {
@@ -288,7 +288,7 @@
 		conf {
 			groups = "usb0_0_grp";
 			slew-rate = <0>;
-			io-standard = <1>;
+			power-source = <1>;
 		};
 
 		conf-rx {
@@ -307,6 +307,14 @@
 &qspi {
 	u-boot,dm-pre-reloc;
 	status = "okay";
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11", "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+	};
 };
 
 &sdhci0 {
diff --git a/arch/arm/dts/zynq-zc770-xm010.dts b/arch/arm/dts/zynq-zc770-xm010.dts
index c547d79..002ff9f 100644
--- a/arch/arm/dts/zynq-zc770-xm010.dts
+++ b/arch/arm/dts/zynq-zc770-xm010.dts
@@ -62,6 +62,14 @@
 
 &qspi {
 	status = "okay";
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11", "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+	};
 };
 
 &sdhci0 {
diff --git a/arch/arm/dts/zynq-zc770-xm012.dts b/arch/arm/dts/zynq-zc770-xm012.dts
index 0d001c9..ccf76e7 100644
--- a/arch/arm/dts/zynq-zc770-xm012.dts
+++ b/arch/arm/dts/zynq-zc770-xm012.dts
@@ -53,6 +53,15 @@
 	};
 };
 
+&nor0 {
+	status = "okay";
+	bank-width = <1>;
+};
+
+&smcc {
+	status = "okay";
+};
+
 &spi1 {
 	status = "okay";
 	num-cs = <4>;
diff --git a/arch/arm/dts/zynq-zc770-xm013.dts b/arch/arm/dts/zynq-zc770-xm013.dts
index 7218ee3..455c8a9 100644
--- a/arch/arm/dts/zynq-zc770-xm013.dts
+++ b/arch/arm/dts/zynq-zc770-xm013.dts
@@ -61,6 +61,14 @@
 
 &qspi {
 	status = "okay";
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11", "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+	};
 };
 
 &spi0 {
diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revA.dts b/arch/arm/dts/zynqmp-sck-kv-g-revA.dts
index 4e8086c..22602d8 100644
--- a/arch/arm/dts/zynqmp-sck-kv-g-revA.dts
+++ b/arch/arm/dts/zynqmp-sck-kv-g-revA.dts
@@ -12,10 +12,10 @@
  * Michal Simek <michal.simek@xilinx.com>
  */
 
- #include <dt-bindings/gpio/gpio.h>
- #include <dt-bindings/net/ti-dp83867.h>
- #include <dt-bindings/phy/phy.h>
- #include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 /dts-v1/;
 /plugin/;
diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revB.dts b/arch/arm/dts/zynqmp-sck-kv-g-revB.dts
index 048d566..df054e1 100644
--- a/arch/arm/dts/zynqmp-sck-kv-g-revB.dts
+++ b/arch/arm/dts/zynqmp-sck-kv-g-revB.dts
@@ -7,10 +7,10 @@
  * Michal Simek <michal.simek@xilinx.com>
  */
 
- #include <dt-bindings/gpio/gpio.h>
- #include <dt-bindings/net/ti-dp83867.h>
- #include <dt-bindings/phy/phy.h>
- #include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 /dts-v1/;
 /plugin/;
diff --git a/arch/arm/dts/zynqmp-sm-k26-revA.dts b/arch/arm/dts/zynqmp-sm-k26-revA.dts
index b613ab2..5f55df2 100644
--- a/arch/arm/dts/zynqmp-sm-k26-revA.dts
+++ b/arch/arm/dts/zynqmp-sm-k26-revA.dts
@@ -60,13 +60,13 @@
 
 	leds {
 		compatible = "gpio-leds";
-		ds35 {
+		ds35-led {
 			label = "heartbeat";
 			gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 
-		ds36 {
+		ds36-led {
 			label = "vbus_det";
 			gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
 			default-state = "on";
@@ -183,7 +183,7 @@
 	};
 };
 
-&sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A*/
+&sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A */
 	status = "okay";
 	non-removable;
 	disable-wp;
@@ -204,17 +204,20 @@
 
 &i2c1 {
 	status = "okay";
+	u-boot,dm-pre-reloc;
 	clock-frequency = <400000>;
 	scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
 	sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
 
 	eeprom: eeprom@50 { /* u46 - also at address 0x58 */
+		u-boot,dm-pre-reloc;
 		compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */
 		reg = <0x50>;
 		/* WP pin EE_WP_EN connected to slg7x644092@68 */
 	};
 
 	eeprom_cc: eeprom@51 { /* required by spec - also at address 0x59 */
+		u-boot,dm-pre-reloc;
 		compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */
 		reg = <0x51>;
 	};
diff --git a/arch/arm/dts/zynqmp-topic-miamimp-xilinx-xdp-v1r1.dts b/arch/arm/dts/zynqmp-topic-miamimp-xilinx-xdp-v1r1.dts
index 6ec96e0..300e2eb 100644
--- a/arch/arm/dts/zynqmp-topic-miamimp-xilinx-xdp-v1r1.dts
+++ b/arch/arm/dts/zynqmp-topic-miamimp-xilinx-xdp-v1r1.dts
@@ -58,7 +58,7 @@
 	status = "okay";
 	is-dual = <1>;
 	flash@0 {
-		compatible = "st,m25p80", "n25q256a";
+		compatible = "st,m25p80", "n25q256a", "jedec,spi-nor";
 		m25p,fast-read;
 		reg = <0x0>;
 		spi-tx-bus-width = <1>;
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 0c35406..f4791c1 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -8,7 +8,7 @@
 
 config SOCFPGA_SECURE_VAB_AUTH
 	bool "Enable boot image authentication with Secure Device Manager"
-	depends on TARGET_SOCFPGA_AGILEX
+	depends on TARGET_SOCFPGA_AGILEX || TARGET_SOCFPGA_N5X
 	select FIT_IMAGE_POST_PROCESS
 	select SHA384
 	select SHA512_ALGO
@@ -91,6 +91,22 @@
 	imply SPL_SYS_MALLOC_SIMPLE
 	imply SPL_USE_TINY_PRINTF
 
+config TARGET_SOCFPGA_N5X
+	bool
+	select ARMV8_MULTIENTRY
+	select ARMV8_SET_SMPEN
+	select BINMAN if SPL_ATF
+	select CLK
+	select FPGA_INTEL_SDM_MAILBOX
+	select NCORE_CACHE
+	select SPL_ALTERA_SDRAM
+	select SPL_CLK if SPL
+	select TARGET_SOCFPGA_SOC64
+
+config TARGET_SOCFPGA_N5X_SOCDK
+	bool "Intel eASIC SoCDK (N5X)"
+	select TARGET_SOCFPGA_N5X
+
 config TARGET_SOCFPGA_SOC64
 	bool
 
@@ -185,6 +201,7 @@
 	default "de10-nano" if TARGET_SOCFPGA_TERASIC_DE10_NANO
 	default "is1" if TARGET_SOCFPGA_IS1
 	default "mcvevk" if TARGET_SOCFPGA_ARIES_MCVEVK
+	default "n5x-socdk" if TARGET_SOCFPGA_N5X_SOCDK
 	default "secu1" if TARGET_SOCFPGA_ARRIA5_SECU1
 	default "sockit" if TARGET_SOCFPGA_TERASIC_SOCKIT
 	default "socrates" if TARGET_SOCFPGA_EBV_SOCRATES
@@ -194,6 +211,7 @@
 
 config SYS_VENDOR
 	default "intel" if TARGET_SOCFPGA_AGILEX_SOCDK
+	default "intel" if TARGET_SOCFPGA_N5X_SOCDK
 	default "altera" if TARGET_SOCFPGA_ARRIA5_SOCDK
 	default "altera" if TARGET_SOCFPGA_ARRIA10_SOCDK
 	default "altera" if TARGET_SOCFPGA_CYCLONE5_SOCDK
@@ -223,6 +241,7 @@
 	default "socfpga_de10_nano" if TARGET_SOCFPGA_TERASIC_DE10_NANO
 	default "socfpga_is1" if TARGET_SOCFPGA_IS1
 	default "socfpga_mcvevk" if TARGET_SOCFPGA_ARIES_MCVEVK
+	default "socfpga_n5x_socdk" if TARGET_SOCFPGA_N5X_SOCDK
 	default "socfpga_sockit" if TARGET_SOCFPGA_TERASIC_SOCKIT
 	default "socfpga_socrates" if TARGET_SOCFPGA_EBV_SOCRATES
 	default "socfpga_sr1500" if TARGET_SOCFPGA_SR1500
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 5779c55..ec38b64 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -4,7 +4,7 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
-# Copyright (C) 2017-2020 Intel Corporation <www.intel.com>
+# Copyright (C) 2017-2021 Intel Corporation <www.intel.com>
 
 obj-y	+= board.o
 obj-y	+= clock_manager.o
@@ -32,7 +32,7 @@
 obj-y	+= clock_manager_s10.o
 obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
-obj-y	+= misc_s10.o
+obj-y	+= misc_soc64.o
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
 obj-y	+= system_manager_soc64.o
@@ -45,7 +45,7 @@
 obj-y	+= clock_manager_agilex.o
 obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
-obj-y	+= misc_s10.o
+obj-y	+= misc_soc64.o
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
 obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= secure_vab.o
@@ -56,6 +56,21 @@
 obj-y	+= wrap_pll_config_soc64.o
 endif
 
+ifdef CONFIG_TARGET_SOCFPGA_N5X
+obj-y	+= clock_manager_n5x.o
+obj-y	+= lowlevel_init_soc64.o
+obj-y	+= mailbox_s10.o
+obj-y	+= misc_soc64.o
+obj-y	+= mmu-arm64_s10.o
+obj-y	+= reset_manager_s10.o
+obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= secure_vab.o
+obj-y	+= system_manager_soc64.o
+obj-y	+= timer_s10.o
+obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= vab.o
+obj-y	+= wrap_handoff_soc64.o
+obj-y	+= wrap_pll_config_soc64.o
+endif
+
 ifdef CONFIG_SPL_BUILD
 ifdef CONFIG_TARGET_SOCFPGA_GEN5
 obj-y	+= spl_gen5.o
@@ -64,18 +79,21 @@
 obj-y	+= wrap_pinmux_config.o
 obj-y	+= wrap_sdram_config.o
 endif
+ifdef CONFIG_TARGET_SOCFPGA_SOC64
+obj-y	+= firewall.o
+obj-y	+= spl_soc64.o
+endif
 ifdef CONFIG_TARGET_SOCFPGA_ARRIA10
 obj-y	+= spl_a10.o
 endif
 ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
-obj-y	+= firewall.o
 obj-y	+= spl_s10.o
-obj-y	+= spl_soc64.o
 endif
 ifdef CONFIG_TARGET_SOCFPGA_AGILEX
-obj-y	+= firewall.o
 obj-y	+= spl_agilex.o
-obj-y	+= spl_soc64.o
+endif
+ifdef CONFIG_TARGET_SOCFPGA_N5X
+obj-y	+= spl_n5x.o
 endif
 else
 obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o
diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c
index 36eecdc..7267163 100644
--- a/arch/arm/mach-socfpga/board.c
+++ b/arch/arm/mach-socfpga/board.c
@@ -116,17 +116,18 @@
 #if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_FIT)
 void board_prep_linux(bootm_headers_t *images)
 {
-	if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) &&
-	    !IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) {
-		/*
-		 * Ensure the OS is always booted from FIT and with
-		 * VAB signed certificate
-		 */
-		if (!images->fit_uname_cfg) {
+	if (!images->fit_uname_cfg) {
+		if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) &&
+		    !IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) {
+			/*
+			 * Ensure the OS is always booted from FIT and with
+			 * VAB signed certificate
+			 */
 			printf("Please use FIT with VAB signed images!\n");
 			hang();
 		}
-
+	} else {
+		/* Update fdt_addr in enviroment variable */
 		env_set_hex("fdt_addr", (ulong)images->ft_addr);
 		debug("images->ft_addr = 0x%08lx\n", (ulong)images->ft_addr);
 	}
diff --git a/arch/arm/mach-socfpga/clock_manager_n5x.c b/arch/arm/mach-socfpga/clock_manager_n5x.c
new file mode 100644
index 0000000..4f09853
--- /dev/null
+++ b/arch/arm/mach-socfpga/clock_manager_n5x.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-bindings/clock/n5x-clock.h>
+#include <malloc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static ulong cm_get_rate_dm(u32 id)
+{
+	struct udevice *dev;
+	struct clk clk;
+	ulong rate;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK,
+					  DM_DRIVER_GET(socfpga_n5x_clk),
+					  &dev);
+	if (ret)
+		return 0;
+
+	clk.id = id;
+	ret = clk_request(dev, &clk);
+	if (ret < 0)
+		return 0;
+
+	rate = clk_get_rate(&clk);
+
+	clk_free(&clk);
+
+	if ((rate == (unsigned long)-ENXIO) ||
+	    (rate == (unsigned long)-EIO)) {
+		debug("%s id %u: clk_get_rate err: %ld\n",
+		      __func__, id, rate);
+		return 0;
+	}
+
+	return rate;
+}
+
+static u32 cm_get_rate_dm_khz(u32 id)
+{
+	return cm_get_rate_dm(id) / 1000;
+}
+
+unsigned long cm_get_mpu_clk_hz(void)
+{
+	return cm_get_rate_dm(N5X_MPU_CLK);
+}
+
+unsigned int cm_get_l4_sys_free_clk_hz(void)
+{
+	return cm_get_rate_dm(N5X_L4_SYS_FREE_CLK);
+}
+
+void cm_print_clock_quick_summary(void)
+{
+	printf("MPU       %10d kHz\n",
+	       cm_get_rate_dm_khz(N5X_MPU_CLK));
+	printf("L4 Main	    %8d kHz\n",
+	       cm_get_rate_dm_khz(N5X_L4_MAIN_CLK));
+	printf("L4 sys free %8d kHz\n",
+	       cm_get_rate_dm_khz(N5X_L4_SYS_FREE_CLK));
+	printf("L4 MP       %8d kHz\n",
+	       cm_get_rate_dm_khz(N5X_L4_MP_CLK));
+	printf("L4 SP       %8d kHz\n",
+	       cm_get_rate_dm_khz(N5X_L4_SP_CLK));
+	printf("SDMMC       %8d kHz\n",
+	       cm_get_rate_dm_khz(N5X_SDMMC_CLK));
+}
diff --git a/arch/arm/mach-socfpga/include/mach/base_addr_s10.h b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
similarity index 84%
rename from arch/arm/mach-socfpga/include/mach/base_addr_s10.h
rename to arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
index d3eca65..3f899fc 100644
--- a/arch/arm/mach-socfpga/include/mach/base_addr_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
@@ -1,16 +1,17 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  */
 
-#ifndef _SOCFPGA_S10_BASE_HARDWARE_H_
-#define _SOCFPGA_S10_BASE_HARDWARE_H_
+#ifndef _SOCFPGA_SOC64_BASE_HARDWARE_H_
+#define _SOCFPGA_SOC64_BASE_HARDWARE_H_
 
 #define SOCFPGA_CCU_ADDRESS			0xf7000000
 #define SOCFPGA_SDR_SCHEDULER_ADDRESS		0xf8000400
 #define SOCFPGA_HMC_MMR_IO48_ADDRESS		0xf8010000
 #define SOCFPGA_SDR_ADDRESS			0xf8011000
-#ifdef CONFIG_TARGET_SOCFPGA_AGILEX
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) || \
+	IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS		0xf8020200
 #else
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS		0xf8020100
@@ -44,4 +45,4 @@
 #define GICD_BASE				0xfffc1000
 #define GICC_BASE				0xfffc2000
 
-#endif /* _SOCFPGA_S10_BASE_HARDWARE_H_ */
+#endif /* _SOCFPGA_SOC64_BASE_HARDWARE_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
index 2f9b471..a8cb07a 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
@@ -12,6 +12,7 @@
 void cm_wait_for_lock(u32 mask);
 int cm_wait_for_fsm(void);
 void cm_print_clock_quick_summary(void);
+unsigned long cm_get_mpu_clk_hz(void);
 unsigned int cm_get_qspi_controller_clk_hz(void);
 
 #if defined(CONFIG_TARGET_SOCFPGA_SOC64)
@@ -27,6 +28,8 @@
 #include <asm/arch/clock_manager_s10.h>
 #elif defined(CONFIG_TARGET_SOCFPGA_AGILEX)
 #include <asm/arch/clock_manager_agilex.h>
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#include <asm/arch/clock_manager_n5x.h>
 #endif
 
 #endif /* _CLOCK_MANAGER_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
index 386e82a..4feae3d 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
@@ -6,8 +6,6 @@
 #ifndef _CLOCK_MANAGER_AGILEX_
 #define _CLOCK_MANAGER_AGILEX_
 
-unsigned long cm_get_mpu_clk_hz(void);
-
 #include <asm/arch/clock_manager_soc64.h>
 #include "../../../../../drivers/clk/altera/clk-agilex.h"
 
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
index 798d374..553ebe6 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
@@ -68,7 +68,6 @@
 
 #include <linux/bitops.h>
 unsigned int cm_get_l4_sp_clk_hz(void);
-unsigned long cm_get_mpu_clk_hz(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
index 4cc1268..d53095a 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
@@ -96,7 +96,6 @@
 #define CLKMGR_PERPLL_EN			CLKMGR_GEN5_PERPLL_EN
 
 /* Clock speed accessors */
-unsigned long cm_get_mpu_clk_hz(void);
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h b/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h
new file mode 100644
index 0000000..54615ae
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _CLOCK_MANAGER_N5X_
+#define _CLOCK_MANAGER_N5X_
+
+#include <asm/arch/clock_manager_soc64.h>
+#include "../../../../../drivers/clk/altera/clk-n5x.h"
+
+#endif /* _CLOCK_MANAGER_N5X_ */
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
index 98c3bf1..7f10296 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
@@ -11,7 +11,6 @@
 #include <linux/bitops.h>
 
 /* Clock speed accessors */
-unsigned long cm_get_mpu_clk_hz(void);
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
diff --git a/arch/arm/mach-socfpga/include/mach/firewall.h b/arch/arm/mach-socfpga/include/mach/firewall.h
index adab65b..5cb7f23 100644
--- a/arch/arm/mach-socfpga/include/mach/firewall.h
+++ b/arch/arm/mach-socfpga/include/mach/firewall.h
@@ -115,10 +115,16 @@
 /* Firewall MPU DDR SCR registers */
 #define FW_MPU_DDR_SCR_EN				0x00
 #define FW_MPU_DDR_SCR_EN_SET				0x04
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE		0x10
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT		0x14
 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT		0x18
 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT		0x1c
+
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE		0x90
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT	0x94
 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT		0x98
 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT	0x9c
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT_FIELD	0xff
 
 #define MPUREGION0_ENABLE				BIT(0)
 #define NONMPUREGION0_ENABLE				BIT(8)
diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
index 3750216..902fc6b 100644
--- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0
  *
- * Copyright (C) 2016-2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -23,8 +23,36 @@
 #define SOC64_HANDOFF_OFFSET_DATA	0x10
 #define SOC64_HANDOFF_SIZE		4096
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_STRATIX10) || \
+	IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX)
 #define SOC64_HANDOFF_BASE		0xFFE3F000
 #define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x610)
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define SOC64_HANDOFF_BASE		0xFFE5F000
+#define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x630)
+
+/* DDR handoff */
+#define SOC64_HANDOFF_DDR_BASE			0xFFE5C000
+#define SOC64_HANDOFF_DDR_MAGIC			0x48524444
+#define SOC64_HANDOFF_DDR_UMCTL2_MAGIC		0x4C54434D
+#define SOC64_HANDOFF_DDR_UMCTL2_DDR4_TYPE	0x34524444
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_0_TYPE	0x3044504C
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_1_TYPE	0x3144504C
+#define SOC64_HANDOFF_DDR_MEMRESET_BASE		(SOC64_HANDOFF_DDR_BASE + 0xC)
+#define SOC64_HANDOFF_DDR_UMCTL2_SECTION	(SOC64_HANDOFF_DDR_BASE + 0x10)
+#define SOC64_HANDOFF_DDR_PHY_MAGIC		0x43594850
+#define SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC	0x45594850
+#define SOC64_HANDOFF_DDR_PHY_BASE_OFFSET	0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET	0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET	0xC
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_1D_SECTION	0xFFE50000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_1D_SECTION	0xFFE58000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_2D_SECTION	0xFFE44000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_2D_SECTION	0xFFE4C000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_LENGTH	SZ_32K
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_LENGTH	SZ_16K
+#endif
+
 #define SOC64_HANDOFF_MUX		(SOC64_HANDOFF_BASE + 0x10)
 #define SOC64_HANDOFF_IOCTL		(SOC64_HANDOFF_BASE + 0x1A0)
 #define SOC64_HANDOFF_FPGA		(SOC64_HANDOFF_BASE + 0x330)
@@ -52,11 +80,11 @@
 #include <asm/types.h>
 enum endianness {
 	LITTLE_ENDIAN = 0,
-	BIG_ENDIAN
+	BIG_ENDIAN,
+	UNKNOWN_ENDIANNESS
 };
 
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian);
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
-			 enum endianness big_endian);
+int socfpga_get_handoff_size(void *handoff_address);
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len);
 #endif
 #endif /* _HANDOFF_SOC64_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
index fc4e178..a800966 100644
--- a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2019-2021 Intel Corporation <www.intel.com>
  */
 
 #ifndef _SYSTEM_MANAGER_SOC64_H_
@@ -28,8 +28,12 @@
 #define SYSMGR_SOC64_FPGAINTF_EN2		0x6c
 #define SYSMGR_SOC64_FPGAINTF_EN3		0x70
 #define SYSMGR_SOC64_DMA_L3MASTER		0x74
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define SYSMGR_SOC64_DDR_MODE			0xb8
+#else
 #define SYSMGR_SOC64_HMC_CLK			0xb4
 #define SYSMGR_SOC64_IO_PA_CTRL			0xb8
+#endif
 #define SYSMGR_SOC64_NOC_TIMEOUT		0xc0
 #define SYSMGR_SOC64_NOC_IDLEREQ_SET		0xc4
 #define SYSMGR_SOC64_NOC_IDLEREQ_CLR		0xc8
@@ -143,4 +147,8 @@
 
 #define SYSMGR_WDDBG_PAUSE_ALL_CPU	0x0F0F0F0F
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define	SYSMGR_SOC64_DDR_MODE_MSK	BIT(0)
+#endif
+
 #endif /* _SYSTEM_MANAGER_SOC64_H_ */
diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c
index f8d3d48..9c19157 100644
--- a/arch/arm/mach-socfpga/misc.c
+++ b/arch/arm/mach-socfpga/misc.c
@@ -254,6 +254,9 @@
 #ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 	ret = socfpga_get_base_addr("intel,agilex-clkmgr",
 				    &socfpga_clkmgr_base);
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	ret = socfpga_get_base_addr("intel,n5x-clkmgr",
+				    &socfpga_clkmgr_base);
 #else
 	ret = socfpga_get_base_addr("altr,clk-mgr", &socfpga_clkmgr_base);
 #endif
diff --git a/arch/arm/mach-socfpga/misc_s10.c b/arch/arm/mach-socfpga/misc_soc64.c
similarity index 99%
rename from arch/arm/mach-socfpga/misc_s10.c
rename to arch/arm/mach-socfpga/misc_soc64.c
index 50c7f19..7b973a7 100644
--- a/arch/arm/mach-socfpga/misc_s10.c
+++ b/arch/arm/mach-socfpga/misc_soc64.c
@@ -6,16 +6,16 @@
 
 #include <altera.h>
 #include <common.h>
-#include <env.h>
-#include <errno.h>
-#include <init.h>
-#include <log.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
 #include <asm/arch/mailbox_s10.h>
 #include <asm/arch/misc.h>
 #include <asm/arch/reset_manager.h>
 #include <asm/arch/system_manager.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <env.h>
+#include <errno.h>
+#include <init.h>
+#include <log.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/arm/mach-socfpga/spl_n5x.c b/arch/arm/mach-socfpga/spl_n5x.c
new file mode 100644
index 0000000..d056871
--- /dev/null
+++ b/arch/arm/mach-socfpga/spl_n5x.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/arch/firewall.h>
+#include <asm/arch/mailbox_s10.h>
+#include <asm/arch/misc.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/u-boot.h>
+#include <asm/utils.h>
+#include <dm/uclass.h>
+#include <hang.h>
+#include <image.h>
+#include <init.h>
+#include <spl.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = spl_early_init();
+	if (ret)
+		hang();
+
+	socfpga_get_managers_addr();
+
+	/* Ensure watchdog is paused when debugging is happening */
+	writel(SYSMGR_WDDBG_PAUSE_ALL_CPU,
+	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_WDDBG);
+
+#ifdef CONFIG_HW_WATCHDOG
+	/* Enable watchdog before initializing the HW */
+	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
+	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
+	hw_watchdog_init();
+#endif
+
+	/* ensure all processors are not released prior Linux boot */
+	writeq(0, CPU_RELEASE_ADDR);
+
+	timer_init();
+
+	sysmgr_pinmux_init();
+
+	preloader_console_init();
+
+	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+	if (ret) {
+		printf("Clock init failed: %d\n", ret);
+		hang();
+	}
+
+	ret = uclass_get_device(UCLASS_CLK, 1, &dev);
+	if (ret) {
+		printf("Memory clock init failed: %d\n", ret);
+		hang();
+	}
+
+	print_reset_info();
+	cm_print_clock_quick_summary();
+
+	firewall_setup();
+
+	ret = uclass_get_device(UCLASS_CACHE, 0, &dev);
+	if (ret) {
+		printf("CCU init failed: %d\n", ret);
+		hang();
+	}
+
+#if CONFIG_IS_ENABLED(ALTERA_SDRAM)
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		printf("DRAM init failed: %d\n", ret);
+		hang();
+	}
+#endif
+
+	mbox_init();
+
+#ifdef CONFIG_CADENCE_QSPI
+	mbox_qspi_open();
+#endif
+}
diff --git a/arch/arm/mach-socfpga/system_manager_soc64.c b/arch/arm/mach-socfpga/system_manager_soc64.c
index 3b5e774..958bb51 100644
--- a/arch/arm/mach-socfpga/system_manager_soc64.c
+++ b/arch/arm/mach-socfpga/system_manager_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -66,10 +66,10 @@
 void populate_sysmgr_pinmux(void)
 {
 	u32 len, i;
-	u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX, BIG_ENDIAN);
-	u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL, BIG_ENDIAN);
-	u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA, BIG_ENDIAN);
-	u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY, BIG_ENDIAN);
+	u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX);
+	u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL);
+	u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA);
+	u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY);
 
 	len = (len_mux > len_ioctl) ? len_mux : len_ioctl;
 	len = (len > len_fpga) ? len : len_fpga;
@@ -79,7 +79,7 @@
 
 	/* setup the pin sel */
 	len = (len_mux < SOC64_HANDOFF_MUX_LEN) ? len_mux : SOC64_HANDOFF_MUX_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -89,7 +89,7 @@
 
 	/* setup the pin ctrl */
 	len = (len_ioctl < SOC64_HANDOFF_IOCTL_LEN) ? len_ioctl : SOC64_HANDOFF_IOCTL_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -99,7 +99,7 @@
 
 	/* setup the fpga use */
 	len = (len_fpga < SOC64_HANDOFF_FPGA_LEN) ? len_fpga : SOC64_HANDOFF_FPGA_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -109,7 +109,7 @@
 
 	/* setup the IO delay */
 	len = (len_delay < SOC64_HANDOFF_DELAY_LEN) ? len_delay : SOC64_HANDOFF_DELAY_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
index a7ad7a1..e7cb5ea 100644
--- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c
+++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -10,12 +10,64 @@
 #include <errno.h>
 #include "log.h"
 
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
+static enum endianness check_endianness(u32 handoff)
+{
+	switch (handoff) {
+	case SOC64_HANDOFF_MAGIC_BOOT:
+	case SOC64_HANDOFF_MAGIC_MUX:
+	case SOC64_HANDOFF_MAGIC_IOCTL:
+	case SOC64_HANDOFF_MAGIC_FPGA:
+	case SOC64_HANDOFF_MAGIC_DELAY:
+	case SOC64_HANDOFF_MAGIC_CLOCK:
+	case SOC64_HANDOFF_MAGIC_MISC:
+		return BIG_ENDIAN;
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
+		debug("%s: umctl2 handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_MAGIC:
+		debug("%s: PHY handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
+		debug("%s: PHY engine handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+#endif
+	default:
+		debug("%s: Unknown endianness!!\n", __func__);
+		return UNKNOWN_ENDIANNESS;
+	}
+}
+
+static int getting_endianness(void *handoff_address, enum endianness *endian_t)
+{
+	/* Checking handoff data is little endian ? */
+	*endian_t = check_endianness(readl(handoff_address));
+
+	if (*endian_t == UNKNOWN_ENDIANNESS) {
+		/* Trying to check handoff data is big endian? */
+		*endian_t = check_endianness(swab32(readl(handoff_address)));
+		if (*endian_t == UNKNOWN_ENDIANNESS) {
+			debug("%s: Cannot find HANDOFF MAGIC ", __func__);
+			debug("at addr 0x%p\n", (u32 *)handoff_address);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+int socfpga_get_handoff_size(void *handoff_address)
 {
 	u32 size;
+	int ret;
+	enum endianness endian_t;
+
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
 
 	size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
-	if (endian == BIG_ENDIAN)
+	if (endian_t == BIG_ENDIAN)
 		size = swab32(size);
 
 	size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
@@ -26,41 +78,53 @@
 	return size;
 }
 
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
-			 enum endianness big_endian)
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
 {
-	u32 temp, i;
+	u32 temp;
 	u32 *table_x32 = table;
+	u32 i = 0;
+	int ret;
+	enum endianness endian_t;
 
-	debug("%s: handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
 
-	if (big_endian) {
-		if (swab32(readl(SOC64_HANDOFF_BASE)) == SOC64_HANDOFF_MAGIC_BOOT) {
-			debug("Handoff table address = 0x%p ", table_x32);
-			debug("table length = 0x%x\n", table_len);
-			debug("%s: handoff data =\n{\n", __func__);
+	temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
+		    (i * sizeof(u32)));
 
-			for (i = 0; i < table_len; i++) {
-				temp = readl(handoff_address +
-					     SOC64_HANDOFF_OFFSET_DATA +
-					     (i * sizeof(u32)));
-				*table_x32 = swab32(temp);
+	if (endian_t == BIG_ENDIAN) {
+		debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+		debug("Handoff table address = 0x%p ", table_x32);
+		debug("table length = 0x%x\n", table_len);
+		debug("%s: handoff data =\n{\n", __func__);
+		*table_x32 = swab32(temp);
+	} else if (endian_t == LITTLE_ENDIAN) {
+		debug(" {\n");
+		*table_x32 = temp;
+	}
 
-				if (!(i % 2))
-					debug(" No.%d Addr 0x%08x: ", i,
-					      *table_x32);
-				else
-					debug(" 0x%08x\n", *table_x32);
+	debug(" No.%d Addr 0x%08x: ", i, *table_x32);
 
-				table_x32++;
-			}
-			debug("\n}\n");
-		} else {
-			debug("%s: Cannot find SOC64_HANDOFF_MAGIC_BOOT ", __func__);
-			debug("at addr  0x%p\n", (u32 *)handoff_address);
-			return -EPERM;
-		}
+	for (i = 1; i < table_len; i++) {
+		table_x32++;
+
+		temp = readl(handoff_address +
+			     SOC64_HANDOFF_OFFSET_DATA +
+			     (i * sizeof(u32)));
+
+		if (endian_t == BIG_ENDIAN)
+			*table_x32 = swab32(temp);
+		else if (endian_t == LITTLE_ENDIAN)
+			*table_x32 = temp;
+
+		if (!(i % 2))
+			debug(" No.%d Addr 0x%08x: ", i,
+			      *table_x32);
+		else
+			debug(" 0x%08x\n", *table_x32);
 	}
+	debug("\n}\n");
 
 	return 0;
 }
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index a35aac2..9dc308b 100644
--- a/arch/arm/mach-versal/cpu.c
+++ b/arch/arm/mach-versal/cpu.c
@@ -13,6 +13,7 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/cache.h>
+#include <dm/platdata.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -120,3 +121,7 @@
 	return 0;
 }
 #endif
+
+U_BOOT_DRVINFO(soc_xilinx_versal) = {
+	.name = "soc_xilinx_versal",
+};
diff --git a/arch/arm/mach-versal/include/mach/hardware.h b/arch/arm/mach-versal/include/mach/hardware.h
index 9af5afd..7b728ac 100644
--- a/arch/arm/mach-versal/include/mach/hardware.h
+++ b/arch/arm/mach-versal/include/mach/hardware.h
@@ -65,6 +65,10 @@
 
 #define crp_base ((struct crp_regs *)VERSAL_CRP_BASEADDR)
 
+#define VERSAL_PS_PMC_VERSION	0xF11A0004
+#define VERSAL_PS_VER_MASK	GENMASK(7, 0)
+#define VERSAL_PS_VER_SHIFT	12
+
 /* Bootmode setting values */
 #define BOOT_MODES_MASK	0x0000000F
 #define QSPI_MODE_24BIT	0x00000001
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 29743ca..26e285c 100644
--- a/arch/arm/mach-zynqmp/cpu.c
+++ b/arch/arm/mach-zynqmp/cpu.c
@@ -15,6 +15,7 @@
 #include <asm/io.h>
 #include <zynqmp_firmware.h>
 #include <asm/cache.h>
+#include <dm/platdata.h>
 
 #define ZYNQ_SILICON_VER_MASK	0xF000
 #define ZYNQ_SILICON_VER_SHIFT	12
@@ -218,3 +219,7 @@
 
 	return ret;
 }
+
+U_BOOT_DRVINFO(soc_xilinx_zynqmp) = {
+	.name = "soc_xilinx_zynqmp",
+};
diff --git a/arch/arm/mach-zynqmp/include/mach/hardware.h b/arch/arm/mach-zynqmp/include/mach/hardware.h
index 3776499..eebf3855 100644
--- a/arch/arm/mach-zynqmp/include/mach/hardware.h
+++ b/arch/arm/mach-zynqmp/include/mach/hardware.h
@@ -69,6 +69,9 @@
 
 #define iou_scntr_secure ((struct iou_scntr_secure *)ZYNQMP_IOU_SCNTR_SECURE)
 
+#define ZYNQMP_PS_VERSION	0xFFCA0044
+#define ZYNQMP_PS_VER_MASK	GENMASK(1, 0)
+
 /* Bootmode setting values */
 #define BOOT_MODES_MASK	0x0000000F
 #define QSPI_MODE_24BIT	0x00000001
diff --git a/arch/arm/mach-zynqmp/mkimage_fit_atf.sh b/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
index 592be7f..72a8a3e 100755
--- a/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
+++ b/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
@@ -57,7 +57,7 @@
 /dts-v1/;
 
 / {
-	description = "Configuration to load ATF before U-Boot";
+	description = "Configuration for Xilinx ZynqMP SoC";
 
 	images {
 		uboot {
@@ -78,7 +78,7 @@
 if [ -f $BL31 ]; then
 cat << __ATF
 		atf {
-			description = "ARM Trusted Firmware";
+			description = "Trusted Firmware-A";
 			data = /incbin/("$BL31");
 			type = "firmware";
 			os = "arm-trusted-firmware";
@@ -111,6 +111,51 @@
 __TEE
 fi
 
+MULTI_DTB=`awk '/CONFIG_MULTI_DTB_FIT / { print $3 }' include/generated/autoconf.h`
+
+if [ 1"$MULTI_DTB" -eq 11 ]; then
+	cat << __FDT_IMAGE_EOF
+		fdt_1 {
+			description = "Multi DTB fit image";
+			data = /incbin/("fit-dtb.blob");
+			type = "flat_dt";
+			arch = "arm64";
+			compression = "none";
+			$DTB_LOAD
+			hash {
+				algo = "md5";
+			};
+		};
+	};
+	configurations {
+		default = "config_1";
+__FDT_IMAGE_EOF
+
+if [ ! -f $BL31 ]; then
+cat << __CONF_SECTION1_EOF
+		config_1 {
+			description = "Multi DTB without TF-A";
+			firmware = "uboot";
+			loadables = "fdt_1";
+		};
+__CONF_SECTION1_EOF
+else
+cat << __CONF_SECTION1_EOF
+		config_1 {
+			description = "Multi DTB with TF-A";
+			firmware = "atf";
+			loadables = "uboot", "fdt_1";
+		};
+__CONF_SECTION1_EOF
+fi
+
+cat << __ITS_EOF
+	};
+};
+__ITS_EOF
+
+else
+
 DEFAULT=1
 cnt=1
 for dtname in $DT
@@ -181,3 +226,5 @@
 	};
 };
 __ITS_EOF
+
+fi
diff --git a/board/intel/n5x-socdk/MAINTAINERS b/board/intel/n5x-socdk/MAINTAINERS
new file mode 100644
index 0000000..ca063a9
--- /dev/null
+++ b/board/intel/n5x-socdk/MAINTAINERS
@@ -0,0 +1,9 @@
+SOCFPGA BOARD
+M:	Chee Tien Fong <tien.fong.chee@intel.com>
+M:	Lim Siew Chin <elly.siew.chin.lim@intel.com>
+S:	Maintained
+F:	board/intel/n5x-socdk/
+F:	include/configs/socfpga_n5x_socdk.h
+F:	configs/socfpga_n5x_defconfig
+F:	configs/socfpga_n5x_atf_defconfig
+F:	configs/socfpga_n5x_vab_defconfig
diff --git a/board/intel/n5x-socdk/Makefile b/board/intel/n5x-socdk/Makefile
new file mode 100644
index 0000000..accfdcd
--- /dev/null
+++ b/board/intel/n5x-socdk/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+#
+# SPDX-License-Identifier:	GPL-2.0
+#
+
+obj-y	:= socfpga.o
diff --git a/board/intel/n5x-socdk/socfpga.c b/board/intel/n5x-socdk/socfpga.c
new file mode 100644
index 0000000..985ba19
--- /dev/null
+++ b/board/intel/n5x-socdk/socfpga.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 92b61d8..9006bd3 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -18,6 +18,8 @@
 #include <i2c_eeprom.h>
 #include <net.h>
 #include <generated/dt.h>
+#include <soc.h>
+#include <linux/ctype.h>
 
 #include "fru.h"
 
@@ -67,7 +69,7 @@
 };
 
 static int highest_id = -1;
-static struct xilinx_board_description **board_info;
+static struct xilinx_board_description *board_info;
 
 #define XILINX_I2C_DETECTION_BITS	sizeof(struct fru_common_hdr)
 
@@ -167,7 +169,7 @@
 static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
 				  struct xilinx_board_description *desc)
 {
-	int ret, eeprom_size;
+	int i, ret, eeprom_size;
 	u8 *fru_content;
 
 	/* FIXME this is shortcut - if eeprom type is wrong it will fail */
@@ -184,21 +186,23 @@
 			  eeprom_size);
 	if (ret) {
 		debug("%s: I2C EEPROM read failed\n", __func__);
-		free(fru_content);
-		return ret;
+		goto end;
 	}
 
-	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 (gd->flags & GD_FLG_RELOC || (_DEBUG && CONFIG_IS_ENABLED(DTB_RESELECT))) {
+		printf("Xilinx I2C FRU format at %s:\n", name);
+		ret = fru_display(0);
+		if (ret) {
+			printf("FRU format decoding failed.\n");
+			goto end;
+		}
 	}
 
 	if (desc->header == EEPROM_HEADER_MAGIC) {
 		debug("Information already filled\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto end;
 	}
 
 	/* It is clear that FRU was captured and structures were filled */
@@ -206,13 +210,19 @@
 		sizeof(desc->manufacturer));
 	strncpy(desc->name, (char *)fru_data.brd.product_name,
 		sizeof(desc->name));
+	for (i = 0; i < sizeof(desc->name); i++) {
+		if (desc->name[i] == ' ')
+			desc->name[i] = '\0';
+	}
 	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;
+end:
+	free(fru_content);
+	return ret;
 }
 
 static bool xilinx_detect_fru(u8 *buffer)
@@ -275,7 +285,7 @@
 
 __maybe_unused int xilinx_read_eeprom(void)
 {
-	int id, ret;
+	int id;
 	char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
 	struct xilinx_board_description *desc;
 
@@ -284,7 +294,7 @@
 	if (highest_id < 0)
 		return -EINVAL;
 
-	board_info = calloc(1, sizeof(desc) * highest_id);
+	board_info = calloc(1, sizeof(*desc) * (highest_id + 1));
 	if (!board_info)
 		return -ENOMEM;
 
@@ -295,21 +305,10 @@
 		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;
-		}
+		desc = &board_info[id];
 
 		/* Ignoring return value for supporting multiple chips */
-		ret = xilinx_read_eeprom_single(name_buf, desc);
-		if (ret) {
-			free(desc);
-			board_info[id] = NULL;
-		}
+		xilinx_read_eeprom_single(name_buf, desc);
 	}
 
 	/*
@@ -395,7 +394,7 @@
 	ret |= env_set_addr("bootm_size", (void *)bootm_size);
 
 	for (id = 0; id <= highest_id; id++) {
-		desc = board_info[id];
+		desc = &board_info[id];
 		if (desc && desc->header == EEPROM_HEADER_MAGIC) {
 			if (desc->manufacturer[0])
 				ret |= env_set_by_index("manufacturer", id,
@@ -431,12 +430,139 @@
 }
 #endif
 
+static char *board_name = DEVICE_TREE;
+
 int __maybe_unused board_fit_config_name_match(const char *name)
 {
-	debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE);
+	debug("%s: Check %s, default %s\n", __func__, name, board_name);
 
-	if (!strcmp(name, DEVICE_TREE))
+	if (!strcmp(name, board_name))
 		return 0;
 
 	return -1;
 }
+
+#if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_ARCH_ZYNQ)
+int print_cpuinfo(void)
+{
+	struct udevice *soc;
+	char name[SOC_MAX_STR_SIZE];
+	int ret;
+
+	ret = soc_get(&soc);
+	if (ret) {
+		printf("CPU:   UNKNOWN\n");
+		return 0;
+	}
+
+	ret = soc_get_family(soc, name, SOC_MAX_STR_SIZE);
+	if (ret)
+		printf("CPU:   %s\n", name);
+
+	ret = soc_get_revision(soc, name, SOC_MAX_STR_SIZE);
+	if (ret)
+		printf("Silicon: %s\n", name);
+
+	return 0;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(DTB_RESELECT)
+#define MAX_NAME_LENGTH	50
+
+char * __maybe_unused __weak board_name_decode(void)
+{
+	char *board_local_name;
+	struct xilinx_board_description *desc;
+	int i, id;
+
+	board_local_name = calloc(1, MAX_NAME_LENGTH);
+	if (!board_info)
+		return NULL;
+
+	for (id = 0; id <= highest_id; id++) {
+		desc = &board_info[id];
+
+		/* No board description */
+		if (!desc)
+			goto error;
+
+		/* Board is not detected */
+		if (desc->header != EEPROM_HEADER_MAGIC)
+			continue;
+
+		/* The first string should be soc name */
+		if (!id)
+			strcat(board_local_name, CONFIG_SYS_BOARD);
+
+		/*
+		 * For two purpose here:
+		 * soc_name- eg: zynqmp-
+		 * and between base board and CC eg: ..revA-sck...
+		 */
+		strcat(board_local_name, "-");
+
+		if (desc->name[0]) {
+			/* For DT composition name needs to be lowercase */
+			for (i = 0; i < sizeof(desc->name); i++)
+				desc->name[i] = tolower(desc->name[i]);
+
+			strcat(board_local_name, desc->name);
+		}
+		if (desc->revision[0]) {
+			strcat(board_local_name, "-rev");
+
+			/* And revision needs to be uppercase */
+			for (i = 0; i < sizeof(desc->revision); i++)
+				desc->revision[i] = toupper(desc->revision[i]);
+
+			strcat(board_local_name, desc->revision);
+		}
+	}
+
+	/*
+	 * Longer strings will end up with buffer overflow and potential
+	 * attacks that's why check it
+	 */
+	if (strlen(board_local_name) >= MAX_NAME_LENGTH)
+		panic("Board name can't be determined\n");
+
+	if (strlen(board_local_name))
+		return board_local_name;
+
+error:
+	free(board_local_name);
+	return NULL;
+}
+
+bool __maybe_unused __weak board_detection(void)
+{
+	if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) {
+		int ret;
+
+		ret = xilinx_read_eeprom();
+		return !ret ? true : false;
+	}
+
+	return false;
+}
+
+int embedded_dtb_select(void)
+{
+	if (board_detection()) {
+		char *board_local_name;
+
+		board_local_name = board_name_decode();
+		if (board_local_name) {
+			board_name = board_local_name;
+			printf("Detected name: %s\n", board_name);
+
+			/* Time to change DTB on fly */
+			/* Both ways should work here */
+			/* fdtdec_resetup(&rescan); */
+			fdtdec_setup();
+		}
+	}
+	return 0;
+}
+#endif
diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 7d8277c..a914028 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -44,8 +44,6 @@
 endif
 endif
 
-obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
-
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZYNQMP) += cmds.o
 endif
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
deleted file mode 100644
index d16bbb8..0000000
--- a/board/xilinx/zynqmp/tap_delays.c
+++ /dev/null
@@ -1,101 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx ZynqMP SoC Tap Delay Programming
- *
- * Copyright (C) 2018 Xilinx, Inc.
- */
-
-#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
-#define SD_OTAP_DLY			0xFF180318
-#define SD0_DLL_RST_MASK		0x00000004
-#define SD0_DLL_RST			0x00000004
-#define SD1_DLL_RST_MASK		0x00040000
-#define SD1_DLL_RST			0x00040000
-#define SD0_ITAPCHGWIN_MASK		0x00000200
-#define SD0_ITAPCHGWIN			0x00000200
-#define SD1_ITAPCHGWIN_MASK		0x02000000
-#define SD1_ITAPCHGWIN			0x02000000
-#define SD0_ITAPDLYENA_MASK		0x00000100
-#define SD0_ITAPDLYENA			0x00000100
-#define SD1_ITAPDLYENA_MASK		0x01000000
-#define SD1_ITAPDLYENA			0x01000000
-#define SD0_ITAPDLYSEL_MASK		0x000000FF
-#define SD1_ITAPDLYSEL_MASK		0x00FF0000
-#define SD0_OTAPDLYSEL_MASK		0x0000003F
-#define SD1_OTAPDLYSEL_MASK		0x003F0000
-
-void zynqmp_dll_reset(u8 deviceid)
-{
-	/* Issue DLL Reset */
-	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);
-
-	mdelay(1);
-
-	/* Release DLL Reset */
-	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);
-}
-
-void arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 itap_delay)
-{
-	if (deviceid == 0) {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
-
-		/* Program 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, itap_delay);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
-
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
-	} else {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
-
-		/* Program 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);
-
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
-	}
-}
-
-void arasan_zynqmp_set_out_tapdelay(u8 deviceid, u32 otap_delay)
-{
-	if (deviceid == 0) {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
-
-		/* Program OTAP delay */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, otap_delay);
-
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
-	} else {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
-
-		/* Program OTAP delay */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-				  (otap_delay << 16));
-
-		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 38c910f..ea15e62 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -8,6 +8,7 @@
 #include <command.h>
 #include <cpu_func.h>
 #include <debug_uart.h>
+#include <dfu.h>
 #include <env.h>
 #include <env_internal.h>
 #include <init.h>
@@ -19,6 +20,7 @@
 #include <ahci.h>
 #include <scsi.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <wdt.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
@@ -346,13 +348,14 @@
 
 static int multi_boot(void)
 {
-	u32 multiboot;
-
-	multiboot = readl(&csu_base->multi_boot);
+	u32 multiboot = 0;
+	int ret;
 
-	printf("Multiboot:\t%d\n", multiboot);
+	ret = zynqmp_mmio_read((ulong)&csu_base->multi_boot, &multiboot);
+	if (ret)
+		return -EINVAL;
 
-	return 0;
+	return multiboot;
 }
 
 #define PS_SYSMON_ANALOG_BUS_VAL	0x3210
@@ -392,7 +395,7 @@
 #endif
 
 	if (current_el() == 3)
-		multi_boot();
+		printf("Multiboot:\t%d\n", multi_boot());
 
 	return 0;
 }
@@ -467,6 +470,9 @@
 	phys_addr_t reg;
 	struct lmb lmb;
 
+	if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
+		panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
+
 	/* found enough not-reserved memory to relocated U-Boot */
 	lmb_init(&lmb);
 	lmb_add(&lmb, gd->ram_base, gd->ram_size);
@@ -515,6 +521,9 @@
 	if (ret)
 		return -EINVAL;
 
+	debug("HW boot mode: %x\n", reg & BOOT_MODES_MASK);
+	debug("ALT boot mode: %x\n", reg >> BOOT_MODE_ALT_SHIFT);
+
 	if (reg >> BOOT_MODE_ALT_SHIFT)
 		reg >>= BOOT_MODE_ALT_SHIFT;
 
@@ -735,6 +744,7 @@
 			env_targets ? env_targets : "");
 
 	env_set("boot_targets", new_targets);
+	free(new_targets);
 
 	reset_reason();
 
@@ -816,3 +826,55 @@
 		return ENVL_NOWHERE;
 	}
 }
+
+#if defined(CONFIG_SET_DFU_ALT_INFO)
+
+#define DFU_ALT_BUF_LEN		SZ_1K
+
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+	u8 multiboot;
+	int bootseq = 0;
+
+	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
+
+	if (env_get("dfu_alt_info"))
+		return;
+
+	memset(buf, 0, sizeof(buf));
+
+	multiboot = multi_boot();
+	debug("Multiboot: %d\n", multiboot);
+
+	switch (zynqmp_get_bootmode()) {
+	case EMMC_MODE:
+	case SD_MODE:
+	case SD1_LSHFT_MODE:
+	case SD_MODE1:
+		bootseq = mmc_get_env_dev();
+		if (!multiboot)
+			snprintf(buf, DFU_ALT_BUF_LEN,
+				 "mmc %d:1=boot.bin fat %d 1;"
+				 "u-boot.itb fat %d 1",
+				 bootseq, bootseq, bootseq);
+		else
+			snprintf(buf, DFU_ALT_BUF_LEN,
+				 "mmc %d:1=boot%04d.bin fat %d 1;"
+				 "u-boot.itb fat %d 1",
+				 bootseq, multiboot, bootseq, bootseq);
+		break;
+	case QSPI_MODE_24BIT:
+	case QSPI_MODE_32BIT:
+		snprintf(buf, DFU_ALT_BUF_LEN,
+			 "sf 0:0=boot.bin raw %x 0x1500000;"
+			 "u-boot.itb raw 0x%x 0x500000",
+			 multiboot * SZ_32K, CONFIG_SYS_SPI_U_BOOT_OFFS);
+		break;
+	default:
+		return;
+	}
+
+	env_set("dfu_alt_info", buf);
+	puts("DFU alt info setting: done\n");
+}
+#endif
diff --git a/cmd/boot.c b/cmd/boot.c
index fab294e..be67a59 100644
--- a/cmd/boot.c
+++ b/cmd/boot.c
@@ -58,7 +58,8 @@
 U_BOOT_CMD(
 	reset, 2, 0,	do_reset,
 	"Perform RESET of the CPU",
-	""
+	"- cold boot without level specifier\n"
+	"reset -w - warm reset if implemented"
 );
 
 #ifdef CONFIG_CMD_POWEROFF
diff --git a/cmd/date.c b/cmd/date.c
index e377cfe..149ca42 100644
--- a/cmd/date.c
+++ b/cmd/date.c
@@ -41,10 +41,13 @@
 #ifdef CONFIG_DM_RTC
 	struct udevice *dev;
 
-	rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
+	rcode = uclass_get_device_by_seq(UCLASS_RTC, 0, &dev);
 	if (rcode) {
-		printf("Cannot find RTC: err=%d\n", rcode);
-		return CMD_RET_FAILURE;
+		rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
+		if (rcode) {
+			printf("Cannot find RTC: err=%d\n", rcode);
+			return CMD_RET_FAILURE;
+		}
 	}
 #elif defined(CONFIG_SYS_I2C_LEGACY)
 	old_bus = i2c_get_bus_num();
diff --git a/cmd/pwm.c b/cmd/pwm.c
index 87d840a..7947e61 100644
--- a/cmd/pwm.c
+++ b/cmd/pwm.c
@@ -108,7 +108,8 @@
 
 U_BOOT_CMD(pwm, 6, 0, do_pwm,
 	   "control pwm channels",
-	   "pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
-	   "pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
-	   "pwm <enable/disable> <pwm_dev_num> <channel>\n"
+	   "invert <pwm_dev_num> <channel> <polarity> - invert polarity\n"
+	   "pwm config <pwm_dev_num> <channel> <period_ns> <duty_ns> - config PWM\n"
+	   "pwm enable <pwm_dev_num> <channel> - enable PWM output\n"
+	   "pwm disable <pwm_dev_num> <channel> - eisable PWM output\n"
 	   "Note: All input values are in decimal");
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 4341d84..8992ac5 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -420,6 +420,24 @@
 #else
 #define MEMORY_BANKS_MAX 4
 #endif
+
+/**
+ * fdt_fixup_memory_banks - Update DT memory node
+ * @blob: Pointer to DT blob
+ * @start: Pointer to memory start addresses array
+ * @size: Pointer to memory sizes array
+ * @banks: Number of memory banks
+ *
+ * Return: 0 on success, negative value on failure
+ *
+ * Based on the passed number of banks and arrays, the function is able to
+ * update existing DT memory nodes to match run time detected/changed memory
+ * configuration. Implementation is handling one specific case with only one
+ * memory node where multiple tuples could be added/updated.
+ * The case where multiple memory nodes with a single tuple (base, size) are
+ * used, this function is only updating the first memory node without removing
+ * others.
+ */
 int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
 {
 	int err, nodeoffset;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 4658f18..ea08a9e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -120,8 +120,6 @@
 CONFIG_NETCONSOLE=y
 CONFIG_IP_DEFRAG=y
 CONFIG_DM_DMA=y
-CONFIG_REGMAP=y
-CONFIG_SYSCON=y
 CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
 CONFIG_SIMPLE_PM_BUS=y
@@ -131,9 +129,9 @@
 CONFIG_AXI_SANDBOX=y
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_DM_BOOTCOUNT=y
-CONFIG_DM_BOOTCOUNT_SYSCON=y
 CONFIG_DM_BOOTCOUNT_RTC=y
 CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y
+CONFIG_DM_BOOTCOUNT_SYSCON=y
 CONFIG_BUTTON=y
 CONFIG_BUTTON_ADC=y
 CONFIG_BUTTON_GPIO=y
diff --git a/configs/socfpga_agilex_atf_defconfig b/configs/socfpga_agilex_atf_defconfig
index 4eed95b..414f49b 100644
--- a/configs/socfpga_agilex_atf_defconfig
+++ b/configs/socfpga_agilex_atf_defconfig
@@ -21,7 +21,7 @@
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="earlycon"
 CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run linux_qspi_enable; run mmcfitboot"
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32=y
 CONFIG_SPL_CACHE=y
 CONFIG_SPL_SPI_LOAD=y
diff --git a/configs/socfpga_n5x_atf_defconfig b/configs/socfpga_n5x_atf_defconfig
new file mode 100644
index 0000000..3b5246e
--- /dev/null
+++ b/configs/socfpga_n5x_atf_defconfig
@@ -0,0 +1,73 @@
+CONFIG_ARM=y
+CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds"
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x200
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
+CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
+CONFIG_SPL_FS_FAT=y
+CONFIG_FIT=y
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTDELAY=5
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
+CONFIG_SPL_CRC32=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DWAPB_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_MMC_DW=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_MODE=0x2003
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_MII=y
+CONFIG_DM_RESET=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_PANIC_HANG=y
diff --git a/configs/socfpga_n5x_defconfig b/configs/socfpga_n5x_defconfig
new file mode 100644
index 0000000..a5649ae
--- /dev/null
+++ b/configs/socfpga_n5x_defconfig
@@ -0,0 +1,64 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_SYS_TEXT_BASE=0x1000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x200
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
+CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
+CONFIG_SPL_FS_FAT=y
+# CONFIG_PSCI_RESET is not set
+CONFIG_BOOTDELAY=5
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run fatscript; run mmcload; run linux_qspi_enable; run mmcboot"
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x3c00000
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DWAPB_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_MMC_DW=y
+CONFIG_SF_DEFAULT_MODE=0x2003
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_MII=y
+CONFIG_DM_RESET=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_PANIC_HANG=y
diff --git a/configs/socfpga_n5x_vab_defconfig b/configs/socfpga_n5x_vab_defconfig
new file mode 100644
index 0000000..cb3f3a9
--- /dev/null
+++ b/configs/socfpga_n5x_vab_defconfig
@@ -0,0 +1,74 @@
+CONFIG_ARM=y
+CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds"
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_SYS_TEXT_BASE=0x200000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x200
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
+CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_SOCFPGA_SECURE_VAB_AUTH=y
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
+CONFIG_SPL_FS_FAT=y
+CONFIG_FIT=y
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_BOOTDELAY=5
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
+CONFIG_SPL_CRC32=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
+CONFIG_SPL_ATF=y
+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DWAPB_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_MMC_DW=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_MODE=0x2003
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_MII=y
+CONFIG_DM_RESET=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_DESIGNWARE_WATCHDOG=y
+CONFIG_WDT=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
+CONFIG_PANIC_HANG=y
diff --git a/configs/socfpga_stratix10_atf_defconfig b/configs/socfpga_stratix10_atf_defconfig
index d99d90f..43c583b 100644
--- a/configs/socfpga_stratix10_atf_defconfig
+++ b/configs/socfpga_stratix10_atf_defconfig
@@ -21,7 +21,7 @@
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="earlycon"
 CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run linux_qspi_enable; run mmcfitboot"
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig
index e679051..590a217 100644
--- a/configs/xilinx_versal_virt_defconfig
+++ b/configs/xilinx_versal_virt_defconfig
@@ -13,9 +13,9 @@
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_BOOTDELAY=5
 CONFIG_USE_PREBOOT=y
-# CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SYS_PROMPT="Versal> "
 CONFIG_CMD_BOOTMENU=y
@@ -95,6 +95,7 @@
 CONFIG_ARM_DCC=y
 CONFIG_PL01X_SERIAL=y
 CONFIG_XILINX_UARTLITE=y
+CONFIG_SOC_XILINX_VERSAL=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_ZYNQ_SPI=y
diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig
index ae67a50..66af37a 100644
--- a/configs/xilinx_zynq_virt_defconfig
+++ b/configs/xilinx_zynq_virt_defconfig
@@ -22,6 +22,7 @@
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_LEGACY_IMAGE_FORMAT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_USE_PREBOOT=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_FPGA=y
diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig
index e6af7c8..2c8dc34 100644
--- a/configs/xilinx_zynqmp_virt_defconfig
+++ b/configs/xilinx_zynqmp_virt_defconfig
@@ -7,6 +7,9 @@
 CONFIG_SYS_MEMTEST_END=0x00001000
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu100-revC"
+CONFIG_SPL_STACK_R_ADDR=0x18000000
+CONFIG_SPL_SIZE_LIMIT=0x2a000
+CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x0
 CONFIG_SPL=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
@@ -20,15 +23,18 @@
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_USE_PREBOOT=y
-# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_PREBOOT="run scsi_init;usb start"
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SPL_STACK_R=y
 CONFIG_SPL_FPGA=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
 CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x100000
 CONFIG_SPL_ATF=y
 CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
 CONFIG_CMD_BOOTMENU=y
@@ -36,6 +42,7 @@
 CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
+CONFIG_CMD_SHA1SUM=y
 CONFIG_CMD_BIND=y
 CONFIG_CMD_CLK=y
 CONFIG_CMD_DFU=y
@@ -59,6 +66,7 @@
 CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_GETTIME=y
 CONFIG_CMD_TIMER=y
@@ -85,6 +93,8 @@
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SCSI_AHCI=y
 CONFIG_SATA_CEVA=y
+CONFIG_BUTTON=y
+CONFIG_BUTTON_GPIO=y
 CONFIG_CLK_ZYNQMP=y
 CONFIG_DFU_TFTP=y
 CONFIG_DFU_TIMEOUT=y
@@ -93,6 +103,7 @@
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
 CONFIG_DFU_MTD=y
+CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_FLASH=y
@@ -149,11 +160,13 @@
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_EMULATION=y
+CONFIG_RTC_ZYNQMP=y
 CONFIG_SCSI=y
 CONFIG_DM_SCSI=y
 CONFIG_ARM_DCC=y
 CONFIG_XILINX_UARTLITE=y
 CONFIG_ZYNQ_SERIAL=y
+CONFIG_SOC_XILINX_ZYNQMP=y
 CONFIG_SPI=y
 CONFIG_ZYNQ_SPI=y
 CONFIG_ZYNQMP_GQSPI=y
@@ -187,7 +200,6 @@
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
 CONFIG_WDT=y
-CONFIG_WDT_CDNS=y
 CONFIG_PANIC_HANG=y
 CONFIG_TPM=y
 CONFIG_SPL_GZIP=y
diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile
index 96215ad..33db092 100644
--- a/drivers/clk/altera/Makefile
+++ b/drivers/clk/altera/Makefile
@@ -1,7 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Copyright (C) 2018 Marek Vasut <marex@denx.de>
+# Copyright (C) 2018-2021 Marek Vasut <marex@denx.de>
 #
 
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o
 obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o
+obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-n5x.o
+obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-mem-n5x.o
diff --git a/drivers/clk/altera/clk-mem-n5x.c b/drivers/clk/altera/clk-mem-n5x.c
new file mode 100644
index 0000000..ca44998
--- /dev/null
+++ b/drivers/clk/altera/clk-mem-n5x.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include "clk-mem-n5x.h"
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/util.h>
+#include <dt-bindings/clock/n5x-clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct socfpga_mem_clk_plat {
+	void __iomem *regs;
+};
+
+void clk_mem_wait_for_lock(struct socfpga_mem_clk_plat *plat, u32 mask)
+{
+	u32 inter_val;
+	u32 retry = 0;
+
+	do {
+		inter_val = CM_REG_READL(plat, MEMCLKMGR_STAT) & mask;
+
+		/* Wait for stable lock */
+		if (inter_val == mask)
+			retry++;
+		else
+			retry = 0;
+
+		if (retry >= 10)
+			return;
+	} while (1);
+}
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+void clk_mem_write_bypass_mempll(struct socfpga_mem_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, MEMCLKMGR_MEMPLL_BYPASS);
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+static void clk_mem_basic_init(struct udevice *dev,
+			       const struct cm_config * const cfg)
+{
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(dev);
+
+	if (!cfg)
+		return;
+
+	/* Put PLLs in bypass */
+	clk_mem_write_bypass_mempll(plat, MEMCLKMGR_BYPASS_MEMPLL_ALL);
+
+	/* Put PLLs in Reset */
+	CM_REG_SETBITS(plat, MEMCLKMGR_MEMPLL_PLLCTRL,
+		       MEMCLKMGR_PLLCTRL_BYPASS_MASK);
+
+	/* setup mem PLL */
+	CM_REG_WRITEL(plat, cfg->mem_memdiv, MEMCLKMGR_MEMPLL_MEMDIV);
+	CM_REG_WRITEL(plat, cfg->mem_pllglob, MEMCLKMGR_MEMPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->mem_plldiv, MEMCLKMGR_MEMPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->mem_plloutdiv, MEMCLKMGR_MEMPLL_PLLOUTDIV);
+
+	/* Take PLL out of reset and power up */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_MEMPLL_PLLCTRL,
+		       MEMCLKMGR_PLLCTRL_BYPASS_MASK);
+}
+
+static int socfpga_mem_clk_enable(struct clk *clk)
+{
+	const struct cm_config *cm_default_cfg = cm_get_default_config();
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(clk->dev);
+
+	clk_mem_basic_init(clk->dev, cm_default_cfg);
+
+	clk_mem_wait_for_lock(plat, MEMCLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, MEMCLKMGR_MEMPLL_PLLGLOB) |
+		      MEMCLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+		      MEMCLKMGR_MEMPLL_PLLGLOB);
+
+	/* Take all PLLs out of bypass */
+	clk_mem_write_bypass_mempll(plat, 0);
+
+	/* Clear the loss of lock bits (write 1 to clear) */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_INTRCLR,
+		       MEMCLKMGR_INTER_MEMPLLLOST_MASK);
+
+	/* Take all ping pong counters out of reset */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_MEMPLL_EXTCNTRST,
+		       MEMCLKMGR_EXTCNTRST_ALLCNTRST);
+
+	return 0;
+}
+
+static int socfpga_mem_clk_of_to_plat(struct udevice *dev)
+{
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(dev);
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	plat->regs = (void __iomem *)addr;
+
+	return 0;
+}
+
+static struct clk_ops socfpga_mem_clk_ops = {
+	.enable		= socfpga_mem_clk_enable
+};
+
+static const struct udevice_id socfpga_mem_clk_match[] = {
+	{ .compatible = "intel,n5x-mem-clkmgr" },
+	{}
+};
+
+U_BOOT_DRIVER(socfpga_n5x_mem_clk) = {
+	.name		= "mem-clk-n5x",
+	.id		= UCLASS_CLK,
+	.of_match	= socfpga_mem_clk_match,
+	.ops		= &socfpga_mem_clk_ops,
+	.of_to_plat     = socfpga_mem_clk_of_to_plat,
+	.plat_auto	= sizeof(struct socfpga_mem_clk_plat),
+};
diff --git a/drivers/clk/altera/clk-mem-n5x.h b/drivers/clk/altera/clk-mem-n5x.h
new file mode 100644
index 0000000..d000ae2
--- /dev/null
+++ b/drivers/clk/altera/clk-mem-n5x.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef	_CLK_MEM_N5X_
+#define	_CLK_MEM_N5X_
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+/* Clock Manager registers */
+#define MEMCLKMGR_STAT					4
+#define MEMCLKMGR_INTRGEN				8
+#define MEMCLKMGR_INTRMSK				0x0c
+#define MEMCLKMGR_INTRCLR				0x10
+#define MEMCLKMGR_INTRSTS				0x14
+#define MEMCLKMGR_INTRSTK				0x18
+#define MEMCLKMGR_INTRRAW				0x1c
+
+/* Memory Clock Manager PPL group registers */
+#define MEMCLKMGR_MEMPLL_EN				0x20
+#define MEMCLKMGR_MEMPLL_ENS				0x24
+#define MEMCLKMGR_MEMPLL_ENR				0x28
+#define MEMCLKMGR_MEMPLL_BYPASS				0x2c
+#define MEMCLKMGR_MEMPLL_BYPASSS			0x30
+#define MEMCLKMGR_MEMPLL_BYPASSR			0x34
+#define MEMCLKMGR_MEMPLL_MEMDIV				0x38
+#define MEMCLKMGR_MEMPLL_PLLGLOB			0x3c
+#define MEMCLKMGR_MEMPLL_PLLCTRL			0x40
+#define MEMCLKMGR_MEMPLL_PLLDIV				0x44
+#define MEMCLKMGR_MEMPLL_PLLOUTDIV			0x48
+#define MEMCLKMGR_MEMPLL_EXTCNTRST			0x4c
+
+#define MEMCLKMGR_CTRL_BOOTMODE				BIT(0)
+
+#define MEMCLKMGR_STAT_MEMPLL_LOCKED			BIT(8)
+
+#define MEMCLKMGR_STAT_ALLPLL_LOCKED_MASK		\
+	(MEMCLKMGR_STAT_MEMPLL_LOCKED)
+
+#define MEMCLKMGR_INTER_MEMPLLLOCKED_MASK		BIT(0)
+#define MEMCLKMGR_INTER_MEMPLLLOST_MASK			BIT(2)
+
+#define MEMCLKMGR_BYPASS_MEMPLL_ALL			0x1
+
+#define MEMCLKMGR_MEMDIV_MPFEDIV_OFFSET			0
+#define MEMCLKMGR_MEMDIV_APBDIV_OFFSET			4
+#define MEMCLKMGR_MEMDIV_DFICTRLDIV_OFFSET		8
+#define MEMCLKMGR_MEMDIV_DFIDIV_OFFSET			12
+#define MEMCLKMGR_MEMDIV_DFICTRLDIV_MASK		BIT(0)
+#define MEMCLKMGR_MEMDIV_DIVIDER_MASK			GENMASK(1, 0)
+
+#define MEMCLKMGR_PLLGLOB_PSRC_MASK			GENMASK(17, 16)
+#define MEMCLKMGR_PLLGLOB_PSRC_OFFSET			16
+#define MEMCLKMGR_PLLGLOB_LOSTLOCK_BYPASS_EN_MASK	BIT(28)
+#define MEMCLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK	BIT(29)
+
+#define MEMCLKMGR_PSRC_EOSC1				0
+#define MEMCLKMGR_PSRC_INTOSC				1
+#define MEMCLKMGR_PSRC_F2S				2
+
+#define MEMCLKMGR_PLLCTRL_BYPASS_MASK			BIT(0)
+#define MEMCLKMGR_PLLCTRL_RST_N_MASK			BIT(1)
+
+#define MEMCLKMGR_PLLDIV_DIVR_MASK			GENMASK(5, 0)
+#define MEMCLKMGR_PLLDIV_DIVF_MASK			GENMASK(16, 8)
+#define MEMCLKMGR_PLLDIV_DIVQ_MASK			GENMASK(26, 24)
+#define MEMCLKMGR_PLLDIV_RANGE_MASK			GENMASK(30, 28)
+
+#define MEMCLKMGR_PLLDIV_DIVR_OFFSET			0
+#define MEMCLKMGR_PLLDIV_DIVF_OFFSET			8
+#define MEMCLKMGR_PLLDIV_DIVQ_QDIV_OFFSET		24
+#define MEMCLKMGR_PLLDIV_RANGE_OFFSET			28
+
+#define MEMCLKMGR_PLLOUTDIV_C0CNT_MASK			GENMASK(4, 0)
+#define MEMCLKMGR_PLLOUTDIV_C0CNT_OFFSET		0
+
+#define MEMCLKMGR_EXTCNTRST_C0CNTRST			BIT(7)
+#define MEMCLKMGR_EXTCNTRST_ALLCNTRST			\
+	(MEMCLKMGR_EXTCNTRST_C0CNTRST)
+
+#endif /* _CLK_MEM_N5X_ */
diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c
new file mode 100644
index 0000000..bdcbbaa
--- /dev/null
+++ b/drivers/clk/altera/clk-n5x.c
@@ -0,0 +1,489 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/util.h>
+#include <dt-bindings/clock/n5x-clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct socfpga_clk_plat {
+	void __iomem *regs;
+};
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS);
+	cm_wait_for_fsm();
+}
+
+static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS);
+	cm_wait_for_fsm();
+}
+
+/* function to write the ctrl register which requires a poll of the busy bit */
+static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_CTRL);
+	cm_wait_for_fsm();
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+static void clk_basic_init(struct udevice *dev,
+			   const struct cm_config * const cfg)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(dev);
+
+	if (!cfg)
+		return;
+
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+	/* Always force clock manager into boot mode before any configuration */
+	clk_write_ctrl(plat,
+		       CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE);
+#else
+	/* Skip clock configuration in SSBL if it's not in boot mode */
+	if (!(CM_REG_READL(plat, CLKMGR_CTRL) & CLKMGR_CTRL_BOOTMODE))
+		return;
+#endif
+
+	/* Put both PLLs in bypass */
+	clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL);
+	clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL);
+
+	/* Put both PLLs in Reset */
+	CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+	CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+
+	/* setup main PLL */
+	CM_REG_WRITEL(plat, cfg->main_pll_pllglob, CLKMGR_MAINPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->main_pll_plldiv, CLKMGR_MAINPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->main_pll_plloutdiv, CLKMGR_MAINPLL_PLLOUTDIV);
+	CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK);
+	CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK);
+	CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV);
+
+	/* setup peripheral */
+	CM_REG_WRITEL(plat, cfg->per_pll_pllglob, CLKMGR_PERPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->per_pll_plldiv, CLKMGR_PERPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->per_pll_plloutdiv, CLKMGR_PERPLL_PLLOUTDIV);
+	CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL);
+	CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV);
+
+	/* Take both PLL out of reset and power up */
+	CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+	CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+
+	cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+	CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR);
+	CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR);
+	CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR);
+	CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR);
+	CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR);
+	CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR);
+	CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR);
+	CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR);
+
+	/* Configure ping pong counters in altera group */
+	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK);
+	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK);
+
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) |
+			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+			CLKMGR_MAINPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) |
+			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+			CLKMGR_PERPLL_PLLGLOB);
+
+	/* Take all PLLs out of bypass */
+	clk_write_bypass_mainpll(plat, 0);
+	clk_write_bypass_perpll(plat, 0);
+
+	/* Clear the loss of lock bits */
+	CM_REG_CLRBITS(plat, CLKMGR_INTRCLR,
+		       CLKMGR_INTER_PERPLLLOST_MASK |
+		       CLKMGR_INTER_MAINPLLLOST_MASK);
+
+	/* Take all ping pong counters out of reset */
+	CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST,
+		       CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK);
+
+	/* Out of boot mode */
+	clk_write_ctrl(plat,
+		       CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE);
+}
+
+static u32 clk_get_5_1_clk_src(struct socfpga_clk_plat *plat, u32 reg)
+{
+	u32 clksrc = CM_REG_READL(plat, reg);
+
+	return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET;
+}
+
+static u64 clk_get_pll_output_hz(struct socfpga_clk_plat *plat,
+				 u32 pllglob_reg, u32 plldiv_reg)
+{
+	u64 clock = 0;
+	u32 clklsrc, divf, divr, divq, power = 1;
+
+	/* Get input clock frequency */
+	clklsrc = (CM_REG_READL(plat, pllglob_reg) &
+		   CLKMGR_PLLGLOB_VCO_PSRC_MASK) >>
+		   CLKMGR_PLLGLOB_VCO_PSRC_OFFSET;
+
+	switch (clklsrc) {
+	case CLKMGR_VCO_PSRC_EOSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_F2S:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	/* Calculate pll out clock frequency */
+	divf = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_FDIV_MASK) >>
+		CLKMGR_PLLDIV_FDIV_OFFSET;
+
+	divr = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_REFCLKDIV_MASK) >>
+		CLKMGR_PLLDIV_REFCLKDIV_OFFSET;
+
+	divq = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >>
+		CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET;
+
+	while (divq) {
+		power *= 2;
+		divq--;
+	}
+
+	return (clock * 2 * (divf + 1)) / ((divr + 1) * power);
+}
+
+static u64 clk_get_clksrc_hz(struct socfpga_clk_plat *plat, u32 clksrc_reg,
+			     u32 main_div, u32 per_div)
+{
+	u64 clock = 0;
+	u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg);
+
+	switch (clklsrc) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_MAINPLL_PLLGLOB,
+					      CLKMGR_MAINPLL_PLLDIV);
+		clock /= 1 + main_div;
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_PERPLL_PLLGLOB,
+					      CLKMGR_PERPLL_PLLDIV);
+		clock /= 1 + per_div;
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	default:
+		return 0;
+	}
+
+	return clock;
+}
+
+static u64 clk_get_mpu_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c0cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
+
+	u32 perpll_c0cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
+
+	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK,
+				      mainpll_c0cnt, perpll_c0cnt);
+
+	clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) &
+		      CLKMGR_CLKCNT_MSK);
+
+	return clock;
+}
+
+static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c1cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
+
+	u32 perpll_c1cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
+
+	return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK,
+				 mainpll_c1cnt, perpll_c1cnt);
+}
+
+static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MAIN_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c3cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
+
+	u32 perpll_c3cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
+
+	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR,
+				      mainpll_c3cnt, perpll_c3cnt);
+
+	clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) &
+		      CLKMGR_CLKCNT_MSK);
+
+	return clock / 4;
+}
+
+static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4SPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat *plat)
+{
+	if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE)
+		return clk_get_l3_main_clk_hz(plat) / 2;
+
+	return clk_get_l3_main_clk_hz(plat) / 4;
+}
+
+static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id)
+{
+	bool emacsel_a;
+	u32 ctl;
+	u32 ctr_reg;
+	u32 clock;
+	u32 div;
+	u32 reg;
+
+	/* Get EMAC clock source */
+	ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL);
+	if (emac_id == N5X_EMAC0_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK;
+	else if (emac_id == N5X_EMAC1_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK;
+	else if (emac_id == N5X_EMAC2_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK;
+	else
+		return 0;
+
+	if (ctl) {
+		/* EMAC B source */
+		emacsel_a = false;
+		ctr_reg = CLKMGR_ALTR_EMACBCTR;
+	} else {
+		/* EMAC A source */
+		emacsel_a = true;
+		ctr_reg = CLKMGR_ALTR_EMACACTR;
+	}
+
+	reg = CM_REG_READL(plat, ctr_reg);
+	clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK)
+		 >> CLKMGR_ALT_EMACCTR_SRC_OFFSET;
+	div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK)
+	       >> CLKMGR_ALT_EMACCTR_CNT_OFFSET;
+
+	switch (clock) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_MAINPLL_PLLGLOB,
+					      CLKMGR_MAINPLL_PLLDIV);
+
+		if (emacsel_a) {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_MAINPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
+		} else {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_MAINPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C3CNT_OFFSET);
+		}
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_PERPLL_PLLGLOB,
+					      CLKMGR_PERPLL_PLLDIV);
+		if (emacsel_a) {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_PERPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
+		} else {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_PERPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C3CNT_MASK >>
+				       CLKMGR_PLLOUTDIV_C3CNT_OFFSET));
+		}
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	clock /= 1 + div;
+
+	return clock;
+}
+
+static ulong socfpga_clk_get_rate(struct clk *clk)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
+
+	switch (clk->id) {
+	case N5X_MPU_CLK:
+		return clk_get_mpu_clk_hz(plat);
+	case N5X_L4_MAIN_CLK:
+		return clk_get_l4_main_clk_hz(plat);
+	case N5X_L4_SYS_FREE_CLK:
+		return clk_get_l4_sys_free_clk_hz(plat);
+	case N5X_L4_MP_CLK:
+		return clk_get_l4_mp_clk_hz(plat);
+	case N5X_L4_SP_CLK:
+		return clk_get_l4_sp_clk_hz(plat);
+	case N5X_SDMMC_CLK:
+		return clk_get_sdmmc_clk_hz(plat);
+	case N5X_EMAC0_CLK:
+	case N5X_EMAC1_CLK:
+	case N5X_EMAC2_CLK:
+		return clk_get_emac_clk_hz(plat, clk->id);
+	case N5X_USB_CLK:
+	case N5X_NAND_X_CLK:
+		return clk_get_l4_mp_clk_hz(plat);
+	case N5X_NAND_CLK:
+		return clk_get_l4_mp_clk_hz(plat) / 4;
+	default:
+		return -ENXIO;
+	}
+}
+
+static int socfpga_clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static int socfpga_clk_probe(struct udevice *dev)
+{
+	const struct cm_config *cm_default_cfg = cm_get_default_config();
+
+	clk_basic_init(dev, cm_default_cfg);
+
+	return 0;
+}
+
+static int socfpga_clk_of_to_plat(struct udevice *dev)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(dev);
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	plat->regs = (void __iomem *)addr;
+
+	return 0;
+}
+
+static struct clk_ops socfpga_clk_ops = {
+	.enable		= socfpga_clk_enable,
+	.get_rate	= socfpga_clk_get_rate,
+};
+
+static const struct udevice_id socfpga_clk_match[] = {
+	{ .compatible = "intel,n5x-clkmgr" },
+	{}
+};
+
+U_BOOT_DRIVER(socfpga_n5x_clk) = {
+	.name		= "clk-n5x",
+	.id		= UCLASS_CLK,
+	.of_match	= socfpga_clk_match,
+	.ops		= &socfpga_clk_ops,
+	.probe		= socfpga_clk_probe,
+	.of_to_plat	= socfpga_clk_of_to_plat,
+	.plat_auto	= sizeof(struct socfpga_clk_plat),
+};
diff --git a/drivers/clk/altera/clk-n5x.h b/drivers/clk/altera/clk-n5x.h
new file mode 100644
index 0000000..8c00e90
--- /dev/null
+++ b/drivers/clk/altera/clk-n5x.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef	_CLK_N5X_
+#define	_CLK_N5X_
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+#define CM_REG_READL(plat, reg)				\
+	readl((plat)->regs + (reg))
+
+#define CM_REG_WRITEL(plat, data, reg)			\
+	writel(data, (plat)->regs + (reg))
+
+#define CM_REG_CLRBITS(plat, reg, clear)		\
+	clrbits_le32((plat)->regs + (reg), (clear))
+
+#define CM_REG_SETBITS(plat, reg, set)			\
+	setbits_le32((plat)->regs + (reg), (set))
+
+struct cm_config {
+	/* main group */
+	u32 main_pll_mpuclk;
+	u32 main_pll_nocclk;
+	u32 main_pll_nocdiv;
+	u32 main_pll_pllglob;
+	u32 main_pll_plldiv;
+	u32 main_pll_plloutdiv;
+	u32 spare_1[4];
+
+	/* peripheral group */
+	u32 per_pll_emacctl;
+	u32 per_pll_gpiodiv;
+	u32 per_pll_pllglob;
+	u32 per_pll_plldiv;
+	u32 per_pll_plloutdiv;
+	u32 spare_2[4];
+
+	/* altera group */
+	u32 alt_emacactr;
+	u32 alt_emacbctr;
+	u32 alt_emacptpctr;
+	u32 alt_gpiodbctr;
+	u32 alt_sdmmcctr;
+	u32 alt_s2fuser0ctr;
+	u32 alt_s2fuser1ctr;
+	u32 alt_psirefctr;
+
+	/* incoming clock */
+	u32 hps_osc_clk_hz;
+	u32 fpga_clk_hz;
+	u32 spare_3[3];
+
+	/* memory clock group */
+	u32 mem_memdiv;
+	u32 mem_pllglob;
+	u32 mem_plldiv;
+	u32 mem_plloutdiv;
+	u32 spare_4[4];
+};
+
+/* Clock Manager registers */
+#define CLKMGR_CTRL					0
+#define CLKMGR_STAT					4
+#define CLKMGR_TESTIOCTRL				8
+#define CLKMGR_INTRGEN					0x0c
+#define CLKMGR_INTRMSK					0x10
+#define CLKMGR_INTRCLR					0x14
+#define CLKMGR_INTRSTS					0x18
+#define CLKMGR_INTRSTK					0x1c
+#define CLKMGR_INTRRAW					0x20
+
+/* Clock Manager Main PPL group registers */
+#define CLKMGR_MAINPLL_EN				0x24
+#define CLKMGR_MAINPLL_ENS				0x28
+#define CLKMGR_MAINPLL_ENR				0x2c
+#define CLKMGR_MAINPLL_BYPASS				0x30
+#define CLKMGR_MAINPLL_BYPASSS				0x34
+#define CLKMGR_MAINPLL_BYPASSR				0x38
+#define CLKMGR_MAINPLL_MPUCLK				0x3c
+#define CLKMGR_MAINPLL_NOCCLK				0x40
+#define CLKMGR_MAINPLL_NOCDIV				0x44
+#define CLKMGR_MAINPLL_PLLGLOB				0x48
+#define CLKMGR_MAINPLL_PLLCTRL				0x4c
+#define CLKMGR_MAINPLL_PLLDIV				0x50
+#define CLKMGR_MAINPLL_PLLOUTDIV			0x54
+#define CLKMGR_MAINPLL_LOSTLOCK				0x58
+
+/* Clock Manager Peripheral PPL group registers */
+#define CLKMGR_PERPLL_EN				0x7c
+#define CLKMGR_PERPLL_ENS				0x80
+#define CLKMGR_PERPLL_ENR				0x84
+#define CLKMGR_PERPLL_BYPASS				0x88
+#define CLKMGR_PERPLL_BYPASSS				0x8c
+#define CLKMGR_PERPLL_BYPASSR				0x90
+#define CLKMGR_PERPLL_EMACCTL				0x94
+#define CLKMGR_PERPLL_GPIODIV				0x98
+#define CLKMGR_PERPLL_PLLGLOB				0x9c
+#define CLKMGR_PERPLL_PLLCTRL				0xa0
+#define CLKMGR_PERPLL_PLLDIV				0xa4
+#define CLKMGR_PERPLL_PLLOUTDIV				0xa8
+#define CLKMGR_PERPLL_LOSTLOCK				0xac
+
+/* Clock Manager Altera group registers */
+#define CLKMGR_ALTR_EMACACTR				0xd4
+#define CLKMGR_ALTR_EMACBCTR				0xd8
+#define CLKMGR_ALTR_EMACPTPCTR				0xdc
+#define CLKMGR_ALTR_GPIODBCTR				0xe0
+#define CLKMGR_ALTR_SDMMCCTR				0xe4
+#define CLKMGR_ALTR_S2FUSER0CTR				0xe8
+#define CLKMGR_ALTR_S2FUSER1CTR				0xec
+#define CLKMGR_ALTR_PSIREFCTR				0xf0
+#define CLKMGR_ALTR_EXTCNTRST				0xf4
+
+#define CLKMGR_CTRL_BOOTMODE				BIT(0)
+
+#define CLKMGR_STAT_BUSY				BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED			BIT(8)
+#define CLKMGR_STAT_MAIN_TRANS				BIT(9)
+#define CLKMGR_STAT_PERPLL_LOCKED			BIT(16)
+#define CLKMGR_STAT_PERF_TRANS				BIT(17)
+#define CLKMGR_STAT_BOOTMODE				BIT(24)
+#define CLKMGR_STAT_BOOTCLKSRC				BIT(25)
+
+#define CLKMGR_STAT_ALLPLL_LOCKED_MASK			\
+	(CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED)
+
+#define CLKMGR_INTER_MAINPLLLOCKED_MASK			BIT(0)
+#define CLKMGR_INTER_PERPLLLOCKED_MASK			BIT(1)
+#define CLKMGR_INTER_MAINPLLLOST_MASK			BIT(2)
+#define CLKMGR_INTER_PERPLLLOST_MASK			BIT(3)
+
+#define CLKMGR_CLKSRC_MASK				GENMASK(18, 16)
+#define CLKMGR_CLKSRC_OFFSET				16
+#define CLKMGR_CLKSRC_MAIN				0
+#define CLKMGR_CLKSRC_PER				1
+#define CLKMGR_CLKSRC_OSC1				2
+#define CLKMGR_CLKSRC_INTOSC				3
+#define CLKMGR_CLKSRC_FPGA				4
+#define CLKMGR_CLKCNT_MSK				GENMASK(10, 0)
+
+#define CLKMGR_BYPASS_MAINPLL_ALL			0x7
+#define CLKMGR_BYPASS_PERPLL_ALL			0x7f
+
+#define CLKMGR_NOCDIV_L4MAIN_OFFSET			0
+#define CLKMGR_NOCDIV_L4MPCLK_OFFSET			8
+#define CLKMGR_NOCDIV_L4SPCLK_OFFSET			16
+#define CLKMGR_NOCDIV_CSATCLK_OFFSET			24
+#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET			26
+#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET			28
+#define CLKMGR_NOCDIV_DIVIDER_MASK			0x3
+
+#define CLKMGR_PLLGLOB_VCO_PSRC_MASK			GENMASK(17, 16)
+#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET			16
+#define CLKMGR_PLLGLOB_LOSTLOCK_BYPASS_EN_MASK		BIT(28)
+#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK		BIT(29)
+
+#define CLKMGR_VCO_PSRC_EOSC1				0
+#define CLKMGR_VCO_PSRC_INTOSC				1
+#define CLKMGR_VCO_PSRC_F2S				2
+
+#define CLKMGR_PLLCTRL_BYPASS_MASK			BIT(0)
+#define CLKMGR_PLLCTRL_RST_N_MASK			BIT(1)
+
+#define CLKMGR_PLLDIV_REFCLKDIV_MASK			GENMASK(5, 0)
+#define CLKMGR_PLLDIV_FDIV_MASK				GENMASK(16, 8)
+#define CLKMGR_PLLDIV_OUTDIV_QDIV_MASK			GENMASK(26, 24)
+#define CLKMGR_PLLDIV_RANGE_MASK			GENMASK(30, 28)
+
+#define CLKMGR_PLLDIV_REFCLKDIV_OFFSET			0
+#define CLKMGR_PLLDIV_FDIV_OFFSET			8
+#define CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET		24
+#define CLKMGR_PLLDIV_RANGE_OFFSET			28
+
+#define CLKMGR_PLLOUTDIV_C0CNT_MASK			GENMASK(4, 0)
+#define CLKMGR_PLLOUTDIV_C1CNT_MASK			GENMASK(12, 8)
+#define CLKMGR_PLLOUTDIV_C2CNT_MASK			GENMASK(20, 16)
+#define CLKMGR_PLLOUTDIV_C3CNT_MASK			GENMASK(28, 24)
+
+#define CLKMGR_PLLOUTDIV_C0CNT_OFFSET			0
+#define CLKMGR_PLLOUTDIV_C1CNT_OFFSET			8
+#define CLKMGR_PLLOUTDIV_C2CNT_OFFSET			16
+#define CLKMGR_PLLOUTDIV_C3CNT_OFFSET			24
+
+#define CLKMGR_PLLCX_EN_SET_MSK				BIT(27)
+#define CLKMGR_PLLCX_MUTE_SET_MSK			BIT(28)
+
+#define CLKMGR_VCOCALIB_MSCNT_MASK			GENMASK(23, 16)
+#define CLKMGR_VCOCALIB_MSCNT_OFFSET			16
+#define CLKMGR_VCOCALIB_HSCNT_MASK			GENMASK(9, 0)
+#define CLKMGR_VCOCALIB_MSCNT_CONST			100
+#define CLKMGR_VCOCALIB_HSCNT_CONST			4
+
+#define CLKMGR_PLLM_MDIV_MASK				GENMASK(9, 0)
+
+#define CLKMGR_LOSTLOCK_SET_MASK			BIT(0)
+
+#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK		BIT(5)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET	26
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK		BIT(26)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET	27
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK		BIT(27)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET	28
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK		BIT(28)
+
+#define CLKMGR_ALT_EMACCTR_SRC_OFFSET			16
+#define CLKMGR_ALT_EMACCTR_SRC_MASK			GENMASK(18, 16)
+#define CLKMGR_ALT_EMACCTR_CNT_OFFSET			0
+#define CLKMGR_ALT_EMACCTR_CNT_MASK			GENMASK(10, 0)
+
+#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK		GENMASK(15, 0)
+
+#endif /* _CLK_N5X_ */
diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile
index 39dfee5..9fa5d85 100644
--- a/drivers/ddr/altera/Makefile
+++ b/drivers/ddr/altera/Makefile
@@ -4,11 +4,12 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # (C) Copyright 2010, Thomas Chou <thomas@wytron.com.tw>
-# Copyright (C) 2014 Altera Corporation <www.altera.com>
+# Copyright (C) 2014-2021 Altera Corporation <www.altera.com>
 
 ifdef CONFIG_$(SPL_)ALTERA_SDRAM
 obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_gen5.o sequencer.o
 obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_arria10.o
 obj-$(CONFIG_TARGET_SOCFPGA_STRATIX10) += sdram_soc64.o sdram_s10.o
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += sdram_soc64.o sdram_agilex.o
+obj-$(CONFIG_TARGET_SOCFPGA_N5X) += sdram_soc64.o sdram_n5x.o
 endif
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
new file mode 100644
index 0000000..ac13ac4
--- /dev/null
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -0,0 +1,2298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <hang.h>
+#include <ram.h>
+#include <reset.h>
+#include "sdram_soc64.h"
+#include <wait_bit.h>
+#include <asm/arch/firewall.h>
+#include <asm/arch/handoff_soc64.h>
+#include <asm/arch/misc.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/io.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* MPFE NOC registers */
+#define FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0	0xF8024050
+
+/* Memory reset manager */
+#define MEM_RST_MGR_STATUS	0x8
+
+/* Register and bit in memory reset manager */
+#define MEM_RST_MGR_STATUS_RESET_COMPLETE	BIT(0)
+#define MEM_RST_MGR_STATUS_PWROKIN_STATUS	BIT(1)
+#define MEM_RST_MGR_STATUS_CONTROLLER_RST	BIT(2)
+#define MEM_RST_MGR_STATUS_AXI_RST		BIT(3)
+
+#define TIMEOUT_200MS     200
+#define TIMEOUT_5000MS    5000
+
+/* DDR4 umctl2 */
+#define DDR4_MSTR_OFFSET		0x0
+#define DDR4_FREQ_RATIO			BIT(22)
+
+#define DDR4_STAT_OFFSET		0x4
+#define DDR4_STAT_SELFREF_TYPE		GENMASK(5, 4)
+#define DDR4_STAT_SELFREF_TYPE_SHIFT	4
+#define DDR4_STAT_OPERATING_MODE	GENMASK(2, 0)
+
+#define DDR4_MRCTRL0_OFFSET		0x10
+#define DDR4_MRCTRL0_MR_TYPE		BIT(0)
+#define DDR4_MRCTRL0_MPR_EN		BIT(1)
+#define DDR4_MRCTRL0_MR_RANK		GENMASK(5, 4)
+#define DDR4_MRCTRL0_MR_RANK_SHIFT	4
+#define DDR4_MRCTRL0_MR_ADDR		GENMASK(15, 12)
+#define DDR4_MRCTRL0_MR_ADDR_SHIFT	12
+#define DDR4_MRCTRL0_MR_WR		BIT(31)
+
+#define DDR4_MRCTRL1_OFFSET		0x14
+#define DDR4_MRCTRL1_MR_DATA		0x3FFFF
+
+#define DDR4_MRSTAT_OFFSET		0x18
+#define DDR4_MRSTAT_MR_WR_BUSY		BIT(0)
+
+#define DDR4_MRCTRL2_OFFSET		0x1C
+
+#define DDR4_PWRCTL_OFFSET			0x30
+#define DDR4_PWRCTL_SELFREF_EN			BIT(0)
+#define DDR4_PWRCTL_POWERDOWN_EN		BIT(1)
+#define DDR4_PWRCTL_EN_DFI_DRAM_CLK_DISABLE	BIT(3)
+#define DDR4_PWRCTL_SELFREF_SW			BIT(5)
+
+#define DDR4_PWRTMG_OFFSET		0x34
+#define DDR4_HWLPCTL_OFFSET		0x38
+#define DDR4_RFSHCTL0_OFFSET		0x50
+#define DDR4_RFSHCTL1_OFFSET		0x54
+
+#define DDR4_RFSHCTL3_OFFSET			0x60
+#define DDR4_RFSHCTL3_DIS_AUTO_REFRESH		BIT(0)
+#define DDR4_RFSHCTL3_REFRESH_MODE		GENMASK(6, 4)
+#define DDR4_RFSHCTL3_REFRESH_MODE_SHIFT	4
+
+#define DDR4_ECCCFG0_OFFSET		0x70
+#define DDR4_ECC_MODE			GENMASK(2, 0)
+#define DDR4_DIS_SCRUB			BIT(4)
+#define LPDDR4_ECCCFG0_ECC_REGION_MAP_GRANU_SHIFT	30
+#define LPDDR4_ECCCFG0_ECC_REGION_MAP_SHIFT	8
+
+#define DDR4_ECCCFG1_OFFSET		0x74
+#define LPDDR4_ECCCFG1_ECC_REGIONS_PARITY_LOCK	BIT(4)
+
+#define DDR4_CRCPARCTL0_OFFSET			0xC0
+#define DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR	BIT(1)
+
+#define DDR4_CRCPARCTL1_OFFSET			0xC4
+#define DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE	BIT(8)
+#define DDR4_CRCPARCTL1_ALERT_WAIT_FOR_SW	BIT(9)
+
+#define DDR4_CRCPARSTAT_OFFSET			0xCC
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_INT	BIT(16)
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_FATL_INT	BIT(17)
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_NO_SW	BIT(19)
+#define DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW	BIT(29)
+
+#define DDR4_INIT0_OFFSET			0xD0
+#define DDR4_INIT0_SKIP_RAM_INIT		GENMASK(31, 30)
+
+#define DDR4_RANKCTL_OFFSET			0xF4
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP		GENMASK(7, 4)
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP		GENMASK(11, 8)
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB	BIT(24)
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB	BIT(26)
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_SHIFT	4
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_SHIFT	8
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB_SHIFT	24
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB_SHIFT	26
+
+#define DDR4_RANKCTL1_OFFSET	0xF8
+#define DDR4_RANKCTL1_WR2RD_DR	GENMASK(5, 0)
+
+#define DDR4_DRAMTMG2_OFFSET	0x108
+#define DDR4_DRAMTMG2_WR2RD	GENMASK(5, 0)
+#define DDR4_DRAMTMG2_RD2WR	GENMASK(13, 8)
+#define DDR4_DRAMTMG2_RD2WR_SHIFT	8
+
+#define DDR4_DRAMTMG9_OFFSET	0x124
+#define DDR4_DRAMTMG9_W2RD_S	GENMASK(5, 0)
+
+#define DDR4_DFITMG1_OFFSET	0x194
+#define DDR4_DFITMG1_DFI_T_WRDATA_DELAY	GENMASK(20, 16)
+#define DDR4_DFITMG1_DFI_T_WRDATA_SHIFT	16
+
+#define DDR4_DFIMISC_OFFSET			0x1B0
+#define DDR4_DFIMISC_DFI_INIT_COMPLETE_EN	BIT(0)
+#define DDR4_DFIMISC_DFI_INIT_START		BIT(5)
+
+#define DDR4_DFISTAT_OFFSET		0x1BC
+#define DDR4_DFI_INIT_COMPLETE		BIT(0)
+
+#define DDR4_DBG0_OFFSET		0x300
+
+#define DDR4_DBG1_OFFSET		0x304
+#define DDR4_DBG1_DISDQ			BIT(0)
+#define DDR4_DBG1_DIS_HIF		BIT(1)
+
+#define DDR4_DBGCAM_OFFSET			0x308
+#define DDR4_DBGCAM_DBG_RD_Q_EMPTY		BIT(25)
+#define DDR4_DBGCAM_DBG_WR_Q_EMPTY		BIT(26)
+#define DDR4_DBGCAM_RD_DATA_PIPELINE_EMPTY	BIT(28)
+#define DDR4_DBGCAM_WR_DATA_PIPELINE_EMPTY	BIT(29)
+
+#define DDR4_SWCTL_OFFSET		0x320
+#define DDR4_SWCTL_SW_DONE		BIT(0)
+
+#define DDR4_SWSTAT_OFFSET		0x324
+#define DDR4_SWSTAT_SW_DONE_ACK		BIT(0)
+
+#define DDR4_PSTAT_OFFSET		0x3FC
+#define DDR4_PSTAT_RD_PORT_BUSY_0	BIT(0)
+#define DDR4_PSTAT_WR_PORT_BUSY_0	BIT(16)
+
+#define DDR4_PCTRL0_OFFSET		0x490
+#define DDR4_PCTRL0_PORT_EN		BIT(0)
+
+#define DDR4_SBRCTL_OFFSET		0xF24
+#define DDR4_SBRCTL_SCRUB_INTERVAL	0x1FFF00
+#define DDR4_SBRCTL_SCRUB_EN		BIT(0)
+#define DDR4_SBRCTL_SCRUB_WRITE		BIT(2)
+#define DDR4_SBRCTL_SCRUB_BURST_1	BIT(4)
+
+#define DDR4_SBRSTAT_OFFSET		0xF28
+#define DDR4_SBRSTAT_SCRUB_BUSY BIT(0)
+#define DDR4_SBRSTAT_SCRUB_DONE BIT(1)
+
+#define DDR4_SBRWDATA0_OFFSET		0xF2C
+#define DDR4_SBRWDATA1_OFFSET		0xF30
+#define DDR4_SBRSTART0_OFFSET		0xF38
+#define DDR4_SBRSTART1_OFFSET		0xF3C
+#define DDR4_SBRRANGE0_OFFSET		0xF40
+#define DDR4_SBRRANGE1_OFFSET		0xF44
+
+/* DDR PHY */
+#define DDR_PHY_TXODTDRVSTREN_B0_P0		0x2009A
+#define DDR_PHY_RXPBDLYTG0_R0			0x200D0
+#define DDR_PHY_DBYTE0_TXDQDLYTG0_U0_P0		0x201A0
+
+#define DDR_PHY_DBYTE0_TXDQDLYTG0_U1_P0		0x203A0
+#define DDR_PHY_DBYTE1_TXDQDLYTG0_U0_P0		0x221A0
+#define DDR_PHY_DBYTE1_TXDQDLYTG0_U1_P0		0x223A0
+#define DDR_PHY_TXDQDLYTG0_COARSE_DELAY		GENMASK(9, 6)
+#define DDR_PHY_TXDQDLYTG0_COARSE_DELAY_SHIFT	6
+
+#define DDR_PHY_CALRATE_OFFSET			0x40110
+#define DDR_PHY_CALZAP_OFFSET			0x40112
+#define DDR_PHY_SEQ0BDLY0_P0_OFFSET		0x40016
+#define DDR_PHY_SEQ0BDLY1_P0_OFFSET		0x40018
+#define DDR_PHY_SEQ0BDLY2_P0_OFFSET		0x4001A
+#define DDR_PHY_SEQ0BDLY3_P0_OFFSET		0x4001C
+
+#define DDR_PHY_MEMRESETL_OFFSET		0x400C0
+#define DDR_PHY_MEMRESETL_VALUE			BIT(0)
+#define DDR_PHY_PROTECT_MEMRESET		BIT(1)
+
+#define DDR_PHY_CALBUSY_OFFSET			0x4012E
+#define DDR_PHY_CALBUSY				BIT(0)
+
+#define DDR_PHY_TRAIN_IMEM_OFFSET		0xA0000
+#define DDR_PHY_TRAIN_DMEM_OFFSET		0xA8000
+
+#define DMEM_MB_CDD_RR_1_0_OFFSET		0xA802C
+#define DMEM_MB_CDD_RR_0_1_OFFSET		0xA8030
+#define DMEM_MB_CDD_WW_1_0_OFFSET		0xA8038
+#define DMEM_MB_CDD_WW_0_1_OFFSET		0xA803C
+#define DMEM_MB_CDD_RW_1_1_OFFSET		0xA8046
+#define DMEM_MB_CDD_RW_1_0_OFFSET		0xA8048
+#define DMEM_MB_CDD_RW_0_1_OFFSET		0xA804A
+#define DMEM_MB_CDD_RW_0_0_OFFSET		0xA804C
+
+#define DMEM_MB_CDD_CHA_RR_1_0_OFFSET		0xA8026
+#define DMEM_MB_CDD_CHA_RR_0_1_OFFSET		0xA8026
+#define DMEM_MB_CDD_CHB_RR_1_0_OFFSET		0xA8058
+#define DMEM_MB_CDD_CHB_RR_0_1_OFFSET		0xA805A
+#define DMEM_MB_CDD_CHA_WW_1_0_OFFSET		0xA8030
+#define DMEM_MB_CDD_CHA_WW_0_1_OFFSET		0xA8030
+#define DMEM_MB_CDD_CHB_WW_1_0_OFFSET		0xA8062
+#define DMEM_MB_CDD_CHB_WW_0_1_OFFSET		0xA8064
+
+#define DMEM_MB_CDD_CHA_RW_1_1_OFFSET		0xA8028
+#define DMEM_MB_CDD_CHA_RW_1_0_OFFSET		0xA8028
+#define DMEM_MB_CDD_CHA_RW_0_1_OFFSET		0xA802A
+#define DMEM_MB_CDD_CHA_RW_0_0_OFFSET		0xA802A
+
+#define DMEM_MB_CDD_CHB_RW_1_1_OFFSET		0xA805A
+#define DMEM_MB_CDD_CHB_RW_1_0_OFFSET		0xA805C
+#define DMEM_MB_CDD_CHB_RW_0_1_OFFSET		0xA805c
+#define DMEM_MB_CDD_CHB_RW_0_0_OFFSET		0xA805E
+
+#define DDR_PHY_SEQ0DISABLEFLAG0_OFFSET		0x120018
+#define DDR_PHY_SEQ0DISABLEFLAG1_OFFSET		0x12001A
+#define DDR_PHY_SEQ0DISABLEFLAG2_OFFSET		0x12001C
+#define DDR_PHY_SEQ0DISABLEFLAG3_OFFSET		0x12001E
+#define DDR_PHY_SEQ0DISABLEFLAG4_OFFSET		0x120020
+#define DDR_PHY_SEQ0DISABLEFLAG5_OFFSET		0x120022
+#define DDR_PHY_SEQ0DISABLEFLAG6_OFFSET		0x120024
+#define DDR_PHY_SEQ0DISABLEFLAG7_OFFSET		0x120026
+
+#define DDR_PHY_UCCLKHCLKENABLES_OFFSET		0x180100
+#define DDR_PHY_UCCLKHCLKENABLES_UCCLKEN	BIT(0)
+#define DDR_PHY_UCCLKHCLKENABLES_HCLKEN		BIT(1)
+
+#define DDR_PHY_UCTWRITEPROT_OFFSET		0x180066
+#define DDR_PHY_UCTWRITEPROT			BIT(0)
+
+#define DDR_PHY_APBONLY0_OFFSET			0x1A0000
+#define DDR_PHY_MICROCONTMUXSEL			BIT(0)
+
+#define DDR_PHY_UCTSHADOWREGS_OFFSET			0x1A0008
+#define DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW	BIT(0)
+
+#define DDR_PHY_DCTWRITEPROT_OFFSET		0x1A0062
+#define DDR_PHY_DCTWRITEPROT			BIT(0)
+
+#define DDR_PHY_UCTWRITEONLYSHADOW_OFFSET	0x1A0064
+#define DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET	0x1A0068
+
+#define DDR_PHY_MICRORESET_OFFSET		0x1A0132
+#define DDR_PHY_MICRORESET_STALL		BIT(0)
+#define DDR_PHY_MICRORESET_RESET		BIT(3)
+
+#define DDR_PHY_TXODTDRVSTREN_B0_P1		0x22009A
+
+/* For firmware training */
+#define HW_DBG_TRACE_CONTROL_OFFSET	0x18
+#define FW_TRAINING_COMPLETED_STAT	0x07
+#define FW_TRAINING_FAILED_STAT		0xFF
+#define FW_COMPLETION_MSG_ONLY_MODE	0xFF
+#define FW_STREAMING_MSG_ID		0x08
+#define GET_LOWHW_DATA(x)		((x) & 0xFFFF)
+#define GET_LOWB_DATA(x)		((x) & 0xFF)
+#define GET_HIGHB_DATA(x)		(((x) & 0xFF00) >> 8)
+
+/* Operating mode */
+#define OPM_INIT			0x000
+#define OPM_NORMAL			0x001
+#define OPM_PWR_D0WN			0x010
+#define OPM_SELF_SELFREF		0x011
+#define OPM_DDR4_DEEP_PWR_DOWN		0x100
+
+/* Refresh mode */
+#define FIXED_1X		0
+#define FIXED_2X		BIT(0)
+#define FIXED_4X		BIT(4)
+
+/* Address of mode register */
+#define MR0	0x0000
+#define MR1	0x0001
+#define MR2	0x0010
+#define MR3	0x0011
+#define MR4	0x0100
+#define MR5	0x0101
+#define MR6	0x0110
+#define MR7	0x0111
+
+/* MR rank */
+#define RANK0		0x1
+#define RANK1		0x2
+#define ALL_RANK	0x3
+
+#define MR5_BIT4	BIT(4)
+
+/* Value for ecc_region_map */
+#define ALL_PROTECTED	0x7F
+
+/* Region size for ECCCFG0.ecc_region_map */
+enum region_size {
+	ONE_EIGHT,
+	ONE_SIXTEENTH,
+	ONE_THIRTY_SECOND,
+	ONE_SIXTY_FOURTH
+};
+
+enum ddr_type {
+	DDRTYPE_LPDDR4_0,
+	DDRTYPE_LPDDR4_1,
+	DDRTYPE_DDR4,
+	DDRTYPE_UNKNOWN
+};
+
+/* Reset type */
+enum reset_type {
+	POR_RESET,
+	WARM_RESET,
+	COLD_RESET
+};
+
+/* DDR handoff structure */
+struct ddr_handoff {
+	/* Memory reset manager base */
+	phys_addr_t mem_reset_base;
+
+	/* First controller attributes */
+	phys_addr_t cntlr_handoff_base;
+	phys_addr_t cntlr_base;
+	size_t cntlr_total_length;
+	enum ddr_type cntlr_t;
+	size_t cntlr_handoff_length;
+
+	/* Second controller attributes*/
+	phys_addr_t cntlr2_handoff_base;
+	phys_addr_t cntlr2_base;
+	size_t cntlr2_total_length;
+	enum ddr_type cntlr2_t;
+	size_t cntlr2_handoff_length;
+
+	/* PHY attributes */
+	phys_addr_t phy_handoff_base;
+	phys_addr_t phy_base;
+	size_t phy_total_length;
+	size_t phy_handoff_length;
+
+	/* PHY engine attributes */
+	phys_addr_t phy_engine_handoff_base;
+	size_t phy_engine_total_length;
+	size_t phy_engine_handoff_length;
+
+	/* Calibration attributes */
+	phys_addr_t train_imem_base;
+	phys_addr_t train_dmem_base;
+	size_t train_imem_length;
+	size_t train_dmem_length;
+};
+
+/* Message mode */
+enum message_mode {
+	MAJOR_MESSAGE,
+	STREAMING_MESSAGE
+};
+
+static int clr_ca_parity_error_status(phys_addr_t umctl2_base)
+{
+	int ret;
+
+	debug("%s: Clear C/A parity error status in MR5[4]\n", __func__);
+
+	/* Set mode register MRS */
+	clrbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MPR_EN);
+
+	/* Set mode register to write operation */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MR_TYPE);
+
+	/* Set the address of mode rgister to 0x101(MR5) */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     (MR5 << DDR4_MRCTRL0_MR_ADDR_SHIFT) &
+		     DDR4_MRCTRL0_MR_ADDR);
+
+	/* Set MR rank to rank 1 */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     (RANK1 << DDR4_MRCTRL0_MR_RANK_SHIFT) &
+		     DDR4_MRCTRL0_MR_RANK);
+
+	/* Clear C/A parity error status in MR5[4] */
+	clrbits_le32(umctl2_base + DDR4_MRCTRL1_OFFSET, MR5_BIT4);
+
+	/* Trigger mode register read or write operation */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MR_WR);
+
+	/* Wait for retry done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_MRSTAT_OFFSET), DDR4_MRSTAT_MR_WR_BUSY,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" no outstanding MR transaction\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ddr_retry_software_sequence(phys_addr_t umctl2_base)
+{
+	u32 value;
+	int ret;
+
+	/* Check software can perform MRS/MPR/PDA? */
+	value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+		      DDR4_CRCPARSTAT_DFI_ALERT_ERR_NO_SW;
+
+	if (value) {
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(umctl2_base + DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+	}
+
+	debug("%s: Software can perform MRS/MPR/PDA\n", __func__);
+
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_MRSTAT_OFFSET),
+				DDR4_MRSTAT_MR_WR_BUSY,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" no outstanding MR transaction\n");
+		return ret;
+	}
+
+	ret = clr_ca_parity_error_status(umctl2_base);
+	if (ret)
+		return ret;
+
+	if (!value) {
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(umctl2_base + DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+	}
+
+	return 0;
+}
+
+static int ensure_retry_procedure_complete(phys_addr_t umctl2_base)
+{
+	u32 value;
+	u32 start = get_timer(0);
+	int ret;
+
+	/* Check parity/crc/error window is emptied ? */
+	value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+		      DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW;
+
+	/* Polling until parity/crc/error window is emptied */
+	while (value) {
+		if (get_timer(start) > TIMEOUT_200MS) {
+			debug("%s: Timeout while waiting for",
+			      __func__);
+			debug(" parity/crc/error window empty\n");
+			return -ETIMEDOUT;
+		}
+
+		/* Check software intervention is enabled? */
+		value = readl(umctl2_base + DDR4_CRCPARCTL1_OFFSET) &
+			      DDR4_CRCPARCTL1_ALERT_WAIT_FOR_SW;
+		if (value) {
+			debug("%s: Software intervention is enabled\n",
+			      __func__);
+
+			/* Check dfi alert error interrupt is set? */
+			value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+				      DDR4_CRCPARSTAT_DFI_ALERT_ERR_INT;
+
+			if (value) {
+				ret = ddr_retry_software_sequence(umctl2_base);
+				debug("%s: DFI alert error interrupt ",
+				      __func__);
+				debug("is set\n");
+
+				if (ret)
+					return ret;
+			}
+
+			/*
+			 * Check fatal parity error interrupt is set?
+			 */
+			value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+				      DDR4_CRCPARSTAT_DFI_ALERT_ERR_FATL_INT;
+			if (value) {
+				printf("%s: Fatal parity error  ",
+				       __func__);
+				printf("interrupt is set, Hang it!!\n");
+				hang();
+			}
+		}
+
+		value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+			      DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW;
+
+		udelay(1);
+		WATCHDOG_RESET();
+	}
+
+	return 0;
+}
+
+static int enable_quasi_dynamic_reg_grp3(phys_addr_t umctl2_base,
+					 enum ddr_type umctl2_type)
+{
+	u32 i, value, backup;
+	int ret = 0;
+
+	/* Disable input traffic per port */
+	clrbits_le32(umctl2_base + DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+
+	/* Polling AXI port until idle */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_PSTAT_OFFSET),
+				DDR4_PSTAT_WR_PORT_BUSY_0 |
+				DDR4_PSTAT_RD_PORT_BUSY_0, false,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" controller idle\n");
+		return ret;
+	}
+
+	/* Backup user setting */
+	backup = readl(umctl2_base + DDR4_DBG1_OFFSET);
+
+	/* Disable input traffic to the controller */
+	setbits_le32(umctl2_base + DDR4_DBG1_OFFSET, DDR4_DBG1_DIS_HIF);
+
+	/*
+	 * Ensure CAM/data pipelines are empty.
+	 * Poll until CAM/data pipelines are set at least twice,
+	 * timeout at 200ms
+	 */
+	for (i = 0; i < 2; i++) {
+		ret = wait_for_bit_le32((const void *)(umctl2_base +
+					DDR4_DBGCAM_OFFSET),
+					DDR4_DBGCAM_WR_DATA_PIPELINE_EMPTY |
+					DDR4_DBGCAM_RD_DATA_PIPELINE_EMPTY |
+					DDR4_DBGCAM_DBG_WR_Q_EMPTY |
+					DDR4_DBGCAM_DBG_RD_Q_EMPTY, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: loop(%u): Timeout while waiting for",
+			      __func__, i + 1);
+			debug(" CAM/data pipelines are empty\n");
+
+			goto out;
+		}
+	}
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		/* Check DDR4 retry is enabled ? */
+		value = readl(umctl2_base + DDR4_CRCPARCTL1_OFFSET) &
+			      DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE;
+
+		if (value) {
+			debug("%s: DDR4 retry is enabled\n", __func__);
+
+			ret = ensure_retry_procedure_complete(umctl2_base);
+			if (ret) {
+				debug("%s: Timeout while waiting for",
+				      __func__);
+				debug(" retry procedure complete\n");
+
+				goto out;
+			}
+		}
+	}
+
+	debug("%s: Quasi-dynamic group 3 registers are enabled\n", __func__);
+
+out:
+	/* Restore user setting */
+	writel(backup, umctl2_base + DDR4_DBG1_OFFSET);
+
+	return ret;
+}
+
+static enum ddr_type get_ddr_type(phys_addr_t ddr_type_location)
+{
+	u32 ddr_type_magic = readl(ddr_type_location);
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_DDR4_TYPE)
+		return DDRTYPE_DDR4;
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_0_TYPE)
+		return DDRTYPE_LPDDR4_0;
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_1_TYPE)
+		return DDRTYPE_LPDDR4_1;
+
+	return DDRTYPE_UNKNOWN;
+}
+
+static void use_lpddr4_interleaving(bool set)
+{
+	if (set) {
+		printf("Starting LPDDR4 interleaving configuration ...\n");
+		setbits_le32(FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0,
+			     BIT(5));
+	} else {
+		printf("Starting LPDDR4 non-interleaving configuration ...\n");
+		clrbits_le32(FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0,
+			     BIT(5));
+	}
+}
+
+static void use_ddr4(enum ddr_type type)
+{
+	if (type == DDRTYPE_DDR4) {
+		printf("Starting DDR4 configuration ...\n");
+		setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DDR_MODE,
+			     SYSMGR_SOC64_DDR_MODE_MSK);
+	} else if (type == DDRTYPE_LPDDR4_0)  {
+		printf("Starting LPDDR4 configuration ...\n");
+		clrbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DDR_MODE,
+			     SYSMGR_SOC64_DDR_MODE_MSK);
+
+		use_lpddr4_interleaving(false);
+	}
+}
+
+static int scrubber_ddr_config(phys_addr_t umctl2_base,
+			       enum ddr_type umctl2_type)
+{
+	u32 backup[9];
+	int ret;
+
+	/* Reset to default value, prevent scrubber stop due to lower power */
+	writel(0, umctl2_base + DDR4_PWRCTL_OFFSET);
+
+	/* Backup user settings */
+	backup[0] = readl(umctl2_base + DDR4_SBRCTL_OFFSET);
+	backup[1] = readl(umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	backup[2] = readl(umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		backup[3] = readl(umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		backup[4] = readl(umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	backup[5] = readl(umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	backup[6] = readl(umctl2_base + DDR4_SBRRANGE1_OFFSET);
+	backup[7] = readl(umctl2_base + DDR4_ECCCFG0_OFFSET);
+	backup[8] = readl(umctl2_base + DDR4_ECCCFG1_OFFSET);
+
+	if (umctl2_type != DDRTYPE_DDR4) {
+		/* Lock ECC region, ensure this regions is not being accessed */
+		setbits_le32(umctl2_base + DDR4_ECCCFG1_OFFSET,
+			     LPDDR4_ECCCFG1_ECC_REGIONS_PARITY_LOCK);
+	}
+	/* Disable input traffic per port */
+	clrbits_le32(umctl2_base + DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+	/* Disables scrubber */
+	clrbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+	/* Polling all scrub writes data have been sent */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_BUSY,
+				false, TIMEOUT_5000MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" sending all scrub data\n");
+		return ret;
+	}
+
+	/* LPDDR4 supports inline ECC only */
+	if (umctl2_type != DDRTYPE_DDR4) {
+		/*
+		 * Setting all regions for protected, this is required for
+		 * srubber to init whole LPDDR4 expect ECC region
+		 */
+		writel(((ONE_EIGHT <<
+		       LPDDR4_ECCCFG0_ECC_REGION_MAP_GRANU_SHIFT) |
+		       (ALL_PROTECTED << LPDDR4_ECCCFG0_ECC_REGION_MAP_SHIFT)),
+		       umctl2_base + DDR4_ECCCFG0_OFFSET);
+	}
+
+	/* Scrub_burst = 1, scrub_mode = 1(performs writes) */
+	writel(DDR4_SBRCTL_SCRUB_BURST_1 | DDR4_SBRCTL_SCRUB_WRITE,
+	       umctl2_base + DDR4_SBRCTL_OFFSET);
+
+	/* Zeroing whole DDR */
+	writel(0, umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	writel(0, umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		writel(0, umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		writel(0, umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	writel(0, umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	writel(0, umctl2_base + DDR4_SBRRANGE1_OFFSET);
+
+	/* Enables scrubber */
+	setbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+	/* Polling all scrub writes commands have been sent */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_DONE,
+				true, TIMEOUT_5000MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" sending all scrub commands\n");
+		return ret;
+	}
+
+	/* Polling all scrub writes data have been sent */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_BUSY,
+				false, TIMEOUT_5000MS, false);
+	if (ret) {
+		printf("%s: Timeout while waiting for", __func__);
+		printf(" sending all scrub data\n");
+		return ret;
+	}
+
+	/* Disables scrubber */
+	clrbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+
+	/* Restore user settings */
+	writel(backup[0], umctl2_base + DDR4_SBRCTL_OFFSET);
+	writel(backup[1], umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	writel(backup[2], umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		writel(backup[3], umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		writel(backup[4], umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	writel(backup[5], umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	writel(backup[6], umctl2_base + DDR4_SBRRANGE1_OFFSET);
+	writel(backup[7], umctl2_base + DDR4_ECCCFG0_OFFSET);
+	writel(backup[8], umctl2_base + DDR4_ECCCFG1_OFFSET);
+
+	/* Enables ECC scrub on scrubber */
+	if (!(readl(umctl2_base + DDR4_SBRCTL_OFFSET) &
+	    DDR4_SBRCTL_SCRUB_WRITE)) {
+		/* Enables scrubber */
+		setbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET,
+			     DDR4_SBRCTL_SCRUB_EN);
+	}
+
+	return 0;
+}
+
+static void handoff_process(struct ddr_handoff *ddr_handoff_info,
+			    phys_addr_t handoff_base, size_t length,
+			    phys_addr_t base)
+{
+	u32 handoff_table[length];
+	u32 i, value = 0;
+
+	/* Execute configuration handoff */
+	socfpga_handoff_read((void *)handoff_base, handoff_table, length);
+
+	for (i = 0; i < length; i = i + 2) {
+		debug("%s: wr = 0x%08x ",  __func__, handoff_table[i + 1]);
+		if (ddr_handoff_info && base == ddr_handoff_info->phy_base) {
+			/*
+			 * Convert PHY odd offset to even offset that
+			 * supported by ARM processor.
+			 */
+			value = handoff_table[i] << 1;
+
+			writew(handoff_table[i + 1],
+			       (uintptr_t)(value + base));
+			debug("rd = 0x%08x ",
+			      readw((uintptr_t)(value + base)));
+			debug("PHY offset: 0x%08x ", handoff_table[i + 1]);
+		} else {
+			value = handoff_table[i];
+			writel(handoff_table[i + 1], (uintptr_t)(value +
+			       base));
+			 debug("rd = 0x%08x ",
+			       readl((uintptr_t)(value + base)));
+		}
+
+		debug("Absolute addr: 0x%08llx, APB offset: 0x%08x\n",
+		      value + base, value);
+	}
+}
+
+static int init_umctl2(phys_addr_t umctl2_handoff_base,
+		       phys_addr_t umctl2_base, enum ddr_type umctl2_type,
+		       size_t umctl2_handoff_length,
+		       u32 *user_backup)
+{
+	int ret;
+
+	if (umctl2_type == DDRTYPE_DDR4)
+		printf("Initializing DDR4 controller ...\n");
+	else if (umctl2_type == DDRTYPE_LPDDR4_0)
+		printf("Initializing LPDDR4_0 controller ...\n");
+	else if (umctl2_type == DDRTYPE_LPDDR4_1)
+		printf("Initializing LPDDR4_1 controller ...\n");
+
+	/* Prevent controller from issuing read/write to SDRAM */
+	setbits_le32(umctl2_base + DDR4_DBG1_OFFSET, DDR4_DBG1_DISDQ);
+
+	/* Put SDRAM into self-refresh */
+	setbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_EN);
+
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Ensure the controller is in initialization mode */
+	ret = wait_for_bit_le32((const void *)(umctl2_base + DDR4_STAT_OFFSET),
+				DDR4_STAT_OPERATING_MODE, false, TIMEOUT_200MS,
+				false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" init operating mode\n");
+		return ret;
+	}
+
+	debug("%s: UMCTL2 handoff base address = 0x%p table length = 0x%08x\n",
+	      __func__, (u32 *)umctl2_handoff_base,
+	      (u32)umctl2_handoff_length);
+
+	handoff_process(NULL, umctl2_handoff_base, umctl2_handoff_length,
+			umctl2_base);
+
+	/* Backup user settings, restore after DDR up running */
+	*user_backup = readl(umctl2_base + DDR4_PWRCTL_OFFSET);
+
+	/* Disable self resfresh */
+	clrbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_EN);
+
+	if (umctl2_type == DDRTYPE_LPDDR4_0 ||
+	    umctl2_type == DDRTYPE_LPDDR4_1) {
+		/* Setting selfref_sw to 1, based on lpddr4 requirement */
+		setbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET,
+			     DDR4_PWRCTL_SELFREF_SW);
+
+		/* Backup user settings, restore after DDR up running */
+		user_backup++;
+		*user_backup = readl(umctl2_base + DDR4_INIT0_OFFSET) &
+				     DDR4_INIT0_SKIP_RAM_INIT;
+
+		/*
+		 * Setting INIT0.skip_dram_init to 0x3, based on lpddr4
+		 * requirement
+		 */
+		setbits_le32(umctl2_base + DDR4_INIT0_OFFSET,
+			     DDR4_INIT0_SKIP_RAM_INIT);
+	}
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Enable controller from issuing read/write to SDRAM */
+	clrbits_le32(umctl2_base + DDR4_DBG1_OFFSET, DDR4_DBG1_DISDQ);
+
+	return 0;
+}
+
+static int phy_pre_handoff_config(phys_addr_t umctl2_base,
+				  enum ddr_type umctl2_type)
+{
+	int ret;
+	u32 value;
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		/* Check DDR4 retry is enabled ? */
+		value = readl(umctl2_base + DDR4_CRCPARCTL1_OFFSET) &
+			      DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE;
+
+		if (value) {
+			debug("%s: DDR4 retry is enabled\n", __func__);
+			debug("%s: Disable auto refresh is not supported\n",
+			      __func__);
+		} else {
+			/* Disable auto refresh */
+			setbits_le32(umctl2_base + DDR4_RFSHCTL3_OFFSET,
+				     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+		}
+	}
+
+	/* Disable selfref_en & powerdown_en, nvr disable dfi dram clk */
+	clrbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET,
+		     DDR4_PWRCTL_EN_DFI_DRAM_CLK_DISABLE |
+		     DDR4_PWRCTL_POWERDOWN_EN | DDR4_PWRCTL_SELFREF_EN);
+
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Masking dfi init complete */
+	clrbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SWSTAT_OFFSET), DDR4_SWSTAT_SW_DONE_ACK,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+	}
+
+	return ret;
+}
+
+static int init_phy(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	printf("Initializing DDR PHY ...\n");
+
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4 ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		ret = phy_pre_handoff_config(ddr_handoff_info->cntlr_base,
+					     ddr_handoff_info->cntlr_t);
+		if (ret)
+			return ret;
+	}
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		ret = phy_pre_handoff_config
+			(ddr_handoff_info->cntlr2_base,
+			 ddr_handoff_info->cntlr2_t);
+		if (ret)
+			return ret;
+	}
+
+	/* Execute PHY configuration handoff */
+	handoff_process(ddr_handoff_info, ddr_handoff_info->phy_handoff_base,
+			ddr_handoff_info->phy_handoff_length,
+			ddr_handoff_info->phy_base);
+
+	printf("DDR PHY configuration is completed\n");
+
+	return 0;
+}
+
+static void phy_init_engine(struct ddr_handoff *handoff)
+{
+	printf("Load PHY Init Engine ...\n");
+
+	/* Execute PIE production code handoff */
+	handoff_process(handoff, handoff->phy_engine_handoff_base,
+			handoff->phy_engine_handoff_length, handoff->phy_base);
+
+	printf("End of loading PHY Init Engine\n");
+}
+
+int populate_ddr_handoff(struct ddr_handoff *handoff)
+{
+	phys_addr_t next_section_header;
+
+	/* DDR handoff */
+	handoff->mem_reset_base = SOC64_HANDOFF_DDR_MEMRESET_BASE;
+	debug("%s: DDR memory reset base = 0x%x\n", __func__,
+	      (u32)handoff->mem_reset_base);
+	debug("%s: DDR memory reset address = 0x%x\n", __func__,
+	      readl(handoff->mem_reset_base));
+
+	/* Beginning of DDR controller handoff */
+	handoff->cntlr_handoff_base = SOC64_HANDOFF_DDR_UMCTL2_SECTION;
+	debug("%s: cntlr handoff base = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_handoff_base);
+
+	/* Get 1st DDR type */
+	handoff->cntlr_t = get_ddr_type(handoff->cntlr_handoff_base +
+					SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET);
+	if (handoff->cntlr_t == DDRTYPE_LPDDR4_1 ||
+	    handoff->cntlr_t == DDRTYPE_UNKNOWN) {
+		debug("%s: Wrong DDR handoff format, the 1st DDR ", __func__);
+		debug("type must be DDR4 or LPDDR4_0\n");
+		return -ENOEXEC;
+	}
+
+	/* 1st cntlr base physical address */
+	handoff->cntlr_base = readl(handoff->cntlr_handoff_base +
+				    SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET);
+	debug("%s: cntlr base = 0x%x\n", __func__, (u32)handoff->cntlr_base);
+
+	/* Get the total length of DDR cntlr handoff section */
+	handoff->cntlr_total_length = readl(handoff->cntlr_handoff_base +
+					    SOC64_HANDOFF_OFFSET_LENGTH);
+	debug("%s: Umctl2 total length in byte = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_total_length);
+
+	/* Get the length of user setting data in DDR cntlr handoff section */
+	handoff->cntlr_handoff_length = socfpga_get_handoff_size((void *)
+						handoff->cntlr_handoff_base);
+	debug("%s: Umctl2 handoff length in word(32-bit) = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_handoff_length);
+
+	/* Wrong format on user setting data */
+	if (handoff->cntlr_handoff_length < 0) {
+		debug("%s: Wrong format on user setting data\n", __func__);
+		return -ENOEXEC;
+	}
+
+	/* Get the next handoff section address */
+	next_section_header = handoff->cntlr_handoff_base +
+				handoff->cntlr_total_length;
+	debug("%s: Next handoff section header location = 0x%llx\n", __func__,
+	      next_section_header);
+
+	/*
+	 * Checking next section handoff is cntlr or PHY, and changing
+	 * subsequent implementation accordingly
+	 */
+	if (readl(next_section_header) == SOC64_HANDOFF_DDR_UMCTL2_MAGIC) {
+		/* Get the next cntlr handoff section address */
+		handoff->cntlr2_handoff_base = next_section_header;
+		debug("%s: umctl2 2nd handoff base = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_handoff_base);
+
+		/* Get 2nd DDR type */
+		handoff->cntlr2_t = get_ddr_type(handoff->cntlr2_handoff_base +
+					SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET);
+		if (handoff->cntlr2_t == DDRTYPE_LPDDR4_0 ||
+		    handoff->cntlr2_t == DDRTYPE_UNKNOWN) {
+			debug("%s: Wrong DDR handoff format, the 2nd DDR ",
+			      __func__);
+			debug("type must be LPDDR4_1\n");
+			return -ENOEXEC;
+		}
+
+		/* 2nd umctl2 base physical address */
+		handoff->cntlr2_base =
+			readl(handoff->cntlr2_handoff_base +
+			      SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET);
+		debug("%s: cntlr2 base = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_base);
+
+		/* Get the total length of 2nd DDR umctl2 handoff section */
+		handoff->cntlr2_total_length =
+			readl(handoff->cntlr2_handoff_base +
+			      SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: Umctl2_2nd total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR umctl2 handoff
+		 * section
+		 */
+		handoff->cntlr2_handoff_length =
+			socfpga_get_handoff_size((void *)
+						 handoff->cntlr2_handoff_base);
+		debug("%s: cntlr2 handoff length in word(32-bit) = 0x%x\n",
+		      __func__,
+		     (u32)handoff->cntlr2_handoff_length);
+
+		/* Wrong format on user setting data */
+		if (handoff->cntlr2_handoff_length < 0) {
+			debug("%s: Wrong format on umctl2 user setting data\n",
+			      __func__);
+			return -ENOEXEC;
+		}
+
+		/* Get the next handoff section address */
+		next_section_header = handoff->cntlr2_handoff_base +
+					handoff->cntlr2_total_length;
+		debug("%s: Next handoff section header location = 0x%llx\n",
+		      __func__, next_section_header);
+	}
+
+	/* Checking next section handoff is PHY ? */
+	if (readl(next_section_header) == SOC64_HANDOFF_DDR_PHY_MAGIC) {
+		/* DDR PHY handoff */
+		handoff->phy_handoff_base = next_section_header;
+		debug("%s: PHY handoff base = 0x%x\n", __func__,
+		      (u32)handoff->phy_handoff_base);
+
+		/* PHY base physical address */
+		handoff->phy_base = readl(handoff->phy_handoff_base +
+					SOC64_HANDOFF_DDR_PHY_BASE_OFFSET);
+		debug("%s: PHY base = 0x%x\n", __func__,
+		      (u32)handoff->phy_base);
+
+		/* Get the total length of PHY handoff section */
+		handoff->phy_total_length = readl(handoff->phy_handoff_base +
+						SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: PHY total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->phy_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR PHY handoff
+		 * section
+		 */
+		handoff->phy_handoff_length = socfpga_get_handoff_size((void *)
+						handoff->phy_handoff_base);
+		debug("%s: PHY handoff length in word(32-bit) = 0x%x\n",
+		      __func__, (u32)handoff->phy_handoff_length);
+
+		/* Wrong format on PHY user setting data */
+		if (handoff->phy_handoff_length < 0) {
+			debug("%s: Wrong format on PHY user setting data\n",
+			      __func__);
+			return -ENOEXEC;
+		}
+
+		/* Get the next handoff section address */
+		next_section_header = handoff->phy_handoff_base +
+					handoff->phy_total_length;
+		debug("%s: Next handoff section header location = 0x%llx\n",
+		      __func__, next_section_header);
+	} else {
+		debug("%s: Wrong format for DDR handoff, expect PHY",
+		      __func__);
+		debug(" handoff section after umctl2 handoff section\n");
+		return -ENOEXEC;
+	}
+
+	/* Checking next section handoff is PHY init Engine ? */
+	if (readl(next_section_header) ==
+		SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC) {
+		/* DDR PHY Engine handoff */
+		handoff->phy_engine_handoff_base = next_section_header;
+		debug("%s: PHY init engine handoff base = 0x%x\n", __func__,
+		      (u32)handoff->phy_engine_handoff_base);
+
+		/* Get the total length of PHY init engine handoff section */
+		handoff->phy_engine_total_length =
+				readl(handoff->phy_engine_handoff_base +
+				      SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: PHY engine total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->phy_engine_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR PHY init engine
+		 * handoff section
+		 */
+		handoff->phy_engine_handoff_length =
+			socfpga_get_handoff_size((void *)
+					handoff->phy_engine_handoff_base);
+		debug("%s: PHY engine handoff length in word(32-bit) = 0x%x\n",
+		      __func__, (u32)handoff->phy_engine_handoff_length);
+
+		/* Wrong format on PHY init engine setting data */
+		if (handoff->phy_engine_handoff_length < 0) {
+			debug("%s: Wrong format on PHY init engine ",
+			      __func__);
+			debug("user setting data\n");
+			return -ENOEXEC;
+		}
+	} else {
+		debug("%s: Wrong format for DDR handoff, expect PHY",
+		      __func__);
+		debug(" init engine handoff section after PHY handoff\n");
+		debug(" section\n");
+		return -ENOEXEC;
+	}
+
+	handoff->train_imem_base = handoff->phy_base +
+						DDR_PHY_TRAIN_IMEM_OFFSET;
+	debug("%s: PHY train IMEM base = 0x%x\n",
+	      __func__, (u32)handoff->train_imem_base);
+
+	handoff->train_dmem_base = handoff->phy_base +
+						DDR_PHY_TRAIN_DMEM_OFFSET;
+	debug("%s: PHY train DMEM base = 0x%x\n",
+	      __func__, (u32)handoff->train_dmem_base);
+
+	handoff->train_imem_length = SOC64_HANDOFF_DDR_TRAIN_IMEM_LENGTH;
+	debug("%s: PHY train IMEM length = 0x%x\n",
+	      __func__, (u32)handoff->train_imem_length);
+
+	handoff->train_dmem_length = SOC64_HANDOFF_DDR_TRAIN_DMEM_LENGTH;
+	debug("%s: PHY train DMEM length = 0x%x\n",
+	      __func__, (u32)handoff->train_dmem_length);
+
+	return 0;
+}
+
+int enable_ddr_clock(struct udevice *dev)
+{
+	struct clk *ddr_clk;
+	int ret;
+
+	/* Enable clock before init DDR */
+	ddr_clk = devm_clk_get(dev, "mem_clk");
+	if (!IS_ERR(ddr_clk)) {
+		ret = clk_enable(ddr_clk);
+		if (ret) {
+			printf("%s: Failed to enable DDR clock\n", __func__);
+			return ret;
+		}
+	} else {
+		ret = PTR_ERR(ddr_clk);
+		debug("%s: Failed to get DDR clock from dts\n", __func__);
+		return ret;
+	}
+
+	printf("%s: DDR clock is enabled\n", __func__);
+
+	return 0;
+}
+
+static int ddr_start_dfi_init(phys_addr_t umctl2_base,
+			      enum ddr_type umctl2_type)
+{
+	int ret;
+
+	debug("%s: Start DFI init\n", __func__);
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Start DFI init sequence */
+	setbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_START);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SWSTAT_OFFSET),
+				DDR4_SWSTAT_SW_DONE_ACK, true,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+	}
+
+	return ret;
+}
+
+static int ddr_check_dfi_init_complete(phys_addr_t umctl2_base,
+				       enum ddr_type umctl2_type)
+{
+	int ret;
+
+	/* Polling DFI init complete */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_DFISTAT_OFFSET),
+				DDR4_DFI_INIT_COMPLETE, true,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" DFI init done\n");
+		return ret;
+	}
+
+	debug("%s: DFI init completed.\n", __func__);
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Stop DFI init sequence */
+	clrbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_START);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SWSTAT_OFFSET),
+				DDR4_SWSTAT_SW_DONE_ACK, true,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+		return ret;
+	}
+
+	debug("%s:DDR programming done\n", __func__);
+
+	return ret;
+}
+
+static int ddr_trigger_sdram_init(phys_addr_t umctl2_base,
+				  enum ddr_type umctl2_type)
+{
+	int ret;
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Unmasking dfi init complete */
+	setbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+	/* Software exit from self-refresh */
+	clrbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_SW);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SWSTAT_OFFSET),
+				DDR4_SWSTAT_SW_DONE_ACK, true,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+		return ret;
+	}
+
+	debug("%s:DDR programming done\n", __func__);
+	return ret;
+}
+
+static int ddr_post_handoff_config(phys_addr_t umctl2_base,
+				   enum ddr_type umctl2_type)
+{
+	int ret = 0;
+	u32 value;
+	u32 start = get_timer(0);
+
+	do {
+		if (get_timer(start) > TIMEOUT_200MS) {
+			debug("%s: Timeout while waiting for",
+			      __func__);
+			debug(" DDR enters normal operating mode\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(1);
+		WATCHDOG_RESET();
+
+		/* Polling until SDRAM entered normal operating mode */
+		value = readl(umctl2_base + DDR4_STAT_OFFSET) &
+			      DDR4_STAT_OPERATING_MODE;
+	} while (value != OPM_NORMAL);
+
+	printf("DDR entered normal operating mode\n");
+
+	/* Enabling auto refresh */
+	clrbits_le32(umctl2_base + DDR4_RFSHCTL3_OFFSET,
+		     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+
+	/* Checking ECC is enabled? */
+	value = readl(umctl2_base + DDR4_ECCCFG0_OFFSET) & DDR4_ECC_MODE;
+	if (value) {
+		printf("ECC is enabled\n");
+		ret = scrubber_ddr_config(umctl2_base, umctl2_type);
+		if (ret)
+			printf("Failed to enable ECC\n");
+	}
+
+	return ret;
+}
+
+static int configure_training_firmware(struct ddr_handoff *ddr_handoff_info,
+				       const void *train_imem,
+				       const void *train_dmem)
+{
+	int ret = 0;
+
+	printf("Configuring training firmware ...\n");
+
+	/* Reset SDRAM */
+	writew(DDR_PHY_PROTECT_MEMRESET,
+	       (uintptr_t)(ddr_handoff_info->phy_base +
+	       DDR_PHY_MEMRESETL_OFFSET));
+
+	/* Enable access to the PHY configuration registers */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	/* Copy train IMEM bin */
+	memcpy((void *)ddr_handoff_info->train_imem_base, train_imem,
+	       ddr_handoff_info->train_imem_length);
+
+	ret = memcmp((void *)ddr_handoff_info->train_imem_base, train_imem,
+		     ddr_handoff_info->train_imem_length);
+	if (ret) {
+		debug("%s: Failed to copy train IMEM binary\n", __func__);
+		/* Isolate the APB access from internal CSRs */
+		setbits_le16(ddr_handoff_info->phy_base +
+			     DDR_PHY_APBONLY0_OFFSET, DDR_PHY_MICROCONTMUXSEL);
+		return ret;
+	}
+
+	memcpy((void *)ddr_handoff_info->train_dmem_base, train_dmem,
+	       ddr_handoff_info->train_dmem_length);
+
+	ret = memcmp((void *)ddr_handoff_info->train_dmem_base, train_dmem,
+		     ddr_handoff_info->train_dmem_length);
+	if (ret)
+		debug("%s: Failed to copy train DMEM binary\n", __func__);
+
+	/* Isolate the APB access from internal CSRs */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	return ret;
+}
+
+static void calibrating_sdram(struct ddr_handoff *ddr_handoff_info)
+{
+	/* Init mailbox protocol - set 1 to DCTWRITEPROT[0] */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	/* Init mailbox protocol - set 1 to UCTWRITEPROT[0] */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_UCTWRITEPROT_OFFSET,
+		     DDR_PHY_UCTWRITEPROT);
+
+	/* Reset and stalling ARC processor */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_RESET | DDR_PHY_MICRORESET_STALL);
+
+	/* Release ARC processor */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_RESET);
+
+	/* Starting PHY firmware execution */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_STALL);
+}
+
+static int get_mail(struct ddr_handoff *handoff, enum message_mode mode,
+		    u32 *message_id)
+{
+	int ret;
+
+	/* Polling major messages from PMU */
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" major messages from PMU\n");
+		return ret;
+	}
+
+	*message_id = readw((uintptr_t)(handoff->phy_base +
+			    DDR_PHY_UCTWRITEONLYSHADOW_OFFSET));
+
+	if (mode == STREAMING_MESSAGE)
+		*message_id |= readw((uintptr_t)((handoff->phy_base +
+				     DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET))) <<
+				     SZ_16;
+
+	/* Ack the receipt of the major message */
+	clrbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" ack the receipt of the major message completed\n");
+		return ret;
+	}
+
+	/* Complete protocol */
+	setbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	return ret;
+}
+
+static int get_mail_streaming(struct ddr_handoff *handoff,
+			      enum message_mode mode, u32 *index)
+{
+	int ret;
+
+	*index = readw((uintptr_t)(handoff->phy_base +
+		       DDR_PHY_UCTWRITEONLYSHADOW_OFFSET));
+
+	if (mode == STREAMING_MESSAGE)
+		*index |= readw((uintptr_t)((handoff->phy_base +
+				DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET))) <<
+				SZ_16;
+
+	/* Ack the receipt of the major message */
+	clrbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" ack the receipt of the major message completed\n");
+		return ret;
+	}
+
+	/* Complete protocol */
+	setbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	return 0;
+}
+
+static int decode_streaming_message(struct ddr_handoff *ddr_handoff_info,
+				    u32 *streaming_index)
+{
+	int i = 0, ret;
+	u32 temp;
+
+	temp = *streaming_index;
+
+	while (i < GET_LOWHW_DATA(temp)) {
+		ret = get_mail(ddr_handoff_info, STREAMING_MESSAGE,
+			       streaming_index);
+		if (ret)
+			return ret;
+
+		printf("args[%d]: 0x%x ", i, *streaming_index);
+		i++;
+	}
+
+	return 0;
+}
+
+static int poll_for_training_complete(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+	u32 message_id = 0;
+	u32 streaming_index = 0;
+
+	do {
+		ret = get_mail(ddr_handoff_info, MAJOR_MESSAGE, &message_id);
+		if (ret)
+			return ret;
+
+		 printf("Major message id = 0%x\n", message_id);
+
+		if (message_id == FW_STREAMING_MSG_ID) {
+			ret = get_mail_streaming(ddr_handoff_info,
+						 STREAMING_MESSAGE,
+						 &streaming_index);
+			if (ret)
+				return ret;
+
+			printf("streaming index 0%x : ", streaming_index);
+
+			decode_streaming_message(ddr_handoff_info,
+						 &streaming_index);
+
+			printf("\n");
+		}
+	} while ((message_id != FW_TRAINING_COMPLETED_STAT) &&
+	       (message_id != FW_TRAINING_FAILED_STAT));
+
+	if (message_id == FW_TRAINING_COMPLETED_STAT) {
+		printf("DDR firmware training completed\n");
+	} else if (message_id == FW_TRAINING_FAILED_STAT) {
+		printf("DDR firmware training failed\n");
+		hang();
+	}
+
+	return 0;
+}
+
+static void enable_phy_clk_for_csr_access(struct ddr_handoff *handoff,
+					  bool enable)
+{
+	if (enable) {
+		/* Enable PHY clk */
+		setbits_le16((uintptr_t)(handoff->phy_base +
+			     DDR_PHY_UCCLKHCLKENABLES_OFFSET),
+			     DDR_PHY_UCCLKHCLKENABLES_UCCLKEN |
+			     DDR_PHY_UCCLKHCLKENABLES_HCLKEN);
+	} else {
+		/* Disable PHY clk */
+		clrbits_le16((uintptr_t)(handoff->phy_base +
+			     DDR_PHY_UCCLKHCLKENABLES_OFFSET),
+			     DDR_PHY_UCCLKHCLKENABLES_UCCLKEN |
+			     DDR_PHY_UCCLKHCLKENABLES_HCLKEN);
+	}
+}
+
+/* helper function for updating train result to umctl2 RANKCTL register */
+static void set_cal_res_to_rankctrl(u32 reg_addr, u16 update_value,
+				    u32 mask, u32 msb_mask, u32 shift)
+{
+	u32 reg, value;
+
+	reg = readl((uintptr_t)reg_addr);
+
+	debug("max value divided by 2 is 0x%x\n", update_value);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+
+	value = (reg & mask) >> shift;
+
+	value += update_value + 3;
+
+	/* reg value greater than 0xF, set one to diff_rank_wr_gap_msb */
+	if (value > 0xF)
+		setbits_le32((u32 *)(uintptr_t)reg_addr, msb_mask);
+	else
+		clrbits_le32((u32 *)(uintptr_t)reg_addr, msb_mask);
+
+	reg = readl((uintptr_t)reg_addr);
+
+	value = (value << shift) & mask;
+
+	/* update register */
+	writel((reg & (~mask)) | value, (uintptr_t)reg_addr);
+
+	reg = readl((uintptr_t)reg_addr);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+}
+
+/* helper function for updating train result to register */
+static void set_cal_res_to_reg(u32 reg_addr, u16 update_value, u32 mask,
+			       u32 shift)
+{
+	u32 reg, value;
+
+	reg = readl((uintptr_t)reg_addr);
+
+	debug("max value divided by 2 is 0x%x\n", update_value);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+
+	value = (reg & mask) >> shift;
+
+	value = ((value + update_value + 3) << shift) & mask;
+
+	/* update register */
+	writel((reg & (~mask)) | value, (uintptr_t)reg_addr);
+
+	reg = readl((uintptr_t)reg_addr);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+}
+
+static u16 get_max_txdqsdlytg0_ux_p0(struct ddr_handoff *handoff, u32 reg,
+				     u8 numdbyte, u16 upd_val)
+{
+	u32 b_addr;
+	u16 val;
+	u8 byte;
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_ux_p0 */
+	for (byte = 0; byte < numdbyte; byte++) {
+		b_addr = byte << 13;
+
+		/* TxDqsDlyTg0[9:6] is the coarse delay */
+		val = (readw((uintptr_t)(handoff->phy_base +
+			     reg + b_addr)) &
+			     DDR_PHY_TXDQDLYTG0_COARSE_DELAY) >>
+			     DDR_PHY_TXDQDLYTG0_COARSE_DELAY_SHIFT;
+
+		upd_val = max(val, upd_val);
+	}
+
+	return upd_val;
+}
+
+static int set_cal_res_to_umctl2(struct ddr_handoff *handoff,
+				 phys_addr_t umctl2_base,
+				 enum ddr_type umctl2_type)
+{
+	int ret;
+	u8 numdbyte = 0x8;
+	u16 upd_val, val;
+	u32 dramtmg2_reg_addr, rankctl_reg_addr, reg_addr;
+
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Enable access to the PHY configuration registers */
+	clrbits_le16(handoff->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_WW_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_WW_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_WW_1_0_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_WW_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_WW_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_WW_0_1_OFFSET)));
+	}
+
+	upd_val = max(val, upd_val);
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 RANKCTL.diff_rank_wr_gap\n");
+	rankctl_reg_addr = umctl2_base + DDR4_RANKCTL_OFFSET;
+	/* Update train value to umctl2 RANKCTL.diff_rank_wr_gap */
+	set_cal_res_to_rankctrl(rankctl_reg_addr, upd_val,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP_SHIFT);
+
+	debug("Update train value to umctl2 DRAMTMG2.W2RD\n");
+	dramtmg2_reg_addr = umctl2_base + DDR4_DRAMTMG2_OFFSET;
+	/* Update train value to umctl2 dramtmg2.wr2rd */
+	set_cal_res_to_reg(dramtmg2_reg_addr, upd_val, DDR4_DRAMTMG2_WR2RD, 0);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		debug("Update train value to umctl2 DRAMTMG9.W2RD_S\n");
+		reg_addr = umctl2_base + DDR4_DRAMTMG9_OFFSET;
+		/* Update train value to umctl2 dramtmg9.wr2rd_s */
+		set_cal_res_to_reg(reg_addr, upd_val, DDR4_DRAMTMG9_W2RD_S, 0);
+	}
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RR_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_RR_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RR_1_0_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_RR_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RR_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_RR_0_1_OFFSET)));
+	}
+
+	upd_val = max(val, upd_val);
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 RANKCTL.diff_rank_rd_gap\n");
+	/* Update train value to umctl2 RANKCTL.diff_rank_rd_gap */
+	set_cal_res_to_rankctrl(rankctl_reg_addr, upd_val,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP_SHIFT);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RW_1_1_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RW_1_1_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHA_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RW_1_1_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHB_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	}
+
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 dramtmg2.rd2wr\n");
+	/* Update train value to umctl2 dramtmg2.rd2wr */
+	set_cal_res_to_reg(dramtmg2_reg_addr, upd_val, DDR4_DRAMTMG2_RD2WR,
+			   DDR4_DRAMTMG2_RD2WR_SHIFT);
+
+	/* Checking ECC is enabled?, lpddr4 using inline ECC */
+	val = readl(umctl2_base + DDR4_ECCCFG0_OFFSET) & DDR4_ECC_MODE;
+	if (val && umctl2_type == DDRTYPE_DDR4)
+		numdbyte = 0x9;
+
+	upd_val = 0;
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_u0_p0 */
+	upd_val = get_max_txdqsdlytg0_ux_p0(handoff,
+					    DDR_PHY_DBYTE0_TXDQDLYTG0_U0_P0,
+					    numdbyte, upd_val);
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_u1_p0 */
+	upd_val = get_max_txdqsdlytg0_ux_p0(handoff,
+					    DDR_PHY_DBYTE0_TXDQDLYTG0_U1_P0,
+					    numdbyte, upd_val);
+
+	debug("TxDqsDlyTg0 max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	reg_addr = umctl2_base + DDR4_DFITMG1_OFFSET;
+	/* Update train value to umctl2 dfitmg1.dfi_wrdata_delay */
+	set_cal_res_to_reg(reg_addr, upd_val, DDR4_DFITMG1_DFI_T_WRDATA_DELAY,
+			   DDR4_DFITMG1_DFI_T_WRDATA_SHIFT);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(umctl2_base +
+				DDR4_SWSTAT_OFFSET), DDR4_SWSTAT_SW_DONE_ACK,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+	}
+
+	/* Isolate the APB access from internal CSRs */
+	setbits_le16(handoff->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	return ret;
+}
+
+static int update_training_result(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret = 0;
+
+	/* Updating training result to first DDR controller */
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4 ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		ret = set_cal_res_to_umctl2(ddr_handoff_info,
+					    ddr_handoff_info->cntlr_base,
+					    ddr_handoff_info->cntlr_t);
+		if (ret) {
+			debug("%s: Failed to update train result to ",
+			      __func__);
+			debug("first DDR controller\n");
+			return ret;
+		}
+	}
+
+	/* Updating training result to 2nd DDR controller */
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		ret = set_cal_res_to_umctl2(ddr_handoff_info,
+					    ddr_handoff_info->cntlr2_base,
+					    ddr_handoff_info->cntlr2_t);
+		if (ret) {
+			debug("%s: Failed to update train result to ",
+			      __func__);
+			debug("2nd DDR controller\n");
+		}
+	}
+
+	return ret;
+}
+
+static int start_ddr_calibration(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	/* Implement 1D training firmware */
+	ret = configure_training_firmware(ddr_handoff_info,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_IMEM_1D_SECTION,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_DMEM_1D_SECTION);
+	if (ret) {
+		debug("%s: Failed to configure 1D training firmware\n",
+		      __func__);
+		return ret;
+	}
+
+	calibrating_sdram(ddr_handoff_info);
+
+	ret = poll_for_training_complete(ddr_handoff_info);
+	if (ret) {
+		debug("%s: Failed to get FW training completed\n",
+		      __func__);
+		return ret;
+	}
+
+	/* Updating training result to DDR controller */
+	ret = update_training_result(ddr_handoff_info);
+	if (ret)
+		return ret;
+
+	/* Implement 2D training firmware */
+	ret = configure_training_firmware(ddr_handoff_info,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_IMEM_2D_SECTION,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_DMEM_2D_SECTION);
+	if (ret) {
+		debug("%s: Failed to update train result to ", __func__);
+		debug("DDR controller\n");
+		return ret;
+	}
+
+	calibrating_sdram(ddr_handoff_info);
+
+	ret = poll_for_training_complete(ddr_handoff_info);
+	if (ret)
+		debug("%s: Failed to get FW training completed\n",
+		      __func__);
+
+	return ret;
+}
+
+static int init_controller(struct ddr_handoff *ddr_handoff_info,
+			   u32 *user_backup, u32 *user_backup_2nd)
+{
+	int ret = 0;
+
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4  ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		/* Initialize 1st DDR controller */
+		ret = init_umctl2(ddr_handoff_info->cntlr_handoff_base,
+				  ddr_handoff_info->cntlr_base,
+				  ddr_handoff_info->cntlr_t,
+				  ddr_handoff_info->cntlr_handoff_length,
+				  user_backup);
+		if (ret) {
+			debug("%s: Failed to inilialize first controller\n",
+			      __func__);
+			return ret;
+		}
+	}
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		/* Initialize 2nd DDR controller */
+		ret = init_umctl2(ddr_handoff_info->cntlr2_handoff_base,
+				  ddr_handoff_info->cntlr2_base,
+				  ddr_handoff_info->cntlr2_t,
+				  ddr_handoff_info->cntlr2_handoff_length,
+				  user_backup_2nd);
+		if (ret)
+			debug("%s: Failed to inilialize 2nd controller\n",
+			      __func__);
+	}
+
+	return ret;
+}
+
+static int dfi_init(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	ret = ddr_start_dfi_init(ddr_handoff_info->cntlr_base,
+				 ddr_handoff_info->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_start_dfi_init(ddr_handoff_info->cntlr2_base,
+					 ddr_handoff_info->cntlr2_t);
+
+	return ret;
+}
+
+static int check_dfi_init(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_check_dfi_init_complete(handoff->cntlr_base,
+					  handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_check_dfi_init_complete(handoff->cntlr2_base,
+						  handoff->cntlr2_t);
+
+	return ret;
+}
+
+static int trigger_sdram_init(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_trigger_sdram_init(handoff->cntlr_base,
+				     handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_trigger_sdram_init(handoff->cntlr2_base,
+					     handoff->cntlr2_t);
+
+	return ret;
+}
+
+static int ddr_post_config(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_post_handoff_config(handoff->cntlr_base,
+				      handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_post_handoff_config(handoff->cntlr2_base,
+					      handoff->cntlr2_t);
+
+	return ret;
+}
+
+static bool is_ddr_retention_enabled(u32 boot_scratch_cold0_reg)
+{
+	return boot_scratch_cold0_reg &
+	       ALT_SYSMGR_SCRATCH_REG_0_DDR_RETENTION_MASK;
+}
+
+static bool is_ddr_bitstream_sha_matching(u32 boot_scratch_cold0_reg)
+{
+	return boot_scratch_cold0_reg & ALT_SYSMGR_SCRATCH_REG_0_DDR_SHA_MASK;
+}
+
+static enum reset_type get_reset_type(u32 boot_scratch_cold0_reg)
+{
+	return (boot_scratch_cold0_reg &
+		ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_MASK) >>
+		ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_SHIFT;
+}
+
+void reset_type_debug_print(u32 boot_scratch_cold0_reg)
+{
+	switch (get_reset_type(boot_scratch_cold0_reg)) {
+	case POR_RESET:
+		debug("%s: POR is triggered\n", __func__);
+		break;
+	case WARM_RESET:
+		debug("%s: Warm reset is triggered\n", __func__);
+		break;
+	case COLD_RESET:
+		debug("%s: Cold reset is triggered\n", __func__);
+		break;
+	default:
+		debug("%s: Invalid reset type\n", __func__);
+	}
+}
+
+bool is_ddr_init(void)
+{
+	u32 reg = readl(socfpga_get_sysmgr_addr() +
+			SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+
+	reset_type_debug_print(reg);
+
+	if (get_reset_type(reg) == POR_RESET) {
+		debug("%s: DDR init is required\n", __func__);
+		return true;
+	}
+
+	if (get_reset_type(reg) == WARM_RESET) {
+		debug("%s: DDR init is skipped\n", __func__);
+		return false;
+	}
+
+	if (get_reset_type(reg) == COLD_RESET) {
+		if (is_ddr_retention_enabled(reg) &&
+		    is_ddr_bitstream_sha_matching(reg)) {
+			debug("%s: DDR retention bit is set\n", __func__);
+			debug("%s: Matching in DDR bistream\n", __func__);
+			debug("%s: DDR init is skipped\n", __func__);
+			return false;
+		}
+	}
+
+	debug("%s: DDR init is required\n", __func__);
+	return true;
+}
+
+int sdram_mmr_init_full(struct udevice *dev)
+{
+	u32 user_backup[2], user_backup_2nd[2];
+	int ret;
+	struct bd_info bd;
+	struct ddr_handoff ddr_handoff_info;
+	struct altera_sdram_priv *priv = dev_get_priv(dev);
+
+	printf("Checking SDRAM configuration in progress ...\n");
+	ret = populate_ddr_handoff(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to populate DDR handoff\n",
+			      __func__);
+			return ret;
+		}
+
+	/* Set the MPFE NoC mux to correct DDR controller type */
+	use_ddr4(ddr_handoff_info.cntlr_t);
+
+	if (is_ddr_init()) {
+		printf("SDRAM init in progress ...\n");
+
+		/*
+		 * Polling reset complete, must be high to ensure DDR subsystem
+		 * in complete reset state before init DDR clock and DDR
+		 * controller
+		 */
+		ret = wait_for_bit_le32((const void *)((uintptr_t)(readl
+					(ddr_handoff_info.mem_reset_base) +
+					MEM_RST_MGR_STATUS)),
+					MEM_RST_MGR_STATUS_RESET_COMPLETE,
+					true, TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" reset complete done\n");
+			return ret;
+		}
+
+		ret = enable_ddr_clock(dev);
+		if (ret)
+			return ret;
+
+		ret = init_controller(&ddr_handoff_info, user_backup,
+				      user_backup_2nd);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR controller\n",
+			      __func__);
+			return ret;
+		}
+
+		/* Release the controller from reset */
+		setbits_le32((uintptr_t)
+			     (readl(ddr_handoff_info.mem_reset_base) +
+			     MEM_RST_MGR_STATUS), MEM_RST_MGR_STATUS_AXI_RST |
+			     MEM_RST_MGR_STATUS_CONTROLLER_RST |
+			     MEM_RST_MGR_STATUS_RESET_COMPLETE);
+
+		printf("DDR controller configuration is completed\n");
+
+		/* Initialize DDR PHY */
+		ret = init_phy(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR PHY\n", __func__);
+			return ret;
+		}
+
+		enable_phy_clk_for_csr_access(&ddr_handoff_info, true);
+
+		ret = start_ddr_calibration(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to calibrate DDR\n", __func__);
+			return ret;
+		}
+
+		enable_phy_clk_for_csr_access(&ddr_handoff_info, false);
+
+		/* Reset ARC processor when no using for security purpose */
+		setbits_le16(ddr_handoff_info.phy_base +
+			     DDR_PHY_MICRORESET_OFFSET,
+			     DDR_PHY_MICRORESET_RESET);
+
+		/* DDR freq set to support DDR4-3200 */
+		phy_init_engine(&ddr_handoff_info);
+
+		ret = dfi_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = check_dfi_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = trigger_sdram_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = ddr_post_config(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		/* Restore user settings */
+		writel(user_backup[0], ddr_handoff_info.cntlr_base +
+		       DDR4_PWRCTL_OFFSET);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_0)
+			setbits_le32(ddr_handoff_info.cntlr_base +
+				     DDR4_INIT0_OFFSET, user_backup[1]);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_1) {
+			/* Restore user settings */
+			writel(user_backup_2nd[0],
+			       ddr_handoff_info.cntlr2_base +
+			       DDR4_PWRCTL_OFFSET);
+
+			setbits_le32(ddr_handoff_info.cntlr2_base +
+				     DDR4_INIT0_OFFSET, user_backup_2nd[1]);
+		}
+
+		/* Enable input traffic per port */
+		setbits_le32(ddr_handoff_info.cntlr_base + DDR4_PCTRL0_OFFSET,
+			     DDR4_PCTRL0_PORT_EN);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_1) {
+			/* Enable input traffic per port */
+			setbits_le32(ddr_handoff_info.cntlr2_base +
+				     DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+		}
+
+		printf("DDR init success\n");
+	}
+
+	/* Get bank configuration from devicetree */
+	ret = fdtdec_decode_ram_size(gd->fdt_blob, NULL, 0, NULL,
+				     (phys_size_t *)&gd->ram_size, &bd);
+	if (ret) {
+		debug("%s: Failed to decode memory node\n",  __func__);
+		return -1;
+	}
+
+	printf("DDR: %lld MiB\n", gd->ram_size >> 20);
+
+	priv->info.base = bd.bi_dram[0].start;
+	priv->info.size = gd->ram_size;
+
+	sdram_size_check(&bd);
+
+	sdram_set_firewall(&bd);
+
+	return 0;
+}
diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index a08f095..d6baac2 100644
--- a/drivers/ddr/altera/sdram_soc64.c
+++ b/drivers/ddr/altera/sdram_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016-2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -100,12 +100,14 @@
 	return 0;
 }
 
+#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
 int poll_hmc_clock_status(void)
 {
 	return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
 				 SYSMGR_SOC64_HMC_CLK),
 				 SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
 }
+#endif
 
 void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
 {
@@ -182,6 +184,7 @@
 	phys_size_t total_ram_check = 0;
 	phys_size_t ram_check = 0;
 	phys_addr_t start = 0;
+	phys_size_t size, remaining_size;
 	int bank;
 
 	/* Sanity check ensure correct SDRAM size specified */
@@ -189,10 +192,27 @@
 
 	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
 		start = bd->bi_dram[bank].start;
+		remaining_size = bd->bi_dram[bank].size;
 		while (ram_check < bd->bi_dram[bank].size) {
-			ram_check += get_ram_size((void *)(start + ram_check),
-						 (phys_size_t)SZ_1G);
+			size = min((phys_addr_t)SZ_1G,
+				   (phys_addr_t)remaining_size);
+
+			/*
+			 * Ensure the size is power of two, this is requirement
+			 * to run get_ram_size() / memory test
+			 */
+			if (size != 0 && ((size & (size - 1)) == 0)) {
+				ram_check += get_ram_size((void *)
+						(start + ram_check), size);
+				remaining_size = bd->bi_dram[bank].size -
+							ram_check;
+			} else {
+				puts("DDR: Memory test requires SDRAM size ");
+				puts("in power of two!\n");
+				hang();
+			}
 		}
+
 		total_ram_check += ram_check;
 		ram_check = 0;
 	}
@@ -231,11 +251,78 @@
 	return size;
 }
 
+void sdram_set_firewall(struct bd_info *bd)
+{
+	u32 i;
+	phys_size_t value;
+	u32 lower, upper;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		if (!bd->bi_dram[i].size)
+			continue;
+
+		value = bd->bi_dram[i].start;
+
+		/* Keep first 1MB of SDRAM memory region as secure region when
+		 * using ATF flow, where the ATF code is located.
+		 */
+		if (IS_ENABLED(CONFIG_SPL_ATF) && i == 0)
+			value += SZ_1M;
+
+		/* Setting non-secure MPU region base and base extended */
+		lower = lower_32_bits(value);
+		upper = upper_32_bits(value);
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure Non-MPU region base and base extended */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure MPU limit and limit extexded */
+		value = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
+
+		lower = lower_32_bits(value);
+		upper = upper_32_bits(value);
+
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure Non-MPU limit and limit extexded */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(u32)));
+
+		FW_MPU_DDR_SCR_WRITEL(BIT(i) | BIT(i + 8),
+				      FW_MPU_DDR_SCR_EN_SET);
+	}
+}
+
 static int altera_sdram_of_to_plat(struct udevice *dev)
 {
 	struct altera_sdram_plat *plat = dev_get_plat(dev);
 	fdt_addr_t addr;
 
+	/* These regs info are part of DDR handoff in bitstream */
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	return 0;
+#endif
+
 	addr = dev_read_addr_index(dev, 0);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
@@ -296,6 +383,7 @@
 static const struct udevice_id altera_sdram_ids[] = {
 	{ .compatible = "altr,sdr-ctl-s10" },
 	{ .compatible = "intel,sdr-ctl-agilex" },
+	{ .compatible = "intel,sdr-ctl-n5x" },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/ddr/altera/sdram_soc64.h b/drivers/ddr/altera/sdram_soc64.h
index 8af0afc..7460f8c 100644
--- a/drivers/ddr/altera/sdram_soc64.h
+++ b/drivers/ddr/altera/sdram_soc64.h
@@ -180,6 +180,7 @@
 int poll_hmc_clock_status(void);
 void sdram_clear_mem(phys_addr_t addr, phys_size_t size);
 void sdram_init_ecc_bits(struct bd_info *bd);
+void sdram_set_firewall(struct bd_info *bd);
 void sdram_size_check(struct bd_info *bd);
 phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat);
 int sdram_mmr_init_full(struct udevice *dev);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index eea4701..2f78da6 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -366,6 +366,7 @@
 {
 	struct sdhci_host *host = mmc->priv;
 	unsigned int div, clk = 0, timeout;
+	int ret;
 
 	/* Wait max 20 ms */
 	timeout = 200;
@@ -386,8 +387,13 @@
 	if (clock == 0)
 		return 0;
 
-	if (host->ops && host->ops->set_delay)
-		host->ops->set_delay(host);
+	if (host->ops && host->ops->set_delay) {
+		ret = host->ops->set_delay(host);
+		if (ret) {
+			printf("%s: Error while setting tap delay\n", __func__);
+			return ret;
+		}
+	}
 
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/*
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index ba87ee8..c94825d 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -15,9 +15,10 @@
 #include <dm/device_compat.h>
 #include <linux/err.h>
 #include <linux/libfdt.h>
+#include <asm/cache.h>
 #include <malloc.h>
 #include <sdhci.h>
-#include <zynqmp_tap_delay.h>
+#include <zynqmp_firmware.h>
 
 #define SDHCI_ARASAN_ITAPDLY_REGISTER	0xF0F8
 #define SDHCI_ARASAN_ITAPDLY_SEL_MASK	GENMASK(7, 0)
@@ -30,6 +31,20 @@
 #define SDHCI_TUNING_LOOP_COUNT		40
 #define MMC_BANK2			0x2
 
+#define SD_DLL_CTRL			0xFF180358
+#define SD_ITAP_DLY			0xFF180314
+#define SD_OTAP_DLY			0xFF180318
+#define SD0_DLL_RST			BIT(2)
+#define SD1_DLL_RST			BIT(18)
+#define SD0_ITAPCHGWIN			BIT(9)
+#define SD1_ITAPCHGWIN			BIT(25)
+#define SD0_ITAPDLYENA			BIT(8)
+#define SD1_ITAPDLYENA			BIT(24)
+#define SD0_ITAPDLYSEL_MASK		GENMASK(7, 0)
+#define SD1_ITAPDLYSEL_MASK		GENMASK(23, 16)
+#define SD0_OTAPDLYSEL_MASK		GENMASK(5, 0)
+#define SD1_OTAPDLYSEL_MASK		GENMASK(21, 16)
+
 struct arasan_sdhci_clk_data {
 	int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
 	int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
@@ -48,6 +63,12 @@
 	u8 no_1p8;
 };
 
+/* For Versal platforms zynqmp_mmio_write() won't be available */
+__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
+{
+	return 0;
+}
+
 #if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
 /* Default settings for ZynqMP Clock Phases */
 static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,
@@ -75,26 +96,126 @@
 	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
-static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+static inline int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
 {
-	u16 clk;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0) {
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
+						SD0_ITAPCHGWIN);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
+						SD0_ITAPDLYENA);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+						itap_delay);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
+			if (ret)
+				return ret;
+		}
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
+					SD1_ITAPCHGWIN);
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
+					SD1_ITAPDLYENA);
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					(itap_delay << 16));
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
+		if (ret)
+			return ret;
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_INPUT, itap_delay, NULL);
+	}
+
+	return 0;
+}
+
+static inline int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_OTAP_DLY,
+						 SD0_OTAPDLYSEL_MASK,
+						 otap_delay);
+
+		return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					 (otap_delay << 16));
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
+	}
+}
+
+static inline int zynqmp_dll_reset(u8 node_id, u32 type)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
+						 type == PM_DLL_RESET_ASSERT ?
+						 SD0_DLL_RST : 0);
+
+		return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
+					 type == PM_DLL_RESET_ASSERT ?
+					 SD1_DLL_RST : 0);
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SD_DLL_RESET, type, 0, NULL);
+	}
+}
+
+static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	struct udevice *dev = mmc->dev;
 	unsigned long timeout;
+	int ret;
+	u16 clk;
 
 	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
 	clk &= ~(SDHCI_CLOCK_CARD_EN);
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
 	/* Issue DLL Reset */
-	zynqmp_dll_reset(deviceid);
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+	if (ret) {
+		dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
+		return ret;
+	}
+
+	/* Allow atleast 1ms delay for proper DLL reset */
+	mdelay(1);
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+	if (ret) {
+		dev_err(dev, "dll_reset release failed with err: %d\n", ret);
+		return ret;
+	}
 
 	/* Wait max 20 ms */
 	timeout = 100;
 	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
 				& SDHCI_CLOCK_INT_STABLE)) {
 		if (timeout == 0) {
-			dev_err(mmc_dev(host->mmc),
-				": Internal clock never stabilised.\n");
-			return;
+			dev_err(dev, ": Internal clock never stabilised.\n");
+			return -EBUSY;
 		}
 		timeout--;
 		udelay(1000);
@@ -102,6 +223,8 @@
 
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	return 0;
 }
 
 static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
@@ -112,12 +235,11 @@
 	struct sdhci_host *host;
 	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
 	char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
-	u8 deviceid;
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 
 	debug("%s\n", __func__);
 
 	host = priv->host;
-	deviceid = priv->deviceid;
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
@@ -125,7 +247,7 @@
 
 	mdelay(1);
 
-	arasan_zynqmp_dll_reset(host, deviceid);
+	arasan_zynqmp_dll_reset(host, node_id);
 
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
@@ -171,7 +293,7 @@
 	}
 
 	udelay(1);
-	arasan_zynqmp_dll_reset(host, deviceid);
+	arasan_zynqmp_dll_reset(host, node_id);
 
 	/* Enable only interrupts served by the SD controller */
 	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
@@ -194,10 +316,13 @@
 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;
+	struct udevice *dev = mmc->dev;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
+	int ret;
 
 	/*
 	 * This is applicable for SDHCI_SPEC_300 and above
@@ -233,7 +358,19 @@
 	/* Limit output tap_delay value to 6 bits */
 	tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
 
-	arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
+	/* Set the Clock Phase */
+	ret = arasan_zynqmp_set_out_tapdelay(node_id, tap_delay);
+	if (ret) {
+		dev_err(dev, "Error setting output Tap Delay\n");
+		return ret;
+	}
+
+	/* Release DLL Reset */
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+	if (ret) {
+		dev_err(dev, "dll_reset release failed with err: %d\n", ret);
+		return ret;
+	}
 
 	return 0;
 }
@@ -250,10 +387,13 @@
 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;
+	struct udevice *dev = mmc->dev;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
+	int ret;
 
 	/*
 	 * This is applicable for SDHCI_SPEC_300 and above
@@ -263,6 +403,13 @@
 	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
 		return 0;
 
+	/* Assert DLL Reset */
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+	if (ret) {
+		dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
+		return ret;
+	}
+
 	switch (timing) {
 	case MMC_TIMING_MMC_HS:
 	case MMC_TIMING_SD_HS:
@@ -289,7 +436,11 @@
 	/* Limit input tap_delay value to 8 bits */
 	tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
 
-	arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
+	ret = arasan_zynqmp_set_in_tapdelay(node_id, tap_delay);
+	if (ret) {
+		dev_err(dev, "Error setting Input Tap Delay\n");
+		return ret;
+	}
 
 	return 0;
 }
@@ -422,7 +573,7 @@
 	return 0;
 }
 
-static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
+static int 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;
@@ -431,18 +582,31 @@
 	u8 timing = mode2timing[mmc->selected_mode];
 	u32 iclk_phase = clk_data->clk_phase_in[timing];
 	u32 oclk_phase = clk_data->clk_phase_out[timing];
+	int ret;
 
 	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);
+		ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
+		if (ret)
+			return ret;
+
+		ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
+		if (ret)
+			return ret;
 	} 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);
+		ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
+		if (ret)
+			return ret;
+
+		ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
+		if (ret)
+			return ret;
 	}
+
+	return 0;
 }
 
 static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
@@ -526,29 +690,10 @@
 				 "clk-phase-mmc-hs400");
 }
 
-static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
-{
-	struct mmc *mmc = (struct mmc *)host->mmc;
-	u32 reg;
-
-	if (!IS_SD(mmc))
-		return;
-
-	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-		reg |= SDHCI_CTRL_VDD_180;
-		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
-	}
-
-	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= MMC_HS_200)
-		sdhci_set_uhs_timing(host);
-}
-
 static const struct sdhci_ops arasan_ops = {
 	.platform_execute_tuning	= &arasan_sdhci_execute_tuning,
 	.set_delay = &arasan_sdhci_set_tapdelay,
-	.set_control_reg = &arasan_sdhci_set_control_reg,
+	.set_control_reg = &sdhci_set_control_reg,
 };
 #endif
 
@@ -612,6 +757,25 @@
 		return ret;
 	upriv->mmc = host->mmc;
 
+	/*
+	 * WORKAROUND: Versal platforms have an issue with card detect state.
+	 * Due to this, host controller is switching off voltage to sd card
+	 * causing sd card timeout error. Workaround this by adding a wait for
+	 * 1000msec till the card detect state gets stable.
+	 */
+	if (IS_ENABLED(CONFIG_ARCH_VERSAL)) {
+		u32 timeout = 1000;
+
+		while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			 SDHCI_CARD_STATE_STABLE) == 0) && timeout--) {
+			mdelay(1);
+		}
+		if (!timeout) {
+			dev_err(dev, "Sdhci card detect state not stable\n");
+			return -ETIMEDOUT;
+		}
+	}
+
 	return sdhci_probe(dev);
 }
 
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index a42b3f0..d73daf5 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -197,4 +197,13 @@
 	  Enable this option if you want to support reset controller
 	  devices exposed by a SCMI agent based on SCMI reset domain
 	  protocol communication with a SCMI server.
+
+config RESET_ZYNQMP
+	bool "Reset Driver for Xilinx ZynqMP SoC's"
+	depends on DM_RESET && ZYNQMP_FIRMWARE
+	help
+	  Support for reset controller on Xilinx ZynqMP SoC. Driver is only
+	  passing request via Xilinx firmware interface to TF-A and PMU
+	  firmware.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 8a0f528..d69486b 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -29,3 +29,4 @@
 obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o
 obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
 obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
+obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
new file mode 100644
index 0000000..5765234
--- /dev/null
+++ b/drivers/reset/reset-zynqmp.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Xilinx, Inc. - Michal Simek
+ */
+
+#define LOG_CATEGORY UCLASS_RESET
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <reset-uclass.h>
+#include <zynqmp_firmware.h>
+
+#define ZYNQMP_NR_RESETS	(ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
+#define ZYNQMP_RESET_ID		ZYNQMP_PM_RESET_START
+
+struct zynqmp_reset_priv {
+	u32 reset_id;
+	u32 nr_reset;
+};
+
+static int zynqmp_pm_reset_assert(const u32 reset,
+				  const enum zynqmp_pm_reset_action assert_flag)
+{
+	return xilinx_pm_request(PM_RESET_ASSERT, reset, assert_flag, 0, 0,
+				 NULL);
+}
+
+static int zynqmp_reset_assert(struct reset_ctl *rst)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+	dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
+
+	return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
+				      PM_RESET_ACTION_ASSERT);
+}
+
+static int zynqmp_reset_deassert(struct reset_ctl *rst)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+	dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
+
+	return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
+				      PM_RESET_ACTION_RELEASE);
+}
+
+static int zynqmp_reset_request(struct reset_ctl *rst)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+	dev_dbg(rst->dev, "%s(rst=%p) (id=%lu) (nr_reset=%d)\n", __func__,
+		rst, rst->id, priv->nr_reset);
+
+	if (rst->id > priv->nr_reset)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int zynqmp_reset_free(struct reset_ctl *rst)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+	dev_dbg(rst->dev, "%s(rst=%p) (id=%lu) (nr_reset=%d)\n", __func__,
+		rst, rst->id, priv->nr_reset);
+
+	return 0;
+}
+
+static int zynqmp_reset_probe(struct udevice *dev)
+{
+	struct zynqmp_reset_priv *priv = dev_get_priv(dev);
+
+	priv->reset_id = ZYNQMP_RESET_ID;
+	priv->nr_reset = ZYNQMP_NR_RESETS;
+	return 0;
+}
+
+const struct reset_ops zynqmp_reset_ops = {
+	.request = zynqmp_reset_request,
+	.rfree = zynqmp_reset_free,
+	.rst_assert = zynqmp_reset_assert,
+	.rst_deassert = zynqmp_reset_deassert,
+};
+
+static const struct udevice_id zynqmp_reset_ids[] = {
+	{ .compatible = "xlnx,zynqmp-reset" },
+	{ }
+};
+
+U_BOOT_DRIVER(zynqmp_reset) = {
+	.name		= "zynqmp_reset",
+	.id		= UCLASS_RESET,
+	.of_match	= zynqmp_reset_ids,
+	.ops		= &zynqmp_reset_ops,
+	.probe		= zynqmp_reset_probe,
+	.priv_auto	= sizeof(struct zynqmp_reset_priv),
+};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index cbdfddb..b6692e6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -195,4 +195,11 @@
 	  Say "yes" here to support the on chip real time clock
 	  present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
 
+config RTC_ZYNQMP
+	bool "Enable ZynqMP RTC driver"
+	depends on ARCH_ZYNQMP
+	help
+	  Say "yes" here to support the on chip real time clock
+	  present on Xilinx ZynqMP SoC.
+
 endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 331a49a..d621be6 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -57,3 +57,4 @@
 obj-$(CONFIG_SANDBOX) += sandbox_rtc.o
 obj-$(CONFIG_RTC_X1205) += x1205.o
 obj-$(CONFIG_RTC_ABX80X) += abx80x.o
+obj-$(CONFIG_RTC_ZYNQMP) += zynqmp_rtc.o
diff --git a/drivers/rtc/rtc-uclass.c b/drivers/rtc/rtc-uclass.c
index be6a2dd..321b873 100644
--- a/drivers/rtc/rtc-uclass.c
+++ b/drivers/rtc/rtc-uclass.c
@@ -176,6 +176,7 @@
 UCLASS_DRIVER(rtc) = {
 	.name		= "rtc",
 	.id		= UCLASS_RTC,
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.post_bind	= dm_scan_fdt_dev,
 #endif
diff --git a/drivers/rtc/zynqmp_rtc.c b/drivers/rtc/zynqmp_rtc.c
new file mode 100644
index 0000000..ab9b93c
--- /dev/null
+++ b/drivers/rtc/zynqmp_rtc.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, Xilinx, Inc.
+ */
+
+#define LOG_CATEGORY UCLASS_RTC
+
+#include <common.h>
+#include <dm.h>
+#include <rtc.h>
+#include <asm/io.h>
+
+/* RTC Registers */
+#define RTC_SET_TM_WR		0x00
+#define RTC_SET_TM_RD		0x04
+#define RTC_CALIB_WR		0x08
+#define RTC_CUR_TM		0x10
+#define RTC_INT_STS		0x20
+#define RTC_CTRL		0x40
+
+#define RTC_INT_SEC		BIT(0)
+#define RTC_BATT_EN		BIT(31)
+#define RTC_CALIB_DEF		0x198233
+#define RTC_CALIB_MASK		0x1FFFFF
+
+struct zynqmp_rtc_priv {
+	fdt_addr_t	base;
+	unsigned int	calibval;
+};
+
+static int zynqmp_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+	struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
+	u32 status;
+	unsigned long read_time;
+
+	status = readl(priv->base + RTC_INT_STS);
+
+	if (status & RTC_INT_SEC) {
+		/*
+		 * RTC has updated the CURRENT_TIME with the time written into
+		 * SET_TIME_WRITE register.
+		 */
+		read_time = readl(priv->base + RTC_CUR_TM);
+	} else {
+		/*
+		 * Time written in SET_TIME_WRITE has not yet updated into
+		 * the seconds read register, so read the time from the
+		 * SET_TIME_WRITE instead of CURRENT_TIME register.
+		 * Since we add +1 sec while writing, we need to -1 sec while
+		 * reading.
+		 */
+		read_time = readl(priv->base + RTC_SET_TM_RD) - 1;
+	}
+
+	rtc_to_tm(read_time, tm);
+
+	return 0;
+}
+
+static int zynqmp_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+	struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
+	unsigned long new_time = 0;
+
+	if (tm)
+		/*
+		 * The value written will be updated after 1 sec into the
+		 * seconds read register, so we need to program time +1 sec
+		 * to get the correct time on read.
+		 */
+		new_time = rtc_mktime(tm) + 1;
+
+	/*
+	 * Writing into calibration register will clear the Tick Counter and
+	 * force the next second to be signaled exactly in 1 second period
+	 */
+	priv->calibval &= RTC_CALIB_MASK;
+	writel(priv->calibval, (priv->base + RTC_CALIB_WR));
+
+	writel(new_time, priv->base + RTC_SET_TM_WR);
+
+	/*
+	 * Clear the rtc interrupt status register after setting the
+	 * time. During a read_time function, the code should read the
+	 * RTC_INT_STATUS register and if bit 0 is still 0, it means
+	 * that one second has not elapsed yet since RTC was set and
+	 * the current time should be read from SET_TIME_READ register;
+	 * otherwise, CURRENT_TIME register is read to report the time
+	 */
+	writel(RTC_INT_SEC, priv->base + RTC_INT_STS);
+
+	return 0;
+}
+
+static int zynqmp_rtc_reset(struct udevice *dev)
+{
+	return zynqmp_rtc_set(dev, NULL);
+}
+
+static int zynqmp_rtc_init(struct udevice *dev)
+{
+	struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
+	u32 rtc_ctrl;
+
+	/* Enable RTC switch to battery when VCC_PSAUX is not available */
+	rtc_ctrl = readl(priv->base + RTC_CTRL);
+	rtc_ctrl |= RTC_BATT_EN;
+	writel(rtc_ctrl, priv->base + RTC_CTRL);
+
+	/*
+	 * Based on crystal freq of 33.330 KHz
+	 * set the seconds counter and enable, set fractions counter
+	 * to default value suggested as per design spec
+	 * to correct RTC delay in frequency over period of time.
+	 */
+	priv->calibval &= RTC_CALIB_MASK;
+	writel(priv->calibval, (priv->base + RTC_CALIB_WR));
+
+	return 0;
+}
+
+static int zynqmp_rtc_probe(struct udevice *dev)
+{
+	struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->base = dev_read_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->calibval = dev_read_u32_default(dev, "calibration",
+					      RTC_CALIB_DEF);
+
+	ret = zynqmp_rtc_init(dev);
+
+	return ret;
+}
+
+static const struct rtc_ops zynqmp_rtc_ops = {
+	.get = zynqmp_rtc_get,
+	.set = zynqmp_rtc_set,
+	.reset = zynqmp_rtc_reset,
+};
+
+static const struct udevice_id zynqmp_rtc_ids[] = {
+	{ .compatible = "xlnx,zynqmp-rtc" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_zynqmp) = {
+	.name = "rtc-zynqmp",
+	.id = UCLASS_RTC,
+	.probe = zynqmp_rtc_probe,
+	.of_match = zynqmp_rtc_ids,
+	.ops = &zynqmp_rtc_ops,
+	.priv_auto = sizeof(struct zynqmp_rtc_priv),
+};
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 864d00a..292dc41 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -16,6 +16,22 @@
 	  This allows Texas Instruments Keystone 3 SoCs to identify
 	  specifics about the SoC in use.
 
+config SOC_XILINX_ZYNQMP
+	bool "Enable SoC Device ID driver for Xilinx ZynqMP"
+	depends on SOC_DEVICE && ARCH_ZYNQMP
+	help
+	  Enable this option to select SoC device id driver for Xilinx ZynqMP.
+	  This allows other drivers to verify the SoC familiy & revision
+	  using matching SoC attributes.
+
+config SOC_XILINX_VERSAL
+	bool "Enable SoC Device ID driver for Xilinx Versal"
+	depends on SOC_DEVICE && ARCH_VERSAL
+	help
+	  Enable this option to select SoC device id driver for Xilinx Versal.
+	  This allows other drivers to verify the SoC familiy & revision using
+	  matching SoC attributes.
+
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 9ef20ca..031fa76 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -6,3 +6,5 @@
 obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
 obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
 obj-$(CONFIG_SANDBOX) += soc_sandbox.o
+obj-$(CONFIG_SOC_XILINX_ZYNQMP) += soc_xilinx_zynqmp.o
+obj-$(CONFIG_SOC_XILINX_VERSAL) += soc_xilinx_versal.o
diff --git a/drivers/soc/soc_xilinx_versal.c b/drivers/soc/soc_xilinx_versal.c
new file mode 100644
index 0000000..f8bcd9a
--- /dev/null
+++ b/drivers/soc/soc_xilinx_versal.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Versal SOC driver
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <soc.h>
+#include <zynqmp_firmware.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/*
+ * v1 -> 0x10 - ES1
+ * v2 -> 0x20 - Production
+ */
+static const char versal_family[] = "Versal";
+
+struct soc_xilinx_versal_priv {
+	const char *family;
+	char revision;
+};
+
+static int soc_xilinx_versal_get_family(struct udevice *dev, char *buf, int size)
+{
+	struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
+
+	return snprintf(buf, size, "%s", priv->family);
+}
+
+static int soc_xilinx_versal_get_revision(struct udevice *dev, char *buf, int size)
+{
+	struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
+
+	return snprintf(buf, size, "v%d", priv->revision);
+}
+
+static const struct soc_ops soc_xilinx_versal_ops = {
+	.get_family = soc_xilinx_versal_get_family,
+	.get_revision = soc_xilinx_versal_get_revision,
+};
+
+static int soc_xilinx_versal_probe(struct udevice *dev)
+{
+	struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
+	u32 ret_payload[4];
+	int ret;
+
+	priv->family = versal_family;
+
+	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
+		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
+					ret_payload);
+		if (ret)
+			return ret;
+	} else {
+		ret_payload[2] = readl(VERSAL_PS_PMC_VERSION);
+		if (!ret_payload[2])
+			return -EINVAL;
+	}
+
+	priv->revision = ret_payload[2] >> VERSAL_PS_VER_SHIFT;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(soc_xilinx_versal) = {
+	.name		= "soc_xilinx_versal",
+	.id		= UCLASS_SOC,
+	.ops		= &soc_xilinx_versal_ops,
+	.probe		= soc_xilinx_versal_probe,
+	.priv_auto	= sizeof(struct soc_xilinx_versal_priv),
+	.flags		= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c
new file mode 100644
index 0000000..7d33ce2
--- /dev/null
+++ b/drivers/soc/soc_xilinx_zynqmp.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP SOC driver
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/cache.h>
+#include <soc.h>
+#include <zynqmp_firmware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+
+/*
+ * Zynqmp has 4 silicon revisions
+ * v0 -> 0(XCZU9EG-ES1)
+ * v1 -> 1(XCZU3EG-ES1, XCZU15EG-ES1)
+ * v2 -> 2(XCZU7EV-ES1, XCZU9EG-ES2, XCZU19EG-ES1)
+ * v3 -> 3(Production Level)
+ */
+static const char zynqmp_family[] = "ZynqMP";
+
+struct soc_xilinx_zynqmp_priv {
+	const char *family;
+	char revision;
+};
+
+static int soc_xilinx_zynqmp_get_family(struct udevice *dev, char *buf, int size)
+{
+	struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
+
+	return snprintf(buf, size, "%s", priv->family);
+}
+
+static int soc_xilinx_zynqmp_get_revision(struct udevice *dev, char *buf, int size)
+{
+	struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
+
+	return snprintf(buf, size, "v%d", priv->revision);
+}
+
+static const struct soc_ops soc_xilinx_zynqmp_ops = {
+	.get_family = soc_xilinx_zynqmp_get_family,
+	.get_revision = soc_xilinx_zynqmp_get_revision,
+};
+
+static int soc_xilinx_zynqmp_probe(struct udevice *dev)
+{
+	struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
+	u32 ret_payload[4];
+	int ret;
+
+	priv->family = zynqmp_family;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3 ||
+	    !IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
+		ret = zynqmp_mmio_read(ZYNQMP_PS_VERSION, &ret_payload[2]);
+	else
+		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
+					ret_payload);
+	if (ret < 0)
+		return ret;
+
+	priv->revision = ret_payload[2] & ZYNQMP_PS_VER_MASK;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(soc_xilinx_zynqmp) = {
+	.name		= "soc_xilinx_zynqmp",
+	.id		= UCLASS_SOC,
+	.ops		= &soc_xilinx_zynqmp_ops,
+	.probe		= soc_xilinx_zynqmp_probe,
+	.priv_auto	= sizeof(struct soc_xilinx_zynqmp_priv),
+	.flags		= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
index 11b30ae..c8e6c60 100644
--- a/drivers/watchdog/xilinx_wwdt.c
+++ b/drivers/watchdog/xilinx_wwdt.c
@@ -14,6 +14,7 @@
 #include <regmap.h>
 #include <wdt.h>
 #include <linux/compat.h>
+#include <dm/device_compat.h>
 #include <linux/io.h>
 
 /* Refresh Register Masks */
diff --git a/include/configs/socfpga_n5x_socdk.h b/include/configs/socfpga_n5x_socdk.h
new file mode 100644
index 0000000..c295e91
--- /dev/null
+++ b/include/configs/socfpga_n5x_socdk.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef __CONFIG_SOCFGPA_N5X_H__
+#define __CONFIG_SOCFGPA_N5X_H__
+
+#include <configs/socfpga_soc64_common.h>
+
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
+	"bootfile=" CONFIG_BOOTFILE "\0" \
+	"fdt_addr=1100000\0" \
+	"fdtimage=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"mmcroot=/dev/mmcblk0p2\0" \
+	"mmcboot=setenv bootargs " CONFIG_BOOTARGS \
+		" root=${mmcroot} rw rootwait;" \
+		"booti ${loadaddr} - ${fdt_addr}\0" \
+	"mmcload=mmc rescan;" \
+		"load mmc 0:1 ${loadaddr} ${bootfile};" \
+		"load mmc 0:1 ${fdt_addr} ${fdtimage}\0" \
+	"mmcfitboot=setenv bootargs " CONFIG_BOOTARGS \
+		" root=${mmcroot} rw rootwait;" \
+		"bootm ${loadaddr}\0" \
+	"mmcfitload=mmc rescan;" \
+		"load mmc 0:1 ${loadaddr} ${bootfile}\0" \
+	"ramboot=setenv bootargs " CONFIG_BOOTARGS";" \
+		"booti ${loadaddr} - ${fdt_addr}\0" \
+	"linux_qspi_enable=if sf probe; then " \
+		"echo Enabling QSPI at Linux DTB...;" \
+		"fdt addr ${fdt_addr}; fdt resize;" \
+		"fdt set /soc/spi@ff8d2000 status okay;" \
+		"if fdt set /soc/clocks/qspi-clk clock-frequency" \
+		" ${qspi_clock}; then" \
+		" else fdt set /soc/clkmgr/clocks/qspi_clk clock-frequency" \
+		" ${qspi_clock}; fi; fi\0" \
+	"scriptaddr=0x02100000\0" \
+	"scriptfile=u-boot.scr\0" \
+	"fatscript=if fatload mmc 0:1 ${scriptaddr} ${scriptfile};" \
+		   "then source ${scriptaddr}; fi\0"
+
+#endif	/* __CONFIG_SOCFGPA_N5X_H__ */
diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h
index 38fd775..a0453e5 100644
--- a/include/configs/socfpga_soc64_common.h
+++ b/include/configs/socfpga_soc64_common.h
@@ -7,7 +7,7 @@
 #ifndef __CONFIG_SOCFPGA_SOC64_COMMON_H__
 #define __CONFIG_SOCFPGA_SOC64_COMMON_H__
 
-#include <asm/arch/base_addr_s10.h>
+#include <asm/arch/base_addr_soc64.h>
 #include <asm/arch/handoff_soc64.h>
 #include <linux/stringify.h>
 
@@ -20,7 +20,6 @@
 #define CONFIG_REMAKE_ELF
 /* sysmgr.boot_scratch_cold4 & 5 (64bit) will be used for PSCI_CPU_ON call */
 #define CPU_RELEASE_ADDR		0xFFD12210
-#define CONFIG_SYS_CACHELINE_SIZE	64
 
 /*
  * U-Boot console configurations
diff --git a/include/dt-bindings/clock/n5x-clock.h b/include/dt-bindings/clock/n5x-clock.h
new file mode 100644
index 0000000..a56e4db
--- /dev/null
+++ b/include/dt-bindings/clock/n5x-clock.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021, Intel Corporation
+ */
+
+#ifndef __N5X_CLOCK_H
+#define __N5X_CLOCK_H
+
+/* fixed rate clocks */
+#define N5X_OSC1					0
+#define N5X_CB_INTOSC_HS_DIV2_CLK		1
+#define N5X_CB_INTOSC_LS_CLK			2
+#define N5X_L4_SYS_FREE_CLK			3
+#define N5X_F2S_FREE_CLK				4
+
+/* PLL clocks */
+#define N5X_MAIN_PLL_CLK				5
+#define N5X_MAIN_PLL_C0_CLK			6
+#define N5X_MAIN_PLL_C1_CLK			7
+#define N5X_MAIN_PLL_C2_CLK			8
+#define N5X_MAIN_PLL_C3_CLK			9
+#define N5X_PERIPH_PLL_CLK			10
+#define N5X_PERIPH_PLL_C0_CLK			11
+#define N5X_PERIPH_PLL_C1_CLK			12
+#define N5X_PERIPH_PLL_C2_CLK			13
+#define N5X_PERIPH_PLL_C3_CLK			14
+#define N5X_MPU_FREE_CLK				15
+#define N5X_MPU_CCU_CLK				16
+#define N5X_BOOT_CLK				17
+
+/* fixed factor clocks */
+#define N5X_L3_MAIN_FREE_CLK			18
+#define N5X_NOC_FREE_CLK				19
+#define N5X_S2F_USR0_CLK				20
+#define N5X_NOC_CLK				21
+#define N5X_EMAC_A_FREE_CLK			22
+#define N5X_EMAC_B_FREE_CLK			23
+#define N5X_EMAC_PTP_FREE_CLK			24
+#define N5X_GPIO_DB_FREE_CLK			25
+#define N5X_SDMMC_FREE_CLK			26
+#define N5X_S2F_USER0_FREE_CLK			27
+#define N5X_S2F_USER1_FREE_CLK			28
+#define N5X_PSI_REF_FREE_CLK			29
+
+/* Gate clocks */
+#define N5X_MPU_CLK				30
+#define N5X_MPU_PERIPH_CLK			31
+#define N5X_L4_MAIN_CLK				32
+#define N5X_L4_MP_CLK				33
+#define N5X_L4_SP_CLK				34
+#define N5X_CS_AT_CLK				35
+#define N5X_CS_TRACE_CLK				36
+#define N5X_CS_PDBG_CLK				37
+#define N5X_CS_TIMER_CLK				38
+#define N5X_S2F_USER0_CLK			39
+#define N5X_EMAC0_CLK				40
+#define N5X_EMAC1_CLK				41
+#define N5X_EMAC2_CLK				42
+#define N5X_EMAC_PTP_CLK				43
+#define N5X_GPIO_DB_CLK				44
+#define N5X_NAND_CLK				45
+#define N5X_PSI_REF_CLK				46
+#define N5X_S2F_USER1_CLK			47
+#define N5X_SDMMC_CLK				48
+#define N5X_SPI_M_CLK				49
+#define N5X_USB_CLK				50
+#define N5X_NAND_X_CLK				51
+#define N5X_NAND_ECC_CLK				52
+#define N5X_NUM_CLKS				53
+
+#endif	/* __N5X_CLOCK_H */
diff --git a/include/sdhci.h b/include/sdhci.h
index 0ae9471..44a0d84 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -268,7 +268,7 @@
 	int	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
 	int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
-	void (*set_delay)(struct sdhci_host *host);
+	int (*set_delay)(struct sdhci_host *host);
 	int	(*deferred_probe)(struct sdhci_host *host);
 };
 
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index f6f82bf..0b068d7 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -10,58 +10,156 @@
 
 enum pm_api_id {
 	PM_GET_API_VERSION = 1,
-	PM_SET_CONFIGURATION,
-	PM_GET_NODE_STATUS,
-	PM_GET_OPERATING_CHARACTERISTIC,
-	PM_REGISTER_NOTIFIER,
-	PM_REQUEST_SUSPEND,
-	PM_SELF_SUSPEND,
-	PM_FORCE_POWERDOWN,
-	PM_ABORT_SUSPEND,
-	PM_REQUEST_WAKEUP,
-	PM_SET_WAKEUP_SOURCE,
-	PM_SYSTEM_SHUTDOWN,
-	PM_REQUEST_NODE,
-	PM_RELEASE_NODE,
-	PM_SET_REQUIREMENT,
-	PM_SET_MAX_LATENCY,
-	PM_RESET_ASSERT,
-	PM_RESET_GET_STATUS,
-	PM_MMIO_WRITE,
-	PM_MMIO_READ,
-	PM_PM_INIT_FINALIZE,
-	PM_FPGA_LOAD,
-	PM_FPGA_GET_STATUS,
-	PM_GET_CHIPID,
+	PM_SET_CONFIGURATION = 2,
+	PM_GET_NODE_STATUS = 3,
+	PM_GET_OPERATING_CHARACTERISTIC = 4,
+	PM_REGISTER_NOTIFIER = 5,
+	/* API for suspending */
+	PM_REQUEST_SUSPEND = 6,
+	PM_SELF_SUSPEND = 7,
+	PM_FORCE_POWERDOWN = 8,
+	PM_ABORT_SUSPEND = 9,
+	PM_REQUEST_WAKEUP = 10,
+	PM_SET_WAKEUP_SOURCE = 11,
+	PM_SYSTEM_SHUTDOWN = 12,
+	PM_REQUEST_NODE = 13,
+	PM_RELEASE_NODE = 14,
+	PM_SET_REQUIREMENT = 15,
+	PM_SET_MAX_LATENCY = 16,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT = 17,
+	PM_RESET_GET_STATUS = 18,
+	PM_MMIO_WRITE = 19,
+	PM_MMIO_READ = 20,
+	PM_PM_INIT_FINALIZE = 21,
+	PM_FPGA_LOAD = 22,
+	PM_FPGA_GET_STATUS = 23,
+	PM_GET_CHIPID = 24,
+	/* ID 25 is been used by U-boot to process secure boot images */
+	/* Secure library generic API functions */
 	PM_SECURE_SHA = 26,
-	PM_SECURE_RSA,
-	PM_PINCTRL_REQUEST,
-	PM_PINCTRL_RELEASE,
-	PM_PINCTRL_GET_FUNCTION,
-	PM_PINCTRL_SET_FUNCTION,
-	PM_PINCTRL_CONFIG_PARAM_GET,
-	PM_PINCTRL_CONFIG_PARAM_SET,
-	PM_IOCTL,
-	PM_QUERY_DATA,
-	PM_CLOCK_ENABLE,
-	PM_CLOCK_DISABLE,
-	PM_CLOCK_GETSTATE,
-	PM_CLOCK_SETDIVIDER,
-	PM_CLOCK_GETDIVIDER,
-	PM_CLOCK_SETRATE,
-	PM_CLOCK_GETRATE,
-	PM_CLOCK_SETPARENT,
-	PM_CLOCK_GETPARENT,
-	PM_SECURE_IMAGE,
+	PM_SECURE_RSA = 27,
+	PM_PINCTRL_REQUEST = 28,
+	PM_PINCTRL_RELEASE = 29,
+	PM_PINCTRL_GET_FUNCTION = 30,
+	PM_PINCTRL_SET_FUNCTION = 31,
+	PM_PINCTRL_CONFIG_PARAM_GET = 32,
+	PM_PINCTRL_CONFIG_PARAM_SET = 33,
+	PM_IOCTL = 34,
+	PM_QUERY_DATA = 35,
+	PM_CLOCK_ENABLE = 36,
+	PM_CLOCK_DISABLE = 37,
+	PM_CLOCK_GETSTATE = 38,
+	PM_CLOCK_SETDIVIDER = 39,
+	PM_CLOCK_GETDIVIDER = 40,
+	PM_CLOCK_SETRATE = 41,
+	PM_CLOCK_GETRATE = 42,
+	PM_CLOCK_SETPARENT = 43,
+	PM_CLOCK_GETPARENT = 44,
+	PM_SECURE_IMAGE = 45,
 	PM_FPGA_READ = 46,
-	PM_SECURE_AES,
+	PM_SECURE_AES = 47,
 	PM_CLOCK_PLL_GETPARAM = 49,
+	/* PM_REGISTER_ACCESS API */
 	PM_REGISTER_ACCESS = 52,
-	PM_EFUSE_ACCESS,
+	PM_EFUSE_ACCESS = 53,
 	PM_FEATURE_CHECK = 63,
 	PM_API_MAX,
 };
 
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU = 1,
+	NODE_APU_0 = 2,
+	NODE_APU_1 = 3,
+	NODE_APU_2 = 4,
+	NODE_APU_3 = 5,
+	NODE_RPU = 6,
+	NODE_RPU_0 = 7,
+	NODE_RPU_1 = 8,
+	NODE_PLD = 9,
+	NODE_FPD = 10,
+	NODE_OCM_BANK_0 = 11,
+	NODE_OCM_BANK_1 = 12,
+	NODE_OCM_BANK_2 = 13,
+	NODE_OCM_BANK_3 = 14,
+	NODE_TCM_0_A = 15,
+	NODE_TCM_0_B = 16,
+	NODE_TCM_1_A = 17,
+	NODE_TCM_1_B = 18,
+	NODE_L2 = 19,
+	NODE_GPU_PP_0 = 20,
+	NODE_GPU_PP_1 = 21,
+	NODE_USB_0 = 22,
+	NODE_USB_1 = 23,
+	NODE_TTC_0 = 24,
+	NODE_TTC_1 = 25,
+	NODE_TTC_2 = 26,
+	NODE_TTC_3 = 27,
+	NODE_SATA = 28,
+	NODE_ETH_0 = 29,
+	NODE_ETH_1 = 30,
+	NODE_ETH_2 = 31,
+	NODE_ETH_3 = 32,
+	NODE_UART_0 = 33,
+	NODE_UART_1 = 34,
+	NODE_SPI_0 = 35,
+	NODE_SPI_1 = 36,
+	NODE_I2C_0 = 37,
+	NODE_I2C_1 = 38,
+	NODE_SD_0 = 39,
+	NODE_SD_1 = 40,
+	NODE_DP = 41,
+	NODE_GDMA = 42,
+	NODE_ADMA = 43,
+	NODE_NAND = 44,
+	NODE_QSPI = 45,
+	NODE_GPIO = 46,
+	NODE_CAN_0 = 47,
+	NODE_CAN_1 = 48,
+	NODE_EXTERN = 49,
+	NODE_APLL = 50,
+	NODE_VPLL = 51,
+	NODE_DPLL = 52,
+	NODE_RPLL = 53,
+	NODE_IOPLL = 54,
+	NODE_DDR = 55,
+	NODE_IPI_APU = 56,
+	NODE_IPI_RPU_0 = 57,
+	NODE_GPU = 58,
+	NODE_PCIE = 59,
+	NODE_PCAP = 60,
+	NODE_RTC = 61,
+	NODE_LPD = 62,
+	NODE_VCU = 63,
+	NODE_IPI_RPU_1 = 64,
+	NODE_IPI_PL_0 = 65,
+	NODE_IPI_PL_1 = 66,
+	NODE_IPI_PL_2 = 67,
+	NODE_IPI_PL_3 = 68,
+	NODE_PL = 69,
+	NODE_GEM_TSU = 70,
+	NODE_SWDT_0 = 71,
+	NODE_SWDT_1 = 72,
+	NODE_CSU = 73,
+	NODE_PJTAG = 74,
+	NODE_TRACE = 75,
+	NODE_TESTSCAN = 76,
+	NODE_PMU = 77,
+	NODE_MAX = 78,
+};
+
+enum tap_delay_type {
+	PM_TAPDELAY_INPUT = 0,
+	PM_TAPDELAY_OUTPUT = 1,
+};
+
+enum dll_reset_type {
+	PM_DLL_RESET_ASSERT = 0,
+	PM_DLL_RESET_RELEASE = 1,
+	PM_DLL_RESET_PULSE = 2,
+};
+
 enum pm_query_id {
 	PM_QID_INVALID = 0,
 	PM_QID_CLOCK_GET_NAME = 1,
@@ -79,6 +177,171 @@
 	PM_QID_CLOCK_GET_MAX_DIVISOR = 13,
 };
 
+enum zynqmp_pm_reset_action {
+	PM_RESET_ACTION_RELEASE = 0,
+	PM_RESET_ACTION_ASSERT = 1,
+	PM_RESET_ACTION_PULSE = 2,
+};
+
+enum zynqmp_pm_reset {
+	ZYNQMP_PM_RESET_START = 1000,
+	ZYNQMP_PM_RESET_PCIE_CFG = ZYNQMP_PM_RESET_START,
+	ZYNQMP_PM_RESET_PCIE_BRIDGE = 1001,
+	ZYNQMP_PM_RESET_PCIE_CTRL = 1002,
+	ZYNQMP_PM_RESET_DP = 1003,
+	ZYNQMP_PM_RESET_SWDT_CRF = 1004,
+	ZYNQMP_PM_RESET_AFI_FM5 = 1005,
+	ZYNQMP_PM_RESET_AFI_FM4 = 1006,
+	ZYNQMP_PM_RESET_AFI_FM3 = 1007,
+	ZYNQMP_PM_RESET_AFI_FM2 = 1008,
+	ZYNQMP_PM_RESET_AFI_FM1 = 1009,
+	ZYNQMP_PM_RESET_AFI_FM0 = 1010,
+	ZYNQMP_PM_RESET_GDMA = 1011,
+	ZYNQMP_PM_RESET_GPU_PP1 = 1012,
+	ZYNQMP_PM_RESET_GPU_PP0 = 1013,
+	ZYNQMP_PM_RESET_GPU = 1014,
+	ZYNQMP_PM_RESET_GT = 1015,
+	ZYNQMP_PM_RESET_SATA = 1016,
+	ZYNQMP_PM_RESET_ACPU3_PWRON = 1017,
+	ZYNQMP_PM_RESET_ACPU2_PWRON = 1018,
+	ZYNQMP_PM_RESET_ACPU1_PWRON = 1019,
+	ZYNQMP_PM_RESET_ACPU0_PWRON = 1020,
+	ZYNQMP_PM_RESET_APU_L2 = 1021,
+	ZYNQMP_PM_RESET_ACPU3 = 1022,
+	ZYNQMP_PM_RESET_ACPU2 = 1023,
+	ZYNQMP_PM_RESET_ACPU1 = 1024,
+	ZYNQMP_PM_RESET_ACPU0 = 1025,
+	ZYNQMP_PM_RESET_DDR = 1026,
+	ZYNQMP_PM_RESET_APM_FPD = 1027,
+	ZYNQMP_PM_RESET_SOFT = 1028,
+	ZYNQMP_PM_RESET_GEM0 = 1029,
+	ZYNQMP_PM_RESET_GEM1 = 1030,
+	ZYNQMP_PM_RESET_GEM2 = 1031,
+	ZYNQMP_PM_RESET_GEM3 = 1032,
+	ZYNQMP_PM_RESET_QSPI = 1033,
+	ZYNQMP_PM_RESET_UART0 = 1034,
+	ZYNQMP_PM_RESET_UART1 = 1035,
+	ZYNQMP_PM_RESET_SPI0 = 1036,
+	ZYNQMP_PM_RESET_SPI1 = 1037,
+	ZYNQMP_PM_RESET_SDIO0 = 1038,
+	ZYNQMP_PM_RESET_SDIO1 = 1039,
+	ZYNQMP_PM_RESET_CAN0 = 1040,
+	ZYNQMP_PM_RESET_CAN1 = 1041,
+	ZYNQMP_PM_RESET_I2C0 = 1042,
+	ZYNQMP_PM_RESET_I2C1 = 1043,
+	ZYNQMP_PM_RESET_TTC0 = 1044,
+	ZYNQMP_PM_RESET_TTC1 = 1045,
+	ZYNQMP_PM_RESET_TTC2 = 1046,
+	ZYNQMP_PM_RESET_TTC3 = 1047,
+	ZYNQMP_PM_RESET_SWDT_CRL = 1048,
+	ZYNQMP_PM_RESET_NAND = 1049,
+	ZYNQMP_PM_RESET_ADMA = 1050,
+	ZYNQMP_PM_RESET_GPIO = 1051,
+	ZYNQMP_PM_RESET_IOU_CC = 1052,
+	ZYNQMP_PM_RESET_TIMESTAMP = 1053,
+	ZYNQMP_PM_RESET_RPU_R50 = 1054,
+	ZYNQMP_PM_RESET_RPU_R51 = 1055,
+	ZYNQMP_PM_RESET_RPU_AMBA = 1056,
+	ZYNQMP_PM_RESET_OCM = 1057,
+	ZYNQMP_PM_RESET_RPU_PGE = 1058,
+	ZYNQMP_PM_RESET_USB0_CORERESET = 1059,
+	ZYNQMP_PM_RESET_USB1_CORERESET = 1060,
+	ZYNQMP_PM_RESET_USB0_HIBERRESET = 1061,
+	ZYNQMP_PM_RESET_USB1_HIBERRESET = 1062,
+	ZYNQMP_PM_RESET_USB0_APB = 1063,
+	ZYNQMP_PM_RESET_USB1_APB = 1064,
+	ZYNQMP_PM_RESET_IPI = 1065,
+	ZYNQMP_PM_RESET_APM_LPD = 1066,
+	ZYNQMP_PM_RESET_RTC = 1067,
+	ZYNQMP_PM_RESET_SYSMON = 1068,
+	ZYNQMP_PM_RESET_AFI_FM6 = 1069,
+	ZYNQMP_PM_RESET_LPD_SWDT = 1070,
+	ZYNQMP_PM_RESET_FPD = 1071,
+	ZYNQMP_PM_RESET_RPU_DBG1 = 1072,
+	ZYNQMP_PM_RESET_RPU_DBG0 = 1073,
+	ZYNQMP_PM_RESET_DBG_LPD = 1074,
+	ZYNQMP_PM_RESET_DBG_FPD = 1075,
+	ZYNQMP_PM_RESET_APLL = 1076,
+	ZYNQMP_PM_RESET_DPLL = 1077,
+	ZYNQMP_PM_RESET_VPLL = 1078,
+	ZYNQMP_PM_RESET_IOPLL = 1079,
+	ZYNQMP_PM_RESET_RPLL = 1080,
+	ZYNQMP_PM_RESET_GPO3_PL_0 = 1081,
+	ZYNQMP_PM_RESET_GPO3_PL_1 = 1082,
+	ZYNQMP_PM_RESET_GPO3_PL_2 = 1083,
+	ZYNQMP_PM_RESET_GPO3_PL_3 = 1084,
+	ZYNQMP_PM_RESET_GPO3_PL_4 = 1085,
+	ZYNQMP_PM_RESET_GPO3_PL_5 = 1086,
+	ZYNQMP_PM_RESET_GPO3_PL_6 = 1087,
+	ZYNQMP_PM_RESET_GPO3_PL_7 = 1088,
+	ZYNQMP_PM_RESET_GPO3_PL_8 = 1089,
+	ZYNQMP_PM_RESET_GPO3_PL_9 = 1090,
+	ZYNQMP_PM_RESET_GPO3_PL_10 = 1091,
+	ZYNQMP_PM_RESET_GPO3_PL_11 = 1092,
+	ZYNQMP_PM_RESET_GPO3_PL_12 = 1093,
+	ZYNQMP_PM_RESET_GPO3_PL_13 = 1094,
+	ZYNQMP_PM_RESET_GPO3_PL_14 = 1095,
+	ZYNQMP_PM_RESET_GPO3_PL_15 = 1096,
+	ZYNQMP_PM_RESET_GPO3_PL_16 = 1097,
+	ZYNQMP_PM_RESET_GPO3_PL_17 = 1098,
+	ZYNQMP_PM_RESET_GPO3_PL_18 = 1099,
+	ZYNQMP_PM_RESET_GPO3_PL_19 = 1100,
+	ZYNQMP_PM_RESET_GPO3_PL_20 = 1101,
+	ZYNQMP_PM_RESET_GPO3_PL_21 = 1102,
+	ZYNQMP_PM_RESET_GPO3_PL_22 = 1103,
+	ZYNQMP_PM_RESET_GPO3_PL_23 = 1104,
+	ZYNQMP_PM_RESET_GPO3_PL_24 = 1105,
+	ZYNQMP_PM_RESET_GPO3_PL_25 = 1106,
+	ZYNQMP_PM_RESET_GPO3_PL_26 = 1107,
+	ZYNQMP_PM_RESET_GPO3_PL_27 = 1108,
+	ZYNQMP_PM_RESET_GPO3_PL_28 = 1109,
+	ZYNQMP_PM_RESET_GPO3_PL_29 = 1110,
+	ZYNQMP_PM_RESET_GPO3_PL_30 = 1111,
+	ZYNQMP_PM_RESET_GPO3_PL_31 = 1112,
+	ZYNQMP_PM_RESET_RPU_LS = 1113,
+	ZYNQMP_PM_RESET_PS_ONLY = 1114,
+	ZYNQMP_PM_RESET_PL = 1115,
+	ZYNQMP_PM_RESET_PS_PL0 = 1116,
+	ZYNQMP_PM_RESET_PS_PL1 = 1117,
+	ZYNQMP_PM_RESET_PS_PL2 = 1118,
+	ZYNQMP_PM_RESET_PS_PL3 = 1119,
+	ZYNQMP_PM_RESET_END = ZYNQMP_PM_RESET_PS_PL3
+};
+
+enum pm_ioctl_id {
+	IOCTL_GET_RPU_OPER_MODE = 0,
+	IOCTL_SET_RPU_OPER_MODE = 1,
+	IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
+	IOCTL_TCM_COMB_CONFIG = 3,
+	IOCTL_SET_TAPDELAY_BYPASS = 4,
+	IOCTL_SET_SGMII_MODE = 5,
+	IOCTL_SD_DLL_RESET = 6,
+	IOCTL_SET_SD_TAPDELAY = 7,
+	IOCTL_SET_PLL_FRAC_MODE = 8,
+	IOCTL_GET_PLL_FRAC_MODE = 9,
+	IOCTL_SET_PLL_FRAC_DATA = 10,
+	IOCTL_GET_PLL_FRAC_DATA = 11,
+	IOCTL_WRITE_GGS = 12,
+	IOCTL_READ_GGS = 13,
+	IOCTL_WRITE_PGGS = 14,
+	IOCTL_READ_PGGS = 15,
+	/* IOCTL for ULPI reset */
+	IOCTL_ULPI_RESET = 16,
+	/* Set healthy bit value*/
+	IOCTL_SET_BOOT_HEALTH_STATUS = 17,
+	IOCTL_AFI = 18,
+	/* Probe counter read/write */
+	IOCTL_PROBE_COUNTER_READ = 19,
+	IOCTL_PROBE_COUNTER_WRITE = 20,
+	IOCTL_OSPI_MUX_SELECT = 21,
+	/* IOCTL for USB power request */
+	IOCTL_USB_SET_STATE = 22,
+	/* IOCTL to get last reset reason */
+	IOCTL_GET_LAST_RESET_REASON = 23,
+	/* AIE ISR Clear */
+	IOCTL_AIE_ISR_CLEAR = 24,
+};
+
 #define PM_SIP_SVC      0xc2000000
 
 #define ZYNQMP_PM_VERSION_MAJOR         1
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
deleted file mode 100644
index 1c1e3e7..0000000
--- a/include/zynqmp_tap_delay.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Xilinx ZynqMP SoC Tap Delay Programming
- *
- * Copyright (C) 2018 Xilinx, Inc.
- */
-
-#ifndef __ZYNQMP_TAP_DELAY_H__
-#define __ZYNQMP_TAP_DELAY_H__
-
-#ifdef CONFIG_ARCH_ZYNQMP
-void zynqmp_dll_reset(u8 deviceid);
-void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
-void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
-#else
-inline void zynqmp_dll_reset(u8 deviceid) {}
-inline void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) {}
-inline void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) {}
-#endif
-
-#endif