brcm47xx/bcm53xx: improve description
[openwrt.git] / target / linux / bcm53xx / patches-3.14 / 170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
1 From 7475eee716d11f487076f78f26a6e403c06d0c76 Mon Sep 17 00:00:00 2001
2 From: Hauke Mehrtens <hauke@hauke-m.de>
3 Date: Mon, 12 May 2014 11:55:20 +0200
4 Subject: [PATCH 14/15] pcie2-bcma: add new PCIe2 driver for bcma
5
6 This driver supports the PCIe controller found on the BCM4708 and
7 similar SoCs. The controller itself is automatically detected by bcma.
8
9 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10 ---
11  arch/arm/mach-bcm/Kconfig     |   1 +
12  drivers/pci/host/Kconfig      |   7 +
13  drivers/pci/host/Makefile     |   1 +
14  drivers/pci/host/pcie2-bcma.c | 594 ++++++++++++++++++++++++++++++++++++++++++
15  4 files changed, 603 insertions(+)
16  create mode 100644 drivers/pci/host/pcie2-bcma.c
17
18 --- a/arch/arm/mach-bcm/Kconfig
19 +++ b/arch/arm/mach-bcm/Kconfig
20 @@ -45,6 +45,7 @@ config ARCH_BCM_5301X
21         select ARM_GLOBAL_TIMER
22         select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
23         select MIGHT_HAVE_PCI
24 +       select PCI_DOMAINS if PCI
25         help
26           Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
27  
28 --- a/drivers/pci/host/Kconfig
29 +++ b/drivers/pci/host/Kconfig
30 @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2
31           There are 3 internal PCI controllers available with a single
32           built-in EHCI/OHCI host controller present on each one.
33  
34 +config PCI_BCMA
35 +       bool "BCMA PCIe2 host controller"
36 +       depends on BCMA && OF
37 +       help
38 +         Say Y here if you want to support a simple generic PCI host
39 +         controller, such as the one emulated by kvmtool.
40 +
41  endmenu
42 --- a/drivers/pci/host/Makefile
43 +++ b/drivers/pci/host/Makefile
44 @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
45  obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
46  obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
47  obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
48 +obj-$(CONFIG_PCI_BCMA) += pcie2-bcma.o
49 --- /dev/null
50 +++ b/drivers/pci/host/pcie2-bcma.c
51 @@ -0,0 +1,594 @@
52 +/*
53 + * Northstar PCI-Express driver
54 + * Only supports Root-Complex (RC) mode
55 + *
56 + * Notes:
57 + * PCI Domains are being used to identify the PCIe port 1:1.
58 + *
59 + * Only MEM access is supported, PAX does not support IO.
60 + *
61 + * TODO:
62 + *     MSI interrupts,
63 + *     DRAM > 128 MBytes (e.g. DMA zones)
64 + */
65 +
66 +#include <linux/kernel.h>
67 +#include <linux/module.h>
68 +#include <linux/bug.h>
69 +#include <linux/delay.h>
70 +#include <linux/pci.h>
71 +#include <linux/io.h>
72 +#include <linux/ioport.h>
73 +#include <linux/interrupt.h>
74 +#include <linux/bcma/bcma.h>
75 +
76 +#define SI_ENUM_BASE           0x18000000      /* Enumeration space base */
77 +
78 +/*
79 + * Register offset definitions
80 + */
81 +#define        SOC_PCIE_CONTROL        0x000   /* a.k.a. CLK_CONTROL reg */
82 +#define        SOC_PCIE_PM_STATUS      0x008
83 +#define        SOC_PCIE_PM_CONTROL     0x00c   /* in EP mode only ! */
84 +
85 +#define        SOC_PCIE_EXT_CFG_ADDR   0x120
86 +#define        SOC_PCIE_EXT_CFG_DATA   0x124
87 +#define        SOC_PCIE_CFG_ADDR       0x1f8
88 +#define        SOC_PCIE_CFG_DATA       0x1fc
89 +
90 +#define        SOC_PCIE_SYS_RC_INTX_EN         0x330
91 +#define        SOC_PCIE_SYS_RC_INTX_CSR        0x334
92 +#define        SOC_PCIE_SYS_HOST_INTR_EN       0x344
93 +#define        SOC_PCIE_SYS_HOST_INTR_CSR      0x348
94 +
95 +#define        SOC_PCIE_HDR_OFF        0x400   /* 256 bytes per function */
96 +
97 +/* 32-bit 4KB in-bound mapping windows for Function 0..3, n=0..7 */
98 +#define        SOC_PCIE_SYS_IMAP0(f, n)        (0xc00 + ((f) << 9)((n) << 2))
99 +/* 64-bit in-bound mapping windows for func 0..3 */
100 +#define        SOC_PCIE_SYS_IMAP1(f)           (0xc80 + ((f) << 3))
101 +#define        SOC_PCIE_SYS_IMAP2(f)           (0xcc0 + ((f) << 3))
102 +/* 64-bit in-bound address range n=0..2 */
103 +#define        SOC_PCIE_SYS_IARR(n)            (0xd00 + ((n) << 3))
104 +/* 64-bit out-bound address filter n=0..2 */
105 +#define        SOC_PCIE_SYS_OARR(n)            (0xd20 + ((n) << 3))
106 +/* 64-bit out-bound mapping windows n=0..2 */
107 +#define        SOC_PCIE_SYS_OMAP(n)            (0xd40 + ((n) << 3))
108 +
109 +#define BCM4360_D11AC_ID       0x43a0
110 +#define BCM4360_D11AC2G_ID     0x43a1
111 +#define BCM4360_D11AC5G_ID     0x43a2
112 +#define BCM4352_D11AC_ID       0x43b1  /* 4352 802.11ac dualband device */
113 +#define BCM4352_D11AC2G_ID     0x43b2  /* 4352 802.11ac 2.4G device */
114 +#define BCM4352_D11AC5G_ID     0x43b3  /* 4352 802.11ac 5G device */
115 +
116 +static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
117 +{
118 +       struct pci_sys_data *sys = pdev->sysdata;
119 +       struct bcma_device *bdev = sys->private_data;
120 +
121 +       return bdev->irq;
122 +}
123 +
124 +static u32 bcma_pcie2_cfg_base(struct bcma_device *bdev, int busno,
125 +                              unsigned int devfn, int where)
126 +{
127 +       int slot = PCI_SLOT(devfn);
128 +       int fn = PCI_FUNC(devfn);
129 +       u32 addr_reg;
130 +
131 +       if (busno == 0) {
132 +               if (slot >= 1)
133 +                       return 0;
134 +               bcma_write32(bdev, SOC_PCIE_EXT_CFG_ADDR, where & 0xffc);
135 +               return SOC_PCIE_EXT_CFG_DATA;
136 +       } else {
137 +               if (fn > 1)
138 +                       return 0;
139 +               addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) |
140 +                          (where & 0xffc) | (1 & 0x3);
141 +
142 +               bcma_write32(bdev, SOC_PCIE_CFG_ADDR, addr_reg);
143 +               return SOC_PCIE_CFG_DATA;
144 +       }
145 +}
146 +
147 +static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno,
148 +                                 unsigned int devfn, int where, int size)
149 +{
150 +       u32 base;
151 +       u32 data_reg;
152 +
153 +       base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
154 +
155 +       if (!base)
156 +               return ~0UL;
157 +
158 +       data_reg = bcma_read32(bdev, base);
159 +
160 +       /* NS: CLASS field is R/O, and set to wrong 0x200 value */
161 +       if (busno == 0 && devfn == 0) {
162 +               /*
163 +                * RC's class is 0x0280, but Linux PCI driver needs 0x604
164 +                * for a PCIe bridge. So we must fixup the class code
165 +                * to 0x604 here.
166 +                */
167 +               if ((where & 0xffc) == PCI_CLASS_REVISION) {
168 +                       data_reg &= 0xff;
169 +                       data_reg |= 0x604 << 16;
170 +               }
171 +       }
172 +       /* HEADER_TYPE=00 indicates the port in EP mode */
173 +
174 +       if (size == 4) {
175 +               return data_reg;
176 +       } else {
177 +               u32 mask = (1 << (size * 8)) - 1;
178 +               int shift = (where % 4) * 8;
179 +               return (data_reg >> shift) & mask;
180 +       }
181 +}
182 +
183 +static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno,
184 +                                   unsigned int devfn, int where, int size,
185 +                                   u32 val)
186 +{
187 +       u32 base;
188 +       u32 data_reg;
189 +
190 +       base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
191 +
192 +       if (!base)
193 +               return;
194 +
195 +       if (size < 4) {
196 +               u32 mask = (1 << (size * 8)) - 1;
197 +               int shift = (where % 4) * 8;
198 +               data_reg = bcma_read32(bdev, base);
199 +               data_reg &= ~(mask << shift);
200 +               data_reg |= (val & mask) << shift;
201 +       } else {
202 +               data_reg = val;
203 +       }
204 +
205 +       bcma_write32(bdev, base, data_reg);
206 +}
207 +
208 +static u8 bcma_pcie2_read_config8(struct bcma_device *bdev, int busno,
209 +                                 unsigned int devfn, int where)
210 +{
211 +       return bcma_pcie2_read_config(bdev, busno, devfn, where, 1);
212 +}
213 +
214 +static u16 bcma_pcie2_read_config16(struct bcma_device *bdev, int busno,
215 +                                   unsigned int devfn, int where)
216 +{
217 +       return bcma_pcie2_read_config(bdev, busno, devfn, where, 2);
218 +}
219 +
220 +static u32 bcma_pcie2_read_config32(struct bcma_device *bdev, int busno,
221 +                                   unsigned int devfn, int where)
222 +{
223 +       return bcma_pcie2_read_config(bdev, busno, devfn, where, 4);
224 +}
225 +
226 +static void bcma_pcie2_write_config8(struct bcma_device *bdev, int busno,
227 +                                    unsigned int devfn, int where, u8 val)
228 +{
229 +       return bcma_pcie2_write_config(bdev, busno, devfn, where, 1, val);
230 +}
231 +
232 +static void bcma_pcie2_write_config16(struct bcma_device *bdev, int busno,
233 +                                     unsigned int devfn, int where, u16 val)
234 +{
235 +       return bcma_pcie2_write_config(bdev, busno, devfn, where, 2, val);
236 +}
237 +
238 +static void bcma_pcie2_write_config32(struct bcma_device *bdev, int busno,
239 +                                     unsigned int devfn, int where, u32 val)
240 +{
241 +       return bcma_pcie2_write_config(bdev, busno, devfn, where, 4, val);
242 +}
243 +
244 +static int bcma_pcie2_read_config_pci(struct pci_bus *bus, unsigned int devfn,
245 +                                  int where, int size, u32 *val)
246 +{
247 +       struct pci_sys_data *sys = bus->sysdata;
248 +       struct bcma_device *bdev = sys->private_data;
249 +
250 +       *val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
251 +
252 +       return PCIBIOS_SUCCESSFUL;
253 +}
254 +
255 +static int bcma_pcie2_write_config_pci(struct pci_bus *bus, unsigned int devfn,
256 +                                   int where, int size, u32 val)
257 +{
258 +       struct pci_sys_data *sys = bus->sysdata;
259 +       struct bcma_device *bdev = sys->private_data;
260 +
261 +       bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
262 +
263 +       return PCIBIOS_SUCCESSFUL;
264 +}
265 +
266 +/*
267 + * Check link status, return 0 if link is up in RC mode,
268 + * otherwise return non-zero
269 + */
270 +static int bcma_pcie2_check_link(struct bcma_device *bdev, u32 allow_gen2)
271 +{
272 +       u32 devfn = 0;
273 +       u8 tmp8;
274 +       u32 tmp32;
275 +
276 +       tmp32 = bcma_pcie2_read_config32(bdev, 0, devfn, 0xdc);
277 +       tmp32 &= ~0xf;
278 +       if (allow_gen2)
279 +               tmp32 |= 2;
280 +       else {
281 +               /* force PCIE GEN1 */
282 +               tmp32 |= 1;
283 +       }
284 +       bcma_pcie2_write_config32(bdev, 0, devfn, 0xdc, tmp32);
285 +
286 +       /* See if the port is in EP mode, indicated by header type 00 */
287 +       tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_HEADER_TYPE);
288 +       if (tmp8 != PCI_HEADER_TYPE_BRIDGE) {
289 +               dev_info(&bdev->dev, "Port %d in End-Point mode - ignored\n",
290 +                        bdev->core_unit);
291 +               return -ENODEV;
292 +       }
293 +
294 +       return 0;
295 +}
296 +
297 +/*
298 + * Initializte the PCIe controller
299 + */
300 +static void bcma_pcie2_hw_init(struct bcma_device *bdev)
301 +{
302 +       u32 devfn = 0;
303 +       u32 tmp32;
304 +       u16 tmp16;
305 +
306 +       /* Change MPS and MRRS to 512 */
307 +       tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, 0x4d4);
308 +       tmp16 &= ~7;
309 +       tmp16 |= 2;
310 +       bcma_pcie2_write_config16(bdev, 0, devfn, 0x4d4, tmp16);
311 +
312 +       tmp32 = bcma_pcie2_read_config32(bdev, 0, devfn, 0xb4);
313 +       tmp32 &= ~((7 << 12) | (7 << 5));
314 +       tmp32 |= (2 << 12) | (2 << 5);
315 +       bcma_pcie2_write_config32(bdev, 0, devfn, 0xb4, tmp32);
316 +
317 +       /* Turn-on Root-Complex (RC) mode, from reset defailt of EP */
318 +
319 +       /* The mode is set by straps, can be overwritten via DMU
320 +          register <cru_straps_control> bit 5, "1" means RC
321 +        */
322 +
323 +       /* Send a downstream reset */
324 +       bcma_write32(bdev, SOC_PCIE_CONTROL, 0x3);
325 +       udelay(250);
326 +       bcma_write32(bdev, SOC_PCIE_CONTROL, 0x1);
327 +       mdelay(250);
328 +
329 +       /* TBD: take care of PM, check we're on */
330 +}
331 +
332 +/*
333 + * Setup the address translation
334 + */
335 +static void bcma_pcie2_map_init(struct bcma_device *bdev)
336 +{
337 +       unsigned size, i;
338 +       u32 addr;
339 +
340 +       /*
341 +        * NOTE:
342 +        * All PCI-to-CPU address mapping are 1:1 for simplicity
343 +        */
344 +
345 +       /* Outbound address translation setup */
346 +       size = SZ_128M;
347 +       addr = bdev->addr_s[0];
348 +       BUG_ON(!addr);
349 +       BUG_ON(addr & ((1 << 25) - 1)); /* 64MB alignment */
350 +
351 +       for (i = 0; i < 3; i++) {
352 +               const unsigned win_size = SZ_64M;
353 +               /* 64-bit LE regs, write low word, high is 0 at reset */
354 +               bcma_write32(bdev, SOC_PCIE_SYS_OMAP(i), addr);
355 +               bcma_write32(bdev, SOC_PCIE_SYS_OARR(i), addr|0x1);
356 +               addr += win_size;
357 +               if (size >= win_size)
358 +                       size -= win_size;
359 +               if (size == 0)
360 +                       break;
361 +       }
362 +       WARN_ON(size > 0);
363 +
364 +       /*
365 +        * Inbound address translation setup
366 +        * Northstar only maps up to 128 MiB inbound, DRAM could be up to 1 GiB.
367 +        *
368 +        * For now allow access to entire DRAM, assuming it is less than 128MiB,
369 +        * otherwise DMA bouncing mechanism may be required.
370 +        * Also consider DMA mask to limit DMA physical address
371 +        */
372 +       size = SZ_128M;
373 +       addr = PHYS_OFFSET;
374 +
375 +       size >>= 20;    /* In MB */
376 +       size &= 0xff;   /* Size is an 8-bit field */
377 +
378 +       WARN_ON(size == 0);
379 +       /* 64-bit LE regs, write low word, high is 0 at reset */
380 +       bcma_write32(bdev, SOC_PCIE_SYS_IMAP1(0), addr | 0x1);
381 +       bcma_write32(bdev, SOC_PCIE_SYS_IARR(1), addr | size);
382 +
383 +#ifdef CONFIG_SPARSEMEM
384 +       addr = PHYS_OFFSET2;
385 +       bcma_write32(bdev, SOC_PCIE_SYS_IMAP2(0), addr | 0x1);
386 +       bcma_write32(bdev, SOC_PCIE_SYS_IARR(2), addr | size);
387 +#endif
388 +}
389 +
390 +/*
391 + * Setup PCIE Host bridge
392 + */
393 +static void bcma_pcie2_bridge_init(struct bcma_device *bdev)
394 +{
395 +       u32 devfn = 0;
396 +       u8 tmp8;
397 +       u16 tmp16;
398 +
399 +       bcma_pcie2_write_config8(bdev, 0, devfn, PCI_PRIMARY_BUS, 0);
400 +       bcma_pcie2_write_config8(bdev, 0, devfn, PCI_SECONDARY_BUS, 1);
401 +       bcma_pcie2_write_config8(bdev, 0, devfn, PCI_SUBORDINATE_BUS, 4);
402 +
403 +       tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_PRIMARY_BUS);
404 +       tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_SECONDARY_BUS);
405 +       tmp8 = bcma_pcie2_read_config8(bdev, 0, devfn, PCI_SUBORDINATE_BUS);
406 +
407 +       /* MEM_BASE, MEM_LIM require 1MB alignment */
408 +       BUG_ON((bdev->addr_s[0] >> 16) & 0xf);
409 +       bcma_pcie2_write_config16(bdev, 0, devfn, PCI_MEMORY_BASE,
410 +               bdev->addr_s[0] >> 16);
411 +       BUG_ON(((bdev->addr_s[0] + SZ_128M) >> 16) & 0xf);
412 +       bcma_pcie2_write_config16(bdev, 0, devfn, PCI_MEMORY_LIMIT,
413 +               (bdev->addr_s[0] + SZ_128M) >> 16);
414 +
415 +       /* These registers are not supported on the NS */
416 +       bcma_pcie2_write_config16(bdev, 0, devfn, PCI_IO_BASE_UPPER16, 0);
417 +       bcma_pcie2_write_config16(bdev, 0, devfn, PCI_IO_LIMIT_UPPER16, 0);
418 +
419 +       /* Force class to that of a Bridge */
420 +       bcma_pcie2_write_config16(bdev, 0, devfn, PCI_CLASS_DEVICE,
421 +                                 PCI_CLASS_BRIDGE_PCI);
422 +
423 +       tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_CLASS_DEVICE);
424 +       tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_MEMORY_BASE);
425 +       tmp16 = bcma_pcie2_read_config16(bdev, 0, devfn, PCI_MEMORY_LIMIT);
426 +}
427 +
428 +static int bcma_pcie2_allow_gen2_rc(struct bcma_device *bdev)
429 +{
430 +       u32 vendorid, devid, chipid, chiprev;
431 +       u32 val, bar;
432 +       void __iomem *base;
433 +       int allow = 1;
434 +
435 +       /* Read PCI vendor/device ID's */
436 +       bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x0);
437 +       val = bcma_read32(bdev, SOC_PCIE_CFG_DATA);
438 +       vendorid = val & 0xffff;
439 +       devid = val >> 16;
440 +       if (vendorid == PCI_VENDOR_ID_BROADCOM &&
441 +           (devid == BCMA_CHIP_ID_BCM4360 || devid == BCM4360_D11AC_ID ||
442 +            devid == BCM4360_D11AC2G_ID || devid == BCM4360_D11AC5G_ID ||
443 +            devid == BCM4352_D11AC_ID || devid == BCM4352_D11AC2G_ID ||
444 +            devid == BCM4352_D11AC5G_ID)) {
445 +               /* Config BAR0 */
446 +               bar = bdev->addr_s[0];
447 +               bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x10);
448 +               bcma_write32(bdev, SOC_PCIE_CFG_DATA, bar);
449 +               /* Config BAR0 window to access chipc */
450 +               bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x80);
451 +               bcma_write32(bdev, SOC_PCIE_CFG_DATA, SI_ENUM_BASE);
452 +
453 +               /* Enable memory resource */
454 +               bcma_write32(bdev, SOC_PCIE_CFG_ADDR, 0x4);
455 +               val = bcma_read32(bdev, SOC_PCIE_CFG_DATA);
456 +               val |= PCI_COMMAND_MEMORY;
457 +               bcma_write32(bdev, SOC_PCIE_CFG_DATA, val);
458 +               /* Enable memory and bus master */
459 +               bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6);
460 +
461 +               /* Read CHIP ID */
462 +               base = ioremap(bar, 0x1000);
463 +               val = __raw_readl(base);
464 +               iounmap(base);
465 +               chipid = val & 0xffff;
466 +               chiprev = (val >> 16) & 0xf;
467 +               if ((chipid == BCMA_CHIP_ID_BCM4360 ||
468 +                    chipid == BCMA_CHIP_ID_BCM43460 ||
469 +                    chipid == BCMA_CHIP_ID_BCM4352) && (chiprev < 3))
470 +                       allow = 0;
471 +       }
472 +       return allow;
473 +}
474 +
475 +static void bcma_pcie2_3rd_init(struct bcma_bus *bus)
476 +{
477 +       /* PCIE PLL block register (base 0x8000) */
478 +       bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x57fe8000);
479 +       /* Check PCIE PLL lock status */
480 +       bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x67c60000);
481 +}
482 +
483 +/* To improve PCIE phy jitter */
484 +static void bcma_pcie2_improve_phy_jitter(struct bcma_bus *bus, int phyaddr)
485 +{
486 +       u32 val;
487 +
488 +       /* Change blkaddr */
489 +       val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x1f << 18) |
490 +               (2 << 16) | (0x863 << 4);
491 +       bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
492 +
493 +       /* Write 0x0190 to 0x13 regaddr */
494 +       val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x13 << 18) |
495 +               (2 << 16) | 0x0190;
496 +       bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
497 +
498 +       /* Write 0x0191 to 0x19 regaddr */
499 +       val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x19 << 18) |
500 +               (2 << 16) | 0x0191;
501 +       bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
502 +}
503 +
504 +static int bcma_pcie2_setup(int nr, struct pci_sys_data *sys)
505 +{
506 +       struct bcma_device *bdev = sys->private_data;
507 +       struct bcma_bus *bus = bdev->bus;
508 +       struct resource *res;
509 +       struct bcma_device *arm_core;
510 +       u32 cru_straps_ctrl;
511 +       int allow_gen2, linkfail;
512 +       int phyaddr;
513 +
514 +       if (bdev->core_unit == 2) {
515 +               arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9);
516 +               cru_straps_ctrl = bcma_read32(arm_core, 0x2a0);
517 +
518 +               /* 3rd PCIE is not selected */
519 +               if (cru_straps_ctrl & 0x10)
520 +                       return -ENODEV;
521 +
522 +               bcma_pcie2_3rd_init(bus);
523 +               phyaddr = 0xf;
524 +       } else {
525 +               phyaddr = bdev->core_unit;
526 +       }
527 +       bcma_pcie2_improve_phy_jitter(bus, phyaddr);
528 +
529 +       /* create mem resource */
530 +       res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
531 +       if (!res) {
532 +               dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
533 +                        bdev->addr_s[0]);
534 +               return -EINVAL;
535 +       }
536 +       res->start = bdev->addr_s[0];
537 +       res->end = res->start + SZ_128M - 1;
538 +       res->name = "PCIe Configuration Space";
539 +       res->flags = IORESOURCE_MEM;
540 +
541 +       pci_add_resource(&sys->resources, res);
542 +
543 +       /* This PCIe controller does not support IO Mem, so use a dummy one. */
544 +       res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
545 +       if (!res) {
546 +               dev_info(&bdev->dev, "requesting resource at 0x%x failed\n",
547 +                        bdev->addr_s[0]);
548 +               return -EINVAL;
549 +       }
550 +       res->start = bdev->addr_s[0];
551 +       res->end = res->start + SZ_128M - 1;
552 +       res->name = "PCIe Configuration Space";
553 +       res->flags = IORESOURCE_IO;
554 +
555 +       pci_add_resource(&sys->resources, res);
556 +
557 +       for (allow_gen2 = 0; allow_gen2 <= 1; allow_gen2++) {
558 +               bcma_pcie2_hw_init(bdev);
559 +               bcma_pcie2_map_init(bdev);
560 +
561 +               /*
562 +                * Skip inactive ports -
563 +                * will need to change this for hot-plugging
564 +                */
565 +               linkfail = bcma_pcie2_check_link(bdev, allow_gen2);
566 +               if (linkfail)
567 +                       break;
568 +
569 +               bcma_pcie2_bridge_init(bdev);
570 +
571 +               if (allow_gen2 == 0) {
572 +                       if (bcma_pcie2_allow_gen2_rc(bdev) == 0)
573 +                               break;
574 +                       dev_info(&bdev->dev, "switching to GEN2\n");
575 +               }
576 +       }
577 +
578 +       if (linkfail)
579 +               return -1;
580 +
581 +       return 1;
582 +}
583 +
584 +/*
585 + * Methods for accessing configuration registers
586 + */
587 +static struct pci_ops bcma_pcie2_ops = {
588 +       .read = bcma_pcie2_read_config_pci,
589 +       .write = bcma_pcie2_write_config_pci,
590 +};
591 +
592 +static int bcma_pcie2_probe(struct bcma_device *bdev)
593 +{
594 +       struct hw_pci hw;
595 +
596 +       dev_info(&bdev->dev, "scanning bus\n");
597 +
598 +       hw = (struct hw_pci) {
599 +               .nr_controllers = 1,
600 +               .domain         = bdev->core_unit,
601 +               .private_data   = (void **)&bdev,
602 +               .setup          = bcma_pcie2_setup,
603 +               .map_irq        = bcma_pcie2_map_irq,
604 +               .ops            = &bcma_pcie2_ops,
605 +       };
606 +
607 +       /* Announce this port to ARM/PCI common code */
608 +       pci_common_init_dev(&bdev->dev, &hw);
609 +
610 +       /* Setup virtual-wire interrupts */
611 +       bcma_write32(bdev, SOC_PCIE_SYS_RC_INTX_EN, 0xf);
612 +
613 +       /* Enable memory and bus master */
614 +       bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6);
615 +
616 +       return 0;
617 +}
618 +
619 +static const struct bcma_device_id bcma_pcie2_table[] = {
620 +       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS),
621 +       BCMA_CORETABLE_END
622 +};
623 +MODULE_DEVICE_TABLE(bcma, bcma_pcie2_table);
624 +
625 +static struct bcma_driver bcma_pcie2_driver = {
626 +       .name           = KBUILD_MODNAME,
627 +       .id_table       = bcma_pcie2_table,
628 +       .probe          = bcma_pcie2_probe,
629 +};
630 +
631 +static int __init bcma_pcie2_init(void)
632 +{
633 +       return bcma_driver_register(&bcma_pcie2_driver);
634 +}
635 +module_init(bcma_pcie2_init);
636 +
637 +static void __exit bcma_pcie2_exit(void)
638 +{
639 +       bcma_driver_unregister(&bcma_pcie2_driver);
640 +}
641 +module_exit(bcma_pcie2_exit);
642 +
643 +MODULE_AUTHOR("Hauke Mehrtens");
644 +MODULE_DESCRIPTION("PCIe Gen2 driver for BCMA");
645 +MODULE_LICENSE("GPLv2");