summaryrefslogtreecommitdiff
path: root/drivers/timer
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-02-02 14:24:56 -0600
committerTom Rini <[email protected]>2026-02-02 14:25:48 -0600
commit1de103fc29761fa729dffaa15d0cfb2766be05e4 (patch)
treefc2253a01976672d68a4d984273e7f02c1fbd3cc /drivers/timer
parent4b287e0a3ae4ab3159584cb5ae12c9b470716be8 (diff)
parent838e3be9e1d39e38661a788ae3bcfb9f989450a8 (diff)
Merge patch series "m68k: Add support for QEMU virt machine"
Kuan-Wei Chiu <[email protected]> says: Add support for the QEMU 'virt' machine on the m68k architecture. The QEMU virt machine models a generic system utilizing Goldfish virtual peripherals and is capable of emulating various classic 68k CPUs. Currently, U-Boot's m68k architecture support focuses on ColdFire variants. This series expands support to include the classic M680x0 architecture, implementing the necessary exception vectors, startup code, and a bootinfo parser compatible with the QEMU interface. Drivers for Goldfish peripherals (TTY, Timer, RTC) and the QEMU Virtual System Controller (sysreset) are also added to enable serial console, timekeeping, and system reset functionality. The implementation has been verified on QEMU targeting the M68040 CPU, confirming successful hardware initialization and boot to the U-Boot command shell. Additionally, the CI configuration was verified locally using gitlab-ci-local "qemu_m68k_virt test.py", resulting in PASS qemu_m68k_virt test.py. Link: https://lore.kernel.org/r/[email protected] [trini: Re-sort MAINTAINERS entries] Signed-off-by: Tom Rini <[email protected]>
Diffstat (limited to 'drivers/timer')
-rw-r--r--drivers/timer/Kconfig8
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/goldfish_timer.c89
3 files changed, 98 insertions, 0 deletions
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..70673bbd93c
--- /dev/null
+++ b/drivers/timer/goldfish_timer.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]>
+ *
+ * Goldfish Timer driver
+ */
+
+#include <dm.h>
+#include <goldfish_timer.h>
+#include <mapmem.h>
+#include <timer.h>
+#include <asm/io.h>
+#include <linux/errno.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_of_to_plat(struct udevice *dev)
+{
+ struct goldfish_timer_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(dev);
+ if (addr != FDT_ADDR_T_NONE)
+ plat->reg = addr;
+
+ return 0;
+}
+
+static int goldfish_timer_probe(struct udevice *dev)
+{
+ struct goldfish_timer_plat *plat = dev_get_plat(dev);
+ struct goldfish_timer_priv *priv = dev_get_priv(dev);
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ if (!plat->reg)
+ return -EINVAL;
+
+ priv->base = map_sysmem(plat->reg, 0x20);
+
+ /* 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,
+ .of_to_plat = goldfish_timer_of_to_plat,
+ .plat_auto = sizeof(struct goldfish_timer_plat),
+ .ops = &goldfish_timer_ops,
+ .probe = goldfish_timer_probe,
+ .priv_auto = sizeof(struct goldfish_timer_priv),
+};