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