Reviewed-by: Angelo Dureghello <[email protected]> On 1/5/26 17:52, Kuan-Wei Chiu wrote: > Add support for the Goldfish timer driver. This driver utilizes the > Goldfish RTC hardware to provide a nanosecond-resolution timer. This > virtual device is commonly found in QEMU virtual machines (such as the > m68k virt machine) and Android emulators. > > The driver implements the standard U-Boot timer UCLASS interface, > exposing a 64-bit monotonically increasing counter with a 1GHz clock > rate derived from the RTC registers. > > Signed-off-by: Kuan-Wei Chiu <[email protected]> > Tested-by: Daniel Palmer <[email protected]> > Reviewed-by: Yao Zi <[email protected]> > --- > Changes in v5: > - Rebase on u-boot/next branch. > > MAINTAINERS | 6 +++ > drivers/timer/Kconfig | 8 ++++ > drivers/timer/Makefile | 1 + > drivers/timer/goldfish_timer.c | 81 ++++++++++++++++++++++++++++++++++ > include/goldfish_timer.h | 13 ++++++ > 5 files changed, 109 insertions(+) > create mode 100644 drivers/timer/goldfish_timer.c > create mode 100644 include/goldfish_timer.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 8f884ff495a..efecb213be7 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -1266,6 +1266,12 @@ S: Maintained > F: drivers/serial/serial_goldfish.c > F: include/goldfish_tty.h > > +GOLDFISH TIMER DRIVER > +M: Kuan-Wei Chiu <[email protected]> > +S: Maintained > +F: drivers/timer/goldfish_timer.c > +F: include/goldfish_timer.h > + > INTERCONNECT: > M: Neil Armstrong <[email protected]> > S: Maintained > diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig > index f9511503b02..a84a0dc0539 100644 > --- a/drivers/timer/Kconfig > +++ b/drivers/timer/Kconfig > @@ -340,4 +340,12 @@ config STARFIVE_TIMER > Select this to enable support for the timer found on > Starfive SoC. > > +config GOLDFISH_TIMER > + bool "Goldfish Timer support" > + depends on TIMER > + help > + Select this to enable support for the Goldfish Timer. > + It uses the Goldfish RTC hardware to provide a nanosecond-resolution > + timer, commonly found in QEMU virt machines. > + > endmenu > diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile > index a72e411fb2f..d8b3f2b65d4 100644 > --- a/drivers/timer/Makefile > +++ b/drivers/timer/Makefile > @@ -36,3 +36,4 @@ obj-$(CONFIG_MCHP_PIT64B_TIMER) += mchp-pit64b-timer.o > obj-$(CONFIG_IMX_GPT_TIMER) += imx-gpt-timer.o > obj-$(CONFIG_XILINX_TIMER) += xilinx-timer.o > obj-$(CONFIG_STARFIVE_TIMER) += starfive-timer.o > +obj-$(CONFIG_GOLDFISH_TIMER) += goldfish_timer.o > diff --git a/drivers/timer/goldfish_timer.c b/drivers/timer/goldfish_timer.c > new file mode 100644 > index 00000000000..63946b9ed97 > --- /dev/null > +++ b/drivers/timer/goldfish_timer.c > @@ -0,0 +1,81 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]> > + * > + * Goldfish Timer driver > + */ > + > +#include <asm/io.h> > +#include <dm.h> > +#include <goldfish_timer.h> > +#include <linux/errno.h> > +#include <mapmem.h> > +#include <timer.h> > + > +struct goldfish_timer_priv { > + void __iomem *base; > +}; > + > +/* Goldfish RTC registers used as Timer */ > +#define TIMER_TIME_LOW 0x00 > +#define TIMER_TIME_HIGH 0x04 > + > +static u64 goldfish_timer_get_count(struct udevice *dev) > +{ > + struct goldfish_timer_priv *priv = dev_get_priv(dev); > + u32 low, high; > + u64 time; > + > + /* > + * TIMER_TIME_HIGH is only updated when TIMER_TIME_LOW is read. > + * We must read LOW before HIGH to latch the high 32-bit value > + * and ensure a consistent 64-bit timestamp. > + */ > + low = readl(priv->base + TIMER_TIME_LOW); > + high = readl(priv->base + TIMER_TIME_HIGH); > + > + time = ((u64)high << 32) | low; > + > + return time; > +} > + > +static int goldfish_timer_probe(struct udevice *dev) > +{ > + struct goldfish_timer_priv *priv = dev_get_priv(dev); > + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); > + struct goldfish_timer_plat *plat; > + fdt_addr_t addr; > + > + addr = dev_read_addr(dev); > + if (addr != FDT_ADDR_T_NONE) { > + priv->base = map_sysmem(addr, 0x20); > + } else { > + plat = dev_get_plat(dev); > + if (!plat) > + return -EINVAL; > + priv->base = plat->base; > + } > + > + /* Goldfish RTC counts in nanoseconds, so the rate is 1GHz */ > + uc_priv->clock_rate = 1000000000; > + > + return 0; > +} > + > +static const struct timer_ops goldfish_timer_ops = { > + .get_count = goldfish_timer_get_count, > +}; > + > +static const struct udevice_id goldfish_timer_ids[] = { > + { .compatible = "google,goldfish-rtc" }, > + { } > +}; > + > +U_BOOT_DRIVER(goldfish_timer) = { > + .name = "goldfish_timer", > + .id = UCLASS_TIMER, > + .of_match = goldfish_timer_ids, > + .ops = &goldfish_timer_ops, > + .probe = goldfish_timer_probe, > + .priv_auto = sizeof(struct goldfish_timer_priv), > +}; > diff --git a/include/goldfish_timer.h b/include/goldfish_timer.h > new file mode 100644 > index 00000000000..2ea28170759 > --- /dev/null > +++ b/include/goldfish_timer.h > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]> > + */ > + > +#ifndef _GOLDFISH_TIMER_H_ > +#define _GOLDFISH_TIMER_H_ > + > +struct goldfish_timer_plat { > + void __iomem *base; > +}; > + > +#endif /* _GOLDFISH_TIMER_H_ */
-- Angelo

