fpga: virtex2: Split out image writing from pre/post operations
This is in preparation for adding slave serial programming support,
which uses the same pre/post operations as slave SelectMAP, to avoid
duplicating code.
Signed-off-by: Robert Hancock <hancock@sedsystems.ca>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c
index b01a31f..2383c69 100644
--- a/drivers/fpga/virtex2.c
+++ b/drivers/fpga/virtex2.c
@@ -154,202 +154,219 @@
* 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_selectmap_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",
__func__, __LINE__, fn);
- if (fn) {
- size_t bytecount = 0;
- unsigned char *data = (unsigned char *)buf;
- int cookie = desc->cookie;
- unsigned long ts;
+ 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);
+ /* 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));
+ /*
+ * 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();
+ (*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));
+ /*
+ * 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));
+ if (fn->wr)
(*fn->wr)(true, true, cookie);
+ if (fn->cs)
(*fn->cs)(true, true, cookie);
- mdelay(10);
+ mdelay(10);
+ return FPGA_SUCCESS;
+}
- /*
- * Load the data byte by byte
- */
- while (bytecount < bsize) {
-#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
- if (ctrlc()) {
- (*fn->abort)(cookie);
- return FPGA_FAIL;
- }
-#endif
+static int virtex2_slave_post(xilinx_virtex2_slave_selectmap_fns *fn,
+ int cookie)
+{
+ int ret_val = FPGA_SUCCESS;
+ unsigned long ts;
- if ((*fn->done)(cookie) == FPGA_SUCCESS) {
- PRINTF("%s:%d:done went active early, bytecount = %d\n",
- __func__, __LINE__, bytecount);
- break;
- }
+ /*
+ * 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);
-#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
- if ((*fn->init)(cookie)) {
- printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
- __func__, __LINE__);
- printf("%d = buffer offset, %d = buffer size\n",
- bytecount, bsize);
- (*fn->abort)(cookie);
- return FPGA_FAIL;
- }
+#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
+ putc('\n');
#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);
+ /*
+ * 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",
+ __func__, __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
- if (bytecount % (bsize / 40) == 0)
- putc('.');
+ printf("** Initialization of FPGA device %d FAILED\n",
+ cookie);
#endif
+ }
+ return ret_val;
+}
+
+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;
+ 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
- /*
- * Finished writing the data; deassert FPGA CS_B and WRITE_B
- * signals.
- */
- CONFIG_FPGA_DELAY();
- (*fn->cs)(false, true, cookie);
- (*fn->wr)(false, 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_PROG_FEEDBACK
- putc('\n');
+#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
+ (*fn->wdata)(data[bytecount++], true, cookie);
+ CONFIG_FPGA_DELAY();
+
/*
- * Check for successful configuration. FPGA INIT_B and DONE
- * should both be high upon successful configuration.
+ * Cycle the clock pin
*/
+ (*fn->clk)(false, true, cookie);
+ CONFIG_FPGA_DELAY();
+ (*fn->clk)(true, true, cookie);
+
+#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
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 toassert and INIT to deassert\n",
+ 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_CONFIG);
+ CONFIG_SYS_FPGA_WAIT_BUSY);
(*fn->abort)(cookie);
- ret_val = FPGA_FAIL;
- break;
+ 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",
- __func__, __LINE__);
}
- return ret_val;
+
+ return virtex2_slave_post(fn, cookie);
}
/*