1 --- a/arch/mips/include/asm/r4kcache.h
2 +++ b/arch/mips/include/asm/r4kcache.h
4 #include <asm/cpu-features.h>
5 #include <asm/mipsmtregs.h>
8 +#include <asm/paccess.h>
9 +#include <linux/ssb/ssb.h>
10 +#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
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)); })
15 +#define BCM4710_DUMMY_RREG()
17 +#define BCM4710_FILL_TLB(addr)
18 +#define BCM4710_PROTECTED_FILL_TLB(addr)
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)
28 + BCM4710_DUMMY_RREG();
29 cache_op(Index_Writeback_Inv_D, addr);
32 @@ -169,6 +184,7 @@ static inline void flush_icache_line(uns
33 static inline void flush_dcache_line(unsigned long addr)
36 + BCM4710_DUMMY_RREG();
37 cache_op(Hit_Writeback_Inv_D, addr);
40 @@ -176,6 +192,7 @@ static inline void flush_dcache_line(uns
41 static inline void invalidate_dcache_line(unsigned long addr)
44 + BCM4710_DUMMY_RREG();
45 cache_op(Hit_Invalidate_D, addr);
48 @@ -208,6 +225,7 @@ static inline void flush_scache_line(uns
50 static inline void protected_flush_icache_line(unsigned long addr)
52 + BCM4710_DUMMY_RREG();
53 protected_cache_op(Hit_Invalidate_I, addr);
56 @@ -219,6 +237,7 @@ static inline void protected_flush_icach
58 static inline void protected_writeback_dcache_line(unsigned long addr)
60 + BCM4710_DUMMY_RREG();
61 protected_cache_op(Hit_Writeback_Inv_D, addr);
64 @@ -339,8 +358,52 @@ static inline void invalidate_tcache_pag
68 +static inline void blast_dcache(void)
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);
75 + BCM4710_DUMMY_RREG();
76 + cache_op(Index_Writeback_Inv_D, start);
77 + start += current_cpu_data.dcache.linesz;
78 + } while(start < end);
81 +static inline void blast_dcache_page(unsigned long page)
83 + unsigned long start = page;
84 + unsigned long end = start + PAGE_SIZE;
86 + BCM4710_FILL_TLB(start);
88 + BCM4710_DUMMY_RREG();
89 + cache_op(Hit_Writeback_Inv_D, start);
90 + start += current_cpu_data.dcache.linesz;
91 + } while(start < end);
94 +static inline void blast_dcache_page_indexed(unsigned long page)
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) {
104 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
105 + BCM4710_DUMMY_RREG();
106 + cache_op(Index_Writeback_Inv_D, addr);
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) \
117 unsigned long start = INDEX_BASE; \
118 @@ -352,6 +415,7 @@ static inline void blast_##pfx##cache##l
120 __##pfx##flush_prologue \
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
128 __##pfx##flush_prologue \
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; \
140 __##pfx##flush_prologue \
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 \
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)
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, )
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, )
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, \
188 unsigned long lsize = cpu_##desc##_line_size(); \
189 unsigned long addr = start & ~(lsize - 1); \
190 unsigned long aend = (end - 1) & ~(lsize - 1); \
193 __##pfx##flush_prologue \
197 prot##cache_op(hitop, addr); \
200 @@ -432,13 +501,13 @@ static inline void prot##blast_##pfx##ca
201 __##pfx##flush_epilogue \
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,,, )
220 #endif /* _ASM_R4KCACHE_H */
221 --- a/arch/mips/include/asm/stackframe.h
222 +++ b/arch/mips/include/asm/stackframe.h
224 .macro RESTORE_SP_AND_RET
225 LONG_L sp, PT_R29(sp)
227 +#ifdef CONFIG_BCM47XX
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)
240 +#ifdef CONFIG_BCM47XX
244 #if R5432_CP0_INTERRUPT_WAR
247 --- a/arch/mips/mm/c-r4k.c
248 +++ b/arch/mips/mm/c-r4k.c
250 #include <asm/cacheflush.h> /* for run_uncached() */
253 +/* For enabling BCM4710 cache workarounds */
257 * Special Variant of smp_call_function for use by cache functions:
259 @@ -111,6 +114,9 @@ static void __cpuinit r4k_blast_dcache_p
261 unsigned long dc_lsize = cpu_dcache_line_size();
264 + r4k_blast_dcache_page = blast_dcache_page;
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
271 unsigned long dc_lsize = cpu_dcache_line_size();
274 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
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
281 unsigned long dc_lsize = cpu_dcache_line_size();
284 + r4k_blast_dcache = blast_dcache;
287 r4k_blast_dcache = (void *)cache_noop;
288 else if (dc_lsize == 16)
289 @@ -680,6 +692,8 @@ static void local_r4k_flush_cache_sigtra
290 unsigned long addr = (unsigned long) arg;
292 R4600_HIT_CACHEOP_WAR_IMPL;
293 + BCM4710_PROTECTED_FILL_TLB(addr);
294 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
296 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
297 if (!cpu_icache_snoops_remote_store && scache_size)
298 @@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo
299 * silly idea of putting something else there ...
301 switch (current_cpu_type()) {
305 + cm = read_c0_diag();
306 + /* Enable icache */
308 + /* Enable dcache */
316 @@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void)
320 + /* Check if special workarounds are required */
321 +#ifdef CONFIG_BCM47XX
322 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
323 + printk("Enabling BCM4710A0 cache workarounds.\n");
332 @@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void)
333 #if !defined(CONFIG_MIPS_CMP)
334 local_r4k___flush_cache_all(NULL);
336 +#ifdef CONFIG_BCM47XX
338 + static void (*_coherency_setup)(void);
339 + _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
340 + _coherency_setup();
346 --- a/arch/mips/mm/tlbex.c
347 +++ b/arch/mips/mm/tlbex.c
348 @@ -733,6 +733,9 @@ static void __cpuinit build_r4000_tlb_re
349 /* No need for uasm_i_nop */
352 +#ifdef CONFIG_BCM47XX
356 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
358 @@ -1185,6 +1188,9 @@ build_r4000_tlbchange_handler_head(u32 *
359 struct uasm_reloc **r, unsigned int pte,
362 +#ifdef CONFIG_BCM47XX
366 build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */