- Add code to flush scache also (need to revisit if any missing) - Add init code for scache - Add WAR for E9000 ENTRYHI bug, aha! And this brings back OPCODE for "or" Signed-off-by: Kiran Kumar Thota <kiran_thota@xxxxxxxxxxxxxx> diff -Naur a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c --- a/arch/mips/mm/c-r4k.c 2005-07-11 11:28:10.000000000 -0700 +++ b/arch/mips/mm/c-r4k.c 2006-06-22 11:48:21.000000000 -0700 @@ -649,7 +649,11 @@ a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); while (1) { +#ifdef CONFIG_CPU_RM9000 + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ +#else flush_dcache_line(a); /* Hit_Writeback_Inv_D */ +#endif if (a == end) break; a += dc_lsize; @@ -694,7 +698,11 @@ a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); while (1) { +#ifdef CONFIG_CPU_RM9000 + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ +#else flush_dcache_line(a); /* Hit_Writeback_Inv_D */ +#endif if (a == end) break; a += dc_lsize; @@ -1164,6 +1172,9 @@ case CPU_RM9000: #ifdef CONFIG_RM7000_CPU_SCACHE rm7k_sc_init(); +#ifdef CONFIG_CPU_RM9000 + sc_present = 1; +#endif #endif return; diff -Naur a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c --- a/arch/mips/mm/sc-rm7k.c 2005-07-11 11:28:10.000000000 -0700 +++ b/arch/mips/mm/sc-rm7k.c 2006-06-22 11:48:21.000000000 -0700 @@ -144,6 +144,9 @@ void __init rm7k_sc_init(void) { unsigned int config = read_c0_config(); +#ifdef CONFIG_CPU_RM9000 + struct cpuinfo_mips *c = ¤t_cpu_data; +#endif if ((config & RM7K_CONF_SC)) return; @@ -154,6 +157,12 @@ if (!(config & RM7K_CONF_SE)) rm7k_sc_enable(); +#ifdef CONFIG_CPU_RM9000 + c->scache.linesz = 16<<((config & R4K_CONF_SB) >> 22); + c->scache.ways = 4; + c->scache.waybit = 5; + c->options |= MIPS_CPU_CACHE_CDEX_S; +#endif /* * While we're at it let's deal with the tertiary cache. */ diff -Naur a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c --- a/arch/mips/mm/tlbex.c 2005-07-11 11:28:10.000000000 -0700 +++ b/arch/mips/mm/tlbex.c 2006-06-22 12:24:19.000000000 -0700 @@ -50,6 +50,12 @@ return R10000_LLSC_WAR; } +static __init int __attribute__((unused)) e9000_llsc_war(void) +{ + return E9000_ENTRYHI_WAR; +} + + /* * A little micro-assembler, intended for TLB refill handler * synthesizing. It is intentionally kept simple, does only support @@ -95,7 +101,7 @@ insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, - insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, + insn_or, insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori }; @@ -147,6 +153,7 @@ { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM }, { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD }, { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD }, + { insn_or, M(spec_op,0,0,0,0,or_op), RS | RT | RD }, { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM }, { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 }, { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM }, @@ -378,6 +385,7 @@ I_u2s3u1(_lw); I_u1u2(_mfc0); I_u1u2(_mtc0); +I_u3u1u2(_or); I_u2u1u3(_ori); I_0(_rfe); I_u2s3u1(_sc); @@ -1157,6 +1165,16 @@ /* No need for i_nop */ } + if (e9000_llsc_war()) { + i_MFC0(&p, K0, C0_BADVADDR); + i_MFC0(&p, K1, C0_ENTRYHI); + i_ori(&p, K0, K0, 0x1fff); + i_xori(&p, K0, K0, 0x1fff); + i_andi(&p, K1, K1, 0x0fff); + i_or(&p, K0, K0, K1); + i_MTC0(&p, K0, C0_ENTRYHI); + } + #ifdef CONFIG_MIPS64 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ #else @@ -1665,6 +1683,16 @@ /* No need for i_nop */ } + if (e9000_llsc_war()) { + i_MFC0(&p, K0, C0_BADVADDR); + i_MFC0(&p, K1, C0_ENTRYHI); + i_ori(&p, K0, K0, 0x1fff); + i_xori(&p, K0, K0, 0x1fff); + i_andi(&p, K1, K1, 0x0fff); + i_or(&p, K0, K0, K1); + i_MTC0(&p, K0, C0_ENTRYHI); + } + build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); build_make_valid(&p, &r, K0, K1); @@ -1704,6 +1732,16 @@ memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); + if (e9000_llsc_war()) { + i_MFC0(&p, K0, C0_BADVADDR); + i_MFC0(&p, K1, C0_ENTRYHI); + i_ori(&p, K0, K0, 0x1fff); + i_xori(&p, K0, K0, 0x1fff); + i_andi(&p, K1, K1, 0x0fff); + i_or(&p, K0, K0, K1); + i_MTC0(&p, K0, C0_ENTRYHI); + } + build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); build_make_write(&p, &r, K0, K1); @@ -1743,6 +1781,16 @@ memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); + if (e9000_llsc_war()) { + i_MFC0(&p, K0, C0_BADVADDR); + i_MFC0(&p, K1, C0_ENTRYHI); + i_ori(&p, K0, K0, 0x1fff); + i_xori(&p, K0, K0, 0x1fff); + i_andi(&p, K1, K1, 0x0fff); + i_or(&p, K0, K0, K1); + i_MTC0(&p, K0, C0_ENTRYHI); + } + build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); /* Present and writable bits set, set accessed and dirty bits. */ diff -Naur a/include/asm-mips/war.h b/include/asm-mips/war.h --- a/include/asm-mips/war.h 2005-07-11 11:28:10.000000000 -0700 +++ b/include/asm-mips/war.h 2006-06-22 11:48:21.000000000 -0700 @@ -182,10 +182,16 @@ * being fetched may case spurious exceptions. */ #if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \ - defined(CONFIG_PMC_YOSEMITE) + defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_PMC_SEQUOIA) #define ICACHE_REFILLS_WORKAROUND_WAR 1 #endif +/* E9000 has a bug - The EntryHi register gets corrupt in some exceptional cases */ +#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \ + defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_PMC_SEQUOIA) +#define E9000_ENTRYHI_WAR 1 +#endif + /* * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that @@ -198,6 +204,9 @@ /* * Workarounds default to off */ +#ifndef E9000_ENTRYHI_WAR +#define E9000_ENTRYHI_WAR 0 +#endif #ifndef ICACHE_REFILLS_WORKAROUND_WAR #define ICACHE_REFILLS_WORKAROUND_WAR 0 #endif