1 diff -ur linux.old/arch/mips/kernel/genex.S linux.dev/arch/mips/kernel/genex.S
2 --- linux.old/arch/mips/kernel/genex.S 2007-03-23 16:10:35.572499592 +0100
3 +++ linux.dev/arch/mips/kernel/genex.S 2007-03-16 11:54:34.901251992 +0100
5 NESTED(except_vec3_generic, 0, sp)
8 +#ifdef CONFIG_BCM947XX
12 #if R5432_CP0_INTERRUPT_WAR
15 diff -ur linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c
16 --- linux.old/arch/mips/mm/c-r4k.c 2007-03-16 12:11:00.344441000 +0100
17 +++ linux.dev/arch/mips/mm/c-r4k.c 2007-03-23 16:03:23.596169976 +0100
19 #include <asm/cacheflush.h> /* for run_uncached() */
22 +/* For enabling BCM4710 cache workarounds */
26 * Special Variant of smp_call_function for use by cache functions:
30 unsigned long dc_lsize = cpu_dcache_line_size();
33 + r4k_blast_dcache_page = blast_dcache_page;
36 r4k_blast_dcache_page = (void *)cache_noop;
37 else if (dc_lsize == 16)
40 unsigned long dc_lsize = cpu_dcache_line_size();
43 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
46 r4k_blast_dcache_page_indexed = (void *)cache_noop;
47 else if (dc_lsize == 16)
50 unsigned long dc_lsize = cpu_dcache_line_size();
53 + r4k_blast_dcache = blast_dcache;
56 r4k_blast_dcache = (void *)cache_noop;
57 else if (dc_lsize == 16)
61 protected_blast_icache_range(start, end);
64 + r4k_flush_cache_all();
67 static void r4k_flush_icache_range(unsigned long start, unsigned long end)
69 unsigned long addr = (unsigned long) arg;
71 R4600_HIT_CACHEOP_WAR_IMPL;
72 + BCM4710_PROTECTED_FILL_TLB(addr);
73 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
75 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
76 if (!cpu_icache_snoops_remote_store && scache_size)
77 @@ -1199,6 +1216,15 @@
79 /* Default cache error handler for R4000 and R5000 family */
80 set_uncached_handler (0x100, &except_vec2_generic, 0x80);
82 + /* Check if special workarounds are required */
83 +#ifdef CONFIG_BCM947XX
84 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
85 + printk("Enabling BCM4710A0 cache workarounds.\n");
93 diff -ur linux.old/arch/mips/mm/tlbex.c linux.dev/arch/mips/mm/tlbex.c
94 --- linux.old/arch/mips/mm/tlbex.c 2007-03-16 11:54:34.826263000 +0100
95 +++ linux.dev/arch/mips/mm/tlbex.c 2007-03-23 16:03:23.608168152 +0100
96 @@ -1174,6 +1174,10 @@
100 +#ifdef CONFIG_BCM947XX
104 static void __init build_r4000_tlb_refill_handler(void)
106 u32 *p = tlb_handler;
107 @@ -1188,6 +1192,12 @@
108 memset(relocs, 0, sizeof(relocs));
109 memset(final_handler, 0, sizeof(final_handler));
111 +#ifdef CONFIG_BCM947XX
118 * create the plain linear handler
120 diff -ur linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h
121 --- linux.old/include/asm-mips/r4kcache.h 2007-01-10 20:10:37.000000000 +0100
122 +++ linux.dev/include/asm-mips/r4kcache.h 2007-03-23 16:38:44.603727816 +0100
124 #include <asm/cpu-features.h>
125 #include <asm/mipsmtregs.h>
127 +#ifdef CONFIG_BCM947XX
128 +#include <asm/paccess.h>
129 +#include <linux/ssb/ssb.h>
130 +#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
132 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
133 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
135 +#define BCM4710_DUMMY_RREG()
137 +#define BCM4710_FILL_TLB(addr)
138 +#define BCM4710_PROTECTED_FILL_TLB(addr)
142 * This macro return a properly sign-extended address suitable as base address
143 * for indexed cache operations. Two issues here:
145 static inline void flush_dcache_line_indexed(unsigned long addr)
148 + BCM4710_DUMMY_RREG();
149 cache_op(Index_Writeback_Inv_D, addr);
153 static inline void flush_dcache_line(unsigned long addr)
156 + BCM4710_DUMMY_RREG();
157 cache_op(Hit_Writeback_Inv_D, addr);
161 static inline void invalidate_dcache_line(unsigned long addr)
164 + BCM4710_DUMMY_RREG();
165 cache_op(Hit_Invalidate_D, addr);
170 static inline void protected_flush_icache_line(unsigned long addr)
172 + BCM4710_DUMMY_RREG();
173 protected_cache_op(Hit_Invalidate_I, addr);
178 static inline void protected_writeback_dcache_line(unsigned long addr)
180 + BCM4710_DUMMY_RREG();
181 protected_cache_op(Hit_Writeback_Inv_D, addr);
188 +static inline void blast_dcache(void)
190 + unsigned long start = KSEG0;
191 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
192 + unsigned long end = (start + dcache_size);
195 + BCM4710_DUMMY_RREG();
196 + cache_op(Index_Writeback_Inv_D, start);
197 + start += current_cpu_data.dcache.linesz;
198 + } while(start < end);
201 +static inline void blast_dcache_page(unsigned long page)
203 + unsigned long start = page;
204 + unsigned long end = start + PAGE_SIZE;
206 + BCM4710_FILL_TLB(start);
208 + BCM4710_DUMMY_RREG();
209 + cache_op(Hit_Writeback_Inv_D, start);
210 + start += current_cpu_data.dcache.linesz;
211 + } while(start < end);
214 +static inline void blast_dcache_page_indexed(unsigned long page)
216 + unsigned long start = page;
217 + unsigned long end = start + PAGE_SIZE;
218 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
219 + unsigned long ws_end = current_cpu_data.dcache.ways <<
220 + current_cpu_data.dcache.waybit;
221 + unsigned long ws, addr;
222 + for (ws = 0; ws < ws_end; ws += ws_inc) {
224 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
225 + BCM4710_DUMMY_RREG();
226 + cache_op(Index_Writeback_Inv_D, addr);
232 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
233 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
234 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
235 static inline void blast_##pfx##cache##lsize(void) \
237 unsigned long start = INDEX_BASE; \
240 __##pfx##flush_prologue \
243 for (ws = 0; ws < ws_end; ws += ws_inc) \
244 for (addr = start; addr < end; addr += lsize * 32) \
245 cache##lsize##_unroll32(addr|ws,indexop); \
248 __##pfx##flush_prologue \
252 cache##lsize##_unroll32(start,hitop); \
253 start += lsize * 32; \
255 current_cpu_data.desc.waybit; \
256 unsigned long ws, addr; \
260 __##pfx##flush_prologue \
262 for (ws = 0; ws < ws_end; ws += ws_inc) \
263 @@ -393,28 +460,30 @@
264 __##pfx##flush_epilogue \
267 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
268 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
269 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
270 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
271 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
272 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
273 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
274 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
275 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
276 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
277 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
278 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
279 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
280 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
281 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
282 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
283 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
284 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
286 /* build blast_xxx_range, protected_blast_xxx_range */
287 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
288 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
289 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
292 unsigned long lsize = cpu_##desc##_line_size(); \
293 unsigned long addr = start & ~(lsize - 1); \
294 unsigned long aend = (end - 1) & ~(lsize - 1); \
297 __##pfx##flush_prologue \
301 prot##cache_op(hitop, addr); \
304 @@ -424,13 +493,13 @@
305 __##pfx##flush_epilogue \
308 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
309 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
310 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
311 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
312 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
313 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
314 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
315 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
316 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
317 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
318 /* blast_inv_dcache_range */
319 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
320 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
321 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
322 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
324 #endif /* _ASM_R4KCACHE_H */
325 diff -ur linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h
326 --- linux.old/include/asm-mips/stackframe.h 2007-03-23 16:10:35.573499440 +0100
327 +++ linux.dev/include/asm-mips/stackframe.h 2007-03-16 11:54:34.903251688 +0100
329 .macro RESTORE_SP_AND_RET
330 LONG_L sp, PT_R29(sp)
332 +#ifdef CONFIG_BCM947XX