
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@codethink.co.uk [ben.dooks@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; }