sparc: Move irq_trans_init() and support code into seperate file.
[linux-2.6] / arch / powerpc / boot / prpmc2800.c
1 /*
2  * Motorola ECC prpmc280/f101 & prpmc2800/f101e platform code.
3  *
4  * Author: Mark A. Greer <mgreer@mvista.com>
5  *
6  * 2007 (c) MontaVista, Software, Inc.  This file is licensed under
7  * the terms of the GNU General Public License version 2.  This program
8  * is licensed "as is" without any warranty of any kind, whether express
9  * or implied.
10  */
11
12 #include <stdarg.h>
13 #include <stddef.h>
14 #include "types.h"
15 #include "elf.h"
16 #include "page.h"
17 #include "string.h"
18 #include "stdio.h"
19 #include "io.h"
20 #include "ops.h"
21 #include "gunzip_util.h"
22 #include "mv64x60.h"
23
24 #define KB      1024U
25 #define MB      (KB*KB)
26 #define GB      (KB*MB)
27 #define MHz     (1000U*1000U)
28 #define GHz     (1000U*MHz)
29
30 #define BOARD_MODEL     "PrPMC2800"
31 #define BOARD_MODEL_MAX 32 /* max strlen(BOARD_MODEL) + 1 */
32
33 #define EEPROM2_ADDR    0xa4
34 #define EEPROM3_ADDR    0xa8
35
36 BSS_STACK(16*KB);
37
38 static u8 *bridge_base;
39
40 typedef enum {
41         BOARD_MODEL_PRPMC280,
42         BOARD_MODEL_PRPMC2800,
43 } prpmc2800_board_model;
44
45 typedef enum {
46         BRIDGE_TYPE_MV64360,
47         BRIDGE_TYPE_MV64362,
48 } prpmc2800_bridge_type;
49
50 struct prpmc2800_board_info {
51         prpmc2800_board_model model;
52         char variant;
53         prpmc2800_bridge_type bridge_type;
54         u8 subsys0;
55         u8 subsys1;
56         u8 vpd4;
57         u8 vpd4_mask;
58         u32 core_speed;
59         u32 mem_size;
60         u32 boot_flash;
61         u32 user_flash;
62 };
63
64 static struct prpmc2800_board_info prpmc2800_board_info[] = {
65         {
66                 .model          = BOARD_MODEL_PRPMC280,
67                 .variant        = 'a',
68                 .bridge_type    = BRIDGE_TYPE_MV64360,
69                 .subsys0        = 0xff,
70                 .subsys1        = 0xff,
71                 .vpd4           = 0x00,
72                 .vpd4_mask      = 0x0f,
73                 .core_speed     = 1*GHz,
74                 .mem_size       = 512*MB,
75                 .boot_flash     = 1*MB,
76                 .user_flash     = 64*MB,
77         },
78         {
79                 .model          = BOARD_MODEL_PRPMC280,
80                 .variant        = 'b',
81                 .bridge_type    = BRIDGE_TYPE_MV64362,
82                 .subsys0        = 0xff,
83                 .subsys1        = 0xff,
84                 .vpd4           = 0x01,
85                 .vpd4_mask      = 0x0f,
86                 .core_speed     = 1*GHz,
87                 .mem_size       = 512*MB,
88                 .boot_flash     = 0,
89                 .user_flash     = 0,
90         },
91         {
92                 .model          = BOARD_MODEL_PRPMC280,
93                 .variant        = 'c',
94                 .bridge_type    = BRIDGE_TYPE_MV64360,
95                 .subsys0        = 0xff,
96                 .subsys1        = 0xff,
97                 .vpd4           = 0x02,
98                 .vpd4_mask      = 0x0f,
99                 .core_speed     = 733*MHz,
100                 .mem_size       = 512*MB,
101                 .boot_flash     = 1*MB,
102                 .user_flash     = 64*MB,
103         },
104         {
105                 .model          = BOARD_MODEL_PRPMC280,
106                 .variant        = 'd',
107                 .bridge_type    = BRIDGE_TYPE_MV64360,
108                 .subsys0        = 0xff,
109                 .subsys1        = 0xff,
110                 .vpd4           = 0x03,
111                 .vpd4_mask      = 0x0f,
112                 .core_speed     = 1*GHz,
113                 .mem_size       = 1*GB,
114                 .boot_flash     = 1*MB,
115                 .user_flash     = 64*MB,
116         },
117         {
118                 .model          = BOARD_MODEL_PRPMC280,
119                 .variant        = 'e',
120                 .bridge_type    = BRIDGE_TYPE_MV64360,
121                 .subsys0        = 0xff,
122                 .subsys1        = 0xff,
123                 .vpd4           = 0x04,
124                 .vpd4_mask      = 0x0f,
125                 .core_speed     = 1*GHz,
126                 .mem_size       = 512*MB,
127                 .boot_flash     = 1*MB,
128                 .user_flash     = 64*MB,
129         },
130         {
131                 .model          = BOARD_MODEL_PRPMC280,
132                 .variant        = 'f',
133                 .bridge_type    = BRIDGE_TYPE_MV64362,
134                 .subsys0        = 0xff,
135                 .subsys1        = 0xff,
136                 .vpd4           = 0x05,
137                 .vpd4_mask      = 0x0f,
138                 .core_speed     = 733*MHz,
139                 .mem_size       = 128*MB,
140                 .boot_flash     = 1*MB,
141                 .user_flash     = 0,
142         },
143         {
144                 .model          = BOARD_MODEL_PRPMC280,
145                 .variant        = 'g',
146                 .bridge_type    = BRIDGE_TYPE_MV64360,
147                 .subsys0        = 0xff,
148                 .subsys1        = 0xff,
149                 .vpd4           = 0x06,
150                 .vpd4_mask      = 0x0f,
151                 .core_speed     = 1*GHz,
152                 .mem_size       = 256*MB,
153                 .boot_flash     = 1*MB,
154                 .user_flash     = 0,
155         },
156         {
157                 .model          = BOARD_MODEL_PRPMC280,
158                 .variant        = 'h',
159                 .bridge_type    = BRIDGE_TYPE_MV64360,
160                 .subsys0        = 0xff,
161                 .subsys1        = 0xff,
162                 .vpd4           = 0x07,
163                 .vpd4_mask      = 0x0f,
164                 .core_speed     = 1*GHz,
165                 .mem_size       = 1*GB,
166                 .boot_flash     = 1*MB,
167                 .user_flash     = 64*MB,
168         },
169         {
170                 .model          = BOARD_MODEL_PRPMC2800,
171                 .variant        = 'a',
172                 .bridge_type    = BRIDGE_TYPE_MV64360,
173                 .subsys0        = 0xb2,
174                 .subsys1        = 0x8c,
175                 .vpd4           = 0x00,
176                 .vpd4_mask      = 0x00,
177                 .core_speed     = 1*GHz,
178                 .mem_size       = 512*MB,
179                 .boot_flash     = 2*MB,
180                 .user_flash     = 64*MB,
181         },
182         {
183                 .model          = BOARD_MODEL_PRPMC2800,
184                 .variant        = 'b',
185                 .bridge_type    = BRIDGE_TYPE_MV64362,
186                 .subsys0        = 0xb2,
187                 .subsys1        = 0x8d,
188                 .vpd4           = 0x00,
189                 .vpd4_mask      = 0x00,
190                 .core_speed     = 1*GHz,
191                 .mem_size       = 512*MB,
192                 .boot_flash     = 0,
193                 .user_flash     = 0,
194         },
195         {
196                 .model          = BOARD_MODEL_PRPMC2800,
197                 .variant        = 'c',
198                 .bridge_type    = BRIDGE_TYPE_MV64360,
199                 .subsys0        = 0xb2,
200                 .subsys1        = 0x8e,
201                 .vpd4           = 0x00,
202                 .vpd4_mask      = 0x00,
203                 .core_speed     = 733*MHz,
204                 .mem_size       = 512*MB,
205                 .boot_flash     = 2*MB,
206                 .user_flash     = 64*MB,
207         },
208         {
209                 .model          = BOARD_MODEL_PRPMC2800,
210                 .variant        = 'd',
211                 .bridge_type    = BRIDGE_TYPE_MV64360,
212                 .subsys0        = 0xb2,
213                 .subsys1        = 0x8f,
214                 .vpd4           = 0x00,
215                 .vpd4_mask      = 0x00,
216                 .core_speed     = 1*GHz,
217                 .mem_size       = 1*GB,
218                 .boot_flash     = 2*MB,
219                 .user_flash     = 64*MB,
220         },
221         {
222                 .model          = BOARD_MODEL_PRPMC2800,
223                 .variant        = 'e',
224                 .bridge_type    = BRIDGE_TYPE_MV64360,
225                 .subsys0        = 0xa2,
226                 .subsys1        = 0x8a,
227                 .vpd4           = 0x00,
228                 .vpd4_mask      = 0x00,
229                 .core_speed     = 1*GHz,
230                 .mem_size       = 512*MB,
231                 .boot_flash     = 2*MB,
232                 .user_flash     = 64*MB,
233         },
234         {
235                 .model          = BOARD_MODEL_PRPMC2800,
236                 .variant        = 'f',
237                 .bridge_type    = BRIDGE_TYPE_MV64362,
238                 .subsys0        = 0xa2,
239                 .subsys1        = 0x8b,
240                 .vpd4           = 0x00,
241                 .vpd4_mask      = 0x00,
242                 .core_speed     = 733*MHz,
243                 .mem_size       = 128*MB,
244                 .boot_flash     = 2*MB,
245                 .user_flash     = 0,
246         },
247         {
248                 .model          = BOARD_MODEL_PRPMC2800,
249                 .variant        = 'g',
250                 .bridge_type    = BRIDGE_TYPE_MV64360,
251                 .subsys0        = 0xa2,
252                 .subsys1        = 0x8c,
253                 .vpd4           = 0x00,
254                 .vpd4_mask      = 0x00,
255                 .core_speed     = 1*GHz,
256                 .mem_size       = 2*GB,
257                 .boot_flash     = 2*MB,
258                 .user_flash     = 64*MB,
259         },
260         {
261                 .model          = BOARD_MODEL_PRPMC2800,
262                 .variant        = 'h',
263                 .bridge_type    = BRIDGE_TYPE_MV64360,
264                 .subsys0        = 0xa2,
265                 .subsys1        = 0x8d,
266                 .vpd4           = 0x00,
267                 .vpd4_mask      = 0x00,
268                 .core_speed     = 733*MHz,
269                 .mem_size       = 1*GB,
270                 .boot_flash     = 2*MB,
271                 .user_flash     = 64*MB,
272         },
273 };
274
275 static struct prpmc2800_board_info *prpmc2800_get_board_info(u8 *vpd)
276 {
277         struct prpmc2800_board_info *bip;
278         int i;
279
280         for (i=0,bip=prpmc2800_board_info; i<ARRAY_SIZE(prpmc2800_board_info);
281                         i++,bip++)
282                 if ((vpd[0] == bip->subsys0) && (vpd[1] == bip->subsys1)
283                                 && ((vpd[4] & bip->vpd4_mask) == bip->vpd4))
284                         return bip;
285
286         return NULL;
287 }
288
289 /* Get VPD from i2c eeprom 2, then match it to a board info entry */
290 static struct prpmc2800_board_info *prpmc2800_get_bip(void)
291 {
292         struct prpmc2800_board_info *bip;
293         u8 vpd[5];
294         int rc;
295
296         if (mv64x60_i2c_open())
297                 fatal("Error: Can't open i2c device\n\r");
298
299         /* Get VPD from i2c eeprom-2 */
300         memset(vpd, 0, sizeof(vpd));
301         rc = mv64x60_i2c_read(EEPROM2_ADDR, vpd, 0x1fde, 2, sizeof(vpd));
302         if (rc < 0)
303                 fatal("Error: Couldn't read eeprom2\n\r");
304         mv64x60_i2c_close();
305
306         /* Get board type & related info */
307         bip = prpmc2800_get_board_info(vpd);
308         if (bip == NULL) {
309                 printf("Error: Unsupported board or corrupted VPD:\n\r");
310                 printf("  0x%x 0x%x 0x%x 0x%x 0x%x\n\r",
311                                 vpd[0], vpd[1], vpd[2], vpd[3], vpd[4]);
312                 printf("Using device tree defaults...\n\r");
313         }
314
315         return bip;
316 }
317
318 static void prpmc2800_bridge_setup(u32 mem_size)
319 {
320         u32 i, v[12], enables, acc_bits;
321         u32 pci_base_hi, pci_base_lo, size, buf[2];
322         unsigned long cpu_base;
323         int rc;
324         void *devp;
325         u8 *bridge_pbase, is_coherent;
326         struct mv64x60_cpu2pci_win *tbl;
327
328         bridge_pbase = mv64x60_get_bridge_pbase();
329         is_coherent = mv64x60_is_coherent();
330
331         if (is_coherent)
332                 acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB
333                         | MV64x60_PCI_ACC_CNTL_SWAP_NONE
334                         | MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES
335                         | MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES;
336         else
337                 acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE
338                         | MV64x60_PCI_ACC_CNTL_SWAP_NONE
339                         | MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES
340                         | MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES;
341
342         mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent);
343         mv64x60_config_pci_windows(bridge_base, bridge_pbase, 0, 0, mem_size,
344                         acc_bits);
345
346         /* Get the cpu -> pci i/o & mem mappings from the device tree */
347         devp = find_node_by_compatible(NULL, "marvell,mv64360-pci");
348         if (devp == NULL)
349                 fatal("Error: Missing marvell,mv64360-pci"
350                                 " device tree node\n\r");
351
352         rc = getprop(devp, "ranges", v, sizeof(v));
353         if (rc != sizeof(v))
354                 fatal("Error: Can't find marvell,mv64360-pci ranges"
355                                 " property\n\r");
356
357         /* Get the cpu -> pci i/o & mem mappings from the device tree */
358         devp = find_node_by_compatible(NULL, "marvell,mv64360");
359         if (devp == NULL)
360                 fatal("Error: Missing marvell,mv64360 device tree node\n\r");
361
362         enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
363         enables |= 0x0007fe00; /* Disable all cpu->pci windows */
364         out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);
365
366         for (i=0; i<12; i+=6) {
367                 switch (v[i] & 0xff000000) {
368                 case 0x01000000: /* PCI I/O Space */
369                         tbl = mv64x60_cpu2pci_io;
370                         break;
371                 case 0x02000000: /* PCI MEM Space */
372                         tbl = mv64x60_cpu2pci_mem;
373                         break;
374                 default:
375                         continue;
376                 }
377
378                 pci_base_hi = v[i+1];
379                 pci_base_lo = v[i+2];
380                 cpu_base = v[i+3];
381                 size = v[i+5];
382
383                 buf[0] = cpu_base;
384                 buf[1] = size;
385
386                 if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base))
387                         fatal("Error: Can't translate PCI address 0x%x\n\r",
388                                         (u32)cpu_base);
389
390                 mv64x60_config_cpu2pci_window(bridge_base, 0, pci_base_hi,
391                                 pci_base_lo, cpu_base, size, tbl);
392         }
393
394         enables &= ~0x00000600; /* Enable cpu->pci0 i/o, cpu->pci0 mem0 */
395         out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);
396 }
397
398 static void prpmc2800_fixups(void)
399 {
400         u32 v[2], l, mem_size;
401         int rc;
402         void *devp;
403         char model[BOARD_MODEL_MAX];
404         struct prpmc2800_board_info *bip;
405
406         bip = prpmc2800_get_bip(); /* Get board info based on VPD */
407
408         mem_size = (bip) ? bip->mem_size : mv64x60_get_mem_size(bridge_base);
409         prpmc2800_bridge_setup(mem_size); /* Do necessary bridge setup */
410
411         /* If the VPD doesn't match what we know about, just use the
412          * defaults already in the device tree.
413          */
414         if (!bip)
415                 return;
416
417         /* Know the board type so override device tree defaults */
418         /* Set /model appropriately */
419         devp = finddevice("/");
420         if (devp == NULL)
421                 fatal("Error: Missing '/' device tree node\n\r");
422         memset(model, 0, BOARD_MODEL_MAX);
423         strncpy(model, BOARD_MODEL, BOARD_MODEL_MAX - 2);
424         l = strlen(model);
425         if (bip->model == BOARD_MODEL_PRPMC280)
426                 l--;
427         model[l++] = bip->variant;
428         model[l++] = '\0';
429         setprop(devp, "model", model, l);
430
431         /* Set /cpus/PowerPC,7447/clock-frequency */
432         devp = find_node_by_prop_value_str(NULL, "device_type", "cpu");
433         if (devp == NULL)
434                 fatal("Error: Missing proper cpu device tree node\n\r");
435         v[0] = bip->core_speed;
436         setprop(devp, "clock-frequency", &v[0], sizeof(v[0]));
437
438         /* Set /memory/reg size */
439         devp = finddevice("/memory");
440         if (devp == NULL)
441                 fatal("Error: Missing /memory device tree node\n\r");
442         v[0] = 0;
443         v[1] = bip->mem_size;
444         setprop(devp, "reg", v, sizeof(v));
445
446         /* Update model, if this is a mv64362 */
447         if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
448                 devp = find_node_by_compatible(NULL, "marvell,mv64360");
449                 if (devp == NULL)
450                         fatal("Error: Missing marvell,mv64360"
451                                         " device tree node\n\r");
452                 setprop(devp, "model", "mv64362", strlen("mv64362") + 1);
453         }
454
455         /* Set User FLASH size */
456         devp = find_node_by_compatible(NULL, "direct-mapped");
457         if (devp == NULL)
458                 fatal("Error: Missing User FLASH device tree node\n\r");
459         rc = getprop(devp, "reg", v, sizeof(v));
460         if (rc != sizeof(v))
461                 fatal("Error: Can't find User FLASH reg property\n\r");
462         v[1] = bip->user_flash;
463         setprop(devp, "reg", v, sizeof(v));
464 }
465
466 #define MV64x60_MPP_CNTL_0      0xf000
467 #define MV64x60_MPP_CNTL_2      0xf008
468 #define MV64x60_GPP_IO_CNTL     0xf100
469 #define MV64x60_GPP_LEVEL_CNTL  0xf110
470 #define MV64x60_GPP_VALUE_SET   0xf118
471
472 static void prpmc2800_reset(void)
473 {
474         u32 temp;
475
476         udelay(5000000);
477
478         if (bridge_base != 0) {
479                 temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0));
480                 temp &= 0xFFFF0FFF;
481                 out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp);
482
483                 temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
484                 temp |= 0x00000004;
485                 out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
486
487                 temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
488                 temp |= 0x00000004;
489                 out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
490
491                 temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2));
492                 temp &= 0xFFFF0FFF;
493                 out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp);
494
495                 temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
496                 temp |= 0x00080000;
497                 out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
498
499                 temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
500                 temp |= 0x00080000;
501                 out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
502
503                 out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET),
504                                 0x00080004);
505         }
506
507         for (;;);
508 }
509
510 #define HEAP_SIZE       (16*MB)
511 static struct gunzip_state gzstate;
512
513 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
514                    unsigned long r6, unsigned long r7)
515 {
516         struct elf_info ei;
517         char *heap_start, *dtb;
518         int dt_size = _dtb_end - _dtb_start;
519         void *vmlinuz_addr = _vmlinux_start;
520         unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
521         char elfheader[256];
522
523         if (dt_size <= 0) /* No fdt */
524                 exit();
525
526         /*
527          * Start heap after end of the kernel (after decompressed to
528          * address 0) or the end of the zImage, whichever is higher.
529          * That's so things allocated by simple_alloc won't overwrite
530          * any part of the zImage and the kernel won't overwrite the dtb
531          * when decompressed & relocated.
532          */
533         gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
534         gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
535
536         if (!parse_elf32(elfheader, &ei))
537                 exit();
538
539         heap_start = (char *)(ei.memsize + ei.elfoffset); /* end of kernel*/
540         heap_start = max(heap_start, (char *)_end); /* end of zImage */
541
542         if ((unsigned)simple_alloc_init(heap_start, HEAP_SIZE, 2*KB, 16)
543                         > (128*MB))
544                 exit();
545
546         /* Relocate dtb to safe area past end of zImage & kernel */
547         dtb = malloc(dt_size);
548         if (!dtb)
549                 exit();
550         memmove(dtb, _dtb_start, dt_size);
551         fdt_init(dtb);
552
553         bridge_base = mv64x60_get_bridge_base();
554
555         platform_ops.fixups = prpmc2800_fixups;
556         platform_ops.exit = prpmc2800_reset;
557
558         if (serial_console_init() < 0)
559                 exit();
560 }
561
562 /* _zimage_start called very early--need to turn off external interrupts */
563 asm ("  .globl _zimage_start\n\
564         _zimage_start:\n\
565                 mfmsr   10\n\
566                 rlwinm  10,10,0,~(1<<15)        /* Clear MSR_EE */\n\
567                 sync\n\
568                 mtmsr   10\n\
569                 isync\n\
570                 b _zimage_start_lib\n\
571 ");