1 /* 2 * (C) Copyright 2003 3 * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de 4 * 5 * (C) Copyright 2002 6 * Rich Ireland, Enterasys Networks, rireland@enterasys.com. 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 * 26 */ 27 28 #include <common.h> /* core U-Boot definitions */ 29 #include <ACEX1K.h> /* ACEX device family */ 30 31 /* Define FPGA_DEBUG to get debug printf's */ 32 #ifdef FPGA_DEBUG 33 #define PRINTF(fmt,args...) printf (fmt ,##args) 34 #else 35 #define PRINTF(fmt,args...) 36 #endif 37 38 /* Note: The assumption is that we cannot possibly run fast enough to 39 * overrun the device (the Slave Parallel mode can free run at 50MHz). 40 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in 41 * the board config file to slow things down. 42 */ 43 #ifndef CONFIG_FPGA_DELAY 44 #define CONFIG_FPGA_DELAY() 45 #endif 46 47 #ifndef CONFIG_SYS_FPGA_WAIT 48 #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10 /* 100 ms */ 49 #endif 50 51 static int ACEX1K_ps_load( Altera_desc *desc, void *buf, size_t bsize ); 52 static int ACEX1K_ps_dump( Altera_desc *desc, void *buf, size_t bsize ); 53 /* static int ACEX1K_ps_info( Altera_desc *desc ); */ 54 static int ACEX1K_ps_reloc( Altera_desc *desc, ulong reloc_offset ); 55 56 /* ------------------------------------------------------------------------- */ 57 /* ACEX1K Generic Implementation */ 58 int ACEX1K_load (Altera_desc * desc, void *buf, size_t bsize) 59 { 60 int ret_val = FPGA_FAIL; 61 62 switch (desc->iface) { 63 case passive_serial: 64 PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__); 65 ret_val = ACEX1K_ps_load (desc, buf, bsize); 66 break; 67 68 /* Add new interface types here */ 69 70 default: 71 printf ("%s: Unsupported interface type, %d\n", 72 __FUNCTION__, desc->iface); 73 } 74 75 return ret_val; 76 } 77 78 int ACEX1K_dump (Altera_desc * desc, void *buf, size_t bsize) 79 { 80 int ret_val = FPGA_FAIL; 81 82 switch (desc->iface) { 83 case passive_serial: 84 PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__); 85 ret_val = ACEX1K_ps_dump (desc, buf, bsize); 86 break; 87 88 /* Add new interface types here */ 89 90 default: 91 printf ("%s: Unsupported interface type, %d\n", 92 __FUNCTION__, desc->iface); 93 } 94 95 return ret_val; 96 } 97 98 int ACEX1K_info( Altera_desc *desc ) 99 { 100 return FPGA_SUCCESS; 101 } 102 103 104 int ACEX1K_reloc (Altera_desc * desc, ulong reloc_offset) 105 { 106 int ret_val = FPGA_FAIL; /* assume a failure */ 107 108 if (desc->family != Altera_ACEX1K) { 109 printf ("%s: Unsupported family type, %d\n", 110 __FUNCTION__, desc->family); 111 return FPGA_FAIL; 112 } else 113 switch (desc->iface) { 114 case passive_serial: 115 ret_val = ACEX1K_ps_reloc (desc, reloc_offset); 116 break; 117 118 /* Add new interface types here */ 119 120 default: 121 printf ("%s: Unsupported interface type, %d\n", 122 __FUNCTION__, desc->iface); 123 } 124 125 return ret_val; 126 } 127 128 129 /* ------------------------------------------------------------------------- */ 130 /* ACEX1K Passive Serial Generic Implementation */ 131 132 static int ACEX1K_ps_load (Altera_desc * desc, void *buf, size_t bsize) 133 { 134 int ret_val = FPGA_FAIL; /* assume the worst */ 135 Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns; 136 int i; 137 138 PRINTF ("%s: start with interface functions @ 0x%p\n", 139 __FUNCTION__, fn); 140 141 if (fn) { 142 size_t bytecount = 0; 143 unsigned char *data = (unsigned char *) buf; 144 int cookie = desc->cookie; /* make a local copy */ 145 unsigned long ts; /* timestamp */ 146 147 PRINTF ("%s: Function Table:\n" 148 "ptr:\t0x%p\n" 149 "struct: 0x%p\n" 150 "config:\t0x%p\n" 151 "status:\t0x%p\n" 152 "clk:\t0x%p\n" 153 "data:\t0x%p\n" 154 "done:\t0x%p\n\n", 155 __FUNCTION__, &fn, fn, fn->config, fn->status, 156 fn->clk, fn->data, fn->done); 157 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 158 printf ("Loading FPGA Device %d...", cookie); 159 #endif 160 161 /* 162 * Run the pre configuration function if there is one. 163 */ 164 if (*fn->pre) { 165 (*fn->pre) (cookie); 166 } 167 168 /* Establish the initial state */ 169 (*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */ 170 171 udelay(2); /* T_cfg > 2us */ 172 173 /* nSTATUS should be asserted now */ 174 (*fn->done) (cookie); 175 if ( !(*fn->status) (cookie) ) { 176 puts ("** nSTATUS is not asserted.\n"); 177 (*fn->abort) (cookie); 178 return FPGA_FAIL; 179 } 180 181 (*fn->config) (FALSE, TRUE, cookie); /* Deassert nCONFIG */ 182 udelay(2); /* T_cf2st1 < 4us */ 183 184 /* Wait for nSTATUS to be released (i.e. deasserted) */ 185 ts = get_timer (0); /* get current time */ 186 do { 187 CONFIG_FPGA_DELAY (); 188 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ 189 puts ("** Timeout waiting for STATUS to go high.\n"); 190 (*fn->abort) (cookie); 191 return FPGA_FAIL; 192 } 193 (*fn->done) (cookie); 194 } while ((*fn->status) (cookie)); 195 196 /* Get ready for the burn */ 197 CONFIG_FPGA_DELAY (); 198 199 /* Load the data */ 200 while (bytecount < bsize) { 201 unsigned char val=0; 202 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC 203 if (ctrlc ()) { 204 (*fn->abort) (cookie); 205 return FPGA_FAIL; 206 } 207 #endif 208 /* Altera detects an error if INIT goes low (active) 209 while DONE is low (inactive) */ 210 #if 0 /* not yet implemented */ 211 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { 212 puts ("** CRC error during FPGA load.\n"); 213 (*fn->abort) (cookie); 214 return (FPGA_FAIL); 215 } 216 #endif 217 val = data [bytecount ++ ]; 218 i = 8; 219 do { 220 /* Deassert the clock */ 221 (*fn->clk) (FALSE, TRUE, cookie); 222 CONFIG_FPGA_DELAY (); 223 /* Write data */ 224 (*fn->data) ( (val & 0x01), TRUE, cookie); 225 CONFIG_FPGA_DELAY (); 226 /* Assert the clock */ 227 (*fn->clk) (TRUE, TRUE, cookie); 228 CONFIG_FPGA_DELAY (); 229 val >>= 1; 230 i --; 231 } while (i > 0); 232 233 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 234 if (bytecount % (bsize / 40) == 0) 235 putc ('.'); /* let them know we are alive */ 236 #endif 237 } 238 239 CONFIG_FPGA_DELAY (); 240 241 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 242 putc (' '); /* terminate the dotted line */ 243 #endif 244 245 /* 246 * Checking FPGA's CONF_DONE signal - correctly booted ? 247 */ 248 249 if ( ! (*fn->done) (cookie) ) { 250 puts ("** Booting failed! CONF_DONE is still deasserted.\n"); 251 (*fn->abort) (cookie); 252 return (FPGA_FAIL); 253 } 254 255 /* 256 * "DCLK must be clocked an additional 10 times fpr ACEX 1K..." 257 */ 258 259 for (i = 0; i < 12; i++) { 260 CONFIG_FPGA_DELAY (); 261 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ 262 CONFIG_FPGA_DELAY (); 263 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ 264 } 265 266 ret_val = FPGA_SUCCESS; 267 268 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 269 if (ret_val == FPGA_SUCCESS) { 270 puts ("Done.\n"); 271 } 272 else { 273 puts ("Fail.\n"); 274 } 275 #endif 276 (*fn->post) (cookie); 277 278 } else { 279 printf ("%s: NULL Interface function table!\n", __FUNCTION__); 280 } 281 282 return ret_val; 283 } 284 285 static int ACEX1K_ps_dump (Altera_desc * desc, void *buf, size_t bsize) 286 { 287 /* Readback is only available through the Slave Parallel and */ 288 /* boundary-scan interfaces. */ 289 printf ("%s: Passive Serial Dumping is unavailable\n", 290 __FUNCTION__); 291 return FPGA_FAIL; 292 } 293 294 static int ACEX1K_ps_reloc (Altera_desc * desc, ulong reloc_offset) 295 { 296 int ret_val = FPGA_FAIL; /* assume the worst */ 297 Altera_ACEX1K_Passive_Serial_fns *fn_r, *fn = 298 (Altera_ACEX1K_Passive_Serial_fns *) (desc->iface_fns); 299 300 if (fn) { 301 ulong addr; 302 303 /* Get the relocated table address */ 304 addr = (ulong) fn + reloc_offset; 305 fn_r = (Altera_ACEX1K_Passive_Serial_fns *) addr; 306 307 if (!fn_r->relocated) { 308 309 if (memcmp (fn_r, fn, 310 sizeof (Altera_ACEX1K_Passive_Serial_fns)) 311 == 0) { 312 /* good copy of the table, fix the descriptor pointer */ 313 desc->iface_fns = fn_r; 314 } else { 315 PRINTF ("%s: Invalid function table at 0x%p\n", 316 __FUNCTION__, fn_r); 317 return FPGA_FAIL; 318 } 319 320 PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, 321 desc); 322 323 addr = (ulong) (fn->pre) + reloc_offset; 324 fn_r->pre = (Altera_pre_fn) addr; 325 326 addr = (ulong) (fn->config) + reloc_offset; 327 fn_r->config = (Altera_config_fn) addr; 328 329 addr = (ulong) (fn->status) + reloc_offset; 330 fn_r->status = (Altera_status_fn) addr; 331 332 addr = (ulong) (fn->done) + reloc_offset; 333 fn_r->done = (Altera_done_fn) addr; 334 335 addr = (ulong) (fn->clk) + reloc_offset; 336 fn_r->clk = (Altera_clk_fn) addr; 337 338 addr = (ulong) (fn->data) + reloc_offset; 339 fn_r->data = (Altera_data_fn) addr; 340 341 addr = (ulong) (fn->abort) + reloc_offset; 342 fn_r->abort = (Altera_abort_fn) addr; 343 344 addr = (ulong) (fn->post) + reloc_offset; 345 fn_r->post = (Altera_post_fn) addr; 346 347 fn_r->relocated = TRUE; 348 349 } else { 350 /* this table has already been moved */ 351 /* XXX - should check to see if the descriptor is correct */ 352 desc->iface_fns = fn_r; 353 } 354 355 ret_val = FPGA_SUCCESS; 356 } else { 357 printf ("%s: NULL Interface function table!\n", __FUNCTION__); 358 } 359 360 return ret_val; 361 362 } 363