Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.23 577 lines 14 kB view raw
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 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");