mips32: detect L1 cache sizes if they're not defined

For boards such as the MIPS Malta with an FPGA core card it is desirable
to be able to detect the L1 cache sizes at runtime, since they are not
dependant upon the board but on the FPGA bitstream in use. This patch
performs that detection when the CONFIG_SYS_[DI]CACHE_SIZE macros are
not defined by the board configuration. In cases where the sizes are
detected this patch also removes the restriction that the I-cache &
D-cache line sizes must be the same, as this is not necessarily true.

If the cache sizes are defined by a configuration then they will be
hardcoded as before, so this patch will not add overhead to such
boards.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
This commit is contained in:
Paul Burton 2013-11-08 11:18:42 +00:00 committed by Daniel Schwierzeck
parent 15c5cdf5aa
commit fa476f75bf
3 changed files with 150 additions and 19 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)