blob: ec544918b12c057b56109c1e688a217bf9ac5750 [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 Shitritb2b3dc22008-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 Shitritb2b3dc22008-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;
Rob Herring2bb08082012-07-09 22:43:33 -050059 struct resource res;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030060};
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 /*
Saeed Bishara651c74c2008-06-22 22:45:06 +0200140 * IORESOURCE_MEM
141 */
Rob Herring2bb08082012-07-09 22:43:33 -0500142 pp->res.name = "PCIe 0 MEM";
143 pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
144 pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
145 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300146}
147
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400148static void __init pcie1_ioresources_init(struct pcie_port *pp)
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300149{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200150 pp->base = PCIE1_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400151 pp->irq = IRQ_KIRKWOOD_PCIE1;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300152
153 /*
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300154 * IORESOURCE_MEM
155 */
Rob Herring2bb08082012-07-09 22:43:33 -0500156 pp->res.name = "PCIe 1 MEM";
157 pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
158 pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
159 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300160}
161
162static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
163{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300164 struct pcie_port *pp;
165 int index;
166
167 if (nr >= num_pcie_ports)
168 return 0;
169
170 index = pcie_port_map[nr];
171 printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
172
173 pp = kzalloc(sizeof(*pp), GFP_KERNEL);
174 if (!pp)
175 panic("PCIe: failed to allocate pcie_port data");
176 sys->private_data = pp;
177 pp->root_bus_nr = sys->busnr;
178 spin_lock_init(&pp->conf_lock);
179
180 switch (index) {
181 case 0:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100182 kirkwood_enable_pcie_clk("0");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400183 pcie0_ioresources_init(pp);
Rob Herring2bb08082012-07-09 22:43:33 -0500184 pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300185 break;
186 case 1:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100187 kirkwood_enable_pcie_clk("1");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400188 pcie1_ioresources_init(pp);
Rob Herring2bb08082012-07-09 22:43:33 -0500189 pci_ioremap_io(SZ_64K * sys->busnr, 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
210static void __devinit rc_pci_fixup(struct pci_dev *dev)
211{
212 /*
213 * Prevent enumeration of root complex.
214 */
215 if (dev->bus->parent == NULL && dev->devfn == 0) {
216 int i;
217
218 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
219 dev->resource[i].start = 0;
220 dev->resource[i].end = 0;
221 dev->resource[i].flags = 0;
222 }
223 }
224}
225DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
226
227static struct pci_bus __init *
228kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
229{
230 struct pci_bus *bus;
231
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300232 if (nr < num_pcie_ports) {
Bjorn Helgaas37d15902011-10-28 16:26:16 -0600233 bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
234 &sys->resources);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200235 } else {
236 bus = NULL;
237 BUG();
238 }
239
240 return bus;
241}
242
Ralf Baechled5341942011-06-10 15:30:21 +0100243static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
244 u8 pin)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200245{
Russell King43ba9902012-03-10 13:31:34 +0000246 struct pci_sys_data *sys = dev->sysdata;
247 struct pcie_port *pp = sys->private_data;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300248
249 return pp->irq;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200250}
251
252static struct hw_pci kirkwood_pci __initdata = {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200253 .setup = kirkwood_pcie_setup,
254 .scan = kirkwood_pcie_scan_bus,
255 .map_irq = kirkwood_pcie_map_irq,
256};
257
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200258static void __init add_pcie_port(int index, void __iomem *base)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200259{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300260 printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
261
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200262 if (orion_pcie_link_up(base)) {
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300263 printk(KERN_INFO "link up\n");
264 pcie_port_map[num_pcie_ports++] = index;
265 } else
266 printk(KERN_INFO "link down, ignoring\n");
267}
268
269void __init kirkwood_pcie_init(unsigned int portmask)
270{
Rob Herringcc22b4c2011-06-28 21:22:40 -0500271 vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
272
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300273 if (portmask & KW_PCIE0)
274 add_pcie_port(0, PCIE_VIRT_BASE);
275
276 if (portmask & KW_PCIE1)
277 add_pcie_port(1, PCIE1_VIRT_BASE);
278
279 kirkwood_pci.nr_controllers = num_pcie_ports;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200280 pci_common_init(&kirkwood_pci);
281}