c510ab13acad106566d1de39a8a5dc3feb0f1b81
[oweals/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  * SPDX-License-Identifier:     GPL-2.0+
6  */
7 #include <common.h>
8 #include <console.h>
9 #include <libfdt.h>
10 #include <fdt_support.h>
11 #include <asm/processor.h>
12 #include <asm/io.h>
13 #include <command.h>
14 #include <malloc.h>
15 #include <net.h>
16 #include <pci.h>
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 extern void __ft_board_setup(void *blob, bd_t *bd);
21
22 #undef FPGA_DEBUG
23
24 /* fpga configuration data - generated by bin2cc */
25 const unsigned char fpgadata[] =
26 {
27 #if defined(CONFIG_CPCI405_VER2)
28 # include "fpgadata_cpci4052.c"
29 #endif
30 };
31
32 /*
33  * include common fpga code (for esd boards)
34  */
35 #include "../common/fpga.c"
36
37 /* Prototypes */
38 int cpci405_version(void);
39 void lxt971_no_sleep(void);
40
41 int board_early_init_f(void)
42 {
43 #ifndef CONFIG_CPCI405_VER2
44         int index, len, i;
45         int status;
46 #endif
47
48 #ifdef FPGA_DEBUG
49         /* set up serial port with default baudrate */
50         (void)get_clocks();
51         gd->baudrate = CONFIG_BAUDRATE;
52         serial_init();
53         console_init_f();
54 #endif
55
56         /*
57          * First pull fpga-prg pin low,
58          * to disable fpga logic (on version 2 board)
59          */
60         out_be32((void *)GPIO0_ODR, 0x00000000);             /* no open drain pins      */
61         out_be32((void *)GPIO0_TCR, CONFIG_SYS_FPGA_PRG); /* setup for output   */
62         out_be32((void *)GPIO0_OR, CONFIG_SYS_FPGA_PRG); /* set output pins to high */
63         out_be32((void *)GPIO0_OR, 0);               /* pull prg low            */
64
65         /*
66          * Boot onboard FPGA
67          */
68 #ifndef CONFIG_CPCI405_VER2
69         if (cpci405_version() == 1) {
70                 status = fpga_boot((unsigned char *)fpgadata, sizeof(fpgadata));
71                 if (status != 0) {
72                         /* booting FPGA failed */
73 #ifndef FPGA_DEBUG
74                         /* set up serial port with default baudrate */
75                         (void)get_clocks();
76                         gd->baudrate = CONFIG_BAUDRATE;
77                         serial_init();
78                         console_init_f();
79 #endif
80                         printf("\nFPGA: Booting failed ");
81                         switch (status) {
82                         case ERROR_FPGA_PRG_INIT_LOW:
83                                 printf("(Timeout: INIT not low after "
84                                        "asserting PROGRAM*)\n ");
85                                 break;
86                         case ERROR_FPGA_PRG_INIT_HIGH:
87                                 printf("(Timeout: INIT not high after "
88                                        "deasserting PROGRAM*)\n ");
89                                 break;
90                         case ERROR_FPGA_PRG_DONE:
91                                 printf("(Timeout: DONE not high after "
92                                        "programming FPGA)\n ");
93                                 break;
94                         }
95
96                         /* display infos on fpgaimage */
97                         index = 15;
98                         for (i = 0; i < 4; i++) {
99                                 len = fpgadata[index];
100                                 printf("FPGA: %s\n", &(fpgadata[index + 1]));
101                                 index += len + 3;
102                         }
103                         putc('\n');
104                         /* delayed reboot */
105                         for (i = 20; i > 0; i--) {
106                                 printf("Rebooting in %2d seconds \r",i);
107                                 for (index = 0; index < 1000; index++)
108                                         udelay(1000);
109                         }
110                         putc('\n');
111                         do_reset(NULL, 0, 0, NULL);
112                 }
113         }
114 #endif /* !CONFIG_CPCI405_VER2 */
115
116         /*
117          * IRQ 0-15  405GP internally generated; active high; level sensitive
118          * IRQ 16    405GP internally generated; active low; level sensitive
119          * IRQ 17-24 RESERVED
120          * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive
121          * IRQ 26 (EXT IRQ 1) CAN1 (+FPGA on CPCI4052); active low; level sens.
122          * IRQ 27 (EXT IRQ 2) PCI SLOT 0; active low; level sensitive
123          * IRQ 28 (EXT IRQ 3) PCI SLOT 1; active low; level sensitive
124          * IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive
125          * IRQ 30 (EXT IRQ 5) PCI SLOT 3; active low; level sensitive
126          * IRQ 31 (EXT IRQ 6) COMPACT FLASH; active high; level sensitive
127          */
128         mtdcr(UIC0SR, 0xFFFFFFFF);      /* clear all ints */
129         mtdcr(UIC0ER, 0x00000000);      /* disable all ints */
130         mtdcr(UIC0CR, 0x00000000);      /* set all to be non-critical*/
131 #if defined(CONFIG_CPCI405_6U)
132         if (cpci405_version() == 3) {
133                 mtdcr(UIC0PR, 0xFFFFFF99);      /* set int polarities */
134         } else {
135                 mtdcr(UIC0PR, 0xFFFFFF81);      /* set int polarities */
136         }
137 #else
138         mtdcr(UIC0PR, 0xFFFFFF81);      /* set int polarities */
139 #endif
140         mtdcr(UIC0TR, 0x10000000);      /* set int trigger levels */
141         mtdcr(UIC0VCR, 0x00000001);     /* set vect base=0,
142                                          * INT0 highest priority */
143         mtdcr(UIC0SR, 0xFFFFFFFF);      /* clear all ints */
144
145         return 0;
146 }
147
148 int ctermm2(void)
149 {
150 #if defined(CONFIG_CPCI405_VER2)
151         return 0;                       /* no, board is cpci405 */
152 #else
153         if ((in_8((void*)0xf0000400) == 0x00) &&
154             (in_8((void*)0xf0000401) == 0x01))
155                 return 0;               /* no, board is cpci405 */
156         else
157                 return -1;              /* yes, board is cterm-m2 */
158 #endif
159 }
160
161 int cpci405_host(void)
162 {
163         if (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN)
164                 return -1;              /* yes, board is cpci405 host */
165         else
166                 return 0;               /* no, board is cpci405 adapter */
167 }
168
169 int cpci405_version(void)
170 {
171         unsigned long CPC0_CR0Reg;
172         unsigned long value;
173
174         /*
175          * Setup GPIO pins (CS2/GPIO11 and CS3/GPIO12 as GPIO)
176          */
177         CPC0_CR0Reg = mfdcr(CPC0_CR0);
178         mtdcr(CPC0_CR0, CPC0_CR0Reg | 0x03000000);
179         out_be32((void*)GPIO0_ODR, in_be32((void*)GPIO0_ODR) & ~0x00180000);
180         out_be32((void*)GPIO0_TCR, in_be32((void*)GPIO0_TCR) & ~0x00180000);
181         udelay(1000); /* wait some time before reading input */
182         value = in_be32((void*)GPIO0_IR) & 0x00180000; /* get config bits */
183
184         /*
185          * Restore GPIO settings
186          */
187         mtdcr(CPC0_CR0, CPC0_CR0Reg);
188
189         switch (value) {
190         case 0x00180000:
191                 /* CS2==1 && CS3==1 -> version 1 */
192                 return 1;
193         case 0x00080000:
194                 /* CS2==0 && CS3==1 -> version 2 */
195                 return 2;
196         case 0x00100000:
197                 /* CS2==1 && CS3==0 -> version 3 or 6U board */
198                 return 3;
199         case 0x00000000:
200                 /* CS2==0 && CS3==0 -> version 4 */
201                 return 4;
202         default:
203                 /* should not be reached! */
204                 return 2;
205         }
206 }
207
208 int misc_init_r (void)
209 {
210         unsigned long CPC0_CR0Reg;
211
212         /* adjust flash start and offset */
213         gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize;
214         gd->bd->bi_flashoffset = 0;
215
216 #if defined(CONFIG_CPCI405_VER2)
217         {
218         unsigned char *dst;
219         ulong len = sizeof(fpgadata);
220         int status;
221         int index;
222         int i;
223
224         /*
225          * On CPCI-405 version 2 the environment is saved in eeprom!
226          * FPGA can be gzip compressed (malloc) and booted this late.
227          */
228         if (cpci405_version() >= 2) {
229                 /*
230                  * Setup GPIO pins (CS6+CS7 as GPIO)
231                  */
232                 CPC0_CR0Reg = mfdcr(CPC0_CR0);
233                 mtdcr(CPC0_CR0, CPC0_CR0Reg | 0x00300000);
234
235                 dst = malloc(CONFIG_SYS_FPGA_MAX_SIZE);
236                 if (gunzip(dst, CONFIG_SYS_FPGA_MAX_SIZE,
237                            (uchar *)fpgadata, &len) != 0) {
238                         printf("GUNZIP ERROR - must RESET board to recover\n");
239                         do_reset(NULL, 0, 0, NULL);
240                 }
241
242                 status = fpga_boot(dst, len);
243                 if (status != 0) {
244                         printf("\nFPGA: Booting failed ");
245                         switch (status) {
246                         case ERROR_FPGA_PRG_INIT_LOW:
247                                 printf("(Timeout: INIT not low after "
248                                        "asserting PROGRAM*)\n ");
249                                 break;
250                         case ERROR_FPGA_PRG_INIT_HIGH:
251                                 printf("(Timeout: INIT not high after "
252                                        "deasserting PROGRAM*)\n ");
253                                 break;
254                         case ERROR_FPGA_PRG_DONE:
255                                 printf("(Timeout: DONE not high after "
256                                        "programming FPGA)\n ");
257                                 break;
258                         }
259
260                         /* display infos on fpgaimage */
261                         index = 15;
262                         for (i = 0; i < 4; i++) {
263                                 len = dst[index];
264                                 printf("FPGA: %s\n", &(dst[index + 1]));
265                                 index += len + 3;
266                         }
267                         putc('\n');
268                         /* delayed reboot */
269                         for (i = 20; i > 0; i--) {
270                                 printf("Rebooting in %2d seconds \r", i);
271                                 for (index = 0; index < 1000; index++)
272                                         udelay(1000);
273                         }
274                         putc('\n');
275                         do_reset(NULL, 0, 0, NULL);
276                 }
277
278                 /* restore gpio/cs settings */
279                 mtdcr(CPC0_CR0, CPC0_CR0Reg);
280
281                 puts("FPGA:  ");
282
283                 /* display infos on fpgaimage */
284                 index = 15;
285                 for (i = 0; i < 4; i++) {
286                         len = dst[index];
287                         printf("%s ", &(dst[index + 1]));
288                         index += len + 3;
289                 }
290                 putc('\n');
291
292                 free(dst);
293
294                 /*
295                  * Reset FPGA via FPGA_DATA pin
296                  */
297                 SET_FPGA(FPGA_PRG | FPGA_CLK);
298                 udelay(1000); /* wait 1ms */
299                 SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);
300                 udelay(1000); /* wait 1ms */
301
302 #if defined(CONFIG_CPCI405_6U)
303 #error HIER GETH ES WEITER MIT IO ACCESSORS
304                 if (cpci405_version() == 3) {
305                         /*
306                          * Enable outputs in fpga on version 3 board
307                          */
308                         out_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR,
309                                  in_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR) |
310                                  CONFIG_SYS_FPGA_MODE_ENABLE_OUTPUT);
311
312                         /*
313                          * Set outputs to 0
314                          */
315                         out_8((void*)CONFIG_SYS_LED_ADDR, 0x00);
316
317                         /*
318                          * Reset external DUART
319                          */
320                         out_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR,
321                                  in_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR) |
322                                  CONFIG_SYS_FPGA_MODE_DUART_RESET);
323                         udelay(100);
324                         out_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR,
325                                  in_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR) &
326                                  ~CONFIG_SYS_FPGA_MODE_DUART_RESET);
327                 }
328 #endif
329         }
330         else {
331                 puts("\n*** U-Boot Version does not match Board Version!\n");
332                 puts("*** CPCI-405 Version 1.x detected!\n");
333                 puts("*** Please use correct U-Boot version "
334                      "(CPCI405 instead of CPCI4052)!\n\n");
335         }
336         }
337 #else /* CONFIG_CPCI405_VER2 */
338         if (cpci405_version() >= 2) {
339                 puts("\n*** U-Boot Version does not match Board Version!\n");
340                 puts("*** CPCI-405 Board Version 2.x detected!\n");
341                 puts("*** Please use correct U-Boot version "
342                      "(CPCI4052 instead of CPCI405)!\n\n");
343         }
344 #endif /* CONFIG_CPCI405_VER2 */
345
346         /*
347          * Select cts (and not dsr) on uart1
348          */
349         CPC0_CR0Reg = mfdcr(CPC0_CR0);
350         mtdcr(CPC0_CR0, CPC0_CR0Reg | 0x00001000);
351
352         return 0;
353 }
354
355 /*
356  * Check Board Identity:
357  */
358
359 int checkboard(void)
360 {
361 #ifndef CONFIG_CPCI405_VER2
362         int index;
363         int len;
364 #endif
365         char str[64];
366         int i = getenv_f("serial#", str, sizeof(str));
367         unsigned short ver;
368
369         puts("Board: ");
370
371         if (i == -1)
372                 puts("### No HW ID - assuming CPCI405");
373         else
374                 puts(str);
375
376         ver = cpci405_version();
377         printf(" (Ver %d.x, ", ver);
378
379         if (ctermm2()) {
380                 char str[4];
381
382                 /*
383                  * Read board-id and save in env-variable
384                  */
385                 sprintf(str, "%d", *(unsigned char *)0xf0000400);
386                 setenv("boardid", str);
387                 printf("CTERM-M2 - Id=%s)", str);
388         } else {
389                 if (cpci405_host())
390                         puts("PCI Host Version)");
391                 else
392                         puts("PCI Adapter Version)");
393         }
394
395 #ifndef CONFIG_CPCI405_VER2
396         puts("\nFPGA:   ");
397
398         /* display infos on fpgaimage */
399         index = 15;
400         for (i = 0; i < 4; i++) {
401                 len = fpgadata[index];
402                 printf("%s ", &(fpgadata[index + 1]));
403                 index += len + 3;
404         }
405 #endif
406
407         putc('\n');
408         return 0;
409 }
410
411 void reset_phy(void)
412 {
413 #if defined(CONFIG_LXT971_NO_SLEEP)
414
415         /*
416          * Disable sleep mode in LXT971
417          */
418         lxt971_no_sleep();
419 #endif
420 }
421
422 #if defined(CONFIG_CPCI405_VER2) && defined (CONFIG_IDE_RESET)
423 void ide_set_reset(int on)
424 {
425         /*
426          * Assert or deassert CompactFlash Reset Pin
427          */
428         if (on) {       /* assert RESET */
429                 out_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR,
430                          in_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR) &
431                          ~CONFIG_SYS_FPGA_MODE_CF_RESET);
432         } else {        /* release RESET */
433                 out_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR,
434                          in_be16((void*)CONFIG_SYS_FPGA_BASE_ADDR) |
435                          CONFIG_SYS_FPGA_MODE_CF_RESET);
436         }
437 }
438
439 #endif /* CONFIG_IDE_RESET && CONFIG_CPCI405_VER2 */
440
441 #if defined(CONFIG_PCI)
442 void cpci405_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
443 {
444         unsigned char int_line = 0xff;
445
446         /*
447          * Write pci interrupt line register (cpci405 specific)
448          */
449         switch (PCI_DEV(dev) & 0x03) {
450         case 0:
451                 int_line = 27 + 2;
452                 break;
453         case 1:
454                 int_line = 27 + 3;
455                 break;
456         case 2:
457                 int_line = 27 + 0;
458                 break;
459         case 3:
460                 int_line = 27 + 1;
461                 break;
462         }
463
464         pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
465 }
466
467 int pci_pre_init(struct pci_controller *hose)
468 {
469         hose->fixup_irq = cpci405_pci_fixup_irq;
470         return 1;
471 }
472 #endif /* defined(CONFIG_PCI) */
473
474 #ifdef CONFIG_OF_BOARD_SETUP
475 int ft_board_setup(void *blob, bd_t *bd)
476 {
477         int rc;
478
479         __ft_board_setup(blob, bd);
480
481         /*
482          * Disable PCI in adapter mode.
483          */
484         if (!cpci405_host()) {
485                 rc = fdt_find_and_setprop(blob, "/plb/pci@ec000000", "status",
486                                           "disabled", sizeof("disabled"), 1);
487                 if (rc) {
488                         printf("Unable to update property status in PCI node, "
489                                "err=%s\n",
490                                fdt_strerror(rc));
491                 }
492         }
493
494         return 0;
495 }
496 #endif /* CONFIG_OF_BOARD_SETUP */