1 Index: linux-2.4.35.4/arch/mips/kernel/entry.S
2 ===================================================================
3 --- linux-2.4.35.4.orig/arch/mips/kernel/entry.S
4 +++ linux-2.4.35.4/arch/mips/kernel/entry.S
5 @@ -100,6 +100,10 @@ END(except_vec1_generic)
6 * and R4400 SC and MC versions.
8 NESTED(except_vec3_generic, 0, sp)
13 #if R5432_CP0_INTERRUPT_WAR
16 Index: linux-2.4.35.4/arch/mips/mm/c-r4k.c
17 ===================================================================
18 --- linux-2.4.35.4.orig/arch/mips/mm/c-r4k.c
19 +++ linux-2.4.35.4/arch/mips/mm/c-r4k.c
22 #include <linux/bitops.h>
24 +#ifdef CONFIG_BCM4710
25 +#include "../bcm947xx/include/typedefs.h"
26 +#include "../bcm947xx/include/sbconfig.h"
27 +#include <asm/paccess.h>
30 #include <asm/bcache.h>
31 #include <asm/bootinfo.h>
32 #include <asm/cacheops.h>
33 @@ -40,6 +46,7 @@ static struct bcache_ops no_sc_ops = {
34 .bc_inv = (void *)no_sc_noop
38 struct bcache_ops *bcops = &no_sc_ops;
40 #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010)
41 @@ -64,8 +71,10 @@ static inline void r4k_blast_dcache_page
42 static inline void r4k_blast_dcache_page_setup(void)
44 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
49 + r4k_blast_dcache_page = blast_dcache_page;
50 + else if (dc_lsize == 16)
51 r4k_blast_dcache_page = blast_dcache16_page;
52 else if (dc_lsize == 32)
53 r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
54 @@ -77,7 +86,9 @@ static void r4k_blast_dcache_page_indexe
56 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
60 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
61 + else if (dc_lsize == 16)
62 r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
63 else if (dc_lsize == 32)
64 r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
65 @@ -89,7 +100,9 @@ static inline void r4k_blast_dcache_setu
67 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
71 + r4k_blast_dcache = blast_dcache;
72 + else if (dc_lsize == 16)
73 r4k_blast_dcache = blast_dcache16;
74 else if (dc_lsize == 32)
75 r4k_blast_dcache = blast_dcache32;
76 @@ -266,6 +279,7 @@ static void r4k___flush_cache_all(void)
81 switch (current_cpu_data.cputype) {
84 @@ -304,10 +318,10 @@ static void r4k_flush_cache_mm(struct mm
85 * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
86 * only flush the primary caches but R10000 and R12000 behave sane ...
88 - if (current_cpu_data.cputype == CPU_R4000SC ||
89 + if (!bcm4710 && (current_cpu_data.cputype == CPU_R4000SC ||
90 current_cpu_data.cputype == CPU_R4000MC ||
91 current_cpu_data.cputype == CPU_R4400SC ||
92 - current_cpu_data.cputype == CPU_R4400MC)
93 + current_cpu_data.cputype == CPU_R4400MC))
97 @@ -383,12 +397,15 @@ static void r4k_flush_icache_range(unsig
98 unsigned long ic_lsize = current_cpu_data.icache.linesz;
99 unsigned long addr, aend;
101 + addr = start & ~(dc_lsize - 1);
102 + aend = (end - 1) & ~(dc_lsize - 1);
104 if (!cpu_has_ic_fills_f_dc) {
105 if (end - start > dcache_size)
108 - addr = start & ~(dc_lsize - 1);
109 - aend = (end - 1) & ~(dc_lsize - 1);
110 + BCM4710_PROTECTED_FILL_TLB(addr);
111 + BCM4710_PROTECTED_FILL_TLB(aend);
114 /* Hit_Writeback_Inv_D */
115 @@ -403,8 +420,6 @@ static void r4k_flush_icache_range(unsig
116 if (end - start > icache_size)
119 - addr = start & ~(ic_lsize - 1);
120 - aend = (end - 1) & ~(ic_lsize - 1);
122 /* Hit_Invalidate_I */
123 protected_flush_icache_line(addr);
124 @@ -413,6 +428,9 @@ static void r4k_flush_icache_range(unsig
134 @@ -443,7 +461,8 @@ static void r4k_flush_icache_page(struct
135 if (cpu_has_subset_pcaches) {
136 unsigned long addr = (unsigned long) page_address(page);
138 - r4k_blast_scache_page(addr);
140 + r4k_blast_scache_page(addr);
141 ClearPageDcacheDirty(page);
144 @@ -451,6 +470,7 @@ static void r4k_flush_icache_page(struct
146 if (!cpu_has_ic_fills_f_dc) {
147 unsigned long addr = (unsigned long) page_address(page);
149 r4k_blast_dcache_page(addr);
150 ClearPageDcacheDirty(page);
152 @@ -477,7 +497,7 @@ static void r4k_dma_cache_wback_inv(unsi
153 /* Catch bad driver code */
156 - if (cpu_has_subset_pcaches) {
157 + if (!bcm4710 && cpu_has_subset_pcaches) {
158 unsigned long sc_lsize = current_cpu_data.scache.linesz;
160 if (size >= scache_size) {
161 @@ -509,6 +529,8 @@ static void r4k_dma_cache_wback_inv(unsi
162 R4600_HIT_CACHEOP_WAR_IMPL;
163 a = addr & ~(dc_lsize - 1);
164 end = (addr + size - 1) & ~(dc_lsize - 1);
165 + BCM4710_FILL_TLB(a);
166 + BCM4710_FILL_TLB(end);
168 flush_dcache_line(a); /* Hit_Writeback_Inv_D */
170 @@ -527,7 +549,7 @@ static void r4k_dma_cache_inv(unsigned l
171 /* Catch bad driver code */
174 - if (cpu_has_subset_pcaches) {
175 + if (!bcm4710 && (cpu_has_subset_pcaches)) {
176 unsigned long sc_lsize = current_cpu_data.scache.linesz;
178 if (size >= scache_size) {
179 @@ -554,6 +576,8 @@ static void r4k_dma_cache_inv(unsigned l
180 R4600_HIT_CACHEOP_WAR_IMPL;
181 a = addr & ~(dc_lsize - 1);
182 end = (addr + size - 1) & ~(dc_lsize - 1);
183 + BCM4710_FILL_TLB(a);
184 + BCM4710_FILL_TLB(end);
186 flush_dcache_line(a); /* Hit_Writeback_Inv_D */
188 @@ -577,6 +601,8 @@ static void r4k_flush_cache_sigtramp(uns
189 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
191 R4600_HIT_CACHEOP_WAR_IMPL;
192 + BCM4710_PROTECTED_FILL_TLB(addr);
193 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
194 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
195 protected_flush_icache_line(addr & ~(ic_lsize - 1));
196 if (MIPS4K_ICACHE_REFILL_WAR) {
197 @@ -986,10 +1012,12 @@ static void __init setup_scache(void)
201 - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
202 - sc_present = probe_scache_kseg1(config);
204 - c->options |= MIPS_CPU_CACHE_CDEX_S;
206 + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
207 + sc_present = probe_scache_kseg1(config);
209 + c->options |= MIPS_CPU_CACHE_CDEX_S;
214 @@ -1041,6 +1069,19 @@ static void __init setup_scache(void)
215 static inline void coherency_setup(void)
217 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
219 +#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365)
220 + if (BCM330X(current_cpu_data.processor_id)) {
223 + cm = read_c0_diag();
224 + /* Enable icache */
226 + /* Enable dcache */
233 * c0_status.cu=0 specifies that updates by the sc instruction use
234 @@ -1073,6 +1114,12 @@ void __init ld_mmu_r4xx0(void)
235 memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
236 memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80);
238 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & PRID_REV_MASK) == 0) {
239 + printk("Enabling BCM4710A0 cache workarounds.\n");
247 Index: linux-2.4.35.4/arch/mips/mm/tlbex-mips32.S
248 ===================================================================
249 --- linux-2.4.35.4.orig/arch/mips/mm/tlbex-mips32.S
250 +++ linux-2.4.35.4/arch/mips/mm/tlbex-mips32.S
253 LEAF(except_vec0_r4000)
255 +#ifdef CONFIG_BCM4704
261 Index: linux-2.4.35.4/include/asm-mips/r4kcache.h
262 ===================================================================
263 --- linux-2.4.35.4.orig/include/asm-mips/r4kcache.h
264 +++ linux-2.4.35.4/include/asm-mips/r4kcache.h
267 #include <asm/cacheops.h>
269 +#ifdef CONFIG_BCM4710
270 +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
272 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
273 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
275 +#define BCM4710_DUMMY_RREG()
277 +#define BCM4710_FILL_TLB(addr)
278 +#define BCM4710_PROTECTED_FILL_TLB(addr)
281 #define cache_op(op,addr) \
282 __asm__ __volatile__( \
283 " .set noreorder \n" \
286 static inline void flush_icache_line_indexed(unsigned long addr)
288 - cache_op(Index_Invalidate_I, addr);
290 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
292 + for (way = 0; way < current_cpu_data.dcache.ways; way++) {
293 + cache_op(Index_Invalidate_I, addr);
298 static inline void flush_dcache_line_indexed(unsigned long addr)
300 - cache_op(Index_Writeback_Inv_D, addr);
302 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
304 + for (way = 0; way < current_cpu_data.dcache.ways; way++) {
305 + BCM4710_DUMMY_RREG();
306 + cache_op(Index_Writeback_Inv_D, addr);
311 static inline void flush_scache_line_indexed(unsigned long addr)
312 @@ -47,6 +72,7 @@ static inline void flush_icache_line(uns
314 static inline void flush_dcache_line(unsigned long addr)
316 + BCM4710_DUMMY_RREG();
317 cache_op(Hit_Writeback_Inv_D, addr);
320 @@ -91,6 +117,7 @@ static inline void protected_flush_icach
322 static inline void protected_writeback_dcache_line(unsigned long addr)
324 + BCM4710_DUMMY_RREG();
325 __asm__ __volatile__(
328 @@ -138,6 +165,62 @@ static inline void invalidate_tcache_pag
332 +#define cache_unroll(base,op) \
333 + __asm__ __volatile__(" \
344 +static inline void blast_dcache(void)
346 + unsigned long start = KSEG0;
347 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
348 + unsigned long end = (start + dcache_size);
350 + while(start < end) {
351 + BCM4710_DUMMY_RREG();
352 + cache_unroll(start,Index_Writeback_Inv_D);
353 + start += current_cpu_data.dcache.linesz;
357 +static inline void blast_dcache_page(unsigned long page)
359 + unsigned long start = page;
360 + unsigned long end = start + PAGE_SIZE;
362 + BCM4710_FILL_TLB(start);
364 + BCM4710_DUMMY_RREG();
365 + cache_unroll(start,Hit_Writeback_Inv_D);
366 + start += current_cpu_data.dcache.linesz;
367 + } while (start < end);
370 +static inline void blast_dcache_page_indexed(unsigned long page)
372 + unsigned long start = page;
373 + unsigned long end = start + PAGE_SIZE;
374 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
375 + unsigned long ws_end = current_cpu_data.dcache.ways <<
376 + current_cpu_data.dcache.waybit;
377 + unsigned long ws, addr;
379 + for (ws = 0; ws < ws_end; ws += ws_inc) {
381 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
382 + BCM4710_DUMMY_RREG();
383 + cache_unroll(addr,Index_Writeback_Inv_D);
388 static inline void blast_dcache16(void)
390 unsigned long start = KSEG0;
391 @@ -148,8 +231,9 @@ static inline void blast_dcache16(void)
392 unsigned long ws, addr;
394 for (ws = 0; ws < ws_end; ws += ws_inc)
395 - for (addr = start; addr < end; addr += 0x200)
396 + for (addr = start; addr < end; addr += 0x200) {
397 cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
401 static inline void blast_dcache16_page(unsigned long page)
402 @@ -173,8 +257,9 @@ static inline void blast_dcache16_page_i
403 unsigned long ws, addr;
405 for (ws = 0; ws < ws_end; ws += ws_inc)
406 - for (addr = start; addr < end; addr += 0x200)
407 + for (addr = start; addr < end; addr += 0x200) {
408 cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
412 static inline void blast_icache16(void)
413 @@ -196,6 +281,7 @@ static inline void blast_icache16_page(u
414 unsigned long start = page;
415 unsigned long end = start + PAGE_SIZE;
417 + BCM4710_FILL_TLB(start);
419 cache16_unroll32(start,Hit_Invalidate_I);
421 @@ -281,6 +367,7 @@ static inline void blast_scache16_page_i
426 static inline void blast_dcache32(void)
428 unsigned long start = KSEG0;
429 @@ -291,8 +378,9 @@ static inline void blast_dcache32(void)
430 unsigned long ws, addr;
432 for (ws = 0; ws < ws_end; ws += ws_inc)
433 - for (addr = start; addr < end; addr += 0x400)
434 + for (addr = start; addr < end; addr += 0x400) {
435 cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
439 static inline void blast_dcache32_page(unsigned long page)
440 @@ -316,8 +404,9 @@ static inline void blast_dcache32_page_i
441 unsigned long ws, addr;
443 for (ws = 0; ws < ws_end; ws += ws_inc)
444 - for (addr = start; addr < end; addr += 0x400)
445 + for (addr = start; addr < end; addr += 0x400) {
446 cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
450 static inline void blast_icache32(void)
451 @@ -339,6 +428,7 @@ static inline void blast_icache32_page(u
452 unsigned long start = page;
453 unsigned long end = start + PAGE_SIZE;
455 + BCM4710_FILL_TLB(start);
457 cache32_unroll32(start,Hit_Invalidate_I);
459 @@ -443,6 +533,7 @@ static inline void blast_icache64_page(u
460 unsigned long start = page;
461 unsigned long end = start + PAGE_SIZE;
463 + BCM4710_FILL_TLB(start);
465 cache64_unroll32(start,Hit_Invalidate_I);
467 Index: linux-2.4.35.4/include/asm-mips/stackframe.h
468 ===================================================================
469 --- linux-2.4.35.4.orig/include/asm-mips/stackframe.h
470 +++ linux-2.4.35.4/include/asm-mips/stackframe.h
475 +#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704)
477 +#undef RESTORE_SP_AND_RET
478 +#define RESTORE_SP_AND_RET \
479 + lw sp, PT_R29(sp); \
492 Index: linux-2.4.35.4/mm/memory.c
493 ===================================================================
494 --- linux-2.4.35.4.orig/mm/memory.c
495 +++ linux-2.4.35.4/mm/memory.c
496 @@ -927,6 +927,7 @@ static inline void break_cow(struct vm_a
497 flush_page_to_ram(new_page);
498 flush_cache_page(vma, address);
499 establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
500 + flush_icache_page(vma, new_page);