mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-08-17 15:38:51 +09:00
![Thomas Chou](/assets/img/avatar_default.png)
Convert cache flush to use dm cpu data. The original cache flush functions are written in assembly and use CONFIG_SYS_{I,D}CACHE_SIZE... macros. It is difficult to convert to use cache configuration in dm cpu data which is extracted from device tree. The cacheflush.c of Linux nios2 arch uses cpuinfo structure, which is very close to our dm cpu data. So we copy and modify it to arch/nios2/lib/cache.c to replace the old cache.S. Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
130 lines
2.9 KiB
C
130 lines
2.9 KiB
C
/*
|
|
* Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
|
|
* Copyright (C) 2009, Wind River Systems Inc
|
|
* Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/cache.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static void __flush_dcache(unsigned long start, unsigned long end)
|
|
{
|
|
unsigned long addr;
|
|
|
|
start &= ~(gd->arch.dcache_line_size - 1);
|
|
end += (gd->arch.dcache_line_size - 1);
|
|
end &= ~(gd->arch.dcache_line_size - 1);
|
|
|
|
for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
|
|
__asm__ __volatile__ (" flushda 0(%0)\n"
|
|
: /* Outputs */
|
|
: /* Inputs */ "r"(addr)
|
|
/* : No clobber */);
|
|
}
|
|
}
|
|
|
|
static void __flush_dcache_all(unsigned long start, unsigned long end)
|
|
{
|
|
unsigned long addr;
|
|
|
|
start &= ~(gd->arch.dcache_line_size - 1);
|
|
end += (gd->arch.dcache_line_size - 1);
|
|
end &= ~(gd->arch.dcache_line_size - 1);
|
|
|
|
if (end > start + gd->arch.dcache_size)
|
|
end = start + gd->arch.dcache_size;
|
|
|
|
for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
|
|
__asm__ __volatile__ (" flushd 0(%0)\n"
|
|
: /* Outputs */
|
|
: /* Inputs */ "r"(addr)
|
|
/* : No clobber */);
|
|
}
|
|
}
|
|
|
|
static void __invalidate_dcache(unsigned long start, unsigned long end)
|
|
{
|
|
unsigned long addr;
|
|
|
|
start &= ~(gd->arch.dcache_line_size - 1);
|
|
end += (gd->arch.dcache_line_size - 1);
|
|
end &= ~(gd->arch.dcache_line_size - 1);
|
|
|
|
for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
|
|
__asm__ __volatile__ (" initda 0(%0)\n"
|
|
: /* Outputs */
|
|
: /* Inputs */ "r"(addr)
|
|
/* : No clobber */);
|
|
}
|
|
}
|
|
|
|
static void __flush_icache(unsigned long start, unsigned long end)
|
|
{
|
|
unsigned long addr;
|
|
|
|
start &= ~(gd->arch.icache_line_size - 1);
|
|
end += (gd->arch.icache_line_size - 1);
|
|
end &= ~(gd->arch.icache_line_size - 1);
|
|
|
|
if (end > start + gd->arch.icache_size)
|
|
end = start + gd->arch.icache_size;
|
|
|
|
for (addr = start; addr < end; addr += gd->arch.icache_line_size) {
|
|
__asm__ __volatile__ (" flushi %0\n"
|
|
: /* Outputs */
|
|
: /* Inputs */ "r"(addr)
|
|
/* : No clobber */);
|
|
}
|
|
__asm__ __volatile(" flushp\n");
|
|
}
|
|
|
|
void flush_dcache_all(void)
|
|
{
|
|
__flush_dcache_all(0, gd->arch.dcache_size);
|
|
__flush_icache(0, gd->arch.icache_size);
|
|
}
|
|
|
|
void flush_dcache_range(unsigned long start, unsigned long end)
|
|
{
|
|
if (gd->arch.has_initda)
|
|
__flush_dcache(start, end);
|
|
else
|
|
__flush_dcache_all(start, end);
|
|
}
|
|
|
|
void flush_cache(unsigned long start, unsigned long size)
|
|
{
|
|
if (gd->arch.has_initda)
|
|
__flush_dcache(start, start + size);
|
|
else
|
|
__flush_dcache_all(start, start + size);
|
|
__flush_icache(start, start + size);
|
|
}
|
|
|
|
void invalidate_dcache_range(unsigned long start, unsigned long end)
|
|
{
|
|
if (gd->arch.has_initda)
|
|
__invalidate_dcache(start, end);
|
|
else
|
|
__flush_dcache_all(start, end);
|
|
}
|
|
|
|
int dcache_status(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
void dcache_enable(void)
|
|
{
|
|
flush_dcache_all();
|
|
}
|
|
|
|
void dcache_disable(void)
|
|
{
|
|
flush_dcache_all();
|
|
}
|