diff options
Diffstat (limited to 'arch/arm/mach-kirkwood/pcie.c')
-rw-r--r-- | arch/arm/mach-kirkwood/pcie.c | 296 |
1 files changed, 0 insertions, 296 deletions
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c deleted file mode 100644 index 12d86f39f380..000000000000 --- a/arch/arm/mach-kirkwood/pcie.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * arch/arm/mach-kirkwood/pcie.c - * - * PCIe functions for Marvell Kirkwood SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/mbus.h> -#include <video/vga.h> -#include <asm/irq.h> -#include <asm/mach/pci.h> -#include <plat/pcie.h> -#include <mach/bridge-regs.h> -#include "common.h" - -/* These can go away once Kirkwood uses the mvebu-mbus DT binding */ -#define KIRKWOOD_MBUS_PCIE0_MEM_TARGET 0x4 -#define KIRKWOOD_MBUS_PCIE0_MEM_ATTR 0xe8 -#define KIRKWOOD_MBUS_PCIE0_IO_TARGET 0x4 -#define KIRKWOOD_MBUS_PCIE0_IO_ATTR 0xe0 -#define KIRKWOOD_MBUS_PCIE1_MEM_TARGET 0x4 -#define KIRKWOOD_MBUS_PCIE1_MEM_ATTR 0xd8 -#define KIRKWOOD_MBUS_PCIE1_IO_TARGET 0x4 -#define KIRKWOOD_MBUS_PCIE1_IO_ATTR 0xd0 - -static void kirkwood_enable_pcie_clk(const char *port) -{ - struct clk *clk; - - clk = clk_get_sys("pcie", port); - if (IS_ERR(clk)) { - pr_err("PCIE clock %s missing\n", port); - return; - } - clk_prepare_enable(clk); - clk_put(clk); -} - -/* This function is called very early in the boot when probing the - hardware to determine what we actually are, and what rate tclk is - ticking at. Hence calling kirkwood_enable_pcie_clk() is not - possible since the clk tree has not been created yet. */ -void kirkwood_enable_pcie(void) -{ - u32 curr = readl(CLOCK_GATING_CTRL); - if (!(curr & CGC_PEX0)) - writel(curr | CGC_PEX0, CLOCK_GATING_CTRL); -} - -void kirkwood_pcie_id(u32 *dev, u32 *rev) -{ - kirkwood_enable_pcie(); - *dev = orion_pcie_dev_id(PCIE_VIRT_BASE); - *rev = orion_pcie_rev(PCIE_VIRT_BASE); -} - -struct pcie_port { - u8 root_bus_nr; - void __iomem *base; - spinlock_t conf_lock; - int irq; - struct resource res; -}; - -static int pcie_port_map[2]; -static int num_pcie_ports; - -static int pcie_valid_config(struct pcie_port *pp, int bus, int dev) -{ - /* - * Don't go out when trying to access -- - * 1. nonexisting device on local bus - * 2. where there's no device connected (no link) - */ - if (bus == pp->root_bus_nr && dev == 0) - return 1; - - if (!orion_pcie_link_up(pp->base)) - return 0; - - if (bus == pp->root_bus_nr && dev != 1) - return 0; - - return 1; -} - - -/* - * PCIe config cycles are done by programming the PCIE_CONF_ADDR register - * and then reading the PCIE_CONF_DATA register. Need to make sure these - * transactions are atomic. - */ - -static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, - int size, u32 *val) -{ - struct pci_sys_data *sys = bus->sysdata; - struct pcie_port *pp = sys->private_data; - unsigned long flags; - int ret; - - if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - spin_lock_irqsave(&pp->conf_lock, flags); - ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val); - spin_unlock_irqrestore(&pp->conf_lock, flags); - - return ret; -} - -static int pcie_wr_conf(struct pci_bus *bus, u32 devfn, - int where, int size, u32 val) -{ - struct pci_sys_data *sys = bus->sysdata; - struct pcie_port *pp = sys->private_data; - unsigned long flags; - int ret; - - if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - - spin_lock_irqsave(&pp->conf_lock, flags); - ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val); - spin_unlock_irqrestore(&pp->conf_lock, flags); - - return ret; -} - -static struct pci_ops pcie_ops = { - .read = pcie_rd_conf, - .write = pcie_wr_conf, -}; - -static void __init pcie0_ioresources_init(struct pcie_port *pp) -{ - pp->base = PCIE_VIRT_BASE; - pp->irq = IRQ_KIRKWOOD_PCIE; - - /* - * IORESOURCE_MEM - */ - pp->res.name = "PCIe 0 MEM"; - pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE; - pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1; - pp->res.flags = IORESOURCE_MEM; -} - -static void __init pcie1_ioresources_init(struct pcie_port *pp) -{ - pp->base = PCIE1_VIRT_BASE; - pp->irq = IRQ_KIRKWOOD_PCIE1; - - /* - * IORESOURCE_MEM - */ - pp->res.name = "PCIe 1 MEM"; - pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE; - pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1; - pp->res.flags = IORESOURCE_MEM; -} - -static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) -{ - struct pcie_port *pp; - int index; - - if (nr >= num_pcie_ports) - return 0; - - index = pcie_port_map[nr]; - pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index); - - pp = kzalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) - panic("PCIe: failed to allocate pcie_port data"); - sys->private_data = pp; - pp->root_bus_nr = sys->busnr; - spin_lock_init(&pp->conf_lock); - - switch (index) { - case 0: - kirkwood_enable_pcie_clk("0"); - pcie0_ioresources_init(pp); - pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE); - break; - case 1: - kirkwood_enable_pcie_clk("1"); - pcie1_ioresources_init(pp); - pci_ioremap_io(SZ_64K * sys->busnr, - KIRKWOOD_PCIE1_IO_PHYS_BASE); - break; - default: - panic("PCIe setup: invalid controller %d", index); - } - - if (request_resource(&iomem_resource, &pp->res)) - panic("Request PCIe%d Memory resource failed\n", index); - - pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset); - - /* - * Generic PCIe unit setup. - */ - orion_pcie_set_local_bus_nr(pp->base, sys->busnr); - - orion_pcie_setup(pp->base); - - return 1; -} - -/* - * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it - * is operating as a root complex this needs to be switched to - * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on - * the device. Decoding setup is handled by the orion code. - */ -static void rc_pci_fixup(struct pci_dev *dev) -{ - if (dev->bus->parent == NULL && dev->devfn == 0) { - int i; - - dev->class &= 0xff; - dev->class |= PCI_CLASS_BRIDGE_HOST << 8; - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - dev->resource[i].start = 0; - dev->resource[i].end = 0; - dev->resource[i].flags = 0; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); - -static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot, - u8 pin) -{ - struct pci_sys_data *sys = dev->sysdata; - struct pcie_port *pp = sys->private_data; - - return pp->irq; -} - -static struct hw_pci kirkwood_pci __initdata = { - .setup = kirkwood_pcie_setup, - .map_irq = kirkwood_pcie_map_irq, - .ops = &pcie_ops, -}; - -static void __init add_pcie_port(int index, void __iomem *base) -{ - pcie_port_map[num_pcie_ports++] = index; - pr_info("Kirkwood PCIe port %d: link %s\n", index, - orion_pcie_link_up(base) ? "up" : "down"); -} - -void __init kirkwood_pcie_init(unsigned int portmask) -{ - mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE0_IO_TARGET, - KIRKWOOD_MBUS_PCIE0_IO_ATTR, - KIRKWOOD_PCIE_IO_PHYS_BASE, - KIRKWOOD_PCIE_IO_SIZE, - KIRKWOOD_PCIE_IO_BUS_BASE); - mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE0_MEM_TARGET, - KIRKWOOD_MBUS_PCIE0_MEM_ATTR, - KIRKWOOD_PCIE_MEM_PHYS_BASE, - KIRKWOOD_PCIE_MEM_SIZE); - mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE1_IO_TARGET, - KIRKWOOD_MBUS_PCIE1_IO_ATTR, - KIRKWOOD_PCIE1_IO_PHYS_BASE, - KIRKWOOD_PCIE1_IO_SIZE, - KIRKWOOD_PCIE1_IO_BUS_BASE); - mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE1_MEM_TARGET, - KIRKWOOD_MBUS_PCIE1_MEM_ATTR, - KIRKWOOD_PCIE1_MEM_PHYS_BASE, - KIRKWOOD_PCIE1_MEM_SIZE); - - vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE; - - if (portmask & KW_PCIE0) - add_pcie_port(0, PCIE_VIRT_BASE); - - if (portmask & KW_PCIE1) - add_pcie_port(1, PCIE1_VIRT_BASE); - - kirkwood_pci.nr_controllers = num_pcie_ports; - pci_common_init(&kirkwood_pci); -} |