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 2006-10-16 19:09:36.000000000 +0200
3 +++ linux.dev/arch/mips/kernel/genex.S 2006-10-16 19:06:50.000000000 +0200
8 +#ifdef CONFIG_BCM947XX
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 2006-10-16 19:09:36.000000000 +0200
17 +++ linux.dev/arch/mips/mm/c-r4k.c 2006-10-16 19:08:46.000000000 +0200
20 #include <linux/bitops.h>
22 +#ifdef CONFIG_BCM947XX
23 +#include "../bcm947xx/include/typedefs.h"
24 +#include "../bcm947xx/include/sbconfig.h"
25 +#include "../bcm947xx/include/mipsinc.h"
29 +#include <asm/paccess.h>
31 #include <asm/bcache.h>
32 #include <asm/bootinfo.h>
33 #include <asm/cache.h>
35 #include <asm/cacheflush.h> /* for run_uncached() */
38 +/* For enabling BCM4710 cache workarounds */
42 * Special Variant of smp_call_function for use by cache functions:
46 unsigned long dc_lsize = cpu_dcache_line_size();
50 + r4k_blast_dcache_page = blast_dcache_page;
51 + else if (dc_lsize == 16)
52 r4k_blast_dcache_page = blast_dcache16_page;
53 else if (dc_lsize == 32)
54 r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
57 unsigned long dc_lsize = cpu_dcache_line_size();
61 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
62 + else if (dc_lsize == 16)
63 r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
64 else if (dc_lsize == 32)
65 r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
68 unsigned long dc_lsize = cpu_dcache_line_size();
72 + r4k_blast_dcache = blast_dcache;
73 + else if (dc_lsize == 16)
74 r4k_blast_dcache = blast_dcache16;
75 else if (dc_lsize == 32)
76 r4k_blast_dcache = blast_dcache32;
80 protected_blast_icache_range(start, end);
83 + r4k_flush_cache_all();
86 static void r4k_flush_icache_range(unsigned long start, unsigned long end)
88 unsigned long addr = (unsigned long) arg;
90 R4600_HIT_CACHEOP_WAR_IMPL;
91 + BCM4710_PROTECTED_FILL_TLB(addr);
92 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
93 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
94 if (!cpu_icache_snoops_remote_store && scache_size)
95 protected_writeback_scache_line(addr & ~(sc_lsize - 1));
96 @@ -1189,6 +1212,16 @@
97 static inline void coherency_setup(void)
99 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
100 +#ifdef CONFIG_BCM947XX
101 + if (BCM330X(current_cpu_data.processor_id)) {
102 + __u32 cm = read_c0_diag();
103 + /* Enable icache */
105 + /* Enable dcache */
112 * c0_status.cu=0 specifies that updates by the sc instruction use
113 @@ -1227,6 +1260,15 @@
115 /* Default cache error handler for R4000 and R5000 family */
116 set_uncached_handler (0x100, &except_vec2_generic, 0x80);
118 + /* Check if special workarounds are required */
119 +#ifdef CONFIG_BCM947XX
120 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
121 + printk("Enabling BCM4710A0 cache workarounds.\n");
129 diff -ur linux.old/arch/mips/mm/tlbex.c linux.dev/arch/mips/mm/tlbex.c
130 --- linux.old/arch/mips/mm/tlbex.c 2006-10-16 19:09:36.000000000 +0200
131 +++ linux.dev/arch/mips/mm/tlbex.c 2006-10-16 19:06:50.000000000 +0200
134 /* #define DEBUG_TLB */
136 +#ifdef CONFIG_BCM947XX
140 static __init int __attribute__((unused)) r45k_bvahwbug(void)
142 /* XXX: We should probe for the presence of this bug, but we don't. */
143 @@ -1184,6 +1188,12 @@
144 memset(relocs, 0, sizeof(relocs));
145 memset(final_handler, 0, sizeof(final_handler));
147 +#ifdef CONFIG_BCM947XX
154 * create the plain linear handler
156 diff -ur linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h
157 --- linux.old/include/asm-mips/r4kcache.h 2006-10-16 19:09:36.000000000 +0200
158 +++ linux.dev/include/asm-mips/r4kcache.h 2006-10-16 19:09:11.000000000 +0200
160 #include <asm/cpu-features.h>
161 #include <asm/mipsmtregs.h>
163 +#ifdef CONFIG_BCM947XX
164 +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
166 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
167 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
169 +#define BCM4710_DUMMY_RREG()
171 +#define BCM4710_FILL_TLB(addr)
172 +#define BCM4710_PROTECTED_FILL_TLB(addr)
176 * This macro return a properly sign-extended address suitable as base address
177 * for indexed cache operations. Two issues here:
179 static inline void flush_dcache_line_indexed(unsigned long addr)
182 + BCM4710_DUMMY_RREG();
183 cache_op(Index_Writeback_Inv_D, addr);
187 static inline void flush_dcache_line(unsigned long addr)
190 + BCM4710_DUMMY_RREG();
191 cache_op(Hit_Writeback_Inv_D, addr);
195 static inline void invalidate_dcache_line(unsigned long addr)
198 + BCM4710_DUMMY_RREG();
199 cache_op(Hit_Invalidate_D, addr);
204 static inline void protected_flush_icache_line(unsigned long addr)
206 + BCM4710_DUMMY_RREG();
207 protected_cache_op(Hit_Invalidate_I, addr);
212 static inline void protected_writeback_dcache_line(unsigned long addr)
214 + BCM4710_DUMMY_RREG();
215 protected_cache_op(Hit_Writeback_Inv_D, addr);
222 +static inline void blast_dcache(void)
224 + unsigned long start = KSEG0;
225 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
226 + unsigned long end = (start + dcache_size);
229 + BCM4710_DUMMY_RREG();
230 + cache_op(Index_Writeback_Inv_D, start);
231 + start += current_cpu_data.dcache.linesz;
232 + } while(start < end);
235 +static inline void blast_dcache_page(unsigned long page)
237 + unsigned long start = page;
238 + unsigned long end = start + PAGE_SIZE;
240 + BCM4710_FILL_TLB(start);
242 + BCM4710_DUMMY_RREG();
243 + cache_op(Hit_Writeback_Inv_D, start);
244 + start += current_cpu_data.dcache.linesz;
245 + } while(start < end);
248 +static inline void blast_dcache_page_indexed(unsigned long page)
250 + unsigned long start = page;
251 + unsigned long end = start + PAGE_SIZE;
252 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
253 + unsigned long ws_end = current_cpu_data.dcache.ways <<
254 + current_cpu_data.dcache.waybit;
255 + unsigned long ws, addr;
256 + for (ws = 0; ws < ws_end; ws += ws_inc) {
258 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
259 + BCM4710_DUMMY_RREG();
260 + cache_op(Index_Writeback_Inv_D, addr);
266 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
267 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
268 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
269 static inline void blast_##pfx##cache##lsize(void) \
271 unsigned long start = INDEX_BASE; \
274 __##pfx##flush_prologue \
277 for (ws = 0; ws < ws_end; ws += ws_inc) \
278 for (addr = start; addr < end; addr += lsize * 32) \
279 cache##lsize##_unroll32(addr|ws,indexop); \
282 __##pfx##flush_prologue \
286 cache##lsize##_unroll32(start,hitop); \
287 start += lsize * 32; \
289 current_cpu_data.desc.waybit; \
290 unsigned long ws, addr; \
294 __##pfx##flush_prologue \
296 for (ws = 0; ws < ws_end; ws += ws_inc) \
297 @@ -393,28 +458,30 @@
298 __##pfx##flush_epilogue \
301 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
302 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
303 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
304 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
305 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
306 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
307 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
308 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
309 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
310 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
311 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
312 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
313 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
314 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
315 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
316 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
317 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
318 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
320 /* build blast_xxx_range, protected_blast_xxx_range */
321 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
322 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
323 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
326 unsigned long lsize = cpu_##desc##_line_size(); \
327 unsigned long addr = start & ~(lsize - 1); \
328 unsigned long aend = (end - 1) & ~(lsize - 1); \
331 __##pfx##flush_prologue \
335 prot##cache_op(hitop, addr); \
338 @@ -424,13 +491,13 @@
339 __##pfx##flush_epilogue \
342 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
343 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
344 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
345 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
346 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
347 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
348 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
349 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
350 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
351 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
352 /* blast_inv_dcache_range */
353 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
354 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
355 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
356 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
358 #endif /* _ASM_R4KCACHE_H */
359 diff -ur linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h
360 --- linux.old/include/asm-mips/stackframe.h 2006-10-16 19:09:36.000000000 +0200
361 +++ linux.dev/include/asm-mips/stackframe.h 2006-10-16 19:06:50.000000000 +0200
363 .macro RESTORE_SP_AND_RET
364 LONG_L sp, PT_R29(sp)
366 +#ifdef CONFIG_BCM947XX