/* terminate the FPGA load (parallel mode) */ static int spartan_parallel_finish(struct fpga_desc *desc) { Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; unsigned long timestamp; if (fn) { /* now check for done signal */ timestamp = get_timer(0); /* get current time */ while (!(*fn->done) ()) { CONFIG_FPGA_DELAY (); (*fn->clk) (0); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (1); /* Assert the clock pin */ if (get_timer(timestamp) > CFG_FPGA_WAIT) { printk("** Timeout waiting for DONE to clear. %d bytes\n", bytecount); (*fn->abort) (); /* abort the burn */ return -ETIMEDOUT; } } (*fn->cs) (0); /* Deassert the chip select */ (*fn->wr) (0); /* Deassert the write pin */ (*fn->post) (); /* release resources */ } return 0; }
/* terminate the FPGA load (serial mode) */ static int spartan_serial_finish(struct fpga_desc *desc) { unsigned long timestamp; Xilinx_Spartan_Slave_Serial_fns *fn = desc->iface_fns; if (fn) { CONFIG_FPGA_DELAY (); /* now check for done signal */ timestamp = get_timer(0); /* get current time */ (*fn->wr)(1); while (! (*fn->done)()) { CONFIG_FPGA_DELAY (); (*fn->clk)(0); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk)(1); /* Assert the clock pin */ if (get_timer(timestamp) > CFG_FPGA_WAIT) { pr_debug("** Timeout waiting for DONE.\n"); return -ETIMEDOUT; } } } return 0; }
/** * initialize the FPGA programming interface (parallel). * return 0 if success, <0 if error detected */ static int spartan_parallel_init(struct fpga_desc *desc) { int res = 0; Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; if (fn) { unsigned long timestamp; /* * Run the pre configuration function if there is one. */ if (*fn->pre) { if( (res = (*fn->pre) ()) ) return res; } mdelay(100); /* Establish the initial state */ (*fn->pgm) (1); /* Assert the program, commit */ timestamp = get_timer(0); /* get current time */ /* Now wait for INIT to go down */ do { CONFIG_FPGA_DELAY (); if (get_timer(timestamp) > CFG_FPGA_WAIT) { pr_debug("** Timeout waiting for INIT to set.\n"); (*fn->abort) (); /* abort the burn */ return -ETIMEDOUT; } } while (!(*fn->init) () ); /* Get ready for the burn */ CONFIG_FPGA_DELAY (); (*fn->pgm) (0); /* Deassert the program, commit */ timestamp = get_timer (0); /* get current time */ /* Now wait for INIT and BUSY to go high */ do { CONFIG_FPGA_DELAY (); if (get_timer(timestamp) > CFG_FPGA_WAIT) { pr_debug("** Timeout waiting for INIT to clear.\n"); (*fn->abort) (); /* abort the burn */ return -ETIMEDOUT; } } while ((*fn->init) ()); (*fn->wr) (1); /* Assert write, commit */ (*fn->cs) (1); /* Assert chip select, commit */ (*fn->clk) (1); /* Assert the clock pin */ bytecount = 0; // reset byte count } return 0; }
/** * initialize the FPGA programming interface (serial). * return 0 if success, <0 if error detected */ static int spartan_serial_init(struct fpga_desc *desc) { Xilinx_Spartan_Slave_Serial_fns *fn = desc->iface_fns; if (fn) { unsigned long timestamp; if (*fn->pre){ (*fn->pre)(); /* Run the pre configuration function if there is one. */ } /* Establish the initial state */ (*fn->pgm)(1); /* Assert the program, commit */ /* Wait for INIT state (init low) */ timestamp = get_timer(0); /* get current time */ do { CONFIG_FPGA_DELAY (); if (get_timer(timestamp) > CFG_FPGA_WAIT) { pr_debug("** Timeout waiting for INIT to start.\n"); return -ETIMEDOUT; } } while (!(*fn->init)()); /* Get ready for the burn */ CONFIG_FPGA_DELAY (); (*fn->pgm)(0); /* Deassert the program, commit */ timestamp = get_timer(0); /* get current time */ /* Now wait for INIT to go high */ do { CONFIG_FPGA_DELAY (); if (get_timer(timestamp) > CFG_FPGA_WAIT) { pr_debug("** Timeout waiting for INIT to clear.\n"); return -ETIMEDOUT; } } while ((*fn->init)()); bytecount = 0; /* reset byte count */ return 0; /* success */ } return -EINVAL; }
/** * program the FPGA (serial mode). * return 0 if success, >0 while programming, <0 if error detected */ static size_t spartan_serial_load(struct fpga_desc *desc, const char* buf, size_t bsize) { Xilinx_Spartan_Slave_Serial_fns *fn = desc->iface_fns; if (fn) { int i; unsigned char val; size_t nbbyte = 0; /* init local counter */ while (nbbyte < bsize) { /* Spartan signals an error if INIT goes low (active) while DONE is low (inactive) */ if ((*fn->done)() == 0 && (*fn->init)()) { printk("** CRC error during FPGA load.\n"); return -ETIMEDOUT; } val = buf[nbbyte ++]; bytecount++; i = 8; do { /* Deassert the clock */ (*fn->clk)(0); CONFIG_FPGA_DELAY(); /* Write data */ (*fn->wr)(val & 0x80); CONFIG_FPGA_DELAY(); /* Assert the clock */ (*fn->clk)(1); CONFIG_FPGA_DELAY(); val <<= 1; i --; } while (i > 0); } if (bytecount % 4096 == 0) printk("."); return bsize; } return -EINVAL; }
/** * program the FPGA (parallel mode). * return 0 if success, >0 while programming, <0 if error detected */ static size_t spartan_parallel_load(struct fpga_desc *desc, const char* buf, size_t bsize) { unsigned long flags; Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; if (fn) { /* Load the data */ size_t nbbyte = 0; raw_local_irq_save(flags); while (nbbyte < bsize) { (*fn->clk) (1); /* Assert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->wdata) (buf[nbbyte++]); /* write the data */ CONFIG_FPGA_DELAY (); (*fn->clk) (0); /* Deassert the clock pin */ bytecount++; } raw_local_irq_restore(flags); return bsize; } return -EINVAL; }
static int Spartan3_ss_load (Xilinx_desc * desc, void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume the worst */ Xilinx_Spartan3_Slave_Serial_fns *fn = desc->iface_fns; int i; unsigned char val; PRINTF ("%s: start with interface functions @ 0x%p\n", __FUNCTION__, fn); if (fn) { size_t bytecount = 0; unsigned char *data = (unsigned char *) buf; int cookie = desc->cookie; /* make a local copy */ unsigned long ts; /* timestamp */ PRINTF ("%s: Function Table:\n" "ptr:\t0x%p\n" "struct: 0x%p\n" "pgm:\t0x%p\n" "init:\t0x%p\n" "clk:\t0x%p\n" "wr:\t0x%p\n" "done:\t0x%p\n\n", __FUNCTION__, &fn, fn, fn->pgm, fn->init, fn->clk, fn->wr, fn->done); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK printf ("Loading FPGA Device %d...\n", cookie); #endif /* * Run the pre configuration function if there is one. */ if (*fn->pre) { (*fn->pre) (cookie); } /* Establish the initial state */ (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ /* Wait for INIT state (init low) */ ts = get_timer (0); /* get current time */ do { CONFIG_FPGA_DELAY (); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for INIT to start.\n"); if (*fn->abort) (*fn->abort) (cookie); return FPGA_FAIL; } } while (!(*fn->init) (cookie)); /* Get ready for the burn */ CONFIG_FPGA_DELAY (); (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT to go high */ do { CONFIG_FPGA_DELAY (); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for INIT to clear.\n"); if (*fn->abort) (*fn->abort) (cookie); return FPGA_FAIL; } } while ((*fn->init) (cookie)); /* Load the data */ if(*fn->bwr) (*fn->bwr) (data, bsize, TRUE, cookie); else { while (bytecount < bsize) { /* Xilinx detects an error if INIT goes low (active) while DONE is low (inactive) */ if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { puts ("** CRC error during FPGA load.\n"); if (*fn->abort) (*fn->abort) (cookie); return (FPGA_FAIL); } val = data [bytecount ++]; i = 8; do { /* Deassert the clock */ (*fn->clk) (FALSE, TRUE, cookie); CONFIG_FPGA_DELAY (); /* Write data */ (*fn->wr) ((val & 0x80), TRUE, cookie); CONFIG_FPGA_DELAY (); /* Assert the clock */ (*fn->clk) (TRUE, TRUE, cookie); CONFIG_FPGA_DELAY (); val <<= 1; i --; } while (i > 0); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) putc ('.'); /* let them know we are alive */ #endif } } CONFIG_FPGA_DELAY (); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ #endif /* now check for done signal */ ts = get_timer (0); /* get current time */ ret_val = FPGA_SUCCESS; (*fn->wr) (TRUE, TRUE, cookie); while (! (*fn->done) (cookie)) { /* XXX - we should have a check in here somewhere to * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ putc ('*'); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for DONE to clear.\n"); ret_val = FPGA_FAIL; break; } } putc ('\n'); /* terminate the dotted line */ /* * Run the post configuration function if there is one. */ if (*fn->post) (*fn->post) (cookie); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (ret_val == FPGA_SUCCESS) puts ("Done.\n"); else puts ("Fail.\n"); #endif } else { printf ("%s: NULL Interface function table!\n", __FUNCTION__); } return ret_val; }
static int Spartan3_sp_load (Xilinx_desc * desc, void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume the worst */ Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; PRINTF ("%s: start with interface functions @ 0x%p\n", __FUNCTION__, fn); if (fn) { size_t bytecount = 0; unsigned char *data = (unsigned char *) buf; int cookie = desc->cookie; /* make a local copy */ unsigned long ts; /* timestamp */ PRINTF ("%s: Function Table:\n" "ptr:\t0x%p\n" "struct: 0x%p\n" "pre: 0x%p\n" "pgm:\t0x%p\n" "init:\t0x%p\n" "err:\t0x%p\n" "clk:\t0x%p\n" "cs:\t0x%p\n" "wr:\t0x%p\n" "read data:\t0x%p\n" "write data:\t0x%p\n" "busy:\t0x%p\n" "abort:\t0x%p\n", "post:\t0x%p\n\n", __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err, fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy, fn->abort, fn->post); /* * This code is designed to emulate the "Express Style" * Continuous Data Loading in Slave Parallel Mode for * the Spartan-II Family. */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK printf ("Loading FPGA Device %d...\n", cookie); #endif /* * Run the pre configuration function if there is one. */ if (*fn->pre) { (*fn->pre) (cookie); } /* Establish the initial state */ (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ /* Get ready for the burn */ CONFIG_FPGA_DELAY (); (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT and BUSY to go high */ do { CONFIG_FPGA_DELAY (); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for INIT to clear.\n"); (*fn->abort) (cookie); /* abort the burn */ return FPGA_FAIL; } } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */ (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ /* Load the data */ while (bytecount < bsize) { /* XXX - do we check for an Ctrl-C press in here ??? */ /* XXX - Check the error bit? */ (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */ CONFIG_FPGA_DELAY (); (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ #ifdef CONFIG_SYS_FPGA_CHECK_BUSY ts = get_timer (0); /* get current time */ while ((*fn->busy) (cookie)) { /* XXX - we should have a check in here somewhere to * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for BUSY to clear.\n"); (*fn->abort) (cookie); /* abort the burn */ return FPGA_FAIL; } } #endif #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) putc ('.'); /* let them know we are alive */ #endif } CONFIG_FPGA_DELAY (); (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */ (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ #endif /* now check for done signal */ ts = get_timer (0); /* get current time */ ret_val = FPGA_SUCCESS; while ((*fn->done) (cookie) == FPGA_FAIL) { /* XXX - we should have a check in here somewhere to * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for DONE to clear.\n"); (*fn->abort) (cookie); /* abort the burn */ ret_val = FPGA_FAIL; break; } } /* * Run the post configuration function if there is one. */ if (*fn->post) (*fn->post) (cookie); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (ret_val == FPGA_SUCCESS) puts ("Done.\n"); else puts ("Fail.\n"); #endif } else { printf ("%s: NULL Interface function table!\n", __FUNCTION__); } return ret_val; }
static int ACEX1K_ps_load (Altera_desc * desc, void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume the worst */ Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns; int i; PRINTF ("%s: start with interface functions @ 0x%p\n", __FUNCTION__, fn); if (fn) { size_t bytecount = 0; unsigned char *data = (unsigned char *) buf; int cookie = desc->cookie; /* make a local copy */ unsigned long ts; /* timestamp */ PRINTF ("%s: Function Table:\n" "ptr:\t0x%p\n" "struct: 0x%p\n" "config:\t0x%p\n" "status:\t0x%p\n" "clk:\t0x%p\n" "data:\t0x%p\n" "done:\t0x%p\n\n", __FUNCTION__, &fn, fn, fn->config, fn->status, fn->clk, fn->data, fn->done); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK printf ("Loading FPGA Device %d...", cookie); #endif /* * Run the pre configuration function if there is one. */ if (*fn->pre) { (*fn->pre) (cookie); } /* Establish the initial state */ (*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */ udelay(2); /* T_cfg > 2us */ /* nSTATUS should be asserted now */ (*fn->done) (cookie); if ( !(*fn->status) (cookie) ) { puts ("** nSTATUS is not asserted.\n"); (*fn->abort) (cookie); return FPGA_FAIL; } (*fn->config) (FALSE, TRUE, cookie); /* Deassert nCONFIG */ udelay(2); /* T_cf2st1 < 4us */ /* Wait for nSTATUS to be released (i.e. deasserted) */ ts = get_timer (0); /* get current time */ do { CONFIG_FPGA_DELAY (); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for STATUS to go high.\n"); (*fn->abort) (cookie); return FPGA_FAIL; } (*fn->done) (cookie); } while ((*fn->status) (cookie)); /* Get ready for the burn */ CONFIG_FPGA_DELAY (); /* Load the data */ while (bytecount < bsize) { unsigned char val=0; #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC if (ctrlc ()) { (*fn->abort) (cookie); return FPGA_FAIL; } #endif /* Altera detects an error if INIT goes low (active) while DONE is low (inactive) */ #if 0 /* not yet implemented */ if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { puts ("** CRC error during FPGA load.\n"); (*fn->abort) (cookie); return (FPGA_FAIL); } #endif val = data [bytecount ++ ]; i = 8; do { /* Deassert the clock */ (*fn->clk) (FALSE, TRUE, cookie); CONFIG_FPGA_DELAY (); /* Write data */ (*fn->data) ( (val & 0x01), TRUE, cookie); CONFIG_FPGA_DELAY (); /* Assert the clock */ (*fn->clk) (TRUE, TRUE, cookie); CONFIG_FPGA_DELAY (); val >>= 1; i --; } while (i > 0); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) putc ('.'); /* let them know we are alive */ #endif } CONFIG_FPGA_DELAY (); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc (' '); /* terminate the dotted line */ #endif /* * Checking FPGA's CONF_DONE signal - correctly booted ? */ if ( ! (*fn->done) (cookie) ) { puts ("** Booting failed! CONF_DONE is still deasserted.\n"); (*fn->abort) (cookie); return (FPGA_FAIL); } /* * "DCLK must be clocked an additional 10 times fpr ACEX 1K..." */ for (i = 0; i < 12; i++) { CONFIG_FPGA_DELAY (); (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ CONFIG_FPGA_DELAY (); (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ } ret_val = FPGA_SUCCESS; #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (ret_val == FPGA_SUCCESS) { puts ("Done.\n"); } else { puts ("Fail.\n"); } #endif (*fn->post) (cookie); } else {
/* CYCLON2 Passive Serial Generic Implementation */ static int CYC2_ps_load (Altera_desc * desc, void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume the worst */ Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns; int ret = 0; PRINTF ("%s: start with interface functions @ 0x%p\n", __FUNCTION__, fn); if (fn) { int cookie = desc->cookie; /* make a local copy */ unsigned long ts; /* timestamp */ PRINTF ("%s: Function Table:\n" "ptr:\t0x%p\n" "struct: 0x%p\n" "config:\t0x%p\n" "status:\t0x%p\n" "write:\t0x%p\n" "done:\t0x%p\n\n", __FUNCTION__, &fn, fn, fn->config, fn->status, fn->write, fn->done); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK printf ("Loading FPGA Device %d...", cookie); #endif /* * Run the pre configuration function if there is one. */ if (*fn->pre) { (*fn->pre) (cookie); } /* Establish the initial state */ (*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */ udelay(2); /* T_cfg > 2us */ /* Wait for nSTATUS to be asserted */ ts = get_timer (0); /* get current time */ do { CONFIG_FPGA_DELAY (); if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for STATUS to go high.\n"); (*fn->abort) (cookie); return FPGA_FAIL; } } while (!(*fn->status) (cookie)); /* Get ready for the burn */ CONFIG_FPGA_DELAY (); ret = (*fn->write) (buf, bsize, TRUE, cookie); if (ret) { puts ("** Write failed.\n"); (*fn->abort) (cookie); return FPGA_FAIL; } #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK puts(" OK? ..."); #endif CONFIG_FPGA_DELAY (); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc (' '); /* terminate the dotted line */ #endif /* * Checking FPGA's CONF_DONE signal - correctly booted ? */ if ( ! (*fn->done) (cookie) ) { puts ("** Booting failed! CONF_DONE is still deasserted.\n"); (*fn->abort) (cookie); return (FPGA_FAIL); } #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK puts(" OK\n"); #endif ret_val = FPGA_SUCCESS; #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (ret_val == FPGA_SUCCESS) { puts ("Done.\n"); } else { puts ("Fail.\n"); } #endif (*fn->post) (cookie); } else { printf ("%s: NULL Interface function table!\n", __FUNCTION__); } return ret_val; }
/* * Virtex-II Slave SelectMap configuration loader. Configuration via * SelectMap 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 * this process, a configuration error (most likely CRC failure) has * ocurred. At this point a status word may be read from the * SelectMap interface to determine the source of the problem (You * could, for instance, put this in your 'abort' function handler). * 4. After all data has been written, test the state of the FPGA * INIT_B and DONE lines. If both are high, configuration has * succeeded. Congratulations! */ static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize) { int ret_val = FPGA_FAIL; Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns; PRINTF ("%s:%d: Start with interface functions @ 0x%p\n", __FUNCTION__, __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); #ifdef CFG_FPGA_PROG_FEEDBACK printf ("Initializing FPGA Device %d...\n", cookie); #endif /* * 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) > CFG_FPGA_WAIT_INIT) { printf ("%s:%d: ** Timeout after %d ticks waiting for INIT" " to assert.\n", __FUNCTION__, __LINE__, CFG_FPGA_WAIT_INIT); (*fn->abort) (cookie); return FPGA_FAIL; } } while (!(*fn->init) (cookie)); (*fn->pgm) (FALSE, TRUE, cookie); CONFIG_FPGA_DELAY (); (*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) > CFG_FPGA_WAIT_INIT) { printf ("%s:%d: ** Timeout after %d ticks waiting for INIT" " to deassert.\n", __FUNCTION__, __LINE__, CFG_FPGA_WAIT_INIT); (*fn->abort) (cookie); return FPGA_FAIL; } } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); (*fn->wr) (TRUE, TRUE, cookie); (*fn->cs) (TRUE, TRUE, cookie); udelay (10000); /* * Load the data byte by byte */ while (bytecount < bsize) { #ifdef CFG_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", __FUNCTION__, __LINE__, bytecount); break; } #ifdef CFG_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; } #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); #ifdef CFG_FPGA_CHECK_BUSY ts = get_timer (0); while ((*fn->busy) (cookie)) { if (get_timer (ts) > CFG_FPGA_WAIT_BUSY) { printf ("%s:%d: ** Timeout after %d ticks waiting for" " BUSY to deassert\n", __FUNCTION__, __LINE__, CFG_FPGA_WAIT_BUSY); (*fn->abort) (cookie); return FPGA_FAIL; } } #endif #ifdef CFG_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) putc ('.'); #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); #ifdef CFG_FPGA_PROG_FEEDBACK putc ('\n'); #endif /* * 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) > CFG_FPGA_WAIT_CONFIG) { printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to" "assert and INIT to deassert\n", __FUNCTION__, __LINE__, CFG_FPGA_WAIT_CONFIG); (*fn->abort) (cookie); ret_val = FPGA_FAIL; break; } } if (ret_val == FPGA_SUCCESS) { #ifdef CFG_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 CFG_FPGA_PROG_FEEDBACK printf ("** Initialization of FPGA device %d FAILED\n", cookie); #endif } } else { printf ("%s:%d: NULL Interface function table!\n", __FUNCTION__, __LINE__); } return ret_val; }