soc: sifive: ccache: Add flush feature 96/294596/1
authorHoegeun Kwon <hoegeun.kwon@samsung.com>
Thu, 8 Jun 2023 11:26:29 +0000 (20:26 +0900)
committerHoegeun Kwon <hoegeun.kwon@samsung.com>
Wed, 21 Jun 2023 07:27:23 +0000 (16:27 +0900)
Add the ccache flush feature applied to kernel v5.15.
This feature flushes the garbage cache when output the screen.

Change-Id: I855fd37416f028f6d7c9b9e1459462e4da7e1740
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
drivers/soc/sifive/Kconfig
drivers/soc/sifive/sifive_ccache.c
include/soc/sifive/sifive_ccache.h

index ed4c571..d37cfc6 100644 (file)
@@ -7,4 +7,20 @@ config SIFIVE_CCACHE
        help
          Support for the composable cache controller on SiFive platforms.
 
+config SIFIVE_FLUSH
+       bool "Support Level 2 Cache Controller Flush operation of SiFive Soc"
+
+if SIFIVE_FLUSH
+
+config SIFIVE_FLUSH_START
+       hex "Level 2 Cache Flush operation start"
+       default 0x80000000
+       default 0x40000000 if SOC_STARFIVE_JH7110
+
+config SIFIVE_FLUSH_SIZE
+       hex "Level 2 Cache Flush operation size"
+       default 0x800000000
+       default 0x400000000 if SOC_STARFIVE_JH7110
+
+endif # SIFIVE_FLUSH
 endif
index 3684f5b..79de317 100644 (file)
@@ -44,6 +44,9 @@
 
 #define SIFIVE_CCACHE_MAX_ECCINTR 4
 
+#define SIFIVE_FLUSH64 0x200
+#define SIFIVE_FLUSH64_LINE_LEN 64
+
 static void __iomem *ccache_base;
 static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR];
 static struct riscv_cacheinfo_ops ccache_cache_ops;
@@ -124,6 +127,42 @@ int unregister_sifive_ccache_error_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier);
 
+
+#ifdef CONFIG_SIFIVE_FLUSH
+void sifive_flush64_range(unsigned long start, unsigned long len)
+{
+       unsigned long line;
+
+       if(!ccache_base) {
+               pr_warn("CACHE: base addr invalid, skipping flush\n");
+               return;
+       }
+
+       /* TODO: if (len == 0), skipping flush or going on? */
+       if(!len) {
+               pr_debug("CACHE: flush64 range @ 0x%lx(len:0)\n", start);
+               return;
+       }
+
+       /* make sure the address is in the range */
+       if(start < CONFIG_SIFIVE_FLUSH_START ||
+          (start + len) > (CONFIG_SIFIVE_FLUSH_START +
+                            CONFIG_SIFIVE_FLUSH_SIZE)) {
+               pr_warn("CACHE: flush64 out of range: %lx(%lx), skip flush\n",
+                       start, len);
+               return;
+       }
+
+       mb();   /* sync */
+       for (line = start; line < start + len;
+            line += SIFIVE_FLUSH64_LINE_LEN) {
+               writeq(line, ccache_base + SIFIVE_FLUSH64);
+               mb();
+       }
+}
+EXPORT_SYMBOL_GPL(sifive_flush64_range);
+#endif
+
 static int ccache_largest_wayenabled(void)
 {
        return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF;
index 4d4ed49..e580a09 100644 (file)
@@ -13,4 +13,11 @@ extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb);
 #define SIFIVE_CCACHE_ERR_TYPE_CE 0
 #define SIFIVE_CCACHE_ERR_TYPE_UE 1
 
+#ifdef CONFIG_SIFIVE_FLUSH
+void sifive_flush64_range(unsigned long start, unsigned long len);
+
+#define starfive_flush_dcache(start, len) \
+       sifive_flush64_range(start, len)
+#endif
+
 #endif /* __SOC_SIFIVE_CCACHE_H */