ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/uboot/drivers/fpga/ACEX1K.c b/marvell/uboot/drivers/fpga/ACEX1K.c
new file mode 100644
index 0000000..06b8837
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/ACEX1K.c
@@ -0,0 +1,249 @@
+/*
+ * (C) Copyright 2003
+ * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>		/* core U-Boot definitions */
+#include <ACEX1K.h>		/* ACEX device family */
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef	FPGA_DEBUG
+#define PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Note: The assumption is that we cannot possibly run fast enough to
+ * overrun the device (the Slave Parallel mode can free run at 50MHz).
+ * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
+ * the board config file to slow things down.
+ */
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CONFIG_SYS_FPGA_WAIT
+#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10		/* 100 ms */
+#endif
+
+static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
+static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
+/* static int ACEX1K_ps_info(Altera_desc *desc); */
+
+/* ------------------------------------------------------------------------- */
+/* ACEX1K Generic Implementation */
+int ACEX1K_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+		PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
+		ret_val = ACEX1K_ps_load (desc, buf, bsize);
+		break;
+
+		/* Add new interface types here */
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int ACEX1K_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+		PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
+		ret_val = ACEX1K_ps_dump (desc, buf, bsize);
+		break;
+
+		/* Add new interface types here */
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int ACEX1K_info( Altera_desc *desc )
+{
+	return FPGA_SUCCESS;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* ACEX1K Passive Serial Generic Implementation                                  */
+
+static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
+	int i;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"config:\t0x%p\n"
+				"status:\t0x%p\n"
+				"clk:\t0x%p\n"
+				"data:\t0x%p\n"
+				"done:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->config, fn->status,
+				fn->clk, fn->data, fn->done);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...", cookie);
+#endif
+
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->config) (true, true, cookie);	/* Assert nCONFIG */
+
+		udelay(2);		/* T_cfg > 2us	*/
+
+		/* nSTATUS should be asserted now */
+		(*fn->done) (cookie);
+		if ( !(*fn->status) (cookie) ) {
+			puts ("** nSTATUS is not asserted.\n");
+			(*fn->abort) (cookie);
+			return FPGA_FAIL;
+		}
+
+		(*fn->config) (false, true, cookie);	/* Deassert nCONFIG */
+		udelay(2);		/* T_cf2st1 < 4us	*/
+
+		/* Wait for nSTATUS to be released (i.e. deasserted) */
+		ts = get_timer (0);		/* get current time */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for STATUS to go high.\n");
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+			(*fn->done) (cookie);
+		} while ((*fn->status) (cookie));
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+
+		/* Load the data */
+		while (bytecount < bsize) {
+			unsigned char val=0;
+#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
+			if (ctrlc ()) {
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+#endif
+			/* Altera detects an error if INIT goes low (active)
+			   while DONE is low (inactive) */
+#if 0 /* not yet implemented */
+			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
+				puts ("** CRC error during FPGA load.\n");
+				(*fn->abort) (cookie);
+				return (FPGA_FAIL);
+			}
+#endif
+			val = data [bytecount ++ ];
+			i = 8;
+			do {
+				/* Deassert the clock */
+				(*fn->clk) (false, true, cookie);
+				CONFIG_FPGA_DELAY ();
+				/* Write data */
+				(*fn->data) ((val & 0x01), true, cookie);
+				CONFIG_FPGA_DELAY ();
+				/* Assert the clock */
+				(*fn->clk) (true, true, cookie);
+				CONFIG_FPGA_DELAY ();
+				val >>= 1;
+				i --;
+			} while (i > 0);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		CONFIG_FPGA_DELAY ();
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc (' ');			/* terminate the dotted line */
+#endif
+
+	/*
+	 * Checking FPGA's CONF_DONE signal - correctly booted ?
+	 */
+
+	if ( ! (*fn->done) (cookie) ) {
+		puts ("** Booting failed! CONF_DONE is still deasserted.\n");
+		(*fn->abort) (cookie);
+		return (FPGA_FAIL);
+	}
+
+	/*
+	 * "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
+	 */
+
+	for (i = 0; i < 12; i++) {
+		CONFIG_FPGA_DELAY ();
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+		CONFIG_FPGA_DELAY ();
+		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+	}
+
+	ret_val = FPGA_SUCCESS;
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		if (ret_val == FPGA_SUCCESS) {
+			puts ("Done.\n");
+		}
+		else {
+			puts ("Fail.\n");
+		}
+#endif
+	(*fn->post) (cookie);
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	/* Readback is only available through the Slave Parallel and         */
+	/* boundary-scan interfaces.                                         */
+	printf ("%s: Passive Serial Dumping is unavailable\n",
+			__FUNCTION__);
+	return FPGA_FAIL;
+}
diff --git a/marvell/uboot/drivers/fpga/Makefile b/marvell/uboot/drivers/fpga/Makefile
new file mode 100644
index 0000000..dfb2e7f
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/Makefile
@@ -0,0 +1,20 @@
+#
+# (C) Copyright 2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += fpga.o
+obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
+obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
+obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
+obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
+obj-$(CONFIG_FPGA_XILINX) += xilinx.o
+obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o
+ifdef CONFIG_FPGA_ALTERA
+obj-y += altera.o
+obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
+obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
+obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+endif
diff --git a/marvell/uboot/drivers/fpga/altera.c b/marvell/uboot/drivers/fpga/altera.c
new file mode 100644
index 0000000..af189f4
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/altera.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2003
+ * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ *  Altera FPGA support
+ */
+#include <common.h>
+#include <ACEX1K.h>
+#include <stratixII.h>
+
+/* Define FPGA_DEBUG to get debug printf's */
+/* #define FPGA_DEBUG */
+
+#ifdef	FPGA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Local Static Functions */
+static int altera_validate (Altera_desc * desc, const char *fn);
+
+/* ------------------------------------------------------------------------- */
+int altera_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume a failure */
+
+	if (!altera_validate (desc, (char *)__FUNCTION__)) {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	} else {
+		switch (desc->family) {
+		case Altera_ACEX1K:
+		case Altera_CYC2:
+#if defined(CONFIG_FPGA_ACEX1K)
+			PRINTF ("%s: Launching the ACEX1K Loader...\n",
+					__FUNCTION__);
+			ret_val = ACEX1K_load (desc, buf, bsize);
+#elif defined(CONFIG_FPGA_CYCLON2)
+			PRINTF ("%s: Launching the CYCLONE II Loader...\n",
+					__FUNCTION__);
+			ret_val = CYC2_load (desc, buf, bsize);
+#else
+			printf ("%s: No support for ACEX1K devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+
+#if defined(CONFIG_FPGA_STRATIX_II)
+		case Altera_StratixII:
+			PRINTF ("%s: Launching the Stratix II Loader...\n",
+				__FUNCTION__);
+			ret_val = StratixII_load (desc, buf, bsize);
+			break;
+#endif
+		default:
+			printf ("%s: Unsupported family type, %d\n",
+					__FUNCTION__, desc->family);
+		}
+	}
+
+	return ret_val;
+}
+
+int altera_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume a failure */
+
+	if (!altera_validate (desc, (char *)__FUNCTION__)) {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	} else {
+		switch (desc->family) {
+		case Altera_ACEX1K:
+#if defined(CONFIG_FPGA_ACEX)
+			PRINTF ("%s: Launching the ACEX1K Reader...\n",
+					__FUNCTION__);
+			ret_val = ACEX1K_dump (desc, buf, bsize);
+#else
+			printf ("%s: No support for ACEX1K devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+
+#if defined(CONFIG_FPGA_STRATIX_II)
+		case Altera_StratixII:
+			PRINTF ("%s: Launching the Stratix II Reader...\n",
+				__FUNCTION__);
+			ret_val = StratixII_dump (desc, buf, bsize);
+			break;
+#endif
+		default:
+			printf ("%s: Unsupported family type, %d\n",
+					__FUNCTION__, desc->family);
+		}
+	}
+
+	return ret_val;
+}
+
+int altera_info( Altera_desc *desc )
+{
+	int ret_val = FPGA_FAIL;
+
+	if (altera_validate (desc, (char *)__FUNCTION__)) {
+		printf ("Family:        \t");
+		switch (desc->family) {
+		case Altera_ACEX1K:
+			printf ("ACEX1K\n");
+			break;
+		case Altera_CYC2:
+			printf ("CYCLON II\n");
+			break;
+		case Altera_StratixII:
+			printf ("Stratix II\n");
+			break;
+			/* Add new family types here */
+		default:
+			printf ("Unknown family type, %d\n", desc->family);
+		}
+
+		printf ("Interface type:\t");
+		switch (desc->iface) {
+		case passive_serial:
+			printf ("Passive Serial (PS)\n");
+			break;
+		case passive_parallel_synchronous:
+			printf ("Passive Parallel Synchronous (PPS)\n");
+			break;
+		case passive_parallel_asynchronous:
+			printf ("Passive Parallel Asynchronous (PPA)\n");
+			break;
+		case passive_serial_asynchronous:
+			printf ("Passive Serial Asynchronous (PSA)\n");
+			break;
+		case altera_jtag_mode:		/* Not used */
+			printf ("JTAG Mode\n");
+			break;
+		case fast_passive_parallel:
+			printf ("Fast Passive Parallel (FPP)\n");
+			break;
+		case fast_passive_parallel_security:
+			printf
+			    ("Fast Passive Parallel with Security (FPPS) \n");
+			break;
+			/* Add new interface types here */
+		default:
+			printf ("Unsupported interface type, %d\n", desc->iface);
+		}
+
+		printf ("Device Size:   \t%d bytes\n"
+				"Cookie:        \t0x%x (%d)\n",
+				desc->size, desc->cookie, desc->cookie);
+
+		if (desc->iface_fns) {
+			printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
+			switch (desc->family) {
+			case Altera_ACEX1K:
+			case Altera_CYC2:
+#if defined(CONFIG_FPGA_ACEX1K)
+				ACEX1K_info (desc);
+#elif defined(CONFIG_FPGA_CYCLON2)
+				CYC2_info (desc);
+#else
+				/* just in case */
+				printf ("%s: No support for ACEX1K devices.\n",
+						__FUNCTION__);
+#endif
+				break;
+#if defined(CONFIG_FPGA_STRATIX_II)
+			case Altera_StratixII:
+				StratixII_info (desc);
+				break;
+#endif
+				/* Add new family types here */
+			default:
+				/* we don't need a message here - we give one up above */
+				break;
+			}
+		} else {
+			printf ("No Device Function Table.\n");
+		}
+
+		ret_val = FPGA_SUCCESS;
+	} else {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int altera_validate (Altera_desc * desc, const char *fn)
+{
+	int ret_val = false;
+
+	if (desc) {
+		if ((desc->family > min_altera_type) &&
+			(desc->family < max_altera_type)) {
+			if ((desc->iface > min_altera_iface_type) &&
+				(desc->iface < max_altera_iface_type)) {
+				if (desc->size) {
+					ret_val = true;
+				} else {
+					printf ("%s: NULL part size\n", fn);
+				}
+			} else {
+				printf ("%s: Invalid Interface type, %d\n",
+					fn, desc->iface);
+			}
+		} else {
+			printf ("%s: Invalid family type, %d\n", fn, desc->family);
+		}
+	} else {
+		printf ("%s: NULL descriptor!\n", fn);
+	}
+
+	return ret_val;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/marvell/uboot/drivers/fpga/cyclon2.c b/marvell/uboot/drivers/fpga/cyclon2.c
new file mode 100644
index 0000000..8ab7679
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/cyclon2.c
@@ -0,0 +1,205 @@
+/*
+ * (C) Copyright 2006
+ * Heiko Schocher, hs@denx.de
+ * Based on ACE1XK.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>		/* core U-Boot definitions */
+#include <altera.h>
+#include <ACEX1K.h>		/* ACEX device family */
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef	FPGA_DEBUG
+#define PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Note: The assumption is that we cannot possibly run fast enough to
+ * overrun the device (the Slave Parallel mode can free run at 50MHz).
+ * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
+ * the board config file to slow things down.
+ */
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CONFIG_SYS_FPGA_WAIT
+#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10		/* 100 ms */
+#endif
+
+static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
+static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
+/* static int CYC2_ps_info( Altera_desc *desc ); */
+
+/* ------------------------------------------------------------------------- */
+/* CYCLON2 Generic Implementation */
+int CYC2_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+		PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
+		ret_val = CYC2_ps_load (desc, buf, bsize);
+		break;
+
+	case fast_passive_parallel:
+		/* Fast Passive Parallel (FPP) and PS only differ in what is
+		 * done in the write() callback. Use the existing PS load
+		 * function for FPP, too.
+		 */
+		PRINTF ("%s: Launching Fast Passive Parallel Loader\n",
+		      __FUNCTION__);
+		ret_val = CYC2_ps_load(desc, buf, bsize);
+		break;
+
+		/* Add new interface types here */
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int CYC2_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+		PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
+		ret_val = CYC2_ps_dump (desc, buf, bsize);
+		break;
+
+		/* Add new interface types here */
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int CYC2_info( Altera_desc *desc )
+{
+	return FPGA_SUCCESS;
+}
+
+/* ------------------------------------------------------------------------- */
+/* CYCLON2 Passive Serial Generic Implementation                                  */
+static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
+	int	ret = 0;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"config:\t0x%p\n"
+				"status:\t0x%p\n"
+				"write:\t0x%p\n"
+				"done:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->config, fn->status,
+				fn->write, fn->done);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...", cookie);
+#endif
+
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->config) (false, true, cookie);	/* De-assert nCONFIG */
+		udelay(100);
+		(*fn->config) (true, true, cookie);	/* Assert nCONFIG */
+
+		udelay(2);		/* T_cfg > 2us	*/
+
+		/* Wait for nSTATUS to be asserted */
+		ts = get_timer (0);		/* get current time */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for STATUS to go high.\n");
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+		} while (!(*fn->status) (cookie));
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+
+		ret = (*fn->write) (buf, bsize, true, cookie);
+		if (ret) {
+			puts ("** Write failed.\n");
+			(*fn->abort) (cookie);
+			return FPGA_FAIL;
+		}
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		puts(" OK? ...");
+#endif
+
+		CONFIG_FPGA_DELAY ();
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc (' ');			/* terminate the dotted line */
+#endif
+
+	/*
+	 * Checking FPGA's CONF_DONE signal - correctly booted ?
+	 */
+
+	if ( ! (*fn->done) (cookie) ) {
+		puts ("** Booting failed! CONF_DONE is still deasserted.\n");
+		(*fn->abort) (cookie);
+		return (FPGA_FAIL);
+	}
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+	puts(" OK\n");
+#endif
+
+	ret_val = FPGA_SUCCESS;
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+	if (ret_val == FPGA_SUCCESS) {
+		puts ("Done.\n");
+	}
+	else {
+		puts ("Fail.\n");
+	}
+#endif
+	(*fn->post) (cookie);
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+	/* Readback is only available through the Slave Parallel and         */
+	/* boundary-scan interfaces.                                         */
+	printf ("%s: Passive Serial Dumping is unavailable\n",
+			__FUNCTION__);
+	return FPGA_FAIL;
+}
diff --git a/marvell/uboot/drivers/fpga/fpga.c b/marvell/uboot/drivers/fpga/fpga.c
new file mode 100644
index 0000000..b940d9b
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/fpga.c
@@ -0,0 +1,287 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* Generic FPGA support */
+#include <common.h>             /* core U-Boot definitions */
+#include <xilinx.h>             /* xilinx specific definitions */
+#include <altera.h>             /* altera specific definitions */
+#include <lattice.h>
+
+/* Local definitions */
+#ifndef CONFIG_MAX_FPGA_DEVICES
+#define CONFIG_MAX_FPGA_DEVICES		5
+#endif
+
+/* Local static data */
+static int next_desc = FPGA_INVALID_DEVICE;
+static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
+
+/*
+ * fpga_no_sup
+ * 'no support' message function
+ */
+static void fpga_no_sup(char *fn, char *msg)
+{
+	if (fn && msg)
+		printf("%s: No support for %s.\n", fn, msg);
+	else if (msg)
+		printf("No support for %s.\n", msg);
+	else
+		printf("No FPGA suport!\n");
+}
+
+
+/* fpga_get_desc
+ *	map a device number to a descriptor
+ */
+static const fpga_desc *const fpga_get_desc(int devnum)
+{
+	fpga_desc *desc = (fpga_desc *)NULL;
+
+	if ((devnum >= 0) && (devnum < next_desc)) {
+		desc = &desc_table[devnum];
+		debug("%s: found fpga descriptor #%d @ 0x%p\n",
+		      __func__, devnum, desc);
+	}
+
+	return desc;
+}
+
+/*
+ * fpga_validate
+ *	generic parameter checking code
+ */
+const fpga_desc *const fpga_validate(int devnum, const void *buf,
+				     size_t bsize, char *fn)
+{
+	const fpga_desc *desc = fpga_get_desc(devnum);
+
+	if (!desc)
+		printf("%s: Invalid device number %d\n", fn, devnum);
+
+	if (!buf) {
+		printf("%s: Null buffer.\n", fn);
+		return (fpga_desc * const)NULL;
+	}
+	return desc;
+}
+
+/*
+ * fpga_dev_info
+ *	generic multiplexing code
+ */
+static int fpga_dev_info(int devnum)
+{
+	int ret_val = FPGA_FAIL; /* assume failure */
+	const fpga_desc * const desc = fpga_get_desc(devnum);
+
+	if (desc) {
+		debug("%s: Device Descriptor @ 0x%p\n",
+		      __func__, desc->devdesc);
+
+		switch (desc->devtype) {
+		case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+			printf("Xilinx Device\nDescriptor @ 0x%p\n", desc);
+			ret_val = xilinx_info(desc->devdesc);
+#else
+			fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+			break;
+		case fpga_altera:
+#if defined(CONFIG_FPGA_ALTERA)
+			printf("Altera Device\nDescriptor @ 0x%p\n", desc);
+			ret_val = altera_info(desc->devdesc);
+#else
+			fpga_no_sup((char *)__func__, "Altera devices");
+#endif
+			break;
+		case fpga_lattice:
+#if defined(CONFIG_FPGA_LATTICE)
+			printf("Lattice Device\nDescriptor @ 0x%p\n", desc);
+			ret_val = lattice_info(desc->devdesc);
+#else
+			fpga_no_sup((char *)__func__, "Lattice devices");
+#endif
+			break;
+		default:
+			printf("%s: Invalid or unsupported device type %d\n",
+			       __func__, desc->devtype);
+		}
+	} else {
+		printf("%s: Invalid device number %d\n", __func__, devnum);
+	}
+
+	return ret_val;
+}
+
+/*
+ * fgpa_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)
+{
+	next_desc = 0;
+	memset(desc_table, 0, sizeof(desc_table));
+
+	debug("%s\n", __func__);
+}
+
+/*
+ * fpga_count
+ * Basic interface function to get the current number of devices available.
+ */
+int fpga_count(void)
+{
+	return next_desc;
+}
+
+/*
+ * fpga_add
+ *	Add the device descriptor to the device table.
+ */
+int fpga_add(fpga_type devtype, void *desc)
+{
+	int devnum = FPGA_INVALID_DEVICE;
+
+	if (next_desc < 0) {
+		printf("%s: FPGA support not initialized!\n", __func__);
+	} else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) {
+		if (desc) {
+			if (next_desc < CONFIG_MAX_FPGA_DEVICES) {
+				devnum = next_desc;
+				desc_table[next_desc].devtype = devtype;
+				desc_table[next_desc++].devdesc = desc;
+			} else {
+				printf("%s: Exceeded Max FPGA device count\n",
+				       __func__);
+			}
+		} else {
+			printf("%s: NULL device descriptor\n", __func__);
+		}
+	} else {
+		printf("%s: Unsupported FPGA type %d\n", __func__, devtype);
+	}
+
+	return devnum;
+}
+
+/*
+ * Convert bitstream data and load into the fpga
+ */
+int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size)
+{
+	printf("Bitstream support not implemented for this FPGA device\n");
+	return FPGA_FAIL;
+}
+
+/*
+ * Generic multiplexing code
+ */
+int fpga_load(int devnum, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;           /* assume failure */
+	const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
+					      (char *)__func__);
+
+	if (desc) {
+		switch (desc->devtype) {
+		case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+			ret_val = xilinx_load(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+			break;
+		case fpga_altera:
+#if defined(CONFIG_FPGA_ALTERA)
+			ret_val = altera_load(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Altera devices");
+#endif
+			break;
+		case fpga_lattice:
+#if defined(CONFIG_FPGA_LATTICE)
+			ret_val = lattice_load(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Lattice devices");
+#endif
+			break;
+		default:
+			printf("%s: Invalid or unsupported device type %d\n",
+			       __func__, desc->devtype);
+		}
+	}
+
+	return ret_val;
+}
+
+/*
+ * fpga_dump
+ *	generic multiplexing code
+ */
+int fpga_dump(int devnum, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;           /* assume failure */
+	const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
+					      (char *)__func__);
+
+	if (desc) {
+		switch (desc->devtype) {
+		case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+			ret_val = xilinx_dump(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+			break;
+		case fpga_altera:
+#if defined(CONFIG_FPGA_ALTERA)
+			ret_val = altera_dump(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Altera devices");
+#endif
+			break;
+		case fpga_lattice:
+#if defined(CONFIG_FPGA_LATTICE)
+			ret_val = lattice_dump(desc->devdesc, buf, bsize);
+#else
+			fpga_no_sup((char *)__func__, "Lattice devices");
+#endif
+			break;
+		default:
+			printf("%s: Invalid or unsupported device type %d\n",
+			       __func__, desc->devtype);
+		}
+	}
+
+	return ret_val;
+}
+
+/*
+ * fpga_info
+ *	front end to fpga_dev_info.  If devnum is invalid, report on all
+ *	available devices.
+ */
+int fpga_info(int devnum)
+{
+	if (devnum == FPGA_INVALID_DEVICE) {
+		if (next_desc > 0) {
+			int dev;
+
+			for (dev = 0; dev < next_desc; dev++)
+				fpga_dev_info(dev);
+
+			return FPGA_SUCCESS;
+		} else {
+			printf("%s: No FPGA devices available.\n", __func__);
+			return FPGA_FAIL;
+		}
+	}
+
+	return fpga_dev_info(devnum);
+}
diff --git a/marvell/uboot/drivers/fpga/ivm_core.c b/marvell/uboot/drivers/fpga/ivm_core.c
new file mode 100644
index 0000000..03aea62
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/ivm_core.c
@@ -0,0 +1,3149 @@
+/*
+ * Porting to u-boot:
+ *
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * Lattice ispVME Embedded code to load Lattice's FPGA:
+ *
+ * Copyright 2009 Lattice Semiconductor Corp.
+ *
+ * ispVME Embedded allows programming of Lattice's suite of FPGA
+ * devices on embedded systems through the JTAG port.  The software
+ * is distributed in source code form and is open to re - distribution
+ * and modification where applicable.
+ *
+ * Revision History of ivm_core.c module:
+ * 4/25/06 ht   Change some variables from unsigned short or int
+ *              to long int to make the code compiler independent.
+ * 5/24/06 ht   Support using RESET (TRST) pin as a special purpose
+ *              control pin such as triggering the loading of known
+ *              state exit.
+ * 3/6/07 ht added functions to support output to terminals
+ *
+ * 09/11/07 NN Type cast mismatch variables
+ *		   Moved the sclock() function to hardware.c
+ * 08/28/08 NN Added Calculate checksum support.
+ * 4/1/09 Nguyen replaced the recursive function call codes on
+ *        the ispVMLCOUNT function
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/string.h>
+#include <malloc.h>
+#include <lattice.h>
+
+#define vme_out_char(c)	printf("%c", c)
+#define vme_out_hex(c)	printf("%x", c)
+#define vme_out_string(s) printf("%s", s)
+
+/*
+ *
+ * Global variables used to specify the flow control and data type.
+ *
+ *	g_usFlowControl:	flow control register. Each bit in the
+ *                               register can potentially change the
+ *                               personality of the embedded engine.
+ *	g_usDataType:		holds the data type of the current row.
+ *
+ */
+
+static unsigned short g_usFlowControl;
+unsigned short g_usDataType;
+
+/*
+ *
+ * Global variables used to specify the ENDDR and ENDIR.
+ *
+ *	g_ucEndDR:		the state that the device goes to after SDR.
+ *	g_ucEndIR:		the state that the device goes to after SIR.
+ *
+ */
+
+unsigned char g_ucEndDR = DRPAUSE;
+unsigned char g_ucEndIR = IRPAUSE;
+
+/*
+ *
+ * Global variables used to support header/trailer.
+ *
+ *	g_usHeadDR:		the number of lead devices in bypass.
+ *	g_usHeadIR:		the sum of IR length of lead devices.
+ *	g_usTailDR:		the number of tail devices in bypass.
+ *	g_usTailIR:		the sum of IR length of tail devices.
+ *
+ */
+
+static unsigned short g_usHeadDR;
+static unsigned short g_usHeadIR;
+static unsigned short g_usTailDR;
+static unsigned short g_usTailIR;
+
+/*
+ *
+ * Global variable to store the number of bits of data or instruction
+ * to be shifted into or out from the device.
+ *
+ */
+
+static unsigned short g_usiDataSize;
+
+/*
+ *
+ * Stores the frequency. Default to 1 MHz.
+ *
+ */
+
+static int g_iFrequency = 1000;
+
+/*
+ *
+ * Stores the maximum amount of ram needed to hold a row of data.
+ *
+ */
+
+static unsigned short g_usMaxSize;
+
+/*
+ *
+ * Stores the LSH or RSH value.
+ *
+ */
+
+static unsigned short g_usShiftValue;
+
+/*
+ *
+ * Stores the current repeat loop value.
+ *
+ */
+
+static unsigned short g_usRepeatLoops;
+
+/*
+ *
+ * Stores the current vendor.
+ *
+ */
+
+static signed char g_cVendor = LATTICE;
+
+/*
+ *
+ * Stores the VME file CRC.
+ *
+ */
+
+unsigned short g_usCalculatedCRC;
+
+/*
+ *
+ * Stores the Device Checksum.
+ *
+ */
+/* 08/28/08 NN Added Calculate checksum support. */
+unsigned long g_usChecksum;
+static unsigned int g_uiChecksumIndex;
+
+/*
+ *
+ * Stores the current state of the JTAG state machine.
+ *
+ */
+
+static signed char g_cCurrentJTAGState;
+
+/*
+ *
+ * Global variables used to support looping.
+ *
+ *	g_pucHeapMemory:	holds the entire repeat loop.
+ *	g_iHeapCounter:		points to the current byte in the repeat loop.
+ *	g_iHEAPSize:		the current size of the repeat in bytes.
+ *
+ */
+
+unsigned char *g_pucHeapMemory;
+unsigned short g_iHeapCounter;
+unsigned short g_iHEAPSize;
+static unsigned short previous_size;
+
+/*
+ *
+ * Global variables used to support intelligent programming.
+ *
+ *	g_usIntelDataIndex:     points to the current byte of the
+ *                               intelligent buffer.
+ *	g_usIntelBufferSize:	holds the size of the intelligent
+ *                               buffer.
+ *
+ */
+
+unsigned short g_usIntelDataIndex;
+unsigned short g_usIntelBufferSize;
+
+/*
+ *
+ * Supported VME versions.
+ *
+ */
+
+const char *const g_szSupportedVersions[] = {
+	"__VME2.0", "__VME3.0", "____12.0", "____12.1", 0};
+
+/*
+ *
+ * Holds the maximum size of each respective buffer. These variables are used
+ * to write the HEX files when converting VME to HEX.
+ *
+*/
+
+static unsigned short g_usTDOSize;
+static unsigned short g_usMASKSize;
+static unsigned short g_usTDISize;
+static unsigned short g_usDMASKSize;
+static unsigned short g_usLCOUNTSize;
+static unsigned short g_usHDRSize;
+static unsigned short g_usTDRSize;
+static unsigned short g_usHIRSize;
+static unsigned short g_usTIRSize;
+static unsigned short g_usHeapSize;
+
+/*
+ *
+ * Global variables used to store data.
+ *
+ *	g_pucOutMaskData:	local RAM to hold one row of MASK data.
+ *	g_pucInData:		local RAM to hold one row of TDI data.
+ *	g_pucOutData:		local RAM to hold one row of TDO data.
+ *	g_pucHIRData:		local RAM to hold the current SIR header.
+ *	g_pucTIRData:		local RAM to hold the current SIR trailer.
+ *	g_pucHDRData:		local RAM to hold the current SDR header.
+ *	g_pucTDRData:		local RAM to hold the current SDR trailer.
+ *	g_pucIntelBuffer:	local RAM to hold the current intelligent buffer
+ *	g_pucOutDMaskData:	local RAM to hold one row of DMASK data.
+ *
+ */
+
+unsigned char	*g_pucOutMaskData	= NULL,
+		*g_pucInData		= NULL,
+		*g_pucOutData		= NULL,
+		*g_pucHIRData		= NULL,
+		*g_pucTIRData		= NULL,
+		*g_pucHDRData		= NULL,
+		*g_pucTDRData		= NULL,
+		*g_pucIntelBuffer	= NULL,
+		*g_pucOutDMaskData	= NULL;
+
+/*
+ *
+ * JTAG state machine transition table.
+ *
+ */
+
+struct {
+	 unsigned char  CurState;  /* From this state */
+	 unsigned char  NextState; /* Step to this state */
+	 unsigned char  Pattern;   /* The tragetory of TMS */
+	 unsigned char  Pulses;    /* The number of steps */
+} g_JTAGTransistions[25] = {
+{ RESET,	RESET,		0xFC, 6 },	/* Transitions from RESET */
+{ RESET,	IDLE,		0x00, 1 },
+{ RESET,	DRPAUSE,	0x50, 5 },
+{ RESET,	IRPAUSE,	0x68, 6 },
+{ IDLE,		RESET,		0xE0, 3 },	/* Transitions from IDLE */
+{ IDLE,		DRPAUSE,	0xA0, 4 },
+{ IDLE,		IRPAUSE,	0xD0, 5 },
+{ DRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from DRPAUSE */
+{ DRPAUSE,	IDLE,		0xC0, 3 },
+{ DRPAUSE,	IRPAUSE,	0xF4, 7 },
+{ DRPAUSE,	DRPAUSE,	0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/
+{ IRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from IRPAUSE */
+{ IRPAUSE,	IDLE,		0xC0, 3 },
+{ IRPAUSE,	DRPAUSE,	0xE8, 6 },
+{ DRPAUSE,	SHIFTDR,	0x80, 2 }, /* Extra transitions using SHIFTDR */
+{ IRPAUSE,	SHIFTDR,	0xE0, 5 },
+{ SHIFTDR,	DRPAUSE,	0x80, 2 },
+{ SHIFTDR,	IDLE,		0xC0, 3 },
+{ IRPAUSE,	SHIFTIR,	0x80, 2 },/* Extra transitions using SHIFTIR */
+{ SHIFTIR,	IRPAUSE,	0x80, 2 },
+{ SHIFTIR,	IDLE,		0xC0, 3 },
+{ DRPAUSE,	DRCAPTURE,	0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
+{ DRCAPTURE, DRPAUSE,	0x80, 2 },
+{ IDLE,     DRCAPTURE,	0x80, 2 },
+{ IRPAUSE,  DRCAPTURE,  0xE0, 4 }
+};
+
+/*
+ *
+ * List to hold all LVDS pairs.
+ *
+ */
+
+LVDSPair *g_pLVDSList;
+unsigned short g_usLVDSPairCount;
+
+/*
+ *
+ * Function prototypes.
+ *
+ */
+
+static signed char ispVMDataCode(void);
+static long int ispVMDataSize(void);
+static void ispVMData(unsigned char *Data);
+static signed char ispVMShift(signed char Code);
+static signed char ispVMAmble(signed char Code);
+static signed char ispVMLoop(unsigned short a_usLoopCount);
+static signed char ispVMBitShift(signed char mode, unsigned short bits);
+static void ispVMComment(unsigned short a_usCommentSize);
+static void ispVMHeader(unsigned short a_usHeaderSize);
+static signed char ispVMLCOUNT(unsigned short a_usCountSize);
+static void ispVMClocks(unsigned short Clocks);
+static void ispVMBypass(signed char ScanType, unsigned short Bits);
+static void ispVMStateMachine(signed char NextState);
+static signed char ispVMSend(unsigned short int);
+static signed char ispVMRead(unsigned short int);
+static signed char ispVMReadandSave(unsigned short int);
+static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount);
+static void ispVMMemManager(signed char types, unsigned short size);
+
+/*
+ *
+ * External variables and functions in hardware.c module
+ *
+ */
+static signed char g_cCurrentJTAGState;
+
+#ifdef DEBUG
+
+/*
+ *
+ * GetState
+ *
+ * Returns the state as a string based on the opcode. Only used
+ * for debugging purposes.
+ *
+ */
+
+const char *GetState(unsigned char a_ucState)
+{
+	switch (a_ucState) {
+	case RESET:
+		return "RESET";
+	case IDLE:
+		return "IDLE";
+	case IRPAUSE:
+		return "IRPAUSE";
+	case DRPAUSE:
+		return "DRPAUSE";
+	case SHIFTIR:
+		return "SHIFTIR";
+	case SHIFTDR:
+		return "SHIFTDR";
+	case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/
+		return "DRCAPTURE";
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * PrintData
+ *
+ * Prints the data. Only used for debugging purposes.
+ *
+ */
+
+void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short usByteSize  = 0;
+	unsigned short usBitIndex  = 0;
+	signed short usByteIndex   = 0;
+	unsigned char ucByte       = 0;
+	unsigned char ucFlipByte   = 0;
+
+	if (a_iDataSize % 8) {
+		/* 09/11/07 NN Type cast mismatch variables */
+		usByteSize = (unsigned short)(a_iDataSize / 8 + 1);
+	} else {
+		/* 09/11/07 NN Type cast mismatch variables */
+		usByteSize = (unsigned short)(a_iDataSize / 8);
+	}
+	puts("(");
+	/* 09/11/07 NN Type cast mismatch variables */
+	for (usByteIndex = (signed short)(usByteSize - 1);
+		usByteIndex >= 0; usByteIndex--) {
+		ucByte = a_pucData[usByteIndex];
+		ucFlipByte = 0x00;
+
+		/*
+		*
+		* Flip each byte.
+		*
+		*/
+
+		for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) {
+			ucFlipByte <<= 1;
+			if (ucByte & 0x1) {
+				ucFlipByte |= 0x1;
+			}
+
+			ucByte >>= 1;
+		}
+
+		/*
+		*
+		* Print the flipped byte.
+		*
+		*/
+
+		printf("%.02X", ucFlipByte);
+		if ((usByteSize - usByteIndex) % 40 == 39) {
+			puts("\n\t\t");
+		}
+		if (usByteIndex < 0)
+			break;
+	}
+	puts(")");
+}
+#endif /* DEBUG */
+
+void ispVMMemManager(signed char cTarget, unsigned short usSize)
+{
+	switch (cTarget) {
+	case XTDI:
+	case TDI:
+		if (g_pucInData != NULL) {
+			if (previous_size == usSize) {/*memory exist*/
+				break;
+			} else {
+				free(g_pucInData);
+				g_pucInData = NULL;
+			}
+		}
+		g_pucInData = (unsigned char *) malloc(usSize / 8 + 2);
+		previous_size = usSize;
+	case XTDO:
+	case TDO:
+		if (g_pucOutData != NULL) {
+			if (previous_size == usSize) { /*already exist*/
+				break;
+			} else {
+				free(g_pucOutData);
+				g_pucOutData = NULL;
+			}
+		}
+		g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2);
+		previous_size = usSize;
+		break;
+	case MASK:
+		if (g_pucOutMaskData != NULL) {
+			if (previous_size == usSize) {/*already allocated*/
+				break;
+			} else {
+				free(g_pucOutMaskData);
+				g_pucOutMaskData = NULL;
+			}
+		}
+		g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2);
+		previous_size = usSize;
+		break;
+	case HIR:
+		if (g_pucHIRData != NULL) {
+			free(g_pucHIRData);
+			g_pucHIRData = NULL;
+		}
+		g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2);
+		break;
+	case TIR:
+		if (g_pucTIRData != NULL) {
+			free(g_pucTIRData);
+			g_pucTIRData = NULL;
+		}
+		g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2);
+		break;
+	case HDR:
+		if (g_pucHDRData != NULL) {
+			free(g_pucHDRData);
+			g_pucHDRData = NULL;
+		}
+		g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2);
+		break;
+	case TDR:
+		if (g_pucTDRData != NULL) {
+			free(g_pucTDRData);
+			g_pucTDRData = NULL;
+		}
+		g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2);
+		break;
+	case HEAP:
+		if (g_pucHeapMemory != NULL) {
+			free(g_pucHeapMemory);
+			g_pucHeapMemory = NULL;
+		}
+		g_pucHeapMemory = (unsigned char *) malloc(usSize + 2);
+		break;
+	case DMASK:
+		if (g_pucOutDMaskData != NULL) {
+			if (previous_size == usSize) { /*already allocated*/
+				break;
+			} else {
+				free(g_pucOutDMaskData);
+				g_pucOutDMaskData = NULL;
+			}
+		}
+		g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2);
+		previous_size = usSize;
+		break;
+	case LHEAP:
+		if (g_pucIntelBuffer != NULL) {
+			free(g_pucIntelBuffer);
+			g_pucIntelBuffer = NULL;
+		}
+		g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2);
+		break;
+	case LVDS:
+		if (g_pLVDSList != NULL) {
+			free(g_pLVDSList);
+			g_pLVDSList = NULL;
+		}
+		g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair));
+		if (g_pLVDSList)
+			memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair));
+		break;
+	default:
+		return;
+    }
+}
+
+void ispVMFreeMem(void)
+{
+	if (g_pucHeapMemory != NULL) {
+		free(g_pucHeapMemory);
+		g_pucHeapMemory = NULL;
+	}
+
+	if (g_pucOutMaskData != NULL) {
+		free(g_pucOutMaskData);
+		g_pucOutMaskData = NULL;
+	}
+
+	if (g_pucInData != NULL) {
+		free(g_pucInData);
+		g_pucInData = NULL;
+	}
+
+	if (g_pucOutData != NULL) {
+		free(g_pucOutData);
+		g_pucOutData = NULL;
+	}
+
+	if (g_pucHIRData != NULL) {
+		free(g_pucHIRData);
+		g_pucHIRData = NULL;
+	}
+
+	if (g_pucTIRData != NULL) {
+		free(g_pucTIRData);
+		g_pucTIRData = NULL;
+	}
+
+	if (g_pucHDRData != NULL) {
+		free(g_pucHDRData);
+		g_pucHDRData = NULL;
+	}
+
+	if (g_pucTDRData != NULL) {
+		free(g_pucTDRData);
+		g_pucTDRData = NULL;
+	}
+
+	if (g_pucOutDMaskData != NULL) {
+		free(g_pucOutDMaskData);
+		g_pucOutDMaskData = NULL;
+	}
+
+	if (g_pucIntelBuffer != NULL) {
+		free(g_pucIntelBuffer);
+		g_pucIntelBuffer = NULL;
+	}
+
+	if (g_pLVDSList != NULL) {
+		free(g_pLVDSList);
+		g_pLVDSList = NULL;
+	}
+}
+
+
+/*
+ *
+ * ispVMDataSize
+ *
+ * Returns a VME-encoded number, usually used to indicate the
+ * bit length of an SIR/SDR command.
+ *
+ */
+
+long int ispVMDataSize()
+{
+	/* 09/11/07 NN added local variables initialization */
+	long int iSize           = 0;
+	signed char cCurrentByte = 0;
+	signed char cIndex       = 0;
+	cIndex = 0;
+	while ((cCurrentByte = GetByte()) & 0x80) {
+		iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
+		cIndex += 7;
+	}
+	iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
+	return iSize;
+}
+
+/*
+ *
+ * ispVMCode
+ *
+ * This is the heart of the embedded engine. All the high-level opcodes
+ * are extracted here. Once they have been identified, then it
+ * will call other functions to handle the processing.
+ *
+ */
+
+signed char ispVMCode()
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short iRepeatSize = 0;
+	signed char cOpcode	   = 0;
+	signed char cRetCode       = 0;
+	unsigned char ucState      = 0;
+	unsigned short usDelay     = 0;
+	unsigned short usToggle    = 0;
+	unsigned char usByte       = 0;
+
+	/*
+	*
+	* Check the compression flag only if this is the first time
+	* this function is entered. Do not check the compression flag if
+	* it is being called recursively from other functions within
+	* the embedded engine.
+	*
+	*/
+
+	if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) {
+		usByte = GetByte();
+		if (usByte == 0xf1) {
+			g_usDataType |= COMPRESS;
+		} else if (usByte == 0xf2) {
+			g_usDataType &= ~COMPRESS;
+		} else {
+			return VME_INVALID_FILE;
+		}
+	}
+
+	/*
+	*
+	* Begin looping through all the VME opcodes.
+	*
+	*/
+
+	while ((cOpcode = GetByte()) >= 0) {
+
+		switch (cOpcode) {
+		case STATE:
+
+			/*
+			 * Step the JTAG state machine.
+			 */
+
+			ucState = GetByte();
+
+			/*
+			 * Step the JTAG state machine to DRCAPTURE
+			 * to support Looping.
+			 */
+
+			if ((g_usDataType & LHEAP_IN) &&
+				 (ucState == DRPAUSE) &&
+				 (g_cCurrentJTAGState == ucState)) {
+				ispVMStateMachine(DRCAPTURE);
+			}
+
+			ispVMStateMachine(ucState);
+
+#ifdef DEBUG
+			if (g_usDataType & LHEAP_IN) {
+				debug("LDELAY %s ", GetState(ucState));
+			} else {
+				debug("STATE %s;\n", GetState(ucState));
+			}
+#endif /* DEBUG */
+			break;
+		case SIR:
+		case SDR:
+		case XSDR:
+
+#ifdef DEBUG
+			switch (cOpcode) {
+			case SIR:
+				puts("SIR ");
+				break;
+			case SDR:
+			case XSDR:
+				if (g_usDataType & LHEAP_IN) {
+					puts("LSDR ");
+				} else {
+					puts("SDR ");
+				}
+				break;
+			}
+#endif /* DEBUG */
+			/*
+			*
+			* Shift in data into the device.
+			*
+			*/
+
+			cRetCode = ispVMShift(cOpcode);
+			if (cRetCode != 0) {
+				return cRetCode;
+			}
+			break;
+		case WAIT:
+
+			/*
+			*
+			* Observe delay.
+			*
+			*/
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			usDelay = (unsigned short) ispVMDataSize();
+			ispVMDelay(usDelay);
+
+#ifdef DEBUG
+			if (usDelay & 0x8000) {
+
+				/*
+				 * Since MSB is set, the delay time must be
+				 * decoded to millisecond. The SVF2VME encodes
+				 * the MSB to represent millisecond.
+				 */
+
+				usDelay &= ~0x8000;
+				if (g_usDataType & LHEAP_IN) {
+					printf("%.2E SEC;\n",
+						(float) usDelay / 1000);
+				} else {
+					printf("RUNTEST %.2E SEC;\n",
+						(float) usDelay / 1000);
+				}
+			} else {
+				/*
+				 * Since MSB is not set, the delay time
+				 * is given as microseconds.
+				 */
+
+				if (g_usDataType & LHEAP_IN) {
+					printf("%.2E SEC;\n",
+						(float) usDelay / 1000000);
+				} else {
+					printf("RUNTEST %.2E SEC;\n",
+						(float) usDelay / 1000000);
+				}
+			}
+#endif /* DEBUG */
+			break;
+		case TCK:
+
+			/*
+			 * Issue clock toggles.
+			*/
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			usToggle = (unsigned short) ispVMDataSize();
+			ispVMClocks(usToggle);
+
+#ifdef DEBUG
+			printf("RUNTEST %d TCK;\n", usToggle);
+#endif /* DEBUG */
+			break;
+		case ENDDR:
+
+			/*
+			*
+			* Set the ENDDR.
+			*
+			*/
+
+			g_ucEndDR = GetByte();
+
+#ifdef DEBUG
+			printf("ENDDR %s;\n", GetState(g_ucEndDR));
+#endif /* DEBUG */
+			break;
+		case ENDIR:
+
+			/*
+			*
+			* Set the ENDIR.
+			*
+			*/
+
+			g_ucEndIR = GetByte();
+
+#ifdef DEBUG
+			printf("ENDIR %s;\n", GetState(g_ucEndIR));
+#endif /* DEBUG */
+			break;
+		case HIR:
+		case TIR:
+		case HDR:
+		case TDR:
+
+#ifdef DEBUG
+			switch (cOpcode) {
+			case HIR:
+				puts("HIR ");
+				break;
+			case TIR:
+				puts("TIR ");
+				break;
+			case HDR:
+				puts("HDR ");
+				break;
+			case TDR:
+				puts("TDR ");
+				break;
+			}
+#endif /* DEBUG */
+			/*
+			 * Set the header/trailer of the device in order
+			 * to bypass
+			 * successfully.
+			 */
+
+			cRetCode = ispVMAmble(cOpcode);
+			if (cRetCode != 0) {
+				return cRetCode;
+			}
+
+#ifdef DEBUG
+			puts(";\n");
+#endif /* DEBUG */
+			break;
+		case MEM:
+
+			/*
+			 * The maximum RAM required to support
+			 * processing one row of the VME file.
+			 */
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_usMaxSize = (unsigned short) ispVMDataSize();
+
+#ifdef DEBUG
+			printf("// MEMSIZE %d\n", g_usMaxSize);
+#endif /* DEBUG */
+			break;
+		case VENDOR:
+
+			/*
+			*
+			* Set the VENDOR type.
+			*
+			*/
+
+			cOpcode = GetByte();
+			switch (cOpcode) {
+			case LATTICE:
+#ifdef DEBUG
+				puts("// VENDOR LATTICE\n");
+#endif /* DEBUG */
+				g_cVendor = LATTICE;
+				break;
+			case ALTERA:
+#ifdef DEBUG
+				puts("// VENDOR ALTERA\n");
+#endif /* DEBUG */
+				g_cVendor = ALTERA;
+				break;
+			case XILINX:
+#ifdef DEBUG
+				puts("// VENDOR XILINX\n");
+#endif /* DEBUG */
+				g_cVendor = XILINX;
+				break;
+			default:
+				break;
+			}
+			break;
+		case SETFLOW:
+
+			/*
+			 * Set the flow control. Flow control determines
+			 * the personality of the embedded engine.
+			 */
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_usFlowControl |= (unsigned short) ispVMDataSize();
+			break;
+		case RESETFLOW:
+
+			/*
+			*
+			* Unset the flow control.
+			*
+			*/
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_usFlowControl &= (unsigned short) ~(ispVMDataSize());
+			break;
+		case HEAP:
+
+			/*
+			*
+			* Allocate heap size to store loops.
+			*
+			*/
+
+			cRetCode = GetByte();
+			if (cRetCode != SECUREHEAP) {
+				return VME_INVALID_FILE;
+			}
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_iHEAPSize = (unsigned short) ispVMDataSize();
+
+			/*
+			 * Store the maximum size of the HEAP buffer.
+			 * Used to convert VME to HEX.
+			 */
+
+			if (g_iHEAPSize > g_usHeapSize) {
+				g_usHeapSize = g_iHEAPSize;
+			}
+
+			ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize);
+			break;
+		case REPEAT:
+
+			/*
+			*
+			* Execute loops.
+			*
+			*/
+
+			g_usRepeatLoops = 0;
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			iRepeatSize = (unsigned short) ispVMDataSize();
+
+			cRetCode = ispVMLoop((unsigned short) iRepeatSize);
+			if (cRetCode != 0) {
+				return cRetCode;
+			}
+			break;
+		case ENDLOOP:
+
+			/*
+			*
+			* Exit point from processing loops.
+			*
+			*/
+
+			return cRetCode;
+		case ENDVME:
+
+			/*
+			 * The only valid exit point that indicates
+			 * end of programming.
+			 */
+
+			return cRetCode;
+		case SHR:
+
+			/*
+			*
+			* Right-shift address.
+			*
+			*/
+
+			g_usFlowControl |= SHIFTRIGHT;
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
+				(unsigned short)GetByte());
+			break;
+		case SHL:
+
+			/*
+			 * Left-shift address.
+			 */
+
+			g_usFlowControl |= SHIFTLEFT;
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
+				(unsigned short)GetByte());
+			break;
+		case FREQUENCY:
+
+			/*
+			*
+			* Set the frequency.
+			*
+			*/
+
+			/* 09/11/07 NN Type cast mismatch variables */
+			g_iFrequency = (int) (ispVMDataSize() / 1000);
+			if (g_iFrequency == 1)
+				g_iFrequency = 1000;
+
+#ifdef DEBUG
+			printf("FREQUENCY %.2E HZ;\n",
+				(float) g_iFrequency * 1000);
+#endif /* DEBUG */
+			break;
+		case LCOUNT:
+
+			/*
+			*
+			* Process LCOUNT command.
+			*
+			*/
+
+			cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize());
+			if (cRetCode != 0) {
+				return cRetCode;
+			}
+			break;
+		case VUES:
+
+			/*
+			*
+			* Set the flow control to verify USERCODE.
+			*
+			*/
+
+			g_usFlowControl |= VERIFYUES;
+			break;
+		case COMMENT:
+
+			/*
+			*
+			* Display comment.
+			*
+			*/
+
+			ispVMComment((unsigned short) ispVMDataSize());
+			break;
+		case LVDS:
+
+			/*
+			*
+			* Process LVDS command.
+			*
+			*/
+
+			ispVMProcessLVDS((unsigned short) ispVMDataSize());
+			break;
+		case HEADER:
+
+			/*
+			*
+			* Discard header.
+			*
+			*/
+
+			ispVMHeader((unsigned short) ispVMDataSize());
+			break;
+		/* 03/14/06 Support Toggle ispENABLE signal*/
+		case ispEN:
+			ucState = GetByte();
+			if ((ucState == ON) || (ucState == 0x01))
+				writePort(g_ucPinENABLE, 0x01);
+			else
+				writePort(g_ucPinENABLE, 0x00);
+			ispVMDelay(1);
+			break;
+		/* 05/24/06 support Toggle TRST pin*/
+		case TRST:
+			ucState = GetByte();
+			if (ucState == 0x01)
+				writePort(g_ucPinTRST, 0x01);
+			else
+				writePort(g_ucPinTRST, 0x00);
+			ispVMDelay(1);
+			break;
+		default:
+
+			/*
+			*
+			* Invalid opcode encountered.
+			*
+			*/
+
+#ifdef DEBUG
+			printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
+#endif /* DEBUG */
+
+			return VME_INVALID_FILE;
+		}
+	}
+
+	/*
+	*
+	* Invalid exit point. Processing the token 'ENDVME' is the only
+	* valid way to exit the embedded engine.
+	*
+	*/
+
+	return VME_INVALID_FILE;
+}
+
+/*
+ *
+ * ispVMDataCode
+ *
+ * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command.
+ *
+ */
+
+signed char ispVMDataCode()
+{
+	/* 09/11/07 NN added local variables initialization */
+	signed char cDataByte    = 0;
+	signed char siDataSource = 0;  /*source of data from file by default*/
+
+	if (g_usDataType & HEAP_IN) {
+		siDataSource = 1;  /*the source of data from memory*/
+	}
+
+	/*
+	*
+	* Clear the data type register.
+	*
+	**/
+
+	g_usDataType &= ~(MASK_DATA + TDI_DATA +
+		TDO_DATA + DMASK_DATA + CMASK_DATA);
+
+	/*
+	 * Iterate through SIR/SDR command and look for TDI,
+	 * TDO, MASK, etc.
+	 */
+
+	while ((cDataByte = GetByte()) >= 0) {
+			ispVMMemManager(cDataByte, g_usMaxSize);
+			switch (cDataByte) {
+			case TDI:
+
+				/*
+				 * Store the maximum size of the TDI buffer.
+				 * Used to convert VME to HEX.
+				 */
+
+				if (g_usiDataSize > g_usTDISize) {
+					g_usTDISize = g_usiDataSize;
+				}
+				/*
+				 * Updated data type register to indicate that
+				 * TDI data is currently being used. Process the
+				 * data in the VME file into the TDI buffer.
+				 */
+
+				g_usDataType |= TDI_DATA;
+				ispVMData(g_pucInData);
+				break;
+			case XTDO:
+
+				/*
+				 * Store the maximum size of the TDO buffer.
+				 * Used to convert VME to HEX.
+				 */
+
+				if (g_usiDataSize > g_usTDOSize) {
+					g_usTDOSize = g_usiDataSize;
+				}
+
+				/*
+				 * Updated data type register to indicate that
+				 * TDO data is currently being used.
+				 */
+
+				g_usDataType |= TDO_DATA;
+				break;
+			case TDO:
+
+				/*
+				 * Store the maximum size of the TDO buffer.
+				 * Used to convert VME to HEX.
+				 */
+
+				if (g_usiDataSize > g_usTDOSize) {
+					g_usTDOSize = g_usiDataSize;
+				}
+
+				/*
+				 * Updated data type register to indicate
+				 * that TDO data is currently being used.
+				 * Process the data in the VME file into the
+				 * TDO buffer.
+				 */
+
+				g_usDataType |= TDO_DATA;
+				ispVMData(g_pucOutData);
+				break;
+			case MASK:
+
+				/*
+				 * Store the maximum size of the MASK buffer.
+				 * Used to convert VME to HEX.
+				 */
+
+				if (g_usiDataSize > g_usMASKSize) {
+					g_usMASKSize = g_usiDataSize;
+				}
+
+				/*
+				 * Updated data type register to indicate that
+				 * MASK data is currently being used. Process
+				 * the data in the VME file into the MASK buffer
+				 */
+
+				g_usDataType |= MASK_DATA;
+				ispVMData(g_pucOutMaskData);
+				break;
+			case DMASK:
+
+				/*
+				 * Store the maximum size of the DMASK buffer.
+				 * Used to convert VME to HEX.
+				 */
+
+				if (g_usiDataSize > g_usDMASKSize) {
+					g_usDMASKSize = g_usiDataSize;
+				}
+
+				/*
+				 * Updated data type register to indicate that
+				 * DMASK data is currently being used. Process
+				 * the data in the VME file into the DMASK
+				 * buffer.
+				 */
+
+				g_usDataType |= DMASK_DATA;
+				ispVMData(g_pucOutDMaskData);
+				break;
+			case CMASK:
+
+				/*
+				 * Updated data type register to indicate that
+				 * MASK data is currently being used. Process
+				 * the data in the VME file into the MASK buffer
+				 */
+
+				g_usDataType |= CMASK_DATA;
+				ispVMData(g_pucOutMaskData);
+				break;
+			case CONTINUE:
+				return 0;
+			default:
+				/*
+				 * Encountered invalid opcode.
+				 */
+				return VME_INVALID_FILE;
+			}
+
+			switch (cDataByte) {
+			case TDI:
+
+				/*
+				 * Left bit shift. Used when performing
+				 * algorithm looping.
+				 */
+
+				if (g_usFlowControl & SHIFTLEFT) {
+					ispVMBitShift(SHL, g_usShiftValue);
+					g_usFlowControl &= ~SHIFTLEFT;
+				}
+
+				/*
+				 * Right bit shift. Used when performing
+				 * algorithm looping.
+				 */
+
+				if (g_usFlowControl & SHIFTRIGHT) {
+					ispVMBitShift(SHR, g_usShiftValue);
+					g_usFlowControl &= ~SHIFTRIGHT;
+				}
+			default:
+				break;
+			}
+
+			if (siDataSource) {
+				g_usDataType |= HEAP_IN; /*restore from memory*/
+			}
+	}
+
+	if (siDataSource) {  /*fetch data from heap memory upon return*/
+		g_usDataType |= HEAP_IN;
+	}
+
+	if (cDataByte < 0) {
+
+		/*
+		 * Encountered invalid opcode.
+		 */
+
+		return VME_INVALID_FILE;
+	} else {
+		return 0;
+	}
+}
+
+/*
+ *
+ * ispVMData
+ * Extract one row of data operand from the current data type opcode. Perform
+ * the decompression if necessary. Extra RAM is not required for the
+ * decompression process. The decompression scheme employed in this module
+ * is on row by row basis. The format of the data stream:
+ * [compression code][compressed data stream]
+ * 0x00    --No compression
+ * 0x01    --Compress by 0x00.
+ *           Example:
+ *           Original stream:   0x000000000000000000000001
+ *           Compressed stream: 0x01000901
+ *           Detail:            0x01 is the code, 0x00 is the key,
+ *                              0x09 is the count of 0x00 bytes,
+ *                              0x01 is the uncompressed byte.
+ * 0x02    --Compress by 0xFF.
+ *           Example:
+ *           Original stream:   0xFFFFFFFFFFFFFFFFFFFFFF01
+ *           Compressed stream: 0x02FF0901
+ *           Detail:            0x02 is the code, 0xFF is the key,
+ *                              0x09 is the count of 0xFF bytes,
+ *                              0x01 is the uncompressed byte.
+ * 0x03
+ * : :
+ * 0xFE   -- Compress by nibble blocks.
+ *           Example:
+ *           Original stream:   0x84210842108421084210
+ *           Compressed stream: 0x0584210
+ *           Detail:            0x05 is the code, means 5 nibbles block.
+ *                              0x84210 is the 5 nibble blocks.
+ *                              The whole row is 80 bits given by g_usiDataSize.
+ *                              The number of times the block repeat itself
+ *                              is found by g_usiDataSize/(4*0x05) which is 4.
+ * 0xFF   -- Compress by the most frequently happen byte.
+ *           Example:
+ *           Original stream:   0x04020401030904040404
+ *           Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
+ *                          or: 0xFF044090181C240
+ *           Detail:            0xFF is the code, 0x04 is the key.
+ *                              a bit of 0 represent the key shall be put into
+ *                              the current bit position and a bit of 1
+ *                              represent copying the next of 8 bits of data
+ *                              in.
+ *
+ */
+
+void ispVMData(unsigned char *ByteData)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short size               = 0;
+	unsigned short i, j, m, getData   = 0;
+	unsigned char cDataByte           = 0;
+	unsigned char compress            = 0;
+	unsigned short FFcount            = 0;
+	unsigned char compr_char          = 0xFF;
+	unsigned short index              = 0;
+	signed char compression           = 0;
+
+	/*convert number in bits to bytes*/
+	if (g_usiDataSize % 8 > 0) {
+		/* 09/11/07 NN Type cast mismatch variables */
+		size = (unsigned short)(g_usiDataSize / 8 + 1);
+	} else {
+		/* 09/11/07 NN Type cast mismatch variables */
+		size = (unsigned short)(g_usiDataSize / 8);
+	}
+
+	/*
+	 * If there is compression, then check if compress by key
+	 * of 0x00 or 0xFF or by other keys or by nibble blocks
+	 */
+
+	if (g_usDataType & COMPRESS) {
+		compression = 1;
+		compress = GetByte();
+		if ((compress  == VAR) && (g_usDataType & HEAP_IN)) {
+			getData = 1;
+			g_usDataType &= ~(HEAP_IN);
+			compress = GetByte();
+		}
+
+		switch (compress) {
+		case 0x00:
+			/* No compression */
+			compression = 0;
+			break;
+		case 0x01:
+			/* Compress by byte 0x00 */
+			compr_char = 0x00;
+			break;
+		case 0x02:
+			/* Compress by byte 0xFF */
+			compr_char = 0xFF;
+			break;
+		case 0xFF:
+			/* Huffman encoding */
+			compr_char = GetByte();
+			i = 8;
+			for (index = 0; index < size; index++) {
+				ByteData[index] = 0x00;
+				if (i > 7) {
+					cDataByte = GetByte();
+					i = 0;
+				}
+				if ((cDataByte << i++) & 0x80)
+					m = 8;
+				else {
+					ByteData[index] = compr_char;
+					m = 0;
+				}
+
+				for (j = 0; j < m; j++) {
+					if (i > 7) {
+						cDataByte = GetByte();
+						i = 0;
+					}
+					ByteData[index] |=
+					((cDataByte << i++) & 0x80) >> j;
+				}
+			}
+			size = 0;
+			break;
+		default:
+			for (index = 0; index < size; index++)
+				ByteData[index] = 0x00;
+			for (index = 0; index < compress; index++) {
+				if (index % 2 == 0)
+					cDataByte = GetByte();
+				for (i = 0; i < size * 2 / compress; i++) {
+					j = (unsigned short)(index +
+						(i * (unsigned short)compress));
+					/*clear the nibble to zero first*/
+					if (j%2) {
+						if (index % 2)
+							ByteData[j/2] |=
+								cDataByte & 0xF;
+						else
+							ByteData[j/2] |=
+								cDataByte >> 4;
+					} else {
+						if (index % 2)
+							ByteData[j/2] |=
+								cDataByte << 4;
+						else
+							ByteData[j/2] |=
+							cDataByte & 0xF0;
+					}
+				}
+			}
+			size = 0;
+			break;
+		}
+	}
+
+	FFcount = 0;
+
+	/* Decompress by byte 0x00 or 0xFF */
+	for (index = 0; index < size; index++) {
+		if (FFcount <= 0) {
+			cDataByte = GetByte();
+			if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) &&
+				!getData && !(g_usDataType&COMPRESS)) {
+				getData = 1;
+				g_usDataType &= ~(HEAP_IN);
+				cDataByte = GetByte();
+			}
+			ByteData[index] = cDataByte;
+			if ((compression) && (cDataByte == compr_char))
+				/* 09/11/07 NN Type cast mismatch variables */
+				FFcount = (unsigned short) ispVMDataSize();
+				/*The number of 0xFF or 0x00 bytes*/
+		} else {
+			FFcount--; /*Use up the 0xFF chain first*/
+			ByteData[index] = compr_char;
+		}
+	}
+
+	if (getData) {
+		g_usDataType |= HEAP_IN;
+		getData = 0;
+	}
+}
+
+/*
+ *
+ * ispVMShift
+ *
+ * Processes the SDR/XSDR/SIR commands.
+ *
+ */
+
+signed char ispVMShift(signed char a_cCode)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short iDataIndex  = 0;
+	unsigned short iReadLoop   = 0;
+	signed char cRetCode       = 0;
+
+	cRetCode = 0;
+	/* 09/11/07 NN Type cast mismatch variables */
+	g_usiDataSize = (unsigned short) ispVMDataSize();
+
+	/*clear the flags first*/
+	g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA);
+	switch (a_cCode) {
+	case SIR:
+		g_usDataType |= SIR_DATA;
+		/*
+		 * 1/15/04 If performing cascading, then go directly to SHIFTIR.
+		 *  Else, go to IRPAUSE before going to SHIFTIR
+		 */
+		if (g_usFlowControl & CASCADE) {
+			ispVMStateMachine(SHIFTIR);
+		} else {
+			ispVMStateMachine(IRPAUSE);
+			ispVMStateMachine(SHIFTIR);
+			if (g_usHeadIR > 0) {
+				ispVMBypass(HIR, g_usHeadIR);
+				sclock();
+			}
+		}
+		break;
+	case XSDR:
+		g_usDataType |= EXPRESS; /*mark simultaneous in and out*/
+	case SDR:
+		g_usDataType |= SDR_DATA;
+		/*
+		 * 1/15/04 If already in SHIFTDR, then do not move state or
+		 * shift in header.  This would imply that the previously
+		 * shifted frame was a cascaded frame.
+		 */
+		if (g_cCurrentJTAGState != SHIFTDR) {
+			/*
+			 * 1/15/04 If performing cascading, then go directly
+			 * to SHIFTDR.  Else, go to DRPAUSE before going
+			 * to SHIFTDR
+			 */
+			if (g_usFlowControl & CASCADE) {
+				if (g_cCurrentJTAGState == DRPAUSE) {
+					ispVMStateMachine(SHIFTDR);
+					/*
+					 * 1/15/04 If cascade flag has been seat
+					 * and the current state is DRPAUSE,
+					 * this implies that the first cascaded
+					 * frame is about to be shifted in.  The
+					 * header must be shifted prior to
+					 * shifting the first cascaded frame.
+					 */
+					if (g_usHeadDR > 0) {
+						ispVMBypass(HDR, g_usHeadDR);
+						sclock();
+					}
+				} else {
+					ispVMStateMachine(SHIFTDR);
+				}
+			} else {
+				ispVMStateMachine(DRPAUSE);
+				ispVMStateMachine(SHIFTDR);
+				if (g_usHeadDR > 0) {
+					ispVMBypass(HDR, g_usHeadDR);
+					sclock();
+				}
+			}
+		}
+		break;
+	default:
+		return VME_INVALID_FILE;
+	}
+
+	cRetCode = ispVMDataCode();
+
+	if (cRetCode != 0) {
+		return VME_INVALID_FILE;
+	}
+
+#ifdef DEBUG
+	printf("%d ", g_usiDataSize);
+
+	if (g_usDataType & TDI_DATA) {
+		puts("TDI ");
+		PrintData(g_usiDataSize, g_pucInData);
+	}
+
+	if (g_usDataType & TDO_DATA) {
+		puts("\n\t\tTDO ");
+		PrintData(g_usiDataSize, g_pucOutData);
+	}
+
+	if (g_usDataType & MASK_DATA) {
+		puts("\n\t\tMASK ");
+		PrintData(g_usiDataSize, g_pucOutMaskData);
+	}
+
+	if (g_usDataType & DMASK_DATA) {
+		puts("\n\t\tDMASK ");
+		PrintData(g_usiDataSize, g_pucOutDMaskData);
+	}
+
+	puts(";\n");
+#endif /* DEBUG */
+
+	if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) {
+		if (g_usDataType & DMASK_DATA) {
+			cRetCode = ispVMReadandSave(g_usiDataSize);
+			if (!cRetCode) {
+				if (g_usTailDR > 0) {
+					sclock();
+					ispVMBypass(TDR, g_usTailDR);
+				}
+				ispVMStateMachine(DRPAUSE);
+				ispVMStateMachine(SHIFTDR);
+				if (g_usHeadDR > 0) {
+					ispVMBypass(HDR, g_usHeadDR);
+					sclock();
+				}
+				for (iDataIndex = 0;
+					iDataIndex < g_usiDataSize / 8 + 1;
+					iDataIndex++)
+					g_pucInData[iDataIndex] =
+						g_pucOutData[iDataIndex];
+				g_usDataType &= ~(TDO_DATA + DMASK_DATA);
+				cRetCode = ispVMSend(g_usiDataSize);
+			}
+		} else {
+			cRetCode = ispVMRead(g_usiDataSize);
+			if (cRetCode == -1 && g_cVendor == XILINX) {
+				for (iReadLoop = 0; iReadLoop < 30;
+					iReadLoop++) {
+					cRetCode = ispVMRead(g_usiDataSize);
+					if (!cRetCode) {
+						break;
+					} else {
+						/* Always DRPAUSE */
+						ispVMStateMachine(DRPAUSE);
+						/*
+						 * Bypass other devices
+						 * when appropriate
+						 */
+						ispVMBypass(TDR, g_usTailDR);
+						ispVMStateMachine(g_ucEndDR);
+						ispVMStateMachine(IDLE);
+						ispVMDelay(1000);
+					}
+				}
+			}
+		}
+	} else { /*TDI only*/
+		cRetCode = ispVMSend(g_usiDataSize);
+	}
+
+	/*transfer the input data to the output buffer for the next verify*/
+	if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) {
+		if (g_pucOutData) {
+			for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1;
+				iDataIndex++)
+				g_pucOutData[iDataIndex] =
+					g_pucInData[iDataIndex];
+		}
+	}
+
+	switch (a_cCode) {
+	case SIR:
+		/* 1/15/04 If not performing cascading, then shift ENDIR */
+		if (!(g_usFlowControl & CASCADE)) {
+			if (g_usTailIR > 0) {
+				sclock();
+				ispVMBypass(TIR, g_usTailIR);
+			}
+			ispVMStateMachine(g_ucEndIR);
+		}
+		break;
+	case XSDR:
+	case SDR:
+		/* 1/15/04 If not performing cascading, then shift ENDDR */
+		if (!(g_usFlowControl & CASCADE)) {
+			if (g_usTailDR > 0) {
+				sclock();
+				ispVMBypass(TDR, g_usTailDR);
+			}
+			ispVMStateMachine(g_ucEndDR);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return cRetCode;
+}
+
+/*
+ *
+ * ispVMAmble
+ *
+ * This routine is to extract Header and Trailer parameter for SIR and
+ * SDR operations.
+ *
+ * The Header and Trailer parameter are the pre-amble and post-amble bit
+ * stream need to be shifted into TDI or out of TDO of the devices. Mostly
+ * is for the purpose of bypassing the leading or trailing devices. ispVM
+ * supports only shifting data into TDI to bypass the devices.
+ *
+ * For a single device, the header and trailer parameters are all set to 0
+ * as default by ispVM. If it is for multiple devices, the header and trailer
+ * value will change as specified by the VME file.
+ *
+ */
+
+signed char ispVMAmble(signed char Code)
+{
+	signed char compress = 0;
+	/* 09/11/07 NN Type cast mismatch variables */
+	g_usiDataSize = (unsigned short)ispVMDataSize();
+
+#ifdef DEBUG
+	printf("%d", g_usiDataSize);
+#endif /* DEBUG */
+
+	if (g_usiDataSize) {
+
+		/*
+		 * Discard the TDI byte and set the compression bit in the data
+		 * type register to false if compression is set because TDI data
+		 * after HIR/HDR/TIR/TDR is not compressed.
+		 */
+
+		GetByte();
+		if (g_usDataType & COMPRESS) {
+			g_usDataType &= ~(COMPRESS);
+			compress = 1;
+		}
+	}
+
+	switch (Code) {
+	case HIR:
+
+		/*
+		 * Store the maximum size of the HIR buffer.
+		 * Used to convert VME to HEX.
+		 */
+
+		if (g_usiDataSize > g_usHIRSize) {
+			g_usHIRSize = g_usiDataSize;
+		}
+
+		/*
+		 * Assign the HIR value and allocate memory.
+		 */
+
+		g_usHeadIR = g_usiDataSize;
+		if (g_usHeadIR) {
+			ispVMMemManager(HIR, g_usHeadIR);
+			ispVMData(g_pucHIRData);
+
+#ifdef DEBUG
+			puts(" TDI ");
+			PrintData(g_usHeadIR, g_pucHIRData);
+#endif /* DEBUG */
+		}
+		break;
+	case TIR:
+
+		/*
+		 * Store the maximum size of the TIR buffer.
+		 * Used to convert VME to HEX.
+		 */
+
+		if (g_usiDataSize > g_usTIRSize) {
+			g_usTIRSize = g_usiDataSize;
+		}
+
+		/*
+		 * Assign the TIR value and allocate memory.
+		 */
+
+		g_usTailIR = g_usiDataSize;
+		if (g_usTailIR) {
+			ispVMMemManager(TIR, g_usTailIR);
+			ispVMData(g_pucTIRData);
+
+#ifdef DEBUG
+			puts(" TDI ");
+			PrintData(g_usTailIR, g_pucTIRData);
+#endif /* DEBUG */
+		}
+		break;
+	case HDR:
+
+		/*
+		 * Store the maximum size of the HDR buffer.
+		 * Used to convert VME to HEX.
+		 */
+
+		if (g_usiDataSize > g_usHDRSize) {
+			g_usHDRSize = g_usiDataSize;
+		}
+
+		/*
+		 * Assign the HDR value and allocate memory.
+		 *
+		 */
+
+		g_usHeadDR = g_usiDataSize;
+		if (g_usHeadDR) {
+			ispVMMemManager(HDR, g_usHeadDR);
+			ispVMData(g_pucHDRData);
+
+#ifdef DEBUG
+			puts(" TDI ");
+			PrintData(g_usHeadDR, g_pucHDRData);
+#endif /* DEBUG */
+		}
+		break;
+	case TDR:
+
+		/*
+		 * Store the maximum size of the TDR buffer.
+		 * Used to convert VME to HEX.
+		 */
+
+		if (g_usiDataSize > g_usTDRSize) {
+			g_usTDRSize = g_usiDataSize;
+		}
+
+		/*
+		 * Assign the TDR value and allocate memory.
+		 *
+		 */
+
+		g_usTailDR = g_usiDataSize;
+		if (g_usTailDR) {
+			ispVMMemManager(TDR, g_usTailDR);
+			ispVMData(g_pucTDRData);
+
+#ifdef DEBUG
+			puts(" TDI ");
+			PrintData(g_usTailDR, g_pucTDRData);
+#endif /* DEBUG */
+		}
+		break;
+	default:
+		break;
+	}
+
+	/*
+	*
+	* Re-enable compression if it was previously set.
+	*
+	**/
+
+	if (compress) {
+		g_usDataType |= COMPRESS;
+	}
+
+	if (g_usiDataSize) {
+		Code = GetByte();
+		if (Code == CONTINUE) {
+			return 0;
+		} else {
+
+			/*
+			 * Encountered invalid opcode.
+			 */
+
+			return VME_INVALID_FILE;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * ispVMLoop
+ *
+ * Perform the function call upon by the REPEAT opcode.
+ * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
+ * After the loop is stored then execution begin. The REPEATLOOP flag is set
+ * on the g_usFlowControl register to indicate the repeat loop is in session
+ * and therefore fetch opcode from the memory instead of from the file.
+ *
+ */
+
+signed char ispVMLoop(unsigned short a_usLoopCount)
+{
+	/* 09/11/07 NN added local variables initialization */
+	signed char cRetCode      = 0;
+	unsigned short iHeapIndex = 0;
+	unsigned short iLoopIndex = 0;
+
+	g_usShiftValue = 0;
+	for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) {
+		g_pucHeapMemory[iHeapIndex] = GetByte();
+	}
+
+	if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) {
+		return VME_INVALID_FILE;
+	}
+
+	g_usFlowControl |= REPEATLOOP;
+	g_usDataType |= HEAP_IN;
+
+	for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) {
+		g_iHeapCounter = 0;
+		cRetCode = ispVMCode();
+		g_usRepeatLoops++;
+		if (cRetCode < 0) {
+			break;
+		}
+	}
+
+	g_usDataType &= ~(HEAP_IN);
+	g_usFlowControl &= ~(REPEATLOOP);
+	return cRetCode;
+}
+
+/*
+ *
+ * ispVMBitShift
+ *
+ * Shift the TDI stream left or right by the number of bits. The data in
+ * *g_pucInData is of the VME format, so the actual shifting is the reverse of
+ * IEEE 1532 or SVF format.
+ *
+ */
+
+signed char ispVMBitShift(signed char mode, unsigned short bits)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short i       = 0;
+	unsigned short size    = 0;
+	unsigned short tmpbits = 0;
+
+	if (g_usiDataSize % 8 > 0) {
+		/* 09/11/07 NN Type cast mismatch variables */
+		size = (unsigned short)(g_usiDataSize / 8 + 1);
+	} else {
+		/* 09/11/07 NN Type cast mismatch variables */
+		size = (unsigned short)(g_usiDataSize / 8);
+	}
+
+	switch (mode) {
+	case SHR:
+		for (i = 0; i < size; i++) {
+			if (g_pucInData[i] != 0) {
+				tmpbits = bits;
+				while (tmpbits > 0) {
+					g_pucInData[i] <<= 1;
+					if (g_pucInData[i] == 0) {
+						i--;
+						g_pucInData[i] = 1;
+					}
+					tmpbits--;
+				}
+			}
+		}
+		break;
+	case SHL:
+		for (i = 0; i < size; i++) {
+			if (g_pucInData[i] != 0) {
+				tmpbits = bits;
+				while (tmpbits > 0) {
+					g_pucInData[i] >>= 1;
+					if (g_pucInData[i] == 0) {
+						i--;
+						g_pucInData[i] = 8;
+					}
+					tmpbits--;
+				}
+			}
+		}
+		break;
+	default:
+		return VME_INVALID_FILE;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * ispVMComment
+ *
+ * Displays the SVF comments.
+ *
+ */
+
+void ispVMComment(unsigned short a_usCommentSize)
+{
+	char cCurByte = 0;
+	for (; a_usCommentSize > 0; a_usCommentSize--) {
+		/*
+		*
+		* Print character to the terminal.
+		*
+		**/
+		cCurByte = GetByte();
+		vme_out_char(cCurByte);
+	}
+	cCurByte = '\n';
+	vme_out_char(cCurByte);
+}
+
+/*
+ *
+ * ispVMHeader
+ *
+ * Iterate the length of the header and discard it.
+ *
+ */
+
+void ispVMHeader(unsigned short a_usHeaderSize)
+{
+	for (; a_usHeaderSize > 0; a_usHeaderSize--) {
+		GetByte();
+	}
+}
+
+/*
+ *
+ * ispVMCalculateCRC32
+ *
+ * Calculate the 32-bit CRC.
+ *
+ */
+
+void ispVMCalculateCRC32(unsigned char a_ucData)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned char ucIndex          = 0;
+	unsigned char ucFlipData       = 0;
+	unsigned short usCRCTableEntry = 0;
+	unsigned int crc_table[16] = {
+		0x0000, 0xCC01, 0xD801,
+		0x1400, 0xF001, 0x3C00,
+		0x2800, 0xE401, 0xA001,
+		0x6C00, 0x7800, 0xB401,
+		0x5000, 0x9C01, 0x8801,
+		0x4400
+	};
+
+	for (ucIndex = 0; ucIndex < 8; ucIndex++) {
+		ucFlipData <<= 1;
+		if (a_ucData & 0x01) {
+			ucFlipData |= 0x01;
+		}
+		a_ucData >>= 1;
+	}
+
+	/* 09/11/07 NN Type cast mismatch variables */
+	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
+	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
+	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
+			usCRCTableEntry ^ crc_table[ucFlipData & 0xF]);
+	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
+	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
+	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
+		usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]);
+}
+
+/*
+ *
+ * ispVMLCOUNT
+ *
+ * Process the intelligent programming loops.
+ *
+ */
+
+signed char ispVMLCOUNT(unsigned short a_usCountSize)
+{
+	unsigned short usContinue	  = 1;
+	unsigned short usIntelBufferIndex = 0;
+	unsigned short usCountIndex       = 0;
+	signed char cRetCode              = 0;
+	signed char cRepeatHeap           = 0;
+	signed char cOpcode               = 0;
+	unsigned char ucState             = 0;
+	unsigned short usDelay            = 0;
+	unsigned short usToggle           = 0;
+
+	g_usIntelBufferSize = (unsigned short)ispVMDataSize();
+
+	/*
+	 * Allocate memory for intel buffer.
+	 *
+	 */
+
+	ispVMMemManager(LHEAP, g_usIntelBufferSize);
+
+	/*
+	 * Store the maximum size of the intelligent buffer.
+	 * Used to convert VME to HEX.
+	 */
+
+	if (g_usIntelBufferSize > g_usLCOUNTSize) {
+		g_usLCOUNTSize = g_usIntelBufferSize;
+	}
+
+	/*
+	 * Copy intel data to the buffer.
+	 */
+
+	for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize;
+		usIntelBufferIndex++) {
+		g_pucIntelBuffer[usIntelBufferIndex] = GetByte();
+	}
+
+	/*
+	 * Set the data type register to get data from the intelligent
+	 * data buffer.
+	 */
+
+	g_usDataType |= LHEAP_IN;
+
+	/*
+	*
+	* If the HEAP_IN flag is set, temporarily unset the flag so data will be
+	* retrieved from the status buffer.
+	*
+	**/
+
+	if (g_usDataType & HEAP_IN) {
+		g_usDataType &= ~HEAP_IN;
+		cRepeatHeap = 1;
+	}
+
+#ifdef DEBUG
+	printf("LCOUNT %d;\n", a_usCountSize);
+#endif /* DEBUG */
+
+	/*
+	 * Iterate through the intelligent programming command.
+	*/
+
+	for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) {
+
+		/*
+		*
+		* Initialize the intel data index to 0 before each iteration.
+		*
+		**/
+
+		g_usIntelDataIndex = 0;
+		cOpcode            = 0;
+		ucState            = 0;
+		usDelay            = 0;
+		usToggle           = 0;
+		usContinue		   = 1;
+
+		/*
+		*
+		* Begin looping through all the VME opcodes.
+		*
+		*/
+		/*
+		* 4/1/09 Nguyen replaced the recursive function call codes on
+		*        the ispVMLCOUNT function
+		*
+		*/
+		while (usContinue) {
+			cOpcode = GetByte();
+			switch (cOpcode) {
+			case HIR:
+			case TIR:
+			case HDR:
+			case TDR:
+				/*
+				 * Set the header/trailer of the device in order
+				 * to bypass successfully.
+				 */
+
+				ispVMAmble(cOpcode);
+			break;
+			case STATE:
+
+				/*
+				 * Step the JTAG state machine.
+				 */
+
+				ucState = GetByte();
+				/*
+				 * Step the JTAG state machine to DRCAPTURE
+				 * to support Looping.
+				 */
+
+				if ((g_usDataType & LHEAP_IN) &&
+					 (ucState == DRPAUSE) &&
+					 (g_cCurrentJTAGState == ucState)) {
+					ispVMStateMachine(DRCAPTURE);
+				}
+				ispVMStateMachine(ucState);
+#ifdef DEBUG
+				printf("LDELAY %s ", GetState(ucState));
+#endif /* DEBUG */
+				break;
+			case SIR:
+#ifdef DEBUG
+				printf("SIR ");
+#endif /* DEBUG */
+				/*
+				 * Shift in data into the device.
+				 */
+
+				cRetCode = ispVMShift(cOpcode);
+				break;
+			case SDR:
+
+#ifdef DEBUG
+				printf("LSDR ");
+#endif /* DEBUG */
+				/*
+				 * Shift in data into the device.
+				 */
+
+				cRetCode = ispVMShift(cOpcode);
+				break;
+			case WAIT:
+
+				/*
+				*
+				* Observe delay.
+				*
+				*/
+
+				usDelay = (unsigned short)ispVMDataSize();
+				ispVMDelay(usDelay);
+
+#ifdef DEBUG
+				if (usDelay & 0x8000) {
+
+					/*
+					 * Since MSB is set, the delay time must
+					 * be decoded to millisecond. The
+					 * SVF2VME encodes the MSB to represent
+					 * millisecond.
+					 */
+
+					usDelay &= ~0x8000;
+					printf("%.2E SEC;\n",
+						(float) usDelay / 1000);
+				} else {
+					/*
+					 * Since MSB is not set, the delay time
+					 * is given as microseconds.
+					 */
+
+					printf("%.2E SEC;\n",
+						(float) usDelay / 1000000);
+				}
+#endif /* DEBUG */
+				break;
+			case TCK:
+
+				/*
+				 * Issue clock toggles.
+				 */
+
+				usToggle = (unsigned short)ispVMDataSize();
+				ispVMClocks(usToggle);
+
+#ifdef DEBUG
+				printf("RUNTEST %d TCK;\n", usToggle);
+#endif /* DEBUG */
+				break;
+			case ENDLOOP:
+
+				/*
+				 * Exit point from processing loops.
+				 */
+				usContinue = 0;
+				break;
+
+			case COMMENT:
+
+				/*
+				 * Display comment.
+				 */
+
+				ispVMComment((unsigned short) ispVMDataSize());
+				break;
+			case ispEN:
+				ucState = GetByte();
+				if ((ucState == ON) || (ucState == 0x01))
+					writePort(g_ucPinENABLE, 0x01);
+				else
+					writePort(g_ucPinENABLE, 0x00);
+				ispVMDelay(1);
+				break;
+			case TRST:
+				if (GetByte() == 0x01)
+					writePort(g_ucPinTRST, 0x01);
+				else
+					writePort(g_ucPinTRST, 0x00);
+				ispVMDelay(1);
+				break;
+			default:
+
+				/*
+				 * Invalid opcode encountered.
+				 */
+
+				debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
+
+				return VME_INVALID_FILE;
+			}
+		}
+		if (cRetCode >= 0) {
+			/*
+			 * Break if intelligent programming is successful.
+			 */
+
+			break;
+		}
+
+	}
+	/*
+	 * If HEAP_IN flag was temporarily disabled,
+	 * re-enable it before exiting
+	 */
+
+	if (cRepeatHeap) {
+		g_usDataType |= HEAP_IN;
+	}
+
+	/*
+	 * Set the data type register to not get data from the
+	 * intelligent data buffer.
+	 */
+
+	g_usDataType &= ~LHEAP_IN;
+	return cRetCode;
+}
+/*
+ *
+ * ispVMClocks
+ *
+ * Applies the specified number of pulses to TCK.
+ *
+ */
+
+void ispVMClocks(unsigned short Clocks)
+{
+	unsigned short iClockIndex = 0;
+	for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) {
+		sclock();
+	}
+}
+
+/*
+ *
+ * ispVMBypass
+ *
+ * This procedure takes care of the HIR, HDR, TIR, TDR for the
+ * purpose of putting the other devices into Bypass mode. The
+ * current state is checked to find out if it is at DRPAUSE or
+ * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
+ * If it is at IRPAUSE, scan into instruction registers the bypass
+ * instruction.
+ *
+ */
+
+void ispVMBypass(signed char ScanType, unsigned short Bits)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short iIndex       = 0;
+	unsigned short iSourceIndex = 0;
+	unsigned char cBitState     = 0;
+	unsigned char cCurByte      = 0;
+	unsigned char *pcSource    = NULL;
+
+	if (Bits <= 0) {
+		return;
+	}
+
+	switch (ScanType) {
+	case HIR:
+		pcSource = g_pucHIRData;
+		break;
+	case TIR:
+		pcSource = g_pucTIRData;
+		break;
+	case HDR:
+		pcSource = g_pucHDRData;
+		break;
+	case TDR:
+		pcSource = g_pucTDRData;
+		break;
+	default:
+		break;
+	}
+
+	iSourceIndex = 0;
+	cBitState = 0;
+	for (iIndex = 0; iIndex < Bits - 1; iIndex++) {
+		/* Scan instruction or bypass register */
+		if (iIndex % 8 == 0) {
+			cCurByte = pcSource[iSourceIndex++];
+		}
+		cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
+			? 0x01 : 0x00);
+		writePort(g_ucPinTDI, cBitState);
+		sclock();
+	}
+
+	if (iIndex % 8 == 0)  {
+		cCurByte = pcSource[iSourceIndex++];
+	}
+
+	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
+		? 0x01 : 0x00);
+	writePort(g_ucPinTDI, cBitState);
+}
+
+/*
+ *
+ * ispVMStateMachine
+ *
+ * This procedure steps all devices in the daisy chain from a given
+ * JTAG state to the next desirable state. If the next state is TLR,
+ * the JTAG state machine is brute forced into TLR by driving TMS
+ * high and pulse TCK 6 times.
+ *
+ */
+
+void ispVMStateMachine(signed char cNextJTAGState)
+{
+	/* 09/11/07 NN added local variables initialization */
+	signed char cPathIndex  = 0;
+	signed char cStateIndex = 0;
+
+	if ((g_cCurrentJTAGState == cNextJTAGState) &&
+		(cNextJTAGState != RESET)) {
+		return;
+	}
+
+	for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) {
+		if ((g_cCurrentJTAGState ==
+			 g_JTAGTransistions[cStateIndex].CurState) &&
+			(cNextJTAGState ==
+				 g_JTAGTransistions[cStateIndex].NextState)) {
+			break;
+		}
+	}
+
+	g_cCurrentJTAGState = cNextJTAGState;
+	for (cPathIndex = 0;
+		cPathIndex < g_JTAGTransistions[cStateIndex].Pulses;
+		cPathIndex++) {
+		if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex)
+			& 0x80) {
+			writePort(g_ucPinTMS, (unsigned char) 0x01);
+		} else {
+			writePort(g_ucPinTMS, (unsigned char) 0x00);
+		}
+		sclock();
+	}
+
+	writePort(g_ucPinTDI, 0x00);
+	writePort(g_ucPinTMS, 0x00);
+}
+
+/*
+ *
+ * ispVMStart
+ *
+ * Enable the port to the device and set the state to RESET (TLR).
+ *
+ */
+
+void ispVMStart()
+{
+#ifdef DEBUG
+	printf("// ISPVM EMBEDDED ADDED\n");
+	printf("STATE RESET;\n");
+#endif
+	g_usFlowControl	= 0;
+	g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0;
+	g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0;
+	g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0;
+	g_usTDOSize =  g_usMASKSize = g_usTDISize = 0;
+	g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0;
+	g_usTDRSize = g_usHIRSize = g_usTIRSize =  g_usHeapSize	= 0;
+	g_pLVDSList = NULL;
+	g_usLVDSPairCount = 0;
+	previous_size = 0;
+
+	ispVMStateMachine(RESET);    /*step devices to RESET state*/
+}
+
+/*
+ *
+ * ispVMEnd
+ *
+ * Set the state of devices to RESET to enable the devices and disable
+ * the port.
+ *
+ */
+
+void ispVMEnd()
+{
+#ifdef DEBUG
+	printf("// ISPVM EMBEDDED ADDED\n");
+	printf("STATE RESET;\n");
+	printf("RUNTEST 1.00E-001 SEC;\n");
+#endif
+
+	ispVMStateMachine(RESET);   /*step devices to RESET state */
+	ispVMDelay(1000);              /*wake up devices*/
+}
+
+/*
+ *
+ * ispVMSend
+ *
+ * Send the TDI data stream to devices. The data stream can be
+ * instructions or data.
+ *
+ */
+
+signed char ispVMSend(unsigned short a_usiDataSize)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short iIndex       = 0;
+	unsigned short iInDataIndex = 0;
+	unsigned char cCurByte      = 0;
+	unsigned char cBitState     = 0;
+
+	for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) {
+		if (iIndex % 8 == 0) {
+			cCurByte = g_pucInData[iInDataIndex++];
+		}
+		cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80)
+			? 0x01 : 0x00);
+		writePort(g_ucPinTDI, cBitState);
+		sclock();
+	}
+
+	if (iIndex % 8 == 0) {
+		/* Take care of the last bit */
+		cCurByte = g_pucInData[iInDataIndex];
+	}
+
+	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
+		? 0x01 : 0x00);
+
+	writePort(g_ucPinTDI, cBitState);
+	if (g_usFlowControl & CASCADE) {
+		/*1/15/04 Clock in last bit for the first n-1 cascaded frames */
+		sclock();
+	}
+
+	return 0;
+}
+
+/*
+ *
+ * ispVMRead
+ *
+ * Read the data stream from devices and verify.
+ *
+ */
+
+signed char ispVMRead(unsigned short a_usiDataSize)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short usDataSizeIndex    = 0;
+	unsigned short usErrorCount       = 0;
+	unsigned short usLastBitIndex     = 0;
+	unsigned char cDataByte           = 0;
+	unsigned char cMaskByte           = 0;
+	unsigned char cInDataByte         = 0;
+	unsigned char cCurBit             = 0;
+	unsigned char cByteIndex          = 0;
+	unsigned short usBufferIndex      = 0;
+	unsigned char ucDisplayByte       = 0x00;
+	unsigned char ucDisplayFlag       = 0x01;
+	char StrChecksum[256]            = {0};
+	unsigned char g_usCalculateChecksum = 0x00;
+
+	/* 09/11/07 NN Type cast mismatch variables */
+	usLastBitIndex = (unsigned short)(a_usiDataSize - 1);
+
+#ifndef DEBUG
+	/*
+	 * If mask is not all zeros, then set the display flag to 0x00,
+	 * otherwise it shall be set to 0x01 to indicate that data read
+	 * from the device shall be displayed. If DEBUG is defined,
+	 * always display data.
+	 */
+
+	for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8;
+		usDataSizeIndex++) {
+		if (g_usDataType & MASK_DATA) {
+			if (g_pucOutMaskData[usDataSizeIndex] != 0x00) {
+				ucDisplayFlag = 0x00;
+				break;
+			}
+		} else if (g_usDataType & CMASK_DATA) {
+			g_usCalculateChecksum = 0x01;
+			ucDisplayFlag = 0x00;
+			break;
+		} else {
+			ucDisplayFlag = 0x00;
+			break;
+		}
+	}
+#endif /* DEBUG */
+
+	/*
+	*
+	* Begin shifting data in and out of the device.
+	*
+	**/
+
+	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
+		usDataSizeIndex++) {
+		if (cByteIndex == 0) {
+
+			/*
+			 * Grab byte from TDO buffer.
+			 */
+
+			if (g_usDataType & TDO_DATA) {
+				cDataByte = g_pucOutData[usBufferIndex];
+			}
+
+			/*
+			 * Grab byte from MASK buffer.
+			 */
+
+			if (g_usDataType & MASK_DATA) {
+				cMaskByte = g_pucOutMaskData[usBufferIndex];
+			} else {
+				cMaskByte = 0xFF;
+			}
+
+			/*
+			 * Grab byte from CMASK buffer.
+			 */
+
+			if (g_usDataType & CMASK_DATA) {
+				cMaskByte = 0x00;
+				g_usCalculateChecksum = 0x01;
+			}
+
+			/*
+			 * Grab byte from TDI buffer.
+			 */
+
+			if (g_usDataType & TDI_DATA) {
+				cInDataByte = g_pucInData[usBufferIndex];
+			}
+
+			usBufferIndex++;
+		}
+
+		cCurBit = readPort();
+
+		if (ucDisplayFlag) {
+			ucDisplayByte <<= 1;
+			ucDisplayByte |= cCurBit;
+		}
+
+		/*
+		 * Check if data read from port matches with expected TDO.
+		 */
+
+		if (g_usDataType & TDO_DATA) {
+			/* 08/28/08 NN Added Calculate checksum support. */
+			if (g_usCalculateChecksum) {
+				if (cCurBit == 0x01)
+					g_usChecksum +=
+						(1 << (g_uiChecksumIndex % 8));
+				g_uiChecksumIndex++;
+			} else {
+				if ((((cMaskByte << cByteIndex) & 0x80)
+					? 0x01 : 0x00)) {
+					if (cCurBit != (unsigned char)
+					(((cDataByte << cByteIndex) & 0x80)
+						? 0x01 : 0x00)) {
+						usErrorCount++;
+					}
+				}
+			}
+		}
+
+		/*
+		 * Write TDI data to the port.
+		 */
+
+		writePort(g_ucPinTDI,
+			(unsigned char)(((cInDataByte << cByteIndex) & 0x80)
+				? 0x01 : 0x00));
+
+		if (usDataSizeIndex < usLastBitIndex) {
+
+			/*
+			 * Clock data out from the data shift register.
+			 */
+
+			sclock();
+		} else if (g_usFlowControl & CASCADE) {
+
+			/*
+			 * Clock in last bit for the first N - 1 cascaded frames
+			 */
+
+			sclock();
+		}
+
+		/*
+		 * Increment the byte index. If it exceeds 7, then reset it back
+		 * to zero.
+		 */
+
+		cByteIndex++;
+		if (cByteIndex >= 8) {
+			if (ucDisplayFlag) {
+
+			/*
+			 * Store displayed data in the TDO buffer. By reusing
+			 * the TDO buffer to store displayed data, there is no
+			 * need to allocate a buffer simply to hold display
+			 * data. This will not cause any false verification
+			 * errors because the true TDO byte has already
+			 * been consumed.
+			 */
+
+				g_pucOutData[usBufferIndex - 1] = ucDisplayByte;
+				ucDisplayByte = 0;
+			}
+
+			cByteIndex = 0;
+		}
+		/* 09/12/07 Nguyen changed to display the 1 bit expected data */
+		else if (a_usiDataSize == 1) {
+			if (ucDisplayFlag) {
+
+				/*
+				 * Store displayed data in the TDO buffer.
+				 * By reusing the TDO buffer to store displayed
+				 * data, there is no need to allocate
+				 * a buffer simply to hold display data. This
+				 * will not cause any false verification errors
+				 * because the true TDO byte has already
+				 * been consumed.
+				 */
+
+				/*
+				 * Flip ucDisplayByte and store it in cDataByte.
+				 */
+				cDataByte = 0x00;
+				for (usBufferIndex = 0; usBufferIndex < 8;
+					usBufferIndex++) {
+					cDataByte <<= 1;
+					if (ucDisplayByte & 0x01) {
+						cDataByte |= 0x01;
+					}
+					ucDisplayByte >>= 1;
+				}
+				g_pucOutData[0] = cDataByte;
+				ucDisplayByte = 0;
+			}
+
+			cByteIndex = 0;
+		}
+	}
+
+	if (ucDisplayFlag) {
+
+#ifdef DEBUG
+		debug("RECEIVED TDO (");
+#else
+		vme_out_string("Display Data: 0x");
+#endif /* DEBUG */
+
+		/* 09/11/07 NN Type cast mismatch variables */
+		for (usDataSizeIndex = (unsigned short)
+				((a_usiDataSize + 7) / 8);
+			usDataSizeIndex > 0 ; usDataSizeIndex--) {
+			cMaskByte = g_pucOutData[usDataSizeIndex - 1];
+			cDataByte = 0x00;
+
+			/*
+			 * Flip cMaskByte and store it in cDataByte.
+			 */
+
+			for (usBufferIndex = 0; usBufferIndex < 8;
+				usBufferIndex++) {
+				cDataByte <<= 1;
+				if (cMaskByte & 0x01) {
+					cDataByte |= 0x01;
+				}
+				cMaskByte >>= 1;
+			}
+#ifdef DEBUG
+			printf("%.2X", cDataByte);
+			if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex)
+				% 40 == 39) {
+				printf("\n\t\t");
+			}
+#else
+			vme_out_hex(cDataByte);
+#endif /* DEBUG */
+		}
+
+#ifdef DEBUG
+		printf(")\n\n");
+#else
+		vme_out_string("\n\n");
+#endif /* DEBUG */
+		/* 09/02/08 Nguyen changed to display the data Checksum */
+		if (g_usChecksum != 0) {
+			g_usChecksum &= 0xFFFF;
+			sprintf(StrChecksum, "Data Checksum: %.4lX\n\n",
+				g_usChecksum);
+			vme_out_string(StrChecksum);
+			g_usChecksum = 0;
+		}
+	}
+
+	if (usErrorCount > 0) {
+		if (g_usFlowControl & VERIFYUES) {
+			vme_out_string(
+				"USERCODE verification failed.   "
+				"Continue programming......\n\n");
+			g_usFlowControl &= ~(VERIFYUES);
+			return 0;
+		} else {
+
+#ifdef DEBUG
+			printf("TOTAL ERRORS: %d\n", usErrorCount);
+#endif /* DEBUG */
+
+			return VME_VERIFICATION_FAILURE;
+		}
+	} else {
+		if (g_usFlowControl & VERIFYUES) {
+			vme_out_string("USERCODE verification passed.    "
+				"Programming aborted.\n\n");
+			g_usFlowControl &= ~(VERIFYUES);
+			return 1;
+		} else {
+			return 0;
+		}
+	}
+}
+
+/*
+ *
+ * ispVMReadandSave
+ *
+ * Support dynamic I/O.
+ *
+ */
+
+signed char ispVMReadandSave(unsigned short int a_usiDataSize)
+{
+	/* 09/11/07 NN added local variables initialization */
+	unsigned short int usDataSizeIndex = 0;
+	unsigned short int usLastBitIndex  = 0;
+	unsigned short int usBufferIndex   = 0;
+	unsigned short int usOutBitIndex   = 0;
+	unsigned short int usLVDSIndex     = 0;
+	unsigned char cDataByte            = 0;
+	unsigned char cDMASKByte           = 0;
+	unsigned char cInDataByte          = 0;
+	unsigned char cCurBit              = 0;
+	unsigned char cByteIndex           = 0;
+	signed char cLVDSByteIndex         = 0;
+
+	/* 09/11/07 NN Type cast mismatch variables */
+	usLastBitIndex = (unsigned short) (a_usiDataSize - 1);
+
+	/*
+	*
+	* Iterate through the data bits.
+	*
+	*/
+
+	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
+		usDataSizeIndex++) {
+		if (cByteIndex == 0) {
+
+			/*
+			 * Grab byte from DMASK buffer.
+			 */
+
+			if (g_usDataType & DMASK_DATA) {
+				cDMASKByte = g_pucOutDMaskData[usBufferIndex];
+			} else {
+				cDMASKByte = 0x00;
+			}
+
+			/*
+			 * Grab byte from TDI buffer.
+			 */
+
+			if (g_usDataType & TDI_DATA) {
+				cInDataByte = g_pucInData[usBufferIndex];
+			}
+
+			usBufferIndex++;
+		}
+
+		cCurBit = readPort();
+		cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80)
+			? 0x01 : 0x00);
+
+		/*
+		 * Initialize the byte to be zero.
+		 */
+
+		if (usOutBitIndex % 8 == 0) {
+			g_pucOutData[usOutBitIndex / 8] = 0x00;
+		}
+
+		/*
+		 * Use TDI, DMASK, and device TDO to create new TDI (actually
+		 * stored in g_pucOutData).
+		 */
+
+		if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) {
+
+			if (g_pLVDSList) {
+				for (usLVDSIndex = 0;
+					 usLVDSIndex < g_usLVDSPairCount;
+					usLVDSIndex++) {
+					if (g_pLVDSList[usLVDSIndex].
+						usNegativeIndex ==
+						usDataSizeIndex) {
+						g_pLVDSList[usLVDSIndex].
+							ucUpdate = 0x01;
+						break;
+					}
+				}
+			}
+
+			/*
+			 * DMASK bit is 1, use TDI.
+			 */
+
+			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
+				(((cDataByte & 0x1) ? 0x01 : 0x00) <<
+				(7 - usOutBitIndex % 8));
+		} else {
+
+			/*
+			 * DMASK bit is 0, use device TDO.
+			 */
+
+			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
+				(((cCurBit & 0x1) ? 0x01 : 0x00) <<
+				(7 - usOutBitIndex % 8));
+		}
+
+		/*
+		 * Shift in TDI in order to get TDO out.
+		 */
+
+		usOutBitIndex++;
+		writePort(g_ucPinTDI, cDataByte);
+		if (usDataSizeIndex < usLastBitIndex) {
+			sclock();
+		}
+
+		/*
+		 * Increment the byte index. If it exceeds 7, then reset it back
+		 * to zero.
+		 */
+
+		cByteIndex++;
+		if (cByteIndex >= 8) {
+			cByteIndex = 0;
+		}
+	}
+
+	/*
+	 * If g_pLVDSList exists and pairs need updating, then update
+	 * the negative-pair to receive the flipped positive-pair value.
+	 */
+
+	if (g_pLVDSList) {
+		for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount;
+			usLVDSIndex++) {
+			if (g_pLVDSList[usLVDSIndex].ucUpdate) {
+
+				/*
+				 * Read the positive value and flip it.
+				 */
+
+				cDataByte = (unsigned char)
+				 (((g_pucOutData[g_pLVDSList[usLVDSIndex].
+					usPositiveIndex / 8]
+					<< (g_pLVDSList[usLVDSIndex].
+					usPositiveIndex % 8)) & 0x80) ?
+					0x01 : 0x00);
+				/* 09/11/07 NN Type cast mismatch variables */
+				cDataByte = (unsigned char) (!cDataByte);
+
+				/*
+				 * Get the byte that needs modification.
+				 */
+
+				cInDataByte =
+				g_pucOutData[g_pLVDSList[usLVDSIndex].
+					usNegativeIndex / 8];
+
+				if (cDataByte) {
+
+					/*
+					 * Copy over the current byte and
+					 * set the negative bit to 1.
+					 */
+
+					cDataByte = 0x00;
+					for (cLVDSByteIndex = 7;
+						cLVDSByteIndex >= 0;
+						cLVDSByteIndex--) {
+						cDataByte <<= 1;
+						if (7 -
+						(g_pLVDSList[usLVDSIndex].
+							usNegativeIndex % 8) ==
+							cLVDSByteIndex) {
+
+							/*
+							 * Set negative bit to 1
+							 */
+
+							cDataByte |= 0x01;
+						} else if (cInDataByte & 0x80) {
+							cDataByte |= 0x01;
+						}
+
+						cInDataByte <<= 1;
+					}
+
+					/*
+					 * Store the modified byte.
+					 */
+
+					g_pucOutData[g_pLVDSList[usLVDSIndex].
+					usNegativeIndex / 8] = cDataByte;
+				} else {
+
+					/*
+					 * Copy over the current byte and set
+					 * the negative bit to 0.
+					 */
+
+					cDataByte = 0x00;
+					for (cLVDSByteIndex = 7;
+						cLVDSByteIndex >= 0;
+						cLVDSByteIndex--) {
+						cDataByte <<= 1;
+						if (7 -
+						(g_pLVDSList[usLVDSIndex].
+						usNegativeIndex % 8) ==
+						cLVDSByteIndex) {
+
+							/*
+							 * Set negative bit to 0
+							 */
+
+							cDataByte |= 0x00;
+						} else if (cInDataByte & 0x80) {
+							cDataByte |= 0x01;
+						}
+
+						cInDataByte <<= 1;
+					}
+
+					/*
+					 * Store the modified byte.
+					 */
+
+					g_pucOutData[g_pLVDSList[usLVDSIndex].
+					usNegativeIndex / 8] = cDataByte;
+				}
+
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+signed char ispVMProcessLVDS(unsigned short a_usLVDSCount)
+{
+	unsigned short usLVDSIndex = 0;
+
+	/*
+	 * Allocate memory to hold LVDS pairs.
+	 */
+
+	ispVMMemManager(LVDS, a_usLVDSCount);
+	g_usLVDSPairCount = a_usLVDSCount;
+
+#ifdef DEBUG
+	printf("LVDS %d (", a_usLVDSCount);
+#endif /* DEBUG */
+
+	/*
+	 * Iterate through each given LVDS pair.
+	 */
+
+	for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) {
+
+		/*
+		 * Assign the positive and negative indices of the LVDS pair.
+		 */
+
+		/* 09/11/07 NN Type cast mismatch variables */
+		g_pLVDSList[usLVDSIndex].usPositiveIndex =
+			(unsigned short) ispVMDataSize();
+		/* 09/11/07 NN Type cast mismatch variables */
+		g_pLVDSList[usLVDSIndex].usNegativeIndex =
+			(unsigned short)ispVMDataSize();
+
+#ifdef DEBUG
+		if (usLVDSIndex < g_usLVDSPairCount - 1) {
+			printf("%d:%d, ",
+				g_pLVDSList[usLVDSIndex].usPositiveIndex,
+				g_pLVDSList[usLVDSIndex].usNegativeIndex);
+		} else {
+			printf("%d:%d",
+				g_pLVDSList[usLVDSIndex].usPositiveIndex,
+				g_pLVDSList[usLVDSIndex].usNegativeIndex);
+		}
+#endif /* DEBUG */
+
+	}
+
+#ifdef DEBUG
+	printf(");\n", a_usLVDSCount);
+#endif /* DEBUG */
+
+	return 0;
+}
diff --git a/marvell/uboot/drivers/fpga/lattice.c b/marvell/uboot/drivers/fpga/lattice.c
new file mode 100644
index 0000000..615a485
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/lattice.c
@@ -0,0 +1,380 @@
+/*
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * ispVM functions adapted from Lattice's ispmVMEmbedded code:
+ * Copyright 2009 Lattice Semiconductor Corp.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <fpga.h>
+#include <lattice.h>
+
+static lattice_board_specific_func *pfns;
+static const char *fpga_image;
+static unsigned long read_bytes;
+static unsigned long bufsize;
+static unsigned short expectedCRC;
+
+/*
+ * External variables and functions declared in ivm_core.c module.
+ */
+extern unsigned short g_usCalculatedCRC;
+extern unsigned short g_usDataType;
+extern unsigned char *g_pucIntelBuffer;
+extern unsigned char *g_pucHeapMemory;
+extern unsigned short g_iHeapCounter;
+extern unsigned short g_iHEAPSize;
+extern unsigned short g_usIntelDataIndex;
+extern unsigned short g_usIntelBufferSize;
+extern char *const g_szSupportedVersions[];
+
+
+/*
+ * ispVMDelay
+ *
+ * Users must implement a delay to observe a_usTimeDelay, where
+ * bit 15 of the a_usTimeDelay defines the unit.
+ *      1 = milliseconds
+ *      0 = microseconds
+ * Example:
+ *      a_usTimeDelay = 0x0001 = 1 microsecond delay.
+ *      a_usTimeDelay = 0x8001 = 1 millisecond delay.
+ *
+ * This subroutine is called upon to provide a delay from 1 millisecond to a few
+ * hundreds milliseconds each time.
+ * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16
+ * bits integer, this function is restricted to produce a delay to 64000
+ * micro-seconds or 32000 milli-second maximum. The VME file will never pass on
+ * to this function a delay time > those maximum number. If it needs more than
+ * those maximum, the VME file will launch the delay function several times to
+ * realize a larger delay time cummulatively.
+ * It is perfectly alright to provide a longer delay than required. It is not
+ * acceptable if the delay is shorter.
+ */
+void ispVMDelay(unsigned short delay)
+{
+	if (delay & 0x8000)
+		delay = (delay & ~0x8000) * 1000;
+	udelay(delay);
+}
+
+void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
+{
+	a_ucValue = a_ucValue ? 1 : 0;
+
+	switch (a_ucPins) {
+	case g_ucPinTDI:
+		pfns->jtag_set_tdi(a_ucValue);
+		break;
+	case g_ucPinTCK:
+		pfns->jtag_set_tck(a_ucValue);
+		break;
+	case g_ucPinTMS:
+		pfns->jtag_set_tms(a_ucValue);
+		break;
+	default:
+		printf("%s: requested unknown pin\n", __func__);
+	}
+}
+
+unsigned char readPort(void)
+{
+	return pfns->jtag_get_tdo();
+}
+
+void sclock(void)
+{
+	writePort(g_ucPinTCK, 0x01);
+	writePort(g_ucPinTCK, 0x00);
+}
+
+void calibration(void)
+{
+	/* Apply 2 pulses to TCK. */
+	writePort(g_ucPinTCK, 0x00);
+	writePort(g_ucPinTCK, 0x01);
+	writePort(g_ucPinTCK, 0x00);
+	writePort(g_ucPinTCK, 0x01);
+	writePort(g_ucPinTCK, 0x00);
+
+	ispVMDelay(0x8001);
+
+	/* Apply 2 pulses to TCK. */
+	writePort(g_ucPinTCK, 0x01);
+	writePort(g_ucPinTCK, 0x00);
+	writePort(g_ucPinTCK, 0x01);
+	writePort(g_ucPinTCK, 0x00);
+}
+
+/*
+ * GetByte
+ *
+ * Returns a byte to the caller. The returned byte depends on the
+ * g_usDataType register. If the HEAP_IN bit is set, then the byte
+ * is returned from the HEAP. If the LHEAP_IN bit is set, then
+ * the byte is returned from the intelligent buffer. Otherwise,
+ * the byte is returned directly from the VME file.
+ */
+unsigned char GetByte(void)
+{
+	unsigned char ucData;
+	unsigned int block_size = 4 * 1024;
+
+	if (g_usDataType & HEAP_IN) {
+
+		/*
+		 * Get data from repeat buffer.
+		 */
+
+		if (g_iHeapCounter > g_iHEAPSize) {
+
+			/*
+			 * Data over-run.
+			 */
+
+			return 0xFF;
+		}
+
+		ucData = g_pucHeapMemory[g_iHeapCounter++];
+	} else if (g_usDataType & LHEAP_IN) {
+
+		/*
+		 * Get data from intel buffer.
+		 */
+
+		if (g_usIntelDataIndex >= g_usIntelBufferSize) {
+			return 0xFF;
+		}
+
+		ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
+	} else {
+		if (read_bytes == bufsize) {
+			return 0xFF;
+		}
+		ucData = *fpga_image++;
+		read_bytes++;
+
+		if (!(read_bytes % block_size)) {
+			printf("Downloading FPGA %ld/%ld completed\r",
+				read_bytes,
+				bufsize);
+		}
+
+		if (expectedCRC != 0) {
+			ispVMCalculateCRC32(ucData);
+		}
+	}
+
+	return ucData;
+}
+
+signed char ispVM(void)
+{
+	char szFileVersion[9]      = { 0 };
+	signed char cRetCode         = 0;
+	signed char cIndex           = 0;
+	signed char cVersionIndex    = 0;
+	unsigned char ucReadByte     = 0;
+	unsigned short crc;
+
+	g_pucHeapMemory		= NULL;
+	g_iHeapCounter		= 0;
+	g_iHEAPSize		= 0;
+	g_usIntelDataIndex	= 0;
+	g_usIntelBufferSize	= 0;
+	g_usCalculatedCRC = 0;
+	expectedCRC   = 0;
+	ucReadByte = GetByte();
+	switch (ucReadByte) {
+	case FILE_CRC:
+		crc = (unsigned char)GetByte();
+		crc <<= 8;
+		crc |= GetByte();
+		expectedCRC = crc;
+
+		for (cIndex = 0; cIndex < 8; cIndex++)
+			szFileVersion[cIndex] = GetByte();
+
+		break;
+	default:
+		szFileVersion[0] = (signed char) ucReadByte;
+		for (cIndex = 1; cIndex < 8; cIndex++)
+			szFileVersion[cIndex] = GetByte();
+
+		break;
+	}
+
+	/*
+	 *
+	 * Compare the VME file version against the supported version.
+	 *
+	 */
+
+	for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0;
+		cVersionIndex++) {
+		for (cIndex = 0; cIndex < 8; cIndex++) {
+			if (szFileVersion[cIndex] !=
+				g_szSupportedVersions[cVersionIndex][cIndex]) {
+				cRetCode = VME_VERSION_FAILURE;
+				break;
+			}
+			cRetCode = 0;
+		}
+
+		if (cRetCode == 0) {
+			break;
+		}
+	}
+
+	if (cRetCode < 0) {
+		return VME_VERSION_FAILURE;
+	}
+
+	printf("VME file checked: starting downloading to FPGA\n");
+
+	ispVMStart();
+
+	cRetCode = ispVMCode();
+
+	ispVMEnd();
+	ispVMFreeMem();
+	puts("\n");
+
+	if (cRetCode == 0 && expectedCRC != 0 &&
+			(expectedCRC != g_usCalculatedCRC)) {
+		printf("Expected CRC:   0x%.4X\n", expectedCRC);
+		printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
+		return VME_CRC_FAILURE;
+	}
+	return cRetCode;
+}
+
+static int lattice_validate(Lattice_desc *desc, const char *fn)
+{
+	int ret_val = false;
+
+	if (desc) {
+		if ((desc->family > min_lattice_type) &&
+			(desc->family < max_lattice_type)) {
+			if ((desc->iface > min_lattice_iface_type) &&
+				(desc->iface < max_lattice_iface_type)) {
+				if (desc->size) {
+					ret_val = true;
+				} else {
+					printf("%s: NULL part size\n", fn);
+				}
+			} else {
+				printf("%s: Invalid Interface type, %d\n",
+					fn, desc->iface);
+			}
+		} else {
+			printf("%s: Invalid family type, %d\n",
+				fn, desc->family);
+		}
+	} else {
+		printf("%s: NULL descriptor!\n", fn);
+	}
+
+	return ret_val;
+}
+
+int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	if (!lattice_validate(desc, (char *)__func__)) {
+		printf("%s: Invalid device descriptor\n", __func__);
+	} else {
+		pfns = desc->iface_fns;
+
+		switch (desc->family) {
+		case Lattice_XP2:
+			fpga_image = buf;
+			read_bytes = 0;
+			bufsize = bsize;
+			debug("%s: Launching the Lattice ISPVME Loader:"
+				" addr %p size 0x%lx...\n",
+				__func__, fpga_image, bufsize);
+			ret_val = ispVM();
+			if (ret_val)
+				printf("%s: error %d downloading FPGA image\n",
+					__func__, ret_val);
+			else
+				puts("FPGA downloaded successfully\n");
+			break;
+		default:
+			printf("%s: Unsupported family type, %d\n",
+					__func__, desc->family);
+		}
+	}
+
+	return ret_val;
+}
+
+int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize)
+{
+	puts("Dump not supported for Lattice FPGA\n");
+
+	return FPGA_FAIL;
+
+}
+
+int lattice_info(Lattice_desc *desc)
+{
+	int ret_val = FPGA_FAIL;
+
+	if (lattice_validate(desc, (char *)__func__)) {
+		printf("Family:        \t");
+		switch (desc->family) {
+		case Lattice_XP2:
+			puts("XP2\n");
+			break;
+			/* Add new family types here */
+		default:
+			printf("Unknown family type, %d\n", desc->family);
+		}
+
+		puts("Interface type:\t");
+		switch (desc->iface) {
+		case lattice_jtag_mode:
+			puts("JTAG Mode\n");
+			break;
+			/* Add new interface types here */
+		default:
+			printf("Unsupported interface type, %d\n", desc->iface);
+		}
+
+		printf("Device Size:   \t%d bytes\n",
+				desc->size);
+
+		if (desc->iface_fns) {
+			printf("Device Function Table @ 0x%p\n",
+				desc->iface_fns);
+			switch (desc->family) {
+			case Lattice_XP2:
+				break;
+				/* Add new family types here */
+			default:
+				break;
+			}
+		} else {
+			puts("No Device Function Table.\n");
+		}
+
+		if (desc->desc)
+			printf("Model:         \t%s\n", desc->desc);
+
+		ret_val = FPGA_SUCCESS;
+	} else {
+		printf("%s: Invalid device descriptor\n", __func__);
+	}
+
+	return ret_val;
+}
diff --git a/marvell/uboot/drivers/fpga/spartan2.c b/marvell/uboot/drivers/fpga/spartan2.c
new file mode 100644
index 0000000..6eab1b5
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/spartan2.c
@@ -0,0 +1,449 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>		/* core U-Boot definitions */
+#include <spartan2.h>		/* Spartan-II device family */
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef	FPGA_DEBUG
+#define PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#undef CONFIG_SYS_FPGA_CHECK_BUSY
+#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
+
+/* Note: The assumption is that we cannot possibly run fast enough to
+ * overrun the device (the Slave Parallel mode can free run at 50MHz).
+ * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
+ * the board config file to slow things down.
+ */
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CONFIG_SYS_FPGA_WAIT
+#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
+#endif
+
+static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+/* static int Spartan2_sp_info(Xilinx_desc *desc ); */
+
+static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+/* static int Spartan2_ss_info(Xilinx_desc *desc ); */
+
+/* ------------------------------------------------------------------------- */
+/* Spartan-II Generic Implementation */
+int Spartan2_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+		ret_val = Spartan2_ss_load (desc, buf, bsize);
+		break;
+
+	case slave_parallel:
+		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+		ret_val = Spartan2_sp_load (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int Spartan2_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+		ret_val = Spartan2_ss_dump (desc, buf, bsize);
+		break;
+
+	case slave_parallel:
+		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+		ret_val = Spartan2_sp_dump (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int Spartan2_info( Xilinx_desc *desc )
+{
+	return FPGA_SUCCESS;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Spartan-II Slave Parallel Generic Implementation */
+
+static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"pre: 0x%p\n"
+				"pgm:\t0x%p\n"
+				"init:\t0x%p\n"
+				"err:\t0x%p\n"
+				"clk:\t0x%p\n"
+				"cs:\t0x%p\n"
+				"wr:\t0x%p\n"
+				"read data:\t0x%p\n"
+				"write data:\t0x%p\n"
+				"busy:\t0x%p\n"
+				"abort:\t0x%p\n",
+				"post:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
+				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
+				fn->abort, fn->post);
+
+		/*
+		 * This code is designed to emulate the "Express Style"
+		 * Continuous Data Loading in Slave Parallel Mode for
+		 * the Spartan-II Family.
+		 */
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...\n", cookie);
+#endif
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
+
+		ts = get_timer (0);		/* get current time */
+		/* Now wait for INIT and BUSY to go high */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to clear.\n");
+				(*fn->abort) (cookie);	/* abort the burn */
+				return FPGA_FAIL;
+			}
+		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
+
+		(*fn->wr) (true, true, cookie); /* Assert write, commit */
+		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+		/* Load the data */
+		while (bytecount < bsize) {
+			/* XXX - do we check for an Ctrl-C press in here ??? */
+			/* XXX - Check the error bit? */
+
+			(*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
+			ts = get_timer (0);	/* get current time */
+			while ((*fn->busy) (cookie)) {
+				/* XXX - we should have a check in here somewhere to
+				 * make sure we aren't busy forever... */
+
+				CONFIG_FPGA_DELAY ();
+				(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+				CONFIG_FPGA_DELAY ();
+				(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+					puts ("** Timeout waiting for BUSY to clear.\n");
+					(*fn->abort) (cookie);	/* abort the burn */
+					return FPGA_FAIL;
+				}
+			}
+#endif
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		CONFIG_FPGA_DELAY ();
+		(*fn->cs) (false, true, cookie);	/* Deassert the chip select */
+		(*fn->wr) (false, true, cookie);	/* Deassert the write pin */
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+
+		/* now check for done signal */
+		ts = get_timer (0);		/* get current time */
+		ret_val = FPGA_SUCCESS;
+		while ((*fn->done) (cookie) == FPGA_FAIL) {
+
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for DONE to clear.\n");
+				(*fn->abort) (cookie);	/* abort the burn */
+				ret_val = FPGA_FAIL;
+				break;
+			}
+		}
+
+		/*
+		 * Run the post configuration function if there is one.
+		 */
+		if (*fn->post)
+			(*fn->post) (cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		if (ret_val == FPGA_SUCCESS)
+			puts ("Done.\n");
+		else
+			puts ("Fail.\n");
+#endif
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
+
+	if (fn) {
+		unsigned char *data = (unsigned char *) buf;
+		size_t bytecount = 0;
+		int cookie = desc->cookie;	/* make a local copy */
+
+		printf ("Starting Dump of FPGA Device %d...\n", cookie);
+
+		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+		/* dump the data */
+		while (bytecount < bsize) {
+			/* XXX - do we check for an Ctrl-C press in here ??? */
+
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		(*fn->cs) (false, false, cookie);	/* Deassert the chip select */
+		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+		puts ("Done.\n");
+
+		/* XXX - checksum the data? */
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
+	int i;
+	unsigned char val;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"pgm:\t0x%p\n"
+				"init:\t0x%p\n"
+				"clk:\t0x%p\n"
+				"wr:\t0x%p\n"
+				"done:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
+				fn->clk, fn->wr, fn->done);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...\n", cookie);
+#endif
+
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
+
+		/* Wait for INIT state (init low)                            */
+		ts = get_timer (0);		/* get current time */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to start.\n");
+				return FPGA_FAIL;
+			}
+		} while (!(*fn->init) (cookie));
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
+
+		ts = get_timer (0);		/* get current time */
+		/* Now wait for INIT to go high */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to clear.\n");
+				return FPGA_FAIL;
+			}
+		} while ((*fn->init) (cookie));
+
+		/* Load the data */
+		while (bytecount < bsize) {
+
+			/* Xilinx detects an error if INIT goes low (active)
+			   while DONE is low (inactive) */
+			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
+				puts ("** CRC error during FPGA load.\n");
+				return (FPGA_FAIL);
+			}
+			val = data [bytecount ++];
+			i = 8;
+			do {
+				/* Deassert the clock */
+				(*fn->clk) (false, true, cookie);
+				CONFIG_FPGA_DELAY ();
+				/* Write data */
+				(*fn->wr) ((val & 0x80), true, cookie);
+				CONFIG_FPGA_DELAY ();
+				/* Assert the clock */
+				(*fn->clk) (true, true, cookie);
+				CONFIG_FPGA_DELAY ();
+				val <<= 1;
+				i --;
+			} while (i > 0);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		CONFIG_FPGA_DELAY ();
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+
+		/* now check for done signal */
+		ts = get_timer (0);		/* get current time */
+		ret_val = FPGA_SUCCESS;
+		(*fn->wr) (true, true, cookie);
+
+		while (! (*fn->done) (cookie)) {
+
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+			putc ('*');
+
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for DONE to clear.\n");
+				ret_val = FPGA_FAIL;
+				break;
+			}
+		}
+		putc ('\n');			/* terminate the dotted line */
+
+		/*
+		 * Run the post configuration function if there is one.
+		 */
+		if (*fn->post)
+			(*fn->post) (cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		if (ret_val == FPGA_SUCCESS)
+			puts ("Done.\n");
+		else
+			puts ("Fail.\n");
+#endif
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	/* Readback is only available through the Slave Parallel and         */
+	/* boundary-scan interfaces.                                         */
+	printf ("%s: Slave Serial Dumping is unavailable\n",
+			__FUNCTION__);
+	return FPGA_FAIL;
+}
diff --git a/marvell/uboot/drivers/fpga/spartan3.c b/marvell/uboot/drivers/fpga/spartan3.c
new file mode 100644
index 0000000..3edc5c2
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/spartan3.c
@@ -0,0 +1,467 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * Configuration support for Xilinx Spartan3 devices.  Based
+ * on spartan2.c (Rich Ireland, rireland@enterasys.com).
+ */
+
+#include <common.h>		/* core U-Boot definitions */
+#include <spartan3.h>		/* Spartan-II device family */
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef	FPGA_DEBUG
+#define PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#undef CONFIG_SYS_FPGA_CHECK_BUSY
+
+/* Note: The assumption is that we cannot possibly run fast enough to
+ * overrun the device (the Slave Parallel mode can free run at 50MHz).
+ * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
+ * the board config file to slow things down.
+ */
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CONFIG_SYS_FPGA_WAIT
+#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
+#endif
+
+static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Spartan3_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+/* static int Spartan3_sp_info(Xilinx_desc *desc ); */
+
+static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Spartan3_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+/* static int Spartan3_ss_info(Xilinx_desc *desc); */
+
+/* ------------------------------------------------------------------------- */
+/* Spartan-II Generic Implementation */
+int Spartan3_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+		ret_val = Spartan3_ss_load (desc, buf, bsize);
+		break;
+
+	case slave_parallel:
+		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+		ret_val = Spartan3_sp_load (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int Spartan3_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+		ret_val = Spartan3_ss_dump (desc, buf, bsize);
+		break;
+
+	case slave_parallel:
+		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+		ret_val = Spartan3_sp_dump (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+
+	return ret_val;
+}
+
+int Spartan3_info( Xilinx_desc *desc )
+{
+	return FPGA_SUCCESS;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Spartan-II Slave Parallel Generic Implementation */
+
+static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"pre: 0x%p\n"
+				"pgm:\t0x%p\n"
+				"init:\t0x%p\n"
+				"err:\t0x%p\n"
+				"clk:\t0x%p\n"
+				"cs:\t0x%p\n"
+				"wr:\t0x%p\n"
+				"read data:\t0x%p\n"
+				"write data:\t0x%p\n"
+				"busy:\t0x%p\n"
+				"abort:\t0x%p\n",
+				"post:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
+				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
+				fn->abort, fn->post);
+
+		/*
+		 * This code is designed to emulate the "Express Style"
+		 * Continuous Data Loading in Slave Parallel Mode for
+		 * the Spartan-II Family.
+		 */
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...\n", cookie);
+#endif
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
+
+		ts = get_timer (0);		/* get current time */
+		/* Now wait for INIT and BUSY to go high */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to clear.\n");
+				(*fn->abort) (cookie);	/* abort the burn */
+				return FPGA_FAIL;
+			}
+		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
+
+		(*fn->wr) (true, true, cookie); /* Assert write, commit */
+		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+		/* Load the data */
+		while (bytecount < bsize) {
+			/* XXX - do we check for an Ctrl-C press in here ??? */
+			/* XXX - Check the error bit? */
+
+			(*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
+			ts = get_timer (0);	/* get current time */
+			while ((*fn->busy) (cookie)) {
+				/* XXX - we should have a check in here somewhere to
+				 * make sure we aren't busy forever... */
+
+				CONFIG_FPGA_DELAY ();
+				(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+				CONFIG_FPGA_DELAY ();
+				(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+					puts ("** Timeout waiting for BUSY to clear.\n");
+					(*fn->abort) (cookie);	/* abort the burn */
+					return FPGA_FAIL;
+				}
+			}
+#endif
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		CONFIG_FPGA_DELAY ();
+		(*fn->cs) (false, true, cookie);	/* Deassert the chip select */
+		(*fn->wr) (false, true, cookie);	/* Deassert the write pin */
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+
+		/* now check for done signal */
+		ts = get_timer (0);		/* get current time */
+		ret_val = FPGA_SUCCESS;
+		while ((*fn->done) (cookie) == FPGA_FAIL) {
+			/* XXX - we should have a check in here somewhere to
+			 * make sure we aren't busy forever... */
+
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for DONE to clear.\n");
+				(*fn->abort) (cookie);	/* abort the burn */
+				ret_val = FPGA_FAIL;
+				break;
+			}
+		}
+
+		/*
+		 * Run the post configuration function if there is one.
+		 */
+		if (*fn->post)
+			(*fn->post) (cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		if (ret_val == FPGA_SUCCESS)
+			puts ("Done.\n");
+		else
+			puts ("Fail.\n");
+#endif
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int Spartan3_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns;
+
+	if (fn) {
+		unsigned char *data = (unsigned char *) buf;
+		size_t bytecount = 0;
+		int cookie = desc->cookie;	/* make a local copy */
+
+		printf ("Starting Dump of FPGA Device %d...\n", cookie);
+
+		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+		/* dump the data */
+		while (bytecount < bsize) {
+			/* XXX - do we check for an Ctrl-C press in here ??? */
+
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');		/* let them know we are alive */
+#endif
+		}
+
+		(*fn->cs) (false, false, cookie);	/* Deassert the chip select */
+		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+		puts ("Done.\n");
+
+		/* XXX - checksum the data? */
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume the worst */
+	Xilinx_Spartan3_Slave_Serial_fns *fn = desc->iface_fns;
+	int i;
+	unsigned char val;
+
+	PRINTF ("%s: start with interface functions @ 0x%p\n",
+			__FUNCTION__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;	/* make a local copy */
+		unsigned long ts;		/* timestamp */
+
+		PRINTF ("%s: Function Table:\n"
+				"ptr:\t0x%p\n"
+				"struct: 0x%p\n"
+				"pgm:\t0x%p\n"
+				"init:\t0x%p\n"
+				"clk:\t0x%p\n"
+				"wr:\t0x%p\n"
+				"done:\t0x%p\n\n",
+				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
+				fn->clk, fn->wr, fn->done);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Loading FPGA Device %d...\n", cookie);
+#endif
+
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/* Establish the initial state */
+		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
+
+		/* Wait for INIT state (init low)                            */
+		ts = get_timer (0);		/* get current time */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to start.\n");
+				if (*fn->abort)
+					(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+		} while (!(*fn->init) (cookie));
+
+		/* Get ready for the burn */
+		CONFIG_FPGA_DELAY ();
+		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
+
+		ts = get_timer (0);		/* get current time */
+		/* Now wait for INIT to go high */
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for INIT to clear.\n");
+				if (*fn->abort)
+					(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+		} while ((*fn->init) (cookie));
+
+		/* Load the data */
+		if(*fn->bwr)
+			(*fn->bwr) (data, bsize, true, cookie);
+		else {
+			while (bytecount < bsize) {
+
+				/* Xilinx detects an error if INIT goes low (active)
+				   while DONE is low (inactive) */
+				if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
+					puts ("** CRC error during FPGA load.\n");
+					if (*fn->abort)
+						(*fn->abort) (cookie);
+					return (FPGA_FAIL);
+				}
+				val = data [bytecount ++];
+				i = 8;
+				do {
+					/* Deassert the clock */
+					(*fn->clk) (false, true, cookie);
+					CONFIG_FPGA_DELAY ();
+					/* Write data */
+					(*fn->wr) ((val & 0x80), true, cookie);
+					CONFIG_FPGA_DELAY ();
+					/* Assert the clock */
+					(*fn->clk) (true, true, cookie);
+					CONFIG_FPGA_DELAY ();
+					val <<= 1;
+					i --;
+				} while (i > 0);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+				if (bytecount % (bsize / 40) == 0)
+					putc ('.');		/* let them know we are alive */
+#endif
+			}
+		}
+
+		CONFIG_FPGA_DELAY ();
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');			/* terminate the dotted line */
+#endif
+
+		/* now check for done signal */
+		ts = get_timer (0);		/* get current time */
+		ret_val = FPGA_SUCCESS;
+		(*fn->wr) (true, true, cookie);
+
+		while (! (*fn->done) (cookie)) {
+			/* XXX - we should have a check in here somewhere to
+			 * make sure we aren't busy forever... */
+
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
+
+			putc ('*');
+
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
+				puts ("** Timeout waiting for DONE to clear.\n");
+				ret_val = FPGA_FAIL;
+				break;
+			}
+		}
+		putc ('\n');			/* terminate the dotted line */
+
+		/*
+		 * Run the post configuration function if there is one.
+		 */
+		if (*fn->post)
+			(*fn->post) (cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		if (ret_val == FPGA_SUCCESS)
+			puts ("Done.\n");
+		else
+			puts ("Fail.\n");
+#endif
+
+	} else {
+		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+static int Spartan3_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	/* Readback is only available through the Slave Parallel and         */
+	/* boundary-scan interfaces.                                         */
+	printf ("%s: Slave Serial Dumping is unavailable\n",
+			__FUNCTION__);
+	return FPGA_FAIL;
+}
diff --git a/marvell/uboot/drivers/fpga/stratixII.c b/marvell/uboot/drivers/fpga/stratixII.c
new file mode 100644
index 0000000..820d016
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/stratixII.c
@@ -0,0 +1,190 @@
+/*
+ * (C) Copyright 2007
+ * Eran Liberty, Extricom , eran.liberty@gmail.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>		/* core U-Boot definitions */
+#include <altera.h>
+
+int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize,
+			   int isSerial, int isSecure);
+int StratixII_ps_fpp_dump (Altera_desc * desc, void *buf, size_t bsize);
+
+/****************************************************************/
+/* Stratix II Generic Implementation                            */
+int StratixII_load (Altera_desc * desc, void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 1, 0);
+		break;
+	case fast_passive_parallel:
+		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 0, 0);
+		break;
+	case fast_passive_parallel_security:
+		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 0, 1);
+		break;
+
+		/* Add new interface types here */
+	default:
+		printf ("%s: Unsupported interface type, %d\n", __FUNCTION__,
+			desc->iface);
+	}
+	return ret_val;
+}
+
+int StratixII_dump (Altera_desc * desc, void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case passive_serial:
+	case fast_passive_parallel:
+	case fast_passive_parallel_security:
+		ret_val = StratixII_ps_fpp_dump (desc, buf, bsize);
+		break;
+		/* Add new interface types here */
+	default:
+		printf ("%s: Unsupported interface type, %d\n", __FUNCTION__,
+			desc->iface);
+	}
+	return ret_val;
+}
+
+int StratixII_info (Altera_desc * desc)
+{
+	return FPGA_SUCCESS;
+}
+
+int StratixII_ps_fpp_dump (Altera_desc * desc, void *buf, size_t bsize)
+{
+	printf ("Stratix II Fast Passive Parallel dump is not implemented\n");
+	return FPGA_FAIL;
+}
+
+int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize,
+			   int isSerial, int isSecure)
+{
+	altera_board_specific_func *fns;
+	int cookie;
+	int ret_val = FPGA_FAIL;
+	int bytecount;
+	char *buff = buf;
+	int i;
+
+	if (!desc) {
+		printf ("%s(%d) Altera_desc missing\n", __FUNCTION__, __LINE__);
+		return FPGA_FAIL;
+	}
+	if (!buff) {
+		printf ("%s(%d) buffer is missing\n", __FUNCTION__, __LINE__);
+		return FPGA_FAIL;
+	}
+	if (!bsize) {
+		printf ("%s(%d) size is zero\n", __FUNCTION__, __LINE__);
+		return FPGA_FAIL;
+	}
+	if (!desc->iface_fns) {
+		printf
+		    ("%s(%d) Altera_desc function interface table is missing\n",
+		     __FUNCTION__, __LINE__);
+		return FPGA_FAIL;
+	}
+	fns = (altera_board_specific_func *) (desc->iface_fns);
+	cookie = desc->cookie;
+
+	if (!
+	    (fns->config && fns->status && fns->done && fns->data
+	     && fns->abort)) {
+		printf
+		    ("%s(%d) Missing some function in the function interface table\n",
+		     __FUNCTION__, __LINE__);
+		return FPGA_FAIL;
+	}
+
+	/* 1. give board specific a chance to do anything before we start */
+	if (fns->pre) {
+		if ((ret_val = fns->pre (cookie)) < 0) {
+			return ret_val;
+		}
+	}
+
+	/* from this point on we must fail gracfully by calling lower layer abort */
+
+	/* 2. Strat burn cycle by deasserting config for t_CFG and waiting t_CF2CK after reaserted */
+	fns->config (0, 1, cookie);
+	udelay (5);		/* nCONFIG low pulse width 2usec */
+	fns->config (1, 1, cookie);
+	udelay (100);		/* nCONFIG high to first rising edge on DCLK */
+
+	/* 3. Start the Data cycle with clk deasserted */
+	bytecount = 0;
+	fns->clk (0, 1, cookie);
+
+	printf ("loading to fpga    ");
+	while (bytecount < bsize) {
+		/* 3.1 check stratix has not signaled us an error */
+		if (fns->status (cookie) != 1) {
+			printf
+			    ("\n%s(%d) Stratix failed (byte transfered till failure 0x%x)\n",
+			     __FUNCTION__, __LINE__, bytecount);
+			fns->abort (cookie);
+			return FPGA_FAIL;
+		}
+		if (isSerial) {
+			int i;
+			uint8_t data = buff[bytecount++];
+			for (i = 0; i < 8; i++) {
+				/* 3.2(ps) put data on the bus */
+				fns->data ((data >> i) & 1, 1, cookie);
+
+				/* 3.3(ps) clock once */
+				fns->clk (1, 1, cookie);
+				fns->clk (0, 1, cookie);
+			}
+		} else {
+			/* 3.2(fpp) put data on the bus */
+			fns->data (buff[bytecount++], 1, cookie);
+
+			/* 3.3(fpp) clock once */
+			fns->clk (1, 1, cookie);
+			fns->clk (0, 1, cookie);
+
+			/* 3.4(fpp) for secure cycle push 3 more  clocks */
+			for (i = 0; isSecure && i < 3; i++) {
+				fns->clk (1, 1, cookie);
+				fns->clk (0, 1, cookie);
+			}
+		}
+
+		/* 3.5 while clk is deasserted it is safe to print some progress indication */
+		if ((bytecount % (bsize / 100)) == 0) {
+			printf ("\b\b\b%02d\%", bytecount * 100 / bsize);
+		}
+	}
+
+	/* 4. Set one last clock and check conf done signal */
+	fns->clk (1, 1, cookie);
+	udelay (100);
+	if (!fns->done (cookie)) {
+		printf (" error!.\n");
+		fns->abort (cookie);
+		return FPGA_FAIL;
+	} else {
+		printf ("\b\b\b done.\n");
+	}
+
+	/* 5. call lower layer post configuration */
+	if (fns->post) {
+		if ((ret_val = fns->post (cookie)) < 0) {
+			fns->abort (cookie);
+			return ret_val;
+		}
+	}
+
+	return FPGA_SUCCESS;
+}
diff --git a/marvell/uboot/drivers/fpga/virtex2.c b/marvell/uboot/drivers/fpga/virtex2.c
new file mode 100644
index 0000000..b5a895d
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/virtex2.c
@@ -0,0 +1,419 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * Configuration support for Xilinx Virtex2 devices.  Based
+ * on spartan2.c (Rich Ireland, rireland@enterasys.com).
+ */
+
+#include <common.h>
+#include <virtex2.h>
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+#ifdef	FPGA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * If the SelectMap interface can be overrun by the processor, define
+ * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
+ * file and add board-specific support for checking BUSY status. By default,
+ * assume that the SelectMap interface cannot be overrun.
+ */
+#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
+#undef CONFIG_SYS_FPGA_CHECK_BUSY
+#endif
+
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
+#define CONFIG_SYS_FPGA_PROG_FEEDBACK
+#endif
+
+/*
+ * Don't allow config cycle to be interrupted
+ */
+#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
+#undef CONFIG_SYS_FPGA_CHECK_CTRLC
+#endif
+
+/*
+ * Check for errors during configuration by default
+ */
+#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
+#define CONFIG_SYS_FPGA_CHECK_ERROR
+#endif
+
+/*
+ * The default timeout in mS for INIT_B to deassert after PROG_B has
+ * been deasserted. Per the latest Virtex II Handbook (page 347), the
+ * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
+ * data frame for the XC2V8000.  The XC2V8000 has 2860 data frames
+ * which yields 11.44 mS.  So let's make it bigger in order to handle
+ * an XC2V1000, if anyone can ever get ahold of one.
+ */
+#ifndef CONFIG_SYS_FPGA_WAIT_INIT
+#define CONFIG_SYS_FPGA_WAIT_INIT	CONFIG_SYS_HZ/2	/* 500 ms */
+#endif
+
+/*
+ * The default timeout for waiting for BUSY to deassert during configuration.
+ * This is normally not necessary since for most reasonable configuration
+ * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
+ */
+#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
+#define CONFIG_SYS_FPGA_WAIT_BUSY	CONFIG_SYS_HZ/200	/* 5 ms*/
+#endif
+
+/* Default timeout for waiting for FPGA to enter operational mode after
+ * configuration data has been written.
+ */
+#ifndef	CONFIG_SYS_FPGA_WAIT_CONFIG
+#define CONFIG_SYS_FPGA_WAIT_CONFIG	CONFIG_SYS_HZ/5	/* 200 ms */
+#endif
+
+static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Virtex2_ssm_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+
+static int Virtex2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize);
+static int Virtex2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
+
+int Virtex2_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+		ret_val = Virtex2_ss_load (desc, buf, bsize);
+		break;
+
+	case slave_selectmap:
+		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+		ret_val = Virtex2_ssm_load (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+	return ret_val;
+}
+
+int Virtex2_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+
+	switch (desc->iface) {
+	case slave_serial:
+		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+		ret_val = Virtex2_ss_dump (desc, buf, bsize);
+		break;
+
+	case slave_parallel:
+		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+		ret_val = Virtex2_ssm_dump (desc, buf, bsize);
+		break;
+
+	default:
+		printf ("%s: Unsupported interface type, %d\n",
+				__FUNCTION__, desc->iface);
+	}
+	return ret_val;
+}
+
+int Virtex2_info (Xilinx_desc * desc)
+{
+	return FPGA_SUCCESS;
+}
+
+/*
+ * Virtex-II Slave SelectMap configuration loader. Configuration via
+ * SelectMap is as follows:
+ * 1. Set the FPGA's PROG_B line low.
+ * 2. Set the FPGA's PROG_B line high.  Wait for INIT_B to go high.
+ * 3. Write data to the SelectMap port.  If INIT_B goes low at any time
+ *    this process, a configuration error (most likely CRC failure) has
+ *    ocurred.  At this point a status word may be read from the
+ *    SelectMap interface to determine the source of the problem (You
+ *    could, for instance, put this in your 'abort' function handler).
+ * 4. After all data has been written, test the state of the FPGA
+ *    INIT_B and DONE lines.  If both are high, configuration has
+ *    succeeded. Congratulations!
+ */
+static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+	Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
+
+	PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
+			__FUNCTION__, __LINE__, fn);
+
+	if (fn) {
+		size_t bytecount = 0;
+		unsigned char *data = (unsigned char *) buf;
+		int cookie = desc->cookie;
+		unsigned long ts;
+
+		/* Gotta split this one up (so the stack won't blow??) */
+		PRINTF ("%s:%d: Function Table:\n"
+				"  base   0x%p\n"
+				"  struct 0x%p\n"
+				"  pre    0x%p\n"
+				"  prog   0x%p\n"
+				"  init   0x%p\n"
+				"  error  0x%p\n",
+				__FUNCTION__, __LINE__,
+				&fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
+		PRINTF ("  clock  0x%p\n"
+				"  cs     0x%p\n"
+				"  write  0x%p\n"
+				"  rdata  0x%p\n"
+				"  wdata  0x%p\n"
+				"  busy   0x%p\n"
+				"  abort  0x%p\n"
+				"  post   0x%p\n\n",
+				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
+				fn->busy, fn->abort, fn->post);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		printf ("Initializing FPGA Device %d...\n", cookie);
+#endif
+		/*
+		 * Run the pre configuration function if there is one.
+		 */
+		if (*fn->pre) {
+			(*fn->pre) (cookie);
+		}
+
+		/*
+		 * Assert the program line.  The minimum pulse width for
+		 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
+		 * There is no maximum value for the pulse width.  Check to make
+		 * sure that INIT_B goes low after assertion of PROG_B
+		 */
+		(*fn->pgm) (true, true, cookie);
+		udelay (10);
+		ts = get_timer (0);
+		do {
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
+				printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
+						" to assert.\n", __FUNCTION__, __LINE__,
+						CONFIG_SYS_FPGA_WAIT_INIT);
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+		} while (!(*fn->init) (cookie));
+
+		(*fn->pgm) (false, true, cookie);
+		CONFIG_FPGA_DELAY ();
+		(*fn->clk) (true, true, cookie);
+
+		/*
+		 * Start a timer and wait for INIT_B to go high
+		 */
+		ts = get_timer (0);
+		do {
+			CONFIG_FPGA_DELAY ();
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
+				printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
+						" to deassert.\n", __FUNCTION__, __LINE__,
+						CONFIG_SYS_FPGA_WAIT_INIT);
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
+
+		(*fn->wr) (true, true, cookie);
+		(*fn->cs) (true, true, cookie);
+
+		udelay (10000);
+
+		/*
+		 * Load the data byte by byte
+		 */
+		while (bytecount < bsize) {
+#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
+			if (ctrlc ()) {
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+#endif
+
+			if ((*fn->done) (cookie) == FPGA_SUCCESS) {
+			    PRINTF ("%s:%d:done went active early, bytecount = %d\n",
+				    __FUNCTION__, __LINE__, bytecount);
+			    break;
+			}
+
+#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
+			if ((*fn->init) (cookie)) {
+				printf ("\n%s:%d:  ** Error: INIT asserted during"
+						" configuration\n", __FUNCTION__, __LINE__);
+				printf ("%d = buffer offset, %d = buffer size\n",
+					bytecount, bsize);
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+#endif
+
+			(*fn->wdata) (data[bytecount++], true, cookie);
+			CONFIG_FPGA_DELAY ();
+
+			/*
+			 * Cycle the clock pin
+			 */
+			(*fn->clk) (false, true, cookie);
+			CONFIG_FPGA_DELAY ();
+			(*fn->clk) (true, true, cookie);
+
+#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
+			ts = get_timer (0);
+			while ((*fn->busy) (cookie)) {
+				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
+					printf ("%s:%d: ** Timeout after %d ticks waiting for"
+							" BUSY to deassert\n",
+							__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
+					(*fn->abort) (cookie);
+					return FPGA_FAIL;
+				}
+			}
+#endif
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');
+#endif
+		}
+
+		/*
+		 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
+		 */
+		CONFIG_FPGA_DELAY ();
+		(*fn->cs) (false, true, cookie);
+		(*fn->wr) (false, true, cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');
+#endif
+
+		/*
+		 * Check for successful configuration.  FPGA INIT_B and DONE should
+		 * both be high upon successful configuration.
+		 */
+		ts = get_timer (0);
+		ret_val = FPGA_SUCCESS;
+		while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
+			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
+				printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
+						"assert and INIT to deassert\n",
+						__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
+				(*fn->abort) (cookie);
+				ret_val = FPGA_FAIL;
+				break;
+			}
+		}
+
+		if (ret_val == FPGA_SUCCESS) {
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			printf ("Initialization of FPGA device %d complete\n", cookie);
+#endif
+			/*
+			 * Run the post configuration function if there is one.
+			 */
+			if (*fn->post) {
+				(*fn->post) (cookie);
+			}
+		} else {
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			printf ("** Initialization of FPGA device %d FAILED\n",
+					cookie);
+#endif
+		}
+	} else {
+		printf ("%s:%d: NULL Interface function table!\n",
+				__FUNCTION__, __LINE__);
+	}
+	return ret_val;
+}
+
+/*
+ * Read the FPGA configuration data
+ */
+static int Virtex2_ssm_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;
+	Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
+
+	if (fn) {
+		unsigned char *data = (unsigned char *) buf;
+		size_t bytecount = 0;
+		int cookie = desc->cookie;
+
+		printf ("Starting Dump of FPGA Device %d...\n", cookie);
+
+		(*fn->cs) (true, true, cookie);
+		(*fn->clk) (true, true, cookie);
+
+		while (bytecount < bsize) {
+#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
+			if (ctrlc ()) {
+				(*fn->abort) (cookie);
+				return FPGA_FAIL;
+			}
+#endif
+			/*
+			 * Cycle the clock and read the data
+			 */
+			(*fn->clk) (false, true, cookie);
+			(*fn->clk) (true, true, cookie);
+			(*fn->rdata) (&(data[bytecount++]), cookie);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+			if (bytecount % (bsize / 40) == 0)
+				putc ('.');
+#endif
+		}
+
+		/*
+		 * Deassert CS_B and cycle the clock to deselect the device.
+		 */
+		(*fn->cs) (false, false, cookie);
+		(*fn->clk) (false, true, cookie);
+		(*fn->clk) (true, true, cookie);
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+		putc ('\n');
+#endif
+		puts ("Done.\n");
+	} else {
+		printf ("%s:%d: NULL Interface function table!\n",
+				__FUNCTION__, __LINE__);
+	}
+	return ret_val;
+}
+
+static int Virtex2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
+	return FPGA_FAIL;
+}
+
+static int Virtex2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
+	return FPGA_FAIL;
+}
+
+/* vim: set ts=4 tw=78: */
diff --git a/marvell/uboot/drivers/fpga/xilinx.c b/marvell/uboot/drivers/fpga/xilinx.c
new file mode 100644
index 0000000..2e0db53
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/xilinx.c
@@ -0,0 +1,394 @@
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ *  Xilinx FPGA support
+ */
+
+#include <common.h>
+#include <fpga.h>
+#include <virtex2.h>
+#include <spartan2.h>
+#include <spartan3.h>
+#include <zynqpl.h>
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef	FPGA_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Local Static Functions */
+static int xilinx_validate (Xilinx_desc * desc, char *fn);
+
+/* ------------------------------------------------------------------------- */
+
+int fpga_loadbitstream(int devnum, char *fpgadata, size_t size)
+{
+	unsigned int length;
+	unsigned int swapsize;
+	char buffer[80];
+	unsigned char *dataptr;
+	unsigned int i;
+	const fpga_desc *desc;
+	Xilinx_desc *xdesc;
+
+	dataptr = (unsigned char *)fpgadata;
+	/* Find out fpga_description */
+	desc = fpga_validate(devnum, dataptr, 0, (char *)__func__);
+	/* Assign xilinx device description */
+	xdesc = desc->devdesc;
+
+	/* skip the first bytes of the bitsteam, their meaning is unknown */
+	length = (*dataptr << 8) + *(dataptr + 1);
+	dataptr += 2;
+	dataptr += length;
+
+	/* get design name (identifier, length, string) */
+	length = (*dataptr << 8) + *(dataptr + 1);
+	dataptr += 2;
+	if (*dataptr++ != 0x61) {
+		debug("%s: Design name id not recognized in bitstream\n",
+		      __func__);
+		return FPGA_FAIL;
+	}
+
+	length = (*dataptr << 8) + *(dataptr + 1);
+	dataptr += 2;
+	for (i = 0; i < length; i++)
+		buffer[i] = *dataptr++;
+
+	printf("  design filename = \"%s\"\n", buffer);
+
+	/* get part number (identifier, length, string) */
+	if (*dataptr++ != 0x62) {
+		printf("%s: Part number id not recognized in bitstream\n",
+		       __func__);
+		return FPGA_FAIL;
+	}
+
+	length = (*dataptr << 8) + *(dataptr + 1);
+	dataptr += 2;
+	for (i = 0; i < length; i++)
+		buffer[i] = *dataptr++;
+
+	if (xdesc->name) {
+		i = strncmp(buffer, xdesc->name, strlen(xdesc->name));
+		if (i) {
+			printf("%s: Wrong bitstream ID for this device\n",
+			       __func__);
+			printf("%s: Bitstream ID %s, current device ID %d/%s\n",
+			       __func__, buffer, devnum, xdesc->name);
+			return FPGA_FAIL;
+		}
+	} else {
+		printf("%s: Please fill correct device ID to Xilinx_desc\n",
+		       __func__);
+	}
+	printf("  part number = \"%s\"\n", buffer);
+
+	/* get date (identifier, length, string) */
+	if (*dataptr++ != 0x63) {
+		printf("%s: Date identifier not recognized in bitstream\n",
+		       __func__);
+		return FPGA_FAIL;
+	}
+
+	length = (*dataptr << 8) + *(dataptr+1);
+	dataptr += 2;
+	for (i = 0; i < length; i++)
+		buffer[i] = *dataptr++;
+	printf("  date = \"%s\"\n", buffer);
+
+	/* get time (identifier, length, string) */
+	if (*dataptr++ != 0x64) {
+		printf("%s: Time identifier not recognized in bitstream\n",
+		       __func__);
+		return FPGA_FAIL;
+	}
+
+	length = (*dataptr << 8) + *(dataptr+1);
+	dataptr += 2;
+	for (i = 0; i < length; i++)
+		buffer[i] = *dataptr++;
+	printf("  time = \"%s\"\n", buffer);
+
+	/* get fpga data length (identifier, length) */
+	if (*dataptr++ != 0x65) {
+		printf("%s: Data length id not recognized in bitstream\n",
+		       __func__);
+		return FPGA_FAIL;
+	}
+	swapsize = ((unsigned int) *dataptr << 24) +
+		   ((unsigned int) *(dataptr + 1) << 16) +
+		   ((unsigned int) *(dataptr + 2) << 8) +
+		   ((unsigned int) *(dataptr + 3));
+	dataptr += 4;
+	printf("  bytes in bitstream = %d\n", swapsize);
+
+	return fpga_load(devnum, dataptr, swapsize);
+}
+
+int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume a failure */
+
+	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	} else
+		switch (desc->family) {
+		case Xilinx_Spartan2:
+#if defined(CONFIG_FPGA_SPARTAN2)
+			PRINTF ("%s: Launching the Spartan-II Loader...\n",
+					__FUNCTION__);
+			ret_val = Spartan2_load (desc, buf, bsize);
+#else
+			printf ("%s: No support for Spartan-II devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+		case Xilinx_Spartan3:
+#if defined(CONFIG_FPGA_SPARTAN3)
+			PRINTF ("%s: Launching the Spartan-III Loader...\n",
+					__FUNCTION__);
+			ret_val = Spartan3_load (desc, buf, bsize);
+#else
+			printf ("%s: No support for Spartan-III devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+		case Xilinx_Virtex2:
+#if defined(CONFIG_FPGA_VIRTEX2)
+			PRINTF ("%s: Launching the Virtex-II Loader...\n",
+					__FUNCTION__);
+			ret_val = Virtex2_load (desc, buf, bsize);
+#else
+			printf ("%s: No support for Virtex-II devices.\n",
+					__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",
+					__FUNCTION__, desc->family);
+		}
+
+	return ret_val;
+}
+
+int xilinx_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	int ret_val = FPGA_FAIL;	/* assume a failure */
+
+	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	} else
+		switch (desc->family) {
+		case Xilinx_Spartan2:
+#if defined(CONFIG_FPGA_SPARTAN2)
+			PRINTF ("%s: Launching the Spartan-II Reader...\n",
+					__FUNCTION__);
+			ret_val = Spartan2_dump (desc, buf, bsize);
+#else
+			printf ("%s: No support for Spartan-II devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+		case Xilinx_Spartan3:
+#if defined(CONFIG_FPGA_SPARTAN3)
+			PRINTF ("%s: Launching the Spartan-III Reader...\n",
+					__FUNCTION__);
+			ret_val = Spartan3_dump (desc, buf, bsize);
+#else
+			printf ("%s: No support for Spartan-III devices.\n",
+					__FUNCTION__);
+#endif
+			break;
+		case Xilinx_Virtex2:
+#if defined( CONFIG_FPGA_VIRTEX2)
+			PRINTF ("%s: Launching the Virtex-II Reader...\n",
+					__FUNCTION__);
+			ret_val = Virtex2_dump (desc, buf, bsize);
+#else
+			printf ("%s: No support for Virtex-II devices.\n",
+					__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",
+					__FUNCTION__, desc->family);
+		}
+
+	return ret_val;
+}
+
+int xilinx_info (Xilinx_desc * desc)
+{
+	int ret_val = FPGA_FAIL;
+
+	if (xilinx_validate (desc, (char *)__FUNCTION__)) {
+		printf ("Family:        \t");
+		switch (desc->family) {
+		case Xilinx_Spartan2:
+			printf ("Spartan-II\n");
+			break;
+		case Xilinx_Spartan3:
+			printf ("Spartan-III\n");
+			break;
+		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);
+		}
+
+		printf ("Interface type:\t");
+		switch (desc->iface) {
+		case slave_serial:
+			printf ("Slave Serial\n");
+			break;
+		case master_serial:	/* Not used */
+			printf ("Master Serial\n");
+			break;
+		case slave_parallel:
+			printf ("Slave Parallel\n");
+			break;
+		case jtag_mode:		/* Not used */
+			printf ("JTAG Mode\n");
+			break;
+		case slave_selectmap:
+			printf ("Slave SelectMap Mode\n");
+			break;
+		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);
+		}
+
+		printf ("Device Size:   \t%d bytes\n"
+				"Cookie:        \t0x%x (%d)\n",
+				desc->size, desc->cookie, desc->cookie);
+		if (desc->name)
+			printf("Device name:   \t%s\n", desc->name);
+
+		if (desc->iface_fns) {
+			printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
+			switch (desc->family) {
+			case Xilinx_Spartan2:
+#if defined(CONFIG_FPGA_SPARTAN2)
+				Spartan2_info (desc);
+#else
+				/* just in case */
+				printf ("%s: No support for Spartan-II devices.\n",
+						__FUNCTION__);
+#endif
+				break;
+			case Xilinx_Spartan3:
+#if defined(CONFIG_FPGA_SPARTAN3)
+				Spartan3_info (desc);
+#else
+				/* just in case */
+				printf ("%s: No support for Spartan-III devices.\n",
+						__FUNCTION__);
+#endif
+				break;
+			case Xilinx_Virtex2:
+#if defined(CONFIG_FPGA_VIRTEX2)
+				Virtex2_info (desc);
+#else
+				/* just in case */
+				printf ("%s: No support for Virtex-II devices.\n",
+						__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 */
+				;
+			}
+		} else
+			printf ("No Device Function Table.\n");
+
+		ret_val = FPGA_SUCCESS;
+	} else {
+		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+	}
+
+	return ret_val;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int xilinx_validate (Xilinx_desc * desc, char *fn)
+{
+	int ret_val = false;
+
+	if (desc) {
+		if ((desc->family > min_xilinx_type) &&
+			(desc->family < max_xilinx_type)) {
+			if ((desc->iface > min_xilinx_iface_type) &&
+				(desc->iface < max_xilinx_iface_type)) {
+				if (desc->size) {
+					ret_val = true;
+				} else
+					printf ("%s: NULL part size\n", fn);
+			} else
+				printf ("%s: Invalid Interface type, %d\n",
+						fn, desc->iface);
+		} else
+			printf ("%s: Invalid family type, %d\n", fn, desc->family);
+	} else
+		printf ("%s: NULL descriptor!\n", fn);
+
+	return ret_val;
+}
diff --git a/marvell/uboot/drivers/fpga/zynqpl.c b/marvell/uboot/drivers/fpga/zynqpl.c
new file mode 100644
index 0000000..1effbad
--- /dev/null
+++ b/marvell/uboot/drivers/fpga/zynqpl.c
@@ -0,0 +1,354 @@
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2012
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <zynqpl.h>
+#include <asm/sizes.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_PCAP_LPBK		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 * 4) /* 4 s */
+#endif
+
+int zynq_info(Xilinx_desc *desc)
+{
+	return FPGA_SUCCESS;
+}
+
+#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,
+	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])) {
+			pattern = __swab32(pattern);
+			swap = SWAP_DONE;
+			debug("%s: data swapped - let's swap\n", __func__);
+		}
+
+		debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i,
+		      (u32)&test[i], pattern, bin_format[i]);
+		if (pattern != bin_format[i]) {
+			debug("%s: Bitstream is not recognized\n", __func__);
+			return 0;
+		}
+	}
+	debug("%s: Found bitstream header at %x %s swapinng\n", __func__,
+	      (u32)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/%x\n", __func__, word, p, (u32)&buf[p]);
+
+		/* Find the first bitstream dummy word */
+		if (word == DUMMY_WORD) {
+			debug("%s: Found dummy word at position %x/%x\n",
+			      __func__, p, (u32)&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 0;
+	}
+	return 0;
+}
+
+
+int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	unsigned long ts; /* Timestamp */
+	u32 partialbit = 0;
+	u32 i, control, isr_status, status, swap, diff;
+	u32 *buf_start;
+
+	/* Detect if we are going working with partial or full bitstream */
+	if (bsize != desc->size) {
+		printf("%s: Working with partial bitstream\n", __func__);
+		partialbit = 1;
+	}
+
+	buf_start = check_data((u8 *)buf, bsize, &swap);
+	if (!buf_start)
+		return FPGA_FAIL;
+
+	/* Check if data is postpone from start */
+	diff = (u32)buf_start - (u32)buf;
+	if (diff) {
+		printf("%s: Bitstream is not validated yet (diff %x)\n",
+		       __func__, diff);
+		return FPGA_FAIL;
+	}
+
+	if ((u32)buf < SZ_1M) {
+		printf("%s: Bitstream has to be placed up to 1MB (%x)\n",
+		       __func__, (u32)buf);
+		return FPGA_FAIL;
+	}
+
+	if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) {
+		u32 *new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN);
+
+		printf("%s: Align buffer at %x to %x(swap %d)\n", __func__,
+		       (u32)buf_start, (u32)new_buf, swap);
+
+		for (i = 0; i < (bsize/4); i++)
+			new_buf[i] = load_word(&buf_start[i], swap);
+
+		swap = SWAP_DONE;
+		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 < (bsize/4); i++)
+			new_buf[i] = load_word(&buf_start[i], swap);
+
+		swap = SWAP_DONE;
+	}
+
+	/* Clear loopback bit */
+	clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
+
+	if (!partialbit) {
+		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) {
+				printf("%s: Timeout wait for INIT to clear\n",
+				       __func__);
+				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) {
+				printf("%s: Timeout wait for INIT to set\n",
+				       __func__);
+				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("%s: Fatal errors in PCAP 0x%X\n", __func__, 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("%s: Status = 0x%08X\n", __func__, status);
+
+	if (status & DEVCFG_STATUS_DMA_CMD_Q_F) {
+		debug("%s: Error: device busy\n", __func__);
+		return FPGA_FAIL;
+	}
+
+	debug("%s: Device ready\n", __func__);
+
+	if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) {
+		if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) {
+			/* Error state, transfer cannot occur */
+			debug("%s: ISR indicates error\n", __func__);
+			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("%s: Source = 0x%08X\n", __func__, (u32)buf);
+	debug("%s: Size = %zu\n", __func__, bsize);
+
+	/* flush(clean & invalidate) d-cache range buf */
+	flush_dcache_range((u32)buf, (u32)buf +
+			   roundup(bsize, ARCH_DMA_MINALIGN));
+
+	/* 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("%s: Error: isr = 0x%08X\n", __func__,
+			      isr_status);
+			debug("%s: Write count = 0x%08X\n", __func__,
+			      readl(&devcfg_base->write_count));
+			debug("%s: Read count = 0x%08X\n", __func__,
+			      readl(&devcfg_base->read_count));
+
+			return FPGA_FAIL;
+		}
+		if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
+			printf("%s: Timeout wait for DMA to complete\n",
+			       __func__);
+			return FPGA_FAIL;
+		}
+		isr_status = readl(&devcfg_base->int_sts);
+	}
+
+	debug("%s: DMA transfer is done\n", __func__);
+
+	/* Check FPGA configuration completion */
+	ts = get_timer(0);
+	while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
+		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+			printf("%s: Timeout wait for FPGA to config\n",
+			       __func__);
+			return FPGA_FAIL;
+		}
+		isr_status = readl(&devcfg_base->int_sts);
+	}
+
+	debug("%s: FPGA config done\n", __func__);
+
+	/* Clear out the DMA status */
+	writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
+
+	if (!partialbit)
+		zynq_slcr_devcfg_enable();
+
+	return FPGA_SUCCESS;
+}
+
+int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
+{
+	return FPGA_FAIL;
+}