aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Zi <ziyao@disroot.org>2025-05-16 13:33:53 +0000
committerAnup Patel <anup@brainfault.org>2025-05-20 13:25:53 +0530
commit60c3f97de840e6ad35494f9228fc83600d1dc5a2 (patch)
tree1f7a47b4742a5acf322c9da476193630b7236e0c
parent7e31dc80525f752d97c2c5a97eb4b9583054e8bc (diff)
downloadopensbi-60c3f97de840e6ad35494f9228fc83600d1dc5a2.zip
opensbi-60c3f97de840e6ad35494f9228fc83600d1dc5a2.tar.gz
opensbi-60c3f97de840e6ad35494f9228fc83600d1dc5a2.tar.bz2
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>
-rw-r--r--lib/utils/fdt/fdt_fixup.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index e237dd0..f3fe8af 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -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");
+ }
}
}