1 From e170282d7d12f4a26f10d4b666b158d24810d2f6 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jonas.gorski@gmail.com>
3 Date: Sun, 3 Jul 2011 03:41:02 +0200
4 Subject: [PATCH 47/79] MIPS: BCM63XX: Add PCIe Support for BCM6328
6 Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
8 arch/mips/pci/ops-bcm63xx.c | 61 +++++++++++++++++++++++
9 arch/mips/pci/pci-bcm63xx.c | 112 +++++++++++++++++++++++++++++++++++++++++++
10 arch/mips/pci/pci-bcm63xx.h | 5 ++
11 3 files changed, 178 insertions(+)
13 --- a/arch/mips/pci/ops-bcm63xx.c
14 +++ b/arch/mips/pci/ops-bcm63xx.c
15 @@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev
17 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
20 +static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
22 + switch (bus->number) {
23 + case PCIE_BUS_BRIDGE:
24 + return (PCI_SLOT(devfn) == 0);
25 + case PCIE_BUS_DEVICE:
26 + if (PCI_SLOT(devfn) == 0)
27 + return bcm_pcie_readl(PCIE_DLSTATUS_REG)
28 + & DLSTATUS_PHYLINKUP;
34 +static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
35 + int where, int size, u32 *val)
38 + u32 reg = where & ~3;
40 + if (!bcm63xx_pcie_can_access(bus, devfn))
41 + return PCIBIOS_DEVICE_NOT_FOUND;
43 + if (bus->number == PCIE_BUS_DEVICE)
44 + reg += PCIE_DEVICE_OFFSET;
46 + data = bcm_pcie_readl(reg);
48 + *val = postprocess_read(data, where, size);
50 + return PCIBIOS_SUCCESSFUL;
54 +static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
55 + int where, int size, u32 val)
58 + u32 reg = where & ~3;
60 + if (!bcm63xx_pcie_can_access(bus, devfn))
61 + return PCIBIOS_DEVICE_NOT_FOUND;
63 + if (bus->number == PCIE_BUS_DEVICE)
64 + reg += PCIE_DEVICE_OFFSET;
67 + data = bcm_pcie_readl(reg);
69 + data = preprocess_write(data, val, where, size);
70 + bcm_pcie_writel(data, reg);
72 + return PCIBIOS_SUCCESSFUL;
76 +struct pci_ops bcm63xx_pcie_ops = {
77 + .read = bcm63xx_pcie_read,
78 + .write = bcm63xx_pcie_write
80 --- a/arch/mips/pci/pci-bcm63xx.c
81 +++ b/arch/mips/pci/pci-bcm63xx.c
83 #include <linux/pci.h>
84 #include <linux/kernel.h>
85 #include <linux/init.h>
86 +#include <linux/delay.h>
87 #include <asm/bootinfo.h>
89 #include "pci-bcm63xx.h"
90 @@ -65,6 +66,26 @@ struct pci_controller bcm63xx_cb_control
94 +static struct resource bcm_pcie_mem_resource = {
95 + .name = "bcm63xx PCIe memory space",
96 + .start = BCM_PCIE_MEM_BASE_PA,
97 + .end = BCM_PCIE_MEM_END_PA,
98 + .flags = IORESOURCE_MEM,
101 +static struct resource bcm_pcie_io_resource = {
102 + .name = "bcm63xx PCIe IO space",
108 +struct pci_controller bcm63xx_pcie_controller = {
109 + .pci_ops = &bcm63xx_pcie_ops,
110 + .io_resource = &bcm_pcie_io_resource,
111 + .mem_resource = &bcm_pcie_mem_resource,
114 static u32 bcm63xx_int_cfg_readl(u32 reg)
117 @@ -88,6 +109,95 @@ static void bcm63xx_int_cfg_writel(u32 v
119 void __iomem *pci_iospace_start;
121 +static void __init bcm63xx_reset_pcie(void)
126 + val = bcm_perf_readl(PERF_CKCTL_REG);
127 + val |= CKCTL_6328_PCIE_EN;
128 + bcm_perf_writel(val, PERF_CKCTL_REG);
130 + /* enable SERDES */
131 + val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
132 + val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
133 + bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
135 + /* reset the PCIe core */
136 + val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
138 + val &= ~SOFTRESET_6328_PCIE_MASK;
139 + val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
140 + val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
141 + val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
142 + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
145 + val |= SOFTRESET_6328_PCIE_MASK;
146 + val |= SOFTRESET_6328_PCIE_CORE_MASK;
147 + val |= SOFTRESET_6328_PCIE_HARD_MASK;
148 + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
151 + val |= SOFTRESET_6328_PCIE_EXT_MASK;
152 + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
156 +static int __init bcm63xx_register_pcie(void)
160 + bcm63xx_reset_pcie();
162 + /* configure the PCIe bridge */
163 + val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
164 + val |= OPT1_RD_BE_OPT_EN;
165 + val |= OPT1_RD_REPLY_BE_FIX_EN;
166 + val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
167 + val |= OPT1_L1_INT_STATUS_MASK_POL;
168 + bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
170 + /* setup the interrupts */
171 + val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
172 + val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
173 + bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
175 + val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
176 + /* enable credit checking and error checking */
177 + val |= OPT2_TX_CREDIT_CHK_EN;
178 + val |= OPT2_UBUS_UR_DECODE_DIS;
180 + /* set device bus/func for the pcie device */
181 + val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
182 + val |= OPT2_CFG_TYPE1_BD_SEL;
183 + bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
185 + /* setup class code as bridge */
186 + val = bcm_pcie_readl(PCIE_IDVAL3_REG);
187 + val &= ~IDVAL3_CLASS_CODE_MASK;
188 + val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
189 + bcm_pcie_writel(val, PCIE_IDVAL3_REG);
191 + /* disable bar1 size */
192 + val = bcm_pcie_readl(PCIE_CONFIG2_REG);
193 + val &= ~CONFIG2_BAR1_SIZE_MASK;
194 + bcm_pcie_writel(val, PCIE_CONFIG2_REG);
196 + /* set bar0 to little endian */
197 + val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
198 + val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
199 + val |= BASEMASK_REMAP_EN;
200 + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
202 + val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
203 + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
205 + register_pci_controller(&bcm63xx_pcie_controller);
210 static int __init bcm63xx_register_pci(void)
212 unsigned int mem_size;
213 @@ -211,6 +321,8 @@ static int __init bcm63xx_register_pci(v
214 int __init bcm63xx_pci_register(void)
216 switch (bcm63xx_get_cpu_id()) {
217 + case BCM6328_CPU_ID:
218 + return bcm63xx_register_pcie();
222 --- a/arch/mips/pci/pci-bcm63xx.h
223 +++ b/arch/mips/pci/pci-bcm63xx.h
226 #define CARDBUS_PCI_IDSEL 0x8
229 +#define PCIE_BUS_BRIDGE 0
230 +#define PCIE_BUS_DEVICE 1
233 * defined in ops-bcm63xx.c
235 extern struct pci_ops bcm63xx_pci_ops;
236 extern struct pci_ops bcm63xx_cb_ops;
237 +extern struct pci_ops bcm63xx_pcie_ops;
240 * defined in pci-bcm63xx.c