blob: df6399dea7458e2dd5e7f22d30dc3cc8ffd74874 [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>
Andrew Lunn45173d52011-12-07 21:48:06 +010020#include <plat/addr-map.h>
Saeed Bishara651c74c2008-06-22 22:45:06 +020021#include "common.h"
22
Andrew Lunn27e53cf2012-03-08 21:45:59 +010023static void kirkwood_enable_pcie_clk(const char *port)
24{
25 struct clk *clk;
26
27 clk = clk_get_sys("pcie", port);
28 if (IS_ERR(clk)) {
29 printk(KERN_ERR "PCIE clock %s missing\n", port);
30 return;
31 }
32 clk_prepare_enable(clk);
33 clk_put(clk);
34}
35
36/* This function is called very early in the boot when probing the
37 hardware to determine what we actually are, and what rate tclk is
38 ticking at. Hence calling kirkwood_enable_pcie_clk() is not
39 possible since the clk tree has not been created yet. */
Eric Cooper0e0cdd32011-02-02 17:16:10 -050040void kirkwood_enable_pcie(void)
41{
42 u32 curr = readl(CLOCK_GATING_CTRL);
43 if (!(curr & CGC_PEX0))
44 writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
45}
46
Andrew Lunn98d99862012-04-11 21:07:45 +020047void kirkwood_pcie_id(u32 *dev, u32 *rev)
Ronen Shitritb2b3dc2f2008-09-15 10:40:35 +030048{
Eric Cooper0e0cdd32011-02-02 17:16:10 -050049 kirkwood_enable_pcie();
Thomas Petazzoni060f3d12012-09-11 14:27:19 +020050 *dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
51 *rev = orion_pcie_rev(PCIE_VIRT_BASE);
Ronen Shitritb2b3dc2f2008-09-15 10:40:35 +030052}
53
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030054struct pcie_port {
55 u8 root_bus_nr;
56 void __iomem *base;
57 spinlock_t conf_lock;
58 int irq;
59 struct resource res[2];
60};
61
62static int pcie_port_map[2];
63static int num_pcie_ports;
64
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030065static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +020066{
67 /*
68 * Don't go out when trying to access --
69 * 1. nonexisting device on local bus
70 * 2. where there's no device connected (no link)
71 */
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030072 if (bus == pp->root_bus_nr && dev == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +020073 return 1;
74
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030075 if (!orion_pcie_link_up(pp->base))
Saeed Bishara651c74c2008-06-22 22:45:06 +020076 return 0;
77
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030078 if (bus == pp->root_bus_nr && dev != 1)
Saeed Bishara651c74c2008-06-22 22:45:06 +020079 return 0;
80
81 return 1;
82}
83
84
85/*
86 * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
87 * and then reading the PCIE_CONF_DATA register. Need to make sure these
88 * transactions are atomic.
89 */
Saeed Bishara651c74c2008-06-22 22:45:06 +020090
91static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
92 int size, u32 *val)
93{
Russell King43ba9902012-03-10 13:31:34 +000094 struct pci_sys_data *sys = bus->sysdata;
95 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +020096 unsigned long flags;
97 int ret;
98
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030099 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200100 *val = 0xffffffff;
101 return PCIBIOS_DEVICE_NOT_FOUND;
102 }
103
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300104 spin_lock_irqsave(&pp->conf_lock, flags);
105 ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
106 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200107
108 return ret;
109}
110
111static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
112 int where, int size, u32 val)
113{
Russell King43ba9902012-03-10 13:31:34 +0000114 struct pci_sys_data *sys = bus->sysdata;
115 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200116 unsigned long flags;
117 int ret;
118
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300119 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200120 return PCIBIOS_DEVICE_NOT_FOUND;
121
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300122 spin_lock_irqsave(&pp->conf_lock, flags);
123 ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
124 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200125
126 return ret;
127}
128
129static struct pci_ops pcie_ops = {
130 .read = pcie_rd_conf,
131 .write = pcie_wr_conf,
132};
133
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400134static void __init pcie0_ioresources_init(struct pcie_port *pp)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200135{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200136 pp->base = PCIE_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400137 pp->irq = IRQ_KIRKWOOD_PCIE;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200138
139 /*
140 * IORESOURCE_IO
141 */
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300142 pp->res[0].name = "PCIe 0 I/O Space";
Arnaud Patarde4ff1c32010-08-22 22:49:46 +0200143 pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300144 pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
145 pp->res[0].flags = IORESOURCE_IO;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200146
147 /*
148 * IORESOURCE_MEM
149 */
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300150 pp->res[1].name = "PCIe 0 MEM";
151 pp->res[1].start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
152 pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE_MEM_SIZE - 1;
153 pp->res[1].flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300154}
155
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400156static void __init pcie1_ioresources_init(struct pcie_port *pp)
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300157{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200158 pp->base = PCIE1_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400159 pp->irq = IRQ_KIRKWOOD_PCIE1;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300160
161 /*
162 * IORESOURCE_IO
163 */
164 pp->res[0].name = "PCIe 1 I/O Space";
Arnaud Patarde4ff1c32010-08-22 22:49:46 +0200165 pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300166 pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
167 pp->res[0].flags = IORESOURCE_IO;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300168
169 /*
170 * IORESOURCE_MEM
171 */
172 pp->res[1].name = "PCIe 1 MEM";
173 pp->res[1].start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
174 pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
175 pp->res[1].flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300176}
177
178static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
179{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300180 struct pcie_port *pp;
181 int index;
182
183 if (nr >= num_pcie_ports)
184 return 0;
185
186 index = pcie_port_map[nr];
187 printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
188
189 pp = kzalloc(sizeof(*pp), GFP_KERNEL);
190 if (!pp)
191 panic("PCIe: failed to allocate pcie_port data");
192 sys->private_data = pp;
193 pp->root_bus_nr = sys->busnr;
194 spin_lock_init(&pp->conf_lock);
195
196 switch (index) {
197 case 0:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100198 kirkwood_enable_pcie_clk("0");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400199 pcie0_ioresources_init(pp);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300200 break;
201 case 1:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100202 kirkwood_enable_pcie_clk("1");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400203 pcie1_ioresources_init(pp);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300204 break;
205 default:
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400206 panic("PCIe setup: invalid controller %d", index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300207 }
208
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400209 if (request_resource(&ioport_resource, &pp->res[0]))
210 panic("Request PCIe%d IO resource failed\n", index);
211 if (request_resource(&iomem_resource, &pp->res[1]))
212 panic("Request PCIe%d Memory resource failed\n", index);
213
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400214 sys->io_offset = 0;
Bjorn Helgaas9f786d02012-02-23 20:19:01 -0700215 pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
216 pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400217
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300218 /*
219 * Generic PCIe unit setup.
220 */
221 orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
222
Andrew Lunn63a93322011-12-07 21:48:07 +0100223 orion_pcie_setup(pp->base);
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +0200224
Saeed Bishara651c74c2008-06-22 22:45:06 +0200225 return 1;
226}
227
228static void __devinit rc_pci_fixup(struct pci_dev *dev)
229{
230 /*
231 * Prevent enumeration of root complex.
232 */
233 if (dev->bus->parent == NULL && dev->devfn == 0) {
234 int i;
235
236 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
237 dev->resource[i].start = 0;
238 dev->resource[i].end = 0;
239 dev->resource[i].flags = 0;
240 }
241 }
242}
243DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
244
245static struct pci_bus __init *
246kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
247{
248 struct pci_bus *bus;
249
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300250 if (nr < num_pcie_ports) {
Bjorn Helgaas37d15902011-10-28 16:26:16 -0600251 bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
252 &sys->resources);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200253 } else {
254 bus = NULL;
255 BUG();
256 }
257
258 return bus;
259}
260
Ralf Baechled5341942011-06-10 15:30:21 +0100261static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
262 u8 pin)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200263{
Russell King43ba9902012-03-10 13:31:34 +0000264 struct pci_sys_data *sys = dev->sysdata;
265 struct pcie_port *pp = sys->private_data;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300266
267 return pp->irq;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200268}
269
270static struct hw_pci kirkwood_pci __initdata = {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200271 .setup = kirkwood_pcie_setup,
272 .scan = kirkwood_pcie_scan_bus,
273 .map_irq = kirkwood_pcie_map_irq,
274};
275
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200276static void __init add_pcie_port(int index, void __iomem *base)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200277{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300278 printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
279
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200280 if (orion_pcie_link_up(base)) {
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300281 printk(KERN_INFO "link up\n");
282 pcie_port_map[num_pcie_ports++] = index;
283 } else
284 printk(KERN_INFO "link down, ignoring\n");
285}
286
287void __init kirkwood_pcie_init(unsigned int portmask)
288{
Rob Herringcc22b4c2011-06-28 21:22:40 -0500289 vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
290
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300291 if (portmask & KW_PCIE0)
292 add_pcie_port(0, PCIE_VIRT_BASE);
293
294 if (portmask & KW_PCIE1)
295 add_pcie_port(1, PCIE1_VIRT_BASE);
296
297 kirkwood_pci.nr_controllers = num_pcie_ports;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200298 pci_common_init(&kirkwood_pci);
299}