spartan3.c 18 KB

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