1*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 2*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 3*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Rich Ireland, Enterasys Networks, rireland@enterasys.com. 4*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * 5*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 6*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * project. 7*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * 8*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 9*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 10*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 11*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 12*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * 13*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 14*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 17*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * 18*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 19*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 20*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 22*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * 23*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 24*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 25*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <common.h> /* core U-Boot definitions */ 26*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #include <spartan2.h> /* Spartan-II device family */ 27*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 28*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Define FPGA_DEBUG to get debug printf's */ 29*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef FPGA_DEBUG 30*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...) printf (fmt ,##args) 31*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #else 32*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define PRINTF(fmt,args...) 33*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 34*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 35*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_CHECK_BUSY 36*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #undef CONFIG_SYS_FPGA_PROG_FEEDBACK 37*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 38*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Note: The assumption is that we cannot possibly run fast enough to 39*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * overrun the device (the Slave Parallel mode can free run at 50MHz). 40*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * If there is a need to operate slower, define CONFIG_FPGA_DELAY in 41*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * the board config file to slow things down. 42*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 43*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_FPGA_DELAY 44*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_FPGA_DELAY() 45*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 46*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 47*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_FPGA_WAIT 48*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */ 49*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 50*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 51*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_load( Xilinx_desc *desc, void *buf, size_t bsize ); 52*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize ); 53*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* static int Spartan2_sp_info( Xilinx_desc *desc ); */ 54*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_reloc( Xilinx_desc *desc, ulong reloc_offset ); 55*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 56*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_load( Xilinx_desc *desc, void *buf, size_t bsize ); 57*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize ); 58*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* static int Spartan2_ss_info( Xilinx_desc *desc ); */ 59*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_reloc( Xilinx_desc *desc, ulong reloc_offset ); 60*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 61*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */ 62*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Generic Implementation */ 63*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_load (Xilinx_desc * desc, void *buf, size_t bsize) 64*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 65*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; 66*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 67*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD switch (desc->iface) { 68*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_serial: 69*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__); 70*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_ss_load (desc, buf, bsize); 71*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 72*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 73*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_parallel: 74*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__); 75*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_sp_load (desc, buf, bsize); 76*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 77*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 78*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD default: 79*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Unsupported interface type, %d\n", 80*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, desc->iface); 81*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 82*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 83*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 84*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 85*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 86*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_dump (Xilinx_desc * desc, void *buf, size_t bsize) 87*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 88*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; 89*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 90*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD switch (desc->iface) { 91*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_serial: 92*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__); 93*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_ss_dump (desc, buf, bsize); 94*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 95*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 96*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_parallel: 97*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__); 98*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_sp_dump (desc, buf, bsize); 99*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 100*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 101*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD default: 102*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Unsupported interface type, %d\n", 103*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, desc->iface); 104*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 105*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 106*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 107*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 108*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 109*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_info( Xilinx_desc *desc ) 110*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 111*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_SUCCESS; 112*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 113*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 114*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 115*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int Spartan2_reloc (Xilinx_desc * desc, ulong reloc_offset) 116*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 117*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume a failure */ 118*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 119*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (desc->family != Xilinx_Spartan2) { 120*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Unsupported family type, %d\n", 121*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, desc->family); 122*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 123*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else 124*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD switch (desc->iface) { 125*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_serial: 126*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_ss_reloc (desc, reloc_offset); 127*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 128*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 129*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD case slave_parallel: 130*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = Spartan2_sp_reloc (desc, reloc_offset); 131*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 132*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 133*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD default: 134*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Unsupported interface type, %d\n", 135*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, desc->iface); 136*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 137*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 138*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 139*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 140*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 141*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 142*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */ 143*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Spartan-II Slave Parallel Generic Implementation */ 144*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 145*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_load (Xilinx_desc * desc, void *buf, size_t bsize) 146*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 147*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume the worst */ 148*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns; 149*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 150*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: start with interface functions @ 0x%p\n", 151*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, fn); 152*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 153*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn) { 154*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD size_t bytecount = 0; 155*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned char *data = (unsigned char *) buf; 156*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int cookie = desc->cookie; /* make a local copy */ 157*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned long ts; /* timestamp */ 158*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 159*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Function Table:\n" 160*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "ptr:\t0x%p\n" 161*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "struct: 0x%p\n" 162*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "pre: 0x%p\n" 163*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "pgm:\t0x%p\n" 164*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "init:\t0x%p\n" 165*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "err:\t0x%p\n" 166*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "clk:\t0x%p\n" 167*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "cs:\t0x%p\n" 168*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "wr:\t0x%p\n" 169*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "read data:\t0x%p\n" 170*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "write data:\t0x%p\n" 171*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "busy:\t0x%p\n" 172*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "abort:\t0x%p\n", 173*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "post:\t0x%p\n\n", 174*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err, 175*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy, 176*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn->abort, fn->post); 177*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 178*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 179*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * This code is designed to emulate the "Express Style" 180*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Continuous Data Loading in Slave Parallel Mode for 181*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * the Spartan-II Family. 182*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 183*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 184*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("Loading FPGA Device %d...\n", cookie); 185*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 186*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 187*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Run the pre configuration function if there is one. 188*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 189*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (*fn->pre) { 190*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pre) (cookie); 191*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 192*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 193*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Establish the initial state */ 194*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ 195*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 196*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Get ready for the burn */ 197*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 198*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ 199*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 200*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 201*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Now wait for INIT and BUSY to go high */ 202*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD do { 203*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 204*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 205*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for INIT to clear.\n"); 206*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->abort) (cookie); /* abort the burn */ 207*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 208*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 209*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); 210*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 211*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */ 212*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ 213*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 214*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 215*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Load the data */ 216*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while (bytecount < bsize) { 217*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - do we check for an Ctrl-C press in here ??? */ 218*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - Check the error bit? */ 219*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 220*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */ 221*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 222*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 223*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 224*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 225*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 226*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_CHECK_BUSY 227*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 228*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while ((*fn->busy) (cookie)) { 229*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - we should have a check in here somewhere to 230*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * make sure we aren't busy forever... */ 231*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 232*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 233*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 234*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 235*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 236*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 237*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 238*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for BUSY to clear.\n"); 239*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->abort) (cookie); /* abort the burn */ 240*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 241*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 242*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 243*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 244*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 245*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 246*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (bytecount % (bsize / 40) == 0) 247*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('.'); /* let them know we are alive */ 248*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 249*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 250*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 251*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 252*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */ 253*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */ 254*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 255*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 256*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('\n'); /* terminate the dotted line */ 257*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 258*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 259*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* now check for done signal */ 260*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 261*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_SUCCESS; 262*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while ((*fn->done) (cookie) == FPGA_FAIL) { 263*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - we should have a check in here somewhere to 264*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * make sure we aren't busy forever... */ 265*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 266*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 267*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 268*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 269*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 270*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 271*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 272*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for DONE to clear.\n"); 273*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->abort) (cookie); /* abort the burn */ 274*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_FAIL; 275*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 276*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 277*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 278*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 279*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (ret_val == FPGA_SUCCESS) { 280*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 281*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("Done.\n"); 282*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 283*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 284*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 285*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Run the post configuration function if there is one. 286*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 287*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (*fn->post) { 288*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->post) (cookie); 289*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 290*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 291*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD else { 292*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 293*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("Fail.\n"); 294*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 295*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 296*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 297*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 298*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: NULL Interface function table!\n", __FUNCTION__); 299*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 300*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 301*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 302*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 303*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 304*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize) 305*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 306*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume the worst */ 307*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns; 308*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 309*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn) { 310*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned char *data = (unsigned char *) buf; 311*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD size_t bytecount = 0; 312*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int cookie = desc->cookie; /* make a local copy */ 313*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 314*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("Starting Dump of FPGA Device %d...\n", cookie); 315*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 316*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ 317*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 318*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 319*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* dump the data */ 320*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while (bytecount < bsize) { 321*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - do we check for an Ctrl-C press in here ??? */ 322*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 323*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 324*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 325*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */ 326*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 327*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (bytecount % (bsize / 40) == 0) 328*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('.'); /* let them know we are alive */ 329*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 330*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 331*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 332*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */ 333*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 334*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 335*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 336*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 337*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('\n'); /* terminate the dotted line */ 338*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 339*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("Done.\n"); 340*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 341*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - checksum the data? */ 342*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 343*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: NULL Interface function table!\n", __FUNCTION__); 344*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 345*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 346*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 347*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 348*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 349*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 350*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_sp_reloc (Xilinx_desc * desc, ulong reloc_offset) 351*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 352*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume the worst */ 353*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD Xilinx_Spartan2_Slave_Parallel_fns *fn_r, *fn = 354*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (Xilinx_Spartan2_Slave_Parallel_fns *) (desc->iface_fns); 355*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 356*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn) { 357*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ulong addr; 358*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 359*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Get the relocated table address */ 360*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) fn + reloc_offset; 361*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r = (Xilinx_Spartan2_Slave_Parallel_fns *) addr; 362*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 363*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (!fn_r->relocated) { 364*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 365*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (memcmp (fn_r, fn, 366*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD sizeof (Xilinx_Spartan2_Slave_Parallel_fns)) 367*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD == 0) { 368*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* good copy of the table, fix the descriptor pointer */ 369*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc->iface_fns = fn_r; 370*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 371*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Invalid function table at 0x%p\n", 372*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, fn_r); 373*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 374*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 375*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 376*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, 377*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc); 378*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 379*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->pre) + reloc_offset; 380*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->pre = (Xilinx_pre_fn) addr; 381*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 382*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->pgm) + reloc_offset; 383*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->pgm = (Xilinx_pgm_fn) addr; 384*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 385*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->init) + reloc_offset; 386*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->init = (Xilinx_init_fn) addr; 387*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 388*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->done) + reloc_offset; 389*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->done = (Xilinx_done_fn) addr; 390*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 391*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->clk) + reloc_offset; 392*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->clk = (Xilinx_clk_fn) addr; 393*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 394*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->err) + reloc_offset; 395*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->err = (Xilinx_err_fn) addr; 396*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 397*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->cs) + reloc_offset; 398*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->cs = (Xilinx_cs_fn) addr; 399*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 400*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->wr) + reloc_offset; 401*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->wr = (Xilinx_wr_fn) addr; 402*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 403*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->rdata) + reloc_offset; 404*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->rdata = (Xilinx_rdata_fn) addr; 405*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 406*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->wdata) + reloc_offset; 407*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->wdata = (Xilinx_wdata_fn) addr; 408*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 409*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->busy) + reloc_offset; 410*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->busy = (Xilinx_busy_fn) addr; 411*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 412*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->abort) + reloc_offset; 413*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->abort = (Xilinx_abort_fn) addr; 414*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 415*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->post) + reloc_offset; 416*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->post = (Xilinx_post_fn) addr; 417*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 418*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->relocated = TRUE; 419*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 420*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 421*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* this table has already been moved */ 422*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - should check to see if the descriptor is correct */ 423*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc->iface_fns = fn_r; 424*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 425*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 426*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_SUCCESS; 427*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 428*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: NULL Interface function table!\n", __FUNCTION__); 429*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 430*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 431*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 432*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 433*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 434*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 435*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* ------------------------------------------------------------------------- */ 436*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 437*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize) 438*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 439*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume the worst */ 440*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns; 441*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int i; 442*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned char val; 443*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 444*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: start with interface functions @ 0x%p\n", 445*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, fn); 446*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 447*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn) { 448*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD size_t bytecount = 0; 449*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned char *data = (unsigned char *) buf; 450*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int cookie = desc->cookie; /* make a local copy */ 451*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD unsigned long ts; /* timestamp */ 452*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 453*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Function Table:\n" 454*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "ptr:\t0x%p\n" 455*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "struct: 0x%p\n" 456*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "pgm:\t0x%p\n" 457*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "init:\t0x%p\n" 458*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "clk:\t0x%p\n" 459*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "wr:\t0x%p\n" 460*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD "done:\t0x%p\n\n", 461*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, &fn, fn, fn->pgm, fn->init, 462*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn->clk, fn->wr, fn->done); 463*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 464*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("Loading FPGA Device %d...\n", cookie); 465*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 466*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 467*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 468*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Run the pre configuration function if there is one. 469*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 470*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (*fn->pre) { 471*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pre) (cookie); 472*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 473*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 474*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Establish the initial state */ 475*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ 476*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 477*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Wait for INIT state (init low) */ 478*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 479*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD do { 480*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 481*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 482*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for INIT to start.\n"); 483*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 484*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 485*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } while (!(*fn->init) (cookie)); 486*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 487*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Get ready for the burn */ 488*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 489*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ 490*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 491*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 492*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Now wait for INIT to go high */ 493*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD do { 494*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 495*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 496*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for INIT to clear.\n"); 497*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 498*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 499*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } while ((*fn->init) (cookie)); 500*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 501*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Load the data */ 502*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while (bytecount < bsize) { 503*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 504*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Xilinx detects an error if INIT goes low (active) 505*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while DONE is low (inactive) */ 506*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { 507*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** CRC error during FPGA load.\n"); 508*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return (FPGA_FAIL); 509*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 510*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD val = data [bytecount ++]; 511*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD i = 8; 512*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD do { 513*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Deassert the clock */ 514*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); 515*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 516*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Write data */ 517*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->wr) ((val & 0x80), TRUE, cookie); 518*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 519*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Assert the clock */ 520*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); 521*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 522*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD val <<= 1; 523*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD i --; 524*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } while (i > 0); 525*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 526*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 527*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (bytecount % (bsize / 40) == 0) 528*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('.'); /* let them know we are alive */ 529*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 530*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 531*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 532*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 533*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 534*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 535*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('\n'); /* terminate the dotted line */ 536*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 537*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 538*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* now check for done signal */ 539*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ts = get_timer (0); /* get current time */ 540*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_SUCCESS; 541*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->wr) (TRUE, TRUE, cookie); 542*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 543*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD while (! (*fn->done) (cookie)) { 544*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - we should have a check in here somewhere to 545*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * make sure we aren't busy forever... */ 546*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 547*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 548*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 549*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD CONFIG_FPGA_DELAY (); 550*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 551*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 552*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('*'); 553*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 554*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 555*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("** Timeout waiting for DONE to clear.\n"); 556*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_FAIL; 557*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD break; 558*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 559*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 560*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD putc ('\n'); /* terminate the dotted line */ 561*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 562*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* 563*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD * Run the post configuration function if there is one. 564*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD */ 565*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (*fn->post) { 566*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (*fn->post) (cookie); 567*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 568*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 569*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 570*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (ret_val == FPGA_SUCCESS) { 571*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("Done.\n"); 572*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 573*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD else { 574*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD puts ("Fail.\n"); 575*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 576*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD #endif 577*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 578*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 579*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: NULL Interface function table!\n", __FUNCTION__); 580*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 581*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 582*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 583*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 584*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 585*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize) 586*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 587*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Readback is only available through the Slave Parallel and */ 588*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* boundary-scan interfaces. */ 589*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: Slave Serial Dumping is unavailable\n", 590*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__); 591*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 592*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 593*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 594*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) 595*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD { 596*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD int ret_val = FPGA_FAIL; /* assume the worst */ 597*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD Xilinx_Spartan2_Slave_Serial_fns *fn_r, *fn = 598*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD (Xilinx_Spartan2_Slave_Serial_fns *) (desc->iface_fns); 599*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 600*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn) { 601*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ulong addr; 602*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 603*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* Get the relocated table address */ 604*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) fn + reloc_offset; 605*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r = (Xilinx_Spartan2_Slave_Serial_fns *) addr; 606*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 607*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (!fn_r->relocated) { 608*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 609*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (memcmp (fn_r, fn, 610*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD sizeof (Xilinx_Spartan2_Slave_Serial_fns)) 611*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD == 0) { 612*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* good copy of the table, fix the descriptor pointer */ 613*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc->iface_fns = fn_r; 614*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 615*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Invalid function table at 0x%p\n", 616*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD __FUNCTION__, fn_r); 617*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return FPGA_FAIL; 618*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 619*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 620*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, 621*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc); 622*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 623*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn->pre) { 624*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->pre) + reloc_offset; 625*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->pre = (Xilinx_pre_fn) addr; 626*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 627*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 628*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->pgm) + reloc_offset; 629*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->pgm = (Xilinx_pgm_fn) addr; 630*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 631*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->init) + reloc_offset; 632*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->init = (Xilinx_init_fn) addr; 633*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 634*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->done) + reloc_offset; 635*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->done = (Xilinx_done_fn) addr; 636*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 637*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->clk) + reloc_offset; 638*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->clk = (Xilinx_clk_fn) addr; 639*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 640*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->wr) + reloc_offset; 641*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->wr = (Xilinx_wr_fn) addr; 642*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 643*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD if (fn->post) { 644*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD addr = (ulong) (fn->post) + reloc_offset; 645*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->post = (Xilinx_post_fn) addr; 646*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 647*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 648*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD fn_r->relocated = TRUE; 649*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 650*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 651*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* this table has already been moved */ 652*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD /* XXX - should check to see if the descriptor is correct */ 653*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD desc->iface_fns = fn_r; 654*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 655*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 656*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD ret_val = FPGA_SUCCESS; 657*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } else { 658*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD printf ("%s: NULL Interface function table!\n", __FUNCTION__); 659*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 660*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 661*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD return ret_val; 662*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD 663*c8aa7dfcSJean-Christophe PLAGNIOL-VILLARD } 664