spartan2.c 17 KB

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