brcm63xx: spi flash on legacy spi controller needs the workaround
[openwrt/svn-archive/archive.git] / target / linux / brcm63xx / patches-3.10 / 103-MIPS-bmips-change-compile-time-checks-to-runtime-che.patch
1 From 12594762fcbec024cb424c9b77efb28402651667 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jogo@openwrt.org>
3 Date: Thu, 27 Jun 2013 21:33:56 +0200
4 Subject: [PATCH 04/10] MIPS: bmips: change compile time checks to runtime
5 checks
6
7 Allow building for all bmips cpus at the same time by changing ifdefs
8 to checks for the cpu type, or adding appropriate checks to the
9 assembly.
10
11 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
12 ---
13 arch/mips/kernel/bmips_vec.S | 55 +++++++---
14 arch/mips/kernel/smp-bmips.c | 241 ++++++++++++++++++++++--------------------
15 2 files changed, 172 insertions(+), 124 deletions(-)
16
17 --- a/arch/mips/kernel/bmips_vec.S
18 +++ b/arch/mips/kernel/bmips_vec.S
19 @@ -13,6 +13,7 @@
20 #include <asm/asm.h>
21 #include <asm/asmmacro.h>
22 #include <asm/cacheops.h>
23 +#include <asm/cpu.h>
24 #include <asm/regdef.h>
25 #include <asm/mipsregs.h>
26 #include <asm/stackframe.h>
27 @@ -89,12 +90,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
28 beqz k0, bmips_smp_entry
29
30 #if defined(CONFIG_CPU_BMIPS5000)
31 + mfc0 k0, CP0_PRID
32 + li k1, PRID_IMP_BMIPS5000
33 + andi k0, 0xff00
34 + bne k0, k1, 1f
35 +
36 /* if we're not on core 0, this must be the SMP boot signal */
37 li k1, (3 << 25)
38 mfc0 k0, $22
39 and k0, k1
40 bnez k0, bmips_smp_entry
41 -#endif
42 +1:
43 +#endif /* CONFIG_CPU_BMIPS5000 */
44 #endif /* CONFIG_SMP */
45
46 /* nope, it's just a regular NMI */
47 @@ -137,7 +144,12 @@ bmips_smp_entry:
48 xori k0, 0x04
49 mtc0 k0, CP0_CONFIG
50
51 + mfc0 k0, CP0_PRID
52 + andi k0, 0xff00
53 #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
54 + li k1, PRID_IMP_BMIPS43XX
55 + bne k0, k1, 2f
56 +
57 /* initialize CPU1's local I-cache */
58 li k0, 0x80000000
59 li k1, 0x80010000
60 @@ -148,14 +160,21 @@ bmips_smp_entry:
61 1: cache Index_Store_Tag_I, 0(k0)
62 addiu k0, 16
63 bne k0, k1, 1b
64 -#elif defined(CONFIG_CPU_BMIPS5000)
65 +
66 + b 3f
67 +2:
68 +#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
69 +#if defined(CONFIG_CPU_BMIPS5000)
70 /* set exception vector base */
71 + li k1, PRID_IMP_BMIPS5000
72 + bne k0, k1, 3f
73 +
74 la k0, ebase
75 lw k0, 0(k0)
76 mtc0 k0, $15, 1
77 BARRIER
78 -#endif
79 -
80 +#endif /* CONFIG_CPU_BMIPS5000 */
81 +3:
82 /* jump back to kseg0 in case we need to remap the kseg1 area */
83 la k0, 1f
84 jr k0
85 @@ -221,8 +240,18 @@ END(bmips_smp_int_vec)
86 LEAF(bmips_enable_xks01)
87
88 #if defined(CONFIG_XKS01)
89 -
90 + mfc0 t0, CP0_PRID
91 + andi t2, t0, 0xff00
92 #if defined(CONFIG_CPU_BMIPS4380)
93 + li t1, PRID_IMP_BMIPS43XX
94 + bne t2, t1, 1f
95 +
96 + andi t0, 0xff
97 + addiu t1, t0, -PRID_REV_BMIPS4380_HI
98 + bgtz t1, 2f
99 + addiu t0, -PRID_REV_BMIPS4380_LO
100 + bltz t0, 2f
101 +
102 mfc0 t0, $22, 3
103 li t1, 0x1ff0
104 li t2, (1 << 12) | (1 << 9)
105 @@ -231,7 +260,13 @@ LEAF(bmips_enable_xks01)
106 or t0, t2
107 mtc0 t0, $22, 3
108 BARRIER
109 -#elif defined(CONFIG_CPU_BMIPS5000)
110 + b 2f
111 +1:
112 +#endif /* CONFIG_CPU_BMIPS4380 */
113 +#if defined(CONFIG_CPU_BMIPS5000)
114 + li t1, PRID_IMP_BMIPS5000
115 + bne t2, t1, 2f
116 +
117 mfc0 t0, $22, 5
118 li t1, 0x01ff
119 li t2, (1 << 8) | (1 << 5)
120 @@ -240,12 +275,8 @@ LEAF(bmips_enable_xks01)
121 or t0, t2
122 mtc0 t0, $22, 5
123 BARRIER
124 -#else
125 -
126 -#error Missing XKS01 setup
127 -
128 -#endif
129 -
130 +#endif /* CONFIG_CPU_BMIPS5000 */
131 +2:
132 #endif /* defined(CONFIG_XKS01) */
133
134 jr ra
135 --- a/arch/mips/kernel/smp-bmips.c
136 +++ b/arch/mips/kernel/smp-bmips.c
137 @@ -49,8 +49,11 @@ cpumask_t bmips_booted_mask;
138 unsigned long bmips_smp_boot_sp;
139 unsigned long bmips_smp_boot_gp;
140
141 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
142 +static void bmips5000_send_ipi_single(int cpu, unsigned int action);
143 static void bmips_send_ipi_single(int cpu, unsigned int action);
144 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
145 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
146 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
147
148 /* SW interrupts 0,1 are used for interprocessor signaling */
149 #define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0)
150 @@ -65,48 +68,49 @@ static void __init bmips_smp_setup(void)
151 {
152 int i, cpu = 1, boot_cpu = 0;
153
154 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
155 - /* arbitration priority */
156 - clear_c0_brcm_cmt_ctrl(0x30);
157 -
158 - /* NBK and weak order flags */
159 - set_c0_brcm_config_0(0x30000);
160 -
161 - /* Find out if we are running on TP0 or TP1 */
162 - boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
163 -
164 - /*
165 - * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
166 - * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
167 - * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
168 - *
169 - * If booting from TP1, leave the existing CMT interrupt routing
170 - * such that TP0 responds to SW1 and TP1 responds to SW0.
171 - */
172 - if (boot_cpu == 0)
173 - change_c0_brcm_cmt_intr(0xf8018000,
174 + if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
175 + /* arbitration priority */
176 + clear_c0_brcm_cmt_ctrl(0x30);
177 +
178 + /* NBK and weak order flags */
179 + set_c0_brcm_config_0(0x30000);
180 +
181 + /* Find out if we are running on TP0 or TP1 */
182 + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
183 +
184 + /*
185 + * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
186 + * thread
187 + * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
188 + * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
189 + *
190 + * If booting from TP1, leave the existing CMT interrupt routing
191 + * such that TP0 responds to SW1 and TP1 responds to SW0.
192 + */
193 + if (boot_cpu == 0)
194 + change_c0_brcm_cmt_intr(0xf8018000,
195 (0x02 << 27) | (0x03 << 15));
196 - else
197 - change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
198 -
199 - /* single core, 2 threads (2 pipelines) */
200 - max_cpus = 2;
201 -#elif defined(CONFIG_CPU_BMIPS5000)
202 - /* enable raceless SW interrupts */
203 - set_c0_brcm_config(0x03 << 22);
204 -
205 - /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
206 - change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
207 + else
208 + change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
209
210 - /* N cores, 2 threads per core */
211 - max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
212 -
213 - /* clear any pending SW interrupts */
214 - for (i = 0; i < max_cpus; i++) {
215 - write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
216 - write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
217 + /* single core, 2 threads (2 pipelines) */
218 + max_cpus = 2;
219 + } else if (cpu_is_bmips5000()) {
220 + /* enable raceless SW interrupts */
221 + set_c0_brcm_config(0x03 << 22);
222 +
223 + /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
224 + change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
225 +
226 + /* N cores, 2 threads per core */
227 + max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
228 +
229 + /* clear any pending SW interrupts */
230 + for (i = 0; i < max_cpus; i++) {
231 + write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
232 + write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
233 + }
234 }
235 -#endif
236
237 if (!bmips_smp_enabled)
238 max_cpus = 1;
239 @@ -134,6 +138,15 @@ static void __init bmips_smp_setup(void)
240 */
241 static void bmips_prepare_cpus(unsigned int max_cpus)
242 {
243 + irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
244 +
245 + if (cpu_is_bmips4350() || cpu_is_bmips4380())
246 + bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
247 + else if (cpu_is_bmips5000())
248 + bmips_ipi_interrupt = bmips5000_ipi_interrupt;
249 + else
250 + return;
251 +
252 if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
253 "smp_ipi0", NULL))
254 panic("Can't request IPI0 interrupt\n");
255 @@ -168,26 +181,26 @@ static void bmips_boot_secondary(int cpu
256
257 pr_info("SMP: Booting CPU%d...\n", cpu);
258
259 - if (cpumask_test_cpu(cpu, &bmips_booted_mask))
260 + if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
261 bmips_send_ipi_single(cpu, 0);
262 - else {
263 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
264 - /* Reset slave TP1 if booting from TP0 */
265 - if (cpu_logical_map(cpu) == 0)
266 - set_c0_brcm_cmt_ctrl(0x01);
267 -#elif defined(CONFIG_CPU_BMIPS5000)
268 - if (cpu & 0x01)
269 - write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
270 - else {
271 - /*
272 - * core N thread 0 was already booted; just
273 - * pulse the NMI line
274 - */
275 - bmips_write_zscm_reg(0x210, 0xc0000000);
276 - udelay(10);
277 - bmips_write_zscm_reg(0x210, 0x00);
278 + } else {
279 + if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
280 + /* Reset slave TP1 if booting from TP0 */
281 + if (cpu_logical_map(cpu) == 0)
282 + set_c0_brcm_cmt_ctrl(0x01);
283 + } else if (cpu_is_bmips5000()) {
284 + if (cpu & 0x01)
285 + write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
286 + else {
287 + /*
288 + * core N thread 0 was already booted; just
289 + * pulse the NMI line
290 + */
291 + bmips_write_zscm_reg(0x210, 0xc0000000);
292 + udelay(10);
293 + bmips_write_zscm_reg(0x210, 0x00);
294 + }
295 }
296 -#endif
297 cpumask_set_cpu(cpu, &bmips_booted_mask);
298 }
299 }
300 @@ -199,20 +212,21 @@ static void bmips_init_secondary(void)
301 {
302 /* move NMI vector to kseg0, in case XKS01 is enabled */
303
304 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
305 - void __iomem *cbr = BMIPS_GET_CBR();
306 - unsigned long old_vec;
307 -
308 - old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
309 - __raw_writel(old_vec & ~0x20000000, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
310 -
311 - clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
312 -#elif defined(CONFIG_CPU_BMIPS5000)
313 - write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
314 - (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
315 + if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
316 + void __iomem *cbr = BMIPS_GET_CBR();
317 + unsigned long old_vec;
318 +
319 + old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
320 + __raw_writel(old_vec & ~0x20000000,
321 + cbr + BMIPS_RELO_VECTOR_CONTROL_1);
322 +
323 + clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
324 + } else if (cpu_is_bmips5000()) {
325 + write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
326 + (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
327
328 - write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
329 -#endif
330 + write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
331 + }
332 }
333
334 /*
335 @@ -237,8 +251,6 @@ static void bmips_cpus_done(void)
336 {
337 }
338
339 -#if defined(CONFIG_CPU_BMIPS5000)
340 -
341 /*
342 * BMIPS5000 raceless IPIs
343 *
344 @@ -247,12 +259,12 @@ static void bmips_cpus_done(void)
345 * IPI1 is used for SMP_CALL_FUNCTION
346 */
347
348 -static void bmips_send_ipi_single(int cpu, unsigned int action)
349 +static void bmips5000_send_ipi_single(int cpu, unsigned int action)
350 {
351 write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
352 }
353
354 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
355 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
356 {
357 int action = irq - IPI0_IRQ;
358
359 @@ -266,8 +278,6 @@ static irqreturn_t bmips_ipi_interrupt(i
360 return IRQ_HANDLED;
361 }
362
363 -#else
364 -
365 /*
366 * BMIPS43xx racey IPIs
367 *
368 @@ -281,7 +291,7 @@ static irqreturn_t bmips_ipi_interrupt(i
369 static DEFINE_SPINLOCK(ipi_lock);
370 static DEFINE_PER_CPU(int, ipi_action_mask);
371
372 -static void bmips_send_ipi_single(int cpu, unsigned int action)
373 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
374 {
375 unsigned long flags;
376
377 @@ -292,7 +302,7 @@ static void bmips_send_ipi_single(int cp
378 spin_unlock_irqrestore(&ipi_lock, flags);
379 }
380
381 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
382 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
383 {
384 unsigned long flags;
385 int action, cpu = irq - IPI0_IRQ;
386 @@ -311,7 +321,13 @@ static irqreturn_t bmips_ipi_interrupt(i
387 return IRQ_HANDLED;
388 }
389
390 -#endif /* BMIPS type */
391 +static void bmips_send_ipi_single(int cpu, unsigned int action)
392 +{
393 + if (cpu_is_bmips4350() || cpu_is_bmips4380())
394 + bmips43xx_send_ipi_single(cpu, action);
395 + else if (cpu_is_bmips5000())
396 + bmips5000_send_ipi_single(cpu, action);
397 +}
398
399 static void bmips_send_ipi_mask(const struct cpumask *mask,
400 unsigned int action)
401 @@ -421,43 +437,44 @@ void __cpuinit bmips_ebase_setup(void)
402
403 BUG_ON(ebase != CKSEG0);
404
405 -#if defined(CONFIG_CPU_BMIPS4350)
406 - /*
407 - * BMIPS4350 cannot relocate the normal vectors, but it
408 - * can relocate the BEV=1 vectors. So CPU1 starts up at
409 - * the relocated BEV=1, IV=0 general exception vector @
410 - * 0xa000_0380.
411 - *
412 - * set_uncached_handler() is used here because:
413 - * - CPU1 will run this from uncached space
414 - * - None of the cacheflush functions are set up yet
415 - */
416 - set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
417 - &bmips_smp_int_vec, 0x80);
418 - __sync();
419 - return;
420 -#elif defined(CONFIG_CPU_BMIPS4380)
421 - /*
422 - * 0x8000_0000: reset/NMI (initially in kseg1)
423 - * 0x8000_0400: normal vectors
424 - */
425 - new_ebase = 0x80000400;
426 - cbr = BMIPS_GET_CBR();
427 - __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
428 - __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
429 -#elif defined(CONFIG_CPU_BMIPS5000)
430 - /*
431 - * 0x8000_0000: reset/NMI (initially in kseg1)
432 - * 0x8000_1000: normal vectors
433 - */
434 - new_ebase = 0x80001000;
435 - write_c0_brcm_bootvec(0xa0088008);
436 - write_c0_ebase(new_ebase);
437 - if (max_cpus > 2)
438 - bmips_write_zscm_reg(0xa0, 0xa008a008);
439 -#else
440 - return;
441 -#endif
442 + if (cpu_is_bmips4350()) {
443 + /*
444 + * BMIPS4350 cannot relocate the normal vectors, but it
445 + * can relocate the BEV=1 vectors. So CPU1 starts up at
446 + * the relocated BEV=1, IV=0 general exception vector @
447 + * 0xa000_0380.
448 + *
449 + * set_uncached_handler() is used here because:
450 + * - CPU1 will run this from uncached space
451 + * - None of the cacheflush functions are set up yet
452 + */
453 + set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
454 + &bmips_smp_int_vec, 0x80);
455 + __sync();
456 + return;
457 + } else if (cpu_is_bmips4380()) {
458 + /*
459 + * 0x8000_0000: reset/NMI (initially in kseg1)
460 + * 0x8000_0400: normal vectors
461 + */
462 + new_ebase = 0x80000400;
463 + cbr = BMIPS_GET_CBR();
464 + __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
465 + __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
466 + } else if (cpu_is_bmips5000()) {
467 + /*
468 + * 0x8000_0000: reset/NMI (initially in kseg1)
469 + * 0x8000_1000: normal vectors
470 + */
471 + new_ebase = 0x80001000;
472 + write_c0_brcm_bootvec(0xa0088008);
473 + write_c0_ebase(new_ebase);
474 + if (max_cpus > 2)
475 + bmips_write_zscm_reg(0xa0, 0xa008a008);
476 + } else {
477 + return;
478 + }
479 +
480 board_nmi_handler_setup = &bmips_nmi_handler_setup;
481 ebase = new_ebase;
482 }