[RFC v5.1 7/9] RISC-V: create a function based cache management interface

Conor Dooley conor at kernel.org
Tue Jan 3 13:03:59 PST 2023


From: Conor Dooley <conor.dooley at microchip.com>

The Zicbo* set of extensions for cache maintenance arrived too late &
several SoCs exist without them that require non-coherent DMA.
As things stand, the StarFive JH7100, Microchip PolarFire SoC & Renesas
RZ/Five all require cache maintenance and lack instructions for this
purpose.
Similar to the interface already used by the SiFive CCache driver to add
cacheinfo_ops, create an interface for registering cache management
functions for a given cache controller.

Signed-off-by: Conor Dooley <conor.dooley at microchip.com>
---
Yes, I made the cmo_patchfunc() __maybe_unused to escape LKP complaints.
The other option that Prabhakar mentioned was having explicit functions
for each of the operations, in which case I cmo_patchfunc() would go
away. I don't particularly like the name of that function, so any
suggestions there would be great!
---
 arch/riscv/Kconfig.erratas          |  4 ++++
 arch/riscv/include/asm/cacheflush.h | 19 +++++++++++++++++++
 arch/riscv/mm/dma-noncoherent.c     | 21 +++++++++++++++++++++
 3 files changed, 44 insertions(+)

diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
index f0f0c1abd52b..b8542e6e8f18 100644
--- a/arch/riscv/Kconfig.erratas
+++ b/arch/riscv/Kconfig.erratas
@@ -1,5 +1,8 @@
 menu "CPU errata selection"
 
+config ERRATA_CMO_FUNC
+	bool
+
 config ERRATA_ANDES
 	bool "Andes AX45MP errata"
 	depends on !XIP_KERNEL
@@ -14,6 +17,7 @@ config ERRATA_ANDES
 config ERRATA_ANDES_CMO
 	bool "Apply Andes cache management errata"
 	depends on ERRATA_ANDES && MMU && ARCH_R9A07G043
+	select ERRATA_CMO_FUNC
 	select RISCV_DMA_NONCOHERENT
 	default y
 	help
diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
index e22019668b9e..795205ec2028 100644
--- a/arch/riscv/include/asm/cacheflush.h
+++ b/arch/riscv/include/asm/cacheflush.h
@@ -62,6 +62,25 @@ void riscv_noncoherent_supported(void);
 static inline void riscv_noncoherent_supported(void) {}
 #endif
 
+struct riscv_cache_maint_ops {
+	void (*cmo_patchfunc) (unsigned int cache_size, void *vaddr,
+			       size_t size, int dir, int ops);
+};
+
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
+void riscv_set_cache_maint_ops(struct riscv_cache_maint_ops *ops);
+#else
+static void riscv_set_cache_maint_ops(struct riscv_cache_maint_ops *ops) {}
+#endif
+
+#ifdef CONFIG_ERRATA_CMO_FUNC
+asmlinkage void cmo_patchfunc(unsigned int cache_size, void *vaddr, size_t size,
+			      int dir, int ops);
+#else
+__maybe_unused static void cmo_patchfunc(unsigned int cache_size, void *vaddr,
+					 size_t size, int dir, int ops) {}
+#endif
+
 /*
  * Bits in sys_riscv_flush_icache()'s flags argument.
  */
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
index e2b82034f504..2f4f147ea0b9 100644
--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -83,3 +83,24 @@ void riscv_noncoherent_supported(void)
 	     "Non-coherent DMA support enabled without a block size\n");
 	noncoherent_supported = true;
 }
+
+static struct riscv_cache_maint_ops *rv_cache_maint_ops;
+static DEFINE_STATIC_KEY_FALSE(cmo_patchfunc_present);
+
+void riscv_set_cache_maint_ops(struct riscv_cache_maint_ops *ops)
+{
+	rv_cache_maint_ops = ops;
+	static_branch_enable(&cmo_patchfunc_present);
+}
+EXPORT_SYMBOL_GPL(riscv_set_cache_maint_ops);
+
+#ifdef CONFIG_ERRATA_CMO_FUNC
+asmlinkage void cmo_patchfunc(unsigned int cache_size, void *vaddr, size_t size,
+			      int dir, int ops)
+{
+	if (!static_branch_unlikely(&cmo_patchfunc_present))
+		return;
+
+	rv_cache_maint_ops->cmo_patchfunc(cache_size, vaddr, size, dir, ops);
+}
+#endif
-- 
2.39.0




More information about the linux-riscv mailing list