blob: 5a6a27c82503c4d4200f6e4488f4d47d8f910dc3 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
stroese6f4474e2003-03-20 15:31:19 +00002 * (C) Copyright 2001-2003
wdenkc6097192002-11-03 00:24:07 +00003 * 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>
27#include <cmd_boot.h>
28#include <malloc.h>
29
30/* ------------------------------------------------------------------------- */
31
32#if 0
33#define FPGA_DEBUG
34#endif
35
36/* fpga configuration data - generated by bin2cc */
37const unsigned char fpgadata[] =
38{
39#ifdef CONFIG_CPCI405_VER2
stroesed4629c82003-05-23 11:30:39 +000040# ifdef CONFIG_CPCI405AB
41# include "fpgadata_cpci405ab.c"
42# else
43# include "fpgadata_cpci4052.c"
44# endif
wdenkc6097192002-11-03 00:24:07 +000045#else
46# include "fpgadata_cpci405.c"
47#endif
48};
49
50/*
51 * include common fpga code (for esd boards)
52 */
53#include "../common/fpga.c"
54
55
56/* Prototypes */
stroese6f4474e2003-03-20 15:31:19 +000057int cpci405_version(void);
wdenkc6097192002-11-03 00:24:07 +000058int gunzip(void *, int, unsigned char *, int *);
59
60
61int board_pre_init (void)
62{
63#ifndef CONFIG_CPCI405_VER2
64 int index, len, i;
65 int status;
66#endif
67
68#ifdef FPGA_DEBUG
69 DECLARE_GLOBAL_DATA_PTR;
70
71 /* set up serial port with default baudrate */
72 (void) get_clocks ();
73 gd->baudrate = CONFIG_BAUDRATE;
74 serial_init ();
75 console_init_f();
76#endif
77
78 /*
79 * First pull fpga-prg pin low, to disable fpga logic (on version 2 board)
80 */
stroesed4629c82003-05-23 11:30:39 +000081 out32(GPIO0_ODR, 0x00000000); /* no open drain pins */
82 out32(GPIO0_TCR, CFG_FPGA_PRG); /* setup for output */
83 out32(GPIO0_OR, CFG_FPGA_PRG); /* set output pins to high */
84 out32(GPIO0_OR, 0); /* pull prg low */
wdenkc6097192002-11-03 00:24:07 +000085
86 /*
87 * Boot onboard FPGA
88 */
89#ifndef CONFIG_CPCI405_VER2
stroese6f4474e2003-03-20 15:31:19 +000090 if (cpci405_version() == 1) {
wdenkc6097192002-11-03 00:24:07 +000091 status = fpga_boot((unsigned char *)fpgadata, sizeof(fpgadata));
92 if (status != 0) {
93 /* booting FPGA failed */
94#ifndef FPGA_DEBUG
95 DECLARE_GLOBAL_DATA_PTR;
96
97 /* set up serial port with default baudrate */
98 (void) get_clocks ();
99 gd->baudrate = CONFIG_BAUDRATE;
100 serial_init ();
101 console_init_f();
102#endif
103 printf("\nFPGA: Booting failed ");
104 switch (status) {
105 case ERROR_FPGA_PRG_INIT_LOW:
106 printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
107 break;
108 case ERROR_FPGA_PRG_INIT_HIGH:
109 printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
110 break;
111 case ERROR_FPGA_PRG_DONE:
112 printf("(Timeout: DONE not high after programming FPGA)\n ");
113 break;
114 }
115
116 /* display infos on fpgaimage */
117 index = 15;
118 for (i=0; i<4; i++) {
119 len = fpgadata[index];
120 printf("FPGA: %s\n", &(fpgadata[index+1]));
121 index += len+3;
122 }
123 putc ('\n');
124 /* delayed reboot */
125 for (i=20; i>0; i--) {
126 printf("Rebooting in %2d seconds \r",i);
127 for (index=0;index<1000;index++)
128 udelay(1000);
129 }
130 putc ('\n');
131 do_reset(NULL, 0, 0, NULL);
132 }
133 }
134#endif /* !CONFIG_CPCI405_VER2 */
135
136 /*
137 * IRQ 0-15 405GP internally generated; active high; level sensitive
138 * IRQ 16 405GP internally generated; active low; level sensitive
139 * IRQ 17-24 RESERVED
140 * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive
141 * IRQ 26 (EXT IRQ 1) CAN1 (+FPGA on CPCI4052) ; active low; level sensitive
142 * IRQ 27 (EXT IRQ 2) PCI SLOT 0; active low; level sensitive
143 * IRQ 28 (EXT IRQ 3) PCI SLOT 1; active low; level sensitive
144 * IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive
145 * IRQ 30 (EXT IRQ 5) PCI SLOT 3; active low; level sensitive
146 * IRQ 31 (EXT IRQ 6) COMPACT FLASH; active high; level sensitive
147 */
148 mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
149 mtdcr(uicer, 0x00000000); /* disable all ints */
150 mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/
stroese6f4474e2003-03-20 15:31:19 +0000151 if (cpci405_version() == 3) {
152 mtdcr(uicpr, 0xFFFFFF99); /* set int polarities */
153 } else {
154 mtdcr(uicpr, 0xFFFFFF81); /* set int polarities */
155 }
wdenkc6097192002-11-03 00:24:07 +0000156 mtdcr(uictr, 0x10000000); /* set int trigger levels */
157 mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/
158 mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */
159
160 return 0;
161}
162
163
164/* ------------------------------------------------------------------------- */
165
166int ctermm2(void)
167{
168#ifdef CONFIG_CPCI405_VER2
169 return 0; /* no, board is cpci405 */
170#else
171 if ((*(unsigned char *)0xf0000400 == 0x00) &&
172 (*(unsigned char *)0xf0000401 == 0x01))
173 return 0; /* no, board is cpci405 */
174 else
175 return -1; /* yes, board is cterm-m2 */
176#endif
177}
178
179
180int cpci405_host(void)
181{
182 if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
183 return -1; /* yes, board is cpci405 host */
184 else
185 return 0; /* no, board is cpci405 adapter */
186}
187
188
stroese6f4474e2003-03-20 15:31:19 +0000189int cpci405_version(void)
wdenkc6097192002-11-03 00:24:07 +0000190{
191 unsigned long cntrl0Reg;
192 unsigned long value;
193
194 /*
stroese6f4474e2003-03-20 15:31:19 +0000195 * Setup GPIO pins (CS2/GPIO11 and CS3/GPIO12 as GPIO)
wdenkc6097192002-11-03 00:24:07 +0000196 */
197 cntrl0Reg = mfdcr(cntrl0);
stroese6f4474e2003-03-20 15:31:19 +0000198 mtdcr(cntrl0, cntrl0Reg | 0x03000000);
stroesed4629c82003-05-23 11:30:39 +0000199 out32(GPIO0_ODR, in32(GPIO0_ODR) & ~0x00180000);
200 out32(GPIO0_TCR, in32(GPIO0_TCR) & ~0x00180000);
wdenkc6097192002-11-03 00:24:07 +0000201 udelay(1000); /* wait some time before reading input */
stroesed4629c82003-05-23 11:30:39 +0000202 value = in32(GPIO0_IR) & 0x00180000; /* get config bits */
wdenkc6097192002-11-03 00:24:07 +0000203
204 /*
stroese6f4474e2003-03-20 15:31:19 +0000205 * Restore GPIO settings
wdenkc6097192002-11-03 00:24:07 +0000206 */
207 mtdcr(cntrl0, cntrl0Reg);
208
stroese6f4474e2003-03-20 15:31:19 +0000209 switch (value) {
210 case 0x00180000:
211 /* CS2==1 && CS3==1 -> version 1 */
212 return 1;
213 case 0x00080000:
214 /* CS2==0 && CS3==1 -> version 2 */
215 return 2;
216 case 0x00100000:
217 /* CS2==1 && CS3==0 -> version 3 */
218 return 3;
219 case 0x00000000:
220 /* CS2==0 && CS3==0 -> version 4 */
221 return 4;
222 default:
223 /* should not be reached! */
224 return 2;
225 }
wdenkc6097192002-11-03 00:24:07 +0000226}
227
228
229int misc_init_f (void)
230{
231 return 0; /* dummy implementation */
232}
233
234
235int misc_init_r (void)
236{
237 DECLARE_GLOBAL_DATA_PTR;
238
239 bd_t *bd = gd->bd;
240 char * tmp; /* Temporary char pointer */
stroeseafcc4a72003-04-04 16:52:57 +0000241 unsigned long cntrl0Reg;
wdenkc6097192002-11-03 00:24:07 +0000242
243#ifdef CONFIG_CPCI405_VER2
244 unsigned char *dst;
245 ulong len = sizeof(fpgadata);
246 int status;
247 int index;
248 int i;
wdenkc6097192002-11-03 00:24:07 +0000249
250 /*
251 * On CPCI-405 version 2 the environment is saved in eeprom!
252 * FPGA can be gzip compressed (malloc) and booted this late.
253 */
254
stroese6f4474e2003-03-20 15:31:19 +0000255 if (cpci405_version() >= 2) {
wdenkc6097192002-11-03 00:24:07 +0000256 /*
257 * Setup GPIO pins (CS6+CS7 as GPIO)
258 */
259 cntrl0Reg = mfdcr(cntrl0);
260 mtdcr(cntrl0, cntrl0Reg | 0x00300000);
261
262 dst = malloc(CFG_FPGA_MAX_SIZE);
263 if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, (int *)&len) != 0) {
264 printf ("GUNZIP ERROR - must RESET board to recover\n");
265 do_reset (NULL, 0, 0, NULL);
266 }
267
268 status = fpga_boot(dst, len);
269 if (status != 0) {
270 printf("\nFPGA: Booting failed ");
271 switch (status) {
272 case ERROR_FPGA_PRG_INIT_LOW:
273 printf("(Timeout: INIT not low after asserting PROGRAM*)\n ");
274 break;
275 case ERROR_FPGA_PRG_INIT_HIGH:
276 printf("(Timeout: INIT not high after deasserting PROGRAM*)\n ");
277 break;
278 case ERROR_FPGA_PRG_DONE:
279 printf("(Timeout: DONE not high after programming FPGA)\n ");
280 break;
281 }
282
283 /* display infos on fpgaimage */
284 index = 15;
285 for (i=0; i<4; i++) {
286 len = dst[index];
287 printf("FPGA: %s\n", &(dst[index+1]));
288 index += len+3;
289 }
290 putc ('\n');
291 /* delayed reboot */
292 for (i=20; i>0; i--) {
293 printf("Rebooting in %2d seconds \r",i);
294 for (index=0;index<1000;index++)
295 udelay(1000);
296 }
297 putc ('\n');
298 do_reset(NULL, 0, 0, NULL);
299 }
300
301 /* restore gpio/cs settings */
302 mtdcr(cntrl0, cntrl0Reg);
303
304 puts("FPGA: ");
305
306 /* display infos on fpgaimage */
307 index = 15;
308 for (i=0; i<4; i++) {
309 len = dst[index];
310 printf("%s ", &(dst[index+1]));
311 index += len+3;
312 }
313 putc ('\n');
314
315 free(dst);
stroese6f4474e2003-03-20 15:31:19 +0000316
317 /*
318 * Reset FPGA via FPGA_DATA pin
319 */
320 SET_FPGA(FPGA_PRG | FPGA_CLK);
321 udelay(1000); /* wait 1ms */
322 SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);
323 udelay(1000); /* wait 1ms */
324
325 if (cpci405_version() == 3) {
326 volatile unsigned short *fpga_mode = (unsigned short *)CFG_FPGA_BASE_ADDR;
327 volatile unsigned char *leds = (unsigned char *)CFG_LED_ADDR;
328
329 /*
330 * Enable outputs in fpga on version 3 board
331 */
332 *fpga_mode |= CFG_FPGA_MODE_ENABLE_OUTPUT;
333
334 /*
335 * Set outputs to 0
336 */
337 *leds = 0x00;
338
339 /*
340 * Reset external DUART
341 */
342 *fpga_mode |= CFG_FPGA_MODE_DUART_RESET;
343 udelay(100);
344 *fpga_mode &= ~(CFG_FPGA_MODE_DUART_RESET);
345 }
wdenkc6097192002-11-03 00:24:07 +0000346 }
347 else {
stroese6f4474e2003-03-20 15:31:19 +0000348 puts("\n*** U-Boot Version does not match Board Version!\n");
349 puts("*** CPCI-405 Version 1.x detected!\n");
350 puts("*** Please use correct U-Boot version (CPCI405 instead of CPCI4052)!\n\n");
wdenkc6097192002-11-03 00:24:07 +0000351 }
352
353#else /* CONFIG_CPCI405_VER2 */
354
355 /*
356 * Generate last byte of ip-addr from code-plug @ 0xf0000400
357 */
358 if (ctermm2()) {
359 char str[32];
360 unsigned char ipbyte = *(unsigned char *)0xf0000400;
361
362 /*
363 * Only overwrite ip-addr with allowed values
364 */
365 if ((ipbyte != 0x00) && (ipbyte != 0xff)) {
366 bd->bi_ip_addr = (bd->bi_ip_addr & 0xffffff00) | ipbyte;
367 sprintf(str, "%ld.%ld.%ld.%ld",
368 (bd->bi_ip_addr & 0xff000000) >> 24,
369 (bd->bi_ip_addr & 0x00ff0000) >> 16,
370 (bd->bi_ip_addr & 0x0000ff00) >> 8,
371 (bd->bi_ip_addr & 0x000000ff));
372 setenv("ipaddr", str);
373 }
374 }
375
stroese6f4474e2003-03-20 15:31:19 +0000376 if (cpci405_version() >= 2) {
377 puts("\n*** U-Boot Version does not match Board Version!\n");
378 puts("*** CPCI-405 Board Version 2.x detected!\n");
379 puts("*** Please use correct U-Boot version (CPCI4052 instead of CPCI405)!\n\n");
wdenkc6097192002-11-03 00:24:07 +0000380 }
381
382#endif /* CONFIG_CPCI405_VER2 */
383
384 /*
stroeseafcc4a72003-04-04 16:52:57 +0000385 * Select cts (and not dsr) on uart1
386 */
387 cntrl0Reg = mfdcr(cntrl0);
388 mtdcr(cntrl0, cntrl0Reg | 0x00001000);
389
390 /*
wdenkc6097192002-11-03 00:24:07 +0000391 * Write ethernet addr in NVRAM for VxWorks
392 */
393 tmp = (char *)CFG_NVRAM_BASE_ADDR + CFG_NVRAM_VXWORKS_OFFS;
394 memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[0], 6 );
395 return (0);
396}
397
398
399/*
400 * Check Board Identity:
401 */
402
403int checkboard (void)
404{
405#ifndef CONFIG_CPCI405_VER2
406 int index;
407 int len;
408#endif
409 unsigned char str[64];
410 int i = getenv_r ("serial#", str, sizeof(str));
stroese6f4474e2003-03-20 15:31:19 +0000411 unsigned short ver;
wdenkc6097192002-11-03 00:24:07 +0000412
413 puts ("Board: ");
414
415 if (i == -1) {
416 puts ("### No HW ID - assuming CPCI405");
417 } else {
418 puts(str);
419 }
420
stroese6f4474e2003-03-20 15:31:19 +0000421 ver = cpci405_version();
422 printf(" (Ver %d.x, ", ver);
wdenkc6097192002-11-03 00:24:07 +0000423
stroese6f4474e2003-03-20 15:31:19 +0000424#if 0 /* test-only */
425 if (ver >= 2) {
426 volatile u16 *fpga_status = (u16 *)CFG_FPGA_BASE_ADDR + 1;
427
428 if (*fpga_status & CFG_FPGA_STATUS_FLASH) {
429 puts ("FLASH Bank B, ");
430 } else {
431 puts ("FLASH Bank A, ");
432 }
433 }
wdenkc6097192002-11-03 00:24:07 +0000434#endif
435
436 if (ctermm2()) {
437 printf("CTERM-M2 - Id=0x%02x)", *(unsigned char *)0xf0000400);
438 } else {
439 if (cpci405_host()) {
440 puts ("PCI Host Version)");
441 } else {
442 puts ("PCI Adapter Version)");
443 }
444 }
445
446#ifndef CONFIG_CPCI405_VER2
447 puts ("\nFPGA: ");
448
449 /* display infos on fpgaimage */
450 index = 15;
451 for (i=0; i<4; i++) {
452 len = fpgadata[index];
453 printf("%s ", &(fpgadata[index+1]));
454 index += len+3;
455 }
456#endif
457
458 putc ('\n');
459
460 return 0;
461}
462
463/* ------------------------------------------------------------------------- */
464
465long int initdram (int board_type)
466{
467 unsigned long val;
468
469 mtdcr(memcfga, mem_mb0cf);
470 val = mfdcr(memcfgd);
471
472#if 0
473 printf("\nmb0cf=%x\n", val); /* test-only */
474 printf("strap=%x\n", mfdcr(strap)); /* test-only */
475#endif
476
477 return (4*1024*1024 << ((val & 0x000e0000) >> 17));
478}
479
480/* ------------------------------------------------------------------------- */
481
482int testdram (void)
483{
484 /* TODO: XXX XXX XXX */
485 printf ("test: 16 MB - ok\n");
486
487 return (0);
488}
489
490/* ------------------------------------------------------------------------- */
491
492#ifdef CONFIG_CPCI405_VER2
493#ifdef CONFIG_IDE_RESET
494
495void ide_set_reset(int on)
496{
497 volatile unsigned short *fpga_mode = (unsigned short *)CFG_FPGA_BASE_ADDR;
498
499 /*
500 * Assert or deassert CompactFlash Reset Pin
501 */
502 if (on) { /* assert RESET */
503 *fpga_mode &= ~(CFG_FPGA_MODE_CF_RESET);
504 } else { /* release RESET */
505 *fpga_mode |= CFG_FPGA_MODE_CF_RESET;
506 }
507}
508
509#endif /* CONFIG_IDE_RESET */
510#endif /* CONFIG_CPCI405_VER2 */
511
stroesed4629c82003-05-23 11:30:39 +0000512#if 0 /* test-only */
wdenkc6097192002-11-03 00:24:07 +0000513/* ------------------------------------------------------------------------- */
stroesed4629c82003-05-23 11:30:39 +0000514
515u8 *dhcp_vendorex_prep (u8 * e)
516{
517 char *ptr;
518
519/* DHCP vendor-class-identifier = 60 */
520 if ((ptr = getenv ("dhcp_vendor-class-identifier"))) {
521 *e++ = 60;
522 *e++ = strlen (ptr);
523 while (*ptr)
524 *e++ = *ptr++;
525 }
526/* my DHCP_CLIENT_IDENTIFIER = 61 */
527 if ((ptr = getenv ("dhcp_client_id"))) {
528 *e++ = 61;
529 *e++ = strlen (ptr);
530 while (*ptr)
531 *e++ = *ptr++;
532 }
533
534 return e;
535}
536
537
538/* ------------------------------------------------------------------------- */
539
540u8 *dhcp_vendorex_proc (u8 * popt)
541{
542 if (*popt == 61)
543 return (u8 *)-1;
544 if (*popt == 43) {
545 printf("|%s|", popt+4); /* test-only */
546 return (u8 *)-1;
547 }
548 return NULL;
549}
550
551/* ------------------------------------------------------------------------- */
552#endif /* test-only */