summaryrefslogtreecommitdiff
path: root/lib/utils/cache
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils/cache')
-rw-r--r--lib/utils/cache/fdt_cmo_helper.c114
-rw-r--r--lib/utils/cache/objects.mk1
2 files changed, 115 insertions, 0 deletions
diff --git a/lib/utils/cache/fdt_cmo_helper.c b/lib/utils/cache/fdt_cmo_helper.c
new file mode 100644
index 00000000..d87bab76
--- /dev/null
+++ b/lib/utils/cache/fdt_cmo_helper.c
@@ -0,0 +1,114 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi_utils/cache/fdt_cache.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+
+static unsigned long flc_offset;
+
+#define get_hart_flc(_s) \
+ sbi_scratch_read_type(_s, struct cache_device *, flc_offset)
+#define set_hart_flc(_s, _p) \
+ sbi_scratch_write_type(_s, struct cache_device *, flc_offset, _p)
+
+int fdt_cmo_private_flc_flush_all(void)
+{
+ struct cache_device *flc = get_hart_flc(sbi_scratch_thishart_ptr());
+
+ if (!flc || !flc->cpu_private)
+ return SBI_ENODEV;
+
+ return cache_flush_all(flc);
+}
+
+int fdt_cmo_llc_flush_all(void)
+{
+ struct cache_device *llc = get_hart_flc(sbi_scratch_thishart_ptr());
+
+ if (!llc)
+ return SBI_ENODEV;
+
+ while (llc->next)
+ llc = llc->next;
+
+ return cache_flush_all(llc);
+}
+
+static int fdt_cmo_cold_init(const void *fdt)
+{
+ struct sbi_scratch *scratch;
+ struct cache_device *dev;
+ int cpu_offset, cpus_offset, rc;
+ u32 hartid;
+
+ cpus_offset = fdt_path_offset(fdt, "/cpus");
+ if (cpus_offset < 0)
+ return SBI_EINVAL;
+
+ fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
+ rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
+ if (rc)
+ continue;
+
+ scratch = sbi_hartid_to_scratch(hartid);
+ if (!scratch)
+ continue;
+
+ rc = fdt_next_cache_get(fdt, cpu_offset, &dev);
+ if (rc && rc != SBI_ENOENT)
+ return rc;
+ if (rc == SBI_ENOENT)
+ dev = NULL;
+
+ set_hart_flc(scratch, dev);
+ }
+
+ return SBI_OK;
+}
+
+static int fdt_cmo_warm_init(void)
+{
+ struct cache_device *cur = get_hart_flc(sbi_scratch_thishart_ptr());
+ int rc;
+
+ while (cur) {
+ if (cur->ops && cur->ops->warm_init) {
+ rc = cur->ops->warm_init(cur);
+ if (rc)
+ return rc;
+ }
+
+ cur = cur->next;
+ }
+
+ return SBI_OK;
+}
+
+int fdt_cmo_init(bool cold_boot)
+{
+ const void *fdt = fdt_get_address();
+ int rc;
+
+ if (cold_boot) {
+ flc_offset = sbi_scratch_alloc_type_offset(struct cache_device *);
+ if (!flc_offset)
+ return SBI_ENOMEM;
+
+ rc = fdt_cmo_cold_init(fdt);
+ if (rc)
+ return rc;
+ }
+
+ rc = fdt_cmo_warm_init();
+ if (rc)
+ return rc;
+
+ return SBI_OK;
+}
diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk
index a343eb8c..6829a966 100644
--- a/lib/utils/cache/objects.mk
+++ b/lib/utils/cache/objects.mk
@@ -6,6 +6,7 @@
libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache.o
libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache_drivers.carray.o
+libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cmo_helper.o
carray-fdt_cache_drivers-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += fdt_sifive_ccache
libsbiutils-objs-$(CONFIG_FDT_CACHE_SIFIVE_CCACHE) += cache/fdt_sifive_ccache.o