aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pci
diff options
context:
space:
mode:
authorJonas Gorski <jonas.gorski@gmail.com>2012-07-24 10:33:13 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-07-24 10:33:13 -0400
commit19c860d932de520017c9b2d88cd9dff90b71ba36 (patch)
tree2feb7f7cb1c91f5bdd6ce761ff4e421814237274 /arch/mips/pci
parent76f42fe8117c85fced0135b23835890cfa41a47b (diff)
MIPS: BCM63XX: Add PCIe Support for BCM6328
Add support for the PCIe port found on BCM6328. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> Cc: linux-mips@linux-mips.org Cc: Maxime Bizon <mbizon@freebox.fr> Cc: Florian Fainelli <florian@openwrt.org> Cc: Kevin Cernekee <cernekee@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/3956/ Reviewed-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/pci')
-rw-r--r--arch/mips/pci/ops-bcm63xx.c61
-rw-r--r--arch/mips/pci/pci-bcm63xx.c112
-rw-r--r--arch/mips/pci/pci-bcm63xx.h5
3 files changed, 178 insertions, 0 deletions
diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c
index 822ae179bc56..4a156629e958 100644
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev *dev)
465 465
466DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup); 466DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
467#endif 467#endif
468
469static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
470{
471 switch (bus->number) {
472 case PCIE_BUS_BRIDGE:
473 return (PCI_SLOT(devfn) == 0);
474 case PCIE_BUS_DEVICE:
475 if (PCI_SLOT(devfn) == 0)
476 return bcm_pcie_readl(PCIE_DLSTATUS_REG)
477 & DLSTATUS_PHYLINKUP;
478 default:
479 return false;
480 }
481}
482
483static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
484 int where, int size, u32 *val)
485{
486 u32 data;
487 u32 reg = where & ~3;
488
489 if (!bcm63xx_pcie_can_access(bus, devfn))
490 return PCIBIOS_DEVICE_NOT_FOUND;
491
492 if (bus->number == PCIE_BUS_DEVICE)
493 reg += PCIE_DEVICE_OFFSET;
494
495 data = bcm_pcie_readl(reg);
496
497 *val = postprocess_read(data, where, size);
498
499 return PCIBIOS_SUCCESSFUL;
500
501}
502
503static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
504 int where, int size, u32 val)
505{
506 u32 data;
507 u32 reg = where & ~3;
508
509 if (!bcm63xx_pcie_can_access(bus, devfn))
510 return PCIBIOS_DEVICE_NOT_FOUND;
511
512 if (bus->number == PCIE_BUS_DEVICE)
513 reg += PCIE_DEVICE_OFFSET;
514
515
516 data = bcm_pcie_readl(reg);
517
518 data = preprocess_write(data, val, where, size);
519 bcm_pcie_writel(data, reg);
520
521 return PCIBIOS_SUCCESSFUL;
522}
523
524
525struct pci_ops bcm63xx_pcie_ops = {
526 .read = bcm63xx_pcie_read,
527 .write = bcm63xx_pcie_write
528};
diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c
index a2b6d55a2492..8a48139d219c 100644
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -10,6 +10,7 @@
10#include <linux/pci.h> 10#include <linux/pci.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h>
13#include <asm/bootinfo.h> 14#include <asm/bootinfo.h>
14 15
15#include "pci-bcm63xx.h" 16#include "pci-bcm63xx.h"
@@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_controller = {
71}; 72};
72#endif 73#endif
73 74
75static struct resource bcm_pcie_mem_resource = {
76 .name = "bcm63xx PCIe memory space",
77 .start = BCM_PCIE_MEM_BASE_PA,
78 .end = BCM_PCIE_MEM_END_PA,
79 .flags = IORESOURCE_MEM,
80};
81
82static struct resource bcm_pcie_io_resource = {
83 .name = "bcm63xx PCIe IO space",
84 .start = 0,
85 .end = 0,
86 .flags = 0,
87};
88
89struct pci_controller bcm63xx_pcie_controller = {
90 .pci_ops = &bcm63xx_pcie_ops,
91 .io_resource = &bcm_pcie_io_resource,
92 .mem_resource = &bcm_pcie_mem_resource,
93};
94
74static u32 bcm63xx_int_cfg_readl(u32 reg) 95static u32 bcm63xx_int_cfg_readl(u32 reg)
75{ 96{
76 u32 tmp; 97 u32 tmp;
@@ -94,6 +115,95 @@ static void bcm63xx_int_cfg_writel(u32 val, u32 reg)
94 115
95void __iomem *pci_iospace_start; 116void __iomem *pci_iospace_start;
96 117
118static void __init bcm63xx_reset_pcie(void)
119{
120 u32 val;
121
122 /* enable clock */
123 val = bcm_perf_readl(PERF_CKCTL_REG);
124 val |= CKCTL_6328_PCIE_EN;
125 bcm_perf_writel(val, PERF_CKCTL_REG);
126
127 /* enable SERDES */
128 val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
129 val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
130 bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
131
132 /* reset the PCIe core */
133 val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
134
135 val &= ~SOFTRESET_6328_PCIE_MASK;
136 val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
137 val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
138 val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
139 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
140 mdelay(10);
141
142 val |= SOFTRESET_6328_PCIE_MASK;
143 val |= SOFTRESET_6328_PCIE_CORE_MASK;
144 val |= SOFTRESET_6328_PCIE_HARD_MASK;
145 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
146 mdelay(10);
147
148 val |= SOFTRESET_6328_PCIE_EXT_MASK;
149 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
150 mdelay(200);
151}
152
153static int __init bcm63xx_register_pcie(void)
154{
155 u32 val;
156
157 bcm63xx_reset_pcie();
158
159 /* configure the PCIe bridge */
160 val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
161 val |= OPT1_RD_BE_OPT_EN;
162 val |= OPT1_RD_REPLY_BE_FIX_EN;
163 val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
164 val |= OPT1_L1_INT_STATUS_MASK_POL;
165 bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
166
167 /* setup the interrupts */
168 val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
169 val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
170 bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
171
172 val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
173 /* enable credit checking and error checking */
174 val |= OPT2_TX_CREDIT_CHK_EN;
175 val |= OPT2_UBUS_UR_DECODE_DIS;
176
177 /* set device bus/func for the pcie device */
178 val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
179 val |= OPT2_CFG_TYPE1_BD_SEL;
180 bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
181
182 /* setup class code as bridge */
183 val = bcm_pcie_readl(PCIE_IDVAL3_REG);
184 val &= ~IDVAL3_CLASS_CODE_MASK;
185 val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
186 bcm_pcie_writel(val, PCIE_IDVAL3_REG);
187
188 /* disable bar1 size */
189 val = bcm_pcie_readl(PCIE_CONFIG2_REG);
190 val &= ~CONFIG2_BAR1_SIZE_MASK;
191 bcm_pcie_writel(val, PCIE_CONFIG2_REG);
192
193 /* set bar0 to little endian */
194 val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
195 val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
196 val |= BASEMASK_REMAP_EN;
197 bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
198
199 val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
200 bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
201
202 register_pci_controller(&bcm63xx_pcie_controller);
203
204 return 0;
205}
206
97static int __init bcm63xx_register_pci(void) 207static int __init bcm63xx_register_pci(void)
98{ 208{
99 unsigned int mem_size; 209 unsigned int mem_size;
@@ -221,6 +331,8 @@ static int __init bcm63xx_pci_init(void)
221 return -ENODEV; 331 return -ENODEV;
222 332
223 switch (bcm63xx_get_cpu_id()) { 333 switch (bcm63xx_get_cpu_id()) {
334 case BCM6328_CPU_ID:
335 return bcm63xx_register_pcie();
224 case BCM6348_CPU_ID: 336 case BCM6348_CPU_ID:
225 case BCM6358_CPU_ID: 337 case BCM6358_CPU_ID:
226 case BCM6368_CPU_ID: 338 case BCM6368_CPU_ID:
diff --git a/arch/mips/pci/pci-bcm63xx.h b/arch/mips/pci/pci-bcm63xx.h
index a6e594ef3d6a..e6736d558ac7 100644
--- a/arch/mips/pci/pci-bcm63xx.h
+++ b/arch/mips/pci/pci-bcm63xx.h
@@ -13,11 +13,16 @@
13 */ 13 */
14#define CARDBUS_PCI_IDSEL 0x8 14#define CARDBUS_PCI_IDSEL 0x8
15 15
16
17#define PCIE_BUS_BRIDGE 0
18#define PCIE_BUS_DEVICE 1
19
16/* 20/*
17 * defined in ops-bcm63xx.c 21 * defined in ops-bcm63xx.c
18 */ 22 */
19extern struct pci_ops bcm63xx_pci_ops; 23extern struct pci_ops bcm63xx_pci_ops;
20extern struct pci_ops bcm63xx_cb_ops; 24extern struct pci_ops bcm63xx_cb_ops;
25extern struct pci_ops bcm63xx_pcie_ops;
21 26
22/* 27/*
23 * defined in pci-bcm63xx.c 28 * defined in pci-bcm63xx.c