On 8/20/20 3:43 AM, Bin Meng wrote: > On Wed, Jul 29, 2020 at 5:56 PM Sean Anderson <sean...@gmail.com> wrote: >> >> This converts the clint driver from the riscv-specific interface to be a >> DM-based UCLASS_TIMER driver. We also need to re-add the initialization for >> IPI back into the SPL code. This was previously implicitly done when the >> timer was initialized. In addition, the SiFive DDR driver previously >> implicitly depended on the CLINT to select REGMAP. >> >> Unlike Andes's PLMT/PLIC (which AFAIK never have anything pass it a dtb), >> the SiFive CLINT is part of the device tree passed in by qemu. This device >> tree doesn't have a clocks or clock-frequency property on clint, so we need >> to fall back on the timebase-frequency property. Perhaps in the future we >> can get a clock-frequency property added to the qemu dtb. >> >> Signed-off-by: Sean Anderson <sean...@gmail.com> >> --- >> This patch builds but has only been tested on the K210 and QEMU. It has NOT >> been tested on a HiFive. >> >> (no changes since v1) >> >> arch/riscv/Kconfig | 4 -- >> arch/riscv/lib/sifive_clint.c | 87 +++++++++++++++++++++++------------ >> common/spl/spl_opensbi.c | 5 ++ >> drivers/ram/sifive/Kconfig | 2 + >> 4 files changed, 64 insertions(+), 34 deletions(-) >> >> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig >> index d9155b9bab..aaa3b833a5 100644 >> --- a/arch/riscv/Kconfig >> +++ b/arch/riscv/Kconfig >> @@ -155,10 +155,6 @@ config 64BIT >> config SIFIVE_CLINT >> bool >> depends on RISCV_MMODE || SPL_RISCV_MMODE >> - select REGMAP >> - select SYSCON >> - select SPL_REGMAP if SPL >> - select SPL_SYSCON if SPL >> help >> The SiFive CLINT block holds memory-mapped control and status >> registers >> associated with software and timer interrupts. >> diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c >> index b9a2c649cc..3345a17ad2 100644 >> --- a/arch/riscv/lib/sifive_clint.c >> +++ b/arch/riscv/lib/sifive_clint.c >> @@ -8,9 +8,9 @@ >> */ >> >> #include <common.h> >> +#include <clk.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> >> @@ -24,35 +24,19 @@ >> >> DECLARE_GLOBAL_DATA_PTR; >> >> -int riscv_get_time(u64 *time) >> -{ >> - /* ensure timer register base has a sane value */ >> - riscv_init_ipi(); >> - >> - *time = readq((void __iomem *)MTIME_REG(gd->arch.clint)); >> - >> - return 0; >> -} >> - >> -int riscv_set_timecmp(int hart, u64 cmp) >> -{ >> - /* ensure timer register base has a sane value */ >> - riscv_init_ipi(); >> - >> - writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart)); >> - >> - return 0; >> -} >> - >> int riscv_init_ipi(void) >> { >> - if (!gd->arch.clint) { >> - long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT); >> + int ret; >> + struct udevice *dev; >> >> - if (IS_ERR(ret)) >> - return PTR_ERR(ret); >> - gd->arch.clint = ret; >> - } >> + ret = uclass_get_device_by_driver(UCLASS_TIMER, >> + DM_GET_DRIVER(sifive_clint), &dev); >> + if (ret) >> + return ret; >> + >> + gd->arch.clint = dev_read_addr_ptr(dev); >> + if (!gd->arch.clint) >> + return -EINVAL; >> >> return 0; >> } >> @@ -78,14 +62,57 @@ int riscv_get_ipi(int hart, int *pending) >> return 0; >> } >> >> +static int sifive_clint_get_count(struct udevice *dev, u64 *count) >> +{ >> + *count = readq((void __iomem *)MTIME_REG(dev->priv)); >> + >> + return 0; >> +} >> + >> +static const struct timer_ops sifive_clint_ops = { >> + .get_count = sifive_clint_get_count, >> +}; >> + >> +static int sifive_clint_probe(struct udevice *dev) >> +{ >> + int ret; >> + ofnode cpu; >> + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); >> + u32 rate; >> + >> + dev->priv = dev_read_addr_ptr(dev); >> + if (!dev->priv) >> + return -EINVAL; >> + >> + /* Did we get our clock rate from the device tree? */ >> + if (uc_priv->clock_rate) >> + return 0; >> + >> + /* Fall back to timebase-frequency */ >> + cpu = ofnode_path("/cpus"); >> + if (!ofnode_valid(cpu)) >> + return -EINVAL; >> + >> + ret = ofnode_read_u32(cpu, "timebase-frequency", &rate); >> + if (ret) >> + return ret; >> + >> + log_warning("missing clocks or clock-frequency property, falling >> back on timebase-frequency\n"); >> + uc_priv->clock_rate = rate; >> + >> + return 0; >> +} >> + >> static const struct udevice_id sifive_clint_ids[] = { >> - { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, > > RISCV_SYSCON_CLINT should be removed from syscon.h
This can't be removed because the IPI driver still depends on it. >> + { .compatible = "riscv,clint0" }, >> { } >> }; >> >> U_BOOT_DRIVER(sifive_clint) = { >> .name = "sifive_clint", >> - .id = UCLASS_SYSCON, >> + .id = UCLASS_TIMER, >> .of_match = sifive_clint_ids, >> + .probe = sifive_clint_probe, >> + .ops = &sifive_clint_ops, >> .flags = DM_FLAG_PRE_RELOC, >> }; >> diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c >> index 14f335f75f..3440bc0294 100644 >> --- a/common/spl/spl_opensbi.c >> +++ b/common/spl/spl_opensbi.c >> @@ -79,6 +79,11 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) >> invalidate_icache_all(); >> >> #ifdef CONFIG_SPL_SMP >> + /* Initialize the IPI before we use it */ >> + ret = riscv_init_ipi(); >> + if (ret) >> + hang(); > > Why above is needed? This is already called in arch_cpu_init_dm() in > arch/riscv/cpu/cpu.c I believe I ran into problems with it not getting called in SPL when testing. I can look into whether this is still needed. > >> + >> /* >> * Start OpenSBI on all secondary harts and wait for acknowledgment. >> * >> diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig >> index 6aca22ab2a..31ad0a7e45 100644 >> --- a/drivers/ram/sifive/Kconfig >> +++ b/drivers/ram/sifive/Kconfig >> @@ -9,5 +9,7 @@ config SIFIVE_FU540_DDR >> bool "SiFive FU540 DDR driver" >> depends on RAM_SIFIVE >> default y if TARGET_SIFIVE_FU540 >> + select REGMAP >> + select SPL_REGMAP if SPL > > I don't understand why this driver depends on REGMAP? I don't either, but it fails to build without these two lines. Previously, regmap was always enabled by the sifive clint. So now that it no longer enables regmap, this dependency became apparent. > >> help >> This enables DDR support for the platforms based on SiFive FU540 >> SoC. >> -- > > Regards, > Bin >