1 --- a/arch/mips/kernel/genex.S
2 +++ b/arch/mips/kernel/genex.S
4 NESTED(except_vec3_generic, 0, sp)
7 +#ifdef CONFIG_BCM947XX
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 @@ -1213,6 +1227,17 @@
66 * silly idea of putting something else there ...
68 switch (current_cpu_data.cputype) {
72 + cm = read_c0_diag();
83 @@ -1243,6 +1268,15 @@
84 /* Default cache error handler for R4000 and R5000 family */
85 set_uncached_handler (0x100, &except_vec2_generic, 0x80);
87 + /* Check if special workarounds are required */
88 +#ifdef CONFIG_BCM947XX
89 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
90 + printk("Enabling BCM4710A0 cache workarounds.\n");
99 @@ -1288,5 +1322,13 @@
102 local_r4k___flush_cache_all(NULL);
103 +#ifdef CONFIG_BCM947XX
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
115 @@ -1273,6 +1273,9 @@
116 /* No need for i_nop */
119 +#ifdef CONFIG_BCM947XX
123 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
125 @@ -1708,6 +1711,9 @@
126 struct reloc **r, unsigned int pte,
129 +#ifdef CONFIG_BCM947XX
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_BCM947XX
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,28 +460,30 @@
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)
290 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
291 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
292 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
293 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
294 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
295 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
296 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
297 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
298 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
300 /* build blast_xxx_range, protected_blast_xxx_range */
301 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
302 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
303 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
306 unsigned long lsize = cpu_##desc##_line_size(); \
307 unsigned long addr = start & ~(lsize - 1); \
308 unsigned long aend = (end - 1) & ~(lsize - 1); \
311 __##pfx##flush_prologue \
315 prot##cache_op(hitop, addr); \
318 @@ -424,13 +493,13 @@
319 __##pfx##flush_epilogue \
322 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
323 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
324 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
325 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
326 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
327 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
328 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
329 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
330 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
331 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
332 /* blast_inv_dcache_range */
333 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
334 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
335 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
336 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
338 #endif /* _ASM_R4KCACHE_H */
339 --- a/include/asm-mips/stackframe.h
340 +++ b/include/asm-mips/stackframe.h
342 .macro RESTORE_SP_AND_RET
343 LONG_L sp, PT_R29(sp)
345 +#ifdef CONFIG_BCM947XX