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