CPCI405AB (special version of esd CPCI405) board added.
[platform/kernel/u-boot.git] / board / esd / cpci405 / cpci405.c
1 /*
2  * (C) Copyright 2001-2003
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>
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 */
37 const unsigned char fpgadata[] =
38 {
39 #ifdef CONFIG_CPCI405_VER2
40 # ifdef CONFIG_CPCI405AB
41 #  include "fpgadata_cpci405ab.c"
42 # else
43 #  include "fpgadata_cpci4052.c"
44 # endif
45 #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 */
57 int cpci405_version(void);
58 int gunzip(void *, int, unsigned char *, int *);
59
60
61 int 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          */
81         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            */
85
86         /*
87          * Boot onboard FPGA
88          */
89 #ifndef CONFIG_CPCI405_VER2
90         if (cpci405_version() == 1) {
91                 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*/
151         if (cpci405_version() == 3) {
152                 mtdcr(uicpr, 0xFFFFFF99);       /* set int polarities */
153         } else {
154                 mtdcr(uicpr, 0xFFFFFF81);       /* set int polarities */
155         }
156         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
166 int 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
180 int 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
189 int cpci405_version(void)
190 {
191         unsigned long cntrl0Reg;
192         unsigned long value;
193
194         /*
195          * Setup GPIO pins (CS2/GPIO11 and CS3/GPIO12 as GPIO)
196          */
197         cntrl0Reg = mfdcr(cntrl0);
198         mtdcr(cntrl0, cntrl0Reg | 0x03000000);
199         out32(GPIO0_ODR, in32(GPIO0_ODR) & ~0x00180000);
200         out32(GPIO0_TCR, in32(GPIO0_TCR) & ~0x00180000);
201         udelay(1000);                   /* wait some time before reading input */
202         value = in32(GPIO0_IR) & 0x00180000;       /* get config bits */
203
204         /*
205          * Restore GPIO settings
206          */
207         mtdcr(cntrl0, cntrl0Reg);
208
209         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         }
226 }
227
228
229 int misc_init_f (void)
230 {
231         return 0;  /* dummy implementation */
232 }
233
234
235 int misc_init_r (void)
236 {
237         DECLARE_GLOBAL_DATA_PTR;
238
239         bd_t *bd = gd->bd;
240         char *  tmp;                    /* Temporary char pointer      */
241         unsigned long cntrl0Reg;
242
243 #ifdef CONFIG_CPCI405_VER2
244         unsigned char *dst;
245         ulong len = sizeof(fpgadata);
246         int status;
247         int index;
248         int i;
249
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
255         if (cpci405_version() >= 2) {
256                 /*
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);
316
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                 }
346         }
347         else {
348                 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");
351         }
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
376         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");
380         }
381
382 #endif /* CONFIG_CPCI405_VER2 */
383
384         /*
385          * Select cts (and not dsr) on uart1
386          */
387         cntrl0Reg = mfdcr(cntrl0);
388         mtdcr(cntrl0, cntrl0Reg | 0x00001000);
389
390         /*
391          * 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
403 int 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));
411         unsigned short ver;
412
413         puts ("Board: ");
414
415         if (i == -1) {
416                 puts ("### No HW ID - assuming CPCI405");
417         } else {
418                 puts(str);
419         }
420
421         ver = cpci405_version();
422         printf(" (Ver %d.x, ", ver);
423
424 #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         }
434 #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
465 long 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
482 int 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
495 void 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
512 #if 0 /* test-only */
513 /* ------------------------------------------------------------------------- */
514
515 u8 *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
540 u8 *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 */