blob: d87bab76ca0011a1b7802b24695ad58238ccb565 [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 SiFive Inc.
*/
#include <libfdt.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/cache/fdt_cache.h>
#include <sbi_utils/cache/fdt_cmo_helper.h>
#include <sbi_utils/fdt/fdt_helper.h>
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;
}