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