lib: utils: fdt: Claim Zicntr if time CSR emulation is possible

OpenSBI is capable of emulating time CSR through an external timer
for HARTs that don't implement a full Zicntr extension. Let's add
Zicntr extension in the FDT if CSR emulation is active.

This avoids hardcoding the extension in the devicetree, which may
confuse pre-SBI bootloaders.

Signed-off-by: Yao Zi <ziyao@disroot.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250516133352.36617-4-ziyao@disroot.org
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Yao Zi
2025-05-16 13:33:53 +00:00
committed by Anup Patel
parent 7e31dc8052
commit 60c3f97de8

View File

@@ -16,6 +16,7 @@
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_timer.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/fdt/fdt_pmu.h>
#include <sbi_utils/fdt/fdt_helper.h>
@@ -107,10 +108,21 @@ int fdt_add_cpu_idle_states(void *fdt, const struct sbi_cpu_idle_state *state)
void fdt_cpu_fixup(void *fdt)
{
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
struct sbi_domain *dom = sbi_domain_thishart_ptr();
int err, cpu_offset, cpus_offset, len;
const char *mmu_type;
const char *mmu_type, *extensions;
u32 hartid, hartindex;
bool emulated_zicntr;
/*
* Claim Zicntr extension in riscv,isa-extensions if
* 1. OpenSBI can emulate time CSR with a timer
* 2. The other two CSRs specified by Zicntr are available
*/
emulated_zicntr = sbi_timer_get_device() != NULL &&
sbi_hart_has_csr(scratch, SBI_HART_CSR_CYCLE) &&
sbi_hart_has_csr(scratch, SBI_HART_CSR_INSTRET);
err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
if (err < 0)
@@ -140,6 +152,25 @@ void fdt_cpu_fixup(void *fdt)
!mmu_type || !len)
fdt_setprop_string(fdt, cpu_offset, "status",
"disabled");
if (!emulated_zicntr)
continue;
extensions = fdt_getprop(fdt, cpu_offset,
"riscv,isa-extensions", &len);
/*
* For legacy devicetrees, don't create riscv,isa-extensions
* property if there hasn't been already one.
*/
if (extensions &&
!fdt_stringlist_contains(extensions, len, "zicntr")) {
err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 16);
if (err)
continue;
fdt_appendprop_string(fdt, cpu_offset,
"riscv,isa-extensions", "zicntr");
}
}
}