bcm63xx: add preliminary support for bcm6328
[openwrt/svn-archive/archive.git] / target / linux / brcm63xx / patches-3.3 / 317-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch
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
5
6 Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
7 ---
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(+)
12
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
16
17 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
18 #endif
19 +
20 +static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
21 +{
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;
29 + default:
30 + return false;
31 + }
32 +}
33 +
34 +static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
35 + int where, int size, u32 *val)
36 +{
37 + u32 data;
38 + u32 reg = where & ~3;
39 +
40 + if (!bcm63xx_pcie_can_access(bus, devfn))
41 + return PCIBIOS_DEVICE_NOT_FOUND;
42 +
43 + if (bus->number == PCIE_BUS_DEVICE)
44 + reg += PCIE_DEVICE_OFFSET;
45 +
46 + data = bcm_pcie_readl(reg);
47 +
48 + *val = postprocess_read(data, where, size);
49 +
50 + return PCIBIOS_SUCCESSFUL;
51 +
52 +}
53 +
54 +static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
55 + int where, int size, u32 val)
56 +{
57 + u32 data;
58 + u32 reg = where & ~3;
59 +
60 + if (!bcm63xx_pcie_can_access(bus, devfn))
61 + return PCIBIOS_DEVICE_NOT_FOUND;
62 +
63 + if (bus->number == PCIE_BUS_DEVICE)
64 + reg += PCIE_DEVICE_OFFSET;
65 +
66 +
67 + data = bcm_pcie_readl(reg);
68 +
69 + data = preprocess_write(data, val, where, size);
70 + bcm_pcie_writel(data, reg);
71 +
72 + return PCIBIOS_SUCCESSFUL;
73 +}
74 +
75 +
76 +struct pci_ops bcm63xx_pcie_ops = {
77 + .read = bcm63xx_pcie_read,
78 + .write = bcm63xx_pcie_write
79 +};
80 --- a/arch/mips/pci/pci-bcm63xx.c
81 +++ b/arch/mips/pci/pci-bcm63xx.c
82 @@ -10,6 +10,7 @@
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>
88
89 #include "pci-bcm63xx.h"
90 @@ -65,6 +66,26 @@ struct pci_controller bcm63xx_cb_control
91 };
92 #endif
93
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,
99 +};
100 +
101 +static struct resource bcm_pcie_io_resource = {
102 + .name = "bcm63xx PCIe IO space",
103 + .start = 0,
104 + .end = 0,
105 + .flags = 0,
106 +};
107 +
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,
112 +};
113 +
114 static u32 bcm63xx_int_cfg_readl(u32 reg)
115 {
116 u32 tmp;
117 @@ -88,6 +109,95 @@ static void bcm63xx_int_cfg_writel(u32 v
118
119 void __iomem *pci_iospace_start;
120
121 +static void __init bcm63xx_reset_pcie(void)
122 +{
123 + u32 val;
124 +
125 + /* enable clock */
126 + val = bcm_perf_readl(PERF_CKCTL_REG);
127 + val |= CKCTL_6328_PCIE_EN;
128 + bcm_perf_writel(val, PERF_CKCTL_REG);
129 +
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);
134 +
135 + /* reset the PCIe core */
136 + val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
137 +
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);
143 + mdelay(10);
144 +
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);
149 + mdelay(10);
150 +
151 + val |= SOFTRESET_6328_PCIE_EXT_MASK;
152 + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
153 + mdelay(200);
154 +}
155 +
156 +static int __init bcm63xx_register_pcie(void)
157 +{
158 + u32 val;
159 +
160 + bcm63xx_reset_pcie();
161 +
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);
169 +
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);
174 +
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;
179 +
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);
184 +
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);
190 +
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);
195 +
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);
201 +
202 + val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
203 + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
204 +
205 + register_pci_controller(&bcm63xx_pcie_controller);
206 +
207 + return 0;
208 +}
209 +
210 static int __init bcm63xx_register_pci(void)
211 {
212 unsigned int mem_size;
213 @@ -211,6 +321,8 @@ static int __init bcm63xx_register_pci(v
214 int __init bcm63xx_pci_register(void)
215 {
216 switch (bcm63xx_get_cpu_id()) {
217 + case BCM6328_CPU_ID:
218 + return bcm63xx_register_pcie();
219 case BCM6348_CPU_ID:
220 case BCM6358_CPU_ID:
221 case BCM6368_CPU_ID:
222 --- a/arch/mips/pci/pci-bcm63xx.h
223 +++ b/arch/mips/pci/pci-bcm63xx.h
224 @@ -13,11 +13,16 @@
225 */
226 #define CARDBUS_PCI_IDSEL 0x8
227
228 +
229 +#define PCIE_BUS_BRIDGE 0
230 +#define PCIE_BUS_DEVICE 1
231 +
232 /*
233 * defined in ops-bcm63xx.c
234 */
235 extern struct pci_ops bcm63xx_pci_ops;
236 extern struct pci_ops bcm63xx_cb_ops;
237 +extern struct pci_ops bcm63xx_pcie_ops;
238
239 /*
240 * defined in pci-bcm63xx.c