linux/arch/arm/mach-mv78xx0/pcie.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-mv78xx0/pcie.c
   3 *
   4 * PCIe functions for Marvell MV78xx0 SoCs
   5 *
   6 * This file is licensed under the terms of the GNU General Public
   7 * License version 2.  This program is licensed "as is" without any
   8 * warranty of any kind, whether express or implied.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/pci.h>
  13#include <video/vga.h>
  14#include <asm/irq.h>
  15#include <asm/mach/pci.h>
  16#include <plat/pcie.h>
  17#include <plat/addr-map.h>
  18#include "common.h"
  19
  20struct pcie_port {
  21        u8                      maj;
  22        u8                      min;
  23        u8                      root_bus_nr;
  24        void __iomem            *base;
  25        spinlock_t              conf_lock;
  26        char                    io_space_name[16];
  27        char                    mem_space_name[16];
  28        struct resource         res[2];
  29};
  30
  31static struct pcie_port pcie_port[8];
  32static int num_pcie_ports;
  33static struct resource pcie_io_space;
  34static struct resource pcie_mem_space;
  35
  36
  37void __init mv78xx0_pcie_id(u32 *dev, u32 *rev)
  38{
  39        *dev = orion_pcie_dev_id((void __iomem *)PCIE00_VIRT_BASE);
  40        *rev = orion_pcie_rev((void __iomem *)PCIE00_VIRT_BASE);
  41}
  42
  43static void __init mv78xx0_pcie_preinit(void)
  44{
  45        int i;
  46        u32 size_each;
  47        u32 start;
  48        int win;
  49
  50        pcie_io_space.name = "PCIe I/O Space";
  51        pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0);
  52        pcie_io_space.end =
  53                MV78XX0_PCIE_IO_PHYS_BASE(0) + MV78XX0_PCIE_IO_SIZE * 8 - 1;
  54        pcie_io_space.flags = IORESOURCE_IO;
  55        if (request_resource(&iomem_resource, &pcie_io_space))
  56                panic("can't allocate PCIe I/O space");
  57
  58        pcie_mem_space.name = "PCIe MEM Space";
  59        pcie_mem_space.start = MV78XX0_PCIE_MEM_PHYS_BASE;
  60        pcie_mem_space.end =
  61                MV78XX0_PCIE_MEM_PHYS_BASE + MV78XX0_PCIE_MEM_SIZE - 1;
  62        pcie_mem_space.flags = IORESOURCE_MEM;
  63        if (request_resource(&iomem_resource, &pcie_mem_space))
  64                panic("can't allocate PCIe MEM space");
  65
  66        for (i = 0; i < num_pcie_ports; i++) {
  67                struct pcie_port *pp = pcie_port + i;
  68
  69                snprintf(pp->io_space_name, sizeof(pp->io_space_name),
  70                        "PCIe %d.%d I/O", pp->maj, pp->min);
  71                pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
  72                pp->res[0].name = pp->io_space_name;
  73                pp->res[0].start = MV78XX0_PCIE_IO_PHYS_BASE(i);
  74                pp->res[0].end = pp->res[0].start + MV78XX0_PCIE_IO_SIZE - 1;
  75                pp->res[0].flags = IORESOURCE_IO;
  76
  77                snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
  78                        "PCIe %d.%d MEM", pp->maj, pp->min);
  79                pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
  80                pp->res[1].name = pp->mem_space_name;
  81                pp->res[1].flags = IORESOURCE_MEM;
  82        }
  83
  84        switch (num_pcie_ports) {
  85        case 0:
  86                size_each = 0;
  87                break;
  88
  89        case 1:
  90                size_each = 0x30000000;
  91                break;
  92
  93        case 2 ... 3:
  94                size_each = 0x10000000;
  95                break;
  96
  97        case 4 ... 6:
  98                size_each = 0x08000000;
  99                break;
 100
 101        case 7:
 102                size_each = 0x04000000;
 103                break;
 104
 105        default:
 106                panic("invalid number of PCIe ports");
 107        }
 108
 109        start = MV78XX0_PCIE_MEM_PHYS_BASE;
 110        for (i = 0; i < num_pcie_ports; i++) {
 111                struct pcie_port *pp = pcie_port + i;
 112
 113                pp->res[1].start = start;
 114                pp->res[1].end = start + size_each - 1;
 115                start += size_each;
 116        }
 117
 118        for (i = 0; i < num_pcie_ports; i++) {
 119                struct pcie_port *pp = pcie_port + i;
 120
 121                if (request_resource(&pcie_io_space, &pp->res[0]))
 122                        panic("can't allocate PCIe I/O sub-space");
 123
 124                if (request_resource(&pcie_mem_space, &pp->res[1]))
 125                        panic("can't allocate PCIe MEM sub-space");
 126        }
 127
 128        win = 0;
 129        for (i = 0; i < num_pcie_ports; i++) {
 130                struct pcie_port *pp = pcie_port + i;
 131
 132                mv78xx0_setup_pcie_io_win(win++, pp->res[0].start,
 133                                          resource_size(&pp->res[0]),
 134                                          pp->maj, pp->min);
 135
 136                mv78xx0_setup_pcie_mem_win(win++, pp->res[1].start,
 137                                           resource_size(&pp->res[1]),
 138                                           pp->maj, pp->min);
 139        }
 140}
 141
 142static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
 143{
 144        struct pcie_port *pp;
 145
 146        if (nr >= num_pcie_ports)
 147                return 0;
 148
 149        pp = &pcie_port[nr];
 150        sys->private_data = pp;
 151        pp->root_bus_nr = sys->busnr;
 152
 153        /*
 154         * Generic PCIe unit setup.
 155         */
 156        orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
 157        orion_pcie_setup(pp->base);
 158
 159        pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
 160        pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
 161
 162        return 1;
 163}
 164
 165static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
 166{
 167        /*
 168         * Don't go out when trying to access nonexisting devices
 169         * on the local bus.
 170         */
 171        if (bus == pp->root_bus_nr && dev > 1)
 172                return 0;
 173
 174        return 1;
 175}
 176
 177static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 178                        int size, u32 *val)
 179{
 180        struct pci_sys_data *sys = bus->sysdata;
 181        struct pcie_port *pp = sys->private_data;
 182        unsigned long flags;
 183        int ret;
 184
 185        if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
 186                *val = 0xffffffff;
 187                return PCIBIOS_DEVICE_NOT_FOUND;
 188        }
 189
 190        spin_lock_irqsave(&pp->conf_lock, flags);
 191        ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
 192        spin_unlock_irqrestore(&pp->conf_lock, flags);
 193
 194        return ret;
 195}
 196
 197static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 198                        int where, int size, u32 val)
 199{
 200        struct pci_sys_data *sys = bus->sysdata;
 201        struct pcie_port *pp = sys->private_data;
 202        unsigned long flags;
 203        int ret;
 204
 205        if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
 206                return PCIBIOS_DEVICE_NOT_FOUND;
 207
 208        spin_lock_irqsave(&pp->conf_lock, flags);
 209        ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
 210        spin_unlock_irqrestore(&pp->conf_lock, flags);
 211
 212        return ret;
 213}
 214
 215static struct pci_ops pcie_ops = {
 216        .read = pcie_rd_conf,
 217        .write = pcie_wr_conf,
 218};
 219
 220static void __devinit rc_pci_fixup(struct pci_dev *dev)
 221{
 222        /*
 223         * Prevent enumeration of root complex.
 224         */
 225        if (dev->bus->parent == NULL && dev->devfn == 0) {
 226                int i;
 227
 228                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
 229                        dev->resource[i].start = 0;
 230                        dev->resource[i].end   = 0;
 231                        dev->resource[i].flags = 0;
 232                }
 233        }
 234}
 235DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
 236
 237static struct pci_bus __init *
 238mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 239{
 240        struct pci_bus *bus;
 241
 242        if (nr < num_pcie_ports) {
 243                bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
 244                                        &sys->resources);
 245        } else {
 246                bus = NULL;
 247                BUG();
 248        }
 249
 250        return bus;
 251}
 252
 253static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
 254        u8 pin)
 255{
 256        struct pci_sys_data *sys = dev->bus->sysdata;
 257        struct pcie_port *pp = sys->private_data;
 258
 259        return IRQ_MV78XX0_PCIE_00 + (pp->maj << 2) + pp->min;
 260}
 261
 262static struct hw_pci mv78xx0_pci __initdata = {
 263        .nr_controllers = 8,
 264        .preinit        = mv78xx0_pcie_preinit,
 265        .setup          = mv78xx0_pcie_setup,
 266        .scan           = mv78xx0_pcie_scan_bus,
 267        .map_irq        = mv78xx0_pcie_map_irq,
 268};
 269
 270static void __init add_pcie_port(int maj, int min, unsigned long base)
 271{
 272        printk(KERN_INFO "MV78xx0 PCIe port %d.%d: ", maj, min);
 273
 274        if (orion_pcie_link_up((void __iomem *)base)) {
 275                struct pcie_port *pp = &pcie_port[num_pcie_ports++];
 276
 277                printk("link up\n");
 278
 279                pp->maj = maj;
 280                pp->min = min;
 281                pp->root_bus_nr = -1;
 282                pp->base = (void __iomem *)base;
 283                spin_lock_init(&pp->conf_lock);
 284                memset(pp->res, 0, sizeof(pp->res));
 285        } else {
 286                printk("link down, ignoring\n");
 287        }
 288}
 289
 290void __init mv78xx0_pcie_init(int init_port0, int init_port1)
 291{
 292        vga_base = MV78XX0_PCIE_MEM_PHYS_BASE;
 293
 294        if (init_port0) {
 295                add_pcie_port(0, 0, PCIE00_VIRT_BASE);
 296                if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
 297                        add_pcie_port(0, 1, PCIE01_VIRT_BASE);
 298                        add_pcie_port(0, 2, PCIE02_VIRT_BASE);
 299                        add_pcie_port(0, 3, PCIE03_VIRT_BASE);
 300                }
 301        }
 302
 303        if (init_port1) {
 304                add_pcie_port(1, 0, PCIE10_VIRT_BASE);
 305                if (!orion_pcie_x4_mode((void __iomem *)PCIE10_VIRT_BASE)) {
 306                        add_pcie_port(1, 1, PCIE11_VIRT_BASE);
 307                        add_pcie_port(1, 2, PCIE12_VIRT_BASE);
 308                        add_pcie_port(1, 3, PCIE13_VIRT_BASE);
 309                }
 310        }
 311
 312        pci_common_init(&mv78xx0_pci);
 313}
 314