]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
arch: armv8: Provide a way to disable cache maintenance ops
authorVignesh Raghavendra <vigneshr@ti.com>
Mon, 22 Apr 2019 16:13:32 +0000 (21:43 +0530)
committerTom Rini <trini@konsulko.com>
Sun, 5 May 2019 12:48:50 +0000 (08:48 -0400)
On AM654 SoC(arm64) which is IO coherent and has L3 Cache, cache
maintenance operations being done to support non-coherent platforms
causes issues.

For example, here is how U-Boot prepares/handles a buffer to receive
data from a device (DMA Write). This may vary slightly depending on the
driver framework:

Start DMA to write to destination buffer
Wait for DMA to be done (dma_receive()/dma_memcpy())
Invalidate destination buffer (invalidate_dcache_range())
Read from destination buffer

The invalidate after the DMA is needed in order to read latest data from
memory that’s updated by DMA write. Also, in case random prefetch has
pulled in buffer data during the “wait for DMA” before the DMA has
written to it. This works well for non-coherent architectures.

In case of coherent architecture with L3 cache, DMA write would directly
update L3 cache contents (assuming cacheline is present in L3) without
updating the DDR memory. So invalidate after “wait for DMA” in above
sequence would discard latest data and read will cause stale data to be
fetched from DDR. Therefore invalidate after “wait for DMA” is not
always correct on coherent architecture.

Therefore, provide a Kconfig option to disable cache maintenance ops on
coherent architectures. This has added benefit of improving the
performance of DMA transfers as we no longer need to invalidate/flush
individual cache lines(especially for buffer thats several KBs in size).

In order to facilitate use of same Kconfig across different
architecture, I have added the symbol to top level arch/Kconfig file.
Patch currently disables cache maintenance ops for arm64 only.
flush_dcache_all() and invalidate_dcache_all() are exclusively used
during enabling/disabling dcache and hence are not disabled.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
arch/Kconfig
arch/arm/cpu/armv8/cache_v8.c

index 2f3d07c13a1817a205f81e7a9792be2c91e75647..760023b19a817e45490058ea5de8ecc5d0633a72 100644 (file)
@@ -227,6 +227,15 @@ config SYS_CONFIG_NAME
          The header file include/configs/<CONFIG_SYS_CONFIG_NAME>.h
          should be included from include/config.h.
 
+config SYS_DISABLE_DCACHE_OPS
+       bool
+       help
+        This option disables dcache flush and dcache invalidation
+        operations. For example, on coherent systems where cache
+        operatios are not required, enable this option to avoid them.
+        Note that, its up to the individual architectures to implement
+        this functionality.
+
 source "arch/arc/Kconfig"
 source "arch/arm/Kconfig"
 source "arch/m68k/Kconfig"
index 038405173eb13493659a58508c2a69639013d359..9ca397e73c9b9776ac9ad9ec172dd94ed5ff11a5 100644 (file)
@@ -443,6 +443,7 @@ inline void flush_dcache_all(void)
                debug("flushing dcache successfully.\n");
 }
 
+#ifndef CONFIG_SYS_DISABLE_DCACHE_OPS
 /*
  * Invalidates range in all levels of D-cache/unified cache
  */
@@ -458,6 +459,15 @@ void flush_dcache_range(unsigned long start, unsigned long stop)
 {
        __asm_flush_dcache_range(start, stop);
 }
+#else
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+#endif /* CONFIG_SYS_DISABLE_DCACHE_OPS */
 
 void dcache_enable(void)
 {