spartan3.c 18 KB

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