blob: 12d86f39f3807b1f2d5ed0274dd9960fd763e8a8 [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
Thomas Petazzoni8baeeeb2013-07-26 10:17:40 -030023/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
24#define KIRKWOOD_MBUS_PCIE0_MEM_TARGET 0x4
25#define KIRKWOOD_MBUS_PCIE0_MEM_ATTR 0xe8
26#define KIRKWOOD_MBUS_PCIE0_IO_TARGET 0x4
27#define KIRKWOOD_MBUS_PCIE0_IO_ATTR 0xe0
28#define KIRKWOOD_MBUS_PCIE1_MEM_TARGET 0x4
29#define KIRKWOOD_MBUS_PCIE1_MEM_ATTR 0xd8
30#define KIRKWOOD_MBUS_PCIE1_IO_TARGET 0x4
31#define KIRKWOOD_MBUS_PCIE1_IO_ATTR 0xd0
32
Andrew Lunn27e53cf2012-03-08 21:45:59 +010033static void kirkwood_enable_pcie_clk(const char *port)
34{
35 struct clk *clk;
36
37 clk = clk_get_sys("pcie", port);
38 if (IS_ERR(clk)) {
Andrew Lunn98adf932012-10-20 13:23:16 +020039 pr_err("PCIE clock %s missing\n", port);
Andrew Lunn27e53cf2012-03-08 21:45:59 +010040 return;
41 }
42 clk_prepare_enable(clk);
43 clk_put(clk);
44}
45
46/* This function is called very early in the boot when probing the
47 hardware to determine what we actually are, and what rate tclk is
48 ticking at. Hence calling kirkwood_enable_pcie_clk() is not
49 possible since the clk tree has not been created yet. */
Eric Cooper0e0cdd32011-02-02 17:16:10 -050050void kirkwood_enable_pcie(void)
51{
52 u32 curr = readl(CLOCK_GATING_CTRL);
53 if (!(curr & CGC_PEX0))
54 writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
55}
56
Andrew Lunn98d99862012-04-11 21:07:45 +020057void kirkwood_pcie_id(u32 *dev, u32 *rev)
Ronen Shitritb2b3dc22008-09-15 10:40:35 +030058{
Eric Cooper0e0cdd32011-02-02 17:16:10 -050059 kirkwood_enable_pcie();
Thomas Petazzoni060f3d12012-09-11 14:27:19 +020060 *dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
61 *rev = orion_pcie_rev(PCIE_VIRT_BASE);
Ronen Shitritb2b3dc22008-09-15 10:40:35 +030062}
63
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030064struct pcie_port {
65 u8 root_bus_nr;
66 void __iomem *base;
67 spinlock_t conf_lock;
68 int irq;
Rob Herring2bb08082012-07-09 22:43:33 -050069 struct resource res;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030070};
71
72static int pcie_port_map[2];
73static int num_pcie_ports;
74
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030075static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +020076{
77 /*
78 * Don't go out when trying to access --
79 * 1. nonexisting device on local bus
80 * 2. where there's no device connected (no link)
81 */
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030082 if (bus == pp->root_bus_nr && dev == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +020083 return 1;
84
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030085 if (!orion_pcie_link_up(pp->base))
Saeed Bishara651c74c2008-06-22 22:45:06 +020086 return 0;
87
Saeed Bisharaffd58bd2010-06-08 14:21:34 +030088 if (bus == pp->root_bus_nr && dev != 1)
Saeed Bishara651c74c2008-06-22 22:45:06 +020089 return 0;
90
91 return 1;
92}
93
94
95/*
96 * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
97 * and then reading the PCIE_CONF_DATA register. Need to make sure these
98 * transactions are atomic.
99 */
Saeed Bishara651c74c2008-06-22 22:45:06 +0200100
101static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
102 int size, u32 *val)
103{
Russell King43ba9902012-03-10 13:31:34 +0000104 struct pci_sys_data *sys = bus->sysdata;
105 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200106 unsigned long flags;
107 int ret;
108
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300109 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
Saeed Bishara651c74c2008-06-22 22:45:06 +0200110 *val = 0xffffffff;
111 return PCIBIOS_DEVICE_NOT_FOUND;
112 }
113
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300114 spin_lock_irqsave(&pp->conf_lock, flags);
115 ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
116 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200117
118 return ret;
119}
120
121static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
122 int where, int size, u32 val)
123{
Russell King43ba9902012-03-10 13:31:34 +0000124 struct pci_sys_data *sys = bus->sysdata;
125 struct pcie_port *pp = sys->private_data;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200126 unsigned long flags;
127 int ret;
128
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300129 if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200130 return PCIBIOS_DEVICE_NOT_FOUND;
131
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300132 spin_lock_irqsave(&pp->conf_lock, flags);
133 ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
134 spin_unlock_irqrestore(&pp->conf_lock, flags);
Saeed Bishara651c74c2008-06-22 22:45:06 +0200135
136 return ret;
137}
138
139static struct pci_ops pcie_ops = {
140 .read = pcie_rd_conf,
141 .write = pcie_wr_conf,
142};
143
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400144static void __init pcie0_ioresources_init(struct pcie_port *pp)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200145{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200146 pp->base = PCIE_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400147 pp->irq = IRQ_KIRKWOOD_PCIE;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200148
149 /*
Saeed Bishara651c74c2008-06-22 22:45:06 +0200150 * IORESOURCE_MEM
151 */
Rob Herring2bb08082012-07-09 22:43:33 -0500152 pp->res.name = "PCIe 0 MEM";
153 pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
154 pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
155 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300156}
157
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400158static void __init pcie1_ioresources_init(struct pcie_port *pp)
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300159{
Thomas Petazzoni060f3d12012-09-11 14:27:19 +0200160 pp->base = PCIE1_VIRT_BASE;
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400161 pp->irq = IRQ_KIRKWOOD_PCIE1;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300162
163 /*
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300164 * IORESOURCE_MEM
165 */
Rob Herring2bb08082012-07-09 22:43:33 -0500166 pp->res.name = "PCIe 1 MEM";
167 pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
168 pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
169 pp->res.flags = IORESOURCE_MEM;
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300170}
171
172static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
173{
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300174 struct pcie_port *pp;
175 int index;
176
177 if (nr >= num_pcie_ports)
178 return 0;
179
180 index = pcie_port_map[nr];
Andrew Lunn98adf932012-10-20 13:23:16 +0200181 pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300182
183 pp = kzalloc(sizeof(*pp), GFP_KERNEL);
184 if (!pp)
185 panic("PCIe: failed to allocate pcie_port data");
186 sys->private_data = pp;
187 pp->root_bus_nr = sys->busnr;
188 spin_lock_init(&pp->conf_lock);
189
190 switch (index) {
191 case 0:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100192 kirkwood_enable_pcie_clk("0");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400193 pcie0_ioresources_init(pp);
Rob Herring2bb08082012-07-09 22:43:33 -0500194 pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300195 break;
196 case 1:
Andrew Lunn27e53cf2012-03-08 21:45:59 +0100197 kirkwood_enable_pcie_clk("1");
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400198 pcie1_ioresources_init(pp);
Andrew Lunn98adf932012-10-20 13:23:16 +0200199 pci_ioremap_io(SZ_64K * sys->busnr,
200 KIRKWOOD_PCIE1_IO_PHYS_BASE);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300201 break;
202 default:
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400203 panic("PCIe setup: invalid controller %d", index);
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300204 }
205
Rob Herring2bb08082012-07-09 22:43:33 -0500206 if (request_resource(&iomem_resource, &pp->res))
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400207 panic("Request PCIe%d Memory resource failed\n", index);
208
Rob Herring2bb08082012-07-09 22:43:33 -0500209 pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
Nicolas Pitrea87182b2010-07-05 13:59:56 -0400210
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300211 /*
212 * Generic PCIe unit setup.
213 */
214 orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
215
Andrew Lunn63a93322011-12-07 21:48:07 +0100216 orion_pcie_setup(pp->base);
Rabeeh Khourye8b2b7b2009-03-22 17:30:32 +0200217
Saeed Bishara651c74c2008-06-22 22:45:06 +0200218 return 1;
219}
220
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700221/*
222 * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
223 * is operating as a root complex this needs to be switched to
224 * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
225 * the device. Decoding setup is handled by the orion code.
226 */
Greg Kroah-Hartman351a1022012-12-21 14:02:24 -0800227static void rc_pci_fixup(struct pci_dev *dev)
Saeed Bishara651c74c2008-06-22 22:45:06 +0200228{
Saeed Bishara651c74c2008-06-22 22:45:06 +0200229 if (dev->bus->parent == NULL && dev->devfn == 0) {
230 int i;
231
Jason Gunthorpe1dc831b2012-11-21 00:19:06 -0700232 dev->class &= 0xff;
233 dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200234 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
235 dev->resource[i].start = 0;
236 dev->resource[i].end = 0;
237 dev->resource[i].flags = 0;
238 }
239 }
240}
241DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
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,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200254 .map_irq = kirkwood_pcie_map_irq,
Jason Gunthorpe4a9329a2012-11-21 00:15:11 -0700255 .ops = &pcie_ops,
Saeed Bishara651c74c2008-06-22 22:45:06 +0200256};
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{
Jason Gunthorpeb73690c2012-11-21 11:25:28 -0700260 pcie_port_map[num_pcie_ports++] = index;
261 pr_info("Kirkwood PCIe port %d: link %s\n", index,
262 orion_pcie_link_up(base) ? "up" : "down");
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300263}
264
265void __init kirkwood_pcie_init(unsigned int portmask)
266{
Thomas Petazzoni8baeeeb2013-07-26 10:17:40 -0300267 mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE0_IO_TARGET,
268 KIRKWOOD_MBUS_PCIE0_IO_ATTR,
Thomas Petazzoni5afb9fe2013-05-15 15:36:55 +0200269 KIRKWOOD_PCIE_IO_PHYS_BASE,
270 KIRKWOOD_PCIE_IO_SIZE,
Thomas Petazzoni8baeeeb2013-07-26 10:17:40 -0300271 KIRKWOOD_PCIE_IO_BUS_BASE);
272 mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE0_MEM_TARGET,
273 KIRKWOOD_MBUS_PCIE0_MEM_ATTR,
274 KIRKWOOD_PCIE_MEM_PHYS_BASE,
275 KIRKWOOD_PCIE_MEM_SIZE);
276 mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE1_IO_TARGET,
277 KIRKWOOD_MBUS_PCIE1_IO_ATTR,
Thomas Petazzoni5afb9fe2013-05-15 15:36:55 +0200278 KIRKWOOD_PCIE1_IO_PHYS_BASE,
279 KIRKWOOD_PCIE1_IO_SIZE,
Thomas Petazzoni8baeeeb2013-07-26 10:17:40 -0300280 KIRKWOOD_PCIE1_IO_BUS_BASE);
281 mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE1_MEM_TARGET,
282 KIRKWOOD_MBUS_PCIE1_MEM_ATTR,
283 KIRKWOOD_PCIE1_MEM_PHYS_BASE,
284 KIRKWOOD_PCIE1_MEM_SIZE);
Thomas Petazzoni5afb9fe2013-05-15 15:36:55 +0200285
Rob Herringcc22b4c2011-06-28 21:22:40 -0500286 vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
287
Saeed Bisharaffd58bd2010-06-08 14:21:34 +0300288 if (portmask & KW_PCIE0)
289 add_pcie_port(0, PCIE_VIRT_BASE);
290
291 if (portmask & KW_PCIE1)
292 add_pcie_port(1, PCIE1_VIRT_BASE);
293
294 kirkwood_pci.nr_controllers = num_pcie_ports;
Saeed Bishara651c74c2008-06-22 22:45:06 +0200295 pci_common_init(&kirkwood_pci);
296}