blob: 7f43e6c2f8c0a15f820ce7fc0cbd6ddb0f6936de [file] [log] [blame]
Saeed Bishara651c74c2008-06-22 22:45:06 +02001/*
2 * arch/arm/mach-kirkwood/pcie.c
3 *
4 * PCIe functions for Marvell Kirkwood 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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Andrew Lunn27e53cf2012-03-08 21:45:59 +010014#include <linux/clk.h>
Rob Herringcc22b4c2011-06-28 21:22:40 -050015#include <video/vga.h>
Nicolas Pitre6e5c11a2009-01-07 04:47:02 +010016#include <asm/irq.h>
Saeed Bishara651c74c2008-06-22 22:45:06 +020017#include <asm/mach/pci.h>
Lennert Buytenhek6f088f12008-08-09 13:44:58 +020018#include <plat/pcie.h>
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +020019#include <mach/bridge-regs.h>
Saeed Bishara651c74c2008-06-22 22:45:06 +020020#include "common.h"
21
Andrew Lunn27e53cf2012-03-08 21:45:59 +010022static void kirkwood_enable_pcie_clk(const char *port)
23{
24 struct clk *clk;
25
26 clk = clk_get_sys("pcie", port);
27 if (IS_ERR(clk)) {
Andrew Lunn98adf932012-10-20 13:23:16 +020028 pr_err("PCIE clock %s missing\n", port);
Andrew Lunn27e53cf2012-03-08 21:45:59 +010029 return;
30 }
31 clk_prepare_enable(clk);
32 clk_put(clk);
33}
34
35/* This function is called very early in the boot when probing the
36 hardware to determine what we actually are, and what rate tclk is
37 ticking at. Hence calling kirkwood_enable_pcie_clk() is not
38 possible since the clk tree has not been created yet. */
Eric Cooper0e0cdd32011-02-02 17:16:10 -050039void kirkwood_enable_pcie(void)
40{
41 u32 curr = readl(CLOCK_GATING_CTRL);
42 if (!(curr & CGC_PEX0))
43 writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
44}
45
Andrew Lunn98d99862012-04-11 21:07:45 +020046void kirkwood_pcie_id(u32 *dev, u32 *rev)
Ronen Shitritb2b3dc22008-09-15 10:40:35 +030047{
Eric Cooper0e0cdd32011-02-02 17:16:10 -050048 kirkwood_enable_pcie();
Thomas Petazzoni060f3d12012-09-11 14:27:19 +020049 *dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
50 *rev = orion_pcie_rev(PCIE_VIRT_BASE);
Ronen Shitritb2b3dc22008-09-15 10:40:35 +030051}
52
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030053struct pcie_port {
54 u8 root_bus_nr;
55 void __iomem *base;
56 spinlock_t conf_lock;
57 int irq;
Rob Herring2bb08082012-07-09 22:43:33 -050058 struct resource res;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030059};
60
61static int pcie_port_map[2];
62static int num_pcie_ports;
63
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030064static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +020065{
66 /*
67 * Don't go out when trying to access --
68 * 1. nonexisting device on local bus
69 * 2. where there's no device connected (no link)
70 */
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030071 if (bus == pp->root_bus_nr && dev == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +020072 return 1;
73
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030074 if (!orion_pcie_link_up(pp->base))
Saeed Bishara651c74c2008-06-22 22:45:06 +020075 return 0;
76
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030077 if (bus == pp->root_bus_nr && dev != 1)
Saeed Bishara651c74c2008-06-22 22:45:06 +020078 return 0;
79
80 return 1;
81}
82
83
84/*
85 * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
86 * and then reading the PCIE_CONF_DATA register. Need to make sure these
87 * transactions are atomic.
88 */
Saeed Bishara651c74c2008-06-22 22:45:06 +020089
90static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
91 int size, u32 *val)
92{
Russell King43ba9902012-03-10 13:31:34 +000093 struct pci_sys_data *sys = bus->sysdata;
94 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +020095 unsigned long flags;
96 int ret;
97
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030098 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
Saeed Bishara651c74c2008-06-22 22:45:06 +020099 *val = 0xffffffff;
100 return PCIBIOS_DEVICE_NOT_FOUND;
101 }
102
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300103 spin_lock_irqsave(&pp->conf_lock, flags);
104 ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
105 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200106
107 return ret;
108}
109
110static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
111 int where, int size, u32 val)
112{
Russell King43ba9902012-03-10 13:31:34 +0000113 struct pci_sys_data *sys = bus->sysdata;
114 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200115 unsigned long flags;
116 int ret;
117
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300118 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200119 return PCIBIOS_DEVICE_NOT_FOUND;
120
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300121 spin_lock_irqsave(&pp->conf_lock, flags);
122 ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
123 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200124
125 return ret;
126}
127
128static struct pci_ops pcie_ops = {
129 .read = pcie_rd_conf,
130 .write = pcie_wr_conf,
131};
132
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400133static void __init pcie0_ioresources_init(struct pcie_port *pp)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200134{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200135 pp->base = PCIE_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400136 pp->irq = IRQ_KIRKWOOD_PCIE;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200137
138 /*
Saeed Bishara651c74c2008-06-22 22:45:06 +0200139 * IORESOURCE_MEM
140 */
Rob Herring2bb08082012-07-09 22:43:33 -0500141 pp->res.name = "PCIe 0 MEM";
142 pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
143 pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
144 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300145}
146
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400147static void __init pcie1_ioresources_init(struct pcie_port *pp)
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300148{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200149 pp->base = PCIE1_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400150 pp->irq = IRQ_KIRKWOOD_PCIE1;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300151
152 /*
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300153 * IORESOURCE_MEM
154 */
Rob Herring2bb08082012-07-09 22:43:33 -0500155 pp->res.name = "PCIe 1 MEM";
156 pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
157 pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
158 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300159}
160
161static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
162{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300163 struct pcie_port *pp;
164 int index;
165
166 if (nr >= num_pcie_ports)
167 return 0;
168
169 index = pcie_port_map[nr];
Andrew Lunn98adf932012-10-20 13:23:16 +0200170 pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300171
172 pp = kzalloc(sizeof(*pp), GFP_KERNEL);
173 if (!pp)
174 panic("PCIe: failed to allocate pcie_port data");
175 sys->private_data = pp;
176 pp->root_bus_nr = sys->busnr;
177 spin_lock_init(&pp->conf_lock);
178
179 switch (index) {
180 case 0:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100181 kirkwood_enable_pcie_clk("0");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400182 pcie0_ioresources_init(pp);
Rob Herring2bb08082012-07-09 22:43:33 -0500183 pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300184 break;
185 case 1:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100186 kirkwood_enable_pcie_clk("1");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400187 pcie1_ioresources_init(pp);
Andrew Lunn98adf932012-10-20 13:23:16 +0200188 pci_ioremap_io(SZ_64K * sys->busnr,
189 KIRKWOOD_PCIE1_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300190 break;
191 default:
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400192 panic("PCIe setup: invalid controller %d", index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300193 }
194
Rob Herring2bb08082012-07-09 22:43:33 -0500195 if (request_resource(&iomem_resource, &pp->res))
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400196 panic("Request PCIe%d Memory resource failed\n", index);
197
Rob Herring2bb08082012-07-09 22:43:33 -0500198 pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400199
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300200 /*
201 * Generic PCIe unit setup.
202 */
203 orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
204
Andrew Lunn63a93322011-12-07 21:48:07 +0100205 orion_pcie_setup(pp->base);
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +0200206
Saeed Bishara651c74c2008-06-22 22:45:06 +0200207 return 1;
208}
209
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700210/*
211 * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
212 * is operating as a root complex this needs to be switched to
213 * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
214 * the device. Decoding setup is handled by the orion code.
215 */
Greg Kroah-Hartman351a1022012-12-21 14:02:24 -0800216static void rc_pci_fixup(struct pci_dev *dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200217{
Saeed Bishara651c74c2008-06-22 22:45:06 +0200218 if (dev->bus->parent == NULL && dev->devfn == 0) {
219 int i;
220
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700221 dev->class &= 0xff;
222 dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200223 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
224 dev->resource[i].start = 0;
225 dev->resource[i].end = 0;
226 dev->resource[i].flags = 0;
227 }
228 }
229}
230DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
231
Ralf Baechled5341942011-06-10 15:30:21 +0100232static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
233 u8 pin)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200234{
Russell King43ba9902012-03-10 13:31:34 +0000235 struct pci_sys_data *sys = dev->sysdata;
236 struct pcie_port *pp = sys->private_data;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300237
238 return pp->irq;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200239}
240
241static struct hw_pci kirkwood_pci __initdata = {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200242 .setup = kirkwood_pcie_setup,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200243 .map_irq = kirkwood_pcie_map_irq,
Jason Gunthorpe4a9329a2012-11-21 00:15:11 -0700244 .ops = &pcie_ops,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200245};
246
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200247static void __init add_pcie_port(int index, void __iomem *base)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200248{
Jason Gunthorpeb73690c2012-11-21 11:25:28 -0700249 pcie_port_map[num_pcie_ports++] = index;
250 pr_info("Kirkwood PCIe port %d: link %s\n", index,
251 orion_pcie_link_up(base) ? "up" : "down");
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300252}
253
254void __init kirkwood_pcie_init(unsigned int portmask)
255{
Rob Herringcc22b4c2011-06-28 21:22:40 -0500256 vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
257
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300258 if (portmask & KW_PCIE0)
259 add_pcie_port(0, PCIE_VIRT_BASE);
260
261 if (portmask & KW_PCIE1)
262 add_pcie_port(1, PCIE1_VIRT_BASE);
263
264 kirkwood_pci.nr_controllers = num_pcie_ports;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200265 pci_common_init(&kirkwood_pci);
266}