From: Torsten Duwe Date: Mon, 14 Aug 2023 16:05:28 +0000 (+0200) Subject: riscv: allow riscv timer to be instantiated via device tree X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=f39f8f77a5268530e982aa38e921c640d532a9ae;p=u-boot.git riscv: allow riscv timer to be instantiated via device tree For the architectural timer on riscv, there already is a defined device tree binding[1]. Allow timer instances to be created from device tree matches, but for now retain the old mechanism, which registers the timer biggy-back with the CPU. [1] linux/Documentation/devicetree/bindings/timer/riscv,timer.yaml Signed-off-by: Torsten Duwe Reviewed-by: Leo Yu-Chi Liang --- diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c index 3627ed79b8..28a6a6870b 100644 --- a/drivers/timer/riscv_timer.c +++ b/drivers/timer/riscv_timer.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -53,9 +54,26 @@ u64 notrace timer_early_get_count(void) static int riscv_timer_probe(struct udevice *dev) { struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + u32 rate; - /* clock frequency was passed from the cpu driver as driver data */ - uc_priv->clock_rate = dev->driver_data; + /* When this function was called from the CPU driver, clock + * frequency is passed as driver data. + */ + rate = dev->driver_data; + + /* When called from an FDT match, the rate needs to be looked up. */ + if (!rate && gd->fdt_blob) { + rate = fdt_getprop_u32_default(gd->fdt_blob, + "/cpus", "timebase-frequency", 0); + } + + uc_priv->clock_rate = rate; + + /* With rate==0, timer uclass post_probe might later fail with -EINVAL. + * Give a hint at the cause for debugging. + */ + if (!rate) + log_err("riscv_timer_probe with invalid clock rate 0!\n"); return 0; } @@ -64,9 +82,15 @@ static const struct timer_ops riscv_timer_ops = { .get_count = riscv_timer_get_count, }; +static const struct udevice_id riscv_timer_ids[] = { + { .compatible = "riscv,timer", }, + { } +}; + U_BOOT_DRIVER(riscv_timer) = { .name = "riscv_timer", .id = UCLASS_TIMER, + .of_match = of_match_ptr(riscv_timer_ids), .probe = riscv_timer_probe, .ops = &riscv_timer_ops, .flags = DM_FLAG_PRE_RELOC,