Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / w7o / fpga.c
diff --git a/qemu/roms/u-boot/board/w7o/fpga.c b/qemu/roms/u-boot/board/w7o/fpga.c
new file mode 100644 (file)
index 0000000..a27e8ab
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ *  and
+ * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#include <config.h>
+#include <common.h>
+#include "w7o.h"
+#include <asm/processor.h>
+#include <linux/compiler.h>
+#include "errors.h"
+
+static void
+fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr)
+{
+       unsigned long i;
+       volatile unsigned long val;
+       volatile unsigned short *dest = daddr;  /* volatile-bypass optimizer */
+
+       for (i = 0; i < len; i++, src++) {
+               val = *src;
+               *dest = (unsigned short) ((val & 0xff000000L) >> 16);
+               *dest = (unsigned short) ((val & 0x00ff0000L) >> 8);
+               *dest = (unsigned short) (val & 0x0000ff00L);
+               *dest = (unsigned short) ((val & 0x000000ffL) << 8);
+       }
+
+       /* Terminate programming with 4 C clocks */
+       dest = daddr;
+       val = *(unsigned short *) dest;
+       val = *(unsigned short *) dest;
+       val = *(unsigned short *) dest;
+       val = *(unsigned short *) dest;
+
+}
+
+
+int
+fpgaDownload(unsigned char *saddr, unsigned long size, unsigned short *daddr)
+{
+       int i;                  /* index, intr disable flag */
+       int start;              /* timer */
+       unsigned long greg, grego;      /* GPIO & output register */
+       unsigned long length;   /* image size in words */
+       unsigned long *source;  /* image source addr */
+       unsigned short *dest;   /* destination FPGA addr */
+       volatile unsigned short *ndest; /* temp dest FPGA addr */
+       unsigned long cnfg = GPIO_XCV_CNFG;     /* FPGA CNFG */
+       unsigned long eirq = GPIO_XCV_IRQ;
+       int retval = -1;        /* Function return value */
+       __maybe_unused volatile unsigned short val;     /* temp val */
+
+       /* Setup some basic values */
+       length = (size / 4) + 1;        /* size in words, rounding UP
+                                          is OK */
+       source = (unsigned long *) saddr;
+       dest = (unsigned short *) daddr;
+
+       /* Get DCR output register */
+       grego = in32(PPC405GP_GPIO0_OR);
+
+       /* Reset FPGA */
+       grego &= ~GPIO_XCV_PROG;        /* PROG line low */
+       out32(PPC405GP_GPIO0_OR, grego);
+
+       /* Setup timeout timer */
+       start = get_timer(0);
+
+       /* Wait for FPGA init line to go low */
+       while (in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT) {
+               /* Check for timeout - 100us max, so use 3ms */
+               if (get_timer(start) > 3) {
+                       printf("     failed to start init.\n");
+                       log_warn(ERR_XINIT0);   /* Don't halt */
+
+                       /* Reset line stays low */
+                       goto done;      /* I like gotos... */
+               }
+       }
+
+       /* Unreset FPGA */
+       grego |= GPIO_XCV_PROG; /* PROG line high */
+       out32(PPC405GP_GPIO0_OR, grego);
+
+       /* Wait for FPGA end of init period = init line go hi  */
+       while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT)) {
+
+               /* Check for timeout */
+               if (get_timer(start) > 3) {
+                       printf("     failed to exit init.\n");
+                       log_warn(ERR_XINIT1);
+
+                       /* Reset FPGA */
+                       grego &= ~GPIO_XCV_PROG;        /* PROG line low */
+                       out32(PPC405GP_GPIO0_OR, grego);
+
+                       goto done;
+               }
+       }
+
+       /* Now program FPGA ... */
+       ndest = dest;
+       for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+               /* Toggle IRQ/GPIO */
+               greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
+               greg |= eirq;   /* toggle irq/gpio */
+               mtdcr(CPC0_CR0, greg);  /*  ... just do it */
+
+               /* turn on open drain for CNFG */
+               greg = in32(PPC405GP_GPIO0_ODR); /* get open drain register */
+               greg |= cnfg;   /* CNFG open drain */
+               out32(PPC405GP_GPIO0_ODR, greg); /*  .. just do it */
+
+               /* Turn output enable on for CNFG */
+               greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
+               greg |= cnfg;   /* CNFG tristate inactive */
+               out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
+
+               /* Setup FPGA for programming */
+               grego &= ~cnfg; /* CONFIG line low */
+               out32(PPC405GP_GPIO0_OR, grego);
+
+               /*
+                * Program the FPGA
+                */
+               printf("\n       destination: 0x%lx ", (unsigned long) ndest);
+
+               fpga_img_write(source, length, (unsigned short *) ndest);
+
+               /* Done programming */
+               grego |= cnfg;  /* CONFIG line high */
+               out32(PPC405GP_GPIO0_OR, grego);
+
+               /* Turn output enable OFF for CNFG */
+               greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
+               greg &= ~cnfg;  /* CNFG tristate inactive */
+               out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
+
+               /* Toggle IRQ/GPIO */
+               greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
+               greg &= ~eirq;  /* toggle irq/gpio */
+               mtdcr(CPC0_CR0, greg);  /*  ... just do it */
+
+               /* XXX - Next FPGA addr */
+               ndest = (unsigned short *) ((char *) ndest + 0x00100000L);
+               cnfg >>= 1;     /* XXX - Next  */
+               eirq >>= 1;
+       }
+
+       /* Terminate programming with 4 C clocks */
+       ndest = dest;
+       for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+               val = *ndest;
+               val = *ndest;
+               val = *ndest;
+               val = *ndest;
+               ndest = (unsigned short *) ((char *) ndest + 0x00100000L);
+       }
+
+       /* Setup timer */
+       start = get_timer(0);
+
+       /* Wait for FPGA end of programming period = Test DONE low  */
+       while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_DONE)) {
+
+               /* Check for timeout */
+               if (get_timer(start) > 3) {
+                       printf("     done failed to come high.\n");
+                       log_warn(ERR_XDONE1);
+
+                       /* Reset FPGA */
+                       grego &= ~GPIO_XCV_PROG;        /* PROG line low */
+                       out32(PPC405GP_GPIO0_OR, grego);
+
+                       goto done;
+               }
+       }
+
+       printf("\n       FPGA load succeeded\n");
+       retval = 0;             /* Program OK */
+
+done:
+       return retval;
+}
+
+/* FPGA image is stored in flash */
+extern flash_info_t flash_info[];
+
+int init_fpga(void)
+{
+       unsigned int i, j, ptr; /* General purpose */
+       unsigned char bufchar;  /* General purpose character */
+       unsigned char *buf;     /* Start of image pointer */
+       unsigned long len;      /* Length of image */
+       unsigned char *fn_buf;  /* Start of filename string */
+       unsigned int fn_len;    /* Length of filename string */
+       unsigned char *xcv_buf; /* Pointer to start of image */
+       unsigned long xcv_len;  /* Length of image */
+       unsigned long crc;      /* 30bit crc in image */
+       unsigned long calc_crc; /* Calc'd 30bit crc */
+       int retval = -1;
+
+       /* Tell the world what we are doing */
+       printf("FPGA:  ");
+
+       /*
+        * Get address of first sector where the FPGA
+        * image is stored.
+        */
+       buf = (unsigned char *) flash_info[1].start[0];
+
+       /*
+        * Get the stored image's CRC & length.
+        */
+       crc = *(unsigned long *) (buf + 4);     /* CRC is first long word */
+       len = *(unsigned long *) (buf + 8);     /* Image len is next long */
+
+       /* Pedantic */
+       if ((len < 0x133A4) || (len > 0x80000))
+               goto bad_image;
+
+       /*
+        * Get the file name pointer and length.
+        * filename length is next short
+        */
+       fn_len = (*(unsigned short *) (buf + 12) & 0xff);
+       fn_buf = buf + 14;
+
+       /*
+        * Get the FPGA image pointer and length length.
+        */
+       xcv_buf = fn_buf + fn_len;      /* pointer to fpga image */
+       xcv_len = len - 14 - fn_len;    /* fpga image length */
+
+       /* Check for uninitialized FLASH */
+       if ((strncmp((char *) buf, "w7o", 3) != 0) || (len > 0x0007ffffL)
+           || (len == 0))
+               goto bad_image;
+
+       /*
+        * Calculate and Check the image's CRC.
+        */
+       calc_crc = crc32(0, xcv_buf, xcv_len);
+       if (crc != calc_crc) {
+               printf("\nfailed - bad CRC\n");
+               goto done;
+       }
+
+       /* Output the file name */
+       printf("file name  : ");
+       for (i = 0; i < fn_len; i++) {
+               bufchar = fn_buf[+i];
+               if (bufchar < ' ' || bufchar > '~')
+                       bufchar = '.';
+               putc(bufchar);
+       }
+
+       /*
+        * find rest of display data
+        */
+       ptr = 15;               /* Offset to ncd filename
+                                  length in fpga image */
+       j = xcv_buf[ptr];       /* Get len of ncd filename */
+       if (j > 32)
+               goto bad_image;
+       ptr = ptr + j + 3;      /* skip ncd filename string +
+                                  3 bytes more bytes */
+
+       /*
+        * output target device string
+        */
+       j = xcv_buf[ptr++] - 1; /* len of targ str less term */
+       if (j > 32)
+               goto bad_image;
+       printf("\n       target     : ");
+       for (i = 0; i < j; i++) {
+               bufchar = (xcv_buf[ptr++]);
+               if (bufchar < ' ' || bufchar > '~')
+                       bufchar = '.';
+               putc(bufchar);
+       }
+
+       /*
+        * output compilation date string and time string
+        */
+       ptr += 3;               /* skip 2 bytes */
+       printf("\n       synth time : ");
+       j = (xcv_buf[ptr++] - 1);       /* len of date str less term */
+       if (j > 32)
+               goto bad_image;
+       for (i = 0; i < j; i++) {
+               bufchar = (xcv_buf[ptr++]);
+               if (bufchar < ' ' || bufchar > '~')
+                       bufchar = '.';
+               putc(bufchar);
+       }
+
+       ptr += 3;               /* Skip 2 bytes */
+       printf(" - ");
+       j = (xcv_buf[ptr++] - 1);       /* slen = targ dev str len */
+       if (j > 32)
+               goto bad_image;
+       for (i = 0; i < j; i++) {
+               bufchar = (xcv_buf[ptr++]);
+               if (bufchar < ' ' || bufchar > '~')
+                       bufchar = '.';
+               putc(bufchar);
+       }
+
+       /*
+        * output crc and length strings
+        */
+       printf("\n       len & crc  : 0x%lx  0x%lx", len, crc);
+
+       /*
+        * Program the FPGA.
+        */
+       retval = fpgaDownload((unsigned char *) xcv_buf, xcv_len,
+                             (unsigned short *) 0xfd000000L);
+       return retval;
+
+bad_image:
+       printf("\n       BAD FPGA image format @ %lx\n",
+              flash_info[1].start[0]);
+       log_warn(ERR_XIMAGE);
+done:
+       return retval;
+}
+
+void test_fpga(unsigned short *daddr)
+{
+       int i;
+       volatile unsigned short *ndest = daddr;
+
+       for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
+#if defined(CONFIG_W7OLMG)
+               ndest[0x7e] = 0x55aa;
+               if (ndest[0x7e] != 0x55aa)
+                       log_warn(ERR_XRW1 + i);
+               ndest[0x7e] = 0xaa55;
+               if (ndest[0x7e] != 0xaa55)
+                       log_warn(ERR_XRW1 + i);
+               ndest[0x7e] = 0xc318;
+               if (ndest[0x7e] != 0xc318)
+                       log_warn(ERR_XRW1 + i);
+
+#elif defined(CONFIG_W7OLMC)
+               ndest[0x800] = 0x55aa;
+               ndest[0x801] = 0xaa55;
+               ndest[0x802] = 0xc318;
+               ndest[0x4800] = 0x55aa;
+               ndest[0x4801] = 0xaa55;
+               ndest[0x4802] = 0xc318;
+               if ((ndest[0x800] != 0x55aa) ||
+                   (ndest[0x801] != 0xaa55) || (ndest[0x802] != 0xc318))
+                       log_warn(ERR_XRW1 + (2 * i)); /* Auto gen error code */
+               if ((ndest[0x4800] != 0x55aa) ||
+                   (ndest[0x4801] != 0xaa55) || (ndest[0x4802] != 0xc318))
+                       log_warn(ERR_XRW2 + (2 * i)); /* Auto gen error code */
+
+#else
+#error "Unknown W7O board configuration"
+#endif
+       }
+
+       printf("       FPGA ready\n");
+       return;
+}