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