diff mbox series

[v3,02/12] lib: utils: Add FDT cache library

Message ID 20250708074940.10904-3-nick.hu@sifive.com
State Changes Requested
Headers show
Series Add SiFive TMC0 and SMC0 driver | expand

Commit Message

Nick Hu July 8, 2025, 7:49 a.m. UTC
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 <vincent.chen@sifive.com>
Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Co-developed-by: Andy Chiu <andy.chiu@sifive.com>
Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Signed-off-by: Nick Hu <nick.hu@sifive.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
---
 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

Comments

Anup Patel Aug. 4, 2025, 8:36 a.m. UTC | #1
On Tue, Jul 8, 2025 at 1:19 PM Nick Hu <nick.hu@sifive.com> wrote:
>
> 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 <vincent.chen@sifive.com>
> Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> Co-developed-by: Andy Chiu <andy.chiu@sifive.com>
> Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
> Signed-off-by: Nick Hu <nick.hu@sifive.com>
> Reviewed-by: Samuel Holland <samuel.holland@sifive.com>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup


> ---
>  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 <sbi_utils/cache/cache.h>
> +
> +/**
> + * 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..e1c6f67c
> --- /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 <libfdt.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_heap.h>
> +#include <sbi_utils/cache/fdt_cache.h>
> +#include <sbi_utils/fdt/fdt_driver.h>
> +
> +/* 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_OK;
> +
> +       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 c7a6531e..b5a7993d 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -7,6 +7,7 @@ CONFIG_PLATFORM_SOPHGO_SG2042=y
>  CONFIG_PLATFORM_STARFIVE_JH7110=y
>  CONFIG_PLATFORM_THEAD=y
>  CONFIG_PLATFORM_MIPS_P8700=y
> +CONFIG_FDT_CACHE=y
>  CONFIG_FDT_CPPC=y
>  CONFIG_FDT_CPPC_RPMI=y
>  CONFIG_FDT_GPIO=y
> --
> 2.17.1
>
diff mbox series

Patch

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 <sbi_utils/cache/cache.h>
+
+/**
+ * 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..e1c6f67c
--- /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 <libfdt.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi_utils/cache/fdt_cache.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+/* 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_OK;
+
+	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 c7a6531e..b5a7993d 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -7,6 +7,7 @@  CONFIG_PLATFORM_SOPHGO_SG2042=y
 CONFIG_PLATFORM_STARFIVE_JH7110=y
 CONFIG_PLATFORM_THEAD=y
 CONFIG_PLATFORM_MIPS_P8700=y
+CONFIG_FDT_CACHE=y
 CONFIG_FDT_CPPC=y
 CONFIG_FDT_CPPC_RPMI=y
 CONFIG_FDT_GPIO=y