mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-07-05 18:56:15 +09:00
![Paul Burton](/assets/img/avatar_default.png)
Move details of the L1 cache line sizes & total sizes into Kconfig, defaulting to 0. A new CONFIG_SYS_CACHE_SIZE_AUTO Kconfig entry is introduced to allow platforms to select auto-detection of cache sizes, and it defaults to being enabled if none of the cache sizes are set by the configuration (ie. sizes are all the default 0), and code is adjusted to #ifdef on that rather than on the definition of the sizes (which will always be defined even if 0). Signed-off-by: Paul Burton <paul.burton@imgtec.com>
127 lines
2.7 KiB
C
127 lines
2.7 KiB
C
/*
|
|
* (C) Copyright 2003
|
|
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/cacheops.h>
|
|
#include <asm/mipsregs.h>
|
|
|
|
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
|
|
|
|
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_SHF;
|
|
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_SHF;
|
|
if (!dl)
|
|
return 0;
|
|
return 2 << dl;
|
|
}
|
|
|
|
#endif /* !CONFIG_SYS_CACHELINE_SIZE */
|
|
|
|
void flush_cache(ulong start_addr, ulong size)
|
|
{
|
|
unsigned long ilsize = icache_line_size();
|
|
unsigned long dlsize = dcache_line_size();
|
|
const void *addr, *aend;
|
|
|
|
/* aend will be miscalculated when size is zero, so we return here */
|
|
if (size == 0)
|
|
return;
|
|
|
|
addr = (const void *)(start_addr & ~(dlsize - 1));
|
|
aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
|
|
|
|
if (ilsize == dlsize) {
|
|
/* flush I-cache & D-cache simultaneously */
|
|
while (1) {
|
|
mips_cache(HIT_WRITEBACK_INV_D, addr);
|
|
mips_cache(HIT_INVALIDATE_I, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += dlsize;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* flush D-cache */
|
|
while (1) {
|
|
mips_cache(HIT_WRITEBACK_INV_D, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += dlsize;
|
|
}
|
|
|
|
/* flush I-cache */
|
|
addr = (const void *)(start_addr & ~(ilsize - 1));
|
|
aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
|
|
while (1) {
|
|
mips_cache(HIT_INVALIDATE_I, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += ilsize;
|
|
}
|
|
}
|
|
|
|
void flush_dcache_range(ulong start_addr, ulong stop)
|
|
{
|
|
unsigned long lsize = dcache_line_size();
|
|
const void *addr = (const void *)(start_addr & ~(lsize - 1));
|
|
const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
|
|
|
|
/* aend will be miscalculated when size is zero, so we return here */
|
|
if (start_addr == stop)
|
|
return;
|
|
|
|
while (1) {
|
|
mips_cache(HIT_WRITEBACK_INV_D, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += lsize;
|
|
}
|
|
}
|
|
|
|
void invalidate_dcache_range(ulong start_addr, ulong stop)
|
|
{
|
|
unsigned long lsize = dcache_line_size();
|
|
const void *addr = (const void *)(start_addr & ~(lsize - 1));
|
|
const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
|
|
|
|
/* aend will be miscalculated when size is zero, so we return here */
|
|
if (start_addr == stop)
|
|
return;
|
|
|
|
while (1) {
|
|
mips_cache(HIT_INVALIDATE_D, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += lsize;
|
|
}
|
|
}
|