summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@mips.com>2017-11-21 11:18:37 -0800
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>2017-11-28 21:59:30 +0100
commit219c2db384ffc4877c52bd58e7b55a62b663fed2 (patch)
tree3b78a0b912f65f5c8f096934e811633dc97d1d7a /arch
parentc5bf161facd5c10348c7e3963af6bd1cc9a79167 (diff)
MIPS: Ensure cache ops complete in cache maintenance functions
A typical use of cache maintenance functions is to force writeback of data which a device is about to read using DMA - for example a descriptor or command structure. Such users of cache maintenance functions require that operations on the cache have completed before they proceed to instruct a device to read memory. This requires that we place a completion barrier (ie. sync instruction) between the cache ops and whatever write informs the device to perform DMA. Whilst strictly speaking this isn't all users of the cache maintenance functions & we could instead place the barriers in the drivers that require them, it would be much more invasive to do so than to just have the barrier be the default by placing it in the cache functions themselves. The cost is low enough that it shouldn't matter to us in any rare cases that we use the cache functions when not performing DMA. Signed-off-by: Paul Burton <paul.burton@mips.com> Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> Cc: u-boot@lists.denx.de
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/lib/cache.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c
index 91b037f87d..eba7fff316 100644
--- a/arch/mips/lib/cache.c
+++ b/arch/mips/lib/cache.c
@@ -10,6 +10,7 @@
#ifdef CONFIG_MIPS_L2_CACHE
#include <asm/cm.h>
#endif
+#include <asm/io.h>
#include <asm/mipsregs.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -116,7 +117,7 @@ void flush_cache(ulong start_addr, ulong size)
/* flush I-cache & D-cache simultaneously */
cache_loop(start_addr, start_addr + size, ilsize,
HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
- return;
+ goto ops_done;
}
/* flush D-cache */
@@ -129,6 +130,10 @@ void flush_cache(ulong start_addr, ulong size)
/* flush I-cache */
cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
+
+ops_done:
+ /* ensure cache ops complete before any further memory accesses */
+ sync();
}
void flush_dcache_range(ulong start_addr, ulong stop)
@@ -145,6 +150,9 @@ void flush_dcache_range(ulong start_addr, ulong stop)
/* flush L2 cache */
if (slsize)
cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
+
+ /* ensure cache ops complete before any further memory accesses */
+ sync();
}
void invalidate_dcache_range(ulong start_addr, ulong stop)
@@ -161,4 +169,7 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D);
+
+ /* ensure cache ops complete before any further memory accesses */
+ sync();
}