Message ID | 20200909200930.232174-6-seanga2@gmail.com |
---|---|
State | Superseded |
Delegated to: | Andes |
Headers | show |
Series | riscv: Clean up timer drivers | expand |
Hi Sean, On Thu, Sep 10, 2020 at 4:09 AM Sean Anderson <seanga2@gmail.com> wrote: > > This converts the clint driver from the riscv-specific interface to be a > DM-based UCLASS_TIMER driver. 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. > > Unlike with the Andes PLMT, the Sifive CLINT is also an IPI controller. > RISCV_SYSCON_CLINT is retained for this purpose. > > Signed-off-by: Sean Anderson <seanga2@gmail.com> > Reviewed-by: Pragnesh Patel <pragnesh.patel@openfive.com> > --- > This patch builds but has only been tested on the K210 and QEMU. It has NOT > been tested on a HiFive. > > Changes in v4: > - Use timer_timebase_fallback > > Changes in v3: > - Don't initialize the IPI in spl_invoke_opensbi. Further testing has > revealed it to be unnecessary. > > arch/riscv/Kconfig | 4 --- > arch/riscv/lib/sifive_clint.c | 66 +++++++++++++++++++---------------- > drivers/ram/sifive/Kconfig | 2 ++ > 3 files changed, 38 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..c9704c596f 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,36 @@ 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) > +{ > + dev->priv = dev_read_addr_ptr(dev); > + if (!dev->priv) > + return -EINVAL; > + > + return timer_timebase_fallback(dev); > +} > + > static const struct udevice_id sifive_clint_ids[] = { > - { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, > + { .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/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 This should be dropped. Please see the patch below: http://patchwork.ozlabs.org/project/uboot/patch/1600157107-57175-2-git-send-email-bmeng.cn@gmail.com/ > help > This enables DDR support for the platforms based on SiFive FU540 SoC. > -- Regards, Bin
On 9/15/20 4:09 AM, Bin Meng wrote: > Hi Sean, > > On Thu, Sep 10, 2020 at 4:09 AM Sean Anderson <seanga2@gmail.com> wrote: >> >> This converts the clint driver from the riscv-specific interface to be a >> DM-based UCLASS_TIMER driver. 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. >> >> Unlike with the Andes PLMT, the Sifive CLINT is also an IPI controller. >> RISCV_SYSCON_CLINT is retained for this purpose. >> >> Signed-off-by: Sean Anderson <seanga2@gmail.com> >> Reviewed-by: Pragnesh Patel <pragnesh.patel@openfive.com> >> --- >> This patch builds but has only been tested on the K210 and QEMU. It has NOT >> been tested on a HiFive. >> >> Changes in v4: >> - Use timer_timebase_fallback >> >> Changes in v3: >> - Don't initialize the IPI in spl_invoke_opensbi. Further testing has >> revealed it to be unnecessary. >> >> arch/riscv/Kconfig | 4 --- >> arch/riscv/lib/sifive_clint.c | 66 +++++++++++++++++++---------------- >> drivers/ram/sifive/Kconfig | 2 ++ >> 3 files changed, 38 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..c9704c596f 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,36 @@ 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) >> +{ >> + dev->priv = dev_read_addr_ptr(dev); >> + if (!dev->priv) >> + return -EINVAL; >> + >> + return timer_timebase_fallback(dev); >> +} >> + >> static const struct udevice_id sifive_clint_ids[] = { >> - { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, >> + { .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/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 > > This should be dropped. Please see the patch below: > http://patchwork.ozlabs.org/project/uboot/patch/1600157107-57175-2-git-send-email-bmeng.cn@gmail.com/ Ok, I can drop this and add a dependency. >> help >> This enables DDR support for the platforms based on SiFive FU540 SoC. >> -- > > Regards, > Bin >
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..c9704c596f 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,36 @@ 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) +{ + dev->priv = dev_read_addr_ptr(dev); + if (!dev->priv) + return -EINVAL; + + return timer_timebase_fallback(dev); +} + static const struct udevice_id sifive_clint_ids[] = { - { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, + { .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/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 help This enables DDR support for the platforms based on SiFive FU540 SoC.