X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/db31d1ad0be1e26091a3254121a155c84a21af7f..2a98d46a5ad35d77570a16072834bafa4d6c854b:/target/linux/linux-2.4/patches/brcm/003-bcm47xx_cache_fixes.patch diff --git a/target/linux/linux-2.4/patches/brcm/003-bcm47xx_cache_fixes.patch b/target/linux/linux-2.4/patches/brcm/003-bcm47xx_cache_fixes.patch index 737571b94..e971e7fdf 100644 --- a/target/linux/linux-2.4/patches/brcm/003-bcm47xx_cache_fixes.patch +++ b/target/linux/linux-2.4/patches/brcm/003-bcm47xx_cache_fixes.patch @@ -1,114 +1,6 @@ -diff -urN linux.old/arch/mips/mm/tlbex-mips32.S linux.dev/arch/mips/mm/tlbex-mips32.S ---- linux.old/arch/mips/mm/tlbex-mips32.S 2005-05-28 17:42:03.000000000 +0200 -+++ linux.dev/arch/mips/mm/tlbex-mips32.S 2005-05-28 21:48:55.000000000 +0200 -@@ -90,6 +90,9 @@ - .set noat - LEAF(except_vec0_r4000) - .set mips3 -+#ifdef CONFIG_BCM4704 -+ nop -+#endif - #ifdef CONFIG_SMP - mfc0 k1, CP0_CONTEXT - la k0, pgd_current -diff -urN linux.old/arch/mips/mm/pg-r4k.c linux.dev/arch/mips/mm/pg-r4k.c ---- linux.old/arch/mips/mm/pg-r4k.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux.dev/arch/mips/mm/pg-r4k.c 2005-05-28 21:57:52.000000000 +0200 -@@ -180,6 +180,7 @@ - - static inline void build_cdex_s(void) - { -+#if !defined(CONFIG_BCM4704) && !defined(CONFIG_BCM4710) - union mips_instruction mi; - - if ((store_offset & (cpu_scache_line_size() - 1))) -@@ -192,10 +193,12 @@ - mi.c_format.simmediate = store_offset; - - emit_instruction(mi); -+#endif - } - - static inline void build_cdex_p(void) - { -+#if !defined(CONFIG_BCM4704) && !defined(CONFIG_BCM4710) - union mips_instruction mi; - - if (store_offset & (cpu_dcache_line_size() - 1)) -@@ -218,6 +221,7 @@ - mi.c_format.simmediate = store_offset; - - emit_instruction(mi); -+#endif - } - - static void __build_store_reg(int reg) -diff -urN linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h ---- linux.old/include/asm-mips/stackframe.h 2002-11-29 00:53:15.000000000 +0100 -+++ linux.dev/include/asm-mips/stackframe.h 2005-05-28 21:53:03.000000000 +0200 -@@ -172,6 +172,46 @@ - rfe; \ - .set pop - -+#elif defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704) -+ -+#define RESTORE_SOME \ -+ .set push; \ -+ .set reorder; \ -+ mfc0 t0, CP0_STATUS; \ -+ .set pop; \ -+ ori t0, 0x1f; \ -+ xori t0, 0x1f; \ -+ mtc0 t0, CP0_STATUS; \ -+ li v1, 0xff00; \ -+ and t0, v1; \ -+ lw v0, PT_STATUS(sp); \ -+ nor v1, $0, v1; \ -+ and v0, v1; \ -+ or v0, t0; \ -+ ori v1, v0, ST0_IE; \ -+ xori v1, v1, ST0_IE; \ -+ mtc0 v1, CP0_STATUS; \ -+ mtc0 v0, CP0_STATUS; \ -+ lw v1, PT_EPC(sp); \ -+ mtc0 v1, CP0_EPC; \ -+ lw $31, PT_R31(sp); \ -+ lw $28, PT_R28(sp); \ -+ lw $25, PT_R25(sp); \ -+ lw $7, PT_R7(sp); \ -+ lw $6, PT_R6(sp); \ -+ lw $5, PT_R5(sp); \ -+ lw $4, PT_R4(sp); \ -+ lw $3, PT_R3(sp); \ -+ lw $2, PT_R2(sp) -+ -+#define RESTORE_SP_AND_RET \ -+ lw sp, PT_R29(sp); \ -+ nop; \ -+ nop; \ -+ .set mips3; \ -+ eret; \ -+ .set mips0 -+ - #else - - #define RESTORE_SOME \ -diff -urN linux.old/arch/mips/mm/tlbex-r4k.S linux.dev/arch/mips/mm/tlbex-r4k.S ---- linux.old/arch/mips/mm/tlbex-r4k.S 2005-05-28 17:42:03.000000000 +0200 -+++ linux.dev/arch/mips/mm/tlbex-r4k.S 2005-05-29 15:04:43.000000000 +0200 -@@ -168,6 +168,9 @@ - .set noat - LEAF(except_vec0_r4000) - .set mips3 -+#ifdef CONFIG_BCM4704 -+ nop -+#endif - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, _PGDIR_SHIFT # get pgd only bits diff -urN linux.old/arch/mips/kernel/entry.S linux.dev/arch/mips/kernel/entry.S ---- linux.old/arch/mips/kernel/entry.S 2003-08-25 13:44:40.000000000 +0200 -+++ linux.dev/arch/mips/kernel/entry.S 2005-06-01 20:10:36.000000000 +0200 +--- linux.old/arch/mips/kernel/entry.S 2005-07-05 16:46:49.000000000 +0200 ++++ linux.dev/arch/mips/kernel/entry.S 2005-07-06 11:23:55.000000000 +0200 @@ -100,6 +100,10 @@ * and R4400 SC and MC versions. */ @@ -121,8 +13,8 @@ diff -urN linux.old/arch/mips/kernel/entry.S linux.dev/arch/mips/kernel/entry.S mfc0 k0, CP0_INDEX #endif diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c ---- linux.old/arch/mips/mm/c-r4k.c 2005-06-01 18:42:44.000000000 +0200 -+++ linux.dev/arch/mips/mm/c-r4k.c 2005-06-01 18:49:07.000000000 +0200 +--- linux.old/arch/mips/mm/c-r4k.c 2005-07-05 16:46:49.000000000 +0200 ++++ linux.dev/arch/mips/mm/c-r4k.c 2005-07-06 11:23:55.000000000 +0200 @@ -14,6 +14,12 @@ #include #include @@ -136,77 +28,238 @@ diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c #include #include #include -@@ -390,6 +396,11 @@ - addr = start & ~(dc_lsize - 1); - aend = (end - 1) & ~(dc_lsize - 1); +@@ -40,6 +46,8 @@ + .bc_inv = (void *)no_sc_noop + }; -+#ifdef CONFIG_BCM4710 -+ BCM4710_FILL_TLB(addr); -+ BCM4710_FILL_TLB(aend); -+#endif ++int bcm4710 = 0; ++EXPORT_SYMBOL(bcm4710); + struct bcache_ops *bcops = &no_sc_ops; + + #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010) +@@ -64,8 +72,10 @@ + static inline void r4k_blast_dcache_page_setup(void) + { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; +- +- if (dc_lsize == 16) ++ ++ if (bcm4710) ++ r4k_blast_dcache_page = blast_dcache_page; ++ else if (dc_lsize == 16) + r4k_blast_dcache_page = blast_dcache16_page; + else if (dc_lsize == 32) + r4k_blast_dcache_page = r4k_blast_dcache_page_dc32; +@@ -77,7 +87,9 @@ + { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + +- if (dc_lsize == 16) ++ if (bcm4710) ++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed; ++ else if (dc_lsize == 16) + r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed; + else if (dc_lsize == 32) + r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed; +@@ -89,7 +101,9 @@ + { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + +- if (dc_lsize == 16) ++ if (bcm4710) ++ r4k_blast_dcache = blast_dcache; ++ else if (dc_lsize == 16) + r4k_blast_dcache = blast_dcache16; + else if (dc_lsize == 32) + r4k_blast_dcache = blast_dcache32; +@@ -266,6 +280,7 @@ + r4k_blast_dcache(); + r4k_blast_icache(); + ++ if (!bcm4710) + switch (current_cpu_data.cputype) { + case CPU_R4000SC: + case CPU_R4000MC: +@@ -304,10 +319,10 @@ + * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we + * only flush the primary caches but R10000 and R12000 behave sane ... + */ +- if (current_cpu_data.cputype == CPU_R4000SC || ++ if (!bcm4710 && (current_cpu_data.cputype == CPU_R4000SC || + current_cpu_data.cputype == CPU_R4000MC || + current_cpu_data.cputype == CPU_R4400SC || +- current_cpu_data.cputype == CPU_R4400MC) ++ current_cpu_data.cputype == CPU_R4400MC)) + r4k_blast_scache(); + } + +@@ -383,12 +398,15 @@ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + unsigned long addr, aend; + ++ addr = start & ~(dc_lsize - 1); ++ aend = (end - 1) & ~(dc_lsize - 1); + + if (!cpu_has_ic_fills_f_dc) { + if (end - start > dcache_size) + r4k_blast_dcache(); + else { +- addr = start & ~(dc_lsize - 1); +- aend = (end - 1) & ~(dc_lsize - 1); ++ BCM4710_PROTECTED_FILL_TLB(addr); ++ BCM4710_PROTECTED_FILL_TLB(aend); + while (1) { /* Hit_Writeback_Inv_D */ - protected_writeback_dcache_line(addr); -@@ -405,6 +416,10 @@ +@@ -403,8 +421,6 @@ + if (end - start > icache_size) + r4k_blast_icache(); else { - addr = start & ~(ic_lsize - 1); - aend = (end - 1) & ~(ic_lsize - 1); -+#ifdef CONFIG_BCM4710 -+ BCM4710_FILL_TLB(addr); -+ BCM4710_FILL_TLB(aend); -+#endif +- addr = start & ~(ic_lsize - 1); +- aend = (end - 1) & ~(ic_lsize - 1); while (1) { /* Hit_Invalidate_I */ protected_flush_icache_line(addr); -@@ -487,6 +502,10 @@ +@@ -413,6 +429,9 @@ + addr += ic_lsize; + } + } ++ ++ if (bcm4710) ++ flush_cache_all(); + } - a = addr & ~(sc_lsize - 1); - end = (addr + size - 1) & ~(sc_lsize - 1); -+#ifdef CONFIG_BCM4710 -+ BCM4710_FILL_TLB(a); -+ BCM4710_FILL_TLB(end); -+#endif - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) -@@ -509,6 +528,10 @@ + /* +@@ -443,7 +462,8 @@ + if (cpu_has_subset_pcaches) { + unsigned long addr = (unsigned long) page_address(page); + +- r4k_blast_scache_page(addr); ++ if (!bcm4710) ++ r4k_blast_scache_page(addr); + ClearPageDcacheDirty(page); + + return; +@@ -451,6 +471,7 @@ + + if (!cpu_has_ic_fills_f_dc) { + unsigned long addr = (unsigned long) page_address(page); ++ + r4k_blast_dcache_page(addr); + ClearPageDcacheDirty(page); + } +@@ -477,7 +498,7 @@ + /* Catch bad driver code */ + BUG_ON(size == 0); + +- if (cpu_has_subset_pcaches) { ++ if (!bcm4710 && cpu_has_subset_pcaches) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { +@@ -509,6 +530,8 @@ R4600_HIT_CACHEOP_WAR_IMPL; a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); -+#ifdef CONFIG_BCM4710 + BCM4710_FILL_TLB(a); + BCM4710_FILL_TLB(end); -+#endif while (1) { flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) -@@ -537,6 +560,10 @@ +@@ -527,7 +550,7 @@ + /* Catch bad driver code */ + BUG_ON(size == 0); - a = addr & ~(sc_lsize - 1); - end = (addr + size - 1) & ~(sc_lsize - 1); -+#ifdef CONFIG_BCM4710 +- if (cpu_has_subset_pcaches) { ++ if (!bcm4710 && (cpu_has_subset_pcaches)) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { +@@ -554,6 +577,8 @@ + R4600_HIT_CACHEOP_WAR_IMPL; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + BCM4710_FILL_TLB(a); + BCM4710_FILL_TLB(end); -+#endif while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) -@@ -576,6 +603,10 @@ - unsigned long ic_lsize = current_cpu_data.icache.linesz; +@@ -577,6 +602,8 @@ unsigned long dc_lsize = current_cpu_data.dcache.linesz; -+#ifdef CONFIG_BCM4710 + R4600_HIT_CACHEOP_WAR_IMPL; + BCM4710_PROTECTED_FILL_TLB(addr); + BCM4710_PROTECTED_FILL_TLB(addr + 4); -+#endif - R4600_HIT_CACHEOP_WAR_IMPL; protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); + if (MIPS4K_ICACHE_REFILL_WAR) { +@@ -986,10 +1013,12 @@ + case CPU_R4000MC: + case CPU_R4400SC: + case CPU_R4400MC: +- probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); +- sc_present = probe_scache_kseg1(config); +- if (sc_present) +- c->options |= MIPS_CPU_CACHE_CDEX_S; ++ if (!bcm4710) { ++ probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); ++ sc_present = probe_scache_kseg1(config); ++ if (sc_present) ++ c->options |= MIPS_CPU_CACHE_CDEX_S; ++ } + break; + + case CPU_R10000: +@@ -1041,6 +1070,19 @@ + static inline void coherency_setup(void) + { + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); ++ ++#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365) ++ if (BCM330X(current_cpu_data.processor_id)) { ++ uint32 cm; ++ ++ cm = read_c0_diag(); ++ /* Enable icache */ ++ cm |= (1 << 31); ++ /* Enable dcache */ ++ cm |= (1 << 30); ++ write_c0_diag(cm); ++ } ++#endif + + /* + * c0_status.cu=0 specifies that updates by the sc instruction use +@@ -1073,6 +1115,12 @@ + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80); + ++ if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & PRID_REV_MASK) == 0) { ++ printk("Enabling BCM4710A0 cache workarounds.\n"); ++ bcm4710 = 1; ++ } else ++ bcm4710 = 0; ++ + probe_pcache(); + setup_scache(); + +diff -urN linux.old/arch/mips/mm/tlbex-mips32.S linux.dev/arch/mips/mm/tlbex-mips32.S +--- linux.old/arch/mips/mm/tlbex-mips32.S 2005-07-05 16:46:49.000000000 +0200 ++++ linux.dev/arch/mips/mm/tlbex-mips32.S 2005-07-06 11:23:56.000000000 +0200 +@@ -90,6 +90,9 @@ + .set noat + LEAF(except_vec0_r4000) + .set mips3 ++#ifdef CONFIG_BCM4704 ++ nop ++#endif + #ifdef CONFIG_SMP + mfc0 k1, CP0_CONTEXT + la k0, pgd_current diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h ---- linux.old/include/asm-mips/r4kcache.h 2005-06-01 18:42:43.000000000 +0200 -+++ linux.dev/include/asm-mips/r4kcache.h 2005-06-01 19:07:11.000000000 +0200 -@@ -15,6 +15,25 @@ +--- linux.old/include/asm-mips/r4kcache.h 2005-07-05 16:46:49.000000000 +0200 ++++ linux.dev/include/asm-mips/r4kcache.h 2005-07-06 12:52:57.000000000 +0200 +@@ -15,6 +15,18 @@ #include #include @@ -215,306 +268,231 @@ diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kca + +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr)) +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); }) -+ -+#define cache_op(op,addr) \ -+ BCM4710_DUMMY_RREG(); \ -+ __asm__ __volatile__( \ -+ " .set noreorder \n" \ -+ " .set mips3\n\t \n" \ -+ " cache %0, %1 \n" \ -+ " .set mips0 \n" \ -+ " .set reorder" \ -+ : \ -+ : "i" (op), "m" (*(unsigned char *)(addr))) -+ +#else ++#define BCM4710_DUMMY_RREG() ++ ++#define BCM4710_FILL_TLB(addr) ++#define BCM4710_PROTECTED_FILL_TLB(addr) ++#endif + #define cache_op(op,addr) \ __asm__ __volatile__( \ " .set noreorder \n" \ -@@ -24,6 +43,8 @@ - " .set reorder" \ - : \ - : "i" (op), "m" (*(unsigned char *)(addr))) -+#endif -+ +@@ -27,12 +39,25 @@ static inline void flush_icache_line_indexed(unsigned long addr) { -@@ -32,6 +53,9 @@ +- cache_op(Index_Invalidate_I, addr); ++ unsigned int way; ++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; ++ ++ for (way = 0; way < current_cpu_data.dcache.ways; way++) { ++ cache_op(Index_Invalidate_I, addr); ++ addr += ws_inc; ++ } + } static inline void flush_dcache_line_indexed(unsigned long addr) { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif - cache_op(Index_Writeback_Inv_D, addr); +- cache_op(Index_Writeback_Inv_D, addr); ++ unsigned int way; ++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; ++ ++ for (way = 0; way < current_cpu_data.dcache.ways; way++) { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Index_Writeback_Inv_D, addr); ++ addr += ws_inc; ++ } } -@@ -47,6 +71,10 @@ + static inline void flush_scache_line_indexed(unsigned long addr) +@@ -47,6 +72,7 @@ static inline void flush_dcache_line(unsigned long addr) { -+ -+#ifdef CONFIG_BCM4710 + BCM4710_DUMMY_RREG(); -+#endif cache_op(Hit_Writeback_Inv_D, addr); } -@@ -91,6 +119,9 @@ +@@ -91,6 +117,7 @@ */ static inline void protected_writeback_dcache_line(unsigned long addr) { -+#ifdef CONFIG_BCM4710 + BCM4710_DUMMY_RREG(); -+#endif __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n" -@@ -148,8 +179,12 @@ +@@ -138,6 +165,62 @@ + : "r" (base), \ + "i" (op)); + ++#define cache_unroll(base,op) \ ++ __asm__ __volatile__(" \ ++ .set noreorder; \ ++ .set mips3; \ ++ cache %1, (%0); \ ++ .set mips0; \ ++ .set reorder" \ ++ : \ ++ : "r" (base), \ ++ "i" (op)); ++ ++ ++static inline void blast_dcache(void) ++{ ++ unsigned long start = KSEG0; ++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways; ++ unsigned long end = (start + dcache_size); ++ ++ while(start < end) { ++ BCM4710_DUMMY_RREG(); ++ cache_unroll(start,Index_Writeback_Inv_D); ++ start += current_cpu_data.dcache.linesz; ++ } ++} ++ ++static inline void blast_dcache_page(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ ++ BCM4710_FILL_TLB(start); ++ do { ++ BCM4710_DUMMY_RREG(); ++ cache_unroll(start,Hit_Writeback_Inv_D); ++ start += current_cpu_data.dcache.linesz; ++ } while (start < end); ++} ++ ++static inline void blast_dcache_page_indexed(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; ++ unsigned long ws_end = current_cpu_data.dcache.ways << ++ current_cpu_data.dcache.waybit; ++ unsigned long ws, addr; ++ ++ for (ws = 0; ws < ws_end; ws += ws_inc) { ++ start = page + ws; ++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) { ++ BCM4710_DUMMY_RREG(); ++ cache_unroll(addr,Index_Writeback_Inv_D); ++ } ++ } ++} ++ + static inline void blast_dcache16(void) + { + unsigned long start = KSEG0; +@@ -148,8 +231,9 @@ unsigned long ws, addr; for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) + for (addr = start; addr < end; addr += 0x200) { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif cache16_unroll32(addr|ws,Index_Writeback_Inv_D); + } } static inline void blast_dcache16_page(unsigned long page) -@@ -158,6 +193,9 @@ - unsigned long end = start + PAGE_SIZE; - - do { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif - cache16_unroll32(start,Hit_Writeback_Inv_D); - start += 0x200; - } while (start < end); -@@ -173,8 +211,12 @@ +@@ -173,8 +257,9 @@ unsigned long ws, addr; for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x200) + for (addr = start; addr < end; addr += 0x200) { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif cache16_unroll32(addr|ws,Index_Writeback_Inv_D); + } } static inline void blast_icache16(void) -@@ -196,7 +238,13 @@ +@@ -196,6 +281,7 @@ unsigned long start = page; unsigned long end = start + PAGE_SIZE; -+#ifdef CONFIG_BCM4710 + BCM4710_FILL_TLB(start); -+#endif do { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif cache16_unroll32(start,Hit_Invalidate_I); start += 0x200; - } while (start < end); -@@ -291,8 +339,12 @@ +@@ -281,6 +367,7 @@ + : "r" (base), \ + "i" (op)); + ++ + static inline void blast_dcache32(void) + { + unsigned long start = KSEG0; +@@ -291,8 +378,9 @@ unsigned long ws, addr; for (ws = 0; ws < ws_end; ws += ws_inc) - for (addr = start; addr < end; addr += 0x400) + for (addr = start; addr < end; addr += 0x400) { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif cache32_unroll32(addr|ws,Index_Writeback_Inv_D); + } } static inline void blast_dcache32_page(unsigned long page) -@@ -300,7 +352,13 @@ +@@ -316,8 +404,9 @@ + unsigned long ws, addr; + + for (ws = 0; ws < ws_end; ws += ws_inc) +- for (addr = start; addr < end; addr += 0x400) ++ for (addr = start; addr < end; addr += 0x400) { + cache32_unroll32(addr|ws,Index_Writeback_Inv_D); ++ } + } + + static inline void blast_icache32(void) +@@ -339,6 +428,7 @@ unsigned long start = page; unsigned long end = start + PAGE_SIZE; -+#ifdef CONFIG_BCM4710 -+ __asm__ __volatile__("nop;nop;nop;nop"); -+#endif ++ BCM4710_FILL_TLB(start); do { -+#ifdef CONFIG_BCM4710 -+ BCM4710_DUMMY_RREG(); -+#endif - cache32_unroll32(start,Hit_Writeback_Inv_D); + cache32_unroll32(start,Hit_Invalidate_I); start += 0x400; - } while (start < end); -@@ -339,6 +397,9 @@ +@@ -443,6 +533,7 @@ unsigned long start = page; unsigned long end = start + PAGE_SIZE; -+#ifdef CONFIG_BCM4710 + BCM4710_FILL_TLB(start); -+#endif do { - cache32_unroll32(start,Hit_Invalidate_I); - start += 0x400; -diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c ---- linux.old/arch/mips/mm/c-r4k.c 2005-06-01 18:49:07.000000000 +0200 -+++ linux.dev/arch/mips/mm/c-r4k.c 2005-06-03 12:11:13.000000000 +0200 -@@ -51,6 +51,7 @@ - #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010) - #define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x2020) - -+#ifndef CONFIG_BCM4710 - #define R4600_HIT_CACHEOP_WAR_IMPL \ - do { \ - if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) \ -@@ -58,11 +59,17 @@ - if (R4600_V1_HIT_CACHEOP_WAR) \ - __asm__ __volatile__("nop;nop;nop;nop"); \ - } while (0) -+#else -+#define R4600_HIT_CACHEOP_WAR_IMPL -+#endif - - static void (* r4k_blast_dcache_page)(unsigned long addr); - - static inline void r4k_blast_dcache_page_dc32(unsigned long addr) - { -+#ifdef CONFIG_BCM4710 -+ BCM4710_FILL_TLB(addr); -+#endif - R4600_HIT_CACHEOP_WAR_IMPL; - blast_dcache32_page(addr); - } -@@ -581,6 +588,10 @@ - R4600_HIT_CACHEOP_WAR_IMPL; - a = addr & ~(dc_lsize - 1); - end = (addr + size - 1) & ~(dc_lsize - 1); -+#ifdef CONFIG_BCM4710 -+ BCM4710_FILL_TLB(a); -+ BCM4710_FILL_TLB(end); -+#endif - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) -diff -urN linux.old/arch/mips/mm/c-r4k.c linux.dev/arch/mips/mm/c-r4k.c ---- linux.old/arch/mips/mm/c-r4k.c 2005-06-11 19:39:17.000000000 +0200 -+++ linux.dev/arch/mips/mm/c-r4k.c 2005-06-11 19:54:48.000000000 +0200 -@@ -1083,6 +1083,19 @@ - static inline void coherency_setup(void) - { - change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); -+ -+#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365) -+ if (BCM330X(current_cpu_data.processor_id)) { -+ uint32 cm; -+ -+ cm = read_c0_diag(); -+ /* Enable icache */ -+ cm |= (1 << 31); -+ /* Enable dcache */ -+ cm |= (1 << 30); -+ write_c0_diag(cm); -+ } -+#endif - - /* - * c0_status.cu=0 specifies that updates by the sc instruction use -@@ -1104,6 +1117,42 @@ + cache64_unroll32(start,Hit_Invalidate_I); + start += 0x800; +diff -urN linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h +--- linux.old/include/asm-mips/stackframe.h 2005-07-05 16:46:49.000000000 +0200 ++++ linux.dev/include/asm-mips/stackframe.h 2005-07-06 11:23:56.000000000 +0200 +@@ -209,6 +209,20 @@ - } + #endif -+#ifdef CONFIG_BCM4704 -+static void __init mips32_icache_fill(unsigned long addr, uint nbytes) -+{ -+ unsigned long ic_lsize = current_cpu_data.icache.linesz; -+ int i; -+ for (i = 0; i < nbytes; i += ic_lsize) -+ fill_icache_line((addr + i)); -+} ++#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704) + -+/* -+ * This must be run from the cache on 4704A0 -+ * so there are no mips core BIU ops in progress -+ * when the PFC is enabled. -+ */ -+#define PFC_CR0 0xff400000 /* control reg 0 */ -+#define PFC_CR1 0xff400004 /* control reg 1 */ -+static void __init enable_pfc(u32 mode) -+{ -+ /* write range */ -+ *(volatile u32 *)PFC_CR1 = 0xffff0000; -+ -+ /* enable */ -+ *(volatile u32 *)PFC_CR0 = mode; -+} ++#undef RESTORE_SP_AND_RET ++#define RESTORE_SP_AND_RET \ ++ lw sp, PT_R29(sp); \ ++ .set mips3; \ ++ nop; \ ++ nop; \ ++ eret; \ ++ .set mips0 + -+void check_enable_mips_pfc(int val) -+{ -+ /* enable prefetch cache */ -+ if (BCM330X(current_cpu_data.processor_id) -+ && (read_c0_diag() & (1 << 29))) { -+ mips32_icache_fill((unsigned long) &enable_pfc, 64); -+ enable_pfc(val); -+ } -+} +#endif + - void __init ld_mmu_r4xx0(void) - { - extern void build_clear_page(void); -@@ -1159,47 +1208,9 @@ - - build_clear_page(); - build_copy_page(); --} -- --#ifdef CONFIG_BCM4704 --static void __init mips32_icache_fill(unsigned long addr, uint nbytes) --{ -- unsigned long ic_lsize = current_cpu_data.icache.linesz; -- int i; -- for (i = 0; i < nbytes; i += ic_lsize) -- fill_icache_line((addr + i)); --} -- --/* -- * This must be run from the cache on 4704A0 -- * so there are no mips core BIU ops in progress -- * when the PFC is enabled. -- */ --#define PFC_CR0 0xff400000 /* control reg 0 */ --#define PFC_CR1 0xff400004 /* control reg 1 */ --static void __init enable_pfc(u32 mode) --{ -- /* write range */ -- *(volatile u32 *)PFC_CR1 = 0xffff0000; -- -- /* enable */ -- *(volatile u32 *)PFC_CR0 = mode; --} --#endif -- -- --void check_enable_mips_pfc(int val) --{ -- -+ - #ifdef CONFIG_BCM4704 -- struct cpuinfo_mips *c = ¤t_cpu_data; -- -- /* enable prefetch cache */ -- if (((c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) == PRID_IMP_BCM3302) -- && (read_c0_diag() & (1 << 29))) { -- mips32_icache_fill((unsigned long) &enable_pfc, 64); -- enable_pfc(val); -- } -+ check_enable_mips_pfc(0x15); - #endif ++ + #define RESTORE_SP \ + lw sp, PT_R29(sp); \ + +diff -urN linux.old/mm/memory.c linux.dev/mm/memory.c +--- linux.old/mm/memory.c 2005-04-04 03:42:20.000000000 +0200 ++++ linux.dev/mm/memory.c 2005-07-06 11:23:56.000000000 +0200 +@@ -925,6 +925,7 @@ + flush_page_to_ram(new_page); + flush_cache_page(vma, address); + establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); ++ flush_icache_page(vma, new_page); } + /*