Merge branch 'zynq' of git://www.denx.de/git/u-boot-microblaze
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2167e29..00be305 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -649,7 +649,7 @@
 	bool "Support Colibri VF50/61"
 	select CPU_V7
 
-config ZYNQ
+config ARCH_ZYNQ
 	bool "Xilinx Zynq Platform"
 	select CPU_V7
 	select SUPPORT_SPL
@@ -837,7 +837,7 @@
 
 source "arch/arm/mach-versatile/Kconfig"
 
-source "arch/arm/cpu/armv7/zynq/Kconfig"
+source "arch/arm/mach-zynq/Kconfig"
 
 source "arch/arm/cpu/armv7/Kconfig"
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index bd4749c..2a5620d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -55,6 +55,7 @@
 machine-$(CONFIG_TEGRA)			+= tegra
 machine-$(CONFIG_ARCH_UNIPHIER)		+= uniphier
 machine-$(CONFIG_ARCH_VERSATILE)	+= versatile
+machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index e6249f1..fcccd0c 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -56,4 +56,3 @@
 obj-$(CONFIG_ARCH_SUNXI) += sunxi/
 obj-$(CONFIG_U8500) += u8500/
 obj-$(CONFIG_VF610) += vf610/
-obj-$(CONFIG_ZYNQ) += zynq/
diff --git a/arch/arm/cpu/armv7/zynq/config.mk b/arch/arm/cpu/armv7/zynq/config.mk
deleted file mode 100644
index 778a377e..0000000
--- a/arch/arm/cpu/armv7/zynq/config.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved.
-#
-# SPDX-License-Identifier:      GPL-2.0
-#
-# Allow NEON instructions (needed for lowlevel_init.S with GNU toolchain)
-PLATFORM_RELFLAGS += -mfpu=neon
diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile
index a997e04..efab5ea 100644
--- a/arch/arm/cpu/armv8/zynqmp/Makefile
+++ b/arch/arm/cpu/armv8/zynqmp/Makefile
@@ -7,3 +7,4 @@
 
 obj-y	+= clk.o
 obj-y	+= cpu.o
+obj-$(CONFIG_MP)	+= mp.o
diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c
index 0af619d..9218586 100644
--- a/arch/arm/cpu/armv8/zynqmp/clk.c
+++ b/arch/arm/cpu/armv8/zynqmp/clk.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 
@@ -16,6 +17,8 @@
 	u32 ver = zynqmp_get_silicon_version();
 
 	switch (ver) {
+	case ZYNQMP_CSU_VERSION_VELOCE:
+		return 48000;
 	case ZYNQMP_CSU_VERSION_EP108:
 		return 25000000;
 	}
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index 6fae03c..60d7d20 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -20,9 +20,175 @@
 	gd->cpu_clk = get_tbclk();
 
 	switch (gd->cpu_clk) {
+	case 0 ... 1000000:
+		return ZYNQMP_CSU_VERSION_VELOCE;
 	case 50000000:
 		return ZYNQMP_CSU_VERSION_QEMU;
 	}
 
 	return ZYNQMP_CSU_VERSION_EP108;
 }
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#include <asm/armv8/mmu.h>
+
+#define SECTION_SHIFT_L1	30UL
+#define SECTION_SHIFT_L2	21UL
+#define BLOCK_SIZE_L0		0x8000000000UL
+#define BLOCK_SIZE_L1		(1 << SECTION_SHIFT_L1)
+#define BLOCK_SIZE_L2		(1 << SECTION_SHIFT_L2)
+
+#define TCR_TG1_4K		(1 << 31)
+#define TCR_EPD1_DISABLE	(1 << 23)
+#define ZYNQMO_VA_BITS		40
+#define ZYNQMP_TCR		TCR_TG1_4K | \
+				TCR_EPD1_DISABLE | \
+				TCR_SHARED_OUTER | \
+				TCR_SHARED_INNER | \
+				TCR_IRGN_WBWA | \
+				TCR_ORGN_WBWA | \
+				TCR_T0SZ(ZYNQMO_VA_BITS)
+
+#define MEMORY_ATTR	PMD_SECT_AF | PMD_SECT_INNER_SHARE |	\
+			PMD_ATTRINDX(MT_NORMAL) |	\
+			PMD_TYPE_SECT
+#define DEVICE_ATTR	PMD_SECT_AF | PMD_SECT_PXN |	\
+			PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_NGNRNE) |	\
+			PMD_TYPE_SECT
+
+/* 4K size is required to place 512 entries in each level */
+#define TLB_TABLE_SIZE	0x1000
+
+struct attr_tbl {
+	u32 num;
+	u64 attr;
+};
+
+static struct attr_tbl attr_tbll1t0[4] = { {16, 0x0},
+					   {8, DEVICE_ATTR},
+					   {32, MEMORY_ATTR},
+					   {456, DEVICE_ATTR}
+					 };
+static struct attr_tbl attr_tbll2t3[4] = { {0x180, DEVICE_ATTR},
+					   {0x40, 0x0},
+					   {0x3F, DEVICE_ATTR},
+					   {0x1, MEMORY_ATTR}
+					 };
+
+/*
+ * This mmu table looks as below
+ * Level 0 table contains two entries to 512GB sizes. One is Level1 Table 0
+ * and other Level1 Table1.
+ * Level1 Table0 contains entries for each 1GB from 0 to 511GB.
+ * Level1 Table1 contains entries for each 1GB from 512GB to 1TB.
+ * Level2 Table0, Level2 Table1, Level2 Table2 and Level2 Table3 contains
+ * entries for each 2MB starting from 0GB, 1GB, 2GB and 3GB respectively.
+ */
+static void zynqmp_mmu_setup(void)
+{
+	int el;
+	u32 index_attr;
+	u64 i, section_l1t0, section_l1t1;
+	u64 section_l2t0, section_l2t1, section_l2t2, section_l2t3;
+	u64 *level0_table = (u64 *)gd->arch.tlb_addr;
+	u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + TLB_TABLE_SIZE);
+	u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + (2 * TLB_TABLE_SIZE));
+	u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE));
+	u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + (4 * TLB_TABLE_SIZE));
+	u64 *level2_table_2 = (u64 *)(gd->arch.tlb_addr + (5 * TLB_TABLE_SIZE));
+	u64 *level2_table_3 = (u64 *)(gd->arch.tlb_addr + (6 * TLB_TABLE_SIZE));
+
+	level0_table[0] =
+		(u64)level1_table_0 | PMD_TYPE_TABLE;
+	level0_table[1] =
+		(u64)level1_table_1 | PMD_TYPE_TABLE;
+
+	/*
+	 * set level 1 table 0, covering 0 to 512GB
+	 * set level 1 table 1, covering 512GB to 1TB
+	 */
+	section_l1t0 = 0;
+	section_l1t1 = BLOCK_SIZE_L0;
+
+	index_attr = 0;
+	for (i = 0; i < 512; i++) {
+		level1_table_0[i] = section_l1t0;
+		level1_table_0[i] |= attr_tbll1t0[index_attr].attr;
+		attr_tbll1t0[index_attr].num--;
+		if (attr_tbll1t0[index_attr].num == 0)
+			index_attr++;
+		level1_table_1[i] = section_l1t1;
+		level1_table_1[i] |= DEVICE_ATTR;
+		section_l1t0 += BLOCK_SIZE_L1;
+		section_l1t1 += BLOCK_SIZE_L1;
+	}
+
+	level1_table_0[0] =
+		(u64)level2_table_0 | PMD_TYPE_TABLE;
+	level1_table_0[1] =
+		(u64)level2_table_1 | PMD_TYPE_TABLE;
+	level1_table_0[2] =
+		(u64)level2_table_2 | PMD_TYPE_TABLE;
+	level1_table_0[3] =
+		(u64)level2_table_3 | PMD_TYPE_TABLE;
+
+	section_l2t0 = 0;
+	section_l2t1 = section_l2t0 + BLOCK_SIZE_L1; /* 1GB */
+	section_l2t2 = section_l2t1 + BLOCK_SIZE_L1; /* 2GB */
+	section_l2t3 = section_l2t2 + BLOCK_SIZE_L1; /* 3GB */
+
+	index_attr = 0;
+
+	for (i = 0; i < 512; i++) {
+		level2_table_0[i] = section_l2t0 | MEMORY_ATTR;
+		level2_table_1[i] = section_l2t1 | MEMORY_ATTR;
+		level2_table_2[i] = section_l2t2 | DEVICE_ATTR;
+		level2_table_3[i] = section_l2t3 |
+				    attr_tbll2t3[index_attr].attr;
+		attr_tbll2t3[index_attr].num--;
+		if (attr_tbll2t3[index_attr].num == 0)
+			index_attr++;
+		section_l2t0 += BLOCK_SIZE_L2;
+		section_l2t1 += BLOCK_SIZE_L2;
+		section_l2t2 += BLOCK_SIZE_L2;
+		section_l2t3 += BLOCK_SIZE_L2;
+	}
+
+	/* flush new MMU table */
+	flush_dcache_range(gd->arch.tlb_addr,
+			   gd->arch.tlb_addr + gd->arch.tlb_size);
+
+	/* point TTBR to the new table */
+	el = current_el();
+	set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
+			  ZYNQMP_TCR, MEMORY_ATTRIBUTES);
+
+	set_sctlr(get_sctlr() | CR_M);
+}
+
+int arch_cpu_init(void)
+{
+	icache_enable();
+	__asm_invalidate_dcache_all();
+	__asm_invalidate_tlb_all();
+	return 0;
+}
+
+/*
+ * This function is called from lib/board.c.
+ * It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
+ * There is no need to disable d-cache for this operation.
+ */
+void enable_caches(void)
+{
+	/* The data cache is not active unless the mmu is enabled */
+	if (!(get_sctlr() & CR_M)) {
+		invalidate_dcache_all();
+		__asm_invalidate_tlb_all();
+		zynqmp_mmu_setup();
+	}
+	puts("Enabling Caches...\n");
+
+	set_sctlr(get_sctlr() | CR_C);
+}
+#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c
new file mode 100644
index 0000000..17e32a7
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/mp.c
@@ -0,0 +1,242 @@
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+
+#define LOCK		0
+#define SPLIT		1
+
+#define HALT		0
+#define RELEASE		1
+
+#define ZYNQMP_BOOTADDR_HIGH_MASK		0xFFFFFFFF
+#define ZYNQMP_R5_HIVEC_ADDR			0xFFFF0000
+#define ZYNQMP_R5_LOVEC_ADDR			0x0
+#define ZYNQMP_RPU_CFG_CPU_HALT_MASK		0x01
+#define ZYNQMP_RPU_CFG_HIVEC_MASK		0x04
+#define ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK	0x08
+#define ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK	0x40
+#define ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK	0x10
+
+#define ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK	0x04
+#define ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK	0x01
+#define ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK	0x02
+#define ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK	0x1000000
+
+#define ZYNQMP_TCM_START_ADDRESS		0xFFE00000
+#define ZYNQMP_TCM_BOTH_SIZE			0x40000
+
+#define ZYNQMP_CORE_APU0	0
+#define ZYNQMP_CORE_APU3	3
+
+#define ZYNQMP_MAX_CORES	6
+
+int is_core_valid(unsigned int core)
+{
+	if (core < ZYNQMP_MAX_CORES)
+		return 1;
+
+	return 0;
+}
+
+int cpu_reset(int nr)
+{
+	puts("Feature is not implemented.\n");
+	return 0;
+}
+
+static void set_r5_halt_mode(u8 halt, u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu0_cfg);
+	if (halt == HALT)
+		tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+	else
+		tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+	writel(tmp, &rpu_base->rpu0_cfg);
+
+	if (mode == LOCK) {
+		tmp = readl(&rpu_base->rpu1_cfg);
+		if (halt == HALT)
+			tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+		else
+			tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+		writel(tmp, &rpu_base->rpu1_cfg);
+	}
+}
+
+static void set_r5_tcm_mode(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu_glbl_ctrl);
+	if (mode == LOCK) {
+		tmp &= ~ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+		tmp |= ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+		       ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK;
+	} else {
+		tmp |= ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+		tmp &= ~(ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+		       ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK);
+	}
+
+	writel(tmp, &rpu_base->rpu_glbl_ctrl);
+}
+
+static void set_r5_reset(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->rst_lpd_top);
+	tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+	       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+	if (mode == LOCK)
+		tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+	writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void release_r5_reset(u8 mode)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->rst_lpd_top);
+	tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+	       ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+	if (mode == LOCK)
+		tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+	writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void enable_clock_r5(void)
+{
+	u32 tmp;
+
+	tmp = readl(&crlapb_base->cpu_r5_ctrl);
+	tmp |= ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK;
+	writel(tmp, &crlapb_base->cpu_r5_ctrl);
+
+	/* Give some delay for clock
+	 * to propogate */
+	udelay(0x500);
+}
+
+int cpu_disable(int nr)
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val |= 1 << nr;
+		writel(val, &crfapb_base->rst_fpd_apu);
+	} else {
+		set_r5_reset(LOCK);
+	}
+
+	return 0;
+}
+
+int cpu_status(int nr)
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+		u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) +
+				      nr * 8);
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val &= 1 << nr;
+		printf("APU CPU%d %s - starting address HI: %x, LOW: %x\n",
+		       nr, val ? "OFF" : "ON" , addr_high, addr_low);
+	} else {
+		u32 val = readl(&crlapb_base->rst_lpd_top);
+		val &= 1 << (nr - 4);
+		printf("RPU CPU%d %s\n", nr - 4, val ? "OFF" : "ON");
+	}
+
+	return 0;
+}
+
+static void set_r5_start(u8 high)
+{
+	u32 tmp;
+
+	tmp = readl(&rpu_base->rpu0_cfg);
+	if (high)
+		tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+	else
+		tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+	writel(tmp, &rpu_base->rpu0_cfg);
+
+	tmp = readl(&rpu_base->rpu1_cfg);
+	if (high)
+		tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+	else
+		tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+	writel(tmp, &rpu_base->rpu1_cfg);
+}
+
+int cpu_release(int nr, int argc, char * const argv[])
+{
+	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+		u64 boot_addr = simple_strtoull(argv[0], NULL, 16);
+		/* HIGH */
+		writel((u32)(boot_addr >> 32),
+		       ((u8 *)&apu_base->rvbar_addr0_h) + nr * 8);
+		/* LOW */
+		writel((u32)(boot_addr & ZYNQMP_BOOTADDR_HIGH_MASK),
+		       ((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+
+		u32 val = readl(&crfapb_base->rst_fpd_apu);
+		val &= ~(1 << nr);
+		writel(val, &crfapb_base->rst_fpd_apu);
+	} else {
+		if (argc != 2) {
+			printf("Invalid number of arguments to release.\n");
+			printf("<addr> <mode>-Start addr lockstep or split\n");
+			return 1;
+		}
+
+		u32 boot_addr = simple_strtoul(argv[0], NULL, 16);
+		if (!(boot_addr == ZYNQMP_R5_LOVEC_ADDR ||
+		      boot_addr == ZYNQMP_R5_HIVEC_ADDR)) {
+			printf("Invalid starting address 0x%x\n", boot_addr);
+			printf("0 or 0xffff0000 are permitted\n");
+			return 1;
+		}
+
+		if (!strncmp(argv[1], "lockstep", 8)) {
+			printf("R5 lockstep mode\n");
+			set_r5_tcm_mode(LOCK);
+			set_r5_halt_mode(HALT, LOCK);
+
+			if (boot_addr == 0)
+				set_r5_start(0);
+			else
+				set_r5_start(1);
+
+			enable_clock_r5();
+			release_r5_reset(LOCK);
+			set_r5_halt_mode(RELEASE, LOCK);
+		} else if (!strncmp(argv[1], "split", 5)) {
+			printf("R5 split mode\n");
+			set_r5_tcm_mode(SPLIT);
+			set_r5_halt_mode(HALT, SPLIT);
+			enable_clock_r5();
+			release_r5_reset(SPLIT);
+			set_r5_halt_mode(RELEASE, SPLIT);
+		} else {
+			printf("Unsupported mode\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 09708d9..46a6171 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -39,11 +39,12 @@
 	uniphier-ph1-pro4-ref.dtb \
 	uniphier-ph1-ld4-ref.dtb \
 	uniphier-ph1-sld8-ref.dtb
-dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \
+dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \
 	zynq-zc706.dtb \
 	zynq-zed.dtb \
 	zynq-zybo.dtb \
 	zynq-microzed.dtb \
+	zynq-picozed.dtb \
 	zynq-zc770-xm010.dtb \
 	zynq-zc770-xm012.dtb \
 	zynq-zc770-xm013.dtb
diff --git a/arch/arm/dts/zynq-picozed.dts b/arch/arm/dts/zynq-picozed.dts
new file mode 100644
index 0000000..686b98f
--- /dev/null
+++ b/arch/arm/dts/zynq-picozed.dts
@@ -0,0 +1,23 @@
+/*
+ * Avnet PicoZed board DTS
+ *
+ * Copyright (C) 2015 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+/dts-v1/;
+#include "zynq-7000.dtsi"
+
+/ {
+	model = "Zynq PicoZed Board";
+	compatible = "xlnx,zynq-picozed", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
+};
diff --git a/arch/arm/include/asm/arch-zynq/gpio.h b/arch/arm/include/asm/arch-zynq/gpio.h
deleted file mode 100644
index a26ae87..0000000
--- a/arch/arm/include/asm/arch-zynq/gpio.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (c) 2013 Xilinx, Inc.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef _ZYNQ_GPIO_H
-#define _ZYNQ_GPIO_H
-
-#endif /* _ZYNQ_GPIO_H */
diff --git a/arch/arm/include/asm/arch-zynqmp/gpio.h b/arch/arm/include/asm/arch-zynqmp/gpio.h
new file mode 100644
index 0000000..098bbde
--- /dev/null
+++ b/arch/arm/include/asm/arch-zynqmp/gpio.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2015 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#ifndef __ARCH_ZYNQMP_GPIO_H
+#define __ARCH_ZYNQMP_GPIO_H
+
+/* Empty file - sdhci requires this. */
+
+#endif
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index 97fb49a..c9dc49d 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -11,6 +11,12 @@
 #define ZYNQ_SERIAL_BASEADDR0	0xFF000000
 #define ZYNQ_SERIAL_BASEADDR1	0xFF001000
 
+#define ZYNQ_SPI_BASEADDR0	0xFF040000
+#define ZYNQ_SPI_BASEADDR1	0xFF050000
+
+#define ZYNQ_I2C_BASEADDR0	0xFF020000
+#define ZYNQ_I2C_BASEADDR1	0xFF030000
+
 #define ZYNQ_SDHCI_BASEADDR0	0xFF160000
 #define ZYNQ_SDHCI_BASEADDR1	0xFF170000
 
@@ -18,11 +24,15 @@
 #define ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT	0x1000000
 
 struct crlapb_regs {
-	u32 reserved0[74];
+	u32 reserved0[36];
+	u32 cpu_r5_ctrl; /* 0x90 */
+	u32 reserved1[37];
 	u32 timestamp_ref_ctrl; /* 0x128 */
-	u32 reserved0_1[53];
+	u32 reserved2[53];
 	u32 boot_mode; /* 0x200 */
-	u32 reserved1[26];
+	u32 reserved3[14];
+	u32 rst_lpd_top; /* 0x23C */
+	u32 reserved4[26];
 };
 
 #define crlapb_base ((struct crlapb_regs *)ZYNQMP_CRL_APB_BASEADDR)
@@ -41,12 +51,47 @@
 
 /* Bootmode setting values */
 #define BOOT_MODES_MASK	0x0000000F
-#define SD_MODE		0x00000005
+#define SD_MODE		0x00000003
+#define EMMC_MODE	0x00000006
 #define JTAG_MODE	0x00000000
 
+#define ZYNQMP_RPU_BASEADDR	0xFF9A0000
+
+struct rpu_regs {
+	u32 rpu_glbl_ctrl;
+	u32 reserved0[63];
+	u32 rpu0_cfg; /* 0x100 */
+	u32 reserved1[63];
+	u32 rpu1_cfg; /* 0x200 */
+};
+
+#define rpu_base ((struct rpu_regs *)ZYNQMP_RPU_BASEADDR)
+
+#define ZYNQMP_CRF_APB_BASEADDR	0xFD1A0000
+
+struct crfapb_regs {
+	u32 reserved0[65];
+	u32 rst_fpd_apu; /* 0x104 */
+	u32 reserved1;
+};
+
+#define crfapb_base ((struct crfapb_regs *)ZYNQMP_CRF_APB_BASEADDR)
+
+#define ZYNQMP_APU_BASEADDR	0xFD5C0000
+
+struct apu_regs {
+	u32 reserved0[16];
+	u32 rvbar_addr0_l; /* 0x40 */
+	u32 rvbar_addr0_h; /* 0x44 */
+	u32 reserved1[20];
+};
+
+#define apu_base ((struct apu_regs *)ZYNQMP_APU_BASEADDR)
+
 /* Board version value */
 #define ZYNQMP_CSU_VERSION_SILICON	0x0
 #define ZYNQMP_CSU_VERSION_EP108	0x1
+#define ZYNQMP_CSU_VERSION_VELOCE	0x2
 #define ZYNQMP_CSU_VERSION_QEMU		0x3
 
 #endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/cpu/armv7/zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
similarity index 85%
rename from arch/arm/cpu/armv7/zynq/Kconfig
rename to arch/arm/mach-zynq/Kconfig
index 3a52535..1046ece 100644
--- a/arch/arm/cpu/armv7/zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -1,4 +1,4 @@
-if ZYNQ
+if ARCH_ZYNQ
 
 choice
 	prompt "Xilinx Zynq board select"
@@ -9,6 +9,9 @@
 config TARGET_ZYNQ_MICROZED
 	bool "Zynq MicroZed"
 
+config TARGET_ZYNQ_PICOZED
+	bool "Zynq PicoZed"
+
 config TARGET_ZYNQ_ZC70X
 	bool "Zynq ZC702/ZC706 Board"
 
@@ -32,6 +35,7 @@
 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_ZC70X
 	default "zynq_zc770" if TARGET_ZYNQ_ZC770
 	default "zynq_zybo" if TARGET_ZYNQ_ZYBO
diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/mach-zynq/Makefile
similarity index 90%
rename from arch/arm/cpu/armv7/zynq/Makefile
rename to arch/arm/mach-zynq/Makefile
index 901f2ce..bf29b4d 100644
--- a/arch/arm/cpu/armv7/zynq/Makefile
+++ b/arch/arm/mach-zynq/Makefile
@@ -14,4 +14,5 @@
 obj-y	+= slcr.o
 obj-y	+= clk.o
 obj-y	+= lowlevel_init.o
+AFLAGS_lowlevel_init.o := -mfpu=neon
 obj-$(CONFIG_SPL_BUILD)	+= spl.o
diff --git a/arch/arm/cpu/armv7/zynq/clk.c b/arch/arm/mach-zynq/clk.c
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/clk.c
rename to arch/arm/mach-zynq/clk.c
diff --git a/arch/arm/cpu/armv7/zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/cpu.c
rename to arch/arm/mach-zynq/cpu.c
diff --git a/arch/arm/cpu/armv7/zynq/ddrc.c b/arch/arm/mach-zynq/ddrc.c
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/ddrc.c
rename to arch/arm/mach-zynq/ddrc.c
diff --git a/arch/arm/include/asm/arch-zynq/clk.h b/arch/arm/mach-zynq/include/mach/clk.h
similarity index 100%
rename from arch/arm/include/asm/arch-zynq/clk.h
rename to arch/arm/mach-zynq/include/mach/clk.h
diff --git a/arch/arm/mach-zynq/include/mach/gpio.h b/arch/arm/mach-zynq/include/mach/gpio.h
new file mode 100644
index 0000000..9e1e7da
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/gpio.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Xilinx, Inc.
+ * Copyright (c) 2015 DAVE Embedded Systems
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ZYNQ_GPIO_H
+#define _ZYNQ_GPIO_H
+
+#define ZYNQ_GPIO_BASE_ADDRESS 0xE000A000
+
+/* Maximum banks */
+#define ZYNQ_GPIO_MAX_BANK	4
+
+#define ZYNQ_GPIO_BANK0_NGPIO	32
+#define ZYNQ_GPIO_BANK1_NGPIO	22
+#define ZYNQ_GPIO_BANK2_NGPIO	32
+#define ZYNQ_GPIO_BANK3_NGPIO	32
+
+#define ZYNQ_GPIO_NR_GPIOS	(ZYNQ_GPIO_BANK0_NGPIO + \
+				 ZYNQ_GPIO_BANK1_NGPIO + \
+				 ZYNQ_GPIO_BANK2_NGPIO + \
+				 ZYNQ_GPIO_BANK3_NGPIO)
+
+#define ZYNQ_GPIO_BANK0_PIN_MIN	0
+#define ZYNQ_GPIO_BANK0_PIN_MAX	(ZYNQ_GPIO_BANK0_PIN_MIN + \
+					ZYNQ_GPIO_BANK0_NGPIO - 1)
+#define ZYNQ_GPIO_BANK1_PIN_MIN	(ZYNQ_GPIO_BANK0_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK1_PIN_MAX	(ZYNQ_GPIO_BANK1_PIN_MIN + \
+					ZYNQ_GPIO_BANK1_NGPIO - 1)
+#define ZYNQ_GPIO_BANK2_PIN_MIN	(ZYNQ_GPIO_BANK1_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK2_PIN_MAX	(ZYNQ_GPIO_BANK2_PIN_MIN + \
+					ZYNQ_GPIO_BANK2_NGPIO - 1)
+#define ZYNQ_GPIO_BANK3_PIN_MIN	(ZYNQ_GPIO_BANK2_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK3_PIN_MAX	(ZYNQ_GPIO_BANK3_PIN_MIN + \
+					ZYNQ_GPIO_BANK3_NGPIO - 1)
+
+/* Register offsets for the GPIO device */
+/* LSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK)	(0x000 + (8 * BANK))
+/* MSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK)	(0x004 + (8 * BANK))
+/* Data Register-RW */
+#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK)	(0x060 + (4 * BANK))
+/* Direction mode reg-RW */
+#define ZYNQ_GPIO_DIRM_OFFSET(BANK)	(0x204 + (0x40 * BANK))
+/* Output enable reg-RW */
+#define ZYNQ_GPIO_OUTEN_OFFSET(BANK)	(0x208 + (0x40 * BANK))
+/* Interrupt mask reg-RO */
+#define ZYNQ_GPIO_INTMASK_OFFSET(BANK)	(0x20C + (0x40 * BANK))
+/* Interrupt enable reg-WO */
+#define ZYNQ_GPIO_INTEN_OFFSET(BANK)	(0x210 + (0x40 * BANK))
+/* Interrupt disable reg-WO */
+#define ZYNQ_GPIO_INTDIS_OFFSET(BANK)	(0x214 + (0x40 * BANK))
+/* Interrupt status reg-RO */
+#define ZYNQ_GPIO_INTSTS_OFFSET(BANK)	(0x218 + (0x40 * BANK))
+/* Interrupt type reg-RW */
+#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK)	(0x21C + (0x40 * BANK))
+/* Interrupt polarity reg-RW */
+#define ZYNQ_GPIO_INTPOL_OFFSET(BANK)	(0x220 + (0x40 * BANK))
+/* Interrupt on any, reg-RW */
+#define ZYNQ_GPIO_INTANY_OFFSET(BANK)	(0x224 + (0x40 * BANK))
+
+/* Disable all interrupts mask */
+#define ZYNQ_GPIO_IXR_DISABLE_ALL	0xFFFFFFFF
+
+/* Mid pin number of a bank */
+#define ZYNQ_GPIO_MID_PIN_NUM 16
+
+/* GPIO upper 16 bit mask */
+#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
+
+#define BIT(x) (1<<x)
+
+#endif /* _ZYNQ_GPIO_H */
diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
similarity index 100%
rename from arch/arm/include/asm/arch-zynq/hardware.h
rename to arch/arm/mach-zynq/include/mach/hardware.h
diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/mach-zynq/include/mach/sys_proto.h
similarity index 100%
rename from arch/arm/include/asm/arch-zynq/sys_proto.h
rename to arch/arm/mach-zynq/include/mach/sys_proto.h
diff --git a/arch/arm/cpu/armv7/zynq/lowlevel_init.S b/arch/arm/mach-zynq/lowlevel_init.S
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/lowlevel_init.S
rename to arch/arm/mach-zynq/lowlevel_init.S
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
similarity index 95%
rename from arch/arm/cpu/armv7/zynq/slcr.c
rename to arch/arm/mach-zynq/slcr.c
index 2521589..05f4099 100644
--- a/arch/arm/cpu/armv7/zynq/slcr.c
+++ b/arch/arm/mach-zynq/slcr.c
@@ -129,11 +129,18 @@
 
 void zynq_slcr_devcfg_disable(void)
 {
+	u32 reg_val;
+
 	zynq_slcr_unlock();
 
 	/* Disable AXI interface by asserting FPGA resets */
 	writel(0xF, &slcr_base->fpga_rst_ctrl);
 
+	/* Disable Level shifters before setting PS-PL */
+	reg_val = readl(&slcr_base->lvl_shftr_en);
+	reg_val &= ~0xF;
+	writel(reg_val, &slcr_base->lvl_shftr_en);
+
 	/* Set Level Shifters DT618760 */
 	writel(0xA, &slcr_base->lvl_shftr_en);
 
diff --git a/arch/arm/cpu/armv7/zynq/spl.c b/arch/arm/mach-zynq/spl.c
similarity index 96%
rename from arch/arm/cpu/armv7/zynq/spl.c
rename to arch/arm/mach-zynq/spl.c
index b80c357..13025f0 100644
--- a/arch/arm/cpu/armv7/zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -85,6 +85,6 @@
 {
 	/*
 	 * This function is overridden by the one in
-	 * board/xilinx/zynq/ps7_init.c, if it exists.
+	 * board/xilinx/zynq/ps7_init_gpl.c, if it exists.
 	 */
 }
diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/mach-zynq/timer.c
similarity index 96%
rename from arch/arm/cpu/armv7/zynq/timer.c
rename to arch/arm/mach-zynq/timer.c
index 303dbcf..5ed9642 100644
--- a/arch/arm/cpu/armv7/zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -93,7 +93,9 @@
 		gd->arch.tbl += gd->arch.lastinc - now;
 	} else {
 		/* We have an overflow ... */
-		gd->arch.tbl += gd->arch.lastinc + TIMER_LOAD_VAL - now + 1;
+		gd->arch.tbl += gd->arch.lastinc + (TIMER_LOAD_VAL /
+				(gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) -
+				now + 1;
 	}
 	gd->arch.lastinc = now;
 
diff --git a/arch/arm/cpu/armv7/zynq/u-boot-spl.lds b/arch/arm/mach-zynq/u-boot-spl.lds
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/u-boot-spl.lds
rename to arch/arm/mach-zynq/u-boot-spl.lds
diff --git a/arch/arm/cpu/armv7/zynq/u-boot.lds b/arch/arm/mach-zynq/u-boot.lds
similarity index 100%
rename from arch/arm/cpu/armv7/zynq/u-boot.lds
rename to arch/arm/mach-zynq/u-boot.lds
diff --git a/board/xilinx/zynq/.gitignore b/board/xilinx/zynq/.gitignore
index 7c36bc9..c455361 100644
--- a/board/xilinx/zynq/.gitignore
+++ b/board/xilinx/zynq/.gitignore
@@ -1,2 +1 @@
-ps7_init.[ch]
 ps7_init_gpl.[ch]
diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
index 3b1eb4f..054c3d8 100644
--- a/board/xilinx/zynq/Makefile
+++ b/board/xilinx/zynq/Makefile
@@ -9,9 +9,7 @@
 
 # Please copy ps7_init_gpl.c/h from hw project to this directory
 obj-$(CONFIG_SPL_BUILD) += \
-		$(if $(wildcard $(srctree)/$(src)/ps7_init_gpl.c), ps7_init_gpl.o, \
-			$(if $(wildcard $(srctree)/$(src)/ps7_init.c), ps7_init.o legacy.o))
+	$(if $(wildcard $(srctree)/$(src)/ps7_init_gpl.c), ps7_init_gpl.o)
 
 # Suppress "warning: function declaration isn't a prototype"
 CFLAGS_REMOVE_ps7_init_gpl.o := -Wstrict-prototypes
-CFLAGS_REMOVE_ps7_init.o := -Wstrict-prototypes
diff --git a/board/xilinx/zynq/legacy.c b/board/xilinx/zynq/legacy.c
deleted file mode 100644
index 4ae913e..0000000
--- a/board/xilinx/zynq/legacy.c
+++ /dev/null
@@ -1,2 +0,0 @@
-
-#warning usage of ps7_init files is deprecated please use ps7_init_gpl
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 1325bca..f5ff64d 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -56,14 +56,18 @@
 {
 	int ret = 0;
 
+	u32 ver = zynqmp_get_silicon_version();
+
+	if (ver != ZYNQMP_CSU_VERSION_VELOCE) {
 #if defined(CONFIG_ZYNQ_SDHCI)
 # if defined(CONFIG_ZYNQ_SDHCI0)
-	ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0);
+		ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0);
 # endif
 # if defined(CONFIG_ZYNQ_SDHCI1)
-	ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1);
+		ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1);
 # endif
 #endif
+	}
 
 	return ret;
 }
@@ -79,6 +83,7 @@
 
 	switch (bootmode) {
 	case SD_MODE:
+	case EMMC_MODE:
 		setenv("modeboot", "sdboot");
 		break;
 	default:
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index 95cfe89..40d675f 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -1,6 +1,6 @@
 CONFIG_SPL=y
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_MICROZED=y
 CONFIG_OF_CONTROL=y
 # CONFIG_SYS_MALLOC_F is not set
diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig
new file mode 100644
index 0000000..61852cb
--- /dev/null
+++ b/configs/zynq_picozed_defconfig
@@ -0,0 +1,6 @@
+CONFIG_SPL=y
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_TARGET_ZYNQ_PICOZED=y
+CONFIG_OF_CONTROL=n
+CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed"
diff --git a/configs/zynq_zc70x_defconfig b/configs/zynq_zc70x_defconfig
index 81fb4af..7c3cb2d 100644
--- a/configs/zynq_zc70x_defconfig
+++ b/configs/zynq_zc70x_defconfig
@@ -1,6 +1,6 @@
 CONFIG_SPL=y
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZC70X=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702"
diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig
index fc39cca..36b95fa 100644
--- a/configs/zynq_zc770_xm010_defconfig
+++ b/configs/zynq_zc770_xm010_defconfig
@@ -1,7 +1,7 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010"
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010"
diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig
index 21e52fb..6c5eecc 100644
--- a/configs/zynq_zc770_xm012_defconfig
+++ b/configs/zynq_zc770_xm012_defconfig
@@ -1,7 +1,7 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012"
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012"
diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig
index 2c38012..eabc106 100644
--- a/configs/zynq_zc770_xm013_defconfig
+++ b/configs/zynq_zc770_xm013_defconfig
@@ -1,7 +1,7 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013"
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZC770=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013"
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index d4dc5bb..b2b4b99 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -1,6 +1,6 @@
 CONFIG_SPL=y
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZED=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zed"
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index 7d06073..da55320 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -1,6 +1,6 @@
 CONFIG_SPL=y
 CONFIG_ARM=y
-CONFIG_ZYNQ=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_TARGET_ZYNQ_ZYBO=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8ca8b05..fb40e09 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -43,3 +43,4 @@
 obj-$(CONFIG_SUNXI_GPIO)	+= sunxi_gpio.o
 obj-$(CONFIG_LPC32XX_GPIO)	+= lpc32xx_gpio.o
 obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
+obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c
new file mode 100644
index 0000000..83a2c46
--- /dev/null
+++ b/drivers/gpio/zynq_gpio.c
@@ -0,0 +1,220 @@
+/*
+ * Xilinx Zynq GPIO device driver
+ *
+ * Copyright (C) 2015 DAVE Embedded Systems <devel@dave.eu>
+ *
+ * Most of code taken from linux kernel driver (linux/drivers/gpio/gpio-zynq.c)
+ * Copyright (C) 2009 - 2014 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+/**
+ * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
+ * for a given pin in the GPIO device
+ * @pin_num:	gpio pin number within the device
+ * @bank_num:	an output parameter used to return the bank number of the gpio
+ *		pin
+ * @bank_pin_num: an output parameter used to return pin number within a bank
+ *		  for the given gpio pin
+ *
+ * Returns the bank number and pin offset within the bank.
+ */
+static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
+					  unsigned int *bank_num,
+					  unsigned int *bank_pin_num)
+{
+	switch (pin_num) {
+	case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
+		*bank_num = 0;
+		*bank_pin_num = pin_num;
+		break;
+	case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
+		*bank_num = 1;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
+		break;
+	case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
+		*bank_num = 2;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
+		break;
+	case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
+		*bank_num = 3;
+		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
+		break;
+	default:
+		printf("invalid GPIO pin number: %u\n", pin_num);
+		*bank_num = 0;
+		*bank_pin_num = 0;
+		break;
+	}
+}
+
+int gpio_is_valid(unsigned gpio)
+{
+	return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
+}
+
+static int check_gpio(unsigned gpio)
+{
+	if (!gpio_is_valid(gpio)) {
+		printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * gpio_get_value - Get the state of the specified pin of GPIO device
+ * @gpio:	gpio pin number within the device
+ *
+ * This function reads the state of the specified pin of the GPIO device.
+ *
+ * Return: 0 if the pin is low, 1 if pin is high.
+ */
+int gpio_get_value(unsigned gpio)
+{
+	u32 data;
+	unsigned int bank_num, bank_pin_num;
+
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
+
+	data = readl(ZYNQ_GPIO_BASE_ADDRESS +
+			     ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
+
+	return (data >> bank_pin_num) & 1;
+}
+
+/**
+ * gpio_set_value - Modify the value of the pin with specified value
+ * @gpio:	gpio pin number within the device
+ * @value:	value used to modify the value of the specified pin
+ *
+ * This function calculates the register offset (i.e to lower 16 bits or
+ * upper 16 bits) based on the given pin number and sets the value of a
+ * gpio pin to the specified value. The value is either 0 or non-zero.
+ */
+int gpio_set_value(unsigned gpio, int value)
+{
+	unsigned int reg_offset, bank_num, bank_pin_num;
+
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
+
+	if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
+		/* only 16 data bits in bit maskable reg */
+		bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
+		reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
+	} else {
+		reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
+	}
+
+	/*
+	 * get the 32 bit value to be written to the mask/data register where
+	 * the upper 16 bits is the mask and lower 16 bits is the data
+	 */
+	value = !!value;
+	value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
+		((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
+
+	writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset);
+
+	return 0;
+}
+
+/**
+ * gpio_direction_input - Set the direction of the specified GPIO pin as input
+ * @gpio:	gpio pin number within the device
+ *
+ * This function uses the read-modify-write sequence to set the direction of
+ * the gpio pin as input.
+ *
+ * Return: -1 if invalid gpio specified, 0 if successul
+ */
+int gpio_direction_input(unsigned gpio)
+{
+	u32 reg;
+	unsigned int bank_num, bank_pin_num;
+
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
+
+	/* bank 0 pins 7 and 8 are special and cannot be used as inputs */
+	if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
+		return -1;
+
+	/* clear the bit in direction mode reg to set the pin as input */
+	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	reg &= ~BIT(bank_pin_num);
+	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+	return 0;
+}
+
+/**
+ * gpio_direction_output - Set the direction of the specified GPIO pin as output
+ * @gpio:	gpio pin number within the device
+ * @value:	value to be written to specified pin
+ *
+ * This function sets the direction of specified GPIO pin as output, configures
+ * the Output Enable register for the pin and uses zynq_gpio_set to set
+ * the value of the pin to the value specified.
+ *
+ * Return: 0 always
+ */
+int gpio_direction_output(unsigned gpio, int value)
+{
+	u32 reg;
+	unsigned int bank_num, bank_pin_num;
+
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
+
+	/* set the GPIO pin as output */
+	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	reg |= BIT(bank_pin_num);
+	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+	/* configure the output enable reg for the pin */
+	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+	reg |= BIT(bank_pin_num);
+	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+
+	/* set the state of the pin */
+	gpio_set_value(gpio, value);
+	return 0;
+}
+
+/**
+ * Request a gpio before using it.
+ *
+ * NOTE: Argument 'label' is unused.
+ */
+int gpio_request(unsigned gpio, const char *label)
+{
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * Reset and free the gpio after using it.
+ */
+int gpio_free(unsigned gpio)
+{
+	return 0;
+}
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 7887f11..d4f3882 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -25,7 +25,7 @@
 
 	host->name = "zynq_sdhci";
 	host->ioaddr = (void *)regbase;
-	host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD |
+	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
 		       SDHCI_QUIRK_BROKEN_R1B;
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
index 3e2b8dc..9278763 100644
--- a/drivers/serial/serial_zynq.c
+++ b/drivers/serial/serial_zynq.c
@@ -48,10 +48,16 @@
 	/* Calculation results. */
 	unsigned int calc_bauderror, bdiv, bgen;
 	unsigned long calc_baud = 0;
-	unsigned long baud = gd->baudrate;
+	unsigned long baud;
 	unsigned long clock = get_uart_clk(port);
 	struct uart_zynq *regs = uart_zynq_ports[port];
 
+	/* Covering case where input clock is so slow */
+	if (clock < 1000000 && gd->baudrate > 4800)
+		gd->baudrate = 4800;
+
+	baud = gd->baudrate;
+
 	/*                master clock
 	 * Baud rate = ------------------
 	 *              bgen * (bdiv + 1)
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 511ecca..880d29c 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -36,7 +36,7 @@
 #define CPU_RELEASE_ADDR	0xFFFFFF0
 
 /* Cache Definitions */
-#define CONFIG_SYS_DCACHE_OFF
+#define CONFIG_SYS_CACHELINE_SIZE	64
 
 #define CONFIG_IDENT_STRING		" Xilinx ZynqMP"
 
@@ -61,13 +61,25 @@
 #define CONFIG_SYS_BAUDRATE_TABLE \
 	{ 4800, 9600, 19200, 38400, 57600, 115200 }
 
+#define CONFIG_ZYNQ_SDHCI0
+
 /* Command line configuration */
 #define CONFIG_CMD_ENV
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_EXT4
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 #define CONFIG_CMD_MEMORY
 #define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_ELF
+#define CONFIG_MP
+
+/* SPI */
+#ifdef CONFIG_ZYNQ_SPI
+# define CONFIG_SPI_FLASH
+# define CONFIG_SPI_FLASH_SST
+# define CONFIG_CMD_SF
+#endif
 
 #if defined(CONFIG_ZYNQ_SDHCI0) || defined(CONFIG_ZYNQ_SDHCI1)
 # define CONFIG_MMC
@@ -90,8 +102,8 @@
 	"kernel_addr=0x80000\0" \
 	"fdt_addr=0x7000000\0" \
 	"fdt_high=0x10000000\0" \
-	"sdboot=mmcinfo && fatload mmc 0:0 $fdt_addr system.dtb && " \
-		"fatload mmc 0:0 $kernel_addr Image && booti $kernel_addr - $fdt_addr\0"
+	"sdboot=mmcinfo && load mmc 0:0 $fdt_addr system.dtb && " \
+		"load mmc 0:0 $kernel_addr Image && booti $kernel_addr - $fdt_addr\0"
 
 #define CONFIG_BOOTARGS		"setenv bootargs console=ttyPS0,${baudrate} " \
 				"earlycon=cdns,mmio,0xff000000,${baudrate}n8"
@@ -117,6 +129,29 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_MAXARGS		64
 
+#define CONFIG_ZYNQ_I2C0
+#define CONFIG_SYS_I2C_ZYNQ
+
+/* I2C */
+#if defined(CONFIG_SYS_I2C_ZYNQ)
+# define CONFIG_CMD_I2C
+# define CONFIG_SYS_I2C
+# define CONFIG_SYS_I2C_ZYNQ_SPEED		100000
+# define CONFIG_SYS_I2C_ZYNQ_SLAVE		0
+#endif
+
+#define CONFIG_ZYNQMP_EEPROM
+
+/* EEPROM */
+#ifdef CONFIG_ZYNQMP_EEPROM
+# define CONFIG_CMD_EEPROM
+# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		2
+# define CONFIG_SYS_I2C_EEPROM_ADDR		0x54
+# define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	4
+# define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS	5
+# define CONFIG_SYS_EEPROM_SIZE			(64 * 1024)
+#endif
+
 #define CONFIG_FIT
 #define CONFIG_FIT_VERBOSE       /* enable fit_format_{error,warning}() */
 
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 485babd..b83e037 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -39,6 +39,9 @@
 # define CONFIG_ZYNQ_SERIAL
 #endif
 
+#define CONFIG_ZYNQ_GPIO
+#define CONFIG_CMD_GPIO
+
 /* Ethernet driver */
 #if defined(CONFIG_ZYNQ_GEM0) || defined(CONFIG_ZYNQ_GEM1)
 # define CONFIG_NET_MULTI
@@ -291,7 +294,7 @@
 # define CONFIG_SYS_MMC_MAX_DEVICE	1
 #endif
 
-#define CONFIG_SYS_LDSCRIPT  "arch/arm/cpu/armv7/zynq/u-boot.lds"
+#define CONFIG_SYS_LDSCRIPT  "arch/arm/mach-zynq/u-boot.lds"
 
 /* Commands */
 #include <config_cmd_default.h>
@@ -309,7 +312,7 @@
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_BOARD_INIT
 
-#define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/armv7/zynq/u-boot-spl.lds"
+#define CONFIG_SPL_LDSCRIPT	"arch/arm/mach-zynq/u-boot-spl.lds"
 
 /* MMC support */
 #ifdef CONFIG_ZYNQ_SDHCI0
diff --git a/include/configs/zynq_picozed.h b/include/configs/zynq_picozed.h
new file mode 100644
index 0000000..d116e05
--- /dev/null
+++ b/include/configs/zynq_picozed.h
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2015 Xilinx, Inc.
+ *
+ * Configuration for PicoZed
+ * See zynq-common.h for Zynq common configs
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQ_PICOZED_H
+#define __CONFIG_ZYNQ_PICOZED_H
+
+#define CONFIG_SYS_SDRAM_SIZE		(1024 * 1024 * 1024)
+
+#define CONFIG_ZYNQ_SERIAL_UART1
+#define CONFIG_ZYNQ_GEM0
+#define CONFIG_ZYNQ_GEM_PHY_ADDR0	0
+
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_ZYNQ_SDHCI1
+#define CONFIG_ZYNQ_USB
+#define CONFIG_ZYNQ_BOOT_FREEBSD
+
+#include <configs/zynq-common.h>
+
+#endif /* __CONFIG_ZYNQ_PICOZED_H */