Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / drivers / fpga / lattice.c
diff --git a/qemu/roms/u-boot/drivers/fpga/lattice.c b/qemu/roms/u-boot/drivers/fpga/lattice.c
new file mode 100644 (file)
index 0000000..615a485
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * ispVM functions adapted from Lattice's ispmVMEmbedded code:
+ * Copyright 2009 Lattice Semiconductor Corp.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <fpga.h>
+#include <lattice.h>
+
+static lattice_board_specific_func *pfns;
+static const char *fpga_image;
+static unsigned long read_bytes;
+static unsigned long bufsize;
+static unsigned short expectedCRC;
+
+/*
+ * External variables and functions declared in ivm_core.c module.
+ */
+extern unsigned short g_usCalculatedCRC;
+extern unsigned short g_usDataType;
+extern unsigned char *g_pucIntelBuffer;
+extern unsigned char *g_pucHeapMemory;
+extern unsigned short g_iHeapCounter;
+extern unsigned short g_iHEAPSize;
+extern unsigned short g_usIntelDataIndex;
+extern unsigned short g_usIntelBufferSize;
+extern char *const g_szSupportedVersions[];
+
+
+/*
+ * ispVMDelay
+ *
+ * Users must implement a delay to observe a_usTimeDelay, where
+ * bit 15 of the a_usTimeDelay defines the unit.
+ *      1 = milliseconds
+ *      0 = microseconds
+ * Example:
+ *      a_usTimeDelay = 0x0001 = 1 microsecond delay.
+ *      a_usTimeDelay = 0x8001 = 1 millisecond delay.
+ *
+ * This subroutine is called upon to provide a delay from 1 millisecond to a few
+ * hundreds milliseconds each time.
+ * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16
+ * bits integer, this function is restricted to produce a delay to 64000
+ * micro-seconds or 32000 milli-second maximum. The VME file will never pass on
+ * to this function a delay time > those maximum number. If it needs more than
+ * those maximum, the VME file will launch the delay function several times to
+ * realize a larger delay time cummulatively.
+ * It is perfectly alright to provide a longer delay than required. It is not
+ * acceptable if the delay is shorter.
+ */
+void ispVMDelay(unsigned short delay)
+{
+       if (delay & 0x8000)
+               delay = (delay & ~0x8000) * 1000;
+       udelay(delay);
+}
+
+void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
+{
+       a_ucValue = a_ucValue ? 1 : 0;
+
+       switch (a_ucPins) {
+       case g_ucPinTDI:
+               pfns->jtag_set_tdi(a_ucValue);
+               break;
+       case g_ucPinTCK:
+               pfns->jtag_set_tck(a_ucValue);
+               break;
+       case g_ucPinTMS:
+               pfns->jtag_set_tms(a_ucValue);
+               break;
+       default:
+               printf("%s: requested unknown pin\n", __func__);
+       }
+}
+
+unsigned char readPort(void)
+{
+       return pfns->jtag_get_tdo();
+}
+
+void sclock(void)
+{
+       writePort(g_ucPinTCK, 0x01);
+       writePort(g_ucPinTCK, 0x00);
+}
+
+void calibration(void)
+{
+       /* Apply 2 pulses to TCK. */
+       writePort(g_ucPinTCK, 0x00);
+       writePort(g_ucPinTCK, 0x01);
+       writePort(g_ucPinTCK, 0x00);
+       writePort(g_ucPinTCK, 0x01);
+       writePort(g_ucPinTCK, 0x00);
+
+       ispVMDelay(0x8001);
+
+       /* Apply 2 pulses to TCK. */
+       writePort(g_ucPinTCK, 0x01);
+       writePort(g_ucPinTCK, 0x00);
+       writePort(g_ucPinTCK, 0x01);
+       writePort(g_ucPinTCK, 0x00);
+}
+
+/*
+ * GetByte
+ *
+ * Returns a byte to the caller. The returned byte depends on the
+ * g_usDataType register. If the HEAP_IN bit is set, then the byte
+ * is returned from the HEAP. If the LHEAP_IN bit is set, then
+ * the byte is returned from the intelligent buffer. Otherwise,
+ * the byte is returned directly from the VME file.
+ */
+unsigned char GetByte(void)
+{
+       unsigned char ucData;
+       unsigned int block_size = 4 * 1024;
+
+       if (g_usDataType & HEAP_IN) {
+
+               /*
+                * Get data from repeat buffer.
+                */
+
+               if (g_iHeapCounter > g_iHEAPSize) {
+
+                       /*
+                        * Data over-run.
+                        */
+
+                       return 0xFF;
+               }
+
+               ucData = g_pucHeapMemory[g_iHeapCounter++];
+       } else if (g_usDataType & LHEAP_IN) {
+
+               /*
+                * Get data from intel buffer.
+                */
+
+               if (g_usIntelDataIndex >= g_usIntelBufferSize) {
+                       return 0xFF;
+               }
+
+               ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
+       } else {
+               if (read_bytes == bufsize) {
+                       return 0xFF;
+               }
+               ucData = *fpga_image++;
+               read_bytes++;
+
+               if (!(read_bytes % block_size)) {
+                       printf("Downloading FPGA %ld/%ld completed\r",
+                               read_bytes,
+                               bufsize);
+               }
+
+               if (expectedCRC != 0) {
+                       ispVMCalculateCRC32(ucData);
+               }
+       }
+
+       return ucData;
+}
+
+signed char ispVM(void)
+{
+       char szFileVersion[9]      = { 0 };
+       signed char cRetCode         = 0;
+       signed char cIndex           = 0;
+       signed char cVersionIndex    = 0;
+       unsigned char ucReadByte     = 0;
+       unsigned short crc;
+
+       g_pucHeapMemory         = NULL;
+       g_iHeapCounter          = 0;
+       g_iHEAPSize             = 0;
+       g_usIntelDataIndex      = 0;
+       g_usIntelBufferSize     = 0;
+       g_usCalculatedCRC = 0;
+       expectedCRC   = 0;
+       ucReadByte = GetByte();
+       switch (ucReadByte) {
+       case FILE_CRC:
+               crc = (unsigned char)GetByte();
+               crc <<= 8;
+               crc |= GetByte();
+               expectedCRC = crc;
+
+               for (cIndex = 0; cIndex < 8; cIndex++)
+                       szFileVersion[cIndex] = GetByte();
+
+               break;
+       default:
+               szFileVersion[0] = (signed char) ucReadByte;
+               for (cIndex = 1; cIndex < 8; cIndex++)
+                       szFileVersion[cIndex] = GetByte();
+
+               break;
+       }
+
+       /*
+        *
+        * Compare the VME file version against the supported version.
+        *
+        */
+
+       for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0;
+               cVersionIndex++) {
+               for (cIndex = 0; cIndex < 8; cIndex++) {
+                       if (szFileVersion[cIndex] !=
+                               g_szSupportedVersions[cVersionIndex][cIndex]) {
+                               cRetCode = VME_VERSION_FAILURE;
+                               break;
+                       }
+                       cRetCode = 0;
+               }
+
+               if (cRetCode == 0) {
+                       break;
+               }
+       }
+
+       if (cRetCode < 0) {
+               return VME_VERSION_FAILURE;
+       }
+
+       printf("VME file checked: starting downloading to FPGA\n");
+
+       ispVMStart();
+
+       cRetCode = ispVMCode();
+
+       ispVMEnd();
+       ispVMFreeMem();
+       puts("\n");
+
+       if (cRetCode == 0 && expectedCRC != 0 &&
+                       (expectedCRC != g_usCalculatedCRC)) {
+               printf("Expected CRC:   0x%.4X\n", expectedCRC);
+               printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
+               return VME_CRC_FAILURE;
+       }
+       return cRetCode;
+}
+
+static int lattice_validate(Lattice_desc *desc, const char *fn)
+{
+       int ret_val = false;
+
+       if (desc) {
+               if ((desc->family > min_lattice_type) &&
+                       (desc->family < max_lattice_type)) {
+                       if ((desc->iface > min_lattice_iface_type) &&
+                               (desc->iface < max_lattice_iface_type)) {
+                               if (desc->size) {
+                                       ret_val = true;
+                               } else {
+                                       printf("%s: NULL part size\n", fn);
+                               }
+                       } else {
+                               printf("%s: Invalid Interface type, %d\n",
+                                       fn, desc->iface);
+                       }
+               } else {
+                       printf("%s: Invalid family type, %d\n",
+                               fn, desc->family);
+               }
+       } else {
+               printf("%s: NULL descriptor!\n", fn);
+       }
+
+       return ret_val;
+}
+
+int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;
+
+       if (!lattice_validate(desc, (char *)__func__)) {
+               printf("%s: Invalid device descriptor\n", __func__);
+       } else {
+               pfns = desc->iface_fns;
+
+               switch (desc->family) {
+               case Lattice_XP2:
+                       fpga_image = buf;
+                       read_bytes = 0;
+                       bufsize = bsize;
+                       debug("%s: Launching the Lattice ISPVME Loader:"
+                               " addr %p size 0x%lx...\n",
+                               __func__, fpga_image, bufsize);
+                       ret_val = ispVM();
+                       if (ret_val)
+                               printf("%s: error %d downloading FPGA image\n",
+                                       __func__, ret_val);
+                       else
+                               puts("FPGA downloaded successfully\n");
+                       break;
+               default:
+                       printf("%s: Unsupported family type, %d\n",
+                                       __func__, desc->family);
+               }
+       }
+
+       return ret_val;
+}
+
+int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize)
+{
+       puts("Dump not supported for Lattice FPGA\n");
+
+       return FPGA_FAIL;
+
+}
+
+int lattice_info(Lattice_desc *desc)
+{
+       int ret_val = FPGA_FAIL;
+
+       if (lattice_validate(desc, (char *)__func__)) {
+               printf("Family:        \t");
+               switch (desc->family) {
+               case Lattice_XP2:
+                       puts("XP2\n");
+                       break;
+                       /* Add new family types here */
+               default:
+                       printf("Unknown family type, %d\n", desc->family);
+               }
+
+               puts("Interface type:\t");
+               switch (desc->iface) {
+               case lattice_jtag_mode:
+                       puts("JTAG Mode\n");
+                       break;
+                       /* Add new interface types here */
+               default:
+                       printf("Unsupported interface type, %d\n", desc->iface);
+               }
+
+               printf("Device Size:   \t%d bytes\n",
+                               desc->size);
+
+               if (desc->iface_fns) {
+                       printf("Device Function Table @ 0x%p\n",
+                               desc->iface_fns);
+                       switch (desc->family) {
+                       case Lattice_XP2:
+                               break;
+                               /* Add new family types here */
+                       default:
+                               break;
+                       }
+               } else {
+                       puts("No Device Function Table.\n");
+               }
+
+               if (desc->desc)
+                       printf("Model:         \t%s\n", desc->desc);
+
+               ret_val = FPGA_SUCCESS;
+       } else {
+               printf("%s: Invalid device descriptor\n", __func__);
+       }
+
+       return ret_val;
+}