common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / fpga / virtex2.c
index 0d2d9a4693264684bbeb5167790057c0ae07b732..b3e0537bab07d08363a023a486f60250b59340a4 100644 (file)
@@ -1,9 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2002
  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  * Keith Outwater, keith_outwater@mvis.com
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
  */
 
 /*
  */
 
 #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)
+#define        PRINTF(fmt, args...)    printf(fmt, ##args)
 #else
-#define PRINTF(fmt,args...)
+#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.
+ * 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
@@ -65,7 +68,7 @@
  * 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 */
+#define CONFIG_SYS_FPGA_WAIT_INIT      CONFIG_SYS_HZ / 2       /* 500 ms */
 #endif
 
 /*
  * 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*/
+#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 */
+#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);
@@ -97,18 +100,18 @@ static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
 
        switch (desc->iface) {
        case slave_serial:
-               PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+               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", __FUNCTION__);
+               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",
-                               __FUNCTION__, desc->iface);
+               printf("%s: Unsupported interface type, %d\n",
+                      __func__, desc->iface);
        }
        return ret_val;
 }
@@ -119,18 +122,18 @@ static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
 
        switch (desc->iface) {
        case slave_serial:
-               PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+               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", __FUNCTION__);
+               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",
-                               __FUNCTION__, desc->iface);
+               printf("%s: Unsupported interface type, %d\n",
+                      __func__, desc->iface);
        }
        return ret_val;
 }
@@ -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,200 +157,236 @@ static int virtex2_info(xilinx_desc *desc)
  *    INIT_B and DONE lines.  If both are high, configuration has
  *    succeeded. Congratulations!
  */
-static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
+static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
 {
-       int ret_val = FPGA_FAIL;
-       xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
+       unsigned long ts;
 
-       PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
-                       __FUNCTION__, __LINE__, fn);
+       PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
+              __func__, __LINE__, fn);
 
-       if (fn) {
-               size_t bytecount = 0;
-               unsigned char *data = (unsigned char *) buf;
-               int cookie = desc->cookie;
-               unsigned long ts;
-
-               /* 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",
-                               __FUNCTION__, __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);
+       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);
+       printf("Initializing FPGA Device %d...\n", cookie);
 #endif
-               /*
-                * Run the pre configuration function if there is one.
-                */
-               if (*fn->pre) {
-                       (*fn->pre) (cookie);
+       /*
+        * 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));
 
-               /*
-                * 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", __FUNCTION__, __LINE__,
-                                               CONFIG_SYS_FPGA_WAIT_INIT);
-                               (*fn->abort) (cookie);
-                               return FPGA_FAIL;
-                       }
-               } while (!(*fn->init) (cookie));
+       if (fn->wr)
+               (*fn->wr)(true, true, cookie);
+       if (fn->cs)
+               (*fn->cs)(true, true, cookie);
 
-               (*fn->pgm) (false, true, cookie);
-               CONFIG_FPGA_DELAY ();
-               (*fn->clk) (true, true, cookie);
+       mdelay(10);
+       return FPGA_SUCCESS;
+}
 
-               /*
-                * 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", __FUNCTION__, __LINE__,
-                                               CONFIG_SYS_FPGA_WAIT_INIT);
-                               (*fn->abort) (cookie);
-                               return FPGA_FAIL;
-                       }
-               } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
+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);
 
-               (*fn->wr) (true, true, cookie);
-               (*fn->cs) (true, true, cookie);
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+       putc('\n');
+#endif
 
-               udelay (10000);
+       /*
+        * 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
                /*
-                * Load the data byte by byte
+                * Run the post configuration function if there is one.
                 */
-               while (bytecount < bsize) {
-#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
-                       if (ctrlc ()) {
-                               (*fn->abort) (cookie);
-                               return FPGA_FAIL;
-                       }
+               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;
+}
 
-                       if ((*fn->done) (cookie) == FPGA_SUCCESS) {
-                           PRINTF ("%s:%d:done went active early, bytecount = %d\n",
-                                   __FUNCTION__, __LINE__, bytecount);
-                           break;
-                       }
-
-#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
-                       if ((*fn->init) (cookie)) {
-                               printf ("\n%s:%d:  ** Error: INIT asserted during"
-                                               " configuration\n", __FUNCTION__, __LINE__);
-                               printf ("%d = buffer offset, %d = buffer size\n",
-                                       bytecount, bsize);
-                               (*fn->abort) (cookie);
-                               return FPGA_FAIL;
-                       }
+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
 
-                       (*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);
+               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_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",
-                                                       __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
-                                       (*fn->abort) (cookie);
-                                       return FPGA_FAIL;
-                               }
-                       }
+#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
 
-#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
-                       if (bytecount % (bsize / 40) == 0)
-                               putc ('.');
-#endif
-               }
+               (*fn->wdata)(data[bytecount++], true, cookie);
+               CONFIG_FPGA_DELAY();
 
                /*
-                * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
+                * Cycle the clock pin
                 */
-               CONFIG_FPGA_DELAY ();
-               (*fn->cs) (false, true, cookie);
-               (*fn->wr) (false, true, cookie);
-
-#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
-               putc ('\n');
-#endif
+               (*fn->clk)(false, true, cookie);
+               CONFIG_FPGA_DELAY();
+               (*fn->clk)(true, true, cookie);
 
-               /*
-                * Check for successful configuration.  FPGA INIT_B and DONE should
-                * both be high upon successful configuration.
-                */
-               ts = get_timer (0);
-               ret_val = FPGA_SUCCESS;
-               while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
-                       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",
-                                               __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
-                               (*fn->abort) (cookie);
-                               ret_val = FPGA_FAIL;
-                               break;
+#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;
                        }
                }
-
-               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);
+               if (bytecount % (bsize / 40) == 0)
+                       putc('.');
 #endif
-               }
-       } else {
-               printf ("%s:%d: NULL Interface function table!\n",
-                               __FUNCTION__, __LINE__);
        }
-       return ret_val;
+
+       return virtex2_slave_post(fn, cookie);
 }
 
 /*
@@ -356,64 +395,127 @@ 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;
+               unsigned char *data = (unsigned char *)buf;
                size_t bytecount = 0;
                int cookie = desc->cookie;
 
-               printf ("Starting Dump of FPGA Device %d...\n", cookie);
+               printf("Starting Dump of FPGA Device %d...\n", cookie);
 
-               (*fn->cs) (true, true, cookie);
-               (*fn->clk) (true, true, 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);
+                       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);
+                       (*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 ('.');
+                               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);
+               (*fn->cs)(false, false, cookie);
+               (*fn->clk)(false, true, cookie);
+               (*fn->clk)(true, true, cookie);
 
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
-               putc ('\n');
+               putc('\n');
 #endif
-               puts ("Done.\n");
+               puts("Done.\n");
        } else {
-               printf ("%s:%d: NULL Interface function table!\n",
-                               __FUNCTION__, __LINE__);
+               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)
 {
-       printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
-       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)
 {
-       printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
+       printf("%s: Slave Serial Dumping is unsupported\n", __func__);
        return FPGA_FAIL;
 }