diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/cpu/mips32/cache.S | 90 | ||||
-rw-r--r-- | arch/mips/cpu/mips32/cpu.c | 73 | ||||
-rw-r--r-- | arch/mips/include/asm/mipsregs.h | 6 |
3 files changed, 150 insertions, 19 deletions
diff --git a/arch/mips/cpu/mips32/cache.S b/arch/mips/cpu/mips32/cache.S index 12f656c..22bd844 100644 --- a/arch/mips/cpu/mips32/cache.S +++ b/arch/mips/cpu/mips32/cache.S @@ -20,15 +20,6 @@ #define RA t9 -/* - * 16kB is the maximum size of instruction and data caches on MIPS 4K, - * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience. - * - * Note that the above size is the maximum size of primary cache. U-Boot - * doesn't have L2 cache support for now. - */ -#define MIPS_MAX_CACHE_SIZE 0x10000 - #define INDEX_BASE CKSEG0 .macro cache_op op addr @@ -126,12 +117,85 @@ LEAF(mips_init_dcache) */ NESTED(mips_cache_reset, 0, ra) move RA, ra - li t2, CONFIG_SYS_ICACHE_SIZE - li t3, CONFIG_SYS_DCACHE_SIZE + +#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \ + !defined(CONFIG_SYS_CACHELINE_SIZE) + /* read Config1 for use below */ + mfc0 t5, CP0_CONFIG, 1 +#endif + +#ifdef CONFIG_SYS_CACHELINE_SIZE + li t7, CONFIG_SYS_CACHELINE_SIZE li t8, CONFIG_SYS_CACHELINE_SIZE +#else + /* Detect I-cache line size. */ + srl t8, t5, MIPS_CONF1_IL_SHIFT + andi t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT) + beqz t8, 1f + li t6, 2 + sllv t8, t6, t8 - li v0, MIPS_MAX_CACHE_SIZE +1: /* Detect D-cache line size. */ + srl t7, t5, MIPS_CONF1_DL_SHIFT + andi t7, t7, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) + beqz t7, 1f + li t6, 2 + sllv t7, t6, t7 +1: +#endif +#ifdef CONFIG_SYS_ICACHE_SIZE + li t2, CONFIG_SYS_ICACHE_SIZE +#else + /* Detect I-cache size. */ + srl t6, t5, MIPS_CONF1_IS_SHIFT + andi t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT) + li t4, 32 + xori t2, t6, 0x7 + beqz t2, 1f + addi t6, t6, 1 + sllv t4, t4, t6 +1: /* At this point t4 == I-cache sets. */ + mul t2, t4, t8 + srl t6, t5, MIPS_CONF1_IA_SHIFT + andi t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT) + addi t6, t6, 1 + /* At this point t6 == I-cache ways. */ + mul t2, t2, t6 +#endif + +#ifdef CONFIG_SYS_DCACHE_SIZE + li t3, CONFIG_SYS_DCACHE_SIZE +#else + /* Detect D-cache size. */ + srl t6, t5, MIPS_CONF1_DS_SHIFT + andi t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) + li t4, 32 + xori t3, t6, 0x7 + beqz t3, 1f + addi t6, t6, 1 + sllv t4, t4, t6 +1: /* At this point t4 == I-cache sets. */ + mul t3, t4, t7 + srl t6, t5, MIPS_CONF1_DA_SHIFT + andi t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) + addi t6, t6, 1 + /* At this point t6 == I-cache ways. */ + mul t3, t3, t6 +#endif + + /* Determine the largest L1 cache size */ +#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) +#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE + li v0, CONFIG_SYS_ICACHE_SIZE +#else + li v0, CONFIG_SYS_DCACHE_SIZE +#endif +#else + move v0, t2 + sltu t1, t2, t3 + movn v0, t3, t1 +#endif /* * Now clear that much memory starting from zero. */ @@ -163,7 +227,7 @@ NESTED(mips_cache_reset, 0, ra) * then initialize D-cache. */ move a1, t3 - move a2, t8 + move a2, t7 PTR_LA v1, mips_init_dcache jalr v1 diff --git a/arch/mips/cpu/mips32/cpu.c b/arch/mips/cpu/mips32/cpu.c index 28d5c45..278865b 100644 --- a/arch/mips/cpu/mips32/cpu.c +++ b/arch/mips/cpu/mips32/cpu.c @@ -34,28 +34,89 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } +#ifdef CONFIG_SYS_CACHELINE_SIZE + +static inline unsigned long icache_line_size(void) +{ + return CONFIG_SYS_CACHELINE_SIZE; +} + +static inline unsigned long dcache_line_size(void) +{ + return CONFIG_SYS_CACHELINE_SIZE; +} + +#else /* !CONFIG_SYS_CACHELINE_SIZE */ + +static inline unsigned long icache_line_size(void) +{ + unsigned long conf1, il; + conf1 = read_c0_config1(); + il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT; + if (!il) + return 0; + return 2 << il; +} + +static inline unsigned long dcache_line_size(void) +{ + unsigned long conf1, dl; + conf1 = read_c0_config1(); + dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT; + if (!dl) + return 0; + return 2 << dl; +} + +#endif /* !CONFIG_SYS_CACHELINE_SIZE */ + void flush_cache(ulong start_addr, ulong size) { - unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; - unsigned long addr = start_addr & ~(lsize - 1); - unsigned long aend = (start_addr + size - 1) & ~(lsize - 1); + unsigned long ilsize = icache_line_size(); + unsigned long dlsize = dcache_line_size(); + unsigned long addr, aend; /* aend will be miscalculated when size is zero, so we return here */ if (size == 0) return; + addr = start_addr & ~(dlsize - 1); + aend = (start_addr + size - 1) & ~(dlsize - 1); + + if (ilsize == dlsize) { + /* flush I-cache & D-cache simultaneously */ + while (1) { + cache_op(HIT_WRITEBACK_INV_D, addr); + cache_op(HIT_INVALIDATE_I, addr); + if (addr == aend) + break; + addr += dlsize; + } + return; + } + + /* flush D-cache */ while (1) { cache_op(HIT_WRITEBACK_INV_D, addr); + if (addr == aend) + break; + addr += dlsize; + } + + /* flush I-cache */ + addr = start_addr & ~(ilsize - 1); + aend = (start_addr + size - 1) & ~(ilsize - 1); + while (1) { cache_op(HIT_INVALIDATE_I, addr); if (addr == aend) break; - addr += lsize; + addr += ilsize; } } void flush_dcache_range(ulong start_addr, ulong stop) { - unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; + unsigned long lsize = dcache_line_size(); unsigned long addr = start_addr & ~(lsize - 1); unsigned long aend = (stop - 1) & ~(lsize - 1); @@ -69,7 +130,7 @@ void flush_dcache_range(ulong start_addr, ulong stop) void invalidate_dcache_range(ulong start_addr, ulong stop) { - unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; + unsigned long lsize = dcache_line_size(); unsigned long addr = start_addr & ~(lsize - 1); unsigned long aend = (stop - 1) & ~(lsize - 1); diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index be7e5c6..3571e4f 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -494,11 +494,17 @@ #define MIPS_CONF1_PC (_ULCAST_(1) << 4) #define MIPS_CONF1_MD (_ULCAST_(1) << 5) #define MIPS_CONF1_C2 (_ULCAST_(1) << 6) +#define MIPS_CONF1_DA_SHIFT 7 #define MIPS_CONF1_DA (_ULCAST_(7) << 7) +#define MIPS_CONF1_DL_SHIFT 10 #define MIPS_CONF1_DL (_ULCAST_(7) << 10) +#define MIPS_CONF1_DS_SHIFT 13 #define MIPS_CONF1_DS (_ULCAST_(7) << 13) +#define MIPS_CONF1_IA_SHIFT 16 #define MIPS_CONF1_IA (_ULCAST_(7) << 16) +#define MIPS_CONF1_IL_SHIFT 19 #define MIPS_CONF1_IL (_ULCAST_(7) << 19) +#define MIPS_CONF1_IS_SHIFT 22 #define MIPS_CONF1_IS (_ULCAST_(7) << 22) #define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) |