Patchwork [U-Boot,v2,15/15] fpga: Add support for loading bitstream for Xilinx Zynq

login
register
mail settings
Submitter Michal Simek
Date April 23, 2013, 10:46 a.m.
Message ID <31cca7fcbc7bf2d7124175d2aece969504dbf7ae.1366713845.git.michal.simek@xilinx.com>
Download mbox | patch
Permalink /patch/238878/
State Accepted
Delegated to: Michal Simek
Headers show

Comments

Michal Simek - April 23, 2013, 10:46 a.m.
Devcfg device requires to load bitstream in binary format.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
Changes in v2:
- Fix bugs reported by Tom Rini
- Fix checkpatch warnings (fpga)
- Fix comments (fpga)
- Do not use CamelCase for XilinxZynq (fpga)

 arch/arm/cpu/armv7/zynq/slcr.c             |  35 +++++
 arch/arm/include/asm/arch-zynq/hardware.h  |  10 +-
 arch/arm/include/asm/arch-zynq/sys_proto.h |   3 +
 board/xilinx/zynq/board.c                  |  37 +++++
 drivers/fpga/Makefile                      |   1 +
 drivers/fpga/xilinx.c                      |  37 +++++
 drivers/fpga/zynqpl.c                      | 231 +++++++++++++++++++++++++++++
 include/configs/zynq.h                     |   6 +
 include/xilinx.h                           |   4 +
 include/zynqpl.h                           |  59 ++++++++
 10 files changed, 421 insertions(+), 2 deletions(-)
 create mode 100644 drivers/fpga/zynqpl.c
 create mode 100644 include/zynqpl.h

--
1.8.2.1

Patch

diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c
index 5a8674a..52048c6 100644
--- a/arch/arm/cpu/armv7/zynq/slcr.c
+++ b/arch/arm/cpu/armv7/zynq/slcr.c
@@ -28,6 +28,9 @@ 
 #define SLCR_LOCK_MAGIC		0x767B
 #define SLCR_UNLOCK_MAGIC	0xDF0D

+#define SLCR_IDCODE_MASK	0x1F000
+#define SLCR_IDCODE_SHIFT	12
+
 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */

 void zynq_slcr_lock(void)
@@ -87,3 +90,35 @@  void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk)
 out:
 	zynq_slcr_lock();
 }
+
+void zynq_slcr_devcfg_disable(void)
+{
+	zynq_slcr_unlock();
+
+	/* Disable AXI interface */
+	writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl);
+
+	/* Set Level Shifters DT618760 */
+	writel(0xA, &slcr_base->lvl_shftr_en);
+
+	zynq_slcr_lock();
+}
+
+void zynq_slcr_devcfg_enable(void)
+{
+	zynq_slcr_unlock();
+
+	/* Set Level Shifters DT618760 */
+	writel(0xF, &slcr_base->lvl_shftr_en);
+
+	/* Disable AXI interface */
+	writel(0x0, &slcr_base->fpga_rst_ctrl);
+
+	zynq_slcr_lock();
+}
+
+u32 zynq_slcr_get_idcode(void)
+{
+	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
+							SLCR_IDCODE_SHIFT;
+}
diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h
index 6af892a..8b8a91a 100644
--- a/arch/arm/include/asm/arch-zynq/hardware.h
+++ b/arch/arm/include/asm/arch-zynq/hardware.h
@@ -53,11 +53,17 @@  struct slcr_regs {
 	u32 boot_mode; /* 0x25c */
 	u32 reserved4[116];
 	u32 trust_zone; /* 0x430 */ /* FIXME */
-	u32 reserved5[115];
+	u32 reserved5_1[63];
+	u32 pss_idcode; /* 0x530 */
+	u32 reserved5_2[51];
 	u32 ddr_urgent; /* 0x600 */
 	u32 reserved6[6];
 	u32 ddr_urgent_sel; /* 0x61c */
-	u32 reserved7[188];
+	u32 reserved7[56];
+	u32 mio_pin[54]; /* 0x700 - 0x7D4 */
+	u32 reserved8[74];
+	u32 lvl_shftr_en; /* 0x900 */
+	u32 reserved9[3];
 	u32 ocm_cfg; /* 0x910 */
 };

diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h
index af9e7f8..2317121 100644
--- a/arch/arm/include/asm/arch-zynq/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynq/sys_proto.h
@@ -27,6 +27,9 @@  extern void zynq_slcr_lock(void);
 extern void zynq_slcr_unlock(void);
 extern void zynq_slcr_cpu_reset(void);
 extern void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk);
+extern void zynq_slcr_devcfg_disable(void);
+extern void zynq_slcr_devcfg_enable(void);
+extern u32 zynq_slcr_get_idcode(void);

 /* Driver extern functions */
 extern int zynq_sdhci_init(u32 regbase);
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
index 1589d21..b02c364 100644
--- a/board/xilinx/zynq/board.c
+++ b/board/xilinx/zynq/board.c
@@ -22,15 +22,52 @@ 

 #include <common.h>
 #include <netdev.h>
+#include <zynqpl.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>

 DECLARE_GLOBAL_DATA_PTR;

+#ifdef CONFIG_FPGA
+Xilinx_desc fpga;
+
+/* It can be done differently */
+Xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
+Xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
+Xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
+Xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
+#endif
+
 int board_init(void)
 {
+#ifdef CONFIG_FPGA
+	u32 idcode;
+
+	idcode = zynq_slcr_get_idcode();
+
+	switch (idcode) {
+	case XILINX_ZYNQ_7010:
+		fpga = fpga010;
+		break;
+	case XILINX_ZYNQ_7020:
+		fpga = fpga020;
+		break;
+	case XILINX_ZYNQ_7030:
+		fpga = fpga030;
+		break;
+	case XILINX_ZYNQ_7045:
+		fpga = fpga045;
+		break;
+	}
+#endif
+
 	icache_enable();

+#ifdef CONFIG_FPGA
+	fpga_init();
+	fpga_add(fpga_xilinx, &fpga);
+#endif
+
 	return 0;
 }

diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index b48f623..0b51dcd 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -30,6 +30,7 @@  COBJS-y += fpga.o
 COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
 COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
 COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
+COBJS-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
 COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o
 COBJS-$(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 32787b2..fe324ab 100644
--- a/drivers/fpga/xilinx.c
+++ b/drivers/fpga/xilinx.c
@@ -1,4 +1,6 @@ 
 /*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
  * (C) Copyright 2002
  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  * Keith Outwater, keith_outwater@mvis.com
@@ -31,6 +33,7 @@ 
 #include <virtex2.h>
 #include <spartan2.h>
 #include <spartan3.h>
+#include <zynqpl.h>

 #if 0
 #define FPGA_DEBUG
@@ -86,6 +89,16 @@  int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize)
 					__FUNCTION__);
 #endif
 			break;
+		case xilinx_zynq:
+#if defined(CONFIG_FPGA_ZYNQPL)
+			PRINTF("%s: Launching the Zynq PL Loader...\n",
+			       __func__);
+			ret_val = zynq_load(desc, buf, bsize);
+#else
+			printf("%s: No support for Zynq devices.\n",
+			       __func__);
+#endif
+			break;

 		default:
 			printf ("%s: Unsupported family type, %d\n",
@@ -133,6 +146,16 @@  int xilinx_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
 					__FUNCTION__);
 #endif
 			break;
+		case xilinx_zynq:
+#if defined(CONFIG_FPGA_ZYNQPL)
+			PRINTF("%s: Launching the Zynq PL Reader...\n",
+			       __func__);
+			ret_val = zynq_dump(desc, buf, bsize);
+#else
+			printf("%s: No support for Zynq devices.\n",
+			       __func__);
+#endif
+			break;

 		default:
 			printf ("%s: Unsupported family type, %d\n",
@@ -158,6 +181,9 @@  int xilinx_info (Xilinx_desc * desc)
 		case Xilinx_Virtex2:
 			printf ("Virtex-II\n");
 			break;
+		case xilinx_zynq:
+			printf("Zynq PL\n");
+			break;
 			/* Add new family types here */
 		default:
 			printf ("Unknown family type, %d\n", desc->family);
@@ -183,6 +209,9 @@  int xilinx_info (Xilinx_desc * desc)
 		case master_selectmap:
 			printf ("Master SelectMap Mode\n");
 			break;
+		case devcfg:
+			printf("Device configuration interface (Zynq)\n");
+			break;
 			/* Add new interface types here */
 		default:
 			printf ("Unsupported interface type, %d\n", desc->iface);
@@ -222,6 +251,14 @@  int xilinx_info (Xilinx_desc * desc)
 						__FUNCTION__);
 #endif
 				break;
+			case xilinx_zynq:
+#if defined(CONFIG_FPGA_ZYNQPL)
+				zynq_info(desc);
+#else
+				/* just in case */
+				printf("%s: No support for Zynq devices.\n",
+				       __func__);
+#endif
 				/* Add new family types here */
 			default:
 				/* we don't need a message here - we give one up above */
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
new file mode 100644
index 0000000..0365803
--- /dev/null
+++ b/drivers/fpga/zynqpl.c
@@ -0,0 +1,231 @@ 
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2012
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <zynqpl.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+#define DEVCFG_CTRL_PCFG_PROG_B		0x40000000
+#define DEVCFG_ISR_FATAL_ERROR_MASK	0x00740040
+#define DEVCFG_ISR_ERROR_FLAGS_MASK	0x00340840
+#define DEVCFG_ISR_RX_FIFO_OV		0x00040000
+#define DEVCFG_ISR_DMA_DONE		0x00002000
+#define DEVCFG_ISR_PCFG_DONE		0x00000004
+#define DEVCFG_STATUS_DMA_CMD_Q_F	0x80000000
+#define DEVCFG_STATUS_DMA_CMD_Q_E	0x40000000
+#define DEVCFG_STATUS_DMA_DONE_CNT_MASK	0x30000000
+#define DEVCFG_STATUS_PCFG_INIT		0x00000010
+#define DEVCFG_MCTRL_RFIFO_FLUSH	0x00000002
+#define DEVCFG_MCTRL_WFIFO_FLUSH	0x00000001
+
+#ifndef CONFIG_SYS_FPGA_WAIT
+#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
+#endif
+
+#ifndef CONFIG_SYS_FPGA_PROG_TIME
+#define CONFIG_SYS_FPGA_PROG_TIME CONFIG_SYS_HZ	/* 1 s */
+#endif
+
+int zynq_info(Xilinx_desc *desc)
+{
+	return FPGA_SUCCESS;
+}
+
+/* Xilinx binary format header */
+static const u32 bin_format[] = {
+	0xffffffff, /* Dummy words */
+	0xffffffff,
+	0xffffffff,
+	0xffffffff,
+	0xffffffff,
+	0xffffffff,
+	0xffffffff,
+	0xffffffff,
+	0x000000bb, /* Sync word */
+	0x11220044, /* Sync word */
+	0xffffffff,
+	0xffffffff,
+	0xaa995566, /* Sync word */
+};
+
+int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	unsigned long ts; /* Timestamp */
+	u32 control;
+	u32 isr_status;
+	u32 status;
+	const u32 *test = buf;
+	int i;
+
+	if ((u32)buf & 0x3) {
+		printf("Error: Buffer is not aligned %x\n", (u32)buf);
+		return FPGA_FAIL;
+	}
+
+	/* Check bitstream size */
+	if (bsize != desc->size) {
+		printf("Error: File size is wrong - should be %x.\n",
+		       desc->size);
+		return FPGA_FAIL;
+	}
+
+	/* Checking that passing bin is not a bitstream */
+	for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
+		if (test[i] != bin_format[i]) {
+			puts("Error: File not in binary format.\n");
+			return FPGA_FAIL;
+		}
+	}
+
+	zynq_slcr_devcfg_disable();
+
+	/* Setting PCFG_PROG_B signal to high */
+	control = readl(&devcfg_base->ctrl);
+	writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
+	/* Setting PCFG_PROG_B signal to low */
+	writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
+
+	/* Polling the PCAP_INIT status for Reset */
+	ts = get_timer(0);
+	while (readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT) {
+		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+			puts("Error: Timeout waiting for INIT to clear.\n");
+			return FPGA_FAIL;
+		}
+	}
+
+	/* Setting PCFG_PROG_B signal to high */
+	writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
+
+	/* Polling the PCAP_INIT status for Set */
+	ts = get_timer(0);
+	while (!(readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT)) {
+		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+			puts("Error: Timeout waiting for INIT to set.\n");
+			return FPGA_FAIL;
+		}
+	}
+
+	isr_status = readl(&devcfg_base->int_sts);
+
+	/* Clear it all, so if Boot ROM comes back, it can proceed */
+	writel(0xFFFFFFFF, &devcfg_base->int_sts);
+
+	if (isr_status & DEVCFG_ISR_FATAL_ERROR_MASK) {
+		debug("Fatal errors in PCAP 0x%X\n", isr_status);
+
+		/* If RX FIFO overflow, need to flush RX FIFO first */
+		if (isr_status & DEVCFG_ISR_RX_FIFO_OV) {
+			writel(DEVCFG_MCTRL_RFIFO_FLUSH, &devcfg_base->mctrl);
+			writel(0xFFFFFFFF, &devcfg_base->int_sts);
+		}
+		return FPGA_FAIL;
+	}
+
+	status = readl(&devcfg_base->status);
+
+	debug("status = 0x%08X\n", status);
+
+	if (status & DEVCFG_STATUS_DMA_CMD_Q_F) {
+		debug("Error: device busy\n");
+		return FPGA_FAIL;
+	}
+
+	debug("device ready\n");
+
+	if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) {
+		if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) {
+			/* Error state, transfer cannot occur */
+			debug("isr indicates error\n");
+			return FPGA_FAIL;
+		} else {
+			/* Clear out the status */
+			writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
+		}
+	}
+
+	if (status & DEVCFG_STATUS_DMA_DONE_CNT_MASK) {
+		/* Clear the count of completed DMA transfers */
+		writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status);
+	}
+
+	debug("Source = 0x%08X\n", (u32)buf);
+	debug("Size = %zu\n", bsize);
+
+	/* Set up the transfer */
+	writel((u32)buf | 1, &devcfg_base->dma_src_addr);
+	writel(0xFFFFFFFF, &devcfg_base->dma_dst_addr);
+	writel(bsize >> 2, &devcfg_base->dma_src_len);
+	writel(0, &devcfg_base->dma_dst_len);
+
+	isr_status = readl(&devcfg_base->int_sts);
+
+	/* Polling the PCAP_INIT status for Set */
+	ts = get_timer(0);
+	while (!(isr_status & DEVCFG_ISR_DMA_DONE)) {
+		if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) {
+			debug("Error: isr = 0x%08X\n", isr_status);
+			debug("Write count = 0x%08X\n",
+			      readl(&devcfg_base->write_count));
+			debug("Read count = 0x%08X\n",
+			      readl(&devcfg_base->read_count));
+
+			return FPGA_FAIL;
+		}
+		if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
+			puts("Error: Timeout waiting for DMA to complete.\n");
+			return FPGA_FAIL;
+		}
+		isr_status = readl(&devcfg_base->int_sts);
+	}
+
+	debug("DMA transfer is done\n");
+
+	/* Check FPGA configuration completion */
+	ts = get_timer(0);
+	while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
+		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+			puts("Error: Timeout waiting for FPGA to config.\n");
+			return FPGA_FAIL;
+		}
+		isr_status = readl(&devcfg_base->int_sts);
+	}
+
+	debug("FPGA config done\n");
+
+	/* Clear out the DMA status */
+	writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
+
+	zynq_slcr_devcfg_enable();
+
+	return FPGA_SUCCESS;
+}
+
+int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	return FPGA_FAIL;
+}
diff --git a/include/configs/zynq.h b/include/configs/zynq.h
index f1f182e..38f04f6 100644
--- a/include/configs/zynq.h
+++ b/include/configs/zynq.h
@@ -88,6 +88,12 @@ 
 # define CONFIG_CPU_V6 /* Required by CONFIG_ARM_DCC */
 #endif

+/* Enable the PL to be downloaded */
+#define CONFIG_FPGA
+#define CONFIG_FPGA_XILINX
+#define CONFIG_FPGA_ZYNQPL
+#define CONFIG_CMD_FPGA
+
 #define CONFIG_BOOTP_SERVERIP
 #define CONFIG_BOOTP_BOOTPATH
 #define CONFIG_BOOTP_GATEWAY
diff --git a/include/xilinx.h b/include/xilinx.h
index 5f25b7a..592cbea 100644
--- a/include/xilinx.h
+++ b/include/xilinx.h
@@ -33,10 +33,12 @@ 
 #define CONFIG_SYS_VIRTEX_E			CONFIG_SYS_FPGA_DEV( 0x2 )
 #define CONFIG_SYS_VIRTEX2			CONFIG_SYS_FPGA_DEV( 0x4 )
 #define CONFIG_SYS_SPARTAN3			CONFIG_SYS_FPGA_DEV( 0x8 )
+#define CONFIG_SYS_ZYNQ				CONFIG_SYS_FPGA_DEV(0x10)
 #define CONFIG_SYS_XILINX_SPARTAN2	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN2)
 #define CONFIG_SYS_XILINX_VIRTEX_E	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX_E)
 #define CONFIG_SYS_XILINX_VIRTEX2	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX2)
 #define CONFIG_SYS_XILINX_SPARTAN3	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN3)
+#define CONFIG_SYS_XILINX_ZYNQ	(CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_ZYNQ)
 /* XXX - Add new models here */


@@ -59,6 +61,7 @@  typedef enum {			/* typedef Xilinx_iface */
 	jtag_mode,		/* jtag/tap serial (not used ) */
 	master_selectmap,	/* master SelectMap (virtex2)           */
 	slave_selectmap,	/* slave SelectMap (virtex2)            */
+	devcfg,			/* devcfg interface (zynq) */
 	max_xilinx_iface_type	/* insert all new types before this */
 } Xilinx_iface;			/* end, typedef Xilinx_iface */

@@ -68,6 +71,7 @@  typedef enum {			/* typedef Xilinx_Family */
 	Xilinx_VirtexE,		/* Virtex-E Family */
 	Xilinx_Virtex2,		/* Virtex2 Family */
 	Xilinx_Spartan3,	/* Spartan-III Family */
+	xilinx_zynq,		/* Zynq Family */
 	max_xilinx_type		/* insert all new types before this */
 } Xilinx_Family;		/* end, typedef Xilinx_Family */

diff --git a/include/zynqpl.h b/include/zynqpl.h
new file mode 100644
index 0000000..bc9b948
--- /dev/null
+++ b/include/zynqpl.h
@@ -0,0 +1,59 @@ 
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2012
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ZYNQPL_H_
+#define _ZYNQPL_H_
+
+#include <xilinx.h>
+
+extern int zynq_load(Xilinx_desc *desc, const void *image, size_t size);
+extern int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+extern int zynq_info(Xilinx_desc *desc);
+
+#define XILINX_ZYNQ_7010	0x2
+#define XILINX_ZYNQ_7020	0x7
+#define XILINX_ZYNQ_7030	0xc
+#define XILINX_ZYNQ_7045	0x11
+
+/* Device Image Sizes */
+#define XILINX_XC7Z010_SIZE	16669920/8
+#define XILINX_XC7Z020_SIZE	32364512/8
+#define XILINX_XC7Z030_SIZE	47839328/8
+#define XILINX_XC7Z045_SIZE	106571232/8
+
+/* Descriptor Macros */
+#define XILINX_XC7Z010_DESC(cookie) \
+{ xilinx_zynq, devcfg, XILINX_XC7Z010_SIZE, NULL, cookie }
+
+#define XILINX_XC7Z020_DESC(cookie) \
+{ xilinx_zynq, devcfg, XILINX_XC7Z020_SIZE, NULL, cookie }
+
+#define XILINX_XC7Z030_DESC(cookie) \
+{ xilinx_zynq, devcfg, XILINX_XC7Z030_SIZE, NULL, cookie }
+
+#define XILINX_XC7Z045_DESC(cookie) \
+{ xilinx_zynq, devcfg, XILINX_XC7Z045_SIZE, NULL, cookie }
+
+#endif /* _ZYNQPL_H_ */