blob: ddcb09f5bdd38403423f2123c329149b74848fd5 [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>
Thomas Petazzoni5afb9fe2013-05-15 15:36:55 +020015#include <linux/mbus.h>
Rob Herringcc22b4c2011-06-28 21:22:40 -050016#include <video/vga.h>
Nicolas Pitre6e5c11a2009-01-07 04:47:02 +010017#include <asm/irq.h>
Saeed Bishara651c74c2008-06-22 22:45:06 +020018#include <asm/mach/pci.h>
Lennert Buytenhek6f088f12008-08-09 13:44:58 +020019#include <plat/pcie.h>
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +020020#include <mach/bridge-regs.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)) {
Andrew Lunn98adf932012-10-20 13:23:16 +020029 pr_err("PCIE clock %s missing\n", port);
Andrew Lunn27e53cf2012-03-08 21:45:59 +010030 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];
Andrew Lunn98adf932012-10-20 13:23:16 +0200171 pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300172
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);
Andrew Lunn98adf932012-10-20 13:23:16 +0200189 pci_ioremap_io(SZ_64K * sys->busnr,
190 KIRKWOOD_PCIE1_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300191 break;
192 default:
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400193 panic("PCIe setup: invalid controller %d", index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300194 }
195
Rob Herring2bb08082012-07-09 22:43:33 -0500196 if (request_resource(&iomem_resource, &pp->res))
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400197 panic("Request PCIe%d Memory resource failed\n", index);
198
Rob Herring2bb08082012-07-09 22:43:33 -0500199 pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400200
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300201 /*
202 * Generic PCIe unit setup.
203 */
204 orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
205
Andrew Lunn63a93322011-12-07 21:48:07 +0100206 orion_pcie_setup(pp->base);
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +0200207
Saeed Bishara651c74c2008-06-22 22:45:06 +0200208 return 1;
209}
210
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700211/*
212 * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
213 * is operating as a root complex this needs to be switched to
214 * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
215 * the device. Decoding setup is handled by the orion code.
216 */
Greg Kroah-Hartman351a1022012-12-21 14:02:24 -0800217static void rc_pci_fixup(struct pci_dev *dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200218{
Saeed Bishara651c74c2008-06-22 22:45:06 +0200219 if (dev->bus->parent == NULL && dev->devfn == 0) {
220 int i;
221
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700222 dev->class &= 0xff;
223 dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200224 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
225 dev->resource[i].start = 0;
226 dev->resource[i].end = 0;
227 dev->resource[i].flags = 0;
228 }
229 }
230}
231DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
232
Ralf Baechled5341942011-06-10 15:30:21 +0100233static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
234 u8 pin)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200235{
Russell King43ba9902012-03-10 13:31:34 +0000236 struct pci_sys_data *sys = dev->sysdata;
237 struct pcie_port *pp = sys->private_data;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300238
239 return pp->irq;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200240}
241
242static struct hw_pci kirkwood_pci __initdata = {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200243 .setup = kirkwood_pcie_setup,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200244 .map_irq = kirkwood_pcie_map_irq,
Jason Gunthorpe4a9329a2012-11-21 00:15:11 -0700245 .ops = &pcie_ops,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200246};
247
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200248static void __init add_pcie_port(int index, void __iomem *base)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200249{
Jason Gunthorpeb73690c2012-11-21 11:25:28 -0700250 pcie_port_map[num_pcie_ports++] = index;
251 pr_info("Kirkwood PCIe port %d: link %s\n", index,
252 orion_pcie_link_up(base) ? "up" : "down");
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300253}
254
255void __init kirkwood_pcie_init(unsigned int portmask)
256{
Thomas Petazzoni5afb9fe2013-05-15 15:36:55 +0200257 mvebu_mbus_add_window_remap_flags("pcie0.0",
258 KIRKWOOD_PCIE_IO_PHYS_BASE,
259 KIRKWOOD_PCIE_IO_SIZE,
260 KIRKWOOD_PCIE_IO_BUS_BASE,
261 MVEBU_MBUS_PCI_IO);
262 mvebu_mbus_add_window_remap_flags("pcie0.0",
263 KIRKWOOD_PCIE_MEM_PHYS_BASE,
264 KIRKWOOD_PCIE_MEM_SIZE,
265 MVEBU_MBUS_NO_REMAP,
266 MVEBU_MBUS_PCI_MEM);
267 mvebu_mbus_add_window_remap_flags("pcie1.0",
268 KIRKWOOD_PCIE1_IO_PHYS_BASE,
269 KIRKWOOD_PCIE1_IO_SIZE,
270 KIRKWOOD_PCIE1_IO_BUS_BASE,
271 MVEBU_MBUS_PCI_IO);
272 mvebu_mbus_add_window_remap_flags("pcie1.0",
273 KIRKWOOD_PCIE1_MEM_PHYS_BASE,
274 KIRKWOOD_PCIE1_MEM_SIZE,
275 MVEBU_MBUS_NO_REMAP,
276 MVEBU_MBUS_PCI_MEM);
277
Rob Herringcc22b4c2011-06-28 21:22:40 -0500278 vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
279
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300280 if (portmask & KW_PCIE0)
281 add_pcie_port(0, PCIE_VIRT_BASE);
282
283 if (portmask & KW_PCIE1)
284 add_pcie_port(1, PCIE1_VIRT_BASE);
285
286 kirkwood_pci.nr_controllers = num_pcie_ports;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200287 pci_common_init(&kirkwood_pci);
288}