[PATCH 2/2] sifive: ccache: add clear LIM area

Ben Dooks ben.dooks at codethink.co.uk
Fri Sep 8 15:37:07 CEST 2023


Add option to clear the LIM area on startup, just in case this
is the cause of some of the data-errors on startup.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
[ben.dooks at codethink.co.uk: changed from sifive.com address]
---
 drivers/cache/Kconfig               |  8 ++++++
 drivers/cache/cache-sifive-ccache.c | 40 +++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index abe7de9abf..9d5cbaedea 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -46,6 +46,14 @@ config SIFIVE_CCACHE
 	  This driver is for SiFive Composable L2/L3 cache. It enables cache
 	  ways of composable cache.
 
+config SIFIVE_CCACHE_LIMZERO
+	bool "Zero LIM (loosely integrated memory) on startup"
+	depends on SIFIVE_CCACHE
+	help
+	  Select this option to clear the LIM (cache memory) block before
+	  enabling the cache. This will increase the init time but may
+	  help with some of the errors being seen on OS startup.
+
 config SIFIVE_PL2CACHE
 	bool "SiFive per-core L2 cache"
 	select CACHE
diff --git a/drivers/cache/cache-sifive-ccache.c b/drivers/cache/cache-sifive-ccache.c
index 178bdcc82d..a84b5c9d04 100644
--- a/drivers/cache/cache-sifive-ccache.c
+++ b/drivers/cache/cache-sifive-ccache.c
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <asm/io.h>
 #include <dm/device.h>
+#include <dm/device_compat.h>
 #include <linux/bitfield.h>
 
 #define SIFIVE_CCACHE_CONFIG		0x000
@@ -43,6 +44,43 @@ static int sifive_ccache_get_info(struct udevice *dev, struct cache_info *info)
 	return 0;
 }
 
+#ifdef CONFIG_SIFIVE_CCACHE_LIMZERO
+static int sifive_clear_lim(struct udevice *dev)
+{
+
+	fdt_addr_t base, size;
+	ofnode mem_node;
+	u32 handle = 0;
+	int ret;
+
+	ret = ofnode_read_u32(dev_ofnode(dev), "memory-region", &handle);
+	if (ret) {
+		dev_err(dev, "no memory-region for lim\n");
+		return -EINVAL;
+	}
+
+	mem_node = ofnode_get_by_phandle(handle);
+	if (!ofnode_valid(mem_node)) {
+		dev_err(dev, "invalid memory region for lim\n");
+		return -EINVAL;
+	}
+
+	base = ofnode_get_addr_size_index(mem_node, 0, &size);
+
+	/* note, we assume this is called so early none of the ways of
+	 * the cache have been enabled, so just clear the entire cache
+	 * memory
+	 */
+
+	dev_info(dev, "clearing l3lim %llx..%llx\n", base, base+size);
+	memset((void *)base, 0x0, size);
+
+	return 0;
+}
+#else
+static inline int sifive_clear_lim(struct udevice *dev) { return 0; }
+#endif
+
 static const struct cache_ops sifive_ccache_ops = {
 	.enable = sifive_ccache_enable,
 	.get_info = sifive_ccache_get_info,
@@ -63,6 +101,8 @@ static int sifive_ccache_probe(struct udevice *dev)
 	(void)readl(base + 0x148);
 	(void)readl(base + 0x168);
 
+	sifive_clear_lim(dev);
+
 	return 0;
 }
 
-- 
2.40.1



More information about the U-Boot mailing list