linux/arch/powerpc/boot/cuboot-c2k.c
<<
>>
Prefs
   1/*
   2 * GEFanuc C2K platform code.
   3 *
   4 * Author: Remi Machet <rmachet@slac.stanford.edu>
   5 *
   6 * Originated from prpmc2800.c
   7 *
   8 * 2008 (c) Stanford University
   9 * 2007 (c) MontaVista, Software, Inc.
  10 *
  11 * This program is free software; you can redistribute it and/or modify it
  12 * under the terms of the GNU General Public License version 2 as published
  13 * by the Free Software Foundation.
  14 */
  15
  16#include "types.h"
  17#include "stdio.h"
  18#include "io.h"
  19#include "ops.h"
  20#include "elf.h"
  21#include "gunzip_util.h"
  22#include "mv64x60.h"
  23#include "cuboot.h"
  24#include "ppcboot.h"
  25
  26static u8 *bridge_base;
  27
  28static void c2k_bridge_setup(u32 mem_size)
  29{
  30        u32 i, v[30], enables, acc_bits;
  31        u32 pci_base_hi, pci_base_lo, size, buf[2];
  32        unsigned long cpu_base;
  33        int rc;
  34        void *devp, *mv64x60_devp;
  35        u8 *bridge_pbase, is_coherent;
  36        struct mv64x60_cpu2pci_win *tbl;
  37        int bus;
  38
  39        bridge_pbase = mv64x60_get_bridge_pbase();
  40        is_coherent = mv64x60_is_coherent();
  41
  42        if (is_coherent)
  43                acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB
  44                        | MV64x60_PCI_ACC_CNTL_SWAP_NONE
  45                        | MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES
  46                        | MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES;
  47        else
  48                acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE
  49                        | MV64x60_PCI_ACC_CNTL_SWAP_NONE
  50                        | MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES
  51                        | MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES;
  52
  53        mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent);
  54        mv64x60_devp = find_node_by_compatible(NULL, "marvell,mv64360");
  55        if (mv64x60_devp == NULL)
  56                fatal("Error: Missing marvell,mv64360 device tree node\n\r");
  57
  58        enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
  59        enables |= 0x007ffe00; /* Disable all cpu->pci windows */
  60        out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);
  61
  62        /* Get the cpu -> pci i/o & mem mappings from the device tree */
  63        devp = NULL;
  64        for (bus = 0; ; bus++) {
  65                char name[] = "pci ";
  66
  67                name[strlen(name)-1] = bus+'0';
  68
  69                devp = find_node_by_alias(name);
  70                if (devp == NULL)
  71                        break;
  72
  73                if (bus >= 2)
  74                        fatal("Error: Only 2 PCI controllers are supported at" \
  75                                " this time.\n");
  76
  77                mv64x60_config_pci_windows(bridge_base, bridge_pbase, bus, 0,
  78                                mem_size, acc_bits);
  79
  80                rc = getprop(devp, "ranges", v, sizeof(v));
  81                if (rc == 0)
  82                        fatal("Error: Can't find marvell,mv64360-pci ranges"
  83                                " property\n\r");
  84
  85                /* Get the cpu -> pci i/o & mem mappings from the device tree */
  86
  87                for (i = 0; i < rc; i += 6) {
  88                        switch (v[i] & 0xff000000) {
  89                        case 0x01000000: /* PCI I/O Space */
  90                                tbl = mv64x60_cpu2pci_io;
  91                                break;
  92                        case 0x02000000: /* PCI MEM Space */
  93                                tbl = mv64x60_cpu2pci_mem;
  94                                break;
  95                        default:
  96                                continue;
  97                        }
  98
  99                        pci_base_hi = v[i+1];
 100                        pci_base_lo = v[i+2];
 101                        cpu_base = v[i+3];
 102                        size = v[i+5];
 103
 104                        buf[0] = cpu_base;
 105                        buf[1] = size;
 106
 107                        if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base))
 108                                fatal("Error: Can't translate PCI address " \
 109                                                "0x%x\n\r", (u32)cpu_base);
 110
 111                        mv64x60_config_cpu2pci_window(bridge_base, bus,
 112                                pci_base_hi, pci_base_lo, cpu_base, size, tbl);
 113                }
 114
 115                enables &= ~(3<<(9+bus*5)); /* Enable cpu->pci<bus> i/o,
 116                                                cpu->pci<bus> mem0 */
 117                out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE),
 118                        enables);
 119        };
 120}
 121
 122static void c2k_fixups(void)
 123{
 124        u32 mem_size;
 125
 126        mem_size = mv64x60_get_mem_size(bridge_base);
 127        c2k_bridge_setup(mem_size); /* Do necessary bridge setup */
 128}
 129
 130#define MV64x60_MPP_CNTL_0      0xf000
 131#define MV64x60_MPP_CNTL_2      0xf008
 132#define MV64x60_GPP_IO_CNTL     0xf100
 133#define MV64x60_GPP_LEVEL_CNTL  0xf110
 134#define MV64x60_GPP_VALUE_SET   0xf118
 135
 136static void c2k_reset(void)
 137{
 138        u32 temp;
 139
 140        udelay(5000000);
 141
 142        if (bridge_base != 0) {
 143                temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0));
 144                temp &= 0xFFFF0FFF;
 145                out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp);
 146
 147                temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
 148                temp |= 0x00000004;
 149                out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
 150
 151                temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
 152                temp |= 0x00000004;
 153                out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
 154
 155                temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2));
 156                temp &= 0xFFFF0FFF;
 157                out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp);
 158
 159                temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));
 160                temp |= 0x00080000;
 161                out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);
 162
 163                temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));
 164                temp |= 0x00080000;
 165                out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);
 166
 167                out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET),
 168                                0x00080004);
 169        }
 170
 171        for (;;);
 172}
 173
 174static bd_t bd;
 175
 176void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 177                        unsigned long r6, unsigned long r7)
 178{
 179        CUBOOT_INIT();
 180
 181        fdt_init(_dtb_start);
 182
 183        bridge_base = mv64x60_get_bridge_base();
 184
 185        platform_ops.fixups = c2k_fixups;
 186        platform_ops.exit = c2k_reset;
 187
 188        if (serial_console_init() < 0)
 189                exit();
 190}
 191