diff options
author | Stefano Babic <sbabic@denx.de> | 2015-10-30 14:52:51 +0100 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2015-10-30 14:52:51 +0100 |
commit | e573bdb324c78fac56655a493bea843842c9d9f8 (patch) | |
tree | 3933d354a6be71cbe66d583fec3f5b2479e596ee /arch/nios2/lib/cache.c | |
parent | a69fdc7787bfa2f27eed74c2ee58c28ce932d502 (diff) | |
parent | 0eb4cf9c14315e1976a116de75da6f420ac0e8dd (diff) |
Merge branch 'master' of git://git.denx.de/u-boot
Diffstat (limited to 'arch/nios2/lib/cache.c')
-rw-r--r-- | arch/nios2/lib/cache.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/arch/nios2/lib/cache.c b/arch/nios2/lib/cache.c new file mode 100644 index 00000000000..7c74e1adfed --- /dev/null +++ b/arch/nios2/lib/cache.c @@ -0,0 +1,129 @@ +/* + * 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(); +} |