From ce4dc7649e5e1f7053d996f08c7da071b80b654f Mon Sep 17 00:00:00 2001 From: Nick Hu Date: Mon, 20 Oct 2025 14:34:06 +0800 Subject: 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 Reviewed-by: Samuel Holland Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20251020-cache-upstream-v7-4-69a132447d8a@sifive.com Signed-off-by: Anup Patel --- lib/utils/cache/fdt_cmo_helper.c | 114 +++++++++++++++++++++++++++++++++++++++ lib/utils/cache/objects.mk | 1 + 2 files changed, 115 insertions(+) create mode 100644 lib/utils/cache/fdt_cmo_helper.c (limited to 'lib/utils/cache') 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 +#include +#include +#include +#include +#include + +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 -- cgit v1.3.1