]>
Commit | Line | Data |
---|---|---|
5d3207da WD |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Rich Ireland, Enterasys Networks, [email protected]. | |
4 | * Keith Outwater, [email protected] | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | * | |
24 | */ | |
25 | ||
26 | /* | |
27 | * Configuration support for Xilinx Virtex2 devices. Based | |
28 | * on spartan2.c (Rich Ireland, [email protected]). | |
29 | */ | |
30 | ||
31 | #include <common.h> | |
32 | #include <virtex2.h> | |
33 | ||
9a9200b4 WD |
34 | #if 0 |
35 | #define FPGA_DEBUG | |
265817c7 | 36 | #endif |
9a9200b4 | 37 | |
5d3207da WD |
38 | #ifdef FPGA_DEBUG |
39 | #define PRINTF(fmt,args...) printf (fmt ,##args) | |
40 | #else | |
41 | #define PRINTF(fmt,args...) | |
42 | #endif | |
43 | ||
44 | /* | |
45 | * If the SelectMap interface can be overrun by the processor, define | |
6d0f6bcf | 46 | * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration |
5d3207da WD |
47 | * file and add board-specific support for checking BUSY status. By default, |
48 | * assume that the SelectMap interface cannot be overrun. | |
49 | */ | |
6d0f6bcf JCPV |
50 | #ifndef CONFIG_SYS_FPGA_CHECK_BUSY |
51 | #undef CONFIG_SYS_FPGA_CHECK_BUSY | |
5d3207da WD |
52 | #endif |
53 | ||
54 | #ifndef CONFIG_FPGA_DELAY | |
55 | #define CONFIG_FPGA_DELAY() | |
56 | #endif | |
57 | ||
6d0f6bcf JCPV |
58 | #ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK |
59 | #define CONFIG_SYS_FPGA_PROG_FEEDBACK | |
5d3207da WD |
60 | #endif |
61 | ||
62 | /* | |
63 | * Don't allow config cycle to be interrupted | |
64 | */ | |
6d0f6bcf JCPV |
65 | #ifndef CONFIG_SYS_FPGA_CHECK_CTRLC |
66 | #undef CONFIG_SYS_FPGA_CHECK_CTRLC | |
5d3207da WD |
67 | #endif |
68 | ||
69 | /* | |
70 | * Check for errors during configuration by default | |
71 | */ | |
6d0f6bcf JCPV |
72 | #ifndef CONFIG_SYS_FPGA_CHECK_ERROR |
73 | #define CONFIG_SYS_FPGA_CHECK_ERROR | |
5d3207da WD |
74 | #endif |
75 | ||
76 | /* | |
77 | * The default timeout in mS for INIT_B to deassert after PROG_B has | |
78 | * been deasserted. Per the latest Virtex II Handbook (page 347), the | |
79 | * max time from PORG_B deassertion to INIT_B deassertion is 4uS per | |
80 | * data frame for the XC2V8000. The XC2V8000 has 2860 data frames | |
81 | * which yields 11.44 mS. So let's make it bigger in order to handle | |
82 | * an XC2V1000, if anyone can ever get ahold of one. | |
83 | */ | |
6d0f6bcf JCPV |
84 | #ifndef CONFIG_SYS_FPGA_WAIT_INIT |
85 | #define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ/2 /* 500 ms */ | |
5d3207da WD |
86 | #endif |
87 | ||
88 | /* | |
89 | * The default timeout for waiting for BUSY to deassert during configuration. | |
90 | * This is normally not necessary since for most reasonable configuration | |
91 | * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary. | |
92 | */ | |
6d0f6bcf JCPV |
93 | #ifndef CONFIG_SYS_FPGA_WAIT_BUSY |
94 | #define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ/200 /* 5 ms*/ | |
5d3207da WD |
95 | #endif |
96 | ||
97 | /* Default timeout for waiting for FPGA to enter operational mode after | |
98 | * configuration data has been written. | |
99 | */ | |
6d0f6bcf JCPV |
100 | #ifndef CONFIG_SYS_FPGA_WAIT_CONFIG |
101 | #define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ/5 /* 200 ms */ | |
5d3207da WD |
102 | #endif |
103 | ||
104 | static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize); | |
105 | static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize); | |
106 | static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset); | |
107 | ||
108 | static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize); | |
109 | static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize); | |
110 | static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset); | |
111 | ||
112 | int Virtex2_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
113 | { | |
114 | int ret_val = FPGA_FAIL; | |
115 | ||
116 | switch (desc->iface) { | |
117 | case slave_serial: | |
118 | PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__); | |
119 | ret_val = Virtex2_ss_load (desc, buf, bsize); | |
120 | break; | |
121 | ||
122 | case slave_selectmap: | |
123 | PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__); | |
124 | ret_val = Virtex2_ssm_load (desc, buf, bsize); | |
125 | break; | |
126 | ||
127 | default: | |
128 | printf ("%s: Unsupported interface type, %d\n", | |
129 | __FUNCTION__, desc->iface); | |
130 | } | |
131 | return ret_val; | |
132 | } | |
133 | ||
134 | int Virtex2_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
135 | { | |
136 | int ret_val = FPGA_FAIL; | |
137 | ||
138 | switch (desc->iface) { | |
139 | case slave_serial: | |
140 | PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__); | |
141 | ret_val = Virtex2_ss_dump (desc, buf, bsize); | |
142 | break; | |
143 | ||
144 | case slave_parallel: | |
145 | PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__); | |
146 | ret_val = Virtex2_ssm_dump (desc, buf, bsize); | |
147 | break; | |
148 | ||
149 | default: | |
150 | printf ("%s: Unsupported interface type, %d\n", | |
151 | __FUNCTION__, desc->iface); | |
152 | } | |
153 | return ret_val; | |
154 | } | |
155 | ||
156 | int Virtex2_info (Xilinx_desc * desc) | |
157 | { | |
158 | return FPGA_SUCCESS; | |
159 | } | |
160 | ||
161 | int Virtex2_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
162 | { | |
163 | int ret_val = FPGA_FAIL; | |
164 | ||
165 | if (desc->family != Xilinx_Virtex2) { | |
166 | printf ("%s: Unsupported family type, %d\n", | |
167 | __FUNCTION__, desc->family); | |
168 | return FPGA_FAIL; | |
169 | } else | |
170 | switch (desc->iface) { | |
171 | case slave_serial: | |
172 | ret_val = Virtex2_ss_reloc (desc, reloc_offset); | |
173 | break; | |
174 | ||
175 | case slave_selectmap: | |
176 | ret_val = Virtex2_ssm_reloc (desc, reloc_offset); | |
177 | break; | |
178 | ||
179 | default: | |
180 | printf ("%s: Unsupported interface type, %d\n", | |
181 | __FUNCTION__, desc->iface); | |
182 | } | |
183 | return ret_val; | |
184 | } | |
185 | ||
186 | /* | |
187 | * Virtex-II Slave SelectMap configuration loader. Configuration via | |
188 | * SelectMap is as follows: | |
189 | * 1. Set the FPGA's PROG_B line low. | |
190 | * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high. | |
191 | * 3. Write data to the SelectMap port. If INIT_B goes low at any time | |
192 | * this process, a configuration error (most likely CRC failure) has | |
193 | * ocurred. At this point a status word may be read from the | |
194 | * SelectMap interface to determine the source of the problem (You | |
9a9200b4 | 195 | * could, for instance, put this in your 'abort' function handler). |
5d3207da WD |
196 | * 4. After all data has been written, test the state of the FPGA |
197 | * INIT_B and DONE lines. If both are high, configuration has | |
198 | * succeeded. Congratulations! | |
199 | */ | |
200 | static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
201 | { | |
202 | int ret_val = FPGA_FAIL; | |
203 | Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns; | |
204 | ||
205 | PRINTF ("%s:%d: Start with interface functions @ 0x%p\n", | |
206 | __FUNCTION__, __LINE__, fn); | |
207 | ||
208 | if (fn) { | |
209 | size_t bytecount = 0; | |
210 | unsigned char *data = (unsigned char *) buf; | |
211 | int cookie = desc->cookie; | |
212 | unsigned long ts; | |
213 | ||
214 | /* Gotta split this one up (so the stack won't blow??) */ | |
215 | PRINTF ("%s:%d: Function Table:\n" | |
216 | " base 0x%p\n" | |
217 | " struct 0x%p\n" | |
218 | " pre 0x%p\n" | |
219 | " prog 0x%p\n" | |
220 | " init 0x%p\n" | |
221 | " error 0x%p\n", | |
222 | __FUNCTION__, __LINE__, | |
223 | &fn, fn, fn->pre, fn->pgm, fn->init, fn->err); | |
224 | PRINTF (" clock 0x%p\n" | |
225 | " cs 0x%p\n" | |
226 | " write 0x%p\n" | |
227 | " rdata 0x%p\n" | |
228 | " wdata 0x%p\n" | |
229 | " busy 0x%p\n" | |
230 | " abort 0x%p\n" | |
231 | " post 0x%p\n\n", | |
232 | fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, | |
233 | fn->busy, fn->abort, fn->post); | |
234 | ||
6d0f6bcf | 235 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
236 | printf ("Initializing FPGA Device %d...\n", cookie); |
237 | #endif | |
238 | /* | |
239 | * Run the pre configuration function if there is one. | |
240 | */ | |
241 | if (*fn->pre) { | |
242 | (*fn->pre) (cookie); | |
243 | } | |
244 | ||
245 | /* | |
246 | * Assert the program line. The minimum pulse width for | |
247 | * Virtex II devices is 300 nS (Tprogram parameter in datasheet). | |
248 | * There is no maximum value for the pulse width. Check to make | |
249 | * sure that INIT_B goes low after assertion of PROG_B | |
250 | */ | |
251 | (*fn->pgm) (TRUE, TRUE, cookie); | |
252 | udelay (10); | |
253 | ts = get_timer (0); | |
254 | do { | |
6d0f6bcf | 255 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) { |
9a9200b4 | 256 | printf ("%s:%d: ** Timeout after %d ticks waiting for INIT" |
5d3207da | 257 | " to assert.\n", __FUNCTION__, __LINE__, |
6d0f6bcf | 258 | CONFIG_SYS_FPGA_WAIT_INIT); |
5d3207da WD |
259 | (*fn->abort) (cookie); |
260 | return FPGA_FAIL; | |
261 | } | |
262 | } while (!(*fn->init) (cookie)); | |
263 | ||
264 | (*fn->pgm) (FALSE, TRUE, cookie); | |
265 | CONFIG_FPGA_DELAY (); | |
266 | (*fn->clk) (TRUE, TRUE, cookie); | |
267 | ||
268 | /* | |
269 | * Start a timer and wait for INIT_B to go high | |
270 | */ | |
271 | ts = get_timer (0); | |
272 | do { | |
273 | CONFIG_FPGA_DELAY (); | |
6d0f6bcf | 274 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) { |
9a9200b4 | 275 | printf ("%s:%d: ** Timeout after %d ticks waiting for INIT" |
5d3207da | 276 | " to deassert.\n", __FUNCTION__, __LINE__, |
6d0f6bcf | 277 | CONFIG_SYS_FPGA_WAIT_INIT); |
5d3207da WD |
278 | (*fn->abort) (cookie); |
279 | return FPGA_FAIL; | |
280 | } | |
281 | } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); | |
282 | ||
283 | (*fn->wr) (TRUE, TRUE, cookie); | |
284 | (*fn->cs) (TRUE, TRUE, cookie); | |
285 | ||
286 | udelay (10000); | |
287 | ||
288 | /* | |
289 | * Load the data byte by byte | |
290 | */ | |
291 | while (bytecount < bsize) { | |
6d0f6bcf | 292 | #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC |
5d3207da WD |
293 | if (ctrlc ()) { |
294 | (*fn->abort) (cookie); | |
295 | return FPGA_FAIL; | |
296 | } | |
297 | #endif | |
9a9200b4 WD |
298 | |
299 | if ((*fn->done) (cookie) == FPGA_SUCCESS) { | |
300 | PRINTF ("%s:%d:done went active early, bytecount = %d\n", | |
301 | __FUNCTION__, __LINE__, bytecount); | |
302 | break; | |
303 | } | |
304 | ||
6d0f6bcf | 305 | #ifdef CONFIG_SYS_FPGA_CHECK_ERROR |
5d3207da | 306 | if ((*fn->init) (cookie)) { |
9a9200b4 | 307 | printf ("\n%s:%d: ** Error: INIT asserted during" |
5d3207da | 308 | " configuration\n", __FUNCTION__, __LINE__); |
9a9200b4 WD |
309 | printf ("%d = buffer offset, %d = buffer size\n", |
310 | bytecount, bsize); | |
5d3207da WD |
311 | (*fn->abort) (cookie); |
312 | return FPGA_FAIL; | |
313 | } | |
314 | #endif | |
9a9200b4 | 315 | |
5d3207da WD |
316 | (*fn->wdata) (data[bytecount++], TRUE, cookie); |
317 | CONFIG_FPGA_DELAY (); | |
318 | ||
319 | /* | |
320 | * Cycle the clock pin | |
321 | */ | |
322 | (*fn->clk) (FALSE, TRUE, cookie); | |
323 | CONFIG_FPGA_DELAY (); | |
324 | (*fn->clk) (TRUE, TRUE, cookie); | |
325 | ||
6d0f6bcf | 326 | #ifdef CONFIG_SYS_FPGA_CHECK_BUSY |
5d3207da WD |
327 | ts = get_timer (0); |
328 | while ((*fn->busy) (cookie)) { | |
6d0f6bcf | 329 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) { |
9a9200b4 | 330 | printf ("%s:%d: ** Timeout after %d ticks waiting for" |
5d3207da | 331 | " BUSY to deassert\n", |
6d0f6bcf | 332 | __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY); |
5d3207da WD |
333 | (*fn->abort) (cookie); |
334 | return FPGA_FAIL; | |
335 | } | |
336 | } | |
337 | #endif | |
338 | ||
6d0f6bcf | 339 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
340 | if (bytecount % (bsize / 40) == 0) |
341 | putc ('.'); | |
342 | #endif | |
343 | } | |
344 | ||
345 | /* | |
346 | * Finished writing the data; deassert FPGA CS_B and WRITE_B signals. | |
347 | */ | |
348 | CONFIG_FPGA_DELAY (); | |
349 | (*fn->cs) (FALSE, TRUE, cookie); | |
350 | (*fn->wr) (FALSE, TRUE, cookie); | |
351 | ||
6d0f6bcf | 352 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
353 | putc ('\n'); |
354 | #endif | |
355 | ||
356 | /* | |
357 | * Check for successful configuration. FPGA INIT_B and DONE should | |
358 | * both be high upon successful configuration. | |
359 | */ | |
360 | ts = get_timer (0); | |
361 | ret_val = FPGA_SUCCESS; | |
362 | while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) { | |
6d0f6bcf | 363 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) { |
9a9200b4 | 364 | printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to" |
5d3207da | 365 | "assert and INIT to deassert\n", |
6d0f6bcf | 366 | __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG); |
5d3207da WD |
367 | (*fn->abort) (cookie); |
368 | ret_val = FPGA_FAIL; | |
369 | break; | |
370 | } | |
371 | } | |
372 | ||
373 | if (ret_val == FPGA_SUCCESS) { | |
6d0f6bcf | 374 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
375 | printf ("Initialization of FPGA device %d complete\n", cookie); |
376 | #endif | |
377 | /* | |
378 | * Run the post configuration function if there is one. | |
379 | */ | |
380 | if (*fn->post) { | |
381 | (*fn->post) (cookie); | |
382 | } | |
383 | } else { | |
6d0f6bcf | 384 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
385 | printf ("** Initialization of FPGA device %d FAILED\n", |
386 | cookie); | |
387 | #endif | |
388 | } | |
389 | } else { | |
390 | printf ("%s:%d: NULL Interface function table!\n", | |
391 | __FUNCTION__, __LINE__); | |
392 | } | |
393 | return ret_val; | |
394 | } | |
395 | ||
396 | /* | |
397 | * Read the FPGA configuration data | |
398 | */ | |
399 | static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
400 | { | |
401 | int ret_val = FPGA_FAIL; | |
402 | Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns; | |
403 | ||
404 | if (fn) { | |
405 | unsigned char *data = (unsigned char *) buf; | |
406 | size_t bytecount = 0; | |
407 | int cookie = desc->cookie; | |
408 | ||
409 | printf ("Starting Dump of FPGA Device %d...\n", cookie); | |
410 | ||
411 | (*fn->cs) (TRUE, TRUE, cookie); | |
412 | (*fn->clk) (TRUE, TRUE, cookie); | |
413 | ||
414 | while (bytecount < bsize) { | |
6d0f6bcf | 415 | #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC |
5d3207da WD |
416 | if (ctrlc ()) { |
417 | (*fn->abort) (cookie); | |
418 | return FPGA_FAIL; | |
419 | } | |
420 | #endif | |
421 | /* | |
422 | * Cycle the clock and read the data | |
423 | */ | |
424 | (*fn->clk) (FALSE, TRUE, cookie); | |
425 | (*fn->clk) (TRUE, TRUE, cookie); | |
426 | (*fn->rdata) (&(data[bytecount++]), cookie); | |
6d0f6bcf | 427 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
428 | if (bytecount % (bsize / 40) == 0) |
429 | putc ('.'); | |
430 | #endif | |
431 | } | |
432 | ||
433 | /* | |
434 | * Deassert CS_B and cycle the clock to deselect the device. | |
435 | */ | |
436 | (*fn->cs) (FALSE, FALSE, cookie); | |
437 | (*fn->clk) (FALSE, TRUE, cookie); | |
438 | (*fn->clk) (TRUE, TRUE, cookie); | |
439 | ||
6d0f6bcf | 440 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK |
5d3207da WD |
441 | putc ('\n'); |
442 | #endif | |
443 | puts ("Done.\n"); | |
444 | } else { | |
445 | printf ("%s:%d: NULL Interface function table!\n", | |
446 | __FUNCTION__, __LINE__); | |
447 | } | |
448 | return ret_val; | |
449 | } | |
450 | ||
451 | /* | |
452 | * Relocate the addresses in the function table from FLASH (or ROM, | |
453 | * or whatever) to RAM. | |
454 | */ | |
455 | static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
456 | { | |
457 | ulong addr; | |
458 | int ret_val = FPGA_FAIL; | |
459 | Xilinx_Virtex2_Slave_SelectMap_fns *fn_r, *fn = | |
460 | (Xilinx_Virtex2_Slave_SelectMap_fns *) (desc->iface_fns); | |
461 | ||
462 | if (fn) { | |
463 | /* | |
464 | * Get the relocated table address | |
465 | */ | |
466 | addr = (ulong) fn + reloc_offset; | |
467 | fn_r = (Xilinx_Virtex2_Slave_SelectMap_fns *) addr; | |
468 | ||
469 | /* | |
470 | * Check to see if the table has already been relocated. If not, do | |
471 | * a sanity check to make sure there is a faithful copy of the | |
472 | * FLASH based function table in RAM, then adjust the table. | |
473 | */ | |
474 | if (!fn_r->relocated) { | |
475 | if (memcmp | |
476 | (fn_r, fn, sizeof (Xilinx_Virtex2_Slave_SelectMap_fns)) | |
477 | == 0) { | |
478 | desc->iface_fns = fn_r; | |
479 | } else { | |
480 | PRINTF ("%s:%d: Invalid function table at 0x%p\n", | |
481 | __FUNCTION__, __LINE__, fn_r); | |
482 | return FPGA_FAIL; | |
483 | } | |
484 | ||
485 | PRINTF ("%s:%d: Relocating descriptor at 0x%p\n", | |
486 | __FUNCTION__, __LINE__, desc); | |
487 | ||
488 | addr = (ulong) (fn->pre) + reloc_offset; | |
489 | fn_r->pre = (Xilinx_pre_fn) addr; | |
490 | addr = (ulong) (fn->pgm) + reloc_offset; | |
491 | fn_r->pgm = (Xilinx_pgm_fn) addr; | |
492 | addr = (ulong) (fn->init) + reloc_offset; | |
493 | fn_r->init = (Xilinx_init_fn) addr; | |
494 | addr = (ulong) (fn->done) + reloc_offset; | |
495 | fn_r->done = (Xilinx_done_fn) addr; | |
496 | addr = (ulong) (fn->err) + reloc_offset; | |
497 | fn_r->err = (Xilinx_err_fn) addr; | |
498 | addr = (ulong) (fn->clk) + reloc_offset; | |
499 | fn_r->clk = (Xilinx_clk_fn) addr; | |
500 | addr = (ulong) (fn->cs) + reloc_offset; | |
501 | fn_r->cs = (Xilinx_cs_fn) addr; | |
502 | addr = (ulong) (fn->wr) + reloc_offset; | |
503 | fn_r->wr = (Xilinx_wr_fn) addr; | |
504 | addr = (ulong) (fn->rdata) + reloc_offset; | |
505 | fn_r->rdata = (Xilinx_rdata_fn) addr; | |
506 | addr = (ulong) (fn->wdata) + reloc_offset; | |
507 | fn_r->wdata = (Xilinx_wdata_fn) addr; | |
508 | addr = (ulong) (fn->busy) + reloc_offset; | |
509 | fn_r->busy = (Xilinx_busy_fn) addr; | |
510 | addr = (ulong) (fn->abort) + reloc_offset; | |
511 | fn_r->abort = (Xilinx_abort_fn) addr; | |
512 | addr = (ulong) (fn->post) + reloc_offset; | |
513 | fn_r->post = (Xilinx_post_fn) addr; | |
514 | fn_r->relocated = TRUE; | |
515 | } else { | |
516 | printf ("%s:%d: Function table @0x%p has already been relocated\n", __FUNCTION__, __LINE__, fn_r); | |
517 | desc->iface_fns = fn_r; | |
518 | } | |
519 | ret_val = FPGA_SUCCESS; | |
520 | } else { | |
521 | printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
522 | } | |
523 | return ret_val; | |
524 | } | |
525 | ||
526 | static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
527 | { | |
528 | printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__); | |
529 | return FPGA_FAIL; | |
530 | } | |
531 | ||
532 | static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
533 | { | |
534 | printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__); | |
535 | return FPGA_FAIL; | |
536 | } | |
537 | ||
538 | static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
539 | { | |
540 | int ret_val = FPGA_FAIL; | |
541 | Xilinx_Virtex2_Slave_Serial_fns *fn = | |
542 | (Xilinx_Virtex2_Slave_Serial_fns *) (desc->iface_fns); | |
543 | ||
544 | if (fn) { | |
545 | printf ("%s:%d: Slave Serial Loading is unsupported\n", | |
546 | __FUNCTION__, __LINE__); | |
547 | } else { | |
548 | printf ("%s:%d: NULL Interface function table!\n", | |
549 | __FUNCTION__, __LINE__); | |
550 | } | |
551 | return ret_val; | |
552 | } | |
5d3207da WD |
553 | |
554 | /* vim: set ts=4 tw=78: */ |