Root/target/linux/brcm47xx/patches-3.2/150-cpu_fixes.patch

1--- a/arch/mips/include/asm/r4kcache.h
2+++ b/arch/mips/include/asm/r4kcache.h
3@@ -17,6 +17,20 @@
4 #include <asm/cpu-features.h>
5 #include <asm/mipsmtregs.h>
6 
7+#ifdef CONFIG_BCM47XX
8+#include <asm/paccess.h>
9+#include <linux/ssb/ssb.h>
10+#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE)))
11+
12+#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
13+#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
14+#else
15+#define BCM4710_DUMMY_RREG()
16+
17+#define BCM4710_FILL_TLB(addr)
18+#define BCM4710_PROTECTED_FILL_TLB(addr)
19+#endif
20+
21 /*
22  * This macro return a properly sign-extended address suitable as base address
23  * for indexed cache operations. Two issues here:
24@@ -150,6 +164,7 @@ static inline void flush_icache_line_ind
25 static inline void flush_dcache_line_indexed(unsigned long addr)
26 {
27     __dflush_prologue
28+ BCM4710_DUMMY_RREG();
29     cache_op(Index_Writeback_Inv_D, addr);
30     __dflush_epilogue
31 }
32@@ -169,6 +184,7 @@ static inline void flush_icache_line(uns
33 static inline void flush_dcache_line(unsigned long addr)
34 {
35     __dflush_prologue
36+ BCM4710_DUMMY_RREG();
37     cache_op(Hit_Writeback_Inv_D, addr);
38     __dflush_epilogue
39 }
40@@ -176,6 +192,7 @@ static inline void flush_dcache_line(uns
41 static inline void invalidate_dcache_line(unsigned long addr)
42 {
43     __dflush_prologue
44+ BCM4710_DUMMY_RREG();
45     cache_op(Hit_Invalidate_D, addr);
46     __dflush_epilogue
47 }
48@@ -208,6 +225,7 @@ static inline void flush_scache_line(uns
49  */
50 static inline void protected_flush_icache_line(unsigned long addr)
51 {
52+ BCM4710_DUMMY_RREG();
53     protected_cache_op(Hit_Invalidate_I, addr);
54 }
55 
56@@ -219,6 +237,7 @@ static inline void protected_flush_icach
57  */
58 static inline void protected_writeback_dcache_line(unsigned long addr)
59 {
60+ BCM4710_DUMMY_RREG();
61     protected_cache_op(Hit_Writeback_Inv_D, addr);
62 }
63 
64@@ -339,8 +358,52 @@ static inline void invalidate_tcache_pag
65         : "r" (base), \
66           "i" (op));
67 
68+static inline void blast_dcache(void)
69+{
70+ unsigned long start = KSEG0;
71+ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
72+ unsigned long end = (start + dcache_size);
73+
74+ do {
75+ BCM4710_DUMMY_RREG();
76+ cache_op(Index_Writeback_Inv_D, start);
77+ start += current_cpu_data.dcache.linesz;
78+ } while(start < end);
79+}
80+
81+static inline void blast_dcache_page(unsigned long page)
82+{
83+ unsigned long start = page;
84+ unsigned long end = start + PAGE_SIZE;
85+
86+ BCM4710_FILL_TLB(start);
87+ do {
88+ BCM4710_DUMMY_RREG();
89+ cache_op(Hit_Writeback_Inv_D, start);
90+ start += current_cpu_data.dcache.linesz;
91+ } while(start < end);
92+}
93+
94+static inline void blast_dcache_page_indexed(unsigned long page)
95+{
96+ unsigned long start = page;
97+ unsigned long end = start + PAGE_SIZE;
98+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
99+ unsigned long ws_end = current_cpu_data.dcache.ways <<
100+ current_cpu_data.dcache.waybit;
101+ unsigned long ws, addr;
102+ for (ws = 0; ws < ws_end; ws += ws_inc) {
103+ start = page + ws;
104+ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
105+ BCM4710_DUMMY_RREG();
106+ cache_op(Index_Writeback_Inv_D, addr);
107+ }
108+ }
109+}
110+
111+
112 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
113-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
114+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
115 static inline void blast_##pfx##cache##lsize(void) \
116 { \
117     unsigned long start = INDEX_BASE; \
118@@ -352,6 +415,7 @@ static inline void blast_##pfx##cache##l
119                                     \
120     __##pfx##flush_prologue \
121                                     \
122+ war \
123     for (ws = 0; ws < ws_end; ws += ws_inc) \
124         for (addr = start; addr < end; addr += lsize * 32) \
125             cache##lsize##_unroll32(addr|ws, indexop); \
126@@ -366,6 +430,7 @@ static inline void blast_##pfx##cache##l
127                                     \
128     __##pfx##flush_prologue \
129                                     \
130+ war \
131     do { \
132         cache##lsize##_unroll32(start, hitop); \
133         start += lsize * 32; \
134@@ -384,6 +449,8 @@ static inline void blast_##pfx##cache##l
135                            current_cpu_data.desc.waybit; \
136     unsigned long ws, addr; \
137                                     \
138+ war \
139+ \
140     __##pfx##flush_prologue \
141                                     \
142     for (ws = 0; ws < ws_end; ws += ws_inc) \
143@@ -393,36 +460,38 @@ static inline void blast_##pfx##cache##l
144     __##pfx##flush_epilogue \
145 }
146 
147-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
148-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
149-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
150-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
151-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
152-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
153-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
154-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
155-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
156-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
157-
158-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
159-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
160-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
161-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
162-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
163-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
164+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
165+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
166+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
167+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
168+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
169+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
170+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
171+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
172+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
173+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
174+
175+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
176+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
177+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
178+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
179+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
180+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
181 
182 /* build blast_xxx_range, protected_blast_xxx_range */
183-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
184+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
185 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
186                             unsigned long end) \
187 { \
188     unsigned long lsize = cpu_##desc##_line_size(); \
189     unsigned long addr = start & ~(lsize - 1); \
190     unsigned long aend = (end - 1) & ~(lsize - 1); \
191+ war \
192                                     \
193     __##pfx##flush_prologue \
194                                     \
195     while (1) { \
196+ war2 \
197         prot##cache_op(hitop, addr); \
198         if (addr == aend) \
199             break; \
200@@ -432,13 +501,13 @@ static inline void prot##blast_##pfx##ca
201     __##pfx##flush_epilogue \
202 }
203 
204-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
205-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
206-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
207-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
208-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
209+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
210+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
211+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
212+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
213+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
214 /* blast_inv_dcache_range */
215-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
216-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
217+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
218+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
219 
220 #endif /* _ASM_R4KCACHE_H */
221--- a/arch/mips/include/asm/stackframe.h
222+++ b/arch/mips/include/asm/stackframe.h
223@@ -449,6 +449,10 @@
224         .macro RESTORE_SP_AND_RET
225         LONG_L sp, PT_R29(sp)
226         .set mips3
227+#ifdef CONFIG_BCM47XX
228+ nop
229+ nop
230+#endif
231         eret
232         .set mips0
233         .endm
234--- a/arch/mips/kernel/genex.S
235+++ b/arch/mips/kernel/genex.S
236@@ -52,6 +52,10 @@ NESTED(except_vec1_generic, 0, sp)
237 NESTED(except_vec3_generic, 0, sp)
238     .set push
239     .set noat
240+#ifdef CONFIG_BCM47XX
241+ nop
242+ nop
243+#endif
244 #if R5432_CP0_INTERRUPT_WAR
245     mfc0 k0, CP0_INDEX
246 #endif
247--- a/arch/mips/mm/c-r4k.c
248+++ b/arch/mips/mm/c-r4k.c
249@@ -35,6 +35,9 @@
250 #include <asm/cacheflush.h> /* for run_uncached() */
251 
252 
253+/* For enabling BCM4710 cache workarounds */
254+int bcm4710 = 0;
255+
256 /*
257  * Special Variant of smp_call_function for use by cache functions:
258  *
259@@ -111,6 +114,9 @@ static void __cpuinit r4k_blast_dcache_p
260 {
261     unsigned long dc_lsize = cpu_dcache_line_size();
262 
263+ if (bcm4710)
264+ r4k_blast_dcache_page = blast_dcache_page;
265+ else
266     if (dc_lsize == 0)
267         r4k_blast_dcache_page = (void *)cache_noop;
268     else if (dc_lsize == 16)
269@@ -127,6 +133,9 @@ static void __cpuinit r4k_blast_dcache_p
270 {
271     unsigned long dc_lsize = cpu_dcache_line_size();
272 
273+ if (bcm4710)
274+ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
275+ else
276     if (dc_lsize == 0)
277         r4k_blast_dcache_page_indexed = (void *)cache_noop;
278     else if (dc_lsize == 16)
279@@ -143,6 +152,9 @@ static void __cpuinit r4k_blast_dcache_s
280 {
281     unsigned long dc_lsize = cpu_dcache_line_size();
282 
283+ if (bcm4710)
284+ r4k_blast_dcache = blast_dcache;
285+ else
286     if (dc_lsize == 0)
287         r4k_blast_dcache = (void *)cache_noop;
288     else if (dc_lsize == 16)
289@@ -683,6 +695,8 @@ static void local_r4k_flush_cache_sigtra
290     unsigned long addr = (unsigned long) arg;
291 
292     R4600_HIT_CACHEOP_WAR_IMPL;
293+ BCM4710_PROTECTED_FILL_TLB(addr);
294+ BCM4710_PROTECTED_FILL_TLB(addr + 4);
295     if (dc_lsize)
296         protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
297     if (!cpu_icache_snoops_remote_store && scache_size)
298@@ -1346,6 +1360,17 @@ static void __cpuinit coherency_setup(vo
299      * silly idea of putting something else there ...
300      */
301     switch (current_cpu_type()) {
302+ case CPU_BMIPS3300:
303+ {
304+ u32 cm;
305+ cm = read_c0_diag();
306+ /* Enable icache */
307+ cm |= (1 << 31);
308+ /* Enable dcache */
309+ cm |= (1 << 30);
310+ write_c0_diag(cm);
311+ }
312+ break;
313     case CPU_R4000PC:
314     case CPU_R4000SC:
315     case CPU_R4000MC:
316@@ -1402,6 +1427,15 @@ void __cpuinit r4k_cache_init(void)
317         break;
318     }
319 
320+ /* Check if special workarounds are required */
321+#ifdef CONFIG_BCM47XX
322+ if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) {
323+ printk("Enabling BCM4710A0 cache workarounds.\n");
324+ bcm4710 = 1;
325+ } else
326+#endif
327+ bcm4710 = 0;
328+
329     probe_pcache();
330     setup_scache();
331 
332@@ -1462,5 +1496,13 @@ void __cpuinit r4k_cache_init(void)
333 #if !defined(CONFIG_MIPS_CMP)
334     local_r4k___flush_cache_all(NULL);
335 #endif
336+#ifdef CONFIG_BCM47XX
337+ {
338+ static void (*_coherency_setup)(void);
339+ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
340+ _coherency_setup();
341+ }
342+#else
343     coherency_setup();
344+#endif
345 }
346--- a/arch/mips/mm/tlbex.c
347+++ b/arch/mips/mm/tlbex.c
348@@ -1264,6 +1264,9 @@ static void __cpuinit build_r4000_tlb_re
349             /* No need for uasm_i_nop */
350         }
351 
352+#ifdef CONFIG_BCM47XX
353+ uasm_i_nop(&p);
354+#endif
355 #ifdef CONFIG_64BIT
356         build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
357 #else
358@@ -1794,6 +1797,9 @@ build_r4000_tlbchange_handler_head(u32 *
359 {
360     struct work_registers wr = build_get_work_registers(p);
361 
362+#ifdef CONFIG_BCM47XX
363+ uasm_i_nop(p);
364+#endif
365 #ifdef CONFIG_64BIT
366     build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
367 #else
368

Archive Download this file



interactive