1 diff -urN linux-2.6.19.ref/arch/mips/kernel/genex.S linux-2.6.19/arch/mips/kernel/genex.S
2 --- linux-2.6.19.ref/arch/mips/kernel/genex.S 2006-11-29 22:57:37.000000000 +0100
3 +++ linux-2.6.19/arch/mips/kernel/genex.S 2006-12-04 21:34:09.000000000 +0100
8 +#ifdef CONFIG_BCM947XX
15 diff -urN linux-2.6.19.ref/arch/mips/mm/c-r4k.c linux-2.6.19/arch/mips/mm/c-r4k.c
16 --- linux-2.6.19.ref/arch/mips/mm/c-r4k.c 2006-12-04 21:34:04.000000000 +0100
17 +++ linux-2.6.19/arch/mips/mm/c-r4k.c 2006-12-04 21:34:09.000000000 +0100
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();
49 + r4k_blast_dcache_page = blast_dcache_page;
52 r4k_blast_dcache_page = (void *)cache_noop;
53 else if (dc_lsize == 16)
56 unsigned long dc_lsize = cpu_dcache_line_size();
59 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
62 r4k_blast_dcache_page_indexed = (void *)cache_noop;
63 else if (dc_lsize == 16)
66 unsigned long dc_lsize = cpu_dcache_line_size();
69 + r4k_blast_dcache = blast_dcache;
72 r4k_blast_dcache = (void *)cache_noop;
73 else if (dc_lsize == 16)
77 protected_blast_icache_range(start, end);
80 + r4k_flush_cache_all();
83 static void r4k_flush_icache_range(unsigned long start, unsigned long end)
85 unsigned long addr = (unsigned long) arg;
87 R4600_HIT_CACHEOP_WAR_IMPL;
88 + BCM4710_PROTECTED_FILL_TLB(addr);
89 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
91 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
92 if (!cpu_icache_snoops_remote_store && scache_size)
93 @@ -1135,6 +1161,16 @@
94 static void __init coherency_setup(void)
96 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
97 +#ifdef CONFIG_BCM947XX
98 + if (BCM330X(current_cpu_data.processor_id)) {
99 + __u32 cm = read_c0_diag();
100 + /* Enable icache */
102 + /* Enable dcache */
109 * c0_status.cu=0 specifies that updates by the sc instruction use
110 @@ -1173,6 +1209,15 @@
112 /* Default cache error handler for R4000 and R5000 family */
113 set_uncached_handler (0x100, &except_vec2_generic, 0x80);
115 + /* Check if special workarounds are required */
116 +#ifdef CONFIG_BCM947XX
117 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
118 + printk("Enabling BCM4710A0 cache workarounds.\n");
126 diff -urN linux-2.6.19.ref/arch/mips/mm/tlbex.c linux-2.6.19/arch/mips/mm/tlbex.c
127 --- linux-2.6.19.ref/arch/mips/mm/tlbex.c 2006-12-04 21:33:48.000000000 +0100
128 +++ linux-2.6.19/arch/mips/mm/tlbex.c 2006-12-04 21:34:09.000000000 +0100
129 @@ -1174,6 +1174,10 @@
133 +#ifdef CONFIG_BCM947XX
137 static void __init build_r4000_tlb_refill_handler(void)
139 u32 *p = tlb_handler;
140 @@ -1188,6 +1192,12 @@
141 memset(relocs, 0, sizeof(relocs));
142 memset(final_handler, 0, sizeof(final_handler));
144 +#ifdef CONFIG_BCM947XX
151 * create the plain linear handler
153 diff -urN linux-2.6.19.ref/include/asm-mips/r4kcache.h linux-2.6.19/include/asm-mips/r4kcache.h
154 --- linux-2.6.19.ref/include/asm-mips/r4kcache.h 2006-11-29 22:57:37.000000000 +0100
155 +++ linux-2.6.19/include/asm-mips/r4kcache.h 2006-12-04 21:34:09.000000000 +0100
157 #include <asm/cpu-features.h>
158 #include <asm/mipsmtregs.h>
160 +#ifdef CONFIG_BCM947XX
161 +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
163 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
164 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
166 +#define BCM4710_DUMMY_RREG()
168 +#define BCM4710_FILL_TLB(addr)
169 +#define BCM4710_PROTECTED_FILL_TLB(addr)
173 * This macro return a properly sign-extended address suitable as base address
174 * for indexed cache operations. Two issues here:
176 static inline void flush_dcache_line_indexed(unsigned long addr)
179 + BCM4710_DUMMY_RREG();
180 cache_op(Index_Writeback_Inv_D, addr);
184 static inline void flush_dcache_line(unsigned long addr)
187 + BCM4710_DUMMY_RREG();
188 cache_op(Hit_Writeback_Inv_D, addr);
192 static inline void invalidate_dcache_line(unsigned long addr)
195 + BCM4710_DUMMY_RREG();
196 cache_op(Hit_Invalidate_D, addr);
201 static inline void protected_flush_icache_line(unsigned long addr)
203 + BCM4710_DUMMY_RREG();
204 protected_cache_op(Hit_Invalidate_I, addr);
209 static inline void protected_writeback_dcache_line(unsigned long addr)
211 + BCM4710_DUMMY_RREG();
212 protected_cache_op(Hit_Writeback_Inv_D, addr);
219 +static inline void blast_dcache(void)
221 + unsigned long start = KSEG0;
222 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
223 + unsigned long end = (start + dcache_size);
226 + BCM4710_DUMMY_RREG();
227 + cache_op(Index_Writeback_Inv_D, start);
228 + start += current_cpu_data.dcache.linesz;
229 + } while(start < end);
232 +static inline void blast_dcache_page(unsigned long page)
234 + unsigned long start = page;
235 + unsigned long end = start + PAGE_SIZE;
237 + BCM4710_FILL_TLB(start);
239 + BCM4710_DUMMY_RREG();
240 + cache_op(Hit_Writeback_Inv_D, start);
241 + start += current_cpu_data.dcache.linesz;
242 + } while(start < end);
245 +static inline void blast_dcache_page_indexed(unsigned long page)
247 + unsigned long start = page;
248 + unsigned long end = start + PAGE_SIZE;
249 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
250 + unsigned long ws_end = current_cpu_data.dcache.ways <<
251 + current_cpu_data.dcache.waybit;
252 + unsigned long ws, addr;
253 + for (ws = 0; ws < ws_end; ws += ws_inc) {
255 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
256 + BCM4710_DUMMY_RREG();
257 + cache_op(Index_Writeback_Inv_D, addr);
263 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
264 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
265 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
266 static inline void blast_##pfx##cache##lsize(void) \
268 unsigned long start = INDEX_BASE; \
271 __##pfx##flush_prologue \
274 for (ws = 0; ws < ws_end; ws += ws_inc) \
275 for (addr = start; addr < end; addr += lsize * 32) \
276 cache##lsize##_unroll32(addr|ws,indexop); \
279 __##pfx##flush_prologue \
283 cache##lsize##_unroll32(start,hitop); \
284 start += lsize * 32; \
286 current_cpu_data.desc.waybit; \
287 unsigned long ws, addr; \
291 __##pfx##flush_prologue \
293 for (ws = 0; ws < ws_end; ws += ws_inc) \
294 @@ -393,28 +458,30 @@
295 __##pfx##flush_epilogue \
298 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
299 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
300 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
301 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
302 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
303 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
304 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
305 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
306 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
307 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
308 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
309 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
310 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
311 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
312 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
313 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
314 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
315 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
317 /* build blast_xxx_range, protected_blast_xxx_range */
318 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
319 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
320 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
323 unsigned long lsize = cpu_##desc##_line_size(); \
324 unsigned long addr = start & ~(lsize - 1); \
325 unsigned long aend = (end - 1) & ~(lsize - 1); \
328 __##pfx##flush_prologue \
332 prot##cache_op(hitop, addr); \
335 @@ -424,13 +491,13 @@
336 __##pfx##flush_epilogue \
339 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
340 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
341 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
342 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
343 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
344 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
345 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
346 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
347 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
348 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
349 /* blast_inv_dcache_range */
350 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
351 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
352 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
353 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
355 #endif /* _ASM_R4KCACHE_H */
356 diff -urN linux-2.6.19.ref/include/asm-mips/stackframe.h linux-2.6.19/include/asm-mips/stackframe.h
357 --- linux-2.6.19.ref/include/asm-mips/stackframe.h 2006-11-29 22:57:37.000000000 +0100
358 +++ linux-2.6.19/include/asm-mips/stackframe.h 2006-12-04 21:34:09.000000000 +0100
360 .macro RESTORE_SP_AND_RET
361 LONG_L sp, PT_R29(sp)
363 +#ifdef CONFIG_BCM947XX