From: Simon Glass <simon.glass@canonical.com> The RISC-V timer driver reads the clock rate from /cpus/timebase-frequency in U-Boot's own device tree. For EFI applications this property may not be present, since the embedded DTB is minimal. Add a fallback that reads the timebase frequency from the firmware- provided FDT, which is available via the EFI configuration tables. To support this, scan for EFI_FDT_GUID in scan_tables() and store the address via a new gd_set_firmware_fdt_addr() accessor. Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- drivers/timer/riscv_timer.c | 13 +++++++++++++ include/asm-generic/global_data.h | 8 ++++++++ lib/efi_client/efi_app.c | 3 +++ 3 files changed, 24 insertions(+) diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c index 1f4980ceb38..ca28d1297d7 100644 --- a/drivers/timer/riscv_timer.c +++ b/drivers/timer/riscv_timer.c @@ -15,8 +15,12 @@ #include <dm.h> #include <errno.h> #include <fdt_support.h> +#include <mapmem.h> #include <timer.h> #include <asm/csr.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; static u64 notrace riscv_timer_get_count(struct udevice *dev) { @@ -89,6 +93,15 @@ static int riscv_timer_probe(struct udevice *dev) "/cpus", "timebase-frequency", 0); } + /* For EFI apps, try the firmware-provided FDT */ + if (!rate && IS_ENABLED(CONFIG_EFI_APP) && + gd_firmware_fdt_addr()) { + void *fw_fdt = map_sysmem(gd_firmware_fdt_addr(), 0); + + rate = fdt_getprop_u32_default(fw_fdt, "/cpus", + "timebase-frequency", 0); + } + uc_priv->clock_rate = rate; /* With rate==0, timer uclass post_probe might later fail with -EINVAL. diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index b17a2e4650b..86204e372aa 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -563,6 +563,14 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #define gd_set_smbios_start(addr) #endif +#ifdef CONFIG_RISCV +#define gd_firmware_fdt_addr() gd->arch.firmware_fdt_addr +#define gd_set_firmware_fdt_addr(addr) gd->arch.firmware_fdt_addr = addr +#else +#define gd_firmware_fdt_addr() 0UL +#define gd_set_firmware_fdt_addr(addr) +#endif + #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) #define gd_multi_dtb_fit() gd->multi_dtb_fit #define gd_set_multi_dtb_fit(_dtb) gd->multi_dtb_fit = _dtb diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 178571d9970..d36ed959f95 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -172,6 +172,7 @@ static void scan_tables(struct efi_system_table *sys_table) efi_guid_t acpi = EFI_ACPI_TABLE_GUID; efi_guid_t smbios = SMBIOS_TABLE_GUID; efi_guid_t smbios3 = SMBIOS3_TABLE_GUID; + efi_guid_t fdt = EFI_FDT_GUID; uint i; for (i = 0; i < sys_table->nr_tables; i++) { @@ -182,6 +183,8 @@ static void scan_tables(struct efi_system_table *sys_table) else if (!memcmp(&tab->guid, &smbios, sizeof(efi_guid_t)) || !memcmp(&tab->guid, &smbios3, sizeof(efi_guid_t))) gd_set_smbios_start(map_to_sysmem(tab->table)); + else if (!memcmp(&tab->guid, &fdt, sizeof(efi_guid_t))) + gd_set_firmware_fdt_addr((ulong)tab->table); } } -- 2.43.0