Merge branch 'master' of git://www.denx.de/git/u-boot-microblaze
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig
index e703991..1eedb39 100644
--- a/arch/arm/cpu/armv8/zynqmp/Kconfig
+++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -47,5 +47,53 @@
 config SYS_MALLOC_F_LEN
 	default 0x600
 
+config SPL_ZYNQMP_ALT_BOOTMODE_ENABLED
+	bool "Overwrite SPL bootmode"
+	depends on SPL
+	help
+	  Overwrite bootmode selected via boot mode pins to tell SPL what should
+	  be the next boot device.
+
+config SPL_ZYNQMP_ALT_BOOTMODE
+	hex
+	default 0x0 if JTAG_MODE
+	default 0x1 if QSPI_MODE_24BIT
+	default 0x2 if QSPI_MODE_32BIT
+	default 0x3 if SD_MODE
+	default 0x4 if NAND_MODE
+	default 0x5 if SD_MODE1
+	default 0x6 if EMMC_MODE
+	default 0x7 if USB_MODE
+
+choice
+	prompt "Boot mode"
+	depends on ZYNQMP_ALT_BOOTMODE_ENABLED
+	default JTAG
+
+config JTAG_MODE
+	bool "JTAG_MODE"
+
+config QSPI_MODE_24BIT
+	bool "QSPI_MODE_24BIT"
+
+config QSPI_MODE_32BIT
+	bool "QSPI_MODE_32BIT"
+
+config SD_MODE
+	bool "SD_MODE"
+
+config SD_MODE1
+	bool "SD_MODE1"
+
+config NAND_MODE
+	bool "NAND_MODE"
+
+config EMMC_MODE
+	bool "EMMC_MODE"
+
+config USB_MODE
+	bool "USB"
+
+endchoice
 
 endif
diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c
index 867d2b2..04e1905 100644
--- a/arch/arm/cpu/armv8/zynqmp/spl.c
+++ b/arch/arm/cpu/armv8/zynqmp/spl.c
@@ -35,10 +35,29 @@
 	board_init_r(NULL, 0);
 }
 
+static void ps_mode_reset(ulong mode)
+{
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+	udelay(5);
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT |
+	       mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+}
+
+/*
+ * Set default PS_MODE1 which is used for USB ULPI phy reset
+ * Also other resets can be connected to this certain pin
+ */
+#ifndef MODE_RESET
+# define MODE_RESET	PS_MODE1
+#endif
+
 #ifdef CONFIG_SPL_BOARD_INIT
 void spl_board_init(void)
 {
 	preloader_console_init();
+	ps_mode_reset(MODE_RESET);
 	board_init();
 }
 #endif
@@ -48,6 +67,13 @@
 	u32 reg = 0;
 	u8 bootmode;
 
+#if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED)
+	/* Change default boot mode at run-time */
+	writel(BOOT_MODE_USE_ALT |
+	       CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT,
+	       &crlapb_base->boot_mode);
+#endif
+
 	reg = readl(&crlapb_base->boot_mode);
 	bootmode = reg & BOOT_MODES_MASK;
 
@@ -60,6 +86,10 @@
 	case SD_MODE1:
 		return BOOT_DEVICE_MMC1;
 #endif
+#ifdef CONFIG_SPL_DFU_SUPPORT
+	case USB_MODE:
+		return BOOT_DEVICE_DFU;
+#endif
 	default:
 		printf("Invalid Boot Mode:0x%x\n", bootmode);
 		break;
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index 35964d6..456c1b0 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -25,6 +25,13 @@
 
 #define ZYNQMP_CRL_APB_BASEADDR	0xFF5E0000
 #define ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT	0x1000000
+#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT	0
+#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT	8
+
+#define PS_MODE0	BIT(0)
+#define PS_MODE1	BIT(1)
+#define PS_MODE2	BIT(2)
+#define PS_MODE3	BIT(3)
 
 struct crlapb_regs {
 	u32 reserved0[36];
@@ -35,7 +42,9 @@
 	u32 boot_mode; /* 0x200 */
 	u32 reserved3[14];
 	u32 rst_lpd_top; /* 0x23C */
-	u32 reserved4[26];
+	u32 reserved4[4];
+	u32 boot_pin_ctrl; /* 0x250 */
+	u32 reserved5[21];
 };
 
 #define crlapb_base ((struct crlapb_regs *)ZYNQMP_CRL_APB_BASEADDR)
@@ -69,7 +78,10 @@
 #define SD_MODE1	0x00000005 /* sd 1 */
 #define NAND_MODE	0x00000004
 #define EMMC_MODE	0x00000006
+#define USB_MODE	0x00000007
 #define JTAG_MODE	0x00000000
+#define BOOT_MODE_USE_ALT	0x100
+#define BOOT_MODE_ALT_SHIFT	12
 
 #define ZYNQMP_IOU_SLCR_BASEADDR	0xFF180000
 
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 19c38f4..6f312d6 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -28,6 +28,7 @@
 	BOOT_DEVICE_SATA,
 	BOOT_DEVICE_I2C,
 	BOOT_DEVICE_BOARD,
+	BOOT_DEVICE_DFU,
 	BOOT_DEVICE_NONE
 };
 #endif
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 0c5d997..566b5e8 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -16,14 +16,114 @@
 #include <asm/io.h>
 #include <usb.h>
 #include <dwc3-uboot.h>
+#include <zynqmppl.h>
 #include <i2c.h>
+#include <g_dnl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
+    !defined(CONFIG_SPL_BUILD)
+static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
+
+static const struct {
+	uint32_t id;
+	char *name;
+} zynqmp_devices[] = {
+	{
+		.id = 0x10,
+		.name = "3eg",
+	},
+	{
+		.id = 0x11,
+		.name = "2eg",
+	},
+	{
+		.id = 0x20,
+		.name = "5ev",
+	},
+	{
+		.id = 0x21,
+		.name = "4ev",
+	},
+	{
+		.id = 0x30,
+		.name = "7ev",
+	},
+	{
+		.id = 0x38,
+		.name = "9eg",
+	},
+	{
+		.id = 0x39,
+		.name = "6eg",
+	},
+	{
+		.id = 0x40,
+		.name = "11eg",
+	},
+	{
+		.id = 0x50,
+		.name = "15eg",
+	},
+	{
+		.id = 0x58,
+		.name = "19eg",
+	},
+	{
+		.id = 0x59,
+		.name = "17eg",
+	},
+};
+
+static int chip_id(void)
+{
+	struct pt_regs regs;
+	regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
+	regs.regs[1] = 0;
+	regs.regs[2] = 0;
+	regs.regs[3] = 0;
+
+	smc_call(&regs);
+
+	return regs.regs[0];
+}
+
+static char *zynqmp_get_silicon_idcode_name(void)
+{
+	uint32_t i, id;
+
+	id = chip_id();
+	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
+		if (zynqmp_devices[i].id == id)
+			return zynqmp_devices[i].name;
+	}
+	return "unknown";
+}
+#endif
+
+#define ZYNQMP_VERSION_SIZE	9
+
 int board_init(void)
 {
 	printf("EL Level:\tEL%d\n", current_el());
 
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
+    !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
+    defined(CONFIG_SPL_BUILD))
+	if (current_el() != 3) {
+		static char version[ZYNQMP_VERSION_SIZE];
+
+		strncat(version, "xczu", ZYNQMP_VERSION_SIZE);
+		zynqmppl.name = strncat(version,
+					zynqmp_get_silicon_idcode_name(),
+					ZYNQMP_VERSION_SIZE);
+		printf("Chip ID:\t%s\n", zynqmppl.name);
+		fpga_init();
+		fpga_add(fpga_xilinx, &zynqmppl);
+	}
+#endif
+
 	return 0;
 }
 
@@ -228,6 +328,10 @@
 
 	puts("Bootmode: ");
 	switch (bootmode) {
+	case USB_MODE:
+		puts("USB_MODE\n");
+		mode = "usb";
+		break;
 	case JTAG_MODE:
 		puts("JTAG_MODE\n");
 		mode = "pxe dhcp";
@@ -283,22 +387,38 @@
 }
 
 #ifdef CONFIG_USB_DWC3
-static struct dwc3_device dwc3_device_data = {
+static struct dwc3_device dwc3_device_data0 = {
 	.maximum_speed = USB_SPEED_HIGH,
 	.base = ZYNQMP_USB0_XHCI_BASEADDR,
 	.dr_mode = USB_DR_MODE_PERIPHERAL,
 	.index = 0,
 };
 
-int usb_gadget_handle_interrupts(void)
+static struct dwc3_device dwc3_device_data1 = {
+	.maximum_speed = USB_SPEED_HIGH,
+	.base = ZYNQMP_USB1_XHCI_BASEADDR,
+	.dr_mode = USB_DR_MODE_PERIPHERAL,
+	.index = 1,
+};
+
+int usb_gadget_handle_interrupts(int index)
 {
-	dwc3_uboot_handle_interrupt(0);
+	dwc3_uboot_handle_interrupt(index);
 	return 0;
 }
 
 int board_usb_init(int index, enum usb_init_type init)
 {
-	return dwc3_uboot_init(&dwc3_device_data);
+	debug("%s: index %x\n", __func__, index);
+
+	switch (index) {
+	case 0:
+		return dwc3_uboot_init(&dwc3_device_data0);
+	case 1:
+		return dwc3_uboot_init(&dwc3_device_data1);
+	};
+
+	return -1;
 }
 
 int board_usb_cleanup(int index, enum usb_init_type init)
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index 196eb69..bd8b906 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -5,6 +5,7 @@
 CONFIG_ZYNQMP_USB=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -46,6 +47,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index a3fb226..6afacd2 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -38,6 +38,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index aec4f9b..4068c28 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -41,6 +41,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
index 0b2ebb1..c717f04 100644
--- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm018_dc4"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm018 dc4"
@@ -34,6 +33,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
index f570b2a..1a27bd0 100644
--- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
@@ -33,6 +33,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index 8fcb2fd..90b5ff6 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -6,6 +6,7 @@
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102"
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -38,6 +39,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC_OPS=y
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index b7ba599..5a0d686 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -6,6 +6,7 @@
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102"
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -38,6 +39,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC_OPS=y
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4f84469..4c555a0 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -20,6 +20,8 @@
 
 source "drivers/dma/Kconfig"
 
+source "drivers/fpga/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/hwmon/Kconfig"
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 0000000..f3f6bf7
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,20 @@
+menu "FPGA support"
+
+config FPGA
+	bool
+
+config FPGA_XILINX
+	bool "Enable Xilinx FPGA drivers"
+	select FPGA
+	help
+	  Enable Xilinx FPGA specific functions which includes bitstream
+	  (in BIT format), fpga and device validation.
+
+config FPGA_ZYNQMPPL
+	bool "Enable Xilinx FPGA driver for ZynqMP"
+	depends on FPGA_XILINX
+	help
+	  Enable FPGA driver for loading bitstream in BIT and BIN format
+	  on Xilinx Zynq UltraScale+ (ZynqMP) device.
+
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index fec3fec..777706f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
 obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
 obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
+obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o
 obj-$(CONFIG_FPGA_XILINX) += xilinx.o
 obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o
 ifdef CONFIG_FPGA_ALTERA
diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c
index d459a2f..2cd0104 100644
--- a/drivers/fpga/xilinx.c
+++ b/drivers/fpga/xilinx.c
@@ -199,6 +199,9 @@
 		case xilinx_zynq:
 			printf("Zynq PL\n");
 			break;
+		case xilinx_zynqmp:
+			printf("ZynqMP PL\n");
+			break;
 			/* Add new family types here */
 		default:
 			printf ("Unknown family type, %d\n", desc->family);
@@ -227,6 +230,9 @@
 		case devcfg:
 			printf("Device configuration interface (Zynq)\n");
 			break;
+		case csu_dma:
+			printf("csu_dma configuration interface (ZynqMP)\n");
+			break;
 			/* Add new interface types here */
 		default:
 			printf ("Unsupported interface type, %d\n", desc->iface);
diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c
new file mode 100644
index 0000000..23039c3
--- /dev/null
+++ b/drivers/fpga/zynqmppl.c
@@ -0,0 +1,238 @@
+/*
+ * (C) Copyright 2015 - 2016, Xilinx, Inc,
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad <siva.durga.paladugu@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <console.h>
+#include <common.h>
+#include <zynqmppl.h>
+#include <linux/sizes.h>
+
+#define DUMMY_WORD	0xffffffff
+
+/* Xilinx binary format header */
+static const u32 bin_format[] = {
+	DUMMY_WORD, /* Dummy words */
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	0x000000bb, /* Sync word */
+	0x11220044, /* Sync word */
+	DUMMY_WORD,
+	DUMMY_WORD,
+	0xaa995566, /* Sync word */
+};
+
+#define SWAP_NO		1
+#define SWAP_DONE	2
+
+/*
+ * Load the whole word from unaligned buffer
+ * Keep in your mind that it is byte loading on little-endian system
+ */
+static u32 load_word(const void *buf, u32 swap)
+{
+	u32 word = 0;
+	u8 *bitc = (u8 *)buf;
+	int p;
+
+	if (swap == SWAP_NO) {
+		for (p = 0; p < 4; p++) {
+			word <<= 8;
+			word |= bitc[p];
+		}
+	} else {
+		for (p = 3; p >= 0; p--) {
+			word <<= 8;
+			word |= bitc[p];
+		}
+	}
+
+	return word;
+}
+
+static u32 check_header(const void *buf)
+{
+	u32 i, pattern;
+	int swap = SWAP_NO;
+	u32 *test = (u32 *)buf;
+
+	debug("%s: Let's check bitstream header\n", __func__);
+
+	/* Checking that passing bin is not a bitstream */
+	for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
+		pattern = load_word(&test[i], swap);
+
+		/*
+		 * Bitstreams in binary format are swapped
+		 * compare to regular bistream.
+		 * Do not swap dummy word but if swap is done assume
+		 * that parsing buffer is binary format
+		 */
+		if ((__swab32(pattern) != DUMMY_WORD) &&
+		    (__swab32(pattern) == bin_format[i])) {
+			swap = SWAP_DONE;
+			debug("%s: data swapped - let's swap\n", __func__);
+		}
+
+		debug("%s: %d/%px: pattern %x/%x bin_format\n", __func__, i,
+		      &test[i], pattern, bin_format[i]);
+	}
+	debug("%s: Found bitstream header at %px %s swapinng\n", __func__,
+	      buf, swap == SWAP_NO ? "without" : "with");
+
+	return swap;
+}
+
+static void *check_data(u8 *buf, size_t bsize, u32 *swap)
+{
+	u32 word, p = 0; /* possition */
+
+	/* Because buf doesn't need to be aligned let's read it by chars */
+	for (p = 0; p < bsize; p++) {
+		word = load_word(&buf[p], SWAP_NO);
+		debug("%s: word %x %x/%px\n", __func__, word, p, &buf[p]);
+
+		/* Find the first bitstream dummy word */
+		if (word == DUMMY_WORD) {
+			debug("%s: Found dummy word at position %x/%px\n",
+			      __func__, p, &buf[p]);
+			*swap = check_header(&buf[p]);
+			if (*swap) {
+				/* FIXME add full bitstream checking here */
+				return &buf[p];
+			}
+		}
+		/* Loop can be huge - support CTRL + C */
+		if (ctrlc())
+			return NULL;
+	}
+	return NULL;
+}
+
+static ulong zynqmp_align_dma_buffer(u32 *buf, u32 len, u32 swap)
+{
+	u32 *new_buf;
+	u32 i;
+
+	if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
+		new_buf = (u32 *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
+
+		/*
+		 * This might be dangerous but permits to flash if
+		 * ARCH_DMA_MINALIGN is greater than header size
+		 */
+		if (new_buf > (u32 *)buf) {
+			debug("%s: Aligned buffer is after buffer start\n",
+			      __func__);
+			new_buf -= ARCH_DMA_MINALIGN;
+		}
+		printf("%s: Align buffer at %px to %px(swap %d)\n", __func__,
+		       buf, new_buf, swap);
+
+		for (i = 0; i < (len/4); i++)
+			new_buf[i] = load_word(&buf[i], swap);
+
+		buf = new_buf;
+	} else if (swap != SWAP_DONE) {
+		/* For bitstream which are aligned */
+		u32 *new_buf = (u32 *)buf;
+
+		printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
+		       swap);
+
+		for (i = 0; i < (len/4); i++)
+			new_buf[i] = load_word(&buf[i], swap);
+	}
+
+	return (ulong)buf;
+}
+
+static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf,
+				   size_t bsize, u32 blocksize, u32 *swap)
+{
+	ulong *buf_start;
+	ulong diff;
+
+	buf_start = check_data((u8 *)buf, blocksize, swap);
+
+	if (!buf_start)
+		return FPGA_FAIL;
+
+	/* Check if data is postpone from start */
+	diff = (ulong)buf_start - (ulong)buf;
+	if (diff) {
+		printf("%s: Bitstream is not validated yet (diff %lx)\n",
+		       __func__, diff);
+		return FPGA_FAIL;
+	}
+
+	if ((ulong)buf < SZ_1M) {
+		printf("%s: Bitstream has to be placed up to 1MB (%px)\n",
+		       __func__, buf);
+		return FPGA_FAIL;
+	}
+
+	return 0;
+}
+
+static int invoke_smc(ulong id, ulong reg0, ulong reg1, ulong reg2)
+{
+	struct pt_regs regs;
+	regs.regs[0] = id;
+	regs.regs[1] = reg0;
+	regs.regs[2] = reg1;
+	regs.regs[3] = reg2;
+
+	smc_call(&regs);
+
+	return regs.regs[0];
+}
+
+static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize,
+		     bitstream_type bstype)
+{
+	u32 swap;
+	ulong bin_buf, flags;
+	int ret;
+
+	if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap))
+		return FPGA_FAIL;
+
+	bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap);
+
+	debug("%s called!\n", __func__);
+	flush_dcache_range(bin_buf, bin_buf + bsize);
+
+	if (bsize % 4)
+		bsize = bsize / 4 + 1;
+	else
+		bsize = bsize / 4;
+
+	flags = (u32)bsize | ((u64)bstype << 32);
+
+	ret = invoke_smc(ZYNQMP_SIP_SVC_PM_FPGA_LOAD, bin_buf, flags, 0);
+	if (ret)
+		debug("PL FPGA LOAD fail\n");
+
+	return ret;
+}
+
+struct xilinx_fpga_op zynqmp_op = {
+	.load = zynqmp_load,
+};
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 09ae1be..7a176a2 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -92,7 +92,8 @@
 	u32 confr;
 
 	/* Disable SPI */
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+	confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+	writel(~confr, &regs->enr);
 
 	/* Disable Interrupts */
 	writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->idr);
@@ -173,8 +174,10 @@
 	struct udevice *bus = dev->parent;
 	struct zynq_spi_priv *priv = dev_get_priv(bus);
 	struct zynq_spi_regs *regs = priv->regs;
+	u32 confr;
 
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+	confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+	writel(~confr, &regs->enr);
 
 	return 0;
 }
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index c43ea19..5ed8beb 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -75,7 +75,9 @@
 
 /* Diff from config_distro_defaults.h */
 #define CONFIG_SUPPORT_RAW_INITRD
+#if !defined(CONFIG_SPL_BUILD)
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
+#endif
 #define CONFIG_AUTO_COMPLETE
 
 /* PXE */
@@ -108,7 +110,7 @@
 #define CONFIG_SYS_LOAD_ADDR		0x8000000
 
 #if defined(CONFIG_ZYNQMP_USB)
-#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         2
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
 #define CONFIG_USB_XHCI_ZYNQMP
 
@@ -136,7 +138,6 @@
 # define DFU_ALT_INFO
 #endif
 
-
 #define CONFIG_BOARD_LATE_INIT
 
 /* Do not preserve environment */
@@ -185,7 +186,6 @@
 #endif
 
 #ifdef CONFIG_SATA_CEVA
-#define CONFIG_AHCI
 #define CONFIG_LIBATA
 #define CONFIG_SCSI_AHCI
 #define CONFIG_SCSI_AHCI_PLAT
@@ -247,13 +247,24 @@
 	DFU_ALT_INFO
 #endif
 
+/* SPL can't handle all huge variables - define just DFU */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT)
+#undef CONFIG_EXTRA_ENV_SETTINGS
+# define CONFIG_EXTRA_ENV_SETTINGS \
+	"dfu_alt_info_ram=uboot.bin ram 0x8000000 0x1000000;" \
+			  "atf-uboot.ub ram 0x10000000 0x1000000;" \
+			  "Image ram 0x80000 0x3f80000;" \
+			  "system.dtb ram 0x4000000 0x100000\0" \
+	"dfu_bufsiz=0x1000\0"
+#endif
+
 #define CONFIG_SPL_TEXT_BASE		0xfffc0000
 #define CONFIG_SPL_STACK		0xfffffffc
-#define CONFIG_SPL_MAX_SIZE		0x20000
+#define CONFIG_SPL_MAX_SIZE		0x40000
 
 /* Just random location in OCM */
-#define CONFIG_SPL_BSS_START_ADDR	0x1000000
-#define CONFIG_SPL_BSS_MAX_SIZE		0x2000000
+#define CONFIG_SPL_BSS_START_ADDR	0x0
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000
 
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_BOARD_INIT
@@ -265,7 +276,7 @@
 #define CONFIG_SYS_SPL_ARGS_ADDR	0x8000000
 
 /* ATF is my kernel image */
-#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"atf.ub"
+#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"atf-uboot.ub"
 
 /* FIT load address for RAM boot */
 #define CONFIG_SPL_LOAD_FIT_ADDRESS	0x10000000
@@ -279,4 +290,18 @@
 # define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
 #endif
 
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT)
+# undef CONFIG_CMD_BOOTD
+# define CONFIG_SPL_ENV_SUPPORT
+# define CONFIG_SPL_HASH_SUPPORT
+# define CONFIG_ENV_MAX_ENTRIES	10
+
+# define CONFIG_SYS_SPL_MALLOC_START	0x20000000
+# define CONFIG_SYS_SPL_MALLOC_SIZE	0x10000000
+
+#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
+# error "Disable CONFIG_SPL_SYS_MALLOC_SIMPLE. Full malloc needs to be used"
+#endif
+#endif
+
 #endif /* __XILINX_ZYNQMP_H */
diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h
index 44434aa..8e4b960 100644
--- a/include/configs/xilinx_zynqmp_ep.h
+++ b/include/configs/xilinx_zynqmp_ep.h
@@ -16,7 +16,6 @@
 #define CONFIG_ZYNQ_SDHCI_MAX_FREQ	52000000
 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ	(CONFIG_ZYNQ_SDHCI_MAX_FREQ << 9)
 #define CONFIG_ZYNQ_EEPROM
-#define CONFIG_AHCI
 #define CONFIG_SATA_CEVA
 #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \
 				 ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h b/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
deleted file mode 100644
index 4866b61..0000000
--- a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Configuration for Xilinx ZynqMP zc1751 XM018 DC4
- *
- * (C) Copyright 2015 Xilinx, Inc.
- * Michal Simek <michal.simek@xilinx.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
-#define __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
-
-#include <configs/xilinx_zynqmp.h>
-
-#endif /* __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H */
diff --git a/include/xilinx.h b/include/xilinx.h
index aebcb3b..d2a2ea7 100644
--- a/include/xilinx.h
+++ b/include/xilinx.h
@@ -21,6 +21,7 @@
 	master_selectmap,	/* master SelectMap (virtex2)           */
 	slave_selectmap,	/* slave SelectMap (virtex2)            */
 	devcfg,			/* devcfg interface (zynq) */
+	csu_dma,		/* csu_dma interface (zynqmp) */
 	max_xilinx_iface_type	/* insert all new types before this */
 } xilinx_iface;			/* end, typedef xilinx_iface */
 
@@ -31,6 +32,7 @@
 	xilinx_virtex2,		/* Virtex2 Family */
 	xilinx_spartan3,	/* Spartan-III Family */
 	xilinx_zynq,		/* Zynq Family */
+	xilinx_zynqmp,		/* ZynqMP Family */
 	max_xilinx_type		/* insert all new types before this */
 } xilinx_family;		/* end, typedef xilinx_family */
 
diff --git a/include/zynqmppl.h b/include/zynqmppl.h
new file mode 100644
index 0000000..542ace9
--- /dev/null
+++ b/include/zynqmppl.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2015 Xilinx, Inc,
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ZYNQMPPL_H_
+#define _ZYNQMPPL_H_
+
+#include <xilinx.h>
+
+#define ZYNQMP_SIP_SVC_CSU_DMA_CHIPID		0xC2000018
+#define ZYNQMP_SIP_SVC_PM_FPGA_LOAD		0xC2000016
+#define ZYNQMP_FPGA_OP_INIT			(1 << 0)
+#define ZYNQMP_FPGA_OP_LOAD			(1 << 1)
+#define ZYNQMP_FPGA_OP_DONE			(1 << 2)
+
+extern struct xilinx_fpga_op zynqmp_op;
+
+#define XILINX_ZYNQMP_DESC \
+{ xilinx_zynqmp, csu_dma, 1, &zynqmp_op, 0, &zynqmp_op }
+
+#endif /* _ZYNQMPPL_H_ */