1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
From 11a8ab8dac4ef5d0d70199843043927edce1d4db Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 15 Dec 2013 20:47:34 +0100
Subject: [PATCH 53/53] MIPS: BCM63XX: add PCIe support for BCM6318
---
arch/mips/bcm63xx/clk.c | 25 ++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 6 ++
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 60 +++++++++++-
arch/mips/pci/ops-bcm63xx.c | 16 +++-
arch/mips/pci/pci-bcm63xx.c | 106 ++++++++++++++++++----
5 files changed, 184 insertions(+), 29 deletions(-)
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -52,6 +52,18 @@ static void bcm_hwclock_set(u32 mask, in
bcm_perf_writel(reg, PERF_CKCTL_REG);
}
+static void bcm_ub_hwclock_set(u32 mask, int enable)
+{
+ u32 reg;
+
+ reg = bcm_perf_readl(PERF_UB_CKCTL_REG);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ bcm_perf_writel(reg, PERF_UB_CKCTL_REG);
+}
+
/*
* Ethernet MAC "misc" clock: dma clocks and main clock on 6348
*/
@@ -362,12 +374,17 @@ static struct clk clk_ipsec = {
static void pcie_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6328())
+ if (BCMCPU_IS_6318()) {
+ bcm_hwclock_set(CKCTL_6318_PCIE_EN, enable);
+ bcm_hwclock_set(CKCTL_6318_PCIE25_EN, enable);
+ bcm_ub_hwclock_set(UB_CKCTL_6318_PCIE_EN, enable);
+ } else if (BCMCPU_IS_6328()) {
bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
- else if (BCMCPU_IS_6362())
+ } else if (BCMCPU_IS_6362()) {
bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
- else if (BCMCPU_IS_63268())
+ } else if (BCMCPU_IS_63268()) {
bcm_hwclock_set(CKCTL_63268_PCIE_EN, enable);
+ }
}
static struct clk clk_pcie = {
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
@@ -41,6 +41,12 @@
#define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
BCM_CB_MEM_SIZE - 1)
+#define BCM_PCIE_MEM_BASE_PA_6318 0x10200000
+#define BCM_PCIE_MEM_SIZE_6318 (1 * 1024 * 1024)
+#define BCM_PCIE_MEM_END_PA_6318 (BCM_PCIE_MEM_BASE_PA_6318 + \
+ BCM_PCIE_MEM_SIZE_6318 - 1)
+
+
#define BCM_PCIE_MEM_BASE_PA_6328 0x10f00000
#define BCM_PCIE_MEM_SIZE_6328 (1 * 1024 * 1024)
#define BCM_PCIE_MEM_END_PA_6328 (BCM_PCIE_MEM_BASE_PA_6328 + \
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -1530,6 +1530,17 @@
* _REG relative to RSET_PCIE
*************************************************************************/
+#define PCIE_SPECIFIC_REG 0x188
+#define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0
+#define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2
+#define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4
+#define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
+#define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0
+#define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1
+#define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2
+
#define PCIE_CONFIG2_REG 0x408
#define CONFIG2_BAR1_SIZE_EN 1
#define CONFIG2_BAR1_SIZE_MASK 0xf
@@ -1575,7 +1586,54 @@
#define PCIE_RC_INT_C (1 << 2)
#define PCIE_RC_INT_D (1 << 3)
-#define PCIE_DEVICE_OFFSET 0x8000
+#define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c
+#define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3
+#define C2P_MEM_WIN_ENDIAN_NO_SWAP 0
+#define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1
+#define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2
+#define C2P_MEM_WIN_BASE_ADDR_SHIFT 20
+#define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT)
+
+#define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c
+#define RC_BAR_CFG_LO_SIZE_256MB 0xd
+#define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20
+#define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT)
+
+#define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070
+#define C2P_BASELIMIT_LIMIT_SHIFT 20
+#define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT)
+#define C2P_BASELIMIT_BASE_SHIFT 4
+#define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT)
+
+#define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088
+#define BAR1_CFG_REMAP_OFFSET_SHIFT 20
+#define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT)
+#define BAR1_CFG_REMAP_ACCESS_EN 1
+
+#define PCIE_HARD_DEBUG_REG 0x4204
+#define HARD_DEBUG_SERDES_IDDQ (1 << 23)
+
+#define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c
+#define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0)
+#define CPU_INT_PCIE_INTA (1 << 1)
+#define CPU_INT_PCIE_INTB (1 << 2)
+#define CPU_INT_PCIE_INTC (1 << 3)
+#define CPU_INT_PCIE_INTD (1 << 4)
+#define CPU_INT_PCIE_INTR (1 << 5)
+#define CPU_INT_PCIE_NMI (1 << 6)
+#define CPU_INT_PCIE_UBUS (1 << 7)
+#define CPU_INT_IPI (1 << 8)
+
+#define PCIE_EXT_CFG_INDEX_REG 0x8400
+#define EXT_CFG_FUNC_NUM_SHIFT 12
+#define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT)
+#define EXT_CFG_DEV_NUM_SHIFT 15
+#define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT)
+#define EXT_CFG_BUS_NUM_SHIFT 20
+#define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT)
+
+#define PCIE_DEVICE_OFFSET_6318 0x9000
+#define PCIE_DEVICE_OFFSET_6328 0x8000
/*************************************************************************
* _REG relative to RSET_OTP
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -488,8 +488,12 @@ static int bcm63xx_pcie_read(struct pci_
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus->number == PCIE_BUS_DEVICE)
- reg += PCIE_DEVICE_OFFSET;
+ if (bus->number == PCIE_BUS_DEVICE) {
+ if (BCMCPU_IS_6318())
+ reg += PCIE_DEVICE_OFFSET_6318;
+ else
+ reg += PCIE_DEVICE_OFFSET_6328;
+ }
data = bcm_pcie_readl(reg);
@@ -508,8 +512,12 @@ static int bcm63xx_pcie_write(struct pci
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus->number == PCIE_BUS_DEVICE)
- reg += PCIE_DEVICE_OFFSET;
+ if (bus->number == PCIE_BUS_DEVICE) {
+ if (BCMCPU_IS_6318())
+ reg += PCIE_DEVICE_OFFSET_6318;
+ else
+ reg += PCIE_DEVICE_OFFSET_6328;
+ }
data = bcm_pcie_readl(reg);
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -118,7 +118,7 @@ static void bcm63xx_int_cfg_writel(u32 v
void __iomem *pci_iospace_start;
-static void __init bcm63xx_reset_pcie(void)
+static void __init bcm63xx_reset_pcie_gen1(void)
{
u32 val;
u32 reg;
@@ -152,20 +152,32 @@ static void __init bcm63xx_reset_pcie(vo
mdelay(200);
}
-static struct clk *pcie_clk;
-
-static int __init bcm63xx_register_pcie(void)
+static void __init bcm63xx_reset_pcie_gen2(void)
{
u32 val;
- /* enable clock */
- pcie_clk = clk_get(NULL, "pcie");
- if (IS_ERR_OR_NULL(pcie_clk))
- return -ENODEV;
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 0);
- clk_prepare_enable(pcie_clk);
+ /* reset the PCIe core */
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 1);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
+ mdelay(10);
+ val = bcm_pcie_readl(PCIE_HARD_DEBUG_REG);
+ val &= ~HARD_DEBUG_SERDES_IDDQ;
+ bcm_pcie_writel(val, PCIE_HARD_DEBUG_REG);
+ mdelay(10);
+ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 0);
+ mdelay(200);
+}
- bcm63xx_reset_pcie();
+static void __init bcm63xx_init_pcie_gen1(void)
+{
+ u32 val;
/* configure the PCIe bridge */
val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
@@ -190,6 +202,65 @@ static int __init bcm63xx_register_pcie(
val |= OPT2_CFG_TYPE1_BD_SEL;
bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
+ /* set bar0 to little endian */
+ val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
+ val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
+ val |= BASEMASK_REMAP_EN;
+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
+
+ val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
+ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
+}
+
+static void __init bcm63xx_init_pcie_gen2(void)
+{
+ u32 val;
+
+ bcm_pcie_writel(CPU_INT_PCIE_INTA | CPU_INT_PCIE_INTB |
+ CPU_INT_PCIE_INTC | CPU_INT_PCIE_INTD,
+ PCIE_CPU_INT1_MASK_CLEAR_REG);
+
+ val = bcm_pcie_mem_resource.end & C2P_BASELIMIT_LIMIT_MASK;
+ val |= (bcm_pcie_mem_resource.start >> C2P_BASELIMIT_LIMIT_SHIFT) <<
+ C2P_BASELIMIT_BASE_SHIFT;
+
+ bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG);
+
+ /* set bar0 to little endian */
+ val = bcm_pcie_readl(PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
+ val |= bcm_pcie_mem_resource.start & C2P_MEM_WIN_BASE_ADDR_MASK;
+ val |= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP;
+ bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
+
+ bcm_pcie_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN, PCIE_SPECIFIC_REG);
+ bcm_pcie_writel(RC_BAR_CFG_LO_SIZE_256MB, PCIE_RC_BAR1_CONFIG_LO_REG);
+ bcm_pcie_writel(BAR1_CFG_REMAP_ACCESS_EN, PCIE_UBUS_BAR1_CFG_REMAP_REG);
+
+ bcm_pcie_writel(PCIE_BUS_DEVICE << EXT_CFG_BUS_NUM_SHIFT,
+ PCIE_EXT_CFG_INDEX_REG);
+}
+
+static struct clk *pcie_clk;
+
+static int __init bcm63xx_register_pcie(void)
+{
+ u32 val;
+
+ /* enable clock */
+ pcie_clk = clk_get(NULL, "pcie");
+ if (IS_ERR_OR_NULL(pcie_clk))
+ return -ENODEV;
+
+ clk_prepare_enable(pcie_clk);
+
+ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
+ bcm63xx_reset_pcie_gen1();
+ bcm63xx_init_pcie_gen1();
+ } else {
+ bcm63xx_reset_pcie_gen2();
+ bcm63xx_init_pcie_gen2();
+ }
+
/* setup class code as bridge */
val = bcm_pcie_readl(PCIE_IDVAL3_REG);
val &= ~IDVAL3_CLASS_CODE_MASK;
@@ -201,15 +272,6 @@ static int __init bcm63xx_register_pcie(
val &= ~CONFIG2_BAR1_SIZE_MASK;
bcm_pcie_writel(val, PCIE_CONFIG2_REG);
- /* set bar0 to little endian */
- val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
- val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
- val |= BASEMASK_REMAP_EN;
- bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
-
- val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
- bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
-
register_pci_controller(&bcm63xx_pcie_controller);
return 0;
@@ -341,7 +403,10 @@ static int __init bcm63xx_pci_init(void)
if (!bcm63xx_pci_enabled)
return -ENODEV;
- if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
+ if (BCMCPU_IS_6318()) {
+ bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6318;
+ bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6318;
+ } if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6328;
bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6328;
} else if (BCMCPU_IS_63268()) {
@@ -350,6 +415,7 @@ static int __init bcm63xx_pci_init(void)
}
switch (bcm63xx_get_cpu_id()) {
+ case BCM6318_CPU_ID:
case BCM6328_CPU_ID:
case BCM6362_CPU_ID:
case BCM63268_CPU_ID:
|