diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6b65d8e76a46fcf259c13bfe5fec77b0219816bd..729b1816bf7ec4bfb87567d477860d189b3fc7c4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -594,6 +594,7 @@ config ARCH_ZYNQMP
 	select DM
 	select OF_CONTROL
 	select DM_SERIAL
+	select SUPPORT_SPL
 
 config TEGRA
 	bool "NVIDIA Tegra"
diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile
index d0ed2223ff7973b27e24cb936546bcf81bb58b85..be8673a7db4410a4e2a3039030a67723c8cb29cc 100644
--- a/arch/arm/cpu/armv8/zynqmp/Makefile
+++ b/arch/arm/cpu/armv8/zynqmp/Makefile
@@ -9,3 +9,4 @@ obj-y	+= clk.o
 obj-y	+= cpu.o
 obj-$(CONFIG_MP)	+= mp.o
 obj-y	+= slcr.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c
new file mode 100644
index 0000000000000000000000000000000000000000..e3e2a4fb5ad3dcd3ec6f60f4a5d54938e8855c8b
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/spl.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2015 - 2016 Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <spl.h>
+
+#include <asm/io.h>
+#include <asm/spl.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+void board_init_f(ulong dummy)
+{
+	psu_init();
+	board_early_init_r();
+
+#ifdef CONFIG_DEBUG_UART
+	/* Uart debug for sure */
+	debug_uart_init();
+	puts("Debug uart enabled\n"); /* or printch() */
+#endif
+	/* Delay is required for clocks to be propagated */
+	udelay(1000000);
+
+	/* Clear the BSS */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* No need to call timer init - it is empty for ZynqMP */
+	board_init_r(NULL, 0);
+}
+
+#ifdef CONFIG_SPL_BOARD_INIT
+void spl_board_init(void)
+{
+	preloader_console_init();
+	board_init();
+}
+#endif
+
+u32 spl_boot_device(void)
+{
+	u32 reg = 0;
+	u8 bootmode;
+
+	reg = readl(&crlapb_base->boot_mode);
+	bootmode = reg & BOOT_MODES_MASK;
+
+	switch (bootmode) {
+	case JTAG_MODE:
+		return BOOT_DEVICE_RAM;
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	case EMMC_MODE:
+	case SD_MODE:
+	case SD_MODE1:
+		return BOOT_DEVICE_MMC1;
+#endif
+	default:
+		printf("Invalid Boot Mode:0x%x\n", bootmode);
+		break;
+	}
+
+	return 0;
+}
+
+u32 spl_boot_mode(void)
+{
+	switch (spl_boot_device()) {
+	case BOOT_DEVICE_RAM:
+		return 0;
+	case BOOT_DEVICE_MMC1:
+		return MMCSD_MODE_FS;
+	default:
+		puts("spl: error: unsupported device\n");
+		hang();
+	}
+}
+
+__weak void psu_init(void)
+{
+	 /*
+	  * This function is overridden by the one in
+	  * board/xilinx/zynqmp/(platform)/psu_init_gpl.c, if it exists.
+	  */
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+int spl_start_uboot(void)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
index a327557c19cce38af45a4c9a82c66ef0ec046ab6..b618a3f484f0e507948bdff1017cc01ec40a4e26 100644
--- a/arch/arm/dts/zynq-7000.dtsi
+++ b/arch/arm/dts/zynq-7000.dtsi
@@ -251,7 +251,7 @@
 		slcr: slcr@f8000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
-			compatible = "xlnx,zynq-slcr", "syscon", "simple-bus";
+			compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
 			reg = <0xF8000000 0x1000>;
 			ranges;
 			clkc: clkc@100 {
diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index fb95b4828b90a7b0cf2fddbf55306f836a49fee6..619450e1ba92c4d55965879b7ab567c0efe0e4f9 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -253,9 +253,9 @@
 			compatible = "arm,gic-400", "arm,cortex-a15-gic";
 			#interrupt-cells = <3>;
 			reg = <0x0 0xf9010000 0x10000>,
-			      <0x0 0xf902f000 0x2000>,
+			      <0x0 0xf9020000 0x20000>,
 			      <0x0 0xf9040000 0x20000>,
-			      <0x0 0xf906f000 0x2000>;
+			      <0x0 0xf9060000 0x20000>;
 			interrupt-controller;
 			interrupt-parent = <&gic>;
 			interrupts = <1 9 0xf04>;
@@ -264,6 +264,7 @@
 
 	amba: amba {
 		compatible = "simple-bus";
+		u-boot,dm-pre-reloc;
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <0 0 0 0 0xffffffff>;
@@ -674,6 +675,7 @@
 		};
 
 		sdhci0: sdhci@ff160000 {
+			u-boot,dm-pre-reloc;
 			compatible = "arasan,sdhci-8.9a";
 			status = "disabled";
 			interrupt-parent = <&gic>;
@@ -685,6 +687,7 @@
 		};
 
 		sdhci1: sdhci@ff170000 {
+			u-boot,dm-pre-reloc;
 			compatible = "arasan,sdhci-8.9a";
 			status = "disabled";
 			interrupt-parent = <&gic>;
@@ -776,6 +779,7 @@
 		};
 
 		uart0: serial@ff000000 {
+			u-boot,dm-pre-reloc;
 			compatible = "cdns,uart-r1p12", "xlnx,xuartps";
 			status = "disabled";
 			interrupt-parent = <&gic>;
@@ -786,6 +790,7 @@
 		};
 
 		uart1: serial@ff010000 {
+			u-boot,dm-pre-reloc;
 			compatible = "cdns,uart-r1p12", "xlnx,xuartps";
 			status = "disabled";
 			interrupt-parent = <&gic>;
diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
index 021626dc1403f0dd2c8865c24d2ff2317164f889..1db2bd6a4f7a227700f5b09a910aab31b78d3dbd 100644
--- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
@@ -17,4 +17,6 @@ int zynq_slcr_get_mio_pin_status(const char *periph);
 
 unsigned int zynqmp_get_silicon_version(void);
 
+void psu_init(void);
+
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index d396a13b6f7c41d858a61ac0ffe16a669128b9d1..db3c5792939e837d9445de839e5e6867d75e50b3 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -1,41 +1,5 @@
 if ARCH_ZYNQ
 
-config ZYNQ_CUSTOM_INIT
-	bool "Use custom ps7_init provided by Xilinx tool"
-	help
-	  U-Boot includes ps7_init_gpl.[ch] for some Zynq board variants.
-	  If you want to override them with customized ones
-	  or ps7_init code for your board is missing, please say Y here
-	  and add ones into board/xilinx/zynq/custom_hw_platform/ directory.
-
-choice
-	prompt "Xilinx Zynq board select"
-	default TARGET_ZYNQ_ZC702
-
-config TARGET_ZYNQ_ZED
-	bool "Zynq ZedBoard"
-
-config TARGET_ZYNQ_MICROZED
-	bool "Zynq MicroZed"
-
-config TARGET_ZYNQ_PICOZED
-	bool "Zynq PicoZed"
-
-config TARGET_ZYNQ_ZC702
-	bool "Zynq ZC702 Board"
-
-config TARGET_ZYNQ_ZC706
-	bool "Zynq ZC706 Board"
-
-config TARGET_ZYNQ_ZC770
-	bool "Zynq ZC770 Board"
-	select ZYNQ_CUSTOM_INIT
-
-config TARGET_ZYNQ_ZYBO
-	bool "Zynq Zybo Board"
-
-endchoice
-
 config SYS_BOARD
 	default "zynq"
 
@@ -46,11 +10,11 @@ config SYS_SOC
 	default "zynq"
 
 config SYS_CONFIG_NAME
-	default "zynq_zed" if TARGET_ZYNQ_ZED
-	default "zynq_microzed" if TARGET_ZYNQ_MICROZED
-	default "zynq_picozed" if TARGET_ZYNQ_PICOZED
-	default "zynq_zc70x" if TARGET_ZYNQ_ZC702 || TARGET_ZYNQ_ZC706
-	default "zynq_zc770" if TARGET_ZYNQ_ZC770
-	default "zynq_zybo" if TARGET_ZYNQ_ZYBO
+	string "Board configuration name"
+	default "zynq-common"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
 
 endif
diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index 723019d25279b15dedfffac977eb98d9ab37d4f2..6c5415ac8f5360a936f2219e512f2258b8778061 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -90,3 +90,28 @@ __weak void ps7_init(void)
 	 * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists.
 	 */
 }
+
+__weak int ps7_post_config(void)
+{
+	/*
+	 * This function is overridden by the one in
+	 * board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists.
+	 */
+	return 0;
+}
+
+void spl_board_prepare_for_boot(void)
+{
+	ps7_post_config();
+	debug("SPL bye\n");
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
index eab93038cefee8ad9130148b5fe77aed72b65e0c..7de0212bc9f79a7571f0d11be0e451ab3cb02d88 100644
--- a/board/xilinx/zynq/Makefile
+++ b/board/xilinx/zynq/Makefile
@@ -7,17 +7,7 @@
 
 obj-y	:= board.o
 
-# Copied from Xilinx SDK 2014.4
-hw-platform-$(CONFIG_TARGET_ZYNQ_ZED)		:= zed_hw_platform
-hw-platform-$(CONFIG_TARGET_ZYNQ_MICROZED)	:= MicroZed_hw_platform
-hw-platform-$(CONFIG_TARGET_ZYNQ_ZC702)		:= ZC702_hw_platform
-hw-platform-$(CONFIG_TARGET_ZYNQ_ZC706)		:= ZC706_hw_platform
-hw-platform-$(CONFIG_TARGET_ZYNQ_ZYBO)		:= zybo_hw_platform
-# If you want to use customized ps7_init_gpl.c/h,
-# enable CONFIG_ZYNQ_CUSTOM_INIT and put them into custom_hw_platform/.
-# This line must be placed at the bottom of the list because
-# it takes precedence over the default ones.
-hw-platform-$(CONFIG_ZYNQ_CUSTOM_INIT)		:= custom_hw_platform
+hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE))
 
 init-objs := $(if $(wildcard $(srctree)/$(src)/$(hw-platform-y)/ps7_init_gpl.c),\
 	$(hw-platform-y)/ps7_init_gpl.o)
diff --git a/board/xilinx/zynq/custom_hw_platform/.gitignore b/board/xilinx/zynq/custom_hw_platform/.gitignore
deleted file mode 100644
index c455361df625752a7953a1c9007734339049e5a0..0000000000000000000000000000000000000000
--- a/board/xilinx/zynq/custom_hw_platform/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-ps7_init_gpl.[ch]
diff --git a/board/xilinx/zynq/MicroZed_hw_platform/ps7_init_gpl.c b/board/xilinx/zynq/zynq-microzed/ps7_init_gpl.c
similarity index 100%
rename from board/xilinx/zynq/MicroZed_hw_platform/ps7_init_gpl.c
rename to board/xilinx/zynq/zynq-microzed/ps7_init_gpl.c
diff --git a/board/xilinx/zynq/MicroZed_hw_platform/ps7_init_gpl.h b/board/xilinx/zynq/zynq-microzed/ps7_init_gpl.h
similarity index 100%
rename from board/xilinx/zynq/MicroZed_hw_platform/ps7_init_gpl.h
rename to board/xilinx/zynq/zynq-microzed/ps7_init_gpl.h
diff --git a/board/xilinx/zynq/ZC702_hw_platform/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zc702/ps7_init_gpl.c
similarity index 100%
rename from board/xilinx/zynq/ZC702_hw_platform/ps7_init_gpl.c
rename to board/xilinx/zynq/zynq-zc702/ps7_init_gpl.c
diff --git a/board/xilinx/zynq/ZC702_hw_platform/ps7_init_gpl.h b/board/xilinx/zynq/zynq-zc702/ps7_init_gpl.h
similarity index 100%
rename from board/xilinx/zynq/ZC702_hw_platform/ps7_init_gpl.h
rename to board/xilinx/zynq/zynq-zc702/ps7_init_gpl.h
diff --git a/board/xilinx/zynq/ZC706_hw_platform/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zc706/ps7_init_gpl.c
similarity index 100%
rename from board/xilinx/zynq/ZC706_hw_platform/ps7_init_gpl.c
rename to board/xilinx/zynq/zynq-zc706/ps7_init_gpl.c
diff --git a/board/xilinx/zynq/ZC706_hw_platform/ps7_init_gpl.h b/board/xilinx/zynq/zynq-zc706/ps7_init_gpl.h
similarity index 100%
rename from board/xilinx/zynq/ZC706_hw_platform/ps7_init_gpl.h
rename to board/xilinx/zynq/zynq-zc706/ps7_init_gpl.h
diff --git a/board/xilinx/zynq/zed_hw_platform/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zed/ps7_init_gpl.c
similarity index 100%
rename from board/xilinx/zynq/zed_hw_platform/ps7_init_gpl.c
rename to board/xilinx/zynq/zynq-zed/ps7_init_gpl.c
diff --git a/board/xilinx/zynq/zed_hw_platform/ps7_init_gpl.h b/board/xilinx/zynq/zynq-zed/ps7_init_gpl.h
similarity index 100%
rename from board/xilinx/zynq/zed_hw_platform/ps7_init_gpl.h
rename to board/xilinx/zynq/zynq-zed/ps7_init_gpl.h
diff --git a/board/xilinx/zynq/zybo_hw_platform/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zybo/ps7_init_gpl.c
similarity index 100%
rename from board/xilinx/zynq/zybo_hw_platform/ps7_init_gpl.c
rename to board/xilinx/zynq/zynq-zybo/ps7_init_gpl.c
diff --git a/board/xilinx/zynq/zybo_hw_platform/ps7_init_gpl.h b/board/xilinx/zynq/zynq-zybo/ps7_init_gpl.h
similarity index 100%
rename from board/xilinx/zynq/zybo_hw_platform/ps7_init_gpl.h
rename to board/xilinx/zynq/zynq-zybo/ps7_init_gpl.h
diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 2ab3f190ac30c7f7bb277f204ea2e41de4754bf8..90f00c650a816a52f55a6d1184d85c3a9da49e52 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -1,8 +1,29 @@
 #
-# (C) Copyright 2014 - 2015 Xilinx, Inc.
+# (C) Copyright 2014 - 2016 Xilinx, Inc.
 # Michal Simek <michal.simek@xilinx.com>
 #
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
 obj-y	:= zynqmp.o
+
+hw-platform-y :=$(shell echo $(CONFIG_SYS_CONFIG_NAME))
+
+init-objs := $(if $(wildcard $(srctree)/$(src)/$(hw-platform-y)/psu_init_gpl.c),\
+	$(hw-platform-y)/psu_init_gpl.o)
+
+ifeq ($(init-objs),)
+ifneq ($(wildcard $(srctree)/$(src)/psu_init_gpl.c),)
+init-objs := psu_init_gpl.o
+$(if $(CONFIG_SPL_BUILD),\
+$(warning Put custom psu_init_gpl.c/h to board/xilinx/zynqmp/custom_hw_platform/))
+endif
+endif
+
+obj-$(CONFIG_SPL_BUILD) += $(init-objs)
+
+# Suppress "warning: function declaration isn't a prototype"
+CFLAGS_REMOVE_psu_init_gpl.o := -Wstrict-prototypes
+
+# To include xil_io.h
+CFLAGS_psu_init_gpl.o := -I$(srctree)/$(src)
diff --git a/board/xilinx/zynqmp/xil_io.h b/board/xilinx/zynqmp/xil_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..57ca4adf11bf42adfbf6911f32de36d1045ec9e2
--- /dev/null
+++ b/board/xilinx/zynqmp/xil_io.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef XIL_IO_H /* prevent circular inclusions */
+#define XIL_IO_H
+
+/* FIXME remove this when vivado is fixed */
+#include <asm/io.h>
+
+#define xil_printf(...)
+
+void Xil_ICacheEnable(void)
+{}
+
+void Xil_DCacheEnable(void)
+{}
+
+void Xil_ICacheDisable(void)
+{}
+
+void Xil_DCacheDisable(void)
+{}
+
+void Xil_Out32(unsigned long addr, unsigned long val)
+{
+	writel(val, addr);
+}
+
+int Xil_In32(unsigned long addr)
+{
+	return readl(addr);
+}
+
+#endif /* XIL_IO_H */
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 132d724fbdf8a9638dbe21a8d95d867fe8fb186d..4623cd49e9c797f309540fb618e5076a2bee82a8 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -15,6 +15,7 @@
 #include <asm/io.h>
 #include <usb.h>
 #include <dwc3-uboot.h>
+#include <i2c.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -50,6 +51,22 @@ int board_early_init_r(void)
 	return 0;
 }
 
+int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
+{
+#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
+    defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
+    defined(CONFIG_ZYNQ_EEPROM_BUS)
+	i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
+
+	if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
+			CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
+			ethaddr, 6))
+		printf("I2C EEPROM MAC address read failed\n");
+#endif
+
+	return 0;
+}
+
 #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
 /*
  * fdt_get_reg - Fill buffer by information from DT
diff --git a/common/bootm.c b/common/bootm.c
index c965326db4169de9a1254282029751ecedc266e0..49414142dcd207902b96a7e93a64923c121e71ba 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -246,6 +246,16 @@ int bootm_find_images(int flag, int argc, char * const argv[])
 #endif
 
 #if IMAGE_ENABLE_FIT
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX)
+	/* find bitstreams */
+	ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT,
+			    NULL, NULL);
+	if (ret) {
+		printf("FPGA image is corrupted or invalid\n");
+		return 1;
+	}
+#endif
+
 	/* find all of the loadables */
 	ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
 			       NULL, NULL);
diff --git a/common/image-fit.c b/common/image-fit.c
index c86b7c6b1182e42e3febf94caaa3604628f809c6..98739572a1bdc9a585432d46acc7ad304fe5ef01 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -422,7 +422,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
 	}
 
 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-	    (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
+	    (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) ||
+	    (type == IH_TYPE_FPGA)) {
 		ret = fit_image_get_load(fit, image_noffset, &load);
 		printf("%s  Load Address: ", p);
 		if (ret)
@@ -1483,6 +1484,10 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
 	if (uname)
 		printf("%s  FDT:          %s\n", p, uname);
 
+	uname = (char *)fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
+	if (uname)
+		printf("%s  FPGA:         %s\n", p, uname);
+
 	/* Print out all of the specified loadables */
 	for (loadables_index = 0;
 	     fdt_get_string_index(fit, noffset,
@@ -1567,6 +1572,8 @@ static const char *fit_get_image_type_property(int type)
 		return FIT_SETUP_PROP;
 	case IH_TYPE_LOADABLE:
 		return FIT_LOADABLE_PROP;
+	case IH_TYPE_FPGA:
+		return FIT_FPGA_PROP;
 	}
 
 	return "unknown";
@@ -1681,7 +1688,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 			fit_image_check_type(fit, noffset,
 					     IH_TYPE_KERNEL_NOLOAD));
 
-	os_ok = image_type == IH_TYPE_FLATDT ||
+	os_ok = image_type == IH_TYPE_FLATDT || IH_TYPE_FPGA ||
 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
 
diff --git a/common/image.c b/common/image.c
index 26d6c9a59279f9953643996c17fdbd123c8830c1..0be09e5c6306df7973b3a45e00c6c891cef7ee26 100644
--- a/common/image.c
+++ b/common/image.c
@@ -32,6 +32,8 @@
 #if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fpga.h>
+#include <xilinx.h>
 #endif
 
 #include <u-boot/md5.h>
@@ -159,6 +161,8 @@ static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_RKSD,       "rksd",       "Rockchip SD Boot Image" },
 	{	IH_TYPE_RKSPI,      "rkspi",      "Rockchip SPI Boot Image" },
 	{	IH_TYPE_ZYNQIMAGE,  "zynqimage",  "Xilinx Zynq Boot Image" },
+	{	IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" },
+	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
 	{	-1,		    "",		  "",			},
 };
 
@@ -1210,6 +1214,96 @@ int boot_get_setup(bootm_headers_t *images, uint8_t arch,
 }
 
 #if IMAGE_ENABLE_FIT
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX)
+int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
+		  uint8_t arch, const ulong *ld_start, ulong * const ld_len)
+{
+	ulong tmp_img_addr, img_data, img_len;
+	void *buf;
+	int conf_noffset;
+	int fit_img_result;
+	char *uname, *name;
+	int err;
+	int devnum = 0; /* TODO support multi fpga platforms */
+	const fpga_desc * const desc = fpga_get_desc(devnum);
+	xilinx_desc *desc_xilinx = desc->devdesc;
+
+	/* Check to see if the images struct has a FIT configuration */
+	if (!genimg_has_config(images)) {
+		debug("## FIT configuration was not specified\n");
+		return 0;
+	}
+
+	/*
+	 * Obtain the os FIT header from the images struct
+	 * copy from dataflash if needed
+	 */
+	tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
+	tmp_img_addr = genimg_get_image(tmp_img_addr);
+	buf = map_sysmem(tmp_img_addr, 0);
+	/*
+	 * Check image type. For FIT images get FIT node
+	 * and attempt to locate a generic binary.
+	 */
+	switch (genimg_get_format(buf)) {
+	case IMAGE_FORMAT_FIT:
+		conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
+
+		err = fdt_get_string_index(buf, conf_noffset, FIT_FPGA_PROP, 0,
+					   (const char **)&uname);
+		if (err < 0) {
+			debug("## FPGA image is not specified\n");
+			return 0;
+		}
+		fit_img_result = fit_image_load(images,
+						tmp_img_addr,
+						(const char **)&uname,
+						&(images->fit_uname_cfg),
+						arch,
+						IH_TYPE_FPGA,
+						BOOTSTAGE_ID_FPGA_INIT,
+						FIT_LOAD_OPTIONAL_NON_ZERO,
+						&img_data, &img_len);
+
+		debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n",
+		      uname, img_data, img_len);
+
+		if (fit_img_result < 0) {
+			/* Something went wrong! */
+			return fit_img_result;
+		}
+
+		if (img_len >= desc_xilinx->size) {
+			name = "full";
+			err = fpga_loadbitstream(devnum, (char *)img_data,
+						 img_len, BIT_FULL);
+			if (err)
+				err = fpga_load(devnum, (const void *)img_data,
+						img_len, BIT_FULL);
+		} else {
+			name = "partial";
+			err = fpga_loadbitstream(devnum, (char *)img_data,
+						 img_len, BIT_PARTIAL);
+			if (err)
+				err = fpga_load(devnum, (const void *)img_data,
+						img_len, BIT_PARTIAL);
+		}
+
+		printf("   Programming %s bitstream... ", name);
+		if (err)
+			printf("failed\n");
+		else
+			printf("OK\n");
+		break;
+	default:
+		printf("The given image format is not supported (corrupt?)\n");
+		return 1;
+	}
+
+	return 0;
+}
+#endif
+
 int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
 		uint8_t arch, const ulong *ld_start, ulong * const ld_len)
 {
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 93f9bd13fcd9b4995c2d69fa3293180f3a48bedc..bdde71691887f3f8d461b0b3e46bd3159468b940 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -64,6 +64,11 @@ __weak void spl_board_prepare_for_linux(void)
 	/* Nothing to do! */
 }
 
+__weak void spl_board_prepare_for_boot(void)
+{
+	/* Nothing to do! */
+}
+
 void spl_set_header_raw_uboot(void)
 {
 	spl_image.size = CONFIG_SYS_MONITOR_LEN;
@@ -135,20 +140,47 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 	image_entry();
 }
 
+#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS
+# define CONFIG_SPL_LOAD_FIT_ADDRESS	0
+#endif
+
 #ifdef CONFIG_SPL_RAM_DEVICE
+static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
+			       ulong count, void *buf)
+{
+	debug("%s: sector %lx, count %lx, buf %lx\n",
+	      __func__, sector, count, (ulong)buf);
+	memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count);
+	return count;
+}
+
 static int spl_ram_load_image(void)
 {
-	const struct image_header *header;
+	struct image_header *header;
 
-	/*
-	 * Get the header.  It will point to an address defined by handoff
-	 * which will tell where the image located inside the flash. For
-	 * now, it will temporary fixed to address pointed by U-Boot.
-	 */
-	header = (struct image_header *)
-		(CONFIG_SYS_TEXT_BASE -	sizeof(struct image_header));
+	header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS;
+
+	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
+	    image_get_magic(header) == FDT_MAGIC) {
+		struct spl_load_info load;
+
+		debug("Found FIT\n");
+		load.bl_len = 1;
+		load.read = spl_ram_load_read;
+		spl_load_simple_fit(&load, 0, header);
+	} else {
+		debug("Legacy image\n");
+		/*
+		 * Get the header.  It will point to an address defined by
+		 * handoff which will tell where the image located inside
+		 * the flash. For now, it will temporary fixed to address
+		 * pointed by U-Boot.
+		 */
+		header = (struct image_header *)
+			(CONFIG_SYS_TEXT_BASE -	sizeof(struct image_header));
 
-	spl_parse_image_header(header);
+		spl_parse_image_header(header);
+	}
 
 	return 0;
 }
@@ -404,6 +436,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 #endif
 
 	debug("loaded - jumping to U-Boot...");
+	spl_board_prepare_for_boot();
 	jump_to_image_no_args(&spl_image);
 }
 
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index b185593dc99df2fbd613f96df13f66ff76df611b..37b80522d01ea068b8b0052fdf4a7872d086801b 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -40,12 +40,21 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_NAND_ARASAN=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=25000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_USB=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index cc08b03842d49491fce13598b798e1e11e54d3ce..fa761e5fbbbb5373634fce7a7a8a8a4445d921c7 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -8,6 +8,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm015-dc1"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
@@ -30,6 +31,8 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
 CONFIG_ZYNQ_SDHCI=y
@@ -40,6 +43,11 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_USB=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index 14d24a03bfba1e92ee35a590ae435445a3ad661e..2811d4bb0cfa15d91c47e72661f2386408ab618f 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -8,6 +8,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm016-dc2"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
@@ -29,6 +30,8 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
 CONFIG_NAND_ARASAN=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
index e1e11b7011c41f58f11eb9453efb03fd4a47342e..37110841427fd3b14912e2cf07d2bce70a3521af 100644
--- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm019-dc5"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
@@ -25,6 +26,8 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_SYS_I2C_CADENCE=y
 CONFIG_DM_MMC=y
 CONFIG_ZYNQ_SDHCI=y
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index 6f1cff8c65d805485b1a48fc9bf19e6142032b10..46a5dd02233a53833d7fff21957ea8a03a7bd0ff 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
@@ -29,6 +30,8 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_DM_MMC=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_SPI_FLASH=y
@@ -38,6 +41,11 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_USB=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index a8982a04a56e550b5f12d83fed4c9fb6df785f21..96a2be11d5bdc67ac82679828c7ba52af1b76bc0 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
@@ -29,6 +30,8 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
 CONFIG_DM_MMC=y
 CONFIG_ZYNQ_SDHCI=y
 CONFIG_SPI_FLASH=y
@@ -38,6 +41,11 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_USB=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index 7c66247d3eefe5d6b4a89a5c6f08a09d69ce8d78..d0b1ec9463b7aef7bc3ef60561d35df3bad12e8a 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_microzed"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_MICROZED=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig
index b46ab44b7848cfeb12031bd3b208f7719dcfc2ff..36244248667d9159d1aee779f3605431089614b6 100644
--- a/configs/zynq_picozed_defconfig
+++ b/configs/zynq_picozed_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_picozed"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_PICOZED=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed"
 CONFIG_SPL=y
 CONFIG_HUSH_PARSER=y
diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig
index 052679a1dc9c22569adea1fd35629727948c1259..e1b1fc93576cd5cf8e65720789395a752991e43b 100644
--- a/configs/zynq_zc702_defconfig
+++ b/configs/zynq_zc702_defconfig
@@ -1,4 +1,5 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc70x"
 CONFIG_ARCH_ZYNQ=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702"
 CONFIG_SPL=y
diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig
index 3539f0547f5bbfeee7ed9bfc7f1e5a6b6af8439b..63d32d90ddd0a08fe7576efdfe87a6b4e56a4be2 100644
--- a/configs/zynq_zc706_defconfig
+++ b/configs/zynq_zc706_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc70x"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZC706=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig
index 6a4726cb9a3616a9a53969b91c972aaadd853b29..6ccbb8ce68dcafa0de7330004624e16cb63b3321 100644
--- a/configs/zynq_zc770_xm010_defconfig
+++ b/configs/zynq_zc770_xm010_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zc770_xm011_defconfig b/configs/zynq_zc770_xm011_defconfig
index 46dd6bee191cd7b9c74119ab9b71212ec8425aa7..e6c646be6e6a4991150cfa8af413bc6ea51ee532 100644
--- a/configs/zynq_zc770_xm011_defconfig
+++ b/configs/zynq_zc770_xm011_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm011"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig
index 12f0e2ca3bb80cde3b2f04e0f067e2082dfe6d02..a8cfeb8988b3aae75b1c0da5b1d1cd665a25c791 100644
--- a/configs/zynq_zc770_xm012_defconfig
+++ b/configs/zynq_zc770_xm012_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig
index 8c7efe53208c546923a808120dd331bc503afbaf..f2d00cad65f379080aa3f3bacbf48502971674ce 100644
--- a/configs/zynq_zc770_xm013_defconfig
+++ b/configs/zynq_zc770_xm013_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zc770"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index 7976e07c3b9e4209e5e30c792cd896f11daf277e..7783eeb0f6c7626602cf030d4729422a7a435006 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zed"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZED=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zed"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index cd222c5a7b072b32428b91e3569d8b5443c2ce27..9236c5e8274573ef6b0147edc54955681bc6b5af 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="zynq_zybo"
 CONFIG_ARCH_ZYNQ=y
-CONFIG_TARGET_ZYNQ_ZYBO=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo"
 CONFIG_SPL=y
 CONFIG_FIT=y
diff --git a/doc/uImage.FIT/multi-with-fpga.its b/doc/uImage.FIT/multi-with-fpga.its
new file mode 100644
index 0000000000000000000000000000000000000000..0cdb31fe91c4f6c580058a9d7d1f70f930219e50
--- /dev/null
+++ b/doc/uImage.FIT/multi-with-fpga.its
@@ -0,0 +1,67 @@
+/*
+ * U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs
+ * This example makes use of the 'loadables' field
+ */
+
+/dts-v1/;
+
+/ {
+	description = "Configuration to load fpga before Kernel";
+	#address-cells = <1>;
+
+	images {
+		fdt@1 {
+			description = "zc706";
+			data = /incbin/("/tftpboot/devicetree.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+			load = <0x10000000>;
+			hash@1 {
+				algo = "md5";
+			};
+		};
+
+		fpga@1 {
+			description = "FPGA";
+			data = /incbin/("/tftpboot/download.bit");
+			type = "fpga";
+			arch = "arm";
+			compression = "none";
+			load = <0x30000000>;
+			hash@1 {
+				algo = "md5";
+			};
+		};
+
+		linux_kernel@1 {
+			description = "Linux";
+			data = /incbin/("/tftpboot/zImage");
+			type = "kernel";
+			arch = "arm";
+			os = "linux";
+			compression = "none";
+			load = <0x8000>;
+			entry = <0x8000>;
+			hash@1 {
+				algo = "md5";
+			};
+		};
+	};
+
+	configurations {
+		default = "config@2";
+		config@1 {
+			description = "Linux";
+			kernel = "linux_kernel@1";
+			fdt = "fdt@1";
+		};
+
+		config@2 {
+			description = "Linux with fpga";
+			kernel = "linux_kernel@1";
+			fdt = "fdt@1";
+			fpga = "fpga@1";
+		};
+	};
+};
diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt
index 9c527c3e012d9dd3a41aa27727e696a7446f10e8..3f5418045e5b6e203a8172a42d1399b6de2c61cd 100644
--- a/doc/uImage.FIT/source_file_format.txt
+++ b/doc/uImage.FIT/source_file_format.txt
@@ -236,6 +236,7 @@ o config@1
   |- kernel = "kernel sub-node unit name"
   |- ramdisk = "ramdisk sub-node unit name"
   |- fdt = "fdt sub-node unit-name"
+  |- fpga = "fpga sub-node unit-name"
   |- loadables = "loadables sub-node unit-name"
 
 
@@ -251,6 +252,8 @@ o config@1
     "fdt type").
   - setup : Unit name of the corresponding setup binary (used for booting
     an x86 kernel). This contains the setup.bin file built by the kernel.
+  - fpga : Unit name of the corresponding fpga bitstream blob
+    (component image node of a "fpga type").
   - loadables : Unit name containing a list of additional binaries to be
     loaded at their given locations.  "loadables" is a comma-separated list
     of strings. U-Boot will load each binary at its given start-address.
diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c
index d94eb5cc25c4fce6c4df48bd22c39a659b709378..7e2f3e17a7649a6bdddb3e41eef6f75c660b3c7c 100644
--- a/drivers/fpga/fpga.c
+++ b/drivers/fpga/fpga.c
@@ -120,7 +120,7 @@ static int fpga_dev_info(int devnum)
 }
 
 /*
- * fgpa_init is usually called from misc_init_r() and MUST be called
+ * fpga_init is usually called from misc_init_r() and MUST be called
  * before any of the other fpga functions are used.
  */
 void fpga_init(void)
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c
index 3a995f610cb3e8acae8f7a6f8220c2365272e5d3..4ab23560810494a386a0b76bad285aa5d9b523ff 100644
--- a/drivers/gpio/zynq_gpio.c
+++ b/drivers/gpio/zynq_gpio.c
@@ -299,11 +299,33 @@ static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
 	return 0;
 }
 
+static int zynq_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	u32 reg;
+	unsigned int bank_num, bank_pin_num;
+	struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+
+	if (check_gpio(offset, dev) < 0)
+		return -1;
+
+	zynq_gpio_get_bank_pin(offset, &bank_num, &bank_pin_num, dev);
+
+	/* set the GPIO pin as output */
+	reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	reg &= BIT(bank_pin_num);
+	if (reg)
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
 static const struct dm_gpio_ops gpio_zynq_ops = {
 	.direction_input	= zynq_gpio_direction_input,
 	.direction_output	= zynq_gpio_direction_output,
 	.get_value		= zynq_gpio_get_value,
 	.set_value		= zynq_gpio_set_value,
+	.get_function		= zynq_gpio_get_function,
+
 };
 
 static const struct udevice_id zynq_gpio_ids[] = {
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 4b2808eff00f27320ea60fc15c7ac089f6b50faa..9871cc3edd7c4df6f688bff425a73814fe8eaa85 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -84,11 +84,14 @@ static int bcm54xx_parse_status(struct phy_device *phydev)
 
 static int bcm54xx_startup(struct phy_device *phydev)
 {
+	int ret;
+
 	/* Read the Status (2x to make sure link is right) */
-	genphy_update_link(phydev);
-	bcm54xx_parse_status(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	return 0;
+	return bcm54xx_parse_status(phydev);
 }
 
 /* Broadcom BCM5482S */
@@ -139,11 +142,14 @@ static int bcm5482_config(struct phy_device *phydev)
 
 static int bcm_cygnus_startup(struct phy_device *phydev)
 {
+	int ret;
+
 	/* Read the Status (2x to make sure link is right) */
-	genphy_update_link(phydev);
-	genphy_parse_link(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	return 0;
+	return genphy_parse_link(phydev);
 }
 
 static int bcm_cygnus_config(struct phy_device *phydev)
@@ -239,17 +245,21 @@ static u32 bcm5482_parse_serdes_sr(struct phy_device *phydev)
  */
 static int bcm5482_startup(struct phy_device *phydev)
 {
+	int ret;
+
 	if (bcm5482_is_serdes(phydev)) {
 		bcm5482_parse_serdes_sr(phydev);
 		phydev->port = PORT_FIBRE;
-	} else {
-		/* Wait for auto-negotiation to complete or fail */
-		genphy_update_link(phydev);
-		/* Parse BCM54xx copper aux status register */
-		bcm54xx_parse_status(phydev);
+		return 0;
 	}
 
-	return 0;
+	/* Wait for auto-negotiation to complete or fail */
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	/* Parse BCM54xx copper aux status register */
+	return bcm54xx_parse_status(phydev);
 }
 
 static struct phy_driver BCM5461S_driver = {
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 0c039fe79ff19401ba4c2b8521487f3e5dfd75a7..0a6e4107ba5dfd0f005a2c2bc06bc5d9a1dc0a4a 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -60,10 +60,13 @@ static int dm9161_parse_status(struct phy_device *phydev)
 
 static int dm9161_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	dm9161_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return dm9161_parse_status(phydev);
 }
 
 static struct phy_driver DM9161_driver = {
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 70c15e2f20c9fe63778d7c2e6caa481e9e556035..2fe01327faaea181c4ce6bf1f0cd0127f41fef79 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -79,9 +79,13 @@ static int et1011c_parse_status(struct phy_device *phydev)
 
 static int et1011c_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	et1011c_parse_status(phydev);
-	return 0;
+	int ret;
+
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return et1011c_parse_status(phydev);
 }
 
 static struct phy_driver et1011c_driver = {
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 91838ce5ea174c08555d813f7922525802c3d914..9abc2a84f9f6492e32867f3c2654123e4bdcedfa 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -49,10 +49,13 @@ static int lxt971_parse_status(struct phy_device *phydev)
 
 static int lxt971_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	lxt971_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return lxt971_parse_status(phydev);
 }
 
 static struct phy_driver LXT971_driver = {
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index b8b1157a0a4a19c9307bdf6a53135195407e08dd..d2e68d492a676a93fabd4eb410fcd09de99eee10 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -103,7 +103,7 @@ static int m88e1011s_config(struct phy_device *phydev)
 /* Parse the 88E1011's status register for speed and duplex
  * information
  */
-static uint m88e1xxx_parse_status(struct phy_device *phydev)
+static int m88e1xxx_parse_status(struct phy_device *phydev)
 {
 	unsigned int speed;
 	unsigned int mii_reg;
@@ -120,7 +120,7 @@ static uint m88e1xxx_parse_status(struct phy_device *phydev)
 			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
 				puts(" TIMEOUT !\n");
 				phydev->link = 0;
-				break;
+				return -ETIMEDOUT;
 			}
 
 			if ((i++ % 1000) == 0)
@@ -162,10 +162,13 @@ static uint m88e1xxx_parse_status(struct phy_device *phydev)
 
 static int m88e1011s_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	m88e1xxx_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return m88e1xxx_parse_status(phydev);
 }
 
 /* Marvell 88E1111S */
@@ -349,22 +352,21 @@ static int m88e1118_config(struct phy_device *phydev)
 	/* Change Page Number */
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 
-	genphy_config_aneg(phydev);
-
-	phy_reset(phydev);
-
-	return 0;
+	return genphy_config_aneg(phydev);
 }
 
 static int m88e1118_startup(struct phy_device *phydev)
 {
+	int ret;
+
 	/* Change Page Number */
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 
-	genphy_update_link(phydev);
-	m88e1xxx_parse_status(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	return 0;
+	return m88e1xxx_parse_status(phydev);
 }
 
 /* Marvell 88E1121R */
@@ -421,12 +423,15 @@ static int m88e1145_config(struct phy_device *phydev)
 
 static int m88e1145_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
+	int ret;
+
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL,
 			MIIM_88E1145_PHY_LED_DIRECT);
-	m88e1xxx_parse_status(phydev);
-
-	return 0;
+	return m88e1xxx_parse_status(phydev);
 }
 
 /* Marvell 88E1149S */
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 8fcf737cb8fa755f44a4caeb7f408563ce5deb16..b08788a2b0516dfd3517b5f08b6a2e0714a21c9c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -181,7 +181,12 @@ static struct phy_driver KS8721_driver = {
 static int ksz90xx_startup(struct phy_device *phydev)
 {
 	unsigned phy_ctl;
-	genphy_update_link(phydev);
+	int ret;
+
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
 	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
 
 	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index d2e4c3c487e385bd1f130b096acd5955860fe945..1592e9b7b97536bd59530d1c9e29ac330950048d 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -93,10 +93,13 @@ static int dp83865_parse_status(struct phy_device *phydev)
 
 static int dp83865_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	dp83865_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return dp83865_parse_status(phydev);
 }
 
 
@@ -134,10 +137,13 @@ static int dp83848_parse_status(struct phy_device *phydev)
 
 static int dp83848_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	dp83848_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return dp83848_parse_status(phydev);
 }
 
 static struct phy_driver DP83848_driver = {
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 23c82bb36e93ed0e70f50af532e659ab6612a68f..4b6c09f88ec08bebb53547b4f45a0b37ef08895b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -248,7 +248,7 @@ int genphy_update_link(struct phy_device *phydev)
 			if (i > PHY_ANEG_TIMEOUT) {
 				printf(" TIMEOUT !\n");
 				phydev->link = 0;
-				return 0;
+				return -ETIMEDOUT;
 			}
 
 			if (ctrlc()) {
@@ -431,10 +431,13 @@ int genphy_config(struct phy_device *phydev)
 
 int genphy_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	genphy_parse_link(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return genphy_parse_link(phydev);
 }
 
 int genphy_shutdown(struct phy_device *phydev)
@@ -876,9 +879,7 @@ __weak int board_phy_config(struct phy_device *phydev)
 int phy_config(struct phy_device *phydev)
 {
 	/* Invoke an optional board-specific helper */
-	board_phy_config(phydev);
-
-	return 0;
+	return board_phy_config(phydev);
 }
 
 int phy_shutdown(struct phy_device *phydev)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 9d7f55bdae07fc7574ccdd87b4a32d89ea5c098a..7a99cb023401581a117d85976f5bf9635568c083 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -208,28 +208,38 @@ static int rtl8211f_parse_status(struct phy_device *phydev)
 
 static int rtl8211x_startup(struct phy_device *phydev)
 {
+	int ret;
+
 	/* Read the Status (2x to make sure link is right) */
-	genphy_update_link(phydev);
-	rtl8211x_parse_status(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	return 0;
+	return rtl8211x_parse_status(phydev);
 }
 
 static int rtl8211e_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	genphy_parse_link(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return genphy_parse_link(phydev);
 }
 
 static int rtl8211f_startup(struct phy_device *phydev)
 {
+	int ret;
+
+	/* Read the Status (2x to make sure link is right) */
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 	/* Read the Status (2x to make sure link is right) */
-	genphy_update_link(phydev);
-	rtl8211f_parse_status(phydev);
 
-	return 0;
+	return rtl8211f_parse_status(phydev);
 }
 
 /* Support for RTL8211B PHY */
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 34986a29fc3fd56906073d5e702e5fad587324ea..313fcdfdc52d07270c2291debdced8b96747bda8 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -34,9 +34,13 @@ static int smsc_parse_status(struct phy_device *phydev)
 
 static int smsc_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	smsc_parse_status(phydev);
-	return 0;
+	int ret;
+
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+
+	return smsc_parse_status(phydev);
 }
 
 static struct phy_driver lan8700_driver = {
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 941d0760b57f378e0ea183c1d46532c79f432db6..2635b821e9679f5b938e26fa500b7f11a852aab1 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -112,10 +112,12 @@ static int vitesse_parse_status(struct phy_device *phydev)
 
 static int vitesse_startup(struct phy_device *phydev)
 {
-	genphy_update_link(phydev);
-	vitesse_parse_status(phydev);
+	int ret;
 
-	return 0;
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
+	return vitesse_parse_status(phydev);
 }
 
 static int cis8204_config(struct phy_device *phydev)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 5862bf0a7e2d4d34d40ac4dbafab10c636b0d15c..7b85aa0463851d22e0c8f6e45f56eb11e62b59ca 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -250,7 +250,7 @@ static void emaclite_stop(struct udevice *dev)
 
 static int setup_phy(struct udevice *dev)
 {
-	int i;
+	int i, ret;
 	u16 phyreg;
 	struct xemaclite *emaclite = dev_get_priv(dev);
 	struct phy_device *phydev;
@@ -302,7 +302,9 @@ static int setup_phy(struct udevice *dev)
 	phydev->advertising = supported;
 	emaclite->phydev = phydev;
 	phy_config(phydev);
-	phy_startup(phydev);
+	ret = phy_startup(phydev);
+	if (ret)
+		return ret;
 
 	if (!phydev->link) {
 		printf("%s: No link.\n", phydev->dev->name);
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index aec8077f10b3e2b7f82e0c2bf504f5183ce89058..4d9c296c0ba9019451c4236ac5000c2f54ba06c5 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -352,14 +352,14 @@ static int zynq_phy_init(struct udevice *dev)
 	priv->phydev->supported = supported | ADVERTISED_Pause |
 				  ADVERTISED_Asym_Pause;
 	priv->phydev->advertising = priv->phydev->supported;
-	phy_config(priv->phydev);
 
-	return 0;
+	return phy_config(priv->phydev);
 }
 
 static int zynq_gem_init(struct udevice *dev)
 {
 	u32 i, nwconfig;
+	int ret;
 	unsigned long clk_rate = 0;
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
 	struct zynq_gem_regs *regs = priv->iobase;
@@ -427,7 +427,9 @@ static int zynq_gem_init(struct udevice *dev)
 		priv->init++;
 	}
 
-	phy_startup(priv->phydev);
+	ret = phy_startup(priv->phydev);
+	if (ret)
+		return ret;
 
 	if (!priv->phydev->link) {
 		printf("%s: No link.\n", priv->phydev->dev->name);
diff --git a/include/bootstage.h b/include/bootstage.h
index 97653602d3dd1eee50510b1d0bd57805f3f44a6a..0880a680b9ea3e4472528df3542f55d592afc0b1 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -198,6 +198,7 @@ enum bootstage_id {
 	BOOTSTAGE_ID_ACCUM_SCSI,
 	BOOTSTAGE_ID_ACCUM_SPI,
 	BOOTSTAGE_ID_ACCUM_DECOMP,
+	BOOTSTAGE_ID_FPGA_INIT,
 
 	/* a few spare for the user, from here */
 	BOOTSTAGE_ID_USER,
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 6b8e3ea8657d453d20277f4eb72c59cb20ce376a..b2fa164f6522b578e7932f241d1f0b98a6354797 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -41,7 +41,7 @@
 # define CONFIG_IDENT_STRING		" Xilinx ZynqMP"
 #endif
 
-#define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_INIT_SP_ADDR		0xfffffffc
 
 /* Generic Timer Definitions - setup in EL3. Setup by ATF for other cases */
 #if !defined(COUNTER_FREQUENCY)
@@ -65,6 +65,9 @@
 #define CONFIG_CMD_ENV
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#ifndef CONFIG_SPL_BUILD
+# define CONFIG_ISO_PARTITION
+#endif
 #define CONFIG_MP
 
 /* BOOTP options */
@@ -74,10 +77,24 @@
 #define CONFIG_BOOTP_HOSTNAME
 #define CONFIG_BOOTP_MAY_FAIL
 #define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_PXE
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_BOOTP_PXE_CLIENTARCH     0x100
+
+/* Diff from config_distro_defaults.h */
+#define CONFIG_SUPPORT_RAW_INITRD
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
+#define CONFIG_AUTO_COMPLETE
+
+/* PXE */
+#define CONFIG_CMD_PXE
+#define CONFIG_MENU
 
 #if defined(CONFIG_ZYNQ_SDHCI)
 # define CONFIG_MMC
 # define CONFIG_GENERIC_MMC
+# define CONFIG_SUPPORT_EMMC_BOOT
 # define CONFIG_SDHCI
 # ifndef CONFIG_ZYNQ_SDHCI_MAX_FREQ
 #  define CONFIG_ZYNQ_SDHCI_MAX_FREQ	200000000
@@ -133,6 +150,7 @@
 #endif
 
 /* Initial environment variables */
+#ifndef CONFIG_EXTRA_ENV_SETTINGS
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"kernel_addr=0x80000\0" \
 	"fdt_addr=0x7000000\0" \
@@ -143,8 +161,8 @@
 		"load mmc $sdbootdev:$partid $kernel_addr Image && " \
 		"booti $kernel_addr - $fdt_addr\0" \
 	DFU_ALT_INFO
+#endif
 
-#define CONFIG_PREBOOT		"run bootargs"
 #define CONFIG_BOOTCOMMAND	"run $modeboot"
 #define CONFIG_BOOTDELAY	3
 
@@ -212,4 +230,41 @@
 #define CONFIG_BOARD_EARLY_INIT_R
 #define CONFIG_CLOCKS
 
+#define CONFIG_SPL_TEXT_BASE		0xfffc0000
+#define CONFIG_SPL_MAX_SIZE		0x20000
+
+/* Just random location in OCM */
+#define CONFIG_SPL_BSS_START_ADDR	0x1000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x2000000
+
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SPL_RAM_DEVICE
+
+#define CONFIG_SPL_OS_BOOT
+/* u-boot is like dtb */
+#define CONFIG_SPL_FS_LOAD_ARGS_NAME	"u-boot.bin"
+#define CONFIG_SYS_SPL_ARGS_ADDR	0x8000000
+
+/* ATF is my kernel image */
+#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"atf.ub"
+
+/* FIT load address for RAM boot */
+#define CONFIG_SPL_LOAD_FIT_ADDRESS	0x10000000
+
+/* MMC support */
+#ifdef CONFIG_ZYNQ_SDHCI
+# define CONFIG_SPL_MMC_SUPPORT
+# define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+# define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR	0 /* unused */
+# define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS	0 /* unused */
+# define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR	0 /* unused */
+# define CONFIG_SPL_LIBDISK_SUPPORT
+# define CONFIG_SPL_FAT_SUPPORT
+# define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
+#endif
+
 #endif /* __XILINX_ZYNQMP_H */
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h
index 30db2e453246113d6805eacfdea76e5400d35fd3..81079fe7d8b239c91420c309e23713608c530374 100644
--- a/include/configs/xilinx_zynqmp_zcu102.h
+++ b/include/configs/xilinx_zynqmp_zcu102.h
@@ -48,6 +48,12 @@
 
 #define CONFIG_IDENT_STRING	" Xilinx ZynqMP ZCU102"
 
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	1
+#define CONFIG_CMD_EEPROM
+#define CONFIG_ZYNQ_EEPROM_BUS		5
+#define CONFIG_ZYNQ_GEM_EEPROM_ADDR	0x54
+#define CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET	0x20
+
 #define CONFIG_KERNEL_FDT_OFST_SIZE \
 	"kernel_offset=0x180000\0" \
 	"fdt_offset=0x100000\0" \
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index a3e4aecb571e5269c93cd71aa7c2154173973132..82ece0df2d6a2684520391390702a179b2ee7121 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -315,11 +315,7 @@
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION     1
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #define CONFIG_SPL_FAT_SUPPORT
-#ifdef CONFIG_OF_SEPARATE
-# define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME     "u-boot-dtb.img"
-#else
-# define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME     "u-boot.img"
-#endif
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME     "u-boot.img"
 #endif
 
 /* Disable dcache for SPL just for sure */
diff --git a/include/image.h b/include/image.h
index f9ee5649c547107f0c5c668cd6440bb93105005d..a8f6bd16f69c62548ebc293cf426e15d01773435 100644
--- a/include/image.h
+++ b/include/image.h
@@ -246,8 +246,10 @@ struct lmb;
 #define IH_TYPE_RKSD		24	/* Rockchip SD card		*/
 #define IH_TYPE_RKSPI		25	/* Rockchip SPI image		*/
 #define IH_TYPE_ZYNQIMAGE	26	/* Xilinx Zynq Boot Image */
+#define IH_TYPE_ZYNQMPIMAGE	27	/* Xilinx ZynqMP Boot Image */
+#define IH_TYPE_FPGA		28	/* FPGA Image */
 
-#define IH_TYPE_COUNT		27	/* Number of image types */
+#define IH_TYPE_COUNT		29	/* Number of image types */
 
 /*
  * Compression Types
@@ -494,6 +496,8 @@ int genimg_get_format(const void *img_addr);
 int genimg_has_config(bootm_headers_t *images);
 ulong genimg_get_image(ulong img_addr);
 
+int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
+		uint8_t arch, const ulong *ld_start, ulong * const ld_len);
 int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 		uint8_t arch, ulong *rd_start, ulong *rd_end);
 
@@ -809,6 +813,7 @@ int bootz_setup(ulong image, ulong *start, ulong *end);
 #define FIT_LOADABLE_PROP	"loadables"
 #define FIT_DEFAULT_PROP	"default"
 #define FIT_SETUP_PROP		"setup"
+#define FIT_FPGA_PROP		"fpga"
 
 #define FIT_MAX_HASH_LEN	HASH_MAX_DIGEST_SIZE
 
diff --git a/include/spl.h b/include/spl.h
index 7edfab46dcd1ea44b039fb2172fe9c17ea173d18..335b76a1b15392c0829af6313d13a21afdbaad84 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -58,6 +58,7 @@ u32 spl_boot_mode(void);
 void spl_set_header_raw_uboot(void);
 int spl_parse_image_header(const struct image_header *header);
 void spl_board_prepare_for_linux(void);
+void spl_board_prepare_for_boot(void);
 void __noreturn jump_to_image_linux(void *arg);
 int spl_start_uboot(void);
 void spl_display_print(void);
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index ec8d8f1b72ad10579c4c59226337e13e11545dc2..6d2017da7e975e88295629bf4dcfaa3450fa43a7 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -129,7 +129,12 @@ endif
 boot.bin: $(obj)/u-boot-spl.bin FORCE
 	$(call if_changed,mkimage)
 else
+ifdef CONFIG_ARCH_ZYNQ
 MKIMAGEFLAGS_boot.bin = -T zynqimage
+endif
+ifdef CONFIG_ARCH_ZYNQMP
+MKIMAGEFLAGS_boot.bin = -T zynqmpimage
+endif
 
 spl/boot.bin: $(obj)/u-boot-spl.bin FORCE
 	$(call if_changed,mkimage)
@@ -157,6 +162,8 @@ ifdef CONFIG_ARCH_ZYNQ
 ALL-y	+= $(obj)/boot.bin
 endif
 
+ALL-(CONFIG_ARCH_ZYNQMP)	+= $(obj)/boot.bin
+
 all:	$(ALL-y)
 
 quiet_cmd_cat = CAT     $@
diff --git a/tools/Makefile b/tools/Makefile
index da50e1bffca459b6a14bb4fe73371a8a79269e05..63355aa36d8cb72b8b46545f8afe687efee2f346 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -98,6 +98,7 @@ dumpimage-mkimage-objs := aisimage.o \
 			common/hash.o \
 			ublimage.o \
 			zynqimage.o \
+			zynqmpimage.o \
 			$(LIBFDT_OBJS) \
 			$(RSA_OBJS-y)
 
diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f28eb401d9b439007b98083843a97cdb0a9345c
--- /dev/null
+++ b/tools/zynqmpimage.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 Michal Simek <michals@xilinx.com>
+ * Copyright (C) 2015 Nathan Rossi <nathan@nathanrossi.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * The following Boot Header format/structures and values are defined in the
+ * following documents:
+ *   * ug1085 ZynqMP TRM (Chapter 9, Table 9-3)
+ *
+ * Expected Header Size = 0x9C0
+ * Forced as 'little' endian, 32-bit words
+ *
+ *  0x  0 - Interrupt table (8 words)
+ *  ...     (Default value = 0xeafffffe)
+ *  0x 1f
+ *  0x 20 - Width detection
+ *         * DEFAULT_WIDTHDETECTION    0xaa995566
+ *  0x 24 - Image identifier
+ *         * DEFAULT_IMAGEIDENTIFIER   0x584c4e58
+ *  0x 28 - Encryption
+ *         * 0x00000000 - None
+ *         * 0xa5c3c5a3 - eFuse
+ *         * 0xa5c3c5a7 - obfuscated key in eFUSE
+ *         * 0x3a5c3c5a - bbRam
+ *         * 0xa35c7ca5 - obfuscated key in boot header
+ *  0x 2C - Image load
+ *  0x 30 - Image offset
+ *  0x 34 - PFW image length
+ *  0x 38 - Total PFW image length
+ *  0x 3C - Image length
+ *  0x 40 - Total image length
+ *  0x 44 - Image attributes
+ *  0x 48 - Header checksum
+ *  0x 4c - Obfuscated key
+ *  ...
+ *  0x 68
+ *  0x 6c - Reserved
+ *  0x 70 - User defined
+ *  ...
+ *  0x 9c
+ *  0x a0 - Secure header initialization vector
+ *  ...
+ *  0x a8
+ *  0x ac - Obfuscated key initialization vector
+ *  ...
+ *  0x b4
+ *  0x b8 - Register Initialization, 511 Address and Data word pairs
+ *         * List is terminated with an address of 0xffffffff or
+ *  ...    * at the max number of entries
+ *  0x8b4
+ *  0x8b8 - Reserved
+ *  ...
+ *  0x9bf
+ *  0x9c0 - Data/Image starts here or above
+ */
+
+#include "imagetool.h"
+#include "mkimage.h"
+#include <image.h>
+
+#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe))
+#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff))
+#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566))
+#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58))
+
+enum {
+	ENCRYPTION_EFUSE = 0xa5c3c5a3,
+	ENCRYPTION_OEFUSE = 0xa5c3c5a7,
+	ENCRYPTION_BBRAM = 0x3a5c3c5a,
+	ENCRYPTION_OBBRAM = 0xa35c7ca5,
+	ENCRYPTION_NONE = 0x0,
+};
+
+struct zynqmp_reginit {
+	uint32_t address;
+	uint32_t data;
+};
+
+#define HEADER_INTERRUPT_VECTORS	8
+#define HEADER_REGINITS			256
+
+struct zynqmp_header {
+	uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */
+	uint32_t width_detection; /* 0x20 */
+	uint32_t image_identifier; /* 0x24 */
+	uint32_t encryption; /* 0x28 */
+	uint32_t image_load; /* 0x2c */
+	uint32_t image_offset; /* 0x30 */
+	uint32_t pfw_image_length; /* 0x34 */
+	uint32_t total_pfw_image_length; /* 0x38 */
+	uint32_t image_size; /* 0x3c */
+	uint32_t image_stored_size; /* 0x40 */
+	uint32_t image_attributes; /* 0x44 */
+	uint32_t checksum; /* 0x48 */
+	uint32_t __reserved1[27]; /* 0x4c */
+	struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */
+	uint32_t __reserved4[66]; /* 0x9c0 */
+};
+
+static struct zynqmp_header zynqmpimage_header;
+
+static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr)
+{
+	uint32_t checksum = 0;
+
+	if (ptr == NULL)
+		return 0;
+
+	checksum += le32_to_cpu(ptr->width_detection);
+	checksum += le32_to_cpu(ptr->image_identifier);
+	checksum += le32_to_cpu(ptr->encryption);
+	checksum += le32_to_cpu(ptr->image_load);
+	checksum += le32_to_cpu(ptr->image_offset);
+	checksum += le32_to_cpu(ptr->pfw_image_length);
+	checksum += le32_to_cpu(ptr->total_pfw_image_length);
+	checksum += le32_to_cpu(ptr->image_size);
+	checksum += le32_to_cpu(ptr->image_stored_size);
+	checksum += le32_to_cpu(ptr->image_attributes);
+	checksum = ~checksum;
+
+	return cpu_to_le32(checksum);
+}
+
+static void zynqmpimage_default_header(struct zynqmp_header *ptr)
+{
+	int i;
+
+	if (ptr == NULL)
+		return;
+
+	ptr->width_detection = HEADER_WIDTHDETECTION;
+	ptr->image_attributes = 0x800;
+	ptr->image_identifier = HEADER_IMAGEIDENTIFIER;
+	ptr->encryption = cpu_to_le32(ENCRYPTION_NONE);
+
+	/* Setup not-supported/constant/reserved fields */
+	for (i = 0; i < HEADER_INTERRUPT_VECTORS; i++)
+		ptr->interrupt_vectors[i] = HEADER_INTERRUPT_DEFAULT;
+
+	for (i = 0; i < HEADER_REGINITS; i++) {
+		ptr->register_init[i].address = HEADER_REGINIT_NULL;
+		ptr->register_init[i].data = 0;
+	}
+
+	/*
+	 * Certain reserved fields are required to be set to 0, ensure they are
+	 * set as such.
+	 */
+	ptr->pfw_image_length = 0x0;
+	ptr->total_pfw_image_length = 0x0;
+}
+
+/* mkimage glue functions */
+static int zynqmpimage_verify_header(unsigned char *ptr, int image_size,
+		struct image_tool_params *params)
+{
+	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
+
+	if (image_size < sizeof(struct zynqmp_header))
+		return -1;
+
+	if (zynqhdr->width_detection != HEADER_WIDTHDETECTION)
+		return -1;
+	if (zynqhdr->image_identifier != HEADER_IMAGEIDENTIFIER)
+		return -1;
+
+	if (zynqmpimage_checksum(zynqhdr) != zynqhdr->checksum)
+		return -1;
+
+	return 0;
+}
+
+static void zynqmpimage_print_header(const void *ptr)
+{
+	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
+	int i;
+
+	printf("Image Type   : Xilinx Zynq Boot Image support\n");
+	printf("Image Offset : 0x%08x\n", le32_to_cpu(zynqhdr->image_offset));
+	printf("Image Size   : %lu bytes (%lu bytes packed)\n",
+	       (unsigned long)le32_to_cpu(zynqhdr->image_size),
+	       (unsigned long)le32_to_cpu(zynqhdr->image_stored_size));
+	printf("Image Load   : 0x%08x\n", le32_to_cpu(zynqhdr->image_load));
+	printf("Checksum     : 0x%08x\n", le32_to_cpu(zynqhdr->checksum));
+
+	for (i = 0; i < HEADER_INTERRUPT_VECTORS; i++) {
+		if (zynqhdr->interrupt_vectors[i] == HEADER_INTERRUPT_DEFAULT)
+			continue;
+
+		printf("Modified Interrupt Vector Address [%d]: 0x%08x\n", i,
+		       le32_to_cpu(zynqhdr->interrupt_vectors[i]));
+	}
+
+	for (i = 0; i < HEADER_REGINITS; i++) {
+		if (zynqhdr->register_init[i].address == HEADER_REGINIT_NULL)
+			break;
+
+		if (i == 0)
+			printf("Custom Register Initialization:\n");
+
+		printf("    @ 0x%08x -> 0x%08x\n",
+		       le32_to_cpu(zynqhdr->register_init[i].address),
+		       le32_to_cpu(zynqhdr->register_init[i].data));
+	}
+}
+
+static int zynqmpimage_check_params(struct image_tool_params *params)
+{
+	if (!params)
+		return 0;
+
+	if (params->addr != 0x0) {
+		fprintf(stderr, "Error: Load Address cannot be specified.\n");
+		return -1;
+	}
+
+	/*
+	 * If the entry point is specified ensure it is 64 byte aligned.
+	 */
+	if (params->eflag && (params->ep % 64 != 0)) {
+		fprintf(stderr,
+			"Error: Entry Point must be aligned to a 64-byte boundary.\n");
+		return -1;
+	}
+
+	return !(params->lflag || params->dflag);
+}
+
+static int zynqmpimage_check_image_types(uint8_t type)
+{
+	if (type == IH_TYPE_ZYNQMPIMAGE)
+		return EXIT_SUCCESS;
+	return EXIT_FAILURE;
+}
+
+static void zynqmpimage_set_header(void *ptr, struct stat *sbuf, int ifd,
+		struct image_tool_params *params)
+{
+	struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr;
+	zynqmpimage_default_header(zynqhdr);
+
+	/* place image directly after header */
+	zynqhdr->image_offset =
+		cpu_to_le32((uint32_t)sizeof(struct zynqmp_header));
+	zynqhdr->image_size = cpu_to_le32(params->file_size -
+					  sizeof(struct zynqmp_header));
+	zynqhdr->image_stored_size = zynqhdr->image_size;
+	zynqhdr->image_load = 0xfffc0000;
+	if (params->eflag)
+		zynqhdr->image_load = cpu_to_le32((uint32_t)params->ep);
+
+	zynqhdr->checksum = zynqmpimage_checksum(zynqhdr);
+}
+
+U_BOOT_IMAGE_TYPE(
+	zynqmpimage,
+	"Xilinx ZynqMP Boot Image support",
+	sizeof(struct zynqmp_header),
+	(void *)&zynqmpimage_header,
+	zynqmpimage_check_params,
+	zynqmpimage_verify_header,
+	zynqmpimage_print_header,
+	zynqmpimage_set_header,
+	NULL,
+	zynqmpimage_check_image_types,
+	NULL,
+	NULL
+);