
On 7/8/20 1:02 AM, Bin Meng wrote:
From: Bin Meng bin.meng@windriver.com
This reverts commit 40686c394e533fec765fe237936e353c84e73fff.
Commit 40686c394e53 ("riscv: Clean up IPI initialization code") caused U-Boot failed to boot on SiFive HiFive Unleashed board.
The codes inside arch_cpu_init_dm() may call U-Boot timer APIs before the call to riscv_init_ipi(). At that time the timer register base (e.g.: the SiFive CLINT device in this case) is unknown yet.
In general, I don't think the existing implementation for timers on riscv (storage of base address in gd_t and initialization on first use) is necessary at all. riscv_timer_probe gets called before riscv_get_time gets called for the first time, and any initialization can be done there. In addition, there is already a way to select and initialize timers in the form of the /chosen/tick-timer property.
For example, the following (untested) patch converts the andestech timer to a uclass timer driver. It fails to link since riscv_get_time is no longer provided, but that function is only ever used by the riscv-timer driver.
--- arch/riscv/dts/ae350_32.dts | 2 ++ arch/riscv/dts/ae350_64.dts | 2 ++ arch/riscv/lib/andes_plmt.c | 51 +++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts index 3f8525fe56..f8f7ec8073 100644 --- a/arch/riscv/dts/ae350_32.dts +++ b/arch/riscv/dts/ae350_32.dts @@ -14,6 +14,7 @@ chosen { bootargs = "console=ttyS0,38400n8 debug loglevel=7"; stdout-path = "uart0:38400n8"; + tick-timer = "/soc/plmt0@e6000000"; };
cpus { @@ -162,6 +163,7 @@ &CPU2_intc 7 &CPU3_intc 7>; reg = <0xe6000000 0x100000>; + clock-frequency = <60000000>; }; };
diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts index 482c707503..f014f053aa 100644 --- a/arch/riscv/dts/ae350_64.dts +++ b/arch/riscv/dts/ae350_64.dts @@ -14,6 +14,7 @@ chosen { bootargs = "console=ttyS0,38400n8 debug loglevel=7"; stdout-path = "uart0:38400n8"; + tick-timer = "/soc/plmt0@e6000000"; };
cpus { @@ -162,6 +163,7 @@ &CPU2_intc 7 &CPU3_intc 7>; reg = <0x0 0xe6000000 0x0 0x100000>; + clock-frequency = <60000000>; }; };
diff --git a/arch/riscv/lib/andes_plmt.c b/arch/riscv/lib/andes_plmt.c index a7e90ca992..653fa55390 100644 --- a/arch/riscv/lib/andes_plmt.c +++ b/arch/riscv/lib/andes_plmt.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2019, Rick Chen rick@andestech.com + * Copyright (C) 2020, Sean Anderson seanga2@gmail.com * * U-Boot syscon driver for Andes's Platform Level Machine Timer (PLMT). * The PLMT block holds memory-mapped mtime register @@ -9,46 +10,52 @@
#include <common.h> #include <dm.h> -#include <regmap.h> -#include <syscon.h> +#include <timer.h> #include <asm/io.h> -#include <asm/syscon.h> #include <linux/err.h>
/* mtime register */ #define MTIME_REG(base) ((ulong)(base))
-DECLARE_GLOBAL_DATA_PTR; - -#define PLMT_BASE_GET(void) \ - do { \ - long *ret; \ - \ - if (!gd->arch.plmt) { \ - ret = syscon_get_first_range(RISCV_SYSCON_PLMT); \ - if (IS_ERR(ret)) \ - return PTR_ERR(ret); \ - gd->arch.plmt = ret; \ - } \ - } while (0) - -int riscv_get_time(u64 *time) +static int andes_plmt_get_count(struct udevice* dev, u64 *count) { - PLMT_BASE_GET(); + *count = readq((void __iomem *)MTIME_REG(dev->priv));
- *time = readq((void __iomem *)MTIME_REG(gd->arch.plmt)); + return 0; +} + +static const struct timer_ops andes_plmt_ops = { + .get_count = andes_plmt_get_count, +}; + +static int andes_plmt_probe(struct udevice *dev) +{ + int ret; + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + u32 clock_rate; + + dev->priv = dev_read_addr_ptr(dev); + if (!dev->priv) + return -EINVAL; + + ret = dev_read_u32(dev, "clock-frequency", &clock_rate); + if (ret) + return ret; + uc_priv->clock_rate = clock_rate;
return 0; }
static const struct udevice_id andes_plmt_ids[] = { - { .compatible = "riscv,plmt0", .data = RISCV_SYSCON_PLMT }, + { .compatible = "riscv,plmt0" }, { } };
U_BOOT_DRIVER(andes_plmt) = { .name = "andes_plmt", - .id = UCLASS_SYSCON, + .id = UCLASS_TIMER, .of_match = andes_plmt_ids, + .ops = &andes_plmt_ops, + .probe = andes_plmt_probe, .flags = DM_FLAG_PRE_RELOC, };