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]> --- Changes in v3: - New patch. The link provided by Daniel [1] returned a 404 error. Since the implementation is straightforward, I wrote this driver from scratch. [1]: https://github.com/fifteenhex/u-boot/blob/mc68000/drivers/rtc/goldfish_timer.c MAINTAINERS | 6 ++++ drivers/timer/Kconfig | 8 +++++ drivers/timer/Makefile | 1 + drivers/timer/goldfish_timer.c | 60 ++++++++++++++++++++++++++++++++++ include/goldfish_timer.h | 13 ++++++++ 5 files changed, 88 insertions(+) create mode 100644 drivers/timer/goldfish_timer.c create mode 100644 include/goldfish_timer.h diff --git a/MAINTAINERS b/MAINTAINERS index da4a6e4d518..fcc437a53ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1265,6 +1265,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 + I2C M: Heiko Schocher <[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..8205ac77853 --- /dev/null +++ b/drivers/timer/goldfish_timer.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]> + * + * Goldfish Timer driver + */ + +#include <dm.h> +#include <timer.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <goldfish_timer.h> + +/* 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_plat *plat = dev_get_plat(dev); + u32 low, high; + u64 time; + + /* + * Goldfish RTC provides time in nanoseconds. + * We read the high 32-bits and low 32-bits to construct the 64-bit value. + */ + low = readl(plat->base + TIMER_TIME_LOW); + high = readl(plat->base + TIMER_TIME_HIGH); + + time = ((u64)high << 32) | low; + + return time; +} + +static int goldfish_timer_probe(struct udevice *dev) +{ + struct goldfish_timer_plat *plat = dev_get_plat(dev); + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + if (!plat || !plat->base) + return -EINVAL; + + /* 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, +}; + +U_BOOT_DRIVER(goldfish_timer) = { + .name = "goldfish_timer", + .id = UCLASS_TIMER, + .ops = &goldfish_timer_ops, + .probe = goldfish_timer_probe, + .plat_auto = sizeof(struct goldfish_timer_plat), +}; 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_ */ -- 2.52.0.358.g0dd7633a29-goog

