]>
Commit | Line | Data |
---|---|---|
1 | // SPDX-License-Identifier: GPL-2.0+ | |
2 | /* | |
3 | * (C) Copyright 2002 | |
4 | * Rich Ireland, Enterasys Networks, [email protected]. | |
5 | */ | |
6 | ||
7 | #include <common.h> /* core U-Boot definitions */ | |
8 | #include <spartan2.h> /* Spartan-II device family */ | |
9 | ||
10 | /* Define FPGA_DEBUG to get debug printf's */ | |
11 | #ifdef FPGA_DEBUG | |
12 | #define PRINTF(fmt,args...) printf (fmt ,##args) | |
13 | #else | |
14 | #define PRINTF(fmt,args...) | |
15 | #endif | |
16 | ||
17 | #undef CONFIG_SYS_FPGA_CHECK_BUSY | |
18 | #undef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
19 | ||
20 | /* Note: The assumption is that we cannot possibly run fast enough to | |
21 | * overrun the device (the Slave Parallel mode can free run at 50MHz). | |
22 | * If there is a need to operate slower, define CONFIG_FPGA_DELAY in | |
23 | * the board config file to slow things down. | |
24 | */ | |
25 | #ifndef CONFIG_FPGA_DELAY | |
26 | #define CONFIG_FPGA_DELAY() | |
27 | #endif | |
28 | ||
29 | #ifndef CONFIG_SYS_FPGA_WAIT | |
30 | #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */ | |
31 | #endif | |
32 | ||
33 | static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize); | |
34 | static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize); | |
35 | /* static int spartan2_sp_info(xilinx_desc *desc ); */ | |
36 | ||
37 | static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize); | |
38 | static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize); | |
39 | /* static int spartan2_ss_info(xilinx_desc *desc ); */ | |
40 | ||
41 | /* ------------------------------------------------------------------------- */ | |
42 | /* Spartan-II Generic Implementation */ | |
43 | static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize, | |
44 | bitstream_type bstype) | |
45 | { | |
46 | int ret_val = FPGA_FAIL; | |
47 | ||
48 | switch (desc->iface) { | |
49 | case slave_serial: | |
50 | PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__); | |
51 | ret_val = spartan2_ss_load(desc, buf, bsize); | |
52 | break; | |
53 | ||
54 | case slave_parallel: | |
55 | PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__); | |
56 | ret_val = spartan2_sp_load(desc, buf, bsize); | |
57 | break; | |
58 | ||
59 | default: | |
60 | printf ("%s: Unsupported interface type, %d\n", | |
61 | __FUNCTION__, desc->iface); | |
62 | } | |
63 | ||
64 | return ret_val; | |
65 | } | |
66 | ||
67 | static int spartan2_dump(xilinx_desc *desc, const void *buf, size_t bsize) | |
68 | { | |
69 | int ret_val = FPGA_FAIL; | |
70 | ||
71 | switch (desc->iface) { | |
72 | case slave_serial: | |
73 | PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__); | |
74 | ret_val = spartan2_ss_dump(desc, buf, bsize); | |
75 | break; | |
76 | ||
77 | case slave_parallel: | |
78 | PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__); | |
79 | ret_val = spartan2_sp_dump(desc, buf, bsize); | |
80 | break; | |
81 | ||
82 | default: | |
83 | printf ("%s: Unsupported interface type, %d\n", | |
84 | __FUNCTION__, desc->iface); | |
85 | } | |
86 | ||
87 | return ret_val; | |
88 | } | |
89 | ||
90 | static int spartan2_info(xilinx_desc *desc) | |
91 | { | |
92 | return FPGA_SUCCESS; | |
93 | } | |
94 | ||
95 | ||
96 | /* ------------------------------------------------------------------------- */ | |
97 | /* Spartan-II Slave Parallel Generic Implementation */ | |
98 | ||
99 | static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize) | |
100 | { | |
101 | int ret_val = FPGA_FAIL; /* assume the worst */ | |
102 | xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns; | |
103 | ||
104 | PRINTF ("%s: start with interface functions @ 0x%p\n", | |
105 | __FUNCTION__, fn); | |
106 | ||
107 | if (fn) { | |
108 | size_t bytecount = 0; | |
109 | unsigned char *data = (unsigned char *) buf; | |
110 | int cookie = desc->cookie; /* make a local copy */ | |
111 | unsigned long ts; /* timestamp */ | |
112 | ||
113 | PRINTF ("%s: Function Table:\n" | |
114 | "ptr:\t0x%p\n" | |
115 | "struct: 0x%p\n" | |
116 | "pre: 0x%p\n" | |
117 | "pgm:\t0x%p\n" | |
118 | "init:\t0x%p\n" | |
119 | "err:\t0x%p\n" | |
120 | "clk:\t0x%p\n" | |
121 | "cs:\t0x%p\n" | |
122 | "wr:\t0x%p\n" | |
123 | "read data:\t0x%p\n" | |
124 | "write data:\t0x%p\n" | |
125 | "busy:\t0x%p\n" | |
126 | "abort:\t0x%p\n", | |
127 | "post:\t0x%p\n\n", | |
128 | __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err, | |
129 | fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy, | |
130 | fn->abort, fn->post); | |
131 | ||
132 | /* | |
133 | * This code is designed to emulate the "Express Style" | |
134 | * Continuous Data Loading in Slave Parallel Mode for | |
135 | * the Spartan-II Family. | |
136 | */ | |
137 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
138 | printf ("Loading FPGA Device %d...\n", cookie); | |
139 | #endif | |
140 | /* | |
141 | * Run the pre configuration function if there is one. | |
142 | */ | |
143 | if (*fn->pre) { | |
144 | (*fn->pre) (cookie); | |
145 | } | |
146 | ||
147 | /* Establish the initial state */ | |
148 | (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ | |
149 | ||
150 | /* Get ready for the burn */ | |
151 | CONFIG_FPGA_DELAY (); | |
152 | (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ | |
153 | ||
154 | ts = get_timer (0); /* get current time */ | |
155 | /* Now wait for INIT and BUSY to go high */ | |
156 | do { | |
157 | CONFIG_FPGA_DELAY (); | |
158 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ | |
159 | puts ("** Timeout waiting for INIT to clear.\n"); | |
160 | (*fn->abort) (cookie); /* abort the burn */ | |
161 | return FPGA_FAIL; | |
162 | } | |
163 | } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); | |
164 | ||
165 | (*fn->wr) (true, true, cookie); /* Assert write, commit */ | |
166 | (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ | |
167 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
168 | ||
169 | /* Load the data */ | |
170 | while (bytecount < bsize) { | |
171 | /* XXX - do we check for an Ctrl-C press in here ??? */ | |
172 | /* XXX - Check the error bit? */ | |
173 | ||
174 | (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */ | |
175 | CONFIG_FPGA_DELAY (); | |
176 | (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ | |
177 | CONFIG_FPGA_DELAY (); | |
178 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
179 | ||
180 | #ifdef CONFIG_SYS_FPGA_CHECK_BUSY | |
181 | ts = get_timer (0); /* get current time */ | |
182 | while ((*fn->busy) (cookie)) { | |
183 | /* XXX - we should have a check in here somewhere to | |
184 | * make sure we aren't busy forever... */ | |
185 | ||
186 | CONFIG_FPGA_DELAY (); | |
187 | (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ | |
188 | CONFIG_FPGA_DELAY (); | |
189 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
190 | ||
191 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ | |
192 | puts ("** Timeout waiting for BUSY to clear.\n"); | |
193 | (*fn->abort) (cookie); /* abort the burn */ | |
194 | return FPGA_FAIL; | |
195 | } | |
196 | } | |
197 | #endif | |
198 | ||
199 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
200 | if (bytecount % (bsize / 40) == 0) | |
201 | putc ('.'); /* let them know we are alive */ | |
202 | #endif | |
203 | } | |
204 | ||
205 | CONFIG_FPGA_DELAY (); | |
206 | (*fn->cs) (false, true, cookie); /* Deassert the chip select */ | |
207 | (*fn->wr) (false, true, cookie); /* Deassert the write pin */ | |
208 | ||
209 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
210 | putc ('\n'); /* terminate the dotted line */ | |
211 | #endif | |
212 | ||
213 | /* now check for done signal */ | |
214 | ts = get_timer (0); /* get current time */ | |
215 | ret_val = FPGA_SUCCESS; | |
216 | while ((*fn->done) (cookie) == FPGA_FAIL) { | |
217 | ||
218 | CONFIG_FPGA_DELAY (); | |
219 | (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ | |
220 | CONFIG_FPGA_DELAY (); | |
221 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
222 | ||
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 | /* | |
232 | * Run the post configuration function if there is one. | |
233 | */ | |
234 | if (*fn->post) | |
235 | (*fn->post) (cookie); | |
236 | ||
237 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
238 | if (ret_val == FPGA_SUCCESS) | |
239 | puts ("Done.\n"); | |
240 | else | |
241 | puts ("Fail.\n"); | |
242 | #endif | |
243 | ||
244 | } else { | |
245 | printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
246 | } | |
247 | ||
248 | return ret_val; | |
249 | } | |
250 | ||
251 | static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize) | |
252 | { | |
253 | int ret_val = FPGA_FAIL; /* assume the worst */ | |
254 | xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns; | |
255 | ||
256 | if (fn) { | |
257 | unsigned char *data = (unsigned char *) buf; | |
258 | size_t bytecount = 0; | |
259 | int cookie = desc->cookie; /* make a local copy */ | |
260 | ||
261 | printf ("Starting Dump of FPGA Device %d...\n", cookie); | |
262 | ||
263 | (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ | |
264 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
265 | ||
266 | /* dump the data */ | |
267 | while (bytecount < bsize) { | |
268 | /* XXX - do we check for an Ctrl-C press in here ??? */ | |
269 | ||
270 | (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ | |
271 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
272 | (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */ | |
273 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
274 | if (bytecount % (bsize / 40) == 0) | |
275 | putc ('.'); /* let them know we are alive */ | |
276 | #endif | |
277 | } | |
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 | ||
283 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
284 | putc ('\n'); /* terminate the dotted line */ | |
285 | #endif | |
286 | puts ("Done.\n"); | |
287 | ||
288 | /* XXX - checksum the data? */ | |
289 | } else { | |
290 | printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
291 | } | |
292 | ||
293 | return ret_val; | |
294 | } | |
295 | ||
296 | ||
297 | /* ------------------------------------------------------------------------- */ | |
298 | ||
299 | static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize) | |
300 | { | |
301 | int ret_val = FPGA_FAIL; /* assume the worst */ | |
302 | xilinx_spartan2_slave_serial_fns *fn = desc->iface_fns; | |
303 | int i; | |
304 | unsigned char val; | |
305 | ||
306 | PRINTF ("%s: start with interface functions @ 0x%p\n", | |
307 | __FUNCTION__, fn); | |
308 | ||
309 | if (fn) { | |
310 | size_t bytecount = 0; | |
311 | unsigned char *data = (unsigned char *) buf; | |
312 | int cookie = desc->cookie; /* make a local copy */ | |
313 | unsigned long ts; /* timestamp */ | |
314 | ||
315 | PRINTF ("%s: Function Table:\n" | |
316 | "ptr:\t0x%p\n" | |
317 | "struct: 0x%p\n" | |
318 | "pgm:\t0x%p\n" | |
319 | "init:\t0x%p\n" | |
320 | "clk:\t0x%p\n" | |
321 | "wr:\t0x%p\n" | |
322 | "done:\t0x%p\n\n", | |
323 | __FUNCTION__, &fn, fn, fn->pgm, fn->init, | |
324 | fn->clk, fn->wr, fn->done); | |
325 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
326 | printf ("Loading FPGA Device %d...\n", cookie); | |
327 | #endif | |
328 | ||
329 | /* | |
330 | * Run the pre configuration function if there is one. | |
331 | */ | |
332 | if (*fn->pre) { | |
333 | (*fn->pre) (cookie); | |
334 | } | |
335 | ||
336 | /* Establish the initial state */ | |
337 | (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ | |
338 | ||
339 | /* Wait for INIT state (init low) */ | |
340 | ts = get_timer (0); /* get current time */ | |
341 | do { | |
342 | CONFIG_FPGA_DELAY (); | |
343 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ | |
344 | puts ("** Timeout waiting for INIT to start.\n"); | |
345 | return FPGA_FAIL; | |
346 | } | |
347 | } while (!(*fn->init) (cookie)); | |
348 | ||
349 | /* Get ready for the burn */ | |
350 | CONFIG_FPGA_DELAY (); | |
351 | (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ | |
352 | ||
353 | ts = get_timer (0); /* get current time */ | |
354 | /* Now wait for INIT to go high */ | |
355 | do { | |
356 | CONFIG_FPGA_DELAY (); | |
357 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ | |
358 | puts ("** Timeout waiting for INIT to clear.\n"); | |
359 | return FPGA_FAIL; | |
360 | } | |
361 | } while ((*fn->init) (cookie)); | |
362 | ||
363 | /* Load the data */ | |
364 | while (bytecount < bsize) { | |
365 | ||
366 | /* Xilinx detects an error if INIT goes low (active) | |
367 | while DONE is low (inactive) */ | |
368 | if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { | |
369 | puts ("** CRC error during FPGA load.\n"); | |
370 | return (FPGA_FAIL); | |
371 | } | |
372 | val = data [bytecount ++]; | |
373 | i = 8; | |
374 | do { | |
375 | /* Deassert the clock */ | |
376 | (*fn->clk) (false, true, cookie); | |
377 | CONFIG_FPGA_DELAY (); | |
378 | /* Write data */ | |
379 | (*fn->wr) ((val & 0x80), true, cookie); | |
380 | CONFIG_FPGA_DELAY (); | |
381 | /* Assert the clock */ | |
382 | (*fn->clk) (true, true, cookie); | |
383 | CONFIG_FPGA_DELAY (); | |
384 | val <<= 1; | |
385 | i --; | |
386 | } while (i > 0); | |
387 | ||
388 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
389 | if (bytecount % (bsize / 40) == 0) | |
390 | putc ('.'); /* let them know we are alive */ | |
391 | #endif | |
392 | } | |
393 | ||
394 | CONFIG_FPGA_DELAY (); | |
395 | ||
396 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
397 | putc ('\n'); /* terminate the dotted line */ | |
398 | #endif | |
399 | ||
400 | /* now check for done signal */ | |
401 | ts = get_timer (0); /* get current time */ | |
402 | ret_val = FPGA_SUCCESS; | |
403 | (*fn->wr) (true, true, cookie); | |
404 | ||
405 | while (! (*fn->done) (cookie)) { | |
406 | ||
407 | CONFIG_FPGA_DELAY (); | |
408 | (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ | |
409 | CONFIG_FPGA_DELAY (); | |
410 | (*fn->clk) (true, true, cookie); /* Assert the clock pin */ | |
411 | ||
412 | putc ('*'); | |
413 | ||
414 | if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ | |
415 | puts ("** Timeout waiting for DONE to clear.\n"); | |
416 | ret_val = FPGA_FAIL; | |
417 | break; | |
418 | } | |
419 | } | |
420 | putc ('\n'); /* terminate the dotted line */ | |
421 | ||
422 | /* | |
423 | * Run the post configuration function if there is one. | |
424 | */ | |
425 | if (*fn->post) | |
426 | (*fn->post) (cookie); | |
427 | ||
428 | #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK | |
429 | if (ret_val == FPGA_SUCCESS) | |
430 | puts ("Done.\n"); | |
431 | else | |
432 | puts ("Fail.\n"); | |
433 | #endif | |
434 | ||
435 | } else { | |
436 | printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
437 | } | |
438 | ||
439 | return ret_val; | |
440 | } | |
441 | ||
442 | static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize) | |
443 | { | |
444 | /* Readback is only available through the Slave Parallel and */ | |
445 | /* boundary-scan interfaces. */ | |
446 | printf ("%s: Slave Serial Dumping is unavailable\n", | |
447 | __FUNCTION__); | |
448 | return FPGA_FAIL; | |
449 | } | |
450 | ||
451 | struct xilinx_fpga_op spartan2_op = { | |
452 | .load = spartan2_load, | |
453 | .dump = spartan2_dump, | |
454 | .info = spartan2_info, | |
455 | }; |