]> Git Repo - J-u-boot.git/blobdiff - drivers/fpga/virtex2.c
Merge branch 'next'
[J-u-boot.git] / drivers / fpga / virtex2.c
index 502824424cd7327552966c46ff9643538e139ff1..b3e0537bab07d08363a023a486f60250b59340a4 100644 (file)
@@ -3,6 +3,8 @@
  * (C) Copyright 2002
  * Rich Ireland, Enterasys Networks, [email protected].
  * Keith Outwater, [email protected]
+ *
+ * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
  */
 
 /*
@@ -13,6 +15,7 @@
 #include <common.h>
 #include <console.h>
 #include <virtex2.h>
+#include <linux/delay.h>
 
 #if 0
 #define FPGA_DEBUG
@@ -141,8 +144,8 @@ static int virtex2_info(xilinx_desc *desc)
 }
 
 /*
- * Virtex-II Slave SelectMap configuration loader. Configuration via
- * SelectMap is as follows:
+ * 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
@@ -154,7 +157,7 @@ static int virtex2_info(xilinx_desc *desc)
  *    INIT_B and DONE lines.  If both are high, configuration has
  *    succeeded. Congratulations!
  */
-static int virtex2_slave_pre(xilinx_virtex2_slave_selectmap_fns *fn, int cookie)
+static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
 {
        unsigned long ts;
 
@@ -243,7 +246,7 @@ static int virtex2_slave_pre(xilinx_virtex2_slave_selectmap_fns *fn, int cookie)
        return FPGA_SUCCESS;
 }
 
-static int virtex2_slave_post(xilinx_virtex2_slave_selectmap_fns *fn,
+static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
                              int cookie)
 {
        int ret_val = FPGA_SUCCESS;
@@ -284,11 +287,16 @@ static int virtex2_slave_post(xilinx_virtex2_slave_selectmap_fns *fn,
                        ret_val = FPGA_FAIL;
                        break;
                }
-               (*fn->wdata) (0xff, true, cookie);
-               CONFIG_FPGA_DELAY();
-               (*fn->clk) (false, true, cookie);
-               CONFIG_FPGA_DELAY();
-               (*fn->clk) (true, true, cookie);
+               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) {
@@ -312,7 +320,7 @@ static int virtex2_slave_post(xilinx_virtex2_slave_selectmap_fns *fn,
 static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
 {
        int ret_val = FPGA_FAIL;
-       xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
+       xilinx_virtex2_slave_fns *fn = desc->iface_fns;
        size_t bytecount = 0;
        unsigned char *data = (unsigned char *)buf;
        int cookie = desc->cookie;
@@ -387,7 +395,7 @@ 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)
 {
        int ret_val = FPGA_FAIL;
-       xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
+       xilinx_virtex2_slave_fns *fn = desc->iface_fns;
 
        if (fn) {
                unsigned char *data = (unsigned char *)buf;
@@ -438,8 +446,71 @@ 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)
 {
-       printf("%s: Slave Serial Loading is unsupported\n", __func__);
-       return FPGA_FAIL;
+       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)
This page took 0.030868 seconds and 4 git commands to generate.