patch-2.4.25 linux-2.4.25/arch/mips/mm/c-r4k.c
Next file: linux-2.4.25/arch/mips/mm/c-sb1.c
Previous file: linux-2.4.25/arch/mips/mm/c-r3k.c
Back to the patch index
Back to the overall index
- Lines: 635
- Date:
2004-02-18 05:36:30.000000000 -0800
- Orig file:
linux-2.4.24/arch/mips/mm/c-r4k.c
- Orig date:
2003-08-25 04:44:40.000000000 -0700
diff -urN linux-2.4.24/arch/mips/mm/c-r4k.c linux-2.4.25/arch/mips/mm/c-r4k.c
@@ -28,27 +28,6 @@
static unsigned long icache_size, dcache_size, scache_size;
-extern void andes_clear_page(void * page);
-extern void r4k_clear_page32_d16(void * page);
-extern void r4k_clear_page32_d32(void * page);
-extern void r4k_clear_page_d16(void * page);
-extern void r4k_clear_page_d32(void * page);
-extern void r4k_clear_page_r4600_v1(void * page);
-extern void r4k_clear_page_r4600_v2(void * page);
-extern void r4k_clear_page_s16(void * page);
-extern void r4k_clear_page_s32(void * page);
-extern void r4k_clear_page_s64(void * page);
-extern void r4k_clear_page_s128(void * page);
-extern void andes_copy_page(void * to, void * from);
-extern void r4k_copy_page_d16(void * to, void * from);
-extern void r4k_copy_page_d32(void * to, void * from);
-extern void r4k_copy_page_r4600_v1(void * to, void * from);
-extern void r4k_copy_page_r4600_v2(void * to, void * from);
-extern void r4k_copy_page_s16(void * to, void * from);
-extern void r4k_copy_page_s32(void * to, void * from);
-extern void r4k_copy_page_s64(void * to, void * from);
-extern void r4k_copy_page_s128(void * to, void * from);
-
/*
* Dummy cache handling routines for machines without boardcaches
*/
@@ -73,80 +52,46 @@
__asm__ __volatile__("nop;nop;nop;nop"); \
} while (0)
-static void r4k_blast_dcache_page(unsigned long addr)
-{
- static void *l = &&init;
- unsigned long dc_lsize;
-
- goto *l;
+static void (* r4k_blast_dcache_page)(unsigned long addr);
-dc_16:
- blast_dcache16_page(addr);
- return;
-
-dc_32:
+static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
+{
R4600_HIT_CACHEOP_WAR_IMPL;
blast_dcache32_page(addr);
- return;
+}
-init:
- dc_lsize = current_cpu_data.dcache.linesz;
+static inline void r4k_blast_dcache_page_setup(void)
+{
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
if (dc_lsize == 16)
- l = &&dc_16;
+ r4k_blast_dcache_page = blast_dcache16_page;
else if (dc_lsize == 32)
- l = &&dc_32;
- goto *l;
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
}
-static void r4k_blast_dcache_page_indexed(unsigned long addr)
-{
- static void *l = &&init;
- unsigned long dc_lsize;
-
- goto *l;
-
-dc_16:
- blast_dcache16_page_indexed(addr);
- return;
-
-dc_32:
- blast_dcache32_page_indexed(addr);
- return;
+static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
-init:
- dc_lsize = current_cpu_data.dcache.linesz;
+static void r4k_blast_dcache_page_indexed_setup(void)
+{
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
if (dc_lsize == 16)
- l = &&dc_16;
+ r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
else if (dc_lsize == 32)
- l = &&dc_32;
- goto *l;
+ r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
}
-static void r4k_blast_dcache(void)
-{
- static void *l = &&init;
- unsigned long dc_lsize;
-
- goto *l;
-
-dc_16:
- blast_dcache16();
- return;
-
-dc_32:
- blast_dcache32();
- return;
+static void (* r4k_blast_dcache)(void);
-init:
- dc_lsize = current_cpu_data.dcache.linesz;
+static inline void r4k_blast_dcache_setup(void)
+{
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
if (dc_lsize == 16)
- l = &&dc_16;
+ r4k_blast_dcache = blast_dcache16;
else if (dc_lsize == 32)
- l = &&dc_32;
- goto *l;
+ r4k_blast_dcache = blast_dcache32;
}
/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
@@ -201,175 +146,82 @@
cache32_unroll32(addr|ws,Index_Invalidate_I);
}
-static void r4k_blast_icache_page(unsigned long addr)
+static void (* r4k_blast_icache_page)(unsigned long addr);
+
+static inline void r4k_blast_icache_page_setup(void)
{
unsigned long ic_lsize = current_cpu_data.icache.linesz;
- static void *l = &&init;
-
- goto *l;
-
-ic_16:
- blast_icache16_page(addr);
- return;
-
-ic_32:
- blast_icache32_page(addr);
- return;
-ic_64:
- blast_icache64_page(addr);
- return;
-
-init:
if (ic_lsize == 16)
- l = &&ic_16;
+ r4k_blast_icache_page = blast_icache16_page;
else if (ic_lsize == 32)
- l = &&ic_32;
+ r4k_blast_icache_page = blast_icache32_page;
else if (ic_lsize == 64)
- l = &&ic_64;
- goto *l;
+ r4k_blast_icache_page = blast_icache64_page;
}
-static void r4k_blast_icache_page_indexed(unsigned long addr)
+static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
+
+static inline void r4k_blast_icache_page_indexed_setup(void)
{
unsigned long ic_lsize = current_cpu_data.icache.linesz;
- static void *l = &&init;
-
- goto *l;
-
-ic_16:
- blast_icache16_page_indexed(addr);
- return;
-
-ic_32:
- blast_icache32_page_indexed(addr);
- return;
-
-ic_64:
- blast_icache64_page_indexed(addr);
- return;
-ic_32_tx49:
- tx49_blast_icache32_page_indexed(addr);
- return;
-
-init:
if (ic_lsize == 16)
- l = &&ic_16;
+ r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
+ else if (ic_lsize == 32 && TX49XX_ICACHE_INDEX_INV_WAR)
+ r4k_blast_icache_page_indexed = tx49_blast_icache32_page_indexed;
else if (ic_lsize == 32)
- if (TX49XX_ICACHE_INDEX_INV_WAR)
- l = &&ic_32_tx49;
- else
- l = &&ic_32;
+ r4k_blast_icache_page_indexed = blast_icache32_page_indexed;
else if (ic_lsize == 64)
- l = &&ic_64;
- goto *l;
+ r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
}
-static void r4k_blast_icache(void)
+static void (* r4k_blast_icache)(void);
+
+static inline void r4k_blast_icache_setup(void)
{
unsigned long ic_lsize = current_cpu_data.icache.linesz;
- static void *l = &&init;
-
- goto *l;
-
-ic_16:
- blast_icache16();
- return;
-
-ic_32:
- blast_icache32();
- return;
-ic_64:
- blast_icache64();
- return;
-
-ic_32_tx49:
- tx49_blast_icache32();
- return;
-
-init:
if (ic_lsize == 16)
- l = &&ic_16;
+ r4k_blast_icache = blast_icache16;
+ else if (ic_lsize == 32 && TX49XX_ICACHE_INDEX_INV_WAR)
+ r4k_blast_icache = tx49_blast_icache32;
else if (ic_lsize == 32)
- if (TX49XX_ICACHE_INDEX_INV_WAR)
- l = &&ic_32_tx49;
- else
- l = &&ic_32;
+ r4k_blast_icache = blast_icache32;
else if (ic_lsize == 64)
- l = &&ic_64;
- goto *l;
+ r4k_blast_icache = blast_icache64;
}
-static void r4k_blast_scache_page(unsigned long addr)
+static void (* r4k_blast_scache_page)(unsigned long addr);
+
+static inline void r4k_blast_scache_page_setup(void)
{
unsigned long sc_lsize = current_cpu_data.scache.linesz;
- static void *l = &&init;
-
- goto *l;
-
-sc_16:
- blast_scache16_page(addr);
- return;
-sc_32:
- blast_scache32_page(addr);
- return;
-
-sc_64:
- blast_scache64_page(addr);
- return;
-
-sc_128:
- blast_scache128_page(addr);
- return;
-
-init:
if (sc_lsize == 16)
- l = &&sc_16;
+ r4k_blast_scache_page = blast_scache16_page;
else if (sc_lsize == 32)
- l = &&sc_32;
+ r4k_blast_scache_page = blast_scache32_page;
else if (sc_lsize == 64)
- l = &&sc_64;
+ r4k_blast_scache_page = blast_scache64_page;
else if (sc_lsize == 128)
- l = &&sc_128;
- goto *l;
+ r4k_blast_scache_page = blast_scache128_page;
}
-static void r4k_blast_scache(void)
+static void (* r4k_blast_scache)(void);
+
+static inline void r4k_blast_scache_setup(void)
{
unsigned long sc_lsize = current_cpu_data.scache.linesz;
- static void *l = &&init;
-
- goto *l;
-sc_16:
- blast_scache16();
- return;
-
-sc_32:
- blast_scache32();
- return;
-
-sc_64:
- blast_scache64();
- return;
-
-sc_128:
- blast_scache128();
- return;
-
-init:
if (sc_lsize == 16)
- l = &&sc_16;
+ r4k_blast_scache = blast_scache16;
else if (sc_lsize == 32)
- l = &&sc_32;
+ r4k_blast_scache = blast_scache32;
else if (sc_lsize == 64)
- l = &&sc_64;
+ r4k_blast_scache = blast_scache64;
else if (sc_lsize == 128)
- l = &&sc_128;
- goto *l;
+ r4k_blast_scache = blast_scache128;
}
static void r4k_flush_cache_all(void)
@@ -561,7 +413,9 @@
*/
if (cpu_has_subset_pcaches) {
unsigned long addr = (unsigned long) page_address(page);
+
r4k_blast_scache_page(addr);
+ ClearPageDcacheDirty(page);
return;
}
@@ -569,6 +423,7 @@
if (!cpu_has_ic_fills_f_dc) {
unsigned long addr = (unsigned long) page_address(page);
r4k_blast_dcache_page(addr);
+ ClearPageDcacheDirty(page);
}
/*
@@ -775,6 +630,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
c->dcache.waybit= ffs(dcache_size/2) - 1;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_R5432:
@@ -788,6 +645,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_TX49XX:
@@ -800,6 +659,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 4;
c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_R4000PC:
@@ -818,6 +679,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 1;
c->dcache.waybit = 0; /* does not matter */
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_R10000:
@@ -831,9 +694,20 @@
c->dcache.linesz = 32;
c->dcache.ways = 2;
c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_PREFETCH;
break;
+ case CPU_VR4133:
+ write_c0_config(config & ~CONF_EB);
case CPU_VR4131:
+ /* Workaround for cache instruction bug of VR4131 */
+ if (c->processor_id == 0x0c80U || c->processor_id == 0x0c81U ||
+ c->processor_id == 0x0c82U) {
+ config &= ~0x00000030U;
+ config |= 0x00410000U;
+ write_c0_config(config);
+ }
icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 2;
@@ -843,6 +717,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
c->dcache.waybit = ffs(dcache_size/2) - 1;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_VR41XX:
@@ -860,11 +736,14 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 1;
c->dcache.waybit = 0; /* does not matter */
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
case CPU_RM7000:
rm7k_erratum31();
+ case CPU_RM9000:
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 4;
@@ -874,6 +753,8 @@
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 4;
c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
break;
default:
@@ -898,6 +779,9 @@
c->icache.linesz;
c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+ if (config & 0x8) /* VI bit */
+ c->icache.flags |= MIPS_CACHE_VTAG;
+
/*
* Now probe the MIPS32 / MIPS64 data cache.
*/
@@ -914,6 +798,8 @@
c->dcache.ways *
c->dcache.linesz;
c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+
+ c->options |= MIPS_CPU_PREFETCH;
break;
}
@@ -947,9 +833,6 @@
if (c->dcache.waysize > PAGE_SIZE)
c->dcache.flags |= MIPS_CACHE_ALIASES;
- if (config & 0x8) /* VI bit */
- c->icache.flags |= MIPS_CACHE_VTAG;
-
switch (c->cputype) {
case CPU_20KC:
/*
@@ -1037,71 +920,6 @@
return 1;
}
-static void __init setup_noscache_funcs(void)
-{
- unsigned int prid;
-
- switch (current_cpu_data.dcache.linesz) {
- case 16:
- if (cpu_has_64bits)
- _clear_page = r4k_clear_page_d16;
- else
- _clear_page = r4k_clear_page32_d16;
- _copy_page = r4k_copy_page_d16;
-
- break;
- case 32:
- prid = read_c0_prid() & 0xfff0;
- if (prid == 0x2010) { /* R4600 V1.7 */
- _clear_page = r4k_clear_page_r4600_v1;
- _copy_page = r4k_copy_page_r4600_v1;
- } else if (prid == 0x2020) { /* R4600 V2.0 */
- _clear_page = r4k_clear_page_r4600_v2;
- _copy_page = r4k_copy_page_r4600_v2;
- } else {
- if (cpu_has_64bits)
- _clear_page = r4k_clear_page_d32;
- else
- _clear_page = r4k_clear_page32_d32;
- _copy_page = r4k_copy_page_d32;
- }
- break;
- }
-}
-
-static void __init setup_scache_funcs(void)
-{
- struct cpuinfo_mips *c = ¤t_cpu_data;
-
- if (c->dcache.linesz > c->scache.linesz)
- panic("Invalid primary cache configuration detected");
-
- if (c->cputype == CPU_R10000 || c->cputype == CPU_R12000) {
- _clear_page = andes_clear_page;
- _copy_page = andes_copy_page;
- return;
- }
-
- switch (c->scache.linesz) {
- case 16:
- _clear_page = r4k_clear_page_s16;
- _copy_page = r4k_copy_page_s16;
- break;
- case 32:
- _clear_page = r4k_clear_page_s32;
- _copy_page = r4k_copy_page_s32;
- break;
- case 64:
- _clear_page = r4k_clear_page_s64;
- _copy_page = r4k_copy_page_s64;
- break;
- case 128:
- _clear_page = r4k_clear_page_s128;
- _copy_page = r4k_copy_page_s128;
- break;
- }
-}
-
typedef int (*probe_func_t)(unsigned long);
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
@@ -1127,6 +945,8 @@
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;
break;
case CPU_R10000:
@@ -1140,14 +960,13 @@
case CPU_R5000:
case CPU_NEVADA:
- setup_noscache_funcs();
#ifdef CONFIG_R5000_CPU_SCACHE
r5k_sc_init();
#endif
return;
case CPU_RM7000:
- setup_noscache_funcs();
+ case CPU_RM9000:
#ifdef CONFIG_RM7000_CPU_SCACHE
rm7k_sc_init();
#endif
@@ -1157,10 +976,8 @@
sc_present = 0;
}
- if (!sc_present) {
- setup_noscache_funcs();
+ if (!sc_present)
return;
- }
if ((c->isa_level == MIPS_CPU_ISA_M32 ||
c->isa_level == MIPS_CPU_ISA_M64) &&
@@ -1176,7 +993,6 @@
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
c->options |= MIPS_CPU_SUBSET_CACHES;
- setup_scache_funcs();
}
static inline void coherency_setup(void)
@@ -1205,6 +1021,8 @@
void __init ld_mmu_r4xx0(void)
{
+ extern void build_clear_page(void);
+ extern void build_copy_page(void);
extern char except_vec2_generic;
struct cpuinfo_mips *c = ¤t_cpu_data;
@@ -1214,11 +1032,19 @@
probe_pcache();
setup_scache();
- coherency_setup();
if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
c->dcache.flags |= MIPS_CACHE_ALIASES;
+ r4k_blast_dcache_page_setup();
+ r4k_blast_dcache_page_indexed_setup();
+ r4k_blast_dcache_setup();
+ r4k_blast_icache_page_setup();
+ r4k_blast_icache_page_indexed_setup();
+ r4k_blast_icache_setup();
+ r4k_blast_scache_page_setup();
+ r4k_blast_scache_setup();
+
/*
* Some MIPS32 and MIPS64 processors have physically indexed caches.
* This code supports virtually indexed processors and will be
@@ -1247,4 +1073,8 @@
#endif
__flush_cache_all();
+ coherency_setup();
+
+ build_clear_page();
+ build_copy_page();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)