/* * 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); }