summaryrefslogtreecommitdiff
path: root/common/cmd_fpga.c
diff options
context:
space:
mode:
authorwdenk <wdenk>2005-01-09 18:12:51 +0000
committerwdenk <wdenk>2005-01-09 18:12:51 +0000
commit30ce5ab043db0b34838ad2d294561992bdb5236a (patch)
treef1897c41bfac1193db786f52eb71854a0c3ef1cc /common/cmd_fpga.c
parent9dd611b8c1db94181918481d5cac1fac241a7954 (diff)
* Patch by Gleb Natapov, 07 Sep 2004:
mpc824x: set PCI latency timer to a sane value (is 0 after reset). * Patch by Kurt Stremerch, 03 Sep 2004: Add bitstream configuration option for fpga command (Xilinx only).
Diffstat (limited to 'common/cmd_fpga.c')
-rw-r--r--common/cmd_fpga.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 325fdd1420f..7c762bab924 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -52,8 +52,122 @@ static int fpga_get_op (char *opstr);
#define FPGA_NONE -1
#define FPGA_INFO 0
#define FPGA_LOAD 1
+#define FPGA_LOADB 2
#define FPGA_DUMP 3
+/* Convert bitstream data and load into the fpga */
+int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
+{
+ int length;
+ char* swapdata;
+ int swapsize;
+ char buffer[80];
+ char *ptr;
+ char *dataptr;
+ int data;
+ int i;
+ int rc;
+
+ dataptr = fpgadata;
+
+#if CFG_FPGA_XILINX
+ /* skip the first 13 bytes of the bitsteam, their meaning is unknown */
+ dataptr+=13;
+
+ /* get design name (identifier, length, string) */
+ if (*dataptr++ != 0x61) {
+ PRINTF(__FUNCTION__ ": Design name identifier not recognized in bitstream.\n");
+ return FPGA_FAIL;
+ }
+
+ length = (*dataptr << 8) + *(dataptr+1);
+ dataptr+=2;
+ for(i=0;i<length;i++)
+ buffer[i]=*dataptr++;
+
+ buffer[length-5]='\0'; /* remove filename extension */
+ PRINTF(__FUNCTION__ ": design name = \"%s\".\n",buffer);
+
+ /* get part number (identifier, length, string) */
+ if (*dataptr++ != 0x62) {
+ printf(__FUNCTION__ ": Part number identifier not recognized in bitstream.\n");
+ return FPGA_FAIL;
+ }
+
+ length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ for(i=0;i<length;i++)
+ buffer[i]=*dataptr++;
+ PRINTF(__FUNCTION__ ": part number = \"%s\".\n",buffer);
+
+ /* get date (identifier, length, string) */
+ if (*dataptr++ != 0x63) {
+ printf(__FUNCTION__ ": Date identifier not recognized in bitstream.\n");
+ return FPGA_FAIL;
+ }
+
+ length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ for(i=0;i<length;i++)
+ buffer[i]=*dataptr++;
+ PRINTF(__FUNCTION__ ": date = \"%s\".\n",buffer);
+
+ /* get time (identifier, length, string) */
+ if (*dataptr++ != 0x64) {
+ printf(__FUNCTION__ ": Time identifier not recognized in bitstream.\n");
+ return FPGA_FAIL;
+ }
+
+ length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
+ for(i=0;i<length;i++)
+ buffer[i]=*dataptr++;
+ PRINTF(__FUNCTION__ ": time = \"%s\".\n",buffer);
+
+ /* get fpga data length (identifier, length) */
+ if (*dataptr++ != 0x65) {
+ printf(__FUNCTION__ ": Data length identifier not recognized in bitstream.\n");
+ return FPGA_FAIL;
+ }
+ swapsize = ((long)*dataptr<<24) + ((long)*(dataptr+1)<<16) + ((long)*(dataptr+2)<<8) + (long)*(dataptr+3);
+ dataptr+=4;
+ PRINTF(__FUNCTION__ ": bytes in bitstream = %d.\n",swapsize);
+
+ /* check consistency of length obtained */
+ if (swapsize >= size) {
+ printf(__FUNCTION__ ": Could not find right length of data in bitstream.\n");
+ return FPGA_FAIL;
+ }
+
+ /* allocate memory */
+ swapdata = (char *)malloc(swapsize);
+ if (swapdata == NULL) {
+ printf(__FUNCTION__ ": Could not allocate %d bytes memory !\n",swapsize);
+ return FPGA_FAIL;
+ }
+
+ /* read data into memory and swap bits */
+ ptr = swapdata;
+ for (i = 0; i < swapsize; i++) {
+ data = 0x00;
+ data |= (*dataptr & 0x01) << 7;
+ data |= (*dataptr & 0x02) << 5;
+ data |= (*dataptr & 0x04) << 3;
+ data |= (*dataptr & 0x08) << 1;
+ data |= (*dataptr & 0x10) >> 1;
+ data |= (*dataptr & 0x20) >> 3;
+ data |= (*dataptr & 0x40) >> 5;
+ data |= (*dataptr & 0x80) >> 7;
+ *ptr++ = data;
+ dataptr++;
+ }
+
+ rc = fpga_load(dev, swapdata, swapsize);
+ free(swapdata);
+ return rc;
+#else
+ printf("Bitstream support only for Xilinx devices.\n");
+ return FPGA_FAIL;
+#endif
+}
+
/* ------------------------------------------------------------------------- */
/* command form:
* fpga <op> <device number> <data addr> <datasize>
@@ -118,6 +232,10 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
rc = fpga_load (dev, fpga_data, data_size);
break;
+ case FPGA_LOADB:
+ rc = fpga_loadbitstream(dev, fpga_data, data_size);
+ break;
+
case FPGA_DUMP:
rc = fpga_dump (dev, fpga_data, data_size);
break;
@@ -145,6 +263,8 @@ static int fpga_get_op (char *opstr)
if (!strcmp ("info", opstr)) {
op = FPGA_INFO;
+ } else if (!strcmp ("loadb", opstr)) {
+ op = FPGA_LOADB;
} else if (!strcmp ("load", opstr)) {
op = FPGA_LOAD;
} else if (!strcmp ("dump", opstr)) {
@@ -163,5 +283,6 @@ U_BOOT_CMD (fpga, 6, 1, do_fpga,
"fpga operations:\n"
"\tinfo\tlist known device information.\n"
"\tload\tLoad device from memory buffer.\n"
+ "\tloadb\tLoad device from bitstream buffer (Xilinx devices only).\n"
"\tdump\tLoad device to memory buffer.\n");
#endif /* CONFIG_FPGA && CONFIG_COMMANDS & CFG_CMD_FPGA */