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