Root/target/linux/brcm63xx/patches-3.3/027-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch

1From 45655e79f84e35c13b8964b961d804e64b3aca91 Mon Sep 17 00:00:00 2001
2From: Jonas Gorski <jonas.gorski@gmail.com>
3Date: Wed, 13 Jun 2012 17:07:13 +0100
4Subject: [PATCH 6/8] MIPS: BCM63XX: Add PCIe Support for BCM6328
5
6Add support for the PCIe port found on BCM6328.
7
8Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
9Cc: linux-mips@linux-mips.org
10Cc: Maxime Bizon <mbizon@freebox.fr>
11Cc: Florian Fainelli <florian@openwrt.org>
12Cc: Kevin Cernekee <cernekee@gmail.com>
13Patchwork: https://patchwork.linux-mips.org/patch/3956/
14Reviewed-by: Florian Fainelli <florian@openwrt.org>
15Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
16---
17 arch/mips/bcm63xx/Kconfig | 1 +
18 arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 9 ++
19 arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 6 +
20 arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 54 ++++++++++
21 arch/mips/pci/ops-bcm63xx.c | 61 +++++++++++
22 arch/mips/pci/pci-bcm63xx.c | 112 +++++++++++++++++++++
23 arch/mips/pci/pci-bcm63xx.h | 5 +
24 7 files changed, 248 insertions(+), 0 deletions(-)
25
26--- a/arch/mips/bcm63xx/Kconfig
27+++ b/arch/mips/bcm63xx/Kconfig
28@@ -3,6 +3,7 @@ menu "CPU support"
29 
30 config BCM63XX_CPU_6328
31     bool "support 6328 CPU"
32+ select HW_HAS_PCI
33 
34 config BCM63XX_CPU_6338
35     bool "support 6338 CPU"
36--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
37+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
38@@ -122,6 +122,7 @@ enum bcm63xx_regs_set {
39     RSET_USBH_PRIV,
40     RSET_MPI,
41     RSET_PCMCIA,
42+ RSET_PCIE,
43     RSET_DSL,
44     RSET_ENET0,
45     RSET_ENET1,
46@@ -188,6 +189,7 @@ enum bcm63xx_regs_set {
47 #define BCM_6328_USBH_PRIV_BASE (0xdeadbeef)
48 #define BCM_6328_MPI_BASE (0xdeadbeef)
49 #define BCM_6328_PCMCIA_BASE (0xdeadbeef)
50+#define BCM_6328_PCIE_BASE (0xb0e40000)
51 #define BCM_6328_SDRAM_REGS_BASE (0xdeadbeef)
52 #define BCM_6328_DSL_BASE (0xb0001900)
53 #define BCM_6328_UBUS_BASE (0xdeadbeef)
54@@ -232,6 +234,7 @@ enum bcm63xx_regs_set {
55 #define BCM_6338_USBH_PRIV_BASE (0xdeadbeef)
56 #define BCM_6338_MPI_BASE (0xfffe3160)
57 #define BCM_6338_PCMCIA_BASE (0xdeadbeef)
58+#define BCM_6338_PCIE_BASE (0xdeadbeef)
59 #define BCM_6338_SDRAM_REGS_BASE (0xfffe3100)
60 #define BCM_6338_DSL_BASE (0xfffe1000)
61 #define BCM_6338_UBUS_BASE (0xdeadbeef)
62@@ -279,6 +282,7 @@ enum bcm63xx_regs_set {
63 #define BCM_6345_ENETSW_BASE (0xdeadbeef)
64 #define BCM_6345_PCMCIA_BASE (0xfffe2028)
65 #define BCM_6345_MPI_BASE (0xfffe2000)
66+#define BCM_6345_PCIE_BASE (0xdeadbeef)
67 #define BCM_6345_OHCI0_BASE (0xfffe2100)
68 #define BCM_6345_OHCI_PRIV_BASE (0xfffe2200)
69 #define BCM_6345_USBH_PRIV_BASE (0xdeadbeef)
70@@ -320,6 +324,7 @@ enum bcm63xx_regs_set {
71 #define BCM_6348_USBH_PRIV_BASE (0xdeadbeef)
72 #define BCM_6348_MPI_BASE (0xfffe2000)
73 #define BCM_6348_PCMCIA_BASE (0xfffe2054)
74+#define BCM_6348_PCIE_BASE (0xdeadbeef)
75 #define BCM_6348_SDRAM_REGS_BASE (0xfffe2300)
76 #define BCM_6348_M2M_BASE (0xfffe2800)
77 #define BCM_6348_DSL_BASE (0xfffe3000)
78@@ -362,6 +367,7 @@ enum bcm63xx_regs_set {
79 #define BCM_6358_USBH_PRIV_BASE (0xfffe1500)
80 #define BCM_6358_MPI_BASE (0xfffe1000)
81 #define BCM_6358_PCMCIA_BASE (0xfffe1054)
82+#define BCM_6358_PCIE_BASE (0xdeadbeef)
83 #define BCM_6358_SDRAM_REGS_BASE (0xfffe2300)
84 #define BCM_6358_M2M_BASE (0xdeadbeef)
85 #define BCM_6358_DSL_BASE (0xfffe3000)
86@@ -405,6 +411,7 @@ enum bcm63xx_regs_set {
87 #define BCM_6368_USBH_PRIV_BASE (0xb0001700)
88 #define BCM_6368_MPI_BASE (0xb0001000)
89 #define BCM_6368_PCMCIA_BASE (0xb0001054)
90+#define BCM_6368_PCIE_BASE (0xdeadbeef)
91 #define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef)
92 #define BCM_6368_M2M_BASE (0xdeadbeef)
93 #define BCM_6368_DSL_BASE (0xdeadbeef)
94@@ -453,6 +460,7 @@ extern const unsigned long *bcm63xx_regs
95     __GEN_RSET_BASE(__cpu, USBH_PRIV) \
96     __GEN_RSET_BASE(__cpu, MPI) \
97     __GEN_RSET_BASE(__cpu, PCMCIA) \
98+ __GEN_RSET_BASE(__cpu, PCIE) \
99     __GEN_RSET_BASE(__cpu, DSL) \
100     __GEN_RSET_BASE(__cpu, ENET0) \
101     __GEN_RSET_BASE(__cpu, ENET1) \
102@@ -493,6 +501,7 @@ extern const unsigned long *bcm63xx_regs
103     [RSET_USBH_PRIV] = BCM_## __cpu ##_USBH_PRIV_BASE, \
104     [RSET_MPI] = BCM_## __cpu ##_MPI_BASE, \
105     [RSET_PCMCIA] = BCM_## __cpu ##_PCMCIA_BASE, \
106+ [RSET_PCIE] = BCM_## __cpu ##_PCIE_BASE, \
107     [RSET_DSL] = BCM_## __cpu ##_DSL_BASE, \
108     [RSET_ENET0] = BCM_## __cpu ##_ENET0_BASE, \
109     [RSET_ENET1] = BCM_## __cpu ##_ENET1_BASE, \
110--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
111+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
112@@ -40,6 +40,10 @@
113 #define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
114                     BCM_CB_MEM_SIZE - 1)
115 
116+#define BCM_PCIE_MEM_BASE_PA 0x10f00000
117+#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024)
118+#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
119+ BCM_PCIE_MEM_SIZE - 1)
120 
121 /*
122  * Internal registers are accessed through KSEG3
123@@ -85,6 +89,8 @@
124 #define bcm_mpi_writel(v, o) bcm_rset_writel(RSET_MPI, (v), (o))
125 #define bcm_pcmcia_readl(o) bcm_rset_readl(RSET_PCMCIA, (o))
126 #define bcm_pcmcia_writel(v, o) bcm_rset_writel(RSET_PCMCIA, (v), (o))
127+#define bcm_pcie_readl(o) bcm_rset_readl(RSET_PCIE, (o))
128+#define bcm_pcie_writel(v, o) bcm_rset_writel(RSET_PCIE, (v), (o))
129 #define bcm_sdram_readl(o) bcm_rset_readl(RSET_SDRAM, (o))
130 #define bcm_sdram_writel(v, o) bcm_rset_writel(RSET_SDRAM, (v), (o))
131 #define bcm_memc_readl(o) bcm_rset_readl(RSET_MEMC, (o))
132--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
133+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
134@@ -1169,6 +1169,9 @@
135 /*************************************************************************
136  * _REG relative to RSET_MISC
137  *************************************************************************/
138+#define MISC_SERDES_CTRL_REG 0x0
139+#define SERDES_PCIE_EN (1 << 0)
140+#define SERDES_PCIE_EXD_EN (1 << 15)
141 
142 #define MISC_STRAPBUS_6328_REG 0x240
143 #define STRAPBUS_6328_FCVO_SHIFT 7
144@@ -1176,4 +1179,55 @@
145 #define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
146 #define STRAPBUS_6328_BOOT_SEL_NAND (0 << 28)
147 
148+/*************************************************************************
149+ * _REG relative to RSET_PCIE
150+ *************************************************************************/
151+
152+#define PCIE_CONFIG2_REG 0x408
153+#define CONFIG2_BAR1_SIZE_EN 1
154+#define CONFIG2_BAR1_SIZE_MASK 0xf
155+
156+#define PCIE_IDVAL3_REG 0x43c
157+#define IDVAL3_CLASS_CODE_MASK 0xffffff
158+#define IDVAL3_SUBCLASS_SHIFT 8
159+#define IDVAL3_CLASS_SHIFT 16
160+
161+#define PCIE_DLSTATUS_REG 0x1048
162+#define DLSTATUS_PHYLINKUP (1 << 13)
163+
164+#define PCIE_BRIDGE_OPT1_REG 0x2820
165+#define OPT1_RD_BE_OPT_EN (1 << 7)
166+#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9)
167+#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11)
168+#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12)
169+
170+#define PCIE_BRIDGE_OPT2_REG 0x2824
171+#define OPT2_UBUS_UR_DECODE_DIS (1 << 2)
172+#define OPT2_TX_CREDIT_CHK_EN (1 << 4)
173+#define OPT2_CFG_TYPE1_BD_SEL (1 << 7)
174+#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16
175+#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT)
176+
177+#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828
178+#define PCIE_BRIDGE_BAR1_BASEMASK_REG 0x2830
179+#define BASEMASK_REMAP_EN (1 << 0)
180+#define BASEMASK_SWAP_EN (1 << 1)
181+#define BASEMASK_MASK_SHIFT 4
182+#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT)
183+#define BASEMASK_BASE_SHIFT 20
184+#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT)
185+
186+#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c
187+#define PCIE_BRIDGE_BAR1_REBASE_ADDR_REG 0x2834
188+#define REBASE_ADDR_BASE_SHIFT 20
189+#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT)
190+
191+#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854
192+#define PCIE_RC_INT_A (1 << 0)
193+#define PCIE_RC_INT_B (1 << 1)
194+#define PCIE_RC_INT_C (1 << 2)
195+#define PCIE_RC_INT_D (1 << 3)
196+
197+#define PCIE_DEVICE_OFFSET 0x8000
198+
199 #endif /* BCM63XX_REGS_H_ */
200--- a/arch/mips/pci/ops-bcm63xx.c
201+++ b/arch/mips/pci/ops-bcm63xx.c
202@@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev
203 
204 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
205 #endif
206+
207+static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
208+{
209+ switch (bus->number) {
210+ case PCIE_BUS_BRIDGE:
211+ return (PCI_SLOT(devfn) == 0);
212+ case PCIE_BUS_DEVICE:
213+ if (PCI_SLOT(devfn) == 0)
214+ return bcm_pcie_readl(PCIE_DLSTATUS_REG)
215+ & DLSTATUS_PHYLINKUP;
216+ default:
217+ return false;
218+ }
219+}
220+
221+static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
222+ int where, int size, u32 *val)
223+{
224+ u32 data;
225+ u32 reg = where & ~3;
226+
227+ if (!bcm63xx_pcie_can_access(bus, devfn))
228+ return PCIBIOS_DEVICE_NOT_FOUND;
229+
230+ if (bus->number == PCIE_BUS_DEVICE)
231+ reg += PCIE_DEVICE_OFFSET;
232+
233+ data = bcm_pcie_readl(reg);
234+
235+ *val = postprocess_read(data, where, size);
236+
237+ return PCIBIOS_SUCCESSFUL;
238+
239+}
240+
241+static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
242+ int where, int size, u32 val)
243+{
244+ u32 data;
245+ u32 reg = where & ~3;
246+
247+ if (!bcm63xx_pcie_can_access(bus, devfn))
248+ return PCIBIOS_DEVICE_NOT_FOUND;
249+
250+ if (bus->number == PCIE_BUS_DEVICE)
251+ reg += PCIE_DEVICE_OFFSET;
252+
253+
254+ data = bcm_pcie_readl(reg);
255+
256+ data = preprocess_write(data, val, where, size);
257+ bcm_pcie_writel(data, reg);
258+
259+ return PCIBIOS_SUCCESSFUL;
260+}
261+
262+
263+struct pci_ops bcm63xx_pcie_ops = {
264+ .read = bcm63xx_pcie_read,
265+ .write = bcm63xx_pcie_write
266+};
267--- a/arch/mips/pci/pci-bcm63xx.c
268+++ b/arch/mips/pci/pci-bcm63xx.c
269@@ -10,6 +10,7 @@
270 #include <linux/pci.h>
271 #include <linux/kernel.h>
272 #include <linux/init.h>
273+#include <linux/delay.h>
274 #include <asm/bootinfo.h>
275 
276 #include "pci-bcm63xx.h"
277@@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_control
278 };
279 #endif
280 
281+static struct resource bcm_pcie_mem_resource = {
282+ .name = "bcm63xx PCIe memory space",
283+ .start = BCM_PCIE_MEM_BASE_PA,
284+ .end = BCM_PCIE_MEM_END_PA,
285+ .flags = IORESOURCE_MEM,
286+};
287+
288+static struct resource bcm_pcie_io_resource = {
289+ .name = "bcm63xx PCIe IO space",
290+ .start = 0,
291+ .end = 0,
292+ .flags = 0,
293+};
294+
295+struct pci_controller bcm63xx_pcie_controller = {
296+ .pci_ops = &bcm63xx_pcie_ops,
297+ .io_resource = &bcm_pcie_io_resource,
298+ .mem_resource = &bcm_pcie_mem_resource,
299+};
300+
301 static u32 bcm63xx_int_cfg_readl(u32 reg)
302 {
303     u32 tmp;
304@@ -94,6 +115,95 @@ static void bcm63xx_int_cfg_writel(u32 v
305 
306 void __iomem *pci_iospace_start;
307 
308+static void __init bcm63xx_reset_pcie(void)
309+{
310+ u32 val;
311+
312+ /* enable clock */
313+ val = bcm_perf_readl(PERF_CKCTL_REG);
314+ val |= CKCTL_6328_PCIE_EN;
315+ bcm_perf_writel(val, PERF_CKCTL_REG);
316+
317+ /* enable SERDES */
318+ val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
319+ val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
320+ bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
321+
322+ /* reset the PCIe core */
323+ val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
324+
325+ val &= ~SOFTRESET_6328_PCIE_MASK;
326+ val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
327+ val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
328+ val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
329+ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
330+ mdelay(10);
331+
332+ val |= SOFTRESET_6328_PCIE_MASK;
333+ val |= SOFTRESET_6328_PCIE_CORE_MASK;
334+ val |= SOFTRESET_6328_PCIE_HARD_MASK;
335+ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
336+ mdelay(10);
337+
338+ val |= SOFTRESET_6328_PCIE_EXT_MASK;
339+ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
340+ mdelay(200);
341+}
342+
343+static int __init bcm63xx_register_pcie(void)
344+{
345+ u32 val;
346+
347+ bcm63xx_reset_pcie();
348+
349+ /* configure the PCIe bridge */
350+ val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
351+ val |= OPT1_RD_BE_OPT_EN;
352+ val |= OPT1_RD_REPLY_BE_FIX_EN;
353+ val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
354+ val |= OPT1_L1_INT_STATUS_MASK_POL;
355+ bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
356+
357+ /* setup the interrupts */
358+ val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
359+ val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
360+ bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
361+
362+ val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
363+ /* enable credit checking and error checking */
364+ val |= OPT2_TX_CREDIT_CHK_EN;
365+ val |= OPT2_UBUS_UR_DECODE_DIS;
366+
367+ /* set device bus/func for the pcie device */
368+ val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
369+ val |= OPT2_CFG_TYPE1_BD_SEL;
370+ bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
371+
372+ /* setup class code as bridge */
373+ val = bcm_pcie_readl(PCIE_IDVAL3_REG);
374+ val &= ~IDVAL3_CLASS_CODE_MASK;
375+ val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
376+ bcm_pcie_writel(val, PCIE_IDVAL3_REG);
377+
378+ /* disable bar1 size */
379+ val = bcm_pcie_readl(PCIE_CONFIG2_REG);
380+ val &= ~CONFIG2_BAR1_SIZE_MASK;
381+ bcm_pcie_writel(val, PCIE_CONFIG2_REG);
382+
383+ /* set bar0 to little endian */
384+ val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
385+ val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
386+ val |= BASEMASK_REMAP_EN;
387+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
388+
389+ val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
390+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
391+
392+ register_pci_controller(&bcm63xx_pcie_controller);
393+
394+ return 0;
395+}
396+
397 static int __init bcm63xx_register_pci(void)
398 {
399     unsigned int mem_size;
400@@ -221,6 +331,8 @@ static int __init bcm63xx_pci_init(void)
401         return -ENODEV;
402 
403     switch (bcm63xx_get_cpu_id()) {
404+ case BCM6328_CPU_ID:
405+ return bcm63xx_register_pcie();
406     case BCM6348_CPU_ID:
407     case BCM6358_CPU_ID:
408     case BCM6368_CPU_ID:
409--- a/arch/mips/pci/pci-bcm63xx.h
410+++ b/arch/mips/pci/pci-bcm63xx.h
411@@ -13,11 +13,16 @@
412  */
413 #define CARDBUS_PCI_IDSEL 0x8
414 
415+
416+#define PCIE_BUS_BRIDGE 0
417+#define PCIE_BUS_DEVICE 1
418+
419 /*
420  * defined in ops-bcm63xx.c
421  */
422 extern struct pci_ops bcm63xx_pci_ops;
423 extern struct pci_ops bcm63xx_cb_ops;
424+extern struct pci_ops bcm63xx_pcie_ops;
425 
426 /*
427  * defined in pci-bcm63xx.c
428

Archive Download this file



interactive