summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom <support@vamrs.com>2021-01-07 21:54:51 +0300
committerEmil Renner Berthing <kernel@esmil.dk>2021-06-07 02:11:17 +0300
commit45f9d2bdcc6fc19bc923100e9dc524bab6246fea (patch)
treea1a8190210b2f54a4a392b5894defdaba978c885
parent057ab4512bfacf0fcd8c98ddbba140ff207009c4 (diff)
downloadlinux-45f9d2bdcc6fc19bc923100e9dc524bab6246fea.tar.xz
sifive/sifive_l2_cache: Add sifive_l2_flush64_range function
-rw-r--r--drivers/soc/sifive/Kconfig15
-rw-r--r--drivers/soc/sifive/sifive_l2_cache.c41
-rw-r--r--include/soc/sifive/sifive_l2_cache.h4
3 files changed, 59 insertions, 1 deletions
diff --git a/drivers/soc/sifive/Kconfig b/drivers/soc/sifive/Kconfig
index 58cf8c40d08d..4d0fdab56e81 100644
--- a/drivers/soc/sifive/Kconfig
+++ b/drivers/soc/sifive/Kconfig
@@ -7,4 +7,19 @@ config SIFIVE_L2
help
Support for the L2 cache controller on SiFive platforms.
+config SIFIVE_L2_FLUSH
+ bool "Support Level 2 Cache Controller Flush operation of SiFive Soc"
+
+if SIFIVE_L2_FLUSH
+
+config SIFIVE_L2_FLUSH_START
+ hex "Level 2 Cache Flush operation start"
+ default 0x80000000
+
+config SIFIVE_L2_FLUSH_SIZE
+ hex "Level 2 Cache Flush operation size"
+ default 0x800000000
+
+endif # SIFIVE_L2_FLUSH
+
endif
diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
index 59640a1d0b28..0b9e9e852ee4 100644
--- a/drivers/soc/sifive/sifive_l2_cache.c
+++ b/drivers/soc/sifive/sifive_l2_cache.c
@@ -29,13 +29,17 @@
#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
+#define SIFIVE_L2_FLUSH64 0x200
+
#define SIFIVE_L2_CONFIG 0x00
#define SIFIVE_L2_WAYENABLE 0x08
#define SIFIVE_L2_ECCINJECTERR 0x40
#define SIFIVE_L2_MAX_ECCINTR 4
-static void __iomem *l2_base;
+#define SIFIVE_L2_FLUSH64_LINE_LEN 64
+
+static void __iomem *l2_base = NULL;
static int g_irq[SIFIVE_L2_MAX_ECCINTR];
static struct riscv_cacheinfo_ops l2_cache_ops;
@@ -116,6 +120,41 @@ int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
+#ifdef CONFIG_SIFIVE_L2_FLUSH
+void sifive_l2_flush64_range(unsigned long start, unsigned long len)
+{
+ unsigned long line;
+
+ if(!l2_base) {
+ pr_warn("L2CACHE: base addr invalid, skipping flush\n");
+ return;
+ }
+
+ /* TODO: if (len == 0), skipping flush or going on? */
+ if(!len) {
+ pr_debug("L2CACHE: flush64 range @ 0x%lx(len:0)\n", start);
+ return;
+ }
+
+ /* make sure the address is in the range */
+ if(start < CONFIG_SIFIVE_L2_FLUSH_START ||
+ (start + len) > (CONFIG_SIFIVE_L2_FLUSH_START +
+ CONFIG_SIFIVE_L2_FLUSH_SIZE)) {
+ pr_warn("L2CACHE: flush64 out of range: %lx(%lx), skip flush\n",
+ start, len);
+ return;
+ }
+
+ mb(); /* sync */
+ for (line = start; line < start + len;
+ line += SIFIVE_L2_FLUSH64_LINE_LEN) {
+ writeq(line, l2_base + SIFIVE_L2_FLUSH64);
+ mb();
+ }
+}
+EXPORT_SYMBOL_GPL(sifive_l2_flush64_range);
+#endif
+
static int l2_largest_wayenabled(void)
{
return readl(l2_base + SIFIVE_L2_WAYENABLE) & 0xFF;
diff --git a/include/soc/sifive/sifive_l2_cache.h b/include/soc/sifive/sifive_l2_cache.h
index 92ade10ed67e..dd3e56787d31 100644
--- a/include/soc/sifive/sifive_l2_cache.h
+++ b/include/soc/sifive/sifive_l2_cache.h
@@ -7,6 +7,10 @@
#ifndef __SOC_SIFIVE_L2_CACHE_H
#define __SOC_SIFIVE_L2_CACHE_H
+#ifdef CONFIG_SIFIVE_L2_FLUSH
+extern void sifive_l2_flush64_range(unsigned long start, unsigned long len);
+#endif
+
extern int register_sifive_l2_error_notifier(struct notifier_block *nb);
extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);