diff options
author | Paul Burton <paul.burton@imgtec.com> | 2016-05-27 14:28:06 +0100 |
---|---|---|
committer | Daniel Schwierzeck <daniel.schwierzeck@gmail.com> | 2016-05-31 09:44:24 +0200 |
commit | fb64cda579985e21610672eae44faf40eadd71ea (patch) | |
tree | cf09504ff3e799d5f2797c39d0bbfc1c49e18b1d /arch/mips/lib/cache.c | |
parent | 372286217f050bfd57695001d59f618c52822f40 (diff) |
MIPS: Abstract cache op loops with a macro
The various cache maintenance routines perform a number of loops over
cache lines. Rather than duplicate the code for performing such loops,
abstract it out into a new cache_loop macro which performs an arbitrary
number of cache ops on a range of addresses. This reduces duplication in
the existing L1 cache maintenance code & will allow for not adding
further duplication when introducing L2 cache support.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Diffstat (limited to 'arch/mips/lib/cache.c')
-rw-r--r-- | arch/mips/lib/cache.c | 59 |
1 files changed, 18 insertions, 41 deletions
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c index 19a42ff831..5f520c069f 100644 --- a/arch/mips/lib/cache.c +++ b/arch/mips/lib/cache.c @@ -37,82 +37,59 @@ static inline unsigned long dcache_line_size(void) return 2 << dl; } +#define cache_loop(start, end, lsize, ops...) do { \ + const void *addr = (const void *)(start & ~(lsize - 1)); \ + const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \ + const unsigned int cache_ops[] = { ops }; \ + unsigned int i; \ + \ + for (; addr <= aend; addr += lsize) { \ + for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \ + mips_cache(cache_ops[i], addr); \ + } \ +} while (0) + 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; - } + cache_loop(start_addr, start_addr + size, ilsize, + HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); return; } /* flush D-cache */ - while (1) { - mips_cache(HIT_WRITEBACK_INV_D, addr); - if (addr == aend) - break; - addr += dlsize; - } + cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); /* 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; - } + cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); } 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; - } + cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); } 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; - } + cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_I); } |