diff options
| -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 12f656cad..22bd844ea 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 28d5c4568..278865b6f 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 be7e5c65e..3571e4fdf 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) |