spartan2.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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. /* XXX - we should have a check in here somewhere to
  220. * make sure we aren't busy forever... */
  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. if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
  226. puts ("** Timeout waiting for DONE to clear.\n");
  227. (*fn->abort) (cookie); /* abort the burn */
  228. ret_val = FPGA_FAIL;
  229. break;
  230. }
  231. }
  232. if (ret_val == FPGA_SUCCESS) {
  233. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  234. puts ("Done.\n");
  235. #endif
  236. }
  237. /*
  238. * Run the post configuration function if there is one.
  239. */
  240. if (*fn->post) {
  241. (*fn->post) (cookie);
  242. }
  243. else {
  244. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  245. puts ("Fail.\n");
  246. #endif
  247. }
  248. } else {
  249. printf ("%s: NULL Interface function table!\n", __FUNCTION__);
  250. }
  251. return ret_val;
  252. }
  253. static int Spartan2_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize)
  254. {
  255. int ret_val = FPGA_FAIL; /* assume the worst */
  256. Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
  257. if (fn) {
  258. unsigned char *data = (unsigned char *) buf;
  259. size_t bytecount = 0;
  260. int cookie = desc->cookie; /* make a local copy */
  261. printf ("Starting Dump of FPGA Device %d...\n", cookie);
  262. (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
  263. (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
  264. /* dump the data */
  265. while (bytecount < bsize) {
  266. /* XXX - do we check for an Ctrl-C press in here ??? */
  267. (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
  268. (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
  269. (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
  270. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  271. if (bytecount % (bsize / 40) == 0)
  272. putc ('.'); /* let them know we are alive */
  273. #endif
  274. }
  275. (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */
  276. (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
  277. (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
  278. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  279. putc ('\n'); /* terminate the dotted line */
  280. #endif
  281. puts ("Done.\n");
  282. /* XXX - checksum the data? */
  283. } else {
  284. printf ("%s: NULL Interface function table!\n", __FUNCTION__);
  285. }
  286. return ret_val;
  287. }
  288. static int Spartan2_sp_reloc (Xilinx_desc * desc, ulong reloc_offset)
  289. {
  290. int ret_val = FPGA_FAIL; /* assume the worst */
  291. Xilinx_Spartan2_Slave_Parallel_fns *fn_r, *fn =
  292. (Xilinx_Spartan2_Slave_Parallel_fns *) (desc->iface_fns);
  293. if (fn) {
  294. ulong addr;
  295. /* Get the relocated table address */
  296. addr = (ulong) fn + reloc_offset;
  297. fn_r = (Xilinx_Spartan2_Slave_Parallel_fns *) addr;
  298. if (!fn_r->relocated) {
  299. if (memcmp (fn_r, fn,
  300. sizeof (Xilinx_Spartan2_Slave_Parallel_fns))
  301. == 0) {
  302. /* good copy of the table, fix the descriptor pointer */
  303. desc->iface_fns = fn_r;
  304. } else {
  305. PRINTF ("%s: Invalid function table at 0x%p\n",
  306. __FUNCTION__, fn_r);
  307. return FPGA_FAIL;
  308. }
  309. PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
  310. desc);
  311. addr = (ulong) (fn->pre) + reloc_offset;
  312. fn_r->pre = (Xilinx_pre_fn) addr;
  313. addr = (ulong) (fn->pgm) + reloc_offset;
  314. fn_r->pgm = (Xilinx_pgm_fn) addr;
  315. addr = (ulong) (fn->init) + reloc_offset;
  316. fn_r->init = (Xilinx_init_fn) addr;
  317. addr = (ulong) (fn->done) + reloc_offset;
  318. fn_r->done = (Xilinx_done_fn) addr;
  319. addr = (ulong) (fn->clk) + reloc_offset;
  320. fn_r->clk = (Xilinx_clk_fn) addr;
  321. addr = (ulong) (fn->err) + reloc_offset;
  322. fn_r->err = (Xilinx_err_fn) addr;
  323. addr = (ulong) (fn->cs) + reloc_offset;
  324. fn_r->cs = (Xilinx_cs_fn) addr;
  325. addr = (ulong) (fn->wr) + reloc_offset;
  326. fn_r->wr = (Xilinx_wr_fn) addr;
  327. addr = (ulong) (fn->rdata) + reloc_offset;
  328. fn_r->rdata = (Xilinx_rdata_fn) addr;
  329. addr = (ulong) (fn->wdata) + reloc_offset;
  330. fn_r->wdata = (Xilinx_wdata_fn) addr;
  331. addr = (ulong) (fn->busy) + reloc_offset;
  332. fn_r->busy = (Xilinx_busy_fn) addr;
  333. addr = (ulong) (fn->abort) + reloc_offset;
  334. fn_r->abort = (Xilinx_abort_fn) addr;
  335. addr = (ulong) (fn->post) + reloc_offset;
  336. fn_r->post = (Xilinx_post_fn) addr;
  337. fn_r->relocated = TRUE;
  338. } else {
  339. /* this table has already been moved */
  340. /* XXX - should check to see if the descriptor is correct */
  341. desc->iface_fns = fn_r;
  342. }
  343. ret_val = FPGA_SUCCESS;
  344. } else {
  345. printf ("%s: NULL Interface function table!\n", __FUNCTION__);
  346. }
  347. return ret_val;
  348. }
  349. /* ------------------------------------------------------------------------- */
  350. static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
  351. {
  352. int ret_val = FPGA_FAIL; /* assume the worst */
  353. Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
  354. int i;
  355. unsigned char val;
  356. PRINTF ("%s: start with interface functions @ 0x%p\n",
  357. __FUNCTION__, fn);
  358. if (fn) {
  359. size_t bytecount = 0;
  360. unsigned char *data = (unsigned char *) buf;
  361. int cookie = desc->cookie; /* make a local copy */
  362. unsigned long ts; /* timestamp */
  363. PRINTF ("%s: Function Table:\n"
  364. "ptr:\t0x%p\n"
  365. "struct: 0x%p\n"
  366. "pgm:\t0x%p\n"
  367. "init:\t0x%p\n"
  368. "clk:\t0x%p\n"
  369. "wr:\t0x%p\n"
  370. "done:\t0x%p\n\n",
  371. __FUNCTION__, &fn, fn, fn->pgm, fn->init,
  372. fn->clk, fn->wr, fn->done);
  373. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  374. printf ("Loading FPGA Device %d...\n", cookie);
  375. #endif
  376. /*
  377. * Run the pre configuration function if there is one.
  378. */
  379. if (*fn->pre) {
  380. (*fn->pre) (cookie);
  381. }
  382. /* Establish the initial state */
  383. (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
  384. /* Wait for INIT state (init low) */
  385. ts = get_timer (0); /* get current time */
  386. do {
  387. CONFIG_FPGA_DELAY ();
  388. if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
  389. puts ("** Timeout waiting for INIT to start.\n");
  390. return FPGA_FAIL;
  391. }
  392. } while (!(*fn->init) (cookie));
  393. /* Get ready for the burn */
  394. CONFIG_FPGA_DELAY ();
  395. (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
  396. ts = get_timer (0); /* get current time */
  397. /* Now wait for INIT to go high */
  398. do {
  399. CONFIG_FPGA_DELAY ();
  400. if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
  401. puts ("** Timeout waiting for INIT to clear.\n");
  402. return FPGA_FAIL;
  403. }
  404. } while ((*fn->init) (cookie));
  405. /* Load the data */
  406. while (bytecount < bsize) {
  407. /* Xilinx detects an error if INIT goes low (active)
  408. while DONE is low (inactive) */
  409. if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
  410. puts ("** CRC error during FPGA load.\n");
  411. return (FPGA_FAIL);
  412. }
  413. val = data [bytecount ++];
  414. i = 8;
  415. do {
  416. /* Deassert the clock */
  417. (*fn->clk) (FALSE, TRUE, cookie);
  418. CONFIG_FPGA_DELAY ();
  419. /* Write data */
  420. (*fn->wr) ((val & 0x80), TRUE, cookie);
  421. CONFIG_FPGA_DELAY ();
  422. /* Assert the clock */
  423. (*fn->clk) (TRUE, TRUE, cookie);
  424. CONFIG_FPGA_DELAY ();
  425. val <<= 1;
  426. i --;
  427. } while (i > 0);
  428. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  429. if (bytecount % (bsize / 40) == 0)
  430. putc ('.'); /* let them know we are alive */
  431. #endif
  432. }
  433. CONFIG_FPGA_DELAY ();
  434. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  435. putc ('\n'); /* terminate the dotted line */
  436. #endif
  437. /* now check for done signal */
  438. ts = get_timer (0); /* get current time */
  439. ret_val = FPGA_SUCCESS;
  440. (*fn->wr) (TRUE, TRUE, cookie);
  441. while (! (*fn->done) (cookie)) {
  442. /* XXX - we should have a check in here somewhere to
  443. * make sure we aren't busy forever... */
  444. CONFIG_FPGA_DELAY ();
  445. (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
  446. CONFIG_FPGA_DELAY ();
  447. (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
  448. putc ('*');
  449. if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
  450. puts ("** Timeout waiting for DONE to clear.\n");
  451. ret_val = FPGA_FAIL;
  452. break;
  453. }
  454. }
  455. putc ('\n'); /* terminate the dotted line */
  456. /*
  457. * Run the post configuration function if there is one.
  458. */
  459. if (*fn->post) {
  460. (*fn->post) (cookie);
  461. }
  462. #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
  463. if (ret_val == FPGA_SUCCESS) {
  464. puts ("Done.\n");
  465. }
  466. else {
  467. puts ("Fail.\n");
  468. }
  469. #endif
  470. } else {
  471. printf ("%s: NULL Interface function table!\n", __FUNCTION__);
  472. }
  473. return ret_val;
  474. }
  475. static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
  476. {
  477. /* Readback is only available through the Slave Parallel and */
  478. /* boundary-scan interfaces. */
  479. printf ("%s: Slave Serial Dumping is unavailable\n",
  480. __FUNCTION__);
  481. return FPGA_FAIL;
  482. }
  483. static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
  484. {
  485. int ret_val = FPGA_FAIL; /* assume the worst */
  486. Xilinx_Spartan2_Slave_Serial_fns *fn_r, *fn =
  487. (Xilinx_Spartan2_Slave_Serial_fns *) (desc->iface_fns);
  488. if (fn) {
  489. ulong addr;
  490. /* Get the relocated table address */
  491. addr = (ulong) fn + reloc_offset;
  492. fn_r = (Xilinx_Spartan2_Slave_Serial_fns *) addr;
  493. if (!fn_r->relocated) {
  494. if (memcmp (fn_r, fn,
  495. sizeof (Xilinx_Spartan2_Slave_Serial_fns))
  496. == 0) {
  497. /* good copy of the table, fix the descriptor pointer */
  498. desc->iface_fns = fn_r;
  499. } else {
  500. PRINTF ("%s: Invalid function table at 0x%p\n",
  501. __FUNCTION__, fn_r);
  502. return FPGA_FAIL;
  503. }
  504. PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
  505. desc);
  506. if (fn->pre) {
  507. addr = (ulong) (fn->pre) + reloc_offset;
  508. fn_r->pre = (Xilinx_pre_fn) addr;
  509. }
  510. addr = (ulong) (fn->pgm) + reloc_offset;
  511. fn_r->pgm = (Xilinx_pgm_fn) addr;
  512. addr = (ulong) (fn->init) + reloc_offset;
  513. fn_r->init = (Xilinx_init_fn) addr;
  514. addr = (ulong) (fn->done) + reloc_offset;
  515. fn_r->done = (Xilinx_done_fn) addr;
  516. addr = (ulong) (fn->clk) + reloc_offset;
  517. fn_r->clk = (Xilinx_clk_fn) addr;
  518. addr = (ulong) (fn->wr) + reloc_offset;
  519. fn_r->wr = (Xilinx_wr_fn) addr;
  520. if (fn->post) {
  521. addr = (ulong) (fn->post) + reloc_offset;
  522. fn_r->post = (Xilinx_post_fn) addr;
  523. }
  524. fn_r->relocated = TRUE;
  525. } else {
  526. /* this table has already been moved */
  527. /* XXX - should check to see if the descriptor is correct */
  528. desc->iface_fns = fn_r;
  529. }
  530. ret_val = FPGA_SUCCESS;
  531. } else {
  532. printf ("%s: NULL Interface function table!\n", __FUNCTION__);
  533. }
  534. return ret_val;
  535. }