]>
Commit | Line | Data |
---|---|---|
c609719b | 1 | /* |
c2642d14 | 2 | * (C) Copyright 2001-2004 |
c609719b WD |
3 | * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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> | |
25 | #include <asm/processor.h> | |
26 | #include <command.h> | |
c609719b WD |
27 | #include <malloc.h> |
28 | #include <pci.h> | |
3048bcbf | 29 | #include <asm/4xx_pci.h> |
c609719b | 30 | |
d69b100e SR |
31 | #include "pci405.h" |
32 | ||
d87080b7 | 33 | DECLARE_GLOBAL_DATA_PTR; |
d69b100e | 34 | |
c2642d14 SR |
35 | /* Prototypes */ |
36 | int gunzip(void *, int, unsigned char *, unsigned long *); | |
37 | int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);/*cmd_boot.c*/ | |
38 | unsigned long fpga_done_state(void); | |
39 | unsigned long fpga_init_state(void); | |
40 | ||
c609719b WD |
41 | #if 0 |
42 | #define FPGA_DEBUG | |
43 | #endif | |
44 | ||
c2642d14 SR |
45 | /* predefine these here */ |
46 | #define FPGA_DONE_STATE (fpga_done_state()) | |
47 | #define FPGA_INIT_STATE (fpga_init_state()) | |
48 | ||
c609719b WD |
49 | /* fpga configuration data - generated by bin2cc */ |
50 | const unsigned char fpgadata[] = | |
51 | { | |
52 | #include "fpgadata.c" | |
53 | }; | |
54 | ||
55 | /* | |
56 | * include common fpga code (for esd boards) | |
57 | */ | |
58 | #include "../common/fpga.c" | |
59 | ||
6d0f6bcf JCPV |
60 | #define FPGA_DONE_STATE_V11 (in32(GPIO0_IR) & CONFIG_SYS_FPGA_DONE) |
61 | #define FPGA_DONE_STATE_V12 (in32(GPIO0_IR) & CONFIG_SYS_FPGA_DONE_V12) | |
c609719b | 62 | |
6d0f6bcf JCPV |
63 | #define FPGA_INIT_STATE_V11 (in32(GPIO0_IR) & CONFIG_SYS_FPGA_INIT) |
64 | #define FPGA_INIT_STATE_V12 (in32(GPIO0_IR) & CONFIG_SYS_FPGA_INIT_V12) | |
c2642d14 SR |
65 | |
66 | ||
67 | int board_revision(void) | |
68 | { | |
69 | unsigned long cntrl0Reg; | |
70 | unsigned long value; | |
71 | ||
72 | /* | |
73 | * Get version of PCI405 board from GPIO's | |
74 | */ | |
75 | ||
76 | /* | |
77 | * Setup GPIO pins (CS2/GPIO11 and CS3/GPIO12 as GPIO) | |
78 | */ | |
79 | cntrl0Reg = mfdcr(cntrl0); | |
80 | mtdcr(cntrl0, cntrl0Reg | 0x03000000); | |
5315dfa9 SR |
81 | out32(GPIO0_ODR, in32(GPIO0_ODR) & ~0x00100200); |
82 | out32(GPIO0_TCR, in32(GPIO0_TCR) & ~0x00100200); | |
c2642d14 | 83 | udelay(1000); /* wait some time before reading input */ |
5315dfa9 | 84 | value = in32(GPIO0_IR) & 0x00100200; /* get config bits */ |
c2642d14 SR |
85 | |
86 | /* | |
87 | * Restore GPIO settings | |
88 | */ | |
89 | mtdcr(cntrl0, cntrl0Reg); | |
90 | ||
91 | switch (value) { | |
5315dfa9 SR |
92 | case 0x00100200: |
93 | /* CS2==1 && IRQ5==1 -> version 1.0 and 1.1 */ | |
c2642d14 | 94 | return 1; |
5315dfa9 SR |
95 | case 0x00000200: |
96 | /* CS2==0 && IRQ5==1 -> version 1.2 */ | |
c2642d14 | 97 | return 2; |
5315dfa9 SR |
98 | case 0x00000000: |
99 | /* CS2==0 && IRQ5==0 -> version 1.3 */ | |
100 | return 3; | |
c2642d14 SR |
101 | #if 0 /* not yet manufactured ! */ |
102 | case 0x00100000: | |
5315dfa9 | 103 | /* CS2==1 && IRQ5==0 -> version 1.4 */ |
c2642d14 SR |
104 | return 4; |
105 | #endif | |
106 | default: | |
107 | /* should not be reached! */ | |
108 | return 0; | |
109 | } | |
110 | } | |
111 | ||
112 | ||
113 | unsigned long fpga_done_state(void) | |
114 | { | |
c2642d14 SR |
115 | if (gd->board_type < 2) { |
116 | return FPGA_DONE_STATE_V11; | |
117 | } else { | |
118 | return FPGA_DONE_STATE_V12; | |
119 | } | |
120 | } | |
121 | ||
122 | ||
123 | unsigned long fpga_init_state(void) | |
124 | { | |
c2642d14 SR |
125 | if (gd->board_type < 2) { |
126 | return FPGA_INIT_STATE_V11; | |
127 | } else { | |
128 | return FPGA_INIT_STATE_V12; | |
129 | } | |
130 | } | |
c609719b WD |
131 | |
132 | ||
c837dcb1 | 133 | int board_early_init_f (void) |
c609719b WD |
134 | { |
135 | unsigned long cntrl0Reg; | |
136 | ||
c2642d14 SR |
137 | /* |
138 | * First pull fpga-prg pin low, to disable fpga logic (on version 1.2 board) | |
139 | */ | |
140 | out32(GPIO0_ODR, 0x00000000); /* no open drain pins */ | |
6d0f6bcf JCPV |
141 | out32(GPIO0_TCR, CONFIG_SYS_FPGA_PRG); /* setup for output */ |
142 | out32(GPIO0_OR, CONFIG_SYS_FPGA_PRG); /* set output pins to high */ | |
c2642d14 SR |
143 | out32(GPIO0_OR, 0); /* pull prg low */ |
144 | ||
c609719b WD |
145 | /* |
146 | * IRQ 0-15 405GP internally generated; active high; level sensitive | |
147 | * IRQ 16 405GP internally generated; active low; level sensitive | |
148 | * IRQ 17-24 RESERVED | |
149 | * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive | |
150 | * IRQ 26 (EXT IRQ 1) CAN1; active low; level sensitive | |
151 | * IRQ 27 (EXT IRQ 2) CAN2; active low; level sensitive | |
152 | * IRQ 28 (EXT IRQ 3) CAN3; active low; level sensitive | |
153 | * IRQ 29 (EXT IRQ 4) unused; active low; level sensitive | |
154 | * IRQ 30 (EXT IRQ 5) FPGA Timestamp; active low; level sensitive | |
155 | * IRQ 31 (EXT IRQ 6) PCI Reset; active low; level sensitive | |
156 | */ | |
157 | mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ | |
158 | mtdcr(uicer, 0x00000000); /* disable all ints */ | |
159 | mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/ | |
160 | mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */ | |
161 | mtdcr(uictr, 0x10000000); /* set int trigger levels */ | |
162 | mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/ | |
163 | mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ | |
164 | ||
165 | /* | |
166 | * Setup GPIO pins (IRQ4/GPIO21 as GPIO) | |
167 | */ | |
168 | cntrl0Reg = mfdcr(cntrl0); | |
169 | mtdcr(cntrl0, cntrl0Reg | 0x00008000); | |
170 | ||
c2642d14 SR |
171 | /* |
172 | * Setup GPIO pins (CS6+CS7 as GPIO) | |
173 | */ | |
174 | mtdcr(cntrl0, cntrl0Reg | 0x00300000); | |
175 | ||
1545ad35 SR |
176 | /* |
177 | * EBC Configuration Register: set ready timeout to 512 ebc-clks -> ca. 25 us | |
178 | */ | |
179 | mtebc (epcr, 0xa8400000); /* ebc always driven */ | |
180 | ||
c609719b WD |
181 | return 0; |
182 | } | |
183 | ||
184 | ||
185 | /* ------------------------------------------------------------------------- */ | |
186 | ||
187 | int misc_init_f (void) | |
188 | { | |
189 | return 0; /* dummy implementation */ | |
190 | } | |
191 | ||
192 | ||
193 | int misc_init_r (void) | |
194 | { | |
195 | unsigned char *dst; | |
196 | ulong len = sizeof(fpgadata); | |
197 | int status; | |
198 | int index; | |
199 | int i; | |
d69b100e SR |
200 | unsigned int *ptr; |
201 | unsigned int *magic; | |
c609719b WD |
202 | |
203 | /* | |
204 | * On PCI-405 the environment is saved in eeprom! | |
205 | * FPGA can be gzip compressed (malloc) and booted this late. | |
206 | */ | |
207 | ||
6d0f6bcf JCPV |
208 | dst = malloc(CONFIG_SYS_FPGA_MAX_SIZE); |
209 | if (gunzip (dst, CONFIG_SYS_FPGA_MAX_SIZE, (uchar *)fpgadata, &len) != 0) { | |
c609719b WD |
210 | printf ("GUNZIP ERROR - must RESET board to recover\n"); |
211 | do_reset (NULL, 0, 0, NULL); | |
212 | } | |
213 | ||
214 | status = fpga_boot(dst, len); | |
215 | if (status != 0) { | |
216 | printf("\nFPGA: Booting failed "); | |
217 | switch (status) { | |
218 | case ERROR_FPGA_PRG_INIT_LOW: | |
219 | printf("(Timeout: INIT not low after asserting PROGRAM*)\n "); | |
220 | break; | |
221 | case ERROR_FPGA_PRG_INIT_HIGH: | |
222 | printf("(Timeout: INIT not high after deasserting PROGRAM*)\n "); | |
223 | break; | |
224 | case ERROR_FPGA_PRG_DONE: | |
225 | printf("(Timeout: DONE not high after programming FPGA)\n "); | |
226 | break; | |
227 | } | |
228 | ||
229 | /* display infos on fpgaimage */ | |
230 | index = 15; | |
231 | for (i=0; i<4; i++) { | |
232 | len = dst[index]; | |
233 | printf("FPGA: %s\n", &(dst[index+1])); | |
234 | index += len+3; | |
235 | } | |
236 | putc ('\n'); | |
237 | /* delayed reboot */ | |
238 | for (i=20; i>0; i--) { | |
239 | printf("Rebooting in %2d seconds \r",i); | |
240 | for (index=0;index<1000;index++) | |
241 | udelay(1000); | |
242 | } | |
243 | putc ('\n'); | |
244 | do_reset(NULL, 0, 0, NULL); | |
245 | } | |
246 | ||
247 | puts("FPGA: "); | |
248 | ||
249 | /* display infos on fpgaimage */ | |
250 | index = 15; | |
251 | for (i=0; i<4; i++) { | |
252 | len = dst[index]; | |
253 | printf("%s ", &(dst[index+1])); | |
254 | index += len+3; | |
255 | } | |
256 | putc ('\n'); | |
257 | ||
258 | /* | |
d69b100e | 259 | * Reset FPGA via FPGA_DATA pin |
c609719b | 260 | */ |
d69b100e SR |
261 | SET_FPGA(FPGA_PRG | FPGA_CLK); |
262 | udelay(1000); /* wait 1ms */ | |
263 | SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); | |
264 | udelay(1000); /* wait 1ms */ | |
265 | ||
266 | /* | |
267 | * Check if magic for pci reconfig is written | |
268 | */ | |
269 | magic = (unsigned int *)0x00000004; | |
270 | if (*magic == PCI_RECONFIG_MAGIC) { | |
271 | /* | |
272 | * Rewrite pci config regs (only after soft-reset with magic set) | |
273 | */ | |
274 | ptr = (unsigned int *)PCI_REGS_ADDR; | |
77ddac94 | 275 | if (crc32(0, (uchar *)PCI_REGS_ADDR+4, PCI_REGS_LEN-4) == *ptr) { |
d69b100e SR |
276 | puts("Restoring PCI Configurations Regs!\n"); |
277 | ptr = (unsigned int *)PCI_REGS_ADDR + 1; | |
278 | for (i=0; i<0x40; i+=4) { | |
279 | pci_write_config_dword(PCIDEVID_405GP, i, *ptr++); | |
280 | } | |
281 | } | |
282 | mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ | |
1545ad35 | 283 | |
d69b100e | 284 | *magic = 0; /* clear pci reconfig magic again */ |
c609719b | 285 | } |
c609719b | 286 | |
c2642d14 SR |
287 | #if 1 /* test-only */ |
288 | /* | |
289 | * Decrease PLB latency timeout and reduce priority of the PCI bridge master | |
290 | */ | |
291 | #define PCI0_BRDGOPT1 0x4a | |
292 | pci_write_config_word(PCIDEVID_405GP, PCI0_BRDGOPT1, 0x3f20); | |
efe2a4d5 | 293 | /* pci_write_config_word(PCIDEVID_405GP, PCI0_BRDGOPT1, 0x3f60); */ |
c2642d14 SR |
294 | |
295 | #define plb0_acr 0x87 | |
296 | /* | |
297 | * Enable fairness and high bus utilization | |
298 | */ | |
299 | mtdcr(plb0_acr, 0x98000000); | |
300 | ||
301 | #if 0 /* test-only */ | |
302 | printf("CCR0=%08x\n", mfspr(ccr0)); /* test-only */ | |
efe2a4d5 | 303 | /* mtspr(ccr0, (mfspr(ccr0) & 0xff8fffff) | 0x00100000); */ |
c2642d14 SR |
304 | mtspr(ccr0, (mfspr(ccr0) & 0xff8fffff) | 0x00000000); |
305 | #endif | |
e2ffd59b | 306 | /* printf("CCR0=%08x\n", mfspr(ccr0)); */ /* test-only */ |
c2642d14 SR |
307 | #endif |
308 | ||
c609719b WD |
309 | free(dst); |
310 | return (0); | |
311 | } | |
312 | ||
313 | ||
314 | /* | |
315 | * Check Board Identity: | |
316 | */ | |
317 | ||
318 | int checkboard (void) | |
319 | { | |
77ddac94 | 320 | char str[64]; |
c609719b WD |
321 | int i = getenv_r ("serial#", str, sizeof(str)); |
322 | ||
323 | puts ("Board: "); | |
324 | ||
325 | if (i == -1) { | |
d69b100e | 326 | puts ("### No HW ID - assuming PCI405"); |
c609719b WD |
327 | } else { |
328 | puts (str); | |
329 | } | |
c2642d14 SR |
330 | |
331 | gd->board_type = board_revision(); | |
332 | printf(" (Rev 1.%ld", gd->board_type); | |
333 | ||
334 | if (gd->board_type >= 2) { | |
335 | unsigned long cntrl0Reg; | |
336 | unsigned long value; | |
337 | ||
338 | /* | |
339 | * Setup GPIO pins (Trace/GPIO1 to GPIO) | |
340 | */ | |
341 | cntrl0Reg = mfdcr(cntrl0); | |
342 | mtdcr(cntrl0, cntrl0Reg & ~0x08000000); | |
343 | out32(GPIO0_ODR, in32(GPIO0_ODR) & ~0x40000000); | |
344 | out32(GPIO0_TCR, in32(GPIO0_TCR) & ~0x40000000); | |
345 | udelay(1000); /* wait some time before reading input */ | |
346 | value = in32(GPIO0_IR) & 0x40000000; /* get config bits */ | |
347 | if (value) { | |
348 | puts(", 33 MHz PCI"); | |
349 | } else { | |
350 | puts(", 66 Mhz PCI"); | |
351 | } | |
352 | } | |
353 | ||
354 | puts(")\n"); | |
c609719b WD |
355 | |
356 | return 0; | |
357 | } | |
358 | ||
c609719b | 359 | /* ------------------------------------------------------------------------- */ |
5315dfa9 SR |
360 | int wpeeprom(int wp) |
361 | { | |
362 | int wp_state = wp; | |
363 | volatile unsigned char *uart1_mcr = (volatile unsigned char *)0xef600404; | |
364 | ||
365 | if (wp == 1) { | |
366 | *uart1_mcr &= ~0x02; | |
367 | } else if (wp == 0) { | |
368 | *uart1_mcr |= 0x02; | |
369 | } else { | |
370 | if (*uart1_mcr & 0x02) { | |
371 | wp_state = 0; | |
372 | } else { | |
373 | wp_state = 1; | |
374 | } | |
375 | } | |
376 | return wp_state; | |
377 | } | |
378 | ||
379 | int do_wpeeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
380 | { | |
381 | int wp = -1; | |
382 | if (argc >= 2) { | |
383 | if (argv[1][0] == '1') { | |
384 | wp = 1; | |
385 | } else if (argv[1][0] == '0') { | |
386 | wp = 0; | |
387 | } | |
388 | } | |
389 | ||
390 | wp = wpeeprom(wp); | |
391 | printf("EEPROM write protection %s\n", wp ? "ENABLED" : "DISABLED"); | |
392 | return 0; | |
393 | } | |
394 | ||
395 | U_BOOT_CMD( | |
396 | wpeeprom, 2, 1, do_wpeeprom, | |
397 | "wpeeprom - Check/Enable/Disable I2C EEPROM write protection\n", | |
398 | "wpeeprom\n" | |
399 | " - check I2C EEPROM write protection state\n" | |
400 | "wpeeprom 1\n" | |
401 | " - enable I2C EEPROM write protection\n" | |
402 | "wpeeprom 0\n" | |
403 | " - disable I2C EEPROM write protection\n" | |
404 | ); |