summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Hu <[email protected]>2025-10-20 14:34:06 +0800
committerAnup Patel <[email protected]>2025-10-28 11:27:53 +0530
commitce4dc7649e5e1f7053d996f08c7da071b80b654f (patch)
tree1a4dee5574d2ba86b26c27b70c4e9ba8a94381e7
parent8ea972838cf3f398b1a2896e645c8c2fb23e2159 (diff)
lib: utils/cache: Add fdt cmo helpers
Add the helpers to build up the cache hierarchy via FDT and provide some cmo functions for the user who want to flush the entire cache. Signed-off-by: Nick Hu <[email protected]> Reviewed-by: Samuel Holland <[email protected]> Reviewed-by: Anup Patel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
-rw-r--r--include/sbi_utils/cache/fdt_cmo_helper.h40
-rw-r--r--lib/utils/cache/fdt_cmo_helper.c114
-rw-r--r--lib/utils/cache/objects.mk1
-rw-r--r--platform/generic/platform.c3
4 files changed, 157 insertions, 1 deletions
diff --git a/include/sbi_utils/cache/fdt_cmo_helper.h b/include/sbi_utils/cache/fdt_cmo_helper.h
new file mode 100644
index 00000000..a6a28db9
--- /dev/null
+++ b/include/sbi_utils/cache/fdt_cmo_helper.h
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SiFive Inc.
+ */
+
+#ifndef __FDT_CMO_HELPER_H__
+#define __FDT_CMO_HELPER_H__
+
+#ifdef CONFIG_FDT_CACHE
+/**
+ * Flush the private first level cache of the current hart
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_private_flc_flush_all(void);
+
+/**
+ * Flush the last level cache of the current hart
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_llc_flush_all(void);
+
+/**
+ * Initialize the cache devices for each hart
+ *
+ * @param fdt devicetree blob
+ * @param cold_boot cold init or warm init
+ *
+ * @return 0 on success, or a negative error code on failure
+ */
+int fdt_cmo_init(bool cold_boot);
+
+#else
+
+static inline int fdt_cmo_init(bool cold_boot) { return 0; }
+
+#endif /* CONFIG_FDT_CACHE */
+#endif /* __FDT_CMO_HELPER_H__ */
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
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 91140958..e66f99fa 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -17,6 +17,7 @@
#include <sbi/sbi_string.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_tlb.h>
+#include <sbi_utils/cache/fdt_cmo_helper.h>
#include <sbi_utils/fdt/fdt_domain.h>
#include <sbi_utils/fdt/fdt_driver.h>
#include <sbi_utils/fdt/fdt_fixup.h>
@@ -230,7 +231,7 @@ int generic_early_init(bool cold_boot)
fdt_driver_init_all(fdt, fdt_early_drivers);
}
- return 0;
+ return fdt_cmo_init(cold_boot);
}
int generic_final_init(bool cold_boot)