From d6b684ec8695fc4f4211670f6c45d54d882af3fb Mon Sep 17 00:00:00 2001 From: Nick Hu Date: Mon, 20 Oct 2025 14:34:04 +0800 Subject: [PATCH] lib: utils: Add FDT cache library Add the FDT cache library so we can build up the cache topology via the 'next-level-cache' DT property. Co-developed-by: Vincent Chen Signed-off-by: Vincent Chen Co-developed-by: Andy Chiu Signed-off-by: Andy Chiu Signed-off-by: Nick Hu Reviewed-by: Samuel Holland Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20251020-cache-upstream-v7-2-69a132447d8a@sifive.com Signed-off-by: Anup Patel --- include/sbi_utils/cache/fdt_cache.h | 34 +++++++++ lib/utils/cache/Kconfig | 6 ++ lib/utils/cache/fdt_cache.c | 87 ++++++++++++++++++++++++ lib/utils/cache/fdt_cache_drivers.carray | 3 + lib/utils/cache/objects.mk | 3 + platform/generic/configs/defconfig | 1 + 6 files changed, 134 insertions(+) create mode 100644 include/sbi_utils/cache/fdt_cache.h create mode 100644 lib/utils/cache/fdt_cache.c create mode 100644 lib/utils/cache/fdt_cache_drivers.carray diff --git a/include/sbi_utils/cache/fdt_cache.h b/include/sbi_utils/cache/fdt_cache.h new file mode 100644 index 00000000..b377d6f5 --- /dev/null +++ b/include/sbi_utils/cache/fdt_cache.h @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 SiFive Inc. + */ + +#ifndef __FDT_CACHE_H__ +#define __FDT_CACHE_H__ + +#include + +/** + * Register a cache device using information from the DT + * + * @param fdt devicetree blob + * @param noff offset of a node in the devicetree blob + * @param dev cache device to register for this devicetree node + * + * @return 0 on success, or a negative error code on failure + */ +int fdt_cache_add(const void *fdt, int noff, struct cache_device *dev); + +/** + * Get the cache device referencd by the "next-level-cache" property of a DT node + * + * @param fdt devicetree blob + * @param noff offset of a node in the devicetree blob + * @param out_dev location to return the cache device + * + * @return 0 on success, or a negative error code on failure + */ +int fdt_next_cache_get(const void *fdt, int noff, struct cache_device **out_dev); + +#endif diff --git a/lib/utils/cache/Kconfig b/lib/utils/cache/Kconfig index 24aa41bc..10602176 100644 --- a/lib/utils/cache/Kconfig +++ b/lib/utils/cache/Kconfig @@ -2,6 +2,12 @@ menu "Cache Support" +config FDT_CACHE + bool "FDT based cache drivers" + depends on FDT + select CACHE + default n + config CACHE bool "Cache support" default n diff --git a/lib/utils/cache/fdt_cache.c b/lib/utils/cache/fdt_cache.c new file mode 100644 index 00000000..aeaa6138 --- /dev/null +++ b/lib/utils/cache/fdt_cache.c @@ -0,0 +1,87 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 SiFive Inc. + */ + +#include +#include +#include +#include +#include +#include + +/* List of FDT cache drivers generated at compile time */ +extern const struct fdt_driver *const fdt_cache_drivers[]; + +int fdt_cache_add(const void *fdt, int noff, struct cache_device *dev) +{ + int rc; + + dev->id = noff; + sbi_strncpy(dev->name, fdt_get_name(fdt, noff, NULL), sizeof(dev->name) - 1); + sbi_dprintf("%s: %s\n", __func__, dev->name); + + rc = fdt_next_cache_get(fdt, noff, &dev->next); + if (rc) + return rc; + + return cache_add(dev); +} + +static int fdt_cache_add_generic(const void *fdt, int noff) +{ + struct cache_device *dev; + int rc; + + dev = sbi_zalloc(sizeof(*dev)); + if (!dev) + return SBI_ENOMEM; + + rc = fdt_cache_add(fdt, noff, dev); + if (rc) { + sbi_free(dev); + return rc; + } + + return 0; +} + +static int fdt_cache_find(const void *fdt, int noff, struct cache_device **out_dev) +{ + struct cache_device *dev = cache_find(noff); + int rc; + + if (!dev) { + rc = fdt_driver_init_by_offset(fdt, noff, fdt_cache_drivers); + if (rc == SBI_ENODEV) + rc = fdt_cache_add_generic(fdt, noff); + if (rc) + return rc; + + dev = cache_find(noff); + if (!dev) + return SBI_EFAIL; + } + + if (out_dev) + *out_dev = dev; + + return SBI_OK; +} + +int fdt_next_cache_get(const void *fdt, int noff, struct cache_device **out_dev) +{ + const fdt32_t *val; + int len; + + val = fdt_getprop(fdt, noff, "next-level-cache", &len); + if (!val || len < sizeof(*val)) + return SBI_ENOENT; + + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(val[0])); + if (noff < 0) + return noff; + + return fdt_cache_find(fdt, noff, out_dev); +} diff --git a/lib/utils/cache/fdt_cache_drivers.carray b/lib/utils/cache/fdt_cache_drivers.carray new file mode 100644 index 00000000..c1b1791c --- /dev/null +++ b/lib/utils/cache/fdt_cache_drivers.carray @@ -0,0 +1,3 @@ +HEADER: sbi_utils/cache/fdt_cache.h +TYPE: const struct fdt_driver +NAME: fdt_cache_drivers diff --git a/lib/utils/cache/objects.mk b/lib/utils/cache/objects.mk index 21d30ce8..2fcf9666 100644 --- a/lib/utils/cache/objects.mk +++ b/lib/utils/cache/objects.mk @@ -4,4 +4,7 @@ # Copyright (c) 2025 SiFive # +libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache.o +libsbiutils-objs-$(CONFIG_FDT_CACHE) += cache/fdt_cache_drivers.carray.o + libsbiutils-objs-$(CONFIG_CACHE) += cache/cache.o diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig index 05b9ea2d..6aa51f56 100644 --- a/platform/generic/configs/defconfig +++ b/platform/generic/configs/defconfig @@ -10,6 +10,7 @@ CONFIG_PLATFORM_STARFIVE_JH7110=y CONFIG_PLATFORM_THEAD=y CONFIG_PLATFORM_MIPS_P8700=y CONFIG_PLATFORM_SPACEMIT_K1=y +CONFIG_FDT_CACHE=y CONFIG_FDT_CPPC=y CONFIG_FDT_CPPC_RPMI=y CONFIG_FDT_GPIO=y