kernel: update linux 3.8 to 3.8.2
[openwrt.git] / target / linux / mvebu / patches-3.8 / 035-arm_mvebu_the_core_pcie_driver.patch
1 This driver implements the hw_pci operations needed by the core ARM
2 PCI code to setup PCI devices and get their corresponding IRQs, and
3 the pci_ops operations that are used by the PCI core to read/write the
4 configuration space of PCI devices.
5
6 In addition, this driver enumerates the different PCIe slots, and for
7 those having a device plugged in, it allocates the necessary address
8 decoding windows, using the new armada_370_xp_alloc_pcie_window()
9 function from mach-mvebu/addr-map.c.
10
11 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
12 ---
13  .../devicetree/bindings/pci/armada-370-xp-pcie.txt |  136 +++++++++
14  arch/arm/mach-mvebu/Makefile                       |    1 +
15  arch/arm/mach-mvebu/pcie.c                         |  306 ++++++++++++++++++++
16  3 files changed, 443 insertions(+)
17  create mode 100644 Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
18  create mode 100644 arch/arm/mach-mvebu/pcie.c
19
20 --- /dev/null
21 +++ b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
22 @@ -0,0 +1,136 @@
23 +* Marvell Armada 370/XP PCIe interfaces
24 +
25 +Mandatory properties:
26 +- compatible: must be "marvell,armada-370-xp-pcie"
27 +- status: either "disabled" or "okay"
28 +- #address-cells, set to <1>
29 +- #size-cells, set to <1>
30 +- ranges: describes the association between the physical addresses of
31 +  the PCIe registers for each PCIe interface with "virtual" addresses
32 +  as seen by the sub-nodes. One entry per PCIe interface. Each entry
33 +  must have 3 values: the "virtual" address seen by the sub-nodes, the
34 +  real physical address of the PCIe registers, and the size.
35 +
36 +In addition, the Device Tree node must have sub-nodes describing each
37 +PCIe interface, having the following mandatory properties:
38 +- reg: the address and size of the PCIe registers (translated
39 +  addresses according to the ranges property of the parent)
40 +- interrupts: the interrupt number of this PCIe interface
41 +- clocks: the clock associated to this PCIe interface
42 +- marvell,pcie-port: the physical PCIe port number
43 +- status: either "disabled" or "okay"
44 +
45 +and the following optional properties:
46 +- marvell,pcie-lane: the physical PCIe lane number, for ports having
47 +  multiple lanes. If this property is not found, we assume that the
48 +  value is 0.
49 +
50 +Example:
51 +
52 +pcie-controller {
53 +       compatible = "marvell,armada-370-xp-pcie";
54 +       status = "disabled";
55 +       #address-cells = <1>;
56 +       #size-cells = <1>;
57 +       ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */
58 +                 0x2000  0xd0042000 0x2000 /* port2x1_port0 */
59 +                 0x4000  0xd0044000 0x2000 /* port0x1_port1 */
60 +                 0x8000  0xd0048000 0x2000 /* port0x1_port2 */
61 +                 0xC000  0xd004C000 0x2000 /* port0x1_port3 */
62 +                 0x10000 0xd0080000 0x2000 /* port1x1_port0 */
63 +                 0x12000 0xd0082000 0x2000 /* port3x1_port0 */
64 +                 0x14000 0xd0084000 0x2000 /* port1x1_port1 */
65 +                 0x18000 0xd0088000 0x2000 /* port1x1_port2 */
66 +                 0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>;
67 +
68 +       pcie0.0@0xd0040000 {
69 +               reg = <0x0 0x2000>;
70 +               interrupts = <58>;
71 +               clocks = <&gateclk 5>;
72 +               marvell,pcie-port = <0>;
73 +               marvell,pcie-lane = <0>;
74 +               status = "disabled";
75 +       };
76 +
77 +       pcie0.1@0xd0044000 {
78 +               reg = <0x4000 0x2000>;
79 +               interrupts = <59>;
80 +               clocks = <&gateclk 5>;
81 +               marvell,pcie-port = <0>;
82 +               marvell,pcie-lane = <1>;
83 +               status = "disabled";
84 +       };
85 +
86 +       pcie0.2@0xd0048000 {
87 +               reg = <0x8000 0x2000>;
88 +               interrupts = <60>;
89 +               clocks = <&gateclk 5>;
90 +               marvell,pcie-port = <0>;
91 +               marvell,pcie-lane = <2>;
92 +               status = "disabled";
93 +       };
94 +
95 +       pcie0.3@0xd004C000 {
96 +               reg = <0xC000 0x2000>;
97 +               interrupts = <61>;
98 +               clocks = <&gateclk 5>;
99 +               marvell,pcie-port = <0>;
100 +               marvell,pcie-lane = <3>;
101 +               status = "disabled";
102 +       };
103 +
104 +       pcie1.0@0xd0040000 {
105 +               reg = <0x10000 0x2000>;
106 +               interrupts = <62>;
107 +               clocks = <&gateclk 6>;
108 +               marvell,pcie-port = <1>;
109 +               marvell,pcie-lane = <0>;
110 +               status = "disabled";
111 +       };
112 +
113 +       pcie1.1@0xd0044000 {
114 +               reg = <0x14000 0x2000>;
115 +               interrupts = <63>;
116 +               clocks = <&gateclk 6>;
117 +               marvell,pcie-port = <1>;
118 +               marvell,pcie-lane = <1>;
119 +               status = "disabled";
120 +       };
121 +
122 +       pcie1.2@0xd0048000 {
123 +               reg = <0x18000 0x2000>;
124 +               interrupts = <64>;
125 +               clocks = <&gateclk 6>;
126 +               marvell,pcie-port = <1>;
127 +               marvell,pcie-lane = <2>;
128 +               status = "disabled";
129 +       };
130 +
131 +       pcie1.3@0xd004C000 {
132 +               reg = <0x1C000 0x2000>;
133 +               interrupts = <65>;
134 +               clocks = <&gateclk 6>;
135 +               marvell,pcie-port = <1>;
136 +               marvell,pcie-lane = <3>;
137 +               status = "disabled";
138 +       };
139 +
140 +       pcie2@0xd0042000 {
141 +               reg = <0x2000 0x2000>;
142 +               interrupts = <99>;
143 +               clocks = <&gateclk 7>;
144 +               marvell,pcie-port = <2>;
145 +               marvell,pcie-lane = <0>;
146 +               status = "disabled";
147 +       };
148 +
149 +       pcie3@0xd0082000 {
150 +               reg = <0x12000 0x2000>;
151 +               interrupts = <103>;
152 +               clocks = <&gateclk 8>;
153 +               marvell,pcie-port = <3>;
154 +               marvell,pcie-lane = <0>;
155 +               status = "disabled";
156 +       };
157 +};
158 +
159 --- a/arch/arm/mach-mvebu/Makefile
160 +++ b/arch/arm/mach-mvebu/Makefile
161 @@ -7,3 +7,4 @@ obj-y += system-controller.o
162  obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
163  obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
164  obj-$(CONFIG_HOTPLUG_CPU)        += hotplug.o
165 +obj-$(CONFIG_PCI)               += pcie.o
166 --- /dev/null
167 +++ b/arch/arm/mach-mvebu/pcie.c
168 @@ -0,0 +1,306 @@
169 +/*
170 + * PCIe driver for Marvell Armada 370 and Armada XP SoCs
171 + *
172 + * This file is licensed under the terms of the GNU General Public
173 + * License version 2.  This program is licensed "as is" without any
174 + * warranty of any kind, whether express or implied.
175 + */
176 +
177 +#include <linux/kernel.h>
178 +#include <linux/pci.h>
179 +#include <linux/clk.h>
180 +#include <linux/module.h>
181 +#include <linux/slab.h>
182 +#include <linux/platform_device.h>
183 +#include <linux/of_address.h>
184 +#include <linux/of_pci.h>
185 +#include <linux/of_irq.h>
186 +#include <linux/of_platform.h>
187 +#include <plat/pcie.h>
188 +#include "common.h"
189 +
190 +struct pcie_port {
191 +       u8                root_bus_nr;
192 +       void __iomem     *base;
193 +       spinlock_t        conf_lock;
194 +       int               irq;
195 +       struct resource   res;
196 +       int               haslink;
197 +       u32               port;
198 +       u32               lane;
199 +       struct clk       *clk;
200 +};
201 +
202 +static struct pcie_port *pcie_ports;
203 +
204 +static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
205 +{
206 +       /*
207 +        * Don't go out when trying to access --
208 +        * 1. nonexisting device on local bus
209 +        * 2. where there's no device connected (no link)
210 +        */
211 +       if (bus == pp->root_bus_nr && dev == 0)
212 +               return 1;
213 +
214 +       if (!orion_pcie_link_up(pp->base))
215 +               return 0;
216 +
217 +       if (bus == pp->root_bus_nr && dev != 1)
218 +               return 0;
219 +
220 +       return 1;
221 +}
222 +
223 +/*
224 + * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
225 + * and then reading the PCIE_CONF_DATA register. Need to make sure these
226 + * transactions are atomic.
227 + */
228 +static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
229 +                       int size, u32 *val)
230 +{
231 +       struct pci_sys_data *sys = bus->sysdata;
232 +       struct pcie_port *pp = sys->private_data;
233 +       unsigned long flags;
234 +       int ret;
235 +
236 +       if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
237 +               *val = 0xffffffff;
238 +               return PCIBIOS_DEVICE_NOT_FOUND;
239 +       }
240 +
241 +       spin_lock_irqsave(&pp->conf_lock, flags);
242 +       ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
243 +       spin_unlock_irqrestore(&pp->conf_lock, flags);
244 +
245 +       return ret;
246 +}
247 +
248 +static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
249 +                       int where, int size, u32 val)
250 +{
251 +       struct pci_sys_data *sys = bus->sysdata;
252 +       struct pcie_port *pp = sys->private_data;
253 +       unsigned long flags;
254 +       int ret;
255 +
256 +       if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
257 +               return PCIBIOS_DEVICE_NOT_FOUND;
258 +
259 +       spin_lock_irqsave(&pp->conf_lock, flags);
260 +       ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
261 +       spin_unlock_irqrestore(&pp->conf_lock, flags);
262 +
263 +       return ret;
264 +}
265 +
266 +static struct pci_ops pcie_ops = {
267 +       .read = pcie_rd_conf,
268 +       .write = pcie_wr_conf,
269 +};
270 +
271 +/*
272 + * Returns 0 when the device could not be initialized, 1 when
273 + * initialization is successful
274 + */
275 +static int __init armada_370_xp_pcie_setup(int nr, struct pci_sys_data *sys)
276 +{
277 +       struct pcie_port *port = &pcie_ports[nr];
278 +       unsigned long membase, iobase;
279 +       int ret;
280 +
281 +       if (!port->haslink)
282 +               return 0;
283 +
284 +       sys->private_data = port;
285 +       port->root_bus_nr = sys->busnr;
286 +       spin_lock_init(&port->conf_lock);
287 +
288 +       ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
289 +                                             IORESOURCE_MEM, SZ_64M, &membase);
290 +       if (ret) {
291 +               pr_err("PCIe%d.%d: Cannot get memory window, device disabled\n",
292 +                      port->port, port->lane);
293 +               return 0;
294 +       }
295 +
296 +       ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
297 +                                             IORESOURCE_IO, SZ_64K, &iobase);
298 +       if (ret) {
299 +               pr_err("PCIe%d.%d: Cannot get I/O window, device disabled\n",
300 +                      port->port, port->lane);
301 +               armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
302 +               return 0;
303 +       }
304 +
305 +       port->res.name = kasprintf(GFP_KERNEL, "PCIe %d.%d MEM",
306 +                                  port->port, port->lane);
307 +       if (!port->res.name) {
308 +               armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K);
309 +               armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
310 +               return 0;
311 +       }
312 +
313 +       port->res.start = membase;
314 +       port->res.end = membase + SZ_32M - 1;
315 +       port->res.flags = IORESOURCE_MEM;
316 +
317 +       pci_ioremap_io(SZ_64K * sys->busnr, iobase);
318 +
319 +       if (request_resource(&iomem_resource, &port->res)) {
320 +               pr_err("PCIe%d.%d: Cannot request memory resource\n",
321 +                      port->port, port->lane);
322 +               kfree(port->res.name);
323 +               armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K);
324 +               armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
325 +               return 0;
326 +       }
327 +
328 +       pci_add_resource_offset(&sys->resources, &port->res, sys->mem_offset);
329 +
330 +       orion_pcie_set_local_bus_nr(port->base, sys->busnr);
331 +       orion_pcie_setup(port->base);
332 +
333 +       return 1;
334 +}
335 +
336 +static void rc_pci_fixup(struct pci_dev *dev)
337 +{
338 +       /*
339 +        * Prevent enumeration of root complex.
340 +        */
341 +       if (dev->bus->parent == NULL && dev->devfn == 0) {
342 +               int i;
343 +
344 +               for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
345 +                       dev->resource[i].start = 0;
346 +                       dev->resource[i].end   = 0;
347 +                       dev->resource[i].flags = 0;
348 +               }
349 +       }
350 +}
351 +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
352 +
353 +static int __init armada_370_xp_pcie_map_irq(const struct pci_dev *dev, u8 slot,
354 +                                            u8 pin)
355 +{
356 +       struct pci_sys_data *sys = dev->sysdata;
357 +       struct pcie_port *port = sys->private_data;
358 +
359 +       return port->irq;
360 +}
361 +
362 +static struct hw_pci armada_370_xp_pci __initdata = {
363 +       .setup          = armada_370_xp_pcie_setup,
364 +       .map_irq        = armada_370_xp_pcie_map_irq,
365 +       .ops            = &pcie_ops,
366 +};
367 +
368 +static int __init armada_370_xp_pcie_probe(struct platform_device *pdev)
369 +{
370 +       struct device_node *child;
371 +       int nports, i;
372 +
373 +       nports = 0;
374 +       for_each_child_of_node(pdev->dev.of_node, child) {
375 +               if (!of_device_is_available(child))
376 +                       continue;
377 +               nports++;
378 +       }
379 +
380 +       pcie_ports = devm_kzalloc(&pdev->dev, nports * sizeof(*pcie_ports),
381 +                                 GFP_KERNEL);
382 +       if (!pcie_ports)
383 +               return -ENOMEM;
384 +
385 +       i = 0;
386 +       for_each_child_of_node(pdev->dev.of_node, child) {
387 +               struct pcie_port *port = &pcie_ports[i];
388 +
389 +               if (!of_device_is_available(child))
390 +                       continue;
391 +
392 +               if (of_property_read_u32(child, "marvell,pcie-port",
393 +                                        &port->port))
394 +                       continue;
395 +
396 +               if (of_property_read_u32(child, "marvell,pcie-lane",
397 +                                        &port->lane))
398 +                       port->lane = 0;
399 +
400 +               port->base = of_iomap(child, 0);
401 +               if (!port->base) {
402 +                       dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
403 +                               port->port, port->lane);
404 +                       continue;
405 +               }
406 +
407 +               if (orion_pcie_link_up(port->base)) {
408 +                       port->haslink = 1;
409 +                       dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
410 +                                port->port, port->lane);
411 +               } else {
412 +                       port->haslink = 0;
413 +                       dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
414 +                                port->port, port->lane);
415 +                       iounmap(port->base);
416 +                       continue;
417 +               }
418 +
419 +               port->irq = irq_of_parse_and_map(child, 0);
420 +               if (port->irq == 0) {
421 +                       dev_err(&pdev->dev, "PCIe%d.%d: cannot parse and map IRQ\n",
422 +                               port->port, port->lane);
423 +                       iounmap(port->base);
424 +                       port->haslink = 0;
425 +                       continue;
426 +               }
427 +
428 +               port->clk = of_clk_get_by_name(child, NULL);
429 +               if (!port->clk) {
430 +                       dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
431 +                              port->port, port->lane);
432 +                       irq_dispose_mapping(port->irq);
433 +                       iounmap(port->base);
434 +                       port->haslink = 0;
435 +                       continue;
436 +               }
437 +
438 +               clk_prepare_enable(port->clk);
439 +
440 +               i++;
441 +       }
442 +
443 +       armada_370_xp_pci.nr_controllers = nports;
444 +       pci_common_init(&armada_370_xp_pci);
445 +
446 +       return 0;
447 +}
448 +
449 +static const struct of_device_id armada_370_xp_pcie_of_match_table[] = {
450 +       { .compatible = "marvell,armada-370-xp-pcie", },
451 +       {},
452 +};
453 +MODULE_DEVICE_TABLE(of, armada_370_xp_pcie_of_match_table);
454 +
455 +static struct platform_driver armada_370_xp_pcie_driver = {
456 +       .driver = {
457 +               .owner = THIS_MODULE,
458 +               .name = "armada-370-xp-pcie",
459 +               .of_match_table =
460 +                  of_match_ptr(armada_370_xp_pcie_of_match_table),
461 +       },
462 +};
463 +
464 +static int armada_370_xp_pcie_init(void)
465 +{
466 +       return platform_driver_probe(&armada_370_xp_pcie_driver,
467 +                                    armada_370_xp_pcie_probe);
468 +}
469 +
470 +subsys_initcall(armada_370_xp_pcie_init);
471 +
472 +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
473 +MODULE_DESCRIPTION("Marvell Armada 370/XP PCIe driver");
474 +MODULE_LICENSE("GPL");