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