1 --- a/arch/mips/kernel/genex.S
2 +++ b/arch/mips/kernel/genex.S
4 NESTED(except_vec3_generic, 0, sp)
11 #if R5432_CP0_INTERRUPT_WAR
14 --- a/arch/mips/mm/c-r4k.c
15 +++ b/arch/mips/mm/c-r4k.c
17 #include <asm/cacheflush.h> /* for run_uncached() */
20 +/* For enabling BCM4710 cache workarounds */
24 * Special Variant of smp_call_function for use by cache functions:
28 unsigned long dc_lsize = cpu_dcache_line_size();
31 + r4k_blast_dcache_page = blast_dcache_page;
34 r4k_blast_dcache_page = (void *)cache_noop;
35 else if (dc_lsize == 16)
38 unsigned long dc_lsize = cpu_dcache_line_size();
41 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
44 r4k_blast_dcache_page_indexed = (void *)cache_noop;
45 else if (dc_lsize == 16)
48 unsigned long dc_lsize = cpu_dcache_line_size();
51 + r4k_blast_dcache = blast_dcache;
54 r4k_blast_dcache = (void *)cache_noop;
55 else if (dc_lsize == 16)
57 unsigned long addr = (unsigned long) arg;
59 R4600_HIT_CACHEOP_WAR_IMPL;
60 + BCM4710_PROTECTED_FILL_TLB(addr);
61 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
63 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
64 if (!cpu_icache_snoops_remote_store && scache_size)
65 @@ -1215,6 +1229,17 @@
66 * silly idea of putting something else there ...
68 switch (current_cpu_type()) {
72 + cm = read_c0_diag();
83 @@ -1254,6 +1279,15 @@
87 + /* Check if special workarounds are required */
88 +#ifdef CONFIG_BCM47XX
89 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
90 + printk("Enabling BCM4710A0 cache workarounds.\n");
99 @@ -1303,5 +1337,13 @@
102 local_r4k___flush_cache_all(NULL);
103 +#ifdef CONFIG_BCM47XX
105 + static void (*_coherency_setup)(void);
106 + _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
107 + _coherency_setup();
113 --- a/arch/mips/mm/tlbex.c
114 +++ b/arch/mips/mm/tlbex.c
116 /* No need for uasm_i_nop */
119 +#ifdef CONFIG_BCM47XX
123 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
125 @@ -1084,6 +1087,9 @@
126 struct uasm_reloc **r, unsigned int pte,
129 +#ifdef CONFIG_BCM47XX
133 build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
135 --- a/include/asm-mips/r4kcache.h
136 +++ b/include/asm-mips/r4kcache.h
138 #include <asm/cpu-features.h>
139 #include <asm/mipsmtregs.h>
141 +#ifdef CONFIG_BCM47XX
142 +#include <asm/paccess.h>
143 +#include <linux/ssb/ssb.h>
144 +#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
146 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
147 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
149 +#define BCM4710_DUMMY_RREG()
151 +#define BCM4710_FILL_TLB(addr)
152 +#define BCM4710_PROTECTED_FILL_TLB(addr)
156 * This macro return a properly sign-extended address suitable as base address
157 * for indexed cache operations. Two issues here:
159 static inline void flush_dcache_line_indexed(unsigned long addr)
162 + BCM4710_DUMMY_RREG();
163 cache_op(Index_Writeback_Inv_D, addr);
167 static inline void flush_dcache_line(unsigned long addr)
170 + BCM4710_DUMMY_RREG();
171 cache_op(Hit_Writeback_Inv_D, addr);
175 static inline void invalidate_dcache_line(unsigned long addr)
178 + BCM4710_DUMMY_RREG();
179 cache_op(Hit_Invalidate_D, addr);
184 static inline void protected_flush_icache_line(unsigned long addr)
186 + BCM4710_DUMMY_RREG();
187 protected_cache_op(Hit_Invalidate_I, addr);
192 static inline void protected_writeback_dcache_line(unsigned long addr)
194 + BCM4710_DUMMY_RREG();
195 protected_cache_op(Hit_Writeback_Inv_D, addr);
202 +static inline void blast_dcache(void)
204 + unsigned long start = KSEG0;
205 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
206 + unsigned long end = (start + dcache_size);
209 + BCM4710_DUMMY_RREG();
210 + cache_op(Index_Writeback_Inv_D, start);
211 + start += current_cpu_data.dcache.linesz;
212 + } while(start < end);
215 +static inline void blast_dcache_page(unsigned long page)
217 + unsigned long start = page;
218 + unsigned long end = start + PAGE_SIZE;
220 + BCM4710_FILL_TLB(start);
222 + BCM4710_DUMMY_RREG();
223 + cache_op(Hit_Writeback_Inv_D, start);
224 + start += current_cpu_data.dcache.linesz;
225 + } while(start < end);
228 +static inline void blast_dcache_page_indexed(unsigned long page)
230 + unsigned long start = page;
231 + unsigned long end = start + PAGE_SIZE;
232 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
233 + unsigned long ws_end = current_cpu_data.dcache.ways <<
234 + current_cpu_data.dcache.waybit;
235 + unsigned long ws, addr;
236 + for (ws = 0; ws < ws_end; ws += ws_inc) {
238 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
239 + BCM4710_DUMMY_RREG();
240 + cache_op(Index_Writeback_Inv_D, addr);
246 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
247 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
248 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
249 static inline void blast_##pfx##cache##lsize(void) \
251 unsigned long start = INDEX_BASE; \
254 __##pfx##flush_prologue \
257 for (ws = 0; ws < ws_end; ws += ws_inc) \
258 for (addr = start; addr < end; addr += lsize * 32) \
259 cache##lsize##_unroll32(addr|ws, indexop); \
262 __##pfx##flush_prologue \
266 cache##lsize##_unroll32(start, hitop); \
267 start += lsize * 32; \
269 current_cpu_data.desc.waybit; \
270 unsigned long ws, addr; \
274 __##pfx##flush_prologue \
276 for (ws = 0; ws < ws_end; ws += ws_inc) \
277 @@ -393,35 +460,37 @@
278 __##pfx##flush_epilogue \
281 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
282 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
283 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
284 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
285 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
286 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
287 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
288 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
289 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
291 -__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
292 -__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
293 -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
294 -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
295 -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
296 -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
297 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
298 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
299 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
300 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
301 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
302 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
303 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
304 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
305 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
307 +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
308 +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
309 +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
310 +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
311 +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
312 +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
314 /* build blast_xxx_range, protected_blast_xxx_range */
315 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
316 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
317 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
320 unsigned long lsize = cpu_##desc##_line_size(); \
321 unsigned long addr = start & ~(lsize - 1); \
322 unsigned long aend = (end - 1) & ~(lsize - 1); \
325 __##pfx##flush_prologue \
329 prot##cache_op(hitop, addr); \
332 @@ -431,13 +500,13 @@
333 __##pfx##flush_epilogue \
336 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
337 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
338 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
339 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
340 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
341 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
342 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
343 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
344 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
345 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
346 /* blast_inv_dcache_range */
347 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
348 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
349 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
350 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
352 #endif /* _ASM_R4KCACHE_H */
353 --- a/include/asm-mips/stackframe.h
354 +++ b/include/asm-mips/stackframe.h
356 .macro RESTORE_SP_AND_RET
357 LONG_L sp, PT_R29(sp)
359 +#ifdef CONFIG_BCM47XX