linux/arch/powerpc/boot/prpmc2800.c
<<
>>
Prefs
   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
  36BSS_STACK(16*KB);
  37
  38static u8 *bridge_base;
  39
  40typedef enum {
  41        BOARD_MODEL_PRPMC280,
  42        BOARD_MODEL_PRPMC2800,
  43} prpmc2800_board_model;
  44
  45typedef enum {
  46        BRIDGE_TYPE_MV64360,
  47        BRIDGE_TYPE_MV64362,
  48} prpmc2800_bridge_type;
  49
  50struct 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
  64static 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
 275static 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 */
 290static 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
 318static 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
 398static 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
 472static 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)
 511static struct gunzip_state gzstate;
 512
 513void 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 */
 563asm ("  .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");
 572