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