aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/fpga
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/fpga
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/fpga')
-rw-r--r--roms/u-boot/drivers/fpga/ACEX1K.c250
-rw-r--r--roms/u-boot/drivers/fpga/Kconfig88
-rw-r--r--roms/u-boot/drivers/fpga/Makefile25
-rw-r--r--roms/u-boot/drivers/fpga/altera.c183
-rw-r--r--roms/u-boot/drivers/fpga/cyclon2.c206
-rw-r--r--roms/u-boot/drivers/fpga/fpga.c358
-rw-r--r--roms/u-boot/drivers/fpga/intel_sdm_mb.c427
-rw-r--r--roms/u-boot/drivers/fpga/ivm_core.c3150
-rw-r--r--roms/u-boot/drivers/fpga/lattice.c381
-rw-r--r--roms/u-boot/drivers/fpga/socfpga.c72
-rw-r--r--roms/u-boot/drivers/fpga/socfpga_arria10.c949
-rw-r--r--roms/u-boot/drivers/fpga/socfpga_gen5.c247
-rw-r--r--roms/u-boot/drivers/fpga/spartan2.c455
-rw-r--r--roms/u-boot/drivers/fpga/spartan3.c473
-rw-r--r--roms/u-boot/drivers/fpga/stratixII.c190
-rw-r--r--roms/u-boot/drivers/fpga/stratixv.c104
-rw-r--r--roms/u-boot/drivers/fpga/versalpl.c55
-rw-r--r--roms/u-boot/drivers/fpga/virtex2.c528
-rw-r--r--roms/u-boot/drivers/fpga/xilinx.c318
-rw-r--r--roms/u-boot/drivers/fpga/zynqmppl.c313
-rw-r--r--roms/u-boot/drivers/fpga/zynqpl.c576
21 files changed, 9348 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/fpga/ACEX1K.c b/roms/u-boot/drivers/fpga/ACEX1K.c
new file mode 100644
index 000000000..aca8049c5
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/ACEX1K.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+#include <common.h> /* core U-Boot definitions */
+#include <console.h>
+#include <ACEX1K.h> /* ACEX device family */
+#include <linux/delay.h>
+
+/* 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/roms/u-boot/drivers/fpga/Kconfig b/roms/u-boot/drivers/fpga/Kconfig
new file mode 100644
index 000000000..dc0b3dd31
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/Kconfig
@@ -0,0 +1,88 @@
+menu "FPGA support"
+
+config FPGA
+ bool
+
+config FPGA_ALTERA
+ bool "Enable Altera FPGA drivers"
+ select FPGA
+ help
+ Say Y here to enable the Altera FPGA driver
+
+ This provides basic infrastructure to support Altera FPGA devices.
+ Enable Altera FPGA specific functions which includes bitstream
+ (in BIT format), fpga and device validation.
+
+config FPGA_SOCFPGA
+ bool "Enable Gen5 and Arria10 common FPGA drivers"
+ select FPGA_ALTERA
+ help
+ Say Y here to enable the Gen5 and Arria10 common FPGA driver
+
+ This provides common functionality for Gen5 and Arria10 devices.
+
+config FPGA_CYCLON2
+ bool "Enable Altera FPGA driver for Cyclone II"
+ depends on FPGA_ALTERA
+ help
+ Say Y here to enable the Altera Cyclone II FPGA specific driver
+
+ This provides common functionality for Altera Cyclone II devices.
+ Enable FPGA driver for loading bitstream in BIT and BIN format
+ on Altera Cyclone II device.
+
+config FPGA_INTEL_SDM_MAILBOX
+ bool "Enable Intel FPGA Full Reconfiguration SDM Mailbox driver"
+ depends on TARGET_SOCFPGA_SOC64
+ select FPGA_ALTERA
+ help
+ Say Y here to enable the Intel FPGA Full Reconfig SDM Mailbox driver
+
+ This provides common functionality for Intel FPGA devices.
+ Enable FPGA driver for writing full bitstream into Intel FPGA
+ devices through SDM (Secure Device Manager) Mailbox.
+
+config FPGA_XILINX
+ bool "Enable Xilinx FPGA drivers"
+ select FPGA
+ help
+ Enable Xilinx FPGA specific functions which includes bitstream
+ (in BIT format), fpga and device validation.
+
+config FPGA_ZYNQMPPL
+ bool "Enable Xilinx FPGA driver for ZynqMP"
+ depends on FPGA_XILINX
+ help
+ Enable FPGA driver for loading bitstream in BIT and BIN format
+ on Xilinx Zynq UltraScale+ (ZynqMP) device.
+
+config FPGA_VERSALPL
+ bool "Enable Xilinx FPGA driver for Versal"
+ depends on FPGA_XILINX
+ help
+ Enable FPGA driver for loading bitstream in PDI format on Xilinx
+ Versal device. PDI is a new programmable device image format for
+ Versal. The bitstream will only be generated as PDI for Versal
+ platform.
+
+config FPGA_SPARTAN3
+ bool "Enable Spartan3 FPGA driver"
+ depends on FPGA_XILINX
+ help
+ Enable Spartan3 FPGA driver for loading in BIT format.
+
+config FPGA_VIRTEX2
+ bool "Enable Xilinx Virtex-II and later FPGA driver"
+ depends on FPGA_XILINX
+ help
+ Enable Virtex-II FPGA driver for loading in BIT format. This driver
+ also supports many newer Xilinx FPGA families.
+
+config FPGA_ZYNQPL
+ bool "Enable Xilinx FPGA for Zynq"
+ depends on ARCH_ZYNQ
+ help
+ Enable FPGA driver for loading bitstream in BIT and BIN format
+ on Xilinx Zynq devices.
+
+endmenu
diff --git a/roms/u-boot/drivers/fpga/Makefile b/roms/u-boot/drivers/fpga/Makefile
new file mode 100644
index 000000000..83243fb10
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/Makefile
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+obj-y += fpga.o
+obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
+obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
+obj-$(CONFIG_FPGA_VERSALPL) += versalpl.o
+obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
+obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
+obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o
+obj-$(CONFIG_FPGA_XILINX) += xilinx.o
+obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o
+ifdef CONFIG_FPGA_ALTERA
+obj-y += altera.o
+obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
+obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
+obj-$(CONFIG_FPGA_INTEL_SDM_MAILBOX) += intel_sdm_mb.o
+obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
+obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
+obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += socfpga_gen5.o
+obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += socfpga_arria10.o
+endif
diff --git a/roms/u-boot/drivers/fpga/altera.c b/roms/u-boot/drivers/fpga/altera.c
new file mode 100644
index 000000000..10c0475d2
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/altera.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+/*
+ * Altera FPGA support
+ */
+#include <common.h>
+#include <errno.h>
+#include <ACEX1K.h>
+#include <log.h>
+#include <stratixII.h>
+
+/* Define FPGA_DEBUG to 1 to get debug printf's */
+#define FPGA_DEBUG 0
+
+static const struct altera_fpga {
+ enum altera_family family;
+ const char *name;
+ int (*load)(Altera_desc *, const void *, size_t);
+ int (*dump)(Altera_desc *, const void *, size_t);
+ int (*info)(Altera_desc *);
+} altera_fpga[] = {
+#if defined(CONFIG_FPGA_ACEX1K)
+ { Altera_ACEX1K, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info },
+ { Altera_CYC2, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info },
+#elif defined(CONFIG_FPGA_CYCLON2)
+ { Altera_ACEX1K, "CycloneII", CYC2_load, CYC2_dump, CYC2_info },
+ { Altera_CYC2, "CycloneII", CYC2_load, CYC2_dump, CYC2_info },
+#endif
+#if defined(CONFIG_FPGA_STRATIX_II)
+ { Altera_StratixII, "StratixII", StratixII_load,
+ StratixII_dump, StratixII_info },
+#endif
+#if defined(CONFIG_FPGA_STRATIX_V)
+ { Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
+#endif
+#if defined(CONFIG_FPGA_SOCFPGA)
+ { Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
+#endif
+#if defined(CONFIG_FPGA_INTEL_SDM_MAILBOX)
+ { Intel_FPGA_SDM_Mailbox, "Intel SDM Mailbox", intel_sdm_mb_load, NULL,
+ NULL },
+#endif
+};
+
+static int altera_validate(Altera_desc *desc, const char *fn)
+{
+ if (!desc) {
+ printf("%s: NULL descriptor!\n", fn);
+ return -EINVAL;
+ }
+
+ if ((desc->family < min_altera_type) ||
+ (desc->family > max_altera_type)) {
+ printf("%s: Invalid family type, %d\n", fn, desc->family);
+ return -EINVAL;
+ }
+
+ if ((desc->iface < min_altera_iface_type) ||
+ (desc->iface > max_altera_iface_type)) {
+ printf("%s: Invalid Interface type, %d\n", fn, desc->iface);
+ return -EINVAL;
+ }
+
+ if (!desc->size) {
+ printf("%s: NULL part size\n", fn);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct altera_fpga *
+altera_desc_to_fpga(Altera_desc *desc, const char *fn)
+{
+ int i;
+
+ if (altera_validate(desc, fn)) {
+ printf("%s: Invalid device descriptor\n", fn);
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(altera_fpga); i++) {
+ if (desc->family == altera_fpga[i].family)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(altera_fpga)) {
+ printf("%s: Unsupported family type, %d\n", fn, desc->family);
+ return NULL;
+ }
+
+ return &altera_fpga[i];
+}
+
+int altera_load(Altera_desc *desc, const void *buf, size_t bsize)
+{
+ const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
+
+ if (!fpga)
+ return FPGA_FAIL;
+
+ debug_cond(FPGA_DEBUG, "%s: Launching the %s Loader...\n",
+ __func__, fpga->name);
+ if (fpga->load)
+ return fpga->load(desc, buf, bsize);
+ return 0;
+}
+
+int altera_dump(Altera_desc *desc, const void *buf, size_t bsize)
+{
+ const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
+
+ if (!fpga)
+ return FPGA_FAIL;
+
+ debug_cond(FPGA_DEBUG, "%s: Launching the %s Reader...\n",
+ __func__, fpga->name);
+ if (fpga->dump)
+ return fpga->dump(desc, buf, bsize);
+ return 0;
+}
+
+int altera_info(Altera_desc *desc)
+{
+ const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
+
+ if (!fpga)
+ return FPGA_FAIL;
+
+ printf("Family: \t%s\n", fpga->name);
+
+ 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;
+ case secure_device_manager_mailbox:
+ puts("Secure Device Manager (SDM) Mailbox\n");
+ break;
+ /* Add new interface types here */
+ default:
+ printf("Unsupported interface type, %d\n", desc->iface);
+ }
+
+ printf("Device Size: \t%zd 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);
+ if (fpga->info)
+ fpga->info(desc);
+ } else {
+ printf("No Device Function Table.\n");
+ }
+
+ return FPGA_SUCCESS;
+}
diff --git a/roms/u-boot/drivers/fpga/cyclon2.c b/roms/u-boot/drivers/fpga/cyclon2.c
new file mode 100644
index 000000000..3b008facb
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/cyclon2.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2006
+ * Heiko Schocher, hs@denx.de
+ * Based on ACE1XK.c
+ */
+
+#include <common.h> /* core U-Boot definitions */
+#include <altera.h>
+#include <ACEX1K.h> /* ACEX device family */
+#include <linux/delay.h>
+
+/* 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", __func__);
+ 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",
+ __func__);
+ ret_val = CYC2_ps_load(desc, buf, bsize);
+ break;
+
+ /* Add new interface types here */
+
+ default:
+ printf("%s: Unsupported interface type, %d\n",
+ __func__, 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", __func__);
+ ret_val = CYC2_ps_dump(desc, buf, bsize);
+ break;
+
+ /* Add new interface types here */
+
+ default:
+ printf("%s: Unsupported interface type, %d\n",
+ __func__, 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",
+ __func__, 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",
+ __func__, &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
+
+ /*
+ * Run the post configuration function if there is one.
+ */
+ if (*fn->post)
+ (*fn->post) (cookie);
+ } else {
+ printf("%s: NULL Interface function table!\n", __func__);
+ }
+
+ 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", __func__);
+ return FPGA_FAIL;
+}
diff --git a/roms/u-boot/drivers/fpga/fpga.c b/roms/u-boot/drivers/fpga/fpga.c
new file mode 100644
index 000000000..fe3dfa123
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/fpga.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+/* Generic FPGA support */
+#include <common.h> /* core U-Boot definitions */
+#include <init.h>
+#include <log.h>
+#include <xilinx.h> /* xilinx specific definitions */
+#include <altera.h> /* altera specific definitions */
+#include <lattice.h>
+#include <dm/device_compat.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 support!\n");
+}
+
+
+/* fpga_get_desc
+ * map a device number to a descriptor
+ */
+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;
+}
+
+/*
+ * fpga_init is usually called from misc_init_r() and MUST be called
+ * before any of the other fpga functions are used.
+ */
+void fpga_init(void)
+{
+ 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 (!desc) {
+ printf("%s: NULL device descriptor\n", __func__);
+ return devnum;
+ }
+
+ if (next_desc < 0) {
+ printf("%s: FPGA support not initialized!\n", __func__);
+ } else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) {
+ 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: Unsupported FPGA type %d\n", __func__, devtype);
+ }
+
+ return devnum;
+}
+
+/*
+ * Return 1 if the fpga data is partial.
+ * This is only required for fpga drivers that support bitstream_type.
+ */
+int __weak fpga_is_partial_data(int devnum, size_t img_len)
+{
+ return 0;
+}
+
+/*
+ * Convert bitstream data and load into the fpga
+ */
+int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
+ bitstream_type bstype)
+{
+ printf("Bitstream support not implemented for this FPGA device\n");
+ return FPGA_FAIL;
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+int fpga_fsload(int devnum, const void *buf, size_t size,
+ fpga_fs_info *fpga_fsinfo)
+{
+ int ret_val = FPGA_FAIL; /* assume failure */
+ const fpga_desc *desc = fpga_validate(devnum, buf, size,
+ (char *)__func__);
+
+ if (desc) {
+ switch (desc->devtype) {
+ case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+ ret_val = xilinx_loadfs(desc->devdesc, buf, size,
+ fpga_fsinfo);
+#else
+ fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+ break;
+ default:
+ printf("%s: Invalid or unsupported device type %d\n",
+ __func__, desc->devtype);
+ }
+ }
+
+ return ret_val;
+}
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+int fpga_loads(int devnum, const void *buf, size_t size,
+ struct fpga_secure_info *fpga_sec_info)
+{
+ int ret_val = FPGA_FAIL;
+
+ const fpga_desc *desc = fpga_validate(devnum, buf, size,
+ (char *)__func__);
+
+ if (desc) {
+ switch (desc->devtype) {
+ case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+ ret_val = xilinx_loads(desc->devdesc, buf, size,
+ fpga_sec_info);
+#else
+ fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+ break;
+ default:
+ printf("%s: Invalid or unsupported device type %d\n",
+ __func__, desc->devtype);
+ }
+ }
+
+ return ret_val;
+}
+#endif
+
+/*
+ * Generic multiplexing code
+ */
+int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype)
+{
+ 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,
+ bstype);
+#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/roms/u-boot/drivers/fpga/intel_sdm_mb.c b/roms/u-boot/drivers/fpga/intel_sdm_mb.c
new file mode 100644
index 000000000..f5fd9a14c
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/intel_sdm_mb.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <log.h>
+#include <watchdog.h>
+#include <asm/arch/mailbox_s10.h>
+#include <asm/arch/smc_api.h>
+#include <linux/delay.h>
+#include <linux/intel-smc.h>
+
+#define RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS 60000
+#define RECONFIG_STATUS_INTERVAL_DELAY_US 1000000
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF)
+
+#define BITSTREAM_CHUNK_SIZE 0xFFFF0
+#define RECONFIG_STATUS_POLL_RETRY_MAX 100
+
+/*
+ * Polling the FPGA configuration status.
+ * Return 0 for success, non-zero for error.
+ */
+static int reconfig_status_polling_resp(void)
+{
+ int ret;
+ unsigned long start = get_timer(0);
+
+ while (1) {
+ ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, NULL, 0,
+ NULL, 0);
+
+ if (!ret)
+ return 0; /* configuration success */
+
+ if (ret != INTEL_SIP_SMC_STATUS_BUSY)
+ return ret;
+
+ if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS)
+ return -ETIMEDOUT; /* time out */
+
+ puts(".");
+ udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+ WATCHDOG_RESET();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int send_bitstream(const void *rbf_data, size_t rbf_size)
+{
+ int i;
+ u64 res_buf[3];
+ u64 args[2];
+ u32 xfer_count = 0;
+ int ret, wr_ret = 0, retry = 0;
+ size_t buf_size = (rbf_size > BITSTREAM_CHUNK_SIZE) ?
+ BITSTREAM_CHUNK_SIZE : rbf_size;
+
+ while (rbf_size || xfer_count) {
+ if (!wr_ret && rbf_size) {
+ args[0] = (u64)rbf_data;
+ args[1] = buf_size;
+ wr_ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_WRITE,
+ args, 2, NULL, 0);
+
+ debug("wr_ret = %d, rbf_data = %p, buf_size = %08lx\n",
+ wr_ret, rbf_data, buf_size);
+
+ if (wr_ret)
+ continue;
+
+ rbf_size -= buf_size;
+ rbf_data += buf_size;
+
+ if (buf_size >= rbf_size)
+ buf_size = rbf_size;
+
+ xfer_count++;
+ puts(".");
+ } else {
+ ret = invoke_smc(
+ INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE,
+ NULL, 0, res_buf, ARRAY_SIZE(res_buf));
+ if (!ret) {
+ for (i = 0; i < ARRAY_SIZE(res_buf); i++) {
+ if (!res_buf[i])
+ break;
+ xfer_count--;
+ wr_ret = 0;
+ retry = 0;
+ }
+ } else if (ret !=
+ INTEL_SIP_SMC_STATUS_BUSY)
+ return ret;
+ else if (!xfer_count)
+ return INTEL_SIP_SMC_STATUS_ERROR;
+
+ if (++retry >= RECONFIG_STATUS_POLL_RETRY_MAX)
+ return -ETIMEDOUT;
+
+ udelay(20000);
+ }
+ WATCHDOG_RESET();
+ }
+
+ return 0;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for success, non-zero for error.
+ */
+int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ int ret;
+ u64 arg = 1;
+
+ debug("Invoking FPGA_CONFIG_START...\n");
+
+ ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0);
+
+ if (ret) {
+ puts("Failure in RECONFIG mailbox command!\n");
+ return ret;
+ }
+
+ ret = send_bitstream(rbf_data, rbf_size);
+ if (ret) {
+ puts("Error sending bitstream!\n");
+ return ret;
+ }
+
+ /* Make sure we don't send MBOX_RECONFIG_STATUS too fast */
+ udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+
+ debug("Polling with MBOX_RECONFIG_STATUS...\n");
+ ret = reconfig_status_polling_resp();
+ if (ret) {
+ puts("FPGA reconfiguration failed!");
+ return ret;
+ }
+
+ puts("FPGA reconfiguration OK!\n");
+
+ return ret;
+}
+
+#else
+
+static const struct mbox_cfgstat_state {
+ int err_no;
+ const char *error_name;
+} mbox_cfgstat_state[] = {
+ {MBOX_CFGSTAT_STATE_IDLE, "FPGA in idle mode."},
+ {MBOX_CFGSTAT_STATE_CONFIG, "FPGA in config mode."},
+ {MBOX_CFGSTAT_STATE_FAILACK, "Acknowledgment failed!"},
+ {MBOX_CFGSTAT_STATE_ERROR_INVALID, "Invalid bitstream!"},
+ {MBOX_CFGSTAT_STATE_ERROR_CORRUPT, "Corrupted bitstream!"},
+ {MBOX_CFGSTAT_STATE_ERROR_AUTH, "Authentication failed!"},
+ {MBOX_CFGSTAT_STATE_ERROR_CORE_IO, "I/O error!"},
+ {MBOX_CFGSTAT_STATE_ERROR_HARDWARE, "Hardware error!"},
+ {MBOX_CFGSTAT_STATE_ERROR_FAKE, "Fake error!"},
+ {MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO, "Error in boot info!"},
+ {MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR, "Error in QSPI!"},
+ {MBOX_RESP_ERROR, "Mailbox general error!"},
+ {-ETIMEDOUT, "I/O timeout error"},
+ {-1, "Unknown error!"}
+};
+
+#define MBOX_CFGSTAT_MAX ARRAY_SIZE(mbox_cfgstat_state)
+
+static const char *mbox_cfgstat_to_str(int err)
+{
+ int i;
+
+ for (i = 0; i < MBOX_CFGSTAT_MAX - 1; i++) {
+ if (mbox_cfgstat_state[i].err_no == err)
+ return mbox_cfgstat_state[i].error_name;
+ }
+
+ return mbox_cfgstat_state[MBOX_CFGSTAT_MAX - 1].error_name;
+}
+
+/*
+ * Add the ongoing transaction's command ID into pending list and return
+ * the command ID for next transfer.
+ */
+static u8 add_transfer(u32 *xfer_pending_list, size_t list_size, u8 id)
+{
+ int i;
+
+ for (i = 0; i < list_size; i++) {
+ if (xfer_pending_list[i])
+ continue;
+ xfer_pending_list[i] = id;
+ debug("ID(%d) added to transaction pending list\n", id);
+ /*
+ * Increment command ID for next transaction.
+ * Valid command ID (4 bits) is from 1 to 15.
+ */
+ id = (id % 15) + 1;
+ break;
+ }
+
+ return id;
+}
+
+/*
+ * Check whether response ID match the command ID in the transfer
+ * pending list. If a match is found in the transfer pending list,
+ * it clears the transfer pending list and return the matched
+ * command ID.
+ */
+static int get_and_clr_transfer(u32 *xfer_pending_list, size_t list_size,
+ u8 id)
+{
+ int i;
+
+ for (i = 0; i < list_size; i++) {
+ if (id != xfer_pending_list[i])
+ continue;
+ xfer_pending_list[i] = 0;
+ return id;
+ }
+
+ return 0;
+}
+
+/*
+ * Polling the FPGA configuration status.
+ * Return 0 for success, non-zero for error.
+ */
+static int reconfig_status_polling_resp(void)
+{
+ int ret;
+ unsigned long start = get_timer(0);
+
+ while (1) {
+ ret = mbox_get_fpga_config_status(MBOX_RECONFIG_STATUS);
+ if (!ret)
+ return 0; /* configuration success */
+
+ if (ret != MBOX_CFGSTAT_STATE_CONFIG)
+ return ret;
+
+ if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS)
+ break; /* time out */
+
+ puts(".");
+ udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+ WATCHDOG_RESET();
+ }
+
+ return -ETIMEDOUT;
+}
+
+static u32 get_resp_hdr(u32 *r_index, u32 *w_index, u32 *resp_count,
+ u32 *resp_buf, u32 buf_size, u32 client_id)
+{
+ u32 buf[MBOX_RESP_BUFFER_SIZE];
+ u32 mbox_hdr;
+ u32 resp_len;
+ u32 hdr_len;
+ u32 i;
+
+ if (*resp_count < buf_size) {
+ u32 rcv_len_max = buf_size - *resp_count;
+
+ if (rcv_len_max > MBOX_RESP_BUFFER_SIZE)
+ rcv_len_max = MBOX_RESP_BUFFER_SIZE;
+ resp_len = mbox_rcv_resp(buf, rcv_len_max);
+
+ for (i = 0; i < resp_len; i++) {
+ resp_buf[(*w_index)++] = buf[i];
+ *w_index %= buf_size;
+ (*resp_count)++;
+ }
+ }
+
+ /* No response in buffer */
+ if (*resp_count == 0)
+ return 0;
+
+ mbox_hdr = resp_buf[*r_index];
+
+ hdr_len = MBOX_RESP_LEN_GET(mbox_hdr);
+
+ /* Insufficient header length to return a mailbox header */
+ if ((*resp_count - 1) < hdr_len)
+ return 0;
+
+ *r_index += (hdr_len + 1);
+ *r_index %= buf_size;
+ *resp_count -= (hdr_len + 1);
+
+ /* Make sure response belongs to us */
+ if (MBOX_RESP_CLIENT_GET(mbox_hdr) != client_id)
+ return 0;
+
+ return mbox_hdr;
+}
+
+/* Send bit stream data to SDM via RECONFIG_DATA mailbox command */
+static int send_reconfig_data(const void *rbf_data, size_t rbf_size,
+ u32 xfer_max, u32 buf_size_max)
+{
+ u32 response_buffer[MBOX_RESP_BUFFER_SIZE];
+ u32 xfer_pending[MBOX_RESP_BUFFER_SIZE];
+ u32 resp_rindex = 0;
+ u32 resp_windex = 0;
+ u32 resp_count = 0;
+ u32 xfer_count = 0;
+ int resp_err = 0;
+ u8 cmd_id = 1;
+ u32 args[3];
+ int ret;
+
+ debug("SDM xfer_max = %d\n", xfer_max);
+ debug("SDM buf_size_max = %x\n\n", buf_size_max);
+
+ memset(xfer_pending, 0, sizeof(xfer_pending));
+
+ while (rbf_size || xfer_count) {
+ if (!resp_err && rbf_size && xfer_count < xfer_max) {
+ args[0] = MBOX_ARG_DESC_COUNT(1);
+ args[1] = (u64)rbf_data;
+ if (rbf_size >= buf_size_max) {
+ args[2] = buf_size_max;
+ rbf_size -= buf_size_max;
+ rbf_data += buf_size_max;
+ } else {
+ args[2] = (u64)rbf_size;
+ rbf_size = 0;
+ }
+
+ resp_err = mbox_send_cmd_only(cmd_id, MBOX_RECONFIG_DATA,
+ MBOX_CMD_INDIRECT, 3, args);
+ if (!resp_err) {
+ xfer_count++;
+ cmd_id = add_transfer(xfer_pending,
+ MBOX_RESP_BUFFER_SIZE,
+ cmd_id);
+ }
+ puts(".");
+ } else {
+ u32 resp_hdr = get_resp_hdr(&resp_rindex, &resp_windex,
+ &resp_count,
+ response_buffer,
+ MBOX_RESP_BUFFER_SIZE,
+ MBOX_CLIENT_ID_UBOOT);
+
+ /*
+ * If no valid response header found or
+ * non-zero length from RECONFIG_DATA
+ */
+ if (!resp_hdr || MBOX_RESP_LEN_GET(resp_hdr))
+ continue;
+
+ /* Check for response's status */
+ if (!resp_err) {
+ resp_err = MBOX_RESP_ERR_GET(resp_hdr);
+ debug("Response error code: %08x\n", resp_err);
+ }
+
+ ret = get_and_clr_transfer(xfer_pending,
+ MBOX_RESP_BUFFER_SIZE,
+ MBOX_RESP_ID_GET(resp_hdr));
+ if (ret) {
+ /* Claim and reuse the ID */
+ cmd_id = (u8)ret;
+ xfer_count--;
+ }
+
+ if (resp_err && !xfer_count)
+ return resp_err;
+ }
+ WATCHDOG_RESET();
+ }
+
+ return 0;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for success, non-zero for error.
+ */
+int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ int ret;
+ u32 resp_len = 2;
+ u32 resp_buf[2];
+
+ debug("Sending MBOX_RECONFIG...\n");
+ ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RECONFIG, MBOX_CMD_DIRECT, 0,
+ NULL, 0, &resp_len, resp_buf);
+ if (ret) {
+ puts("Failure in RECONFIG mailbox command!\n");
+ return ret;
+ }
+
+ ret = send_reconfig_data(rbf_data, rbf_size, resp_buf[0], resp_buf[1]);
+ if (ret) {
+ printf("RECONFIG_DATA error: %08x, %s\n", ret,
+ mbox_cfgstat_to_str(ret));
+ return ret;
+ }
+
+ /* Make sure we don't send MBOX_RECONFIG_STATUS too fast */
+ udelay(RECONFIG_STATUS_INTERVAL_DELAY_US);
+
+ debug("Polling with MBOX_RECONFIG_STATUS...\n");
+ ret = reconfig_status_polling_resp();
+ if (ret) {
+ printf("RECONFIG_STATUS Error: %08x, %s\n", ret,
+ mbox_cfgstat_to_str(ret));
+ return ret;
+ }
+
+ puts("FPGA reconfiguration OK!\n");
+
+ return ret;
+}
+#endif
diff --git a/roms/u-boot/drivers/fpga/ivm_core.c b/roms/u-boot/drivers/fpga/ivm_core.c
new file mode 100644
index 000000000..adc60919f
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/ivm_core.c
@@ -0,0 +1,3150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 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
+ */
+
+#include <common.h>
+#include <log.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");
+#endif /* DEBUG */
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/fpga/lattice.c b/roms/u-boot/drivers/fpga/lattice.c
new file mode 100644
index 000000000..e292d991c
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/lattice.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (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.
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <fpga.h>
+#include <lattice.h>
+#include <linux/delay.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/roms/u-boot/drivers/fpga/socfpga.c b/roms/u-boot/drivers/fpga/socfpga.c
new file mode 100644
index 000000000..685957626
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/socfpga.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+
+/* Timeout count */
+#define FPGA_TIMEOUT_CNT 0x1000000
+
+static struct socfpga_fpga_manager *fpgamgr_regs =
+ (struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
+
+int fpgamgr_dclkcnt_set(unsigned long cnt)
+{
+ unsigned long i;
+
+ /* Clear any existing done status */
+ if (readl(&fpgamgr_regs->dclkstat))
+ writel(0x1, &fpgamgr_regs->dclkstat);
+
+ /* Write the dclkcnt */
+ writel(cnt, &fpgamgr_regs->dclkcnt);
+
+ /* Wait till the dclkcnt done */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (!readl(&fpgamgr_regs->dclkstat))
+ continue;
+
+ writel(0x1, &fpgamgr_regs->dclkstat);
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
+/* Write the RBF data to FPGA Manager */
+void fpgamgr_program_write(const void *rbf_data, size_t rbf_size)
+{
+ uint32_t src = (uint32_t)rbf_data;
+ uint32_t dst = SOCFPGA_FPGAMGRDATA_ADDRESS;
+
+ /* Number of loops for 32-byte long copying. */
+ uint32_t loops32 = rbf_size / 32;
+ /* Number of loops for 4-byte long copying + trailing bytes */
+ uint32_t loops4 = DIV_ROUND_UP(rbf_size % 32, 4);
+
+ asm volatile(
+ " cmp %2, #0\n"
+ " beq 2f\n"
+ "1: ldmia %0!, {r0-r7}\n"
+ " stmia %1!, {r0-r7}\n"
+ " sub %1, #32\n"
+ " subs %2, #1\n"
+ " bne 1b\n"
+ "2: cmp %3, #0\n"
+ " beq 4f\n"
+ "3: ldr %2, [%0], #4\n"
+ " str %2, [%1]\n"
+ " subs %3, #1\n"
+ " bne 3b\n"
+ "4: nop\n"
+ : "+r"(src), "+r"(dst), "+r"(loops32), "+r"(loops4) :
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "cc");
+}
+
diff --git a/roms/u-boot/drivers/fpga/socfpga_arria10.c b/roms/u-boot/drivers/fpga/socfpga_arria10.c
new file mode 100644
index 000000000..b992e6f08
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/socfpga_arria10.c
@@ -0,0 +1,949 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017-2019 Intel Corporation <www.intel.com>
+ */
+#include <image.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/arch/sdram.h>
+#include <asm/arch/misc.h>
+#include <altera.h>
+#include <asm/arch/pinmux.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/ofnode.h>
+#include <errno.h>
+#include <fs_loader.h>
+#include <wait_bit.h>
+#include <watchdog.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#define CFGWDTH_32 1
+#define MIN_BITSTREAM_SIZECHECK 230
+#define ENCRYPTION_OFFSET 69
+#define COMPRESSION_OFFSET 229
+#define FPGA_TIMEOUT_MSEC 1000 /* timeout in ms */
+#define FPGA_TIMEOUT_CNT 0x1000000
+#define DEFAULT_DDR_LOAD_ADDRESS 0x400
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct socfpga_fpga_manager *fpga_manager_base =
+ (void *)SOCFPGA_FPGAMGRREGS_ADDRESS;
+
+static void fpgamgr_set_cd_ratio(unsigned long ratio);
+
+static uint32_t fpgamgr_get_msel(void)
+{
+ u32 reg;
+
+ reg = readl(&fpga_manager_base->imgcfg_stat);
+ reg = (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SET_MSD) >>
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_MSEL0_LSB;
+
+ return reg;
+}
+
+static void fpgamgr_set_cfgwdth(int width)
+{
+ if (width)
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
+ else
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK);
+}
+
+int is_fpgamgr_user_mode(void)
+{
+ return (readl(&fpga_manager_base->imgcfg_stat) &
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) != 0;
+}
+
+static int wait_for_user_mode(void)
+{
+ return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
+ 1, FPGA_TIMEOUT_MSEC, false);
+}
+
+int is_fpgamgr_early_user_mode(void)
+{
+ return (readl(&fpga_manager_base->imgcfg_stat) &
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0;
+}
+
+int fpgamgr_wait_early_user_mode(void)
+{
+ u32 sync_data = 0xffffffff;
+ u32 i = 0;
+ unsigned start = get_timer(0);
+ unsigned long cd_ratio;
+
+ /* Getting existing CDRATIO */
+ cd_ratio = (readl(&fpga_manager_base->imgcfg_ctrl_02) &
+ ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK) >>
+ ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB;
+
+ /* Using CDRATIO_X1 for better compatibility */
+ fpgamgr_set_cd_ratio(CDRATIO_x1);
+
+ while (!is_fpgamgr_early_user_mode()) {
+ if (get_timer(start) > FPGA_TIMEOUT_MSEC)
+ return -ETIMEDOUT;
+ fpgamgr_program_write((const long unsigned int *)&sync_data,
+ sizeof(sync_data));
+ udelay(FPGA_TIMEOUT_MSEC);
+ i++;
+ }
+
+ debug("FPGA: Additional %i sync word needed\n", i);
+
+ /* restoring original CDRATIO */
+ fpgamgr_set_cd_ratio(cd_ratio);
+
+ return 0;
+}
+
+/* Read f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted */
+static int wait_for_nconfig_pin_and_nstatus_pin(void)
+{
+ unsigned long mask = ALT_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK;
+
+ /*
+ * Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until
+ * de-asserted, timeout at 1000ms
+ */
+ return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat, mask,
+ true, FPGA_TIMEOUT_MSEC, false);
+}
+
+static int wait_for_f2s_nstatus_pin(unsigned long value)
+{
+ /* Poll until f2s to specific value, timeout at 1000ms */
+ return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
+ value, FPGA_TIMEOUT_MSEC, false);
+}
+
+/* set CD ratio */
+static void fpgamgr_set_cd_ratio(unsigned long ratio)
+{
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
+
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ (ratio << ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB) &
+ ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SET_MSK);
+}
+
+/* get the MSEL value, verify we are set for FPP configuration mode */
+static int fpgamgr_verify_msel(void)
+{
+ u32 msel = fpgamgr_get_msel();
+
+ if (msel & ~BIT(0)) {
+ printf("Fail: read msel=%d\n", msel);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+/*
+ * Write cdratio and cdwidth based on whether the bitstream is compressed
+ * and/or encoded
+ */
+static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data,
+ size_t rbf_size)
+{
+ unsigned int cd_ratio;
+ bool encrypt, compress;
+
+ /*
+ * According to the bitstream specification,
+ * both encryption and compression status are
+ * in location before offset 230 of the buffer.
+ */
+ if (rbf_size < MIN_BITSTREAM_SIZECHECK)
+ return -EINVAL;
+
+ encrypt = (rbf_data[ENCRYPTION_OFFSET] >> 2) & 3;
+ encrypt = encrypt != 0;
+
+ compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1;
+ compress = !compress;
+
+ debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]);
+ debug("FPGA: Header word %d = %08x.\n", 229, rbf_data[229]);
+ debug("FPGA: Read from rbf header: encrypt=%d compress=%d.\n", encrypt,
+ compress);
+
+ /*
+ * from the register map description of cdratio in imgcfg_ctrl_02:
+ * Normal Configuration : 32bit Passive Parallel
+ * Partial Reconfiguration : 16bit Passive Parallel
+ */
+
+ /*
+ * cd ratio is dependent on cfg width and whether the bitstream
+ * is encrypted and/or compressed.
+ *
+ * | width | encr. | compr. | cd ratio |
+ * | 16 | 0 | 0 | 1 |
+ * | 16 | 0 | 1 | 4 |
+ * | 16 | 1 | 0 | 2 |
+ * | 16 | 1 | 1 | 4 |
+ * | 32 | 0 | 0 | 1 |
+ * | 32 | 0 | 1 | 8 |
+ * | 32 | 1 | 0 | 4 |
+ * | 32 | 1 | 1 | 8 |
+ */
+ if (!compress && !encrypt) {
+ cd_ratio = CDRATIO_x1;
+ } else {
+ if (compress)
+ cd_ratio = CDRATIO_x4;
+ else
+ cd_ratio = CDRATIO_x2;
+
+ /* if 32 bit, double the cd ratio (so register
+ field setting is incremented) */
+ if (cfg_width == CFGWDTH_32)
+ cd_ratio += 1;
+ }
+
+ fpgamgr_set_cfgwdth(cfg_width);
+ fpgamgr_set_cd_ratio(cd_ratio);
+
+ return 0;
+}
+
+static int fpgamgr_reset(void)
+{
+ unsigned long reg;
+
+ /* S2F_NCONFIG = 0 */
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
+
+ /* Wait for f2s_nstatus == 0 */
+ if (wait_for_f2s_nstatus_pin(0))
+ return -ETIME;
+
+ /* S2F_NCONFIG = 1 */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
+
+ /* Wait for f2s_nstatus == 1 */
+ if (wait_for_f2s_nstatus_pin(1))
+ return -ETIME;
+
+ /* read and confirm f2s_condone_pin = 0 and f2s_condone_oe = 1 */
+ reg = readl(&fpga_manager_base->imgcfg_stat);
+ if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) != 0)
+ return -EPERM;
+
+ if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_OE_SET_MSK) == 0)
+ return -EPERM;
+
+ return 0;
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size)
+{
+ int ret;
+
+ /* Step 1 */
+ if (fpgamgr_verify_msel())
+ return -EPERM;
+
+ /* Step 2 */
+ if (fpgamgr_set_cdratio_cdwidth(CFGWDTH_32, rbf_data, rbf_size))
+ return -EPERM;
+
+ /*
+ * Step 3:
+ * Make sure no other external devices are trying to interfere with
+ * programming:
+ */
+ if (wait_for_nconfig_pin_and_nstatus_pin())
+ return -ETIME;
+
+ /*
+ * Step 4:
+ * Deassert the signal drives from HPS
+ *
+ * S2F_NCE = 1
+ * S2F_PR_REQUEST = 0
+ * EN_CFG_CTRL = 0
+ * EN_CFG_DATA = 0
+ * S2F_NCONFIG = 1
+ * S2F_NSTATUS_OE = 0
+ * S2F_CONDONE_OE = 0
+ */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
+
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST_SET_MSK);
+
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
+
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG_SET_MSK);
+
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE_SET_MSK);
+
+ /*
+ * Step 5:
+ * Enable overrides
+ * S2F_NENABLE_CONFIG = 0
+ * S2F_NENABLE_NCONFIG = 0
+ */
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
+
+ /*
+ * Disable driving signals that HPS doesn't need to drive.
+ * S2F_NENABLE_NSTATUS = 1
+ * S2F_NENABLE_CONDONE = 1
+ */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE_SET_MSK);
+
+ /*
+ * Step 6:
+ * Drive chip select S2F_NCE = 0
+ */
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
+
+ /* Step 7 */
+ if (wait_for_nconfig_pin_and_nstatus_pin())
+ return -ETIME;
+
+ /* Step 8 */
+ ret = fpgamgr_reset();
+
+ if (ret)
+ return ret;
+
+ /*
+ * Step 9:
+ * EN_CFG_CTRL and EN_CFG_DATA = 1
+ */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
+
+ return 0;
+}
+
+/* Ensure the FPGA entering config done */
+static int fpgamgr_program_poll_cd(void)
+{
+ unsigned long reg, i;
+
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ reg = readl(&fpga_manager_base->imgcfg_stat);
+ if (reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK)
+ return 0;
+
+ if ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) == 0) {
+ printf("nstatus == 0 while waiting for condone\n");
+ return -EPERM;
+ }
+ WATCHDOG_RESET();
+ }
+
+ if (i == FPGA_TIMEOUT_CNT)
+ return -ETIME;
+
+ return 0;
+}
+
+/* Ensure the FPGA entering user mode */
+static int fpgamgr_program_poll_usermode(void)
+{
+ unsigned long reg;
+ int ret = 0;
+
+ if (fpgamgr_dclkcnt_set(0xf))
+ return -ETIME;
+
+ ret = wait_for_user_mode();
+ if (ret < 0) {
+ printf("%s: Failed to enter user mode with ", __func__);
+ printf("error code %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Step 14:
+ * Stop DATA path and Dclk
+ * EN_CFG_CTRL and EN_CFG_DATA = 0
+ */
+ clrbits_le32(&fpga_manager_base->imgcfg_ctrl_02,
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA_SET_MSK |
+ ALT_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL_SET_MSK);
+
+ /*
+ * Step 15:
+ * Disable overrides
+ * S2F_NENABLE_CONFIG = 1
+ * S2F_NENABLE_NCONFIG = 1
+ */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG_SET_MSK);
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_00,
+ ALT_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG_SET_MSK);
+
+ /* Disable chip select S2F_NCE = 1 */
+ setbits_le32(&fpga_manager_base->imgcfg_ctrl_01,
+ ALT_FPGAMGR_IMGCFG_CTL_01_S2F_NCE_SET_MSK);
+
+ /*
+ * Step 16:
+ * Final check
+ */
+ reg = readl(&fpga_manager_base->imgcfg_stat);
+ if (((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) !=
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK) ||
+ ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) !=
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN_SET_MSK) ||
+ ((reg & ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK) !=
+ ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK))
+ return -EPERM;
+
+ return 0;
+}
+
+int fpgamgr_program_finish(void)
+{
+ /* Ensure the FPGA entering config done */
+ int status = fpgamgr_program_poll_cd();
+
+ if (status) {
+ printf("FPGA: Poll CD failed with error code %d\n", status);
+ return -EPERM;
+ }
+
+ /* Ensure the FPGA entering user mode */
+ status = fpgamgr_program_poll_usermode();
+ if (status) {
+ printf("FPGA: Poll usermode failed with error code %d\n",
+ status);
+ return -EPERM;
+ }
+
+ printf("Full Configuration Succeeded.\n");
+
+ return 0;
+}
+
+ofnode get_fpga_mgr_ofnode(ofnode from)
+{
+ return ofnode_by_compatible(from, "altr,socfpga-a10-fpga-mgr");
+}
+
+const char *get_fpga_filename(void)
+{
+ const char *fpga_filename = NULL;
+
+ ofnode fpgamgr_node = get_fpga_mgr_ofnode(ofnode_null());
+
+ if (ofnode_valid(fpgamgr_node))
+ fpga_filename = ofnode_read_string(fpgamgr_node,
+ "altr,bitstream");
+
+ return fpga_filename;
+}
+
+static void get_rbf_image_info(struct rbf_info *rbf, u16 *buffer)
+{
+ /*
+ * Magic ID starting at:
+ * -> 1st dword[15:0] in periph.rbf
+ * -> 2nd dword[15:0] in core.rbf
+ * Note: dword == 32 bits
+ */
+ u32 word_reading_max = 2;
+ u32 i;
+
+ for (i = 0; i < word_reading_max; i++) {
+ if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) {
+ rbf->security = unencrypted;
+ } else if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_ENCRYPTED) {
+ rbf->security = encrypted;
+ } else if (*(buffer + i + 1) ==
+ FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) {
+ rbf->security = unencrypted;
+ } else if (*(buffer + i + 1) ==
+ FPGA_SOCFPGA_A10_RBF_ENCRYPTED) {
+ rbf->security = encrypted;
+ } else {
+ rbf->security = invalid;
+ continue;
+ }
+
+ /* PERIPH RBF(buffer + i + 1), CORE RBF(buffer + i + 2) */
+ if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_PERIPH) {
+ rbf->section = periph_section;
+ break;
+ } else if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_CORE) {
+ rbf->section = core_section;
+ break;
+ } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_PERIPH) {
+ rbf->section = periph_section;
+ break;
+ } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_CORE) {
+ rbf->section = core_section;
+ break;
+ }
+
+ rbf->section = unknown;
+ break;
+
+ WATCHDOG_RESET();
+ }
+}
+
+#ifdef CONFIG_FS_LOADER
+static int first_loading_rbf_to_buffer(struct udevice *dev,
+ struct fpga_loadfs_info *fpga_loadfs,
+ u32 *buffer, size_t *buffer_bsize)
+{
+ u32 *buffer_p = (u32 *)*buffer;
+ u32 *loadable = buffer_p;
+ size_t buffer_size = *buffer_bsize;
+ size_t fit_size;
+ int ret, i, count, confs_noffset, images_noffset, rbf_offset, rbf_size;
+ const char *fpga_node_name = NULL;
+ const char *uname = NULL;
+
+ /* Load image header into buffer */
+ ret = request_firmware_into_buf(dev,
+ fpga_loadfs->fpga_fsinfo->filename,
+ buffer_p, sizeof(struct image_header),
+ 0);
+ if (ret < 0) {
+ debug("FPGA: Failed to read image header from flash.\n");
+ return -ENOENT;
+ }
+
+ if (image_get_magic((struct image_header *)buffer_p) != FDT_MAGIC) {
+ debug("FPGA: No FDT magic was found.\n");
+ return -EBADF;
+ }
+
+ fit_size = fdt_totalsize(buffer_p);
+
+ if (fit_size > buffer_size) {
+ debug("FPGA: FIT image is larger than available buffer.\n");
+ debug("Please use FIT external data or increasing buffer.\n");
+ return -ENOMEM;
+ }
+
+ /* Load entire FIT into buffer */
+ ret = request_firmware_into_buf(dev,
+ fpga_loadfs->fpga_fsinfo->filename,
+ buffer_p, fit_size, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = fit_check_format(buffer_p, IMAGE_SIZE_INVAL);
+ if (ret) {
+ debug("FPGA: No valid FIT image was found.\n");
+ return ret;
+ }
+
+ confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH);
+ images_noffset = fdt_path_offset(buffer_p, FIT_IMAGES_PATH);
+ if (confs_noffset < 0 || images_noffset < 0) {
+ debug("FPGA: No Configurations or images nodes were found.\n");
+ return -ENOENT;
+ }
+
+ /* Get default configuration unit name from default property */
+ confs_noffset = fit_conf_get_node(buffer_p, NULL);
+ if (confs_noffset < 0) {
+ debug("FPGA: No default configuration was found in config.\n");
+ return -ENOENT;
+ }
+
+ count = fit_conf_get_prop_node_count(buffer_p, confs_noffset,
+ FIT_FPGA_PROP);
+ if (count < 0) {
+ debug("FPGA: Invalid configuration format for FPGA node.\n");
+ return count;
+ }
+ debug("FPGA: FPGA node count: %d\n", count);
+
+ for (i = 0; i < count; i++) {
+ images_noffset = fit_conf_get_prop_node_index(buffer_p,
+ confs_noffset,
+ FIT_FPGA_PROP, i);
+ uname = fit_get_name(buffer_p, images_noffset, NULL);
+ if (uname) {
+ debug("FPGA: %s\n", uname);
+
+ if (strstr(uname, "fpga-periph") &&
+ (!is_fpgamgr_early_user_mode() ||
+ is_fpgamgr_user_mode())) {
+ fpga_node_name = uname;
+ printf("FPGA: Start to program ");
+ printf("peripheral/full bitstream ...\n");
+ break;
+ } else if (strstr(uname, "fpga-core") &&
+ (is_fpgamgr_early_user_mode() &&
+ !is_fpgamgr_user_mode())) {
+ fpga_node_name = uname;
+ printf("FPGA: Start to program core ");
+ printf("bitstream ...\n");
+ break;
+ }
+ }
+ WATCHDOG_RESET();
+ }
+
+ if (!fpga_node_name) {
+ debug("FPGA: No suitable bitstream was found, count: %d.\n", i);
+ return 1;
+ }
+
+ images_noffset = fit_image_get_node(buffer_p, fpga_node_name);
+ if (images_noffset < 0) {
+ debug("FPGA: No node '%s' was found in FIT.\n",
+ fpga_node_name);
+ return -ENOENT;
+ }
+
+ if (!fit_image_get_data_position(buffer_p, images_noffset,
+ &rbf_offset)) {
+ debug("FPGA: Data position was found.\n");
+ } else if (!fit_image_get_data_offset(buffer_p, images_noffset,
+ &rbf_offset)) {
+ /*
+ * For FIT with external data, figure out where
+ * the external images start. This is the base
+ * for the data-offset properties in each image.
+ */
+ rbf_offset += ((fdt_totalsize(buffer_p) + 3) & ~3);
+ debug("FPGA: Data offset was found.\n");
+ } else {
+ debug("FPGA: No data position/offset was found.\n");
+ return -ENOENT;
+ }
+
+ ret = fit_image_get_data_size(buffer_p, images_noffset, &rbf_size);
+ if (ret < 0) {
+ debug("FPGA: No data size was found (err=%d).\n", ret);
+ return -ENOENT;
+ }
+
+ if (gd->ram_size < rbf_size) {
+ debug("FPGA: Using default OCRAM buffer and size.\n");
+ } else {
+ ret = fit_image_get_load(buffer_p, images_noffset,
+ (ulong *)loadable);
+ if (ret < 0) {
+ buffer_p = (u32 *)DEFAULT_DDR_LOAD_ADDRESS;
+ debug("FPGA: No loadable was found.\n");
+ debug("FPGA: Using default DDR load address: 0x%x .\n",
+ DEFAULT_DDR_LOAD_ADDRESS);
+ } else {
+ buffer_p = (u32 *)*loadable;
+ debug("FPGA: Found loadable address = 0x%x.\n",
+ *loadable);
+ }
+
+ buffer_size = rbf_size;
+ }
+
+ debug("FPGA: External data: offset = 0x%x, size = 0x%x.\n",
+ rbf_offset, rbf_size);
+
+ fpga_loadfs->remaining = rbf_size;
+
+ /*
+ * Determine buffer size vs bitstream size, and calculating number of
+ * chunk by chunk transfer is required due to smaller buffer size
+ * compare to bitstream
+ */
+ if (rbf_size <= buffer_size) {
+ /* Loading whole bitstream into buffer */
+ buffer_size = rbf_size;
+ fpga_loadfs->remaining = 0;
+ } else {
+ fpga_loadfs->remaining -= buffer_size;
+ }
+
+ fpga_loadfs->offset = rbf_offset;
+ /* Loading bitstream into buffer */
+ ret = request_firmware_into_buf(dev,
+ fpga_loadfs->fpga_fsinfo->filename,
+ buffer_p, buffer_size,
+ fpga_loadfs->offset);
+ if (ret < 0) {
+ debug("FPGA: Failed to read bitstream from flash.\n");
+ return -ENOENT;
+ }
+
+ /* Getting info about bitstream types */
+ get_rbf_image_info(&fpga_loadfs->rbfinfo, (u16 *)buffer_p);
+
+ /* Update next reading bitstream offset */
+ fpga_loadfs->offset += buffer_size;
+
+ /* Update the final addr for bitstream */
+ *buffer = (u32)buffer_p;
+
+ /* Update the size of bitstream to be programmed into FPGA */
+ *buffer_bsize = buffer_size;
+
+ return 0;
+}
+
+static int subsequent_loading_rbf_to_buffer(struct udevice *dev,
+ struct fpga_loadfs_info *fpga_loadfs,
+ u32 *buffer, size_t *buffer_bsize)
+{
+ int ret = 0;
+ u32 *buffer_p = (u32 *)*buffer;
+
+ /* Read the bitstream chunk by chunk. */
+ if (fpga_loadfs->remaining > *buffer_bsize) {
+ fpga_loadfs->remaining -= *buffer_bsize;
+ } else {
+ *buffer_bsize = fpga_loadfs->remaining;
+ fpga_loadfs->remaining = 0;
+ }
+
+ ret = request_firmware_into_buf(dev,
+ fpga_loadfs->fpga_fsinfo->filename,
+ buffer_p, *buffer_bsize,
+ fpga_loadfs->offset);
+ if (ret < 0) {
+ debug("FPGA: Failed to read bitstream from flash.\n");
+ return -ENOENT;
+ }
+
+ /* Update next reading bitstream offset */
+ fpga_loadfs->offset += *buffer_bsize;
+
+ return 0;
+}
+
+int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize,
+ u32 offset)
+{
+ struct fpga_loadfs_info fpga_loadfs;
+ struct udevice *dev;
+ int status, ret, size;
+ u32 buffer = (uintptr_t)buf;
+ size_t buffer_sizebytes = bsize;
+ size_t buffer_sizebytes_ori = bsize;
+ size_t total_sizeof_image = 0;
+ ofnode node;
+ const fdt32_t *phandle_p;
+ u32 phandle;
+
+ node = get_fpga_mgr_ofnode(ofnode_null());
+
+ if (ofnode_valid(node)) {
+ phandle_p = ofnode_get_property(node, "firmware-loader", &size);
+ if (!phandle_p) {
+ node = ofnode_path("/chosen");
+ if (!ofnode_valid(node)) {
+ debug("FPGA: /chosen node was not found.\n");
+ return -ENOENT;
+ }
+
+ phandle_p = ofnode_get_property(node, "firmware-loader",
+ &size);
+ if (!phandle_p) {
+ debug("FPGA: firmware-loader property was not");
+ debug(" found.\n");
+ return -ENOENT;
+ }
+ }
+ } else {
+ debug("FPGA: FPGA manager node was not found.\n");
+ return -ENOENT;
+ }
+
+ phandle = fdt32_to_cpu(*phandle_p);
+ ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
+ phandle, &dev);
+ if (ret)
+ return ret;
+
+ memset(&fpga_loadfs, 0, sizeof(fpga_loadfs));
+
+ fpga_loadfs.fpga_fsinfo = fpga_fsinfo;
+ fpga_loadfs.offset = offset;
+
+ printf("FPGA: Checking FPGA configuration setting ...\n");
+
+ /*
+ * Note: Both buffer and buffer_sizebytes values can be altered by
+ * function below.
+ */
+ ret = first_loading_rbf_to_buffer(dev, &fpga_loadfs, &buffer,
+ &buffer_sizebytes);
+ if (ret == 1) {
+ printf("FPGA: Skipping configuration ...\n");
+ return 0;
+ } else if (ret) {
+ return ret;
+ }
+
+ if (fpga_loadfs.rbfinfo.section == core_section &&
+ !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) {
+ debug("FPGA : Must be in Early Release mode to program ");
+ debug("core bitstream.\n");
+ return -EPERM;
+ }
+
+ /* Disable all signals from HPS peripheral controller to FPGA */
+ writel(0, socfpga_get_sysmgr_addr() + SYSMGR_A10_FPGAINTF_EN_GLOBAL);
+
+ /* Disable all axi bridges (hps2fpga, lwhps2fpga & fpga2hps) */
+ socfpga_bridges_reset();
+
+ if (fpga_loadfs.rbfinfo.section == periph_section) {
+ /* Initialize the FPGA Manager */
+ status = fpgamgr_program_init((u32 *)buffer, buffer_sizebytes);
+ if (status) {
+ debug("FPGA: Init with peripheral bitstream failed.\n");
+ return -EPERM;
+ }
+ }
+
+ /* Transfer bitstream to FPGA Manager */
+ fpgamgr_program_write((void *)buffer, buffer_sizebytes);
+
+ total_sizeof_image += buffer_sizebytes;
+
+ while (fpga_loadfs.remaining) {
+ ret = subsequent_loading_rbf_to_buffer(dev,
+ &fpga_loadfs,
+ &buffer,
+ &buffer_sizebytes_ori);
+
+ if (ret)
+ return ret;
+
+ /* Transfer data to FPGA Manager */
+ fpgamgr_program_write((void *)buffer,
+ buffer_sizebytes_ori);
+
+ total_sizeof_image += buffer_sizebytes_ori;
+
+ WATCHDOG_RESET();
+ }
+
+ if (fpga_loadfs.rbfinfo.section == periph_section) {
+ if (fpgamgr_wait_early_user_mode() != -ETIMEDOUT) {
+ config_pins(gd->fdt_blob, "shared");
+ puts("FPGA: Early Release Succeeded.\n");
+ } else {
+ debug("FPGA: Failed to see Early Release.\n");
+ return -EIO;
+ }
+
+ /* For monolithic bitstream */
+ if (is_fpgamgr_user_mode()) {
+ /* Ensure the FPGA entering config done */
+ status = fpgamgr_program_finish();
+ if (status)
+ return status;
+
+ config_pins(gd->fdt_blob, "fpga");
+ puts("FPGA: Enter user mode.\n");
+ }
+ } else if (fpga_loadfs.rbfinfo.section == core_section) {
+ /* Ensure the FPGA entering config done */
+ status = fpgamgr_program_finish();
+ if (status)
+ return status;
+
+ config_pins(gd->fdt_blob, "fpga");
+ puts("FPGA: Enter user mode.\n");
+ } else {
+ debug("FPGA: Config Error: Unsupported bitstream type.\n");
+ return -ENOEXEC;
+ }
+
+ return (int)total_sizeof_image;
+}
+
+void fpgamgr_program(const void *buf, size_t bsize, u32 offset)
+{
+ fpga_fs_info fpga_fsinfo;
+
+ fpga_fsinfo.filename = get_fpga_filename();
+
+ if (fpga_fsinfo.filename)
+ socfpga_loadfs(&fpga_fsinfo, buf, bsize, offset);
+}
+#endif
+
+/* This function is used to load the core bitstream from the OCRAM. */
+int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ unsigned long status;
+ struct rbf_info rbfinfo;
+
+ memset(&rbfinfo, 0, sizeof(rbfinfo));
+
+ /* Disable all signals from hps peripheral controller to fpga */
+ writel(0, socfpga_get_sysmgr_addr() + SYSMGR_A10_FPGAINTF_EN_GLOBAL);
+
+ /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+ socfpga_bridges_reset();
+
+ /* Getting info about bitstream types */
+ get_rbf_image_info(&rbfinfo, (u16 *)rbf_data);
+
+ if (rbfinfo.section == periph_section) {
+ /* Initialize the FPGA Manager */
+ status = fpgamgr_program_init((u32 *)rbf_data, rbf_size);
+ if (status)
+ return status;
+ }
+
+ if (rbfinfo.section == core_section &&
+ !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) {
+ debug("FPGA : Must be in early release mode to program ");
+ debug("core bitstream.\n");
+ return -EPERM;
+ }
+
+ /* Write the bitstream to FPGA Manager */
+ fpgamgr_program_write(rbf_data, rbf_size);
+
+ status = fpgamgr_program_finish();
+ if (status)
+ return status;
+
+ config_pins(gd->fdt_blob, "fpga");
+ puts("FPGA: Enter user mode.\n");
+
+ return status;
+}
diff --git a/roms/u-boot/drivers/fpga/socfpga_gen5.c b/roms/u-boot/drivers/fpga/socfpga_gen5.c
new file mode 100644
index 000000000..d73474f29
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/socfpga_gen5.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+
+#define FPGA_TIMEOUT_CNT 0x1000000
+
+static struct socfpga_fpga_manager *fpgamgr_regs =
+ (struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
+
+/* Set CD ratio */
+static void fpgamgr_set_cd_ratio(unsigned long ratio)
+{
+ clrsetbits_le32(&fpgamgr_regs->ctrl,
+ 0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB,
+ (ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB);
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+static int fpgamgr_program_init(void)
+{
+ unsigned long msel, i;
+
+ /* Get the MSEL value */
+ msel = readl(&fpgamgr_regs->stat);
+ msel &= FPGAMGRREGS_STAT_MSEL_MASK;
+ msel >>= FPGAMGRREGS_STAT_MSEL_LSB;
+
+ /*
+ * Set the cfg width
+ * If MSEL[3] = 1, cfg width = 32 bit
+ */
+ if (msel & 0x8) {
+ setbits_le32(&fpgamgr_regs->ctrl,
+ FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+
+ /* To determine the CD ratio */
+ /* MSEL[1:0] = 0, CD Ratio = 1 */
+ if ((msel & 0x3) == 0x0)
+ fpgamgr_set_cd_ratio(CDRATIO_x1);
+ /* MSEL[1:0] = 1, CD Ratio = 4 */
+ else if ((msel & 0x3) == 0x1)
+ fpgamgr_set_cd_ratio(CDRATIO_x4);
+ /* MSEL[1:0] = 2, CD Ratio = 8 */
+ else if ((msel & 0x3) == 0x2)
+ fpgamgr_set_cd_ratio(CDRATIO_x8);
+
+ } else { /* MSEL[3] = 0 */
+ clrbits_le32(&fpgamgr_regs->ctrl,
+ FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+
+ /* To determine the CD ratio */
+ /* MSEL[1:0] = 0, CD Ratio = 1 */
+ if ((msel & 0x3) == 0x0)
+ fpgamgr_set_cd_ratio(CDRATIO_x1);
+ /* MSEL[1:0] = 1, CD Ratio = 2 */
+ else if ((msel & 0x3) == 0x1)
+ fpgamgr_set_cd_ratio(CDRATIO_x2);
+ /* MSEL[1:0] = 2, CD Ratio = 4 */
+ else if ((msel & 0x3) == 0x2)
+ fpgamgr_set_cd_ratio(CDRATIO_x4);
+ }
+
+ /* To enable FPGA Manager configuration */
+ clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCE_MASK);
+
+ /* To enable FPGA Manager drive over configuration line */
+ setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+ /* Put FPGA into reset phase */
+ setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+ /* (1) wait until FPGA enter reset phase */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE)
+ break;
+ }
+
+ /* If not in reset state, return error */
+ if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) {
+ puts("FPGA: Could not reset\n");
+ return -1;
+ }
+
+ /* Release FPGA from reset phase */
+ clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+ /* (2) wait until FPGA enter configuration phase */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE)
+ break;
+ }
+
+ /* If not in configuration state, return error */
+ if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE) {
+ puts("FPGA: Could not configure\n");
+ return -2;
+ }
+
+ /* Clear all interrupts in CB Monitor */
+ writel(0xFFF, &fpgamgr_regs->gpio_porta_eoi);
+
+ /* Enable AXI configuration */
+ setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+
+ return 0;
+}
+
+/* Ensure the FPGA entering config done */
+static int fpgamgr_program_poll_cd(void)
+{
+ const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK |
+ FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK;
+ unsigned long reg, i;
+
+ /* (3) wait until full config done */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ reg = readl(&fpgamgr_regs->gpio_ext_porta);
+
+ /* Config error */
+ if (!(reg & mask)) {
+ printf("FPGA: Configuration error.\n");
+ return -3;
+ }
+
+ /* Config done without error */
+ if (reg & mask)
+ break;
+ }
+
+ /* Timeout happened, return error */
+ if (i == FPGA_TIMEOUT_CNT) {
+ printf("FPGA: Timeout waiting for program.\n");
+ return -4;
+ }
+
+ /* Disable AXI configuration */
+ clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+
+ return 0;
+}
+
+/* Ensure the FPGA entering init phase */
+static int fpgamgr_program_poll_initphase(void)
+{
+ unsigned long i;
+
+ /* Additional clocks for the CB to enter initialization phase */
+ if (fpgamgr_dclkcnt_set(0x4))
+ return -5;
+
+ /* (4) wait until FPGA enter init phase or user mode */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE)
+ break;
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+ break;
+ }
+
+ /* If not in configuration state, return error */
+ if (i == FPGA_TIMEOUT_CNT)
+ return -6;
+
+ return 0;
+}
+
+/* Ensure the FPGA entering user mode */
+static int fpgamgr_program_poll_usermode(void)
+{
+ unsigned long i;
+
+ /* Additional clocks for the CB to exit initialization phase */
+ if (fpgamgr_dclkcnt_set(0x5000))
+ return -7;
+
+ /* (5) wait until FPGA enter user mode */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+ break;
+ }
+ /* If not in configuration state, return error */
+ if (i == FPGA_TIMEOUT_CNT)
+ return -8;
+
+ /* To release FPGA Manager drive over configuration line */
+ clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+ return 0;
+}
+
+/*
+ * FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ int status;
+
+ if ((uint32_t)rbf_data & 0x3) {
+ puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+ return -EINVAL;
+ }
+
+ /* Prior programming the FPGA, all bridges need to be shut off */
+
+ /* Disable all signals from hps peripheral controller to fpga */
+ writel(0, socfpga_get_sysmgr_addr() + SYSMGR_GEN5_FPGAINFGRP_MODULE);
+
+ /* Disable all signals from FPGA to HPS SDRAM */
+#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
+ writel(0, SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS);
+
+ /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+ socfpga_bridges_reset(1);
+
+ /* Unmap the bridges from NIC-301 */
+ writel(0x1, SOCFPGA_L3REGS_ADDRESS);
+
+ /* Initialize the FPGA Manager */
+ status = fpgamgr_program_init();
+ if (status)
+ return status;
+
+ /* Write the RBF data to FPGA Manager */
+ fpgamgr_program_write(rbf_data, rbf_size);
+
+ /* Ensure the FPGA entering config done */
+ status = fpgamgr_program_poll_cd();
+ if (status)
+ return status;
+
+ /* Ensure the FPGA entering init phase */
+ status = fpgamgr_program_poll_initphase();
+ if (status)
+ return status;
+
+ /* Ensure the FPGA entering user mode */
+ return fpgamgr_program_poll_usermode();
+}
diff --git a/roms/u-boot/drivers/fpga/spartan2.c b/roms/u-boot/drivers/fpga/spartan2.c
new file mode 100644
index 000000000..3435400e5
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/spartan2.c
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+#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 */
+static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+struct xilinx_fpga_op spartan2_op = {
+ .load = spartan2_load,
+ .dump = spartan2_dump,
+ .info = spartan2_info,
+};
diff --git a/roms/u-boot/drivers/fpga/spartan3.c b/roms/u-boot/drivers/fpga/spartan3.c
new file mode 100644
index 000000000..4850c9935
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/spartan3.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+/*
+ * 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 */
+static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+struct xilinx_fpga_op spartan3_op = {
+ .load = spartan3_load,
+ .dump = spartan3_dump,
+ .info = spartan3_info,
+};
diff --git a/roms/u-boot/drivers/fpga/stratixII.c b/roms/u-boot/drivers/fpga/stratixII.c
new file mode 100644
index 000000000..b450a8107
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/stratixII.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Eran Liberty, Extricom , eran.liberty@gmail.com
+ */
+
+#include <common.h> /* core U-Boot definitions */
+#include <altera.h>
+#include <linux/delay.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 transferred 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/roms/u-boot/drivers/fpga/stratixv.c b/roms/u-boot/drivers/fpga/stratixv.c
new file mode 100644
index 000000000..abae3b5b7
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/stratixv.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <log.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+
+/* Write the RBF data to FPGA via SPI */
+static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
+ unsigned long rbf_size)
+{
+ struct spi_slave *slave;
+ int ret;
+
+ debug("%s (%d): data=%p size=%ld\n",
+ __func__, __LINE__, rbf_data, rbf_size);
+
+ /* FIXME: How to get the max. SPI clock and SPI mode? */
+ slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
+ if (!slave)
+ return -1;
+
+ if (spi_claim_bus(slave))
+ return -1;
+
+ ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+
+ spi_release_bus(slave);
+
+ return ret;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ altera_board_specific_func *pfns = desc->iface_fns;
+ int cookie = desc->cookie;
+ int spi_bus;
+ int spi_dev;
+ int ret = 0;
+
+ if ((u32)rbf_data & 0x3) {
+ puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+ return -EINVAL;
+ }
+
+ /* Run the pre configuration function if there is one */
+ if (pfns->pre)
+ (pfns->pre)(cookie);
+
+ /* Establish the initial state */
+ if (pfns->config) {
+ /* De-assert nCONFIG */
+ (pfns->config)(false, true, cookie);
+
+ /* nConfig minimum low pulse width is 2us */
+ udelay(200);
+
+ /* Assert nCONFIG */
+ (pfns->config)(true, true, cookie);
+
+ /* nCONFIG high to first rising clock on DCLK min 1506 us */
+ udelay(1600);
+ }
+
+ /* Write the RBF data to FPGA */
+ if (pfns->write) {
+ /*
+ * Use board specific data function to write bitstream
+ * into the FPGA
+ */
+ ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
+ } else {
+ /*
+ * Use common SPI functions to write bitstream into the
+ * FPGA
+ */
+ spi_bus = COOKIE2SPI_BUS(cookie);
+ spi_dev = COOKIE2SPI_DEV(cookie);
+ ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
+ }
+ if (ret)
+ return ret;
+
+ /* Check done pin */
+ if (pfns->done) {
+ ret = (pfns->done)(cookie);
+
+ if (ret)
+ printf("Error: DONE not set (ret=%d)!\n", ret);
+ }
+
+ return ret;
+}
diff --git a/roms/u-boot/drivers/fpga/versalpl.c b/roms/u-boot/drivers/fpga/versalpl.c
new file mode 100644
index 000000000..c44a7d345
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/versalpl.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019, Xilinx, Inc,
+ * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <asm/arch/sys_proto.h>
+#include <memalign.h>
+#include <versalpl.h>
+#include <zynqmp_firmware.h>
+#include <asm/cache.h>
+
+static ulong versal_align_dma_buffer(ulong *buf, u32 len)
+{
+ ulong *new_buf;
+
+ if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
+ new_buf = (ulong *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
+ memcpy(new_buf, buf, len);
+ buf = new_buf;
+ }
+
+ return (ulong)buf;
+}
+
+static int versal_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ ulong bin_buf;
+ int ret;
+ u32 buf_lo, buf_hi;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ bin_buf = versal_align_dma_buffer((ulong *)buf, bsize);
+
+ debug("%s called!\n", __func__);
+ flush_dcache_range(bin_buf, bin_buf + bsize);
+
+ buf_lo = lower_32_bits(bin_buf);
+ buf_hi = upper_32_bits(bin_buf);
+
+ ret = xilinx_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_lo,
+ buf_hi, 0, ret_payload);
+ if (ret)
+ printf("PL FPGA LOAD failed with err: 0x%08x\n", ret);
+
+ return ret;
+}
+
+struct xilinx_fpga_op versal_op = {
+ .load = versal_load,
+};
diff --git a/roms/u-boot/drivers/fpga/virtex2.c b/roms/u-boot/drivers/fpga/virtex2.c
new file mode 100644
index 000000000..b3e0537ba
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/virtex2.c
@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.com
+ *
+ * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
+ */
+
+/*
+ * Configuration support for Xilinx Virtex2 devices. Based
+ * on spartan2.c (Rich Ireland, rireland@enterasys.com).
+ */
+
+#include <common.h>
+#include <console.h>
+#include <virtex2.h>
+#include <linux/delay.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);
+
+static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ int ret_val = FPGA_FAIL;
+
+ switch (desc->iface) {
+ case slave_serial:
+ PRINTF("%s: Launching Slave Serial Load\n", __func__);
+ ret_val = virtex2_ss_load(desc, buf, bsize);
+ break;
+
+ case slave_selectmap:
+ PRINTF("%s: Launching Slave Parallel Load\n", __func__);
+ ret_val = virtex2_ssm_load(desc, buf, bsize);
+ break;
+
+ default:
+ printf("%s: Unsupported interface type, %d\n",
+ __func__, desc->iface);
+ }
+ return ret_val;
+}
+
+static 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", __func__);
+ ret_val = virtex2_ss_dump(desc, buf, bsize);
+ break;
+
+ case slave_parallel:
+ PRINTF("%s: Launching Slave Parallel Dump\n", __func__);
+ ret_val = virtex2_ssm_dump(desc, buf, bsize);
+ break;
+
+ default:
+ printf("%s: Unsupported interface type, %d\n",
+ __func__, desc->iface);
+ }
+ return ret_val;
+}
+
+static int virtex2_info(xilinx_desc *desc)
+{
+ return FPGA_SUCCESS;
+}
+
+/*
+ * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
+ * 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_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
+{
+ unsigned long ts;
+
+ PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
+ __func__, __LINE__, fn);
+
+ if (!fn) {
+ printf("%s:%d: NULL Interface function table!\n",
+ __func__, __LINE__);
+ return FPGA_FAIL;
+ }
+
+ /* 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",
+ __func__, __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",
+ __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
+ (*fn->abort)(cookie);
+ return FPGA_FAIL;
+ }
+ } while (!(*fn->init)(cookie));
+
+ (*fn->pgm)(false, true, cookie);
+ CONFIG_FPGA_DELAY();
+ if (fn->clk)
+ (*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",
+ __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
+ (*fn->abort)(cookie);
+ return FPGA_FAIL;
+ }
+ } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
+
+ if (fn->wr)
+ (*fn->wr)(true, true, cookie);
+ if (fn->cs)
+ (*fn->cs)(true, true, cookie);
+
+ mdelay(10);
+ return FPGA_SUCCESS;
+}
+
+static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
+ int cookie)
+{
+ int ret_val = FPGA_SUCCESS;
+ int num_done = 0;
+ unsigned long ts;
+
+ /*
+ * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
+ */
+ CONFIG_FPGA_DELAY();
+ if (fn->cs)
+ (*fn->cs)(false, true, cookie);
+ if (fn->wr)
+ (*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. Continue pulsing
+ * clock with data set to all ones until DONE is asserted and for 8
+ * clock cycles afterwards.
+ */
+ ts = get_timer(0);
+ while (true) {
+ if ((*fn->done)(cookie) == FPGA_SUCCESS &&
+ !((*fn->init)(cookie))) {
+ if (num_done++ >= 8)
+ break;
+ }
+
+ 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",
+ __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
+ (*fn->abort)(cookie);
+ ret_val = FPGA_FAIL;
+ break;
+ }
+ if (fn->wbulkdata) {
+ unsigned char dummy = 0xff;
+ (*fn->wbulkdata)(&dummy, 1, true, cookie);
+ } else {
+ (*fn->wdata)(0xff, true, cookie);
+ CONFIG_FPGA_DELAY();
+ (*fn->clk)(false, true, cookie);
+ CONFIG_FPGA_DELAY();
+ (*fn->clk)(true, true, cookie);
+ }
+ }
+
+ 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
+ }
+ return ret_val;
+}
+
+static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL;
+ xilinx_virtex2_slave_fns *fn = desc->iface_fns;
+ size_t bytecount = 0;
+ unsigned char *data = (unsigned char *)buf;
+ int cookie = desc->cookie;
+
+ ret_val = virtex2_slave_pre(fn, cookie);
+ if (ret_val != FPGA_SUCCESS)
+ return ret_val;
+
+ /*
+ * 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",
+ __func__, __LINE__, bytecount);
+ break;
+ }
+
+#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
+ if ((*fn->init)(cookie)) {
+ printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
+ __func__, __LINE__);
+ printf("%zu = buffer offset, %zu = 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",
+ __func__, __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
+ }
+
+ return virtex2_slave_post(fn, cookie);
+}
+
+/*
+ * 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_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",
+ __func__, __LINE__);
+ }
+ return ret_val;
+}
+
+static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL;
+ xilinx_virtex2_slave_fns *fn = desc->iface_fns;
+ unsigned char *data = (unsigned char *)buf;
+ int cookie = desc->cookie;
+
+ ret_val = virtex2_slave_pre(fn, cookie);
+ if (ret_val != FPGA_SUCCESS)
+ return ret_val;
+
+ if (fn->wbulkdata) {
+ /* Load the data in a single chunk */
+ (*fn->wbulkdata)(data, bsize, true, cookie);
+ } else {
+ size_t bytecount = 0;
+
+ /*
+ * Load the data bit by bit
+ */
+ while (bytecount < bsize) {
+ unsigned char curr_data = data[bytecount++];
+ int bit;
+
+#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",
+ __func__, __LINE__, bytecount);
+ break;
+ }
+
+#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
+ if ((*fn->init)(cookie)) {
+ printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
+ __func__, __LINE__);
+ printf("%zu = buffer offset, %zu = buffer size\n",
+ bytecount, bsize);
+ (*fn->abort)(cookie);
+ return FPGA_FAIL;
+ }
+#endif
+
+ for (bit = 7; bit >= 0; --bit) {
+ unsigned char curr_bit = (curr_data >> bit) & 1;
+ (*fn->wdata)(curr_bit, true, cookie);
+ CONFIG_FPGA_DELAY();
+ (*fn->clk)(false, true, cookie);
+ CONFIG_FPGA_DELAY();
+ (*fn->clk)(true, true, cookie);
+ }
+
+ /* Slave serial never uses a busy pin */
+
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+ if (bytecount % (bsize / 40) == 0)
+ putc('.');
+#endif
+ }
+ }
+
+ return virtex2_slave_post(fn, cookie);
+}
+
+static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
+{
+ printf("%s: Slave Serial Dumping is unsupported\n", __func__);
+ return FPGA_FAIL;
+}
+
+/* vim: set ts=4 tw=78: */
+
+struct xilinx_fpga_op virtex2_op = {
+ .load = virtex2_load,
+ .dump = virtex2_dump,
+ .info = virtex2_info,
+};
diff --git a/roms/u-boot/drivers/fpga/xilinx.c b/roms/u-boot/drivers/fpga/xilinx.c
new file mode 100644
index 000000000..cbebefb55
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/xilinx.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.com
+ */
+
+/*
+ * Xilinx FPGA support
+ */
+
+#include <common.h>
+#include <fpga.h>
+#include <log.h>
+#include <virtex2.h>
+#include <spartan2.h>
+#include <spartan3.h>
+#include <zynqpl.h>
+
+/* Local Static Functions */
+static int xilinx_validate(xilinx_desc *desc, char *fn);
+
+/* ------------------------------------------------------------------------- */
+
+int fpga_is_partial_data(int devnum, size_t img_len)
+{
+ const fpga_desc * const desc = fpga_get_desc(devnum);
+ xilinx_desc *desc_xilinx = desc->devdesc;
+
+ /* Check datasize against FPGA size */
+ if (img_len >= desc_xilinx->size)
+ return 0;
+
+ /* datasize is smaller, must be partial data */
+ return 1;
+}
+
+int fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
+ bitstream_type bstype)
+{
+ unsigned int length;
+ unsigned int swapsize;
+ 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;
+ printf(" design filename = \"%s\"\n", dataptr);
+ dataptr += length;
+
+ /* 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;
+
+ if (xdesc->name) {
+ i = (ulong)strstr((char *)dataptr, 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__, dataptr, devnum, xdesc->name);
+ return FPGA_FAIL;
+ }
+ } else {
+ printf("%s: Please fill correct device ID to xilinx_desc\n",
+ __func__);
+ }
+ printf(" part number = \"%s\"\n", dataptr);
+ dataptr += length;
+
+ /* 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;
+ printf(" date = \"%s\"\n", dataptr);
+ dataptr += length;
+
+ /* 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;
+ printf(" time = \"%s\"\n", dataptr);
+ dataptr += length;
+
+ /* 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, bstype);
+}
+
+int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
+ printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ if (!desc->operations || !desc->operations->load) {
+ printf("%s: Missing load operation\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ return desc->operations->load(desc, buf, bsize, bstype);
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+ fpga_fs_info *fpga_fsinfo)
+{
+ if (!xilinx_validate(desc, (char *)__func__)) {
+ printf("%s: Invalid device descriptor\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ if (!desc->operations || !desc->operations->loadfs) {
+ printf("%s: Missing loadfs operation\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo);
+}
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+int xilinx_loads(xilinx_desc *desc, const void *buf, size_t bsize,
+ struct fpga_secure_info *fpga_sec_info)
+{
+ if (!xilinx_validate(desc, (char *)__func__)) {
+ printf("%s: Invalid device descriptor\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ if (!desc->operations || !desc->operations->loads) {
+ printf("%s: Missing loads operation\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ return desc->operations->loads(desc, buf, bsize, fpga_sec_info);
+}
+#endif
+
+int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize)
+{
+ if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
+ printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ if (!desc->operations || !desc->operations->dump) {
+ printf("%s: Missing dump operation\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ return desc->operations->dump(desc, buf, bsize);
+}
+
+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;
+ case xilinx_zynqmp:
+ printf("ZynqMP PL\n");
+ break;
+ case xilinx_versal:
+ printf("Versal 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;
+ case csu_dma:
+ printf("csu_dma configuration interface (ZynqMP)\n");
+ break;
+ case cfi:
+ printf("CFI configuration interface (Versal)\n");
+ break;
+ /* Add new interface types here */
+ default:
+ printf ("Unsupported interface type, %d\n", desc->iface);
+ }
+
+ printf("Device Size: \t%zd 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);
+ else
+ printf ("No Device Function Table.\n");
+
+ if (desc->operations && desc->operations->info)
+ desc->operations->info(desc);
+
+ 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/roms/u-boot/drivers/fpga/zynqmppl.c b/roms/u-boot/drivers/fpga/zynqmppl.c
new file mode 100644
index 000000000..6b394869d
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/zynqmppl.c
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2015 - 2016, Xilinx, Inc,
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad <siva.durga.paladugu@xilinx.com>
+ */
+
+#include <console.h>
+#include <common.h>
+#include <compiler.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <zynqmppl.h>
+#include <zynqmp_firmware.h>
+#include <asm/cache.h>
+#include <linux/bitops.h>
+#include <linux/sizes.h>
+#include <asm/arch/sys_proto.h>
+#include <memalign.h>
+
+#define DUMMY_WORD 0xffffffff
+
+/* Xilinx binary format header */
+static const u32 bin_format[] = {
+ DUMMY_WORD, /* Dummy words */
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ DUMMY_WORD,
+ 0x000000bb, /* Sync word */
+ 0x11220044, /* Sync word */
+ DUMMY_WORD,
+ DUMMY_WORD,
+ 0xaa995566, /* Sync word */
+};
+
+#define SWAP_NO 1
+#define SWAP_DONE 2
+
+/*
+ * Load the whole word from unaligned buffer
+ * Keep in your mind that it is byte loading on little-endian system
+ */
+static u32 load_word(const void *buf, u32 swap)
+{
+ u32 word = 0;
+ u8 *bitc = (u8 *)buf;
+ int p;
+
+ if (swap == SWAP_NO) {
+ for (p = 0; p < 4; p++) {
+ word <<= 8;
+ word |= bitc[p];
+ }
+ } else {
+ for (p = 3; p >= 0; p--) {
+ word <<= 8;
+ word |= bitc[p];
+ }
+ }
+
+ return word;
+}
+
+static u32 check_header(const void *buf)
+{
+ u32 i, pattern;
+ int swap = SWAP_NO;
+ u32 *test = (u32 *)buf;
+
+ debug("%s: Let's check bitstream header\n", __func__);
+
+ /* Checking that passing bin is not a bitstream */
+ for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
+ pattern = load_word(&test[i], swap);
+
+ /*
+ * Bitstreams in binary format are swapped
+ * compare to regular bistream.
+ * Do not swap dummy word but if swap is done assume
+ * that parsing buffer is binary format
+ */
+ if ((__swab32(pattern) != DUMMY_WORD) &&
+ (__swab32(pattern) == bin_format[i])) {
+ swap = SWAP_DONE;
+ debug("%s: data swapped - let's swap\n", __func__);
+ }
+
+ debug("%s: %d/%px: pattern %x/%x bin_format\n", __func__, i,
+ &test[i], pattern, bin_format[i]);
+ }
+ debug("%s: Found bitstream header at %px %s swapinng\n", __func__,
+ buf, swap == SWAP_NO ? "without" : "with");
+
+ return swap;
+}
+
+static void *check_data(u8 *buf, size_t bsize, u32 *swap)
+{
+ u32 word, p = 0; /* possition */
+
+ /* Because buf doesn't need to be aligned let's read it by chars */
+ for (p = 0; p < bsize; p++) {
+ word = load_word(&buf[p], SWAP_NO);
+ debug("%s: word %x %x/%px\n", __func__, word, p, &buf[p]);
+
+ /* Find the first bitstream dummy word */
+ if (word == DUMMY_WORD) {
+ debug("%s: Found dummy word at position %x/%px\n",
+ __func__, p, &buf[p]);
+ *swap = check_header(&buf[p]);
+ if (*swap) {
+ /* FIXME add full bitstream checking here */
+ return &buf[p];
+ }
+ }
+ /* Loop can be huge - support CTRL + C */
+ if (ctrlc())
+ return NULL;
+ }
+ return NULL;
+}
+
+static ulong zynqmp_align_dma_buffer(u32 *buf, u32 len, u32 swap)
+{
+ u32 *new_buf;
+ u32 i;
+
+ if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
+ new_buf = (u32 *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
+
+ /*
+ * This might be dangerous but permits to flash if
+ * ARCH_DMA_MINALIGN is greater than header size
+ */
+ if (new_buf > (u32 *)buf) {
+ debug("%s: Aligned buffer is after buffer start\n",
+ __func__);
+ new_buf -= ARCH_DMA_MINALIGN;
+ }
+ printf("%s: Align buffer at %px to %px(swap %d)\n", __func__,
+ buf, new_buf, swap);
+
+ for (i = 0; i < (len/4); i++)
+ new_buf[i] = load_word(&buf[i], swap);
+
+ buf = new_buf;
+ } else if ((swap != SWAP_DONE) &&
+ (zynqmp_firmware_version() <= PMUFW_V1_0)) {
+ /* For bitstream which are aligned */
+ new_buf = buf;
+
+ printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
+ swap);
+
+ for (i = 0; i < (len/4); i++)
+ new_buf[i] = load_word(&buf[i], swap);
+ }
+
+ return (ulong)buf;
+}
+
+static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf,
+ size_t bsize, u32 blocksize, u32 *swap)
+{
+ ulong *buf_start;
+ ulong diff;
+
+ buf_start = check_data((u8 *)buf, blocksize, swap);
+
+ if (!buf_start)
+ return FPGA_FAIL;
+
+ /* Check if data is postpone from start */
+ diff = (ulong)buf_start - (ulong)buf;
+ if (diff) {
+ printf("%s: Bitstream is not validated yet (diff %lx)\n",
+ __func__, diff);
+ return FPGA_FAIL;
+ }
+
+ if ((ulong)buf < SZ_1M) {
+ printf("%s: Bitstream has to be placed up to 1MB (%px)\n",
+ __func__, buf);
+ return FPGA_FAIL;
+ }
+
+ return 0;
+}
+
+static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(u32, bsizeptr, 1);
+ u32 swap = 0;
+ ulong bin_buf;
+ int ret;
+ u32 buf_lo, buf_hi;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ bool xilfpga_old = false;
+
+ if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+ puts("WARN: PMUFW v1.0 or less is detected\n");
+ puts("WARN: Not all bitstream formats are supported\n");
+ puts("WARN: Please upgrade PMUFW\n");
+ xilfpga_old = true;
+ if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap))
+ return FPGA_FAIL;
+ bsizeptr = (u32 *)&bsize;
+ flush_dcache_range((ulong)bsizeptr,
+ (ulong)bsizeptr + sizeof(size_t));
+ bstype |= BIT(ZYNQMP_FPGA_BIT_NS);
+ }
+
+ bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap);
+
+ debug("%s called!\n", __func__);
+ flush_dcache_range(bin_buf, bin_buf + bsize);
+
+ buf_lo = (u32)bin_buf;
+ buf_hi = upper_32_bits(bin_buf);
+
+ if (xilfpga_old)
+ ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
+ buf_hi, (u32)(uintptr_t)bsizeptr,
+ bstype, ret_payload);
+ else
+ ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
+ buf_hi, (u32)bsize, 0, ret_payload);
+
+ if (ret)
+ printf("PL FPGA LOAD failed with err: 0x%08x\n", ret);
+
+ return ret;
+}
+
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) && !defined(CONFIG_SPL_BUILD)
+static int zynqmp_loads(xilinx_desc *desc, const void *buf, size_t bsize,
+ struct fpga_secure_info *fpga_sec_info)
+{
+ int ret;
+ u32 buf_lo, buf_hi;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ u8 flag = 0;
+
+ flush_dcache_range((ulong)buf, (ulong)buf +
+ ALIGN(bsize, CONFIG_SYS_CACHELINE_SIZE));
+
+ if (!fpga_sec_info->encflag)
+ flag |= BIT(ZYNQMP_FPGA_BIT_ENC_DEV_KEY);
+
+ if (fpga_sec_info->userkey_addr &&
+ fpga_sec_info->encflag == FPGA_ENC_USR_KEY) {
+ flush_dcache_range((ulong)fpga_sec_info->userkey_addr,
+ (ulong)fpga_sec_info->userkey_addr +
+ ALIGN(KEY_PTR_LEN,
+ CONFIG_SYS_CACHELINE_SIZE));
+ flag |= BIT(ZYNQMP_FPGA_BIT_ENC_USR_KEY);
+ }
+
+ if (!fpga_sec_info->authflag)
+ flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_OCM);
+
+ if (fpga_sec_info->authflag == ZYNQMP_FPGA_AUTH_DDR)
+ flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_DDR);
+
+ buf_lo = lower_32_bits((ulong)buf);
+ buf_hi = upper_32_bits((ulong)buf);
+
+ ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo,
+ buf_hi,
+ (u32)(uintptr_t)fpga_sec_info->userkey_addr,
+ flag, ret_payload);
+ if (ret)
+ puts("PL FPGA LOAD fail\n");
+ else
+ puts("Bitstream successfully loaded\n");
+
+ return ret;
+}
+#endif
+
+static int zynqmp_pcap_info(xilinx_desc *desc)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ ret = xilinx_pm_request(PM_FPGA_GET_STATUS, 0, 0, 0,
+ 0, ret_payload);
+ if (!ret)
+ printf("PCAP status\t0x%x\n", ret_payload[1]);
+
+ return ret;
+}
+
+struct xilinx_fpga_op zynqmp_op = {
+ .load = zynqmp_load,
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) && !defined(CONFIG_SPL_BUILD)
+ .loads = zynqmp_loads,
+#endif
+ .info = zynqmp_pcap_info,
+};
diff --git a/roms/u-boot/drivers/fpga/zynqpl.c b/roms/u-boot/drivers/fpga/zynqpl.c
new file mode 100644
index 000000000..2de40109a
--- /dev/null
+++ b/roms/u-boot/drivers/fpga/zynqpl.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012-2013, Xilinx, Michal Simek
+ *
+ * (C) Copyright 2012
+ * Joe Hershberger <joe.hershberger@ni.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <fs.h>
+#include <zynqpl.h>
+#include <linux/delay.h>
+#include <linux/sizes.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+#define DEVCFG_CTRL_PCFG_PROG_B 0x40000000
+#define DEVCFG_CTRL_PCFG_AES_EFUSE_MASK 0x00001000
+#define DEVCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000
+#define DEVCFG_CTRL_PCFG_AES_EN_MASK 0x00000E00
+#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
+
+#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 NULL;
+ }
+ return NULL;
+}
+
+static int zynq_dma_transfer(u32 srcbuf, u32 srclen, u32 dstbuf, u32 dstlen)
+{
+ unsigned long ts;
+ u32 isr_status;
+
+ /* Set up the transfer */
+ writel((u32)srcbuf, &devcfg_base->dma_src_addr);
+ writel(dstbuf, &devcfg_base->dma_dst_addr);
+ writel(srclen, &devcfg_base->dma_src_len);
+ writel(dstlen, &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__);
+
+ /* Clear out the DMA status */
+ writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
+
+ return FPGA_SUCCESS;
+}
+
+static int zynq_dma_xfer_init(bitstream_type bstype)
+{
+ u32 status, control, isr_status;
+ unsigned long ts;
+
+ /* Clear loopback bit */
+ clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
+
+ if (bstype != BIT_PARTIAL && bstype != BIT_NONE) {
+ 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);
+
+ /*
+ * Delay is required if AES efuse is selected as
+ * key source.
+ */
+ if (control & DEVCFG_CTRL_PCFG_AES_EFUSE_MASK)
+ mdelay(5);
+
+ /* Setting PCFG_PROG_B signal to low */
+ writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
+
+ /*
+ * Delay is required if AES efuse is selected as
+ * key source.
+ */
+ if (control & DEVCFG_CTRL_PCFG_AES_EFUSE_MASK)
+ mdelay(5);
+
+ /* 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);
+ }
+
+ return FPGA_SUCCESS;
+}
+
+static u32 *zynq_align_dma_buffer(u32 *buf, u32 len, u32 swap)
+{
+ u32 *new_buf;
+ u32 i;
+
+ if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) {
+ new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN);
+
+ /*
+ * This might be dangerous but permits to flash if
+ * ARCH_DMA_MINALIGN is greater than header size
+ */
+ if (new_buf > buf) {
+ debug("%s: Aligned buffer is after buffer start\n",
+ __func__);
+ new_buf = (u32 *)((u32)new_buf - ARCH_DMA_MINALIGN);
+ }
+ printf("%s: Align buffer at %x to %x(swap %d)\n", __func__,
+ (u32)buf, (u32)new_buf, swap);
+
+ for (i = 0; i < (len/4); i++)
+ new_buf[i] = load_word(&buf[i], swap);
+
+ buf = new_buf;
+ } else if (swap != SWAP_DONE) {
+ /* For bitstream which are aligned */
+ u32 *new_buf = (u32 *)buf;
+
+ printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
+ swap);
+
+ for (i = 0; i < (len/4); i++)
+ new_buf[i] = load_word(&buf[i], swap);
+ }
+
+ return buf;
+}
+
+static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
+ size_t bsize, u32 blocksize, u32 *swap,
+ bitstream_type *bstype)
+{
+ u32 *buf_start;
+ u32 diff;
+
+ buf_start = check_data((u8 *)buf, blocksize, 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 (zynq_dma_xfer_init(*bstype))
+ return FPGA_FAIL;
+
+ return 0;
+}
+
+static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
+ bitstream_type bstype)
+{
+ unsigned long ts; /* Timestamp */
+ u32 isr_status, swap;
+
+ /*
+ * send bsize inplace of blocksize as it was not a bitstream
+ * in chunks
+ */
+ if (zynq_validate_bitstream(desc, buf, bsize, bsize, &swap,
+ &bstype))
+ return FPGA_FAIL;
+
+ buf = zynq_align_dma_buffer((u32 *)buf, bsize, swap);
+
+ 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));
+
+ if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
+ return FPGA_FAIL;
+
+ isr_status = readl(&devcfg_base->int_sts);
+ /* 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__);
+
+ if (bstype != BIT_PARTIAL)
+ zynq_slcr_devcfg_enable();
+
+ puts("INFO:post config was not run, please run manually if needed\n");
+
+ return FPGA_SUCCESS;
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS) && !defined(CONFIG_SPL_BUILD)
+static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+ fpga_fs_info *fsinfo)
+{
+ unsigned long ts; /* Timestamp */
+ u32 isr_status, swap;
+ u32 partialbit = 0;
+ loff_t blocksize, actread;
+ loff_t pos = 0;
+ int fstype;
+ char *interface, *dev_part;
+ const char *filename;
+
+ blocksize = fsinfo->blocksize;
+ interface = fsinfo->interface;
+ dev_part = fsinfo->dev_part;
+ filename = fsinfo->filename;
+ fstype = fsinfo->fstype;
+
+ if (fs_set_blk_dev(interface, dev_part, fstype))
+ return FPGA_FAIL;
+
+ if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
+ return FPGA_FAIL;
+
+ if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap,
+ &partialbit))
+ return FPGA_FAIL;
+
+ dcache_disable();
+
+ do {
+ buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+ if (zynq_dma_transfer((u32)buf | 1, blocksize >> 2,
+ 0xffffffff, 0))
+ return FPGA_FAIL;
+
+ bsize -= blocksize;
+ pos += blocksize;
+
+ if (fs_set_blk_dev(interface, dev_part, fstype))
+ return FPGA_FAIL;
+
+ if (bsize > blocksize) {
+ if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
+ return FPGA_FAIL;
+ } else {
+ if (fs_read(filename, (u32) buf, pos, bsize, &actread) < 0)
+ return FPGA_FAIL;
+ }
+ } while (bsize > blocksize);
+
+ buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+ if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
+ return FPGA_FAIL;
+
+ dcache_enable();
+
+ isr_status = readl(&devcfg_base->int_sts);
+
+ /* 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__);
+
+ if (!partialbit)
+ zynq_slcr_devcfg_enable();
+
+ return FPGA_SUCCESS;
+}
+#endif
+
+struct xilinx_fpga_op zynq_op = {
+ .load = zynq_load,
+#if defined(CONFIG_CMD_FPGA_LOADFS) && !defined(CONFIG_SPL_BUILD)
+ .loadfs = zynq_loadfs,
+#endif
+};
+
+#ifdef CONFIG_CMD_ZYNQ_AES
+/*
+ * Load the encrypted image from src addr and decrypt the image and
+ * place it back the decrypted image into dstaddr.
+ */
+int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen,
+ u8 bstype)
+{
+ u32 isr_status, ts;
+
+ if (srcaddr < SZ_1M || dstaddr < SZ_1M) {
+ printf("%s: src and dst addr should be > 1M\n",
+ __func__);
+ return FPGA_FAIL;
+ }
+
+ /* Check AES engine is enabled */
+ if (!(readl(&devcfg_base->ctrl) &
+ DEVCFG_CTRL_PCFG_AES_EN_MASK)) {
+ printf("%s: AES engine is not enabled\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ if (zynq_dma_xfer_init(bstype)) {
+ printf("%s: zynq_dma_xfer_init FAIL\n", __func__);
+ return FPGA_FAIL;
+ }
+
+ writel((readl(&devcfg_base->ctrl) | DEVCFG_CTRL_PCAP_RATE_EN_MASK),
+ &devcfg_base->ctrl);
+
+ debug("%s: Source = 0x%08X\n", __func__, (u32)srcaddr);
+ debug("%s: Size = %zu\n", __func__, srclen);
+
+ /* flush(clean & invalidate) d-cache range buf */
+ flush_dcache_range((u32)srcaddr, (u32)srcaddr +
+ roundup(srclen << 2, ARCH_DMA_MINALIGN));
+ /*
+ * Flush destination address range only if image is not
+ * bitstream.
+ */
+ if (bstype == BIT_NONE && dstaddr != 0xFFFFFFFF)
+ flush_dcache_range((u32)dstaddr, (u32)dstaddr +
+ roundup(dstlen << 2, ARCH_DMA_MINALIGN));
+
+ if (zynq_dma_transfer(srcaddr | 1, srclen, dstaddr | 1, dstlen))
+ return FPGA_FAIL;
+
+ if (bstype == BIT_FULL) {
+ isr_status = readl(&devcfg_base->int_sts);
+ /* 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);
+ }
+ printf("%s: FPGA config done\n", __func__);
+ zynq_slcr_devcfg_enable();
+ }
+
+ return FPGA_SUCCESS;
+}
+#endif