]>
Commit | Line | Data |
---|---|---|
16f21704 WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
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 | * | |
6dd652fa | 23 | * hacked for Hymod FPGA support by Murray.Jensen@csiro.au, 29-Jan-01 |
16f21704 WD |
24 | */ |
25 | ||
26 | #include <common.h> | |
27 | #include <command.h> | |
28 | #include <net.h> | |
16f21704 | 29 | #include <asm/iopin_8260.h> |
16f21704 | 30 | |
d87080b7 WD |
31 | DECLARE_GLOBAL_DATA_PTR; |
32 | ||
16f21704 WD |
33 | /*----------------------------------------------------------------------- |
34 | * Board Special Commands: FPGA load/store, EEPROM erase | |
35 | */ | |
36 | ||
c508a4ce | 37 | #if defined(CONFIG_CMD_BSP) |
16f21704 WD |
38 | |
39 | #define LOAD_SUCCESS 0 | |
40 | #define LOAD_FAIL_NOCONF 1 | |
41 | #define LOAD_FAIL_NOINIT 2 | |
42 | #define LOAD_FAIL_NODONE 3 | |
43 | ||
44 | #define STORE_SUCCESS 0 | |
45 | ||
46 | /* | |
47 | * Programming the Hymod FPGAs | |
48 | * | |
49 | * The 8260 io port config table is set up so that the INIT pin is | |
50 | * held Low (Open Drain output 0) - this will delay the automatic | |
51 | * Power-On config until INIT is released (by making it an input). | |
52 | * | |
53 | * If the FPGA has been programmed before, then the assertion of PROGRAM | |
54 | * will initiate configuration (i.e. it begins clearing the RAM). | |
55 | * | |
56 | * When the FPGA is ready to receive configuration data (either after | |
57 | * releasing INIT after Power-On, or after asserting PROGRAM), it will | |
58 | * pull INIT high. | |
59 | * | |
60 | * Notes from Paul Dunn: | |
61 | * | |
62 | * 1. program pin should be forced low for >= 300ns | |
63 | * (about 20 bus clock cycles minimum). | |
64 | * | |
65 | * 2. then wait for init to go high, which signals | |
66 | * that the FPGA has cleared its internal memory | |
67 | * and is ready to load | |
68 | * | |
69 | * 3. perform load writes of entire config file | |
70 | * | |
71 | * 4. wait for done to go high, which should be | |
72 | * within a few bus clock cycles. If done has not | |
73 | * gone high after reasonable period, then load | |
74 | * has not worked (wait several ms?) | |
75 | */ | |
76 | ||
6dd652fa WD |
77 | int |
78 | fpga_load (int mezz, uchar *addr, ulong size) | |
16f21704 | 79 | { |
16f21704 | 80 | hymod_conf_t *cp = &gd->bd->bi_hymod_conf; |
6dd652fa | 81 | xlx_info_t *fp; |
16f21704 WD |
82 | xlx_iopins_t *fpgaio; |
83 | volatile uchar *fpgabase; | |
84 | volatile uint cnt; | |
85 | uchar *eaddr = addr + size; | |
86 | int result; | |
87 | ||
6dd652fa WD |
88 | if (mezz) |
89 | fp = &cp->mezz.xlx[0]; | |
90 | else | |
91 | fp = &cp->main.xlx[0]; | |
92 | ||
93 | if (!fp->mmap.prog.exists) | |
94 | return (LOAD_FAIL_NOCONF); | |
95 | ||
96 | fpgabase = (uchar *)fp->mmap.prog.base; | |
97 | fpgaio = &fp->iopins; | |
16f21704 WD |
98 | |
99 | /* set enable HIGH if required */ | |
100 | if (fpgaio->enable_pin.flag) | |
101 | iopin_set_high (&fpgaio->enable_pin); | |
102 | ||
103 | /* ensure INIT is released (set it to be an input) */ | |
104 | iopin_set_in (&fpgaio->init_pin); | |
105 | ||
106 | /* toggle PROG Low then High (will already be Low after Power-On) */ | |
107 | iopin_set_low (&fpgaio->prog_pin); | |
6dd652fa | 108 | udelay (1); /* minimum 300ns - 1usec should do it */ |
16f21704 WD |
109 | iopin_set_high (&fpgaio->prog_pin); |
110 | ||
111 | /* wait for INIT High */ | |
112 | cnt = 0; | |
113 | while (!iopin_is_high (&fpgaio->init_pin)) | |
114 | if (++cnt == 10000000) { | |
115 | result = LOAD_FAIL_NOINIT; | |
116 | goto done; | |
117 | } | |
118 | ||
119 | /* write configuration data */ | |
120 | while (addr < eaddr) | |
121 | *fpgabase = *addr++; | |
122 | ||
123 | /* wait for DONE High */ | |
124 | cnt = 0; | |
125 | while (!iopin_is_high (&fpgaio->done_pin)) | |
126 | if (++cnt == 100000000) { | |
127 | result = LOAD_FAIL_NODONE; | |
128 | goto done; | |
129 | } | |
130 | ||
131 | /* success */ | |
132 | result = LOAD_SUCCESS; | |
133 | ||
134 | done: | |
135 | ||
136 | if (fpgaio->enable_pin.flag) | |
137 | iopin_set_low (&fpgaio->enable_pin); | |
138 | ||
139 | return (result); | |
140 | } | |
141 | ||
142 | /* ------------------------------------------------------------------------- */ | |
143 | int | |
144 | do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) | |
145 | { | |
146 | uchar *addr, *save_addr; | |
147 | ulong size; | |
148 | int mezz, arg, result; | |
149 | ||
150 | switch (argc) { | |
151 | ||
152 | case 0: | |
153 | case 1: | |
154 | break; | |
155 | ||
156 | case 2: | |
157 | if (strcmp (argv[1], "info") == 0) { | |
158 | printf ("\nHymod FPGA Info...\n"); | |
6dd652fa WD |
159 | printf ("\t\t\t\tAddress\t\tSize\n"); |
160 | printf ("\tMain Configuration:\t0x%08x\t%d\n", | |
161 | FPGA_MAIN_CFG_BASE, FPGA_MAIN_CFG_SIZE); | |
162 | printf ("\tMain Register:\t\t0x%08x\t%d\n", | |
163 | FPGA_MAIN_REG_BASE, FPGA_MAIN_REG_SIZE); | |
164 | printf ("\tMain Port:\t\t0x%08x\t%d\n", | |
165 | FPGA_MAIN_PORT_BASE, FPGA_MAIN_PORT_SIZE); | |
166 | printf ("\tMezz Configuration:\t0x%08x\t%d\n", | |
167 | FPGA_MEZZ_CFG_BASE, FPGA_MEZZ_CFG_SIZE); | |
16f21704 WD |
168 | return 0; |
169 | } | |
170 | break; | |
171 | ||
172 | case 3: | |
173 | if (strcmp (argv[1], "store") == 0) { | |
174 | addr = (uchar *) simple_strtoul (argv[2], NULL, 16); | |
175 | ||
176 | save_addr = addr; | |
177 | #if 0 | |
6dd652fa WD |
178 | /* fpga readback unimplemented */ |
179 | while (more readback data) | |
180 | *addr++ = *fpga; | |
181 | result = error ? STORE_FAIL_XXX : STORE_SUCCESS; | |
16f21704 | 182 | #else |
6dd652fa | 183 | result = STORE_SUCCESS; |
16f21704 | 184 | #endif |
6dd652fa | 185 | |
16f21704 | 186 | if (result == STORE_SUCCESS) { |
6dd652fa WD |
187 | printf ("SUCCEEDED (%d bytes)\n", |
188 | addr - save_addr); | |
16f21704 WD |
189 | return 0; |
190 | } else | |
6dd652fa WD |
191 | printf ("FAILED (%d bytes)\n", |
192 | addr - save_addr); | |
16f21704 WD |
193 | return 1; |
194 | } | |
195 | break; | |
196 | ||
197 | case 4: | |
198 | if (strcmp (argv[1], "tftp") == 0) { | |
199 | copy_filename (BootFile, argv[2], sizeof (BootFile)); | |
200 | load_addr = simple_strtoul (argv[3], NULL, 16); | |
6dd652fa | 201 | NetBootFileXferSize = 0; |
16f21704 | 202 | |
eb9401e3 | 203 | if (NetLoop (TFTP) <= 0) { |
6dd652fa WD |
204 | printf ("tftp transfer failed - aborting " |
205 | "fgpa load\n"); | |
16f21704 WD |
206 | return 1; |
207 | } | |
208 | ||
209 | if (NetBootFileXferSize == 0) { | |
6dd652fa WD |
210 | printf ("can't determine file size - " |
211 | "aborting fpga load\n"); | |
16f21704 WD |
212 | return 1; |
213 | } | |
214 | ||
6dd652fa WD |
215 | printf ("File transfer succeeded - " |
216 | "beginning fpga load..."); | |
16f21704 WD |
217 | |
218 | result = fpga_load (0, (uchar *) load_addr, | |
6dd652fa WD |
219 | NetBootFileXferSize); |
220 | ||
16f21704 WD |
221 | if (result == LOAD_SUCCESS) { |
222 | printf ("SUCCEEDED\n"); | |
223 | return 0; | |
6dd652fa WD |
224 | } else if (result == LOAD_FAIL_NOCONF) |
225 | printf ("FAILED (no CONF)\n"); | |
226 | else if (result == LOAD_FAIL_NOINIT) | |
16f21704 WD |
227 | printf ("FAILED (no INIT)\n"); |
228 | else | |
229 | printf ("FAILED (no DONE)\n"); | |
230 | return 1; | |
231 | ||
232 | } | |
233 | /* fall through ... */ | |
234 | ||
235 | case 5: | |
236 | if (strcmp (argv[1], "load") == 0) { | |
237 | if (argc == 5) { | |
238 | if (strcmp (argv[2], "main") == 0) | |
239 | mezz = 0; | |
240 | else if (strcmp (argv[2], "mezz") == 0) | |
241 | mezz = 1; | |
242 | else { | |
6dd652fa WD |
243 | printf ("FPGA type must be either " |
244 | "`main' or `mezz'\n"); | |
16f21704 WD |
245 | return 1; |
246 | } | |
247 | arg = 3; | |
248 | } else { | |
249 | mezz = 0; | |
250 | arg = 2; | |
251 | } | |
6dd652fa | 252 | |
16f21704 WD |
253 | addr = (uchar *) simple_strtoul (argv[arg++], NULL, 16); |
254 | size = (ulong) simple_strtoul (argv[arg], NULL, 16); | |
255 | ||
256 | result = fpga_load (mezz, addr, size); | |
6dd652fa | 257 | |
16f21704 WD |
258 | if (result == LOAD_SUCCESS) { |
259 | printf ("SUCCEEDED\n"); | |
260 | return 0; | |
6dd652fa WD |
261 | } else if (result == LOAD_FAIL_NOCONF) |
262 | printf ("FAILED (no CONF)\n"); | |
263 | else if (result == LOAD_FAIL_NOINIT) | |
16f21704 WD |
264 | printf ("FAILED (no INIT)\n"); |
265 | else | |
266 | printf ("FAILED (no DONE)\n"); | |
267 | return 1; | |
268 | } | |
269 | break; | |
270 | ||
271 | default: | |
272 | break; | |
273 | } | |
274 | ||
62c3ae7c | 275 | cmd_usage(cmdtp); |
16f21704 WD |
276 | return 1; |
277 | } | |
0d498393 WD |
278 | U_BOOT_CMD( |
279 | fpga, 6, 1, do_fpga, | |
8bde7f77 WD |
280 | "fpga - FPGA sub-system\n", |
281 | "load [type] addr size\n" | |
282 | " - write the configuration data at memory address `addr',\n" | |
283 | " size `size' bytes, into the FPGA of type `type' (either\n" | |
284 | " `main' or `mezz', default `main'). e.g.\n" | |
285 | " `fpga load 100000 7d8f'\n" | |
286 | " loads the main FPGA with config data at address 100000\n" | |
287 | " HEX, size 7d8f HEX (32143 DEC) bytes\n" | |
288 | "fpga tftp file addr\n" | |
289 | " - transfers `file' from the tftp server into memory at\n" | |
290 | " address `addr', then writes the entire file contents\n" | |
291 | " into the main FPGA\n" | |
292 | "fpga store addr\n" | |
293 | " - read configuration data from the main FPGA (the mezz\n" | |
294 | " FPGA is write-only), into address `addr'. There must be\n" | |
295 | " enough memory available at `addr' to hold all the config\n" | |
296 | " data - the size of which is determined by VC:???\n" | |
297 | "fpga info\n" | |
298 | " - print information about the Hymod FPGA, namely the\n" | |
299 | " memory addresses at which the four FPGA local bus\n" | |
300 | " address spaces appear in the physical address space\n" | |
301 | ); | |
16f21704 WD |
302 | /* ------------------------------------------------------------------------- */ |
303 | int | |
304 | do_eecl (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) | |
305 | { | |
306 | uchar data[HYMOD_EEPROM_SIZE]; | |
6d0f6bcf | 307 | uint addr = CONFIG_SYS_I2C_EEPROM_ADDR; |
16f21704 WD |
308 | |
309 | switch (argc) { | |
310 | ||
311 | case 1: | |
6dd652fa | 312 | addr |= HYMOD_EEOFF_MAIN; |
16f21704 WD |
313 | break; |
314 | ||
315 | case 2: | |
316 | if (strcmp (argv[1], "main") == 0) { | |
6dd652fa | 317 | addr |= HYMOD_EEOFF_MAIN; |
16f21704 WD |
318 | break; |
319 | } | |
320 | if (strcmp (argv[1], "mezz") == 0) { | |
6dd652fa | 321 | addr |= HYMOD_EEOFF_MEZZ; |
16f21704 WD |
322 | break; |
323 | } | |
324 | /* fall through ... */ | |
325 | ||
326 | default: | |
62c3ae7c | 327 | cmd_usage(cmdtp); |
16f21704 WD |
328 | return 1; |
329 | } | |
330 | ||
331 | memset (data, 0, HYMOD_EEPROM_SIZE); | |
6dd652fa WD |
332 | |
333 | eeprom_write (addr, 0, data, HYMOD_EEPROM_SIZE); | |
334 | ||
335 | return 0; | |
336 | } | |
0d498393 WD |
337 | U_BOOT_CMD( |
338 | eeclear, 1, 0, do_eecl, | |
8bde7f77 WD |
339 | "eeclear - Clear the eeprom on a Hymod board \n", |
340 | "[type]\n" | |
341 | " - write zeroes into the EEPROM on the board of type `type'\n" | |
342 | " (`type' is either `main' or `mezz' - default `main')\n" | |
343 | " Note: the EEPROM write enable jumper must be installed\n" | |
344 | ); | |
6dd652fa WD |
345 | |
346 | /* ------------------------------------------------------------------------- */ | |
347 | ||
6dd652fa WD |
348 | int |
349 | do_htest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
350 | { | |
351 | #if 0 | |
352 | int rc; | |
353 | #endif | |
354 | #ifdef CONFIG_ETHER_LOOPBACK_TEST | |
355 | extern void eth_loopback_test (void); | |
356 | #endif /* CONFIG_ETHER_LOOPBACK_TEST */ | |
357 | ||
358 | printf ("HYMOD tests - ensure loopbacks etc. are connected\n\n"); | |
359 | ||
360 | #if 0 | |
361 | /* Load FPGA with test program */ | |
362 | ||
363 | printf ("Loading test FPGA program ..."); | |
364 | ||
365 | rc = fpga_load (0, test_bitfile, sizeof (test_bitfile)); | |
366 | ||
367 | switch (rc) { | |
368 | ||
369 | case LOAD_SUCCESS: | |
370 | printf (" SUCCEEDED\n"); | |
371 | break; | |
372 | ||
373 | case LOAD_FAIL_NOCONF: | |
374 | printf (" FAILED (no configuration space defined)\n"); | |
375 | return 1; | |
376 | ||
377 | case LOAD_FAIL_NOINIT: | |
378 | printf (" FAILED (timeout - no INIT signal seen)\n"); | |
379 | return 1; | |
380 | ||
381 | case LOAD_FAIL_NODONE: | |
382 | printf (" FAILED (timeout - no DONE signal seen)\n"); | |
383 | return 1; | |
384 | ||
385 | default: | |
386 | printf (" FAILED (unknown return code from fpga_load\n"); | |
387 | return 1; | |
16f21704 WD |
388 | } |
389 | ||
6dd652fa WD |
390 | /* run Local Bus <=> Xilinx tests */ |
391 | ||
392 | /* tell Xilinx to run ZBT Ram, High Speed serial and Mezzanine tests */ | |
393 | ||
394 | /* run SDRAM test */ | |
395 | #endif | |
396 | ||
397 | #ifdef CONFIG_ETHER_LOOPBACK_TEST | |
398 | /* run Ethernet test */ | |
399 | eth_loopback_test (); | |
400 | #endif /* CONFIG_ETHER_LOOPBACK_TEST */ | |
401 | ||
402 | return 0; | |
16f21704 WD |
403 | } |
404 | ||
77a31854 | 405 | #endif |