^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * arch/arm/mach-dove/pcie.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * PCIe functions for Marvell Dove 88AP510 SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/mach/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/mach/arch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <plat/pcie.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <plat/addr-map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "irqs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "bridge-regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct pcie_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u8 root_bus_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) spinlock_t conf_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) char mem_space_name[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static struct pcie_port pcie_port[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int num_pcie_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct pcie_port *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (nr >= num_pcie_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pp = &pcie_port[nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) sys->private_data = pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) pp->root_bus_nr = sys->busnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Generic PCIe unit setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) orion_pcie_setup(pp->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (pp->index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE0_IO_PHYS_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE1_IO_PHYS_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * IORESOURCE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "PCIe %d MEM", pp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) pp->res.name = pp->mem_space_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (pp->index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) pp->res.start = DOVE_PCIE0_MEM_PHYS_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pp->res.end = pp->res.start + DOVE_PCIE0_MEM_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pp->res.start = DOVE_PCIE1_MEM_PHYS_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pp->res.end = pp->res.start + DOVE_PCIE1_MEM_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pp->res.flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (request_resource(&iomem_resource, &pp->res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) panic("Request PCIe Memory resource failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Don't go out when trying to access nonexisting devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * on the local bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (bus == pp->root_bus_nr && dev > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int size, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct pci_sys_data *sys = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct pcie_port *pp = sys->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *val = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return PCIBIOS_DEVICE_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) spin_lock_irqsave(&pp->conf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) spin_unlock_irqrestore(&pp->conf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int where, int size, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct pci_sys_data *sys = bus->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct pcie_port *pp = sys->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return PCIBIOS_DEVICE_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) spin_lock_irqsave(&pp->conf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) spin_unlock_irqrestore(&pp->conf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static struct pci_ops pcie_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .read = pcie_rd_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .write = pcie_wr_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void rc_pci_fixup(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Prevent enumeration of root complex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (dev->bus->parent == NULL && dev->devfn == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dev->resource[i].start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev->resource[i].end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dev->resource[i].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (nr >= num_pcie_ports) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) list_splice_init(&sys->resources, &bridge->windows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bridge->dev.parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bridge->sysdata = sys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bridge->busnr = sys->busnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bridge->ops = &pcie_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return pci_scan_root_bus_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct pci_sys_data *sys = dev->sysdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pcie_port *pp = sys->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return pp->index ? IRQ_DOVE_PCIE1 : IRQ_DOVE_PCIE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static struct hw_pci dove_pci __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .nr_controllers = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .setup = dove_pcie_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .scan = dove_pcie_scan_bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .map_irq = dove_pcie_map_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void __init add_pcie_port(int index, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) printk(KERN_INFO "Dove PCIe port %d: ", index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (orion_pcie_link_up(base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct pcie_port *pp = &pcie_port[num_pcie_ports++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) clk_prepare_enable(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) printk(KERN_INFO "link up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pp->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pp->root_bus_nr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pp->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) spin_lock_init(&pp->conf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) memset(&pp->res, 0, sizeof(pp->res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) printk(KERN_INFO "link down, ignoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) void __init dove_pcie_init(int init_port0, int init_port1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (init_port0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (init_port1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) add_pcie_port(1, DOVE_PCIE1_VIRT_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) pci_common_init(&dove_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }