aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/watchdog/wdt_i6300esb.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index e694fa9969..4ebdbb8586 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -125,8 +125,14 @@ static void i6300esb_restart_timer(I6300State *d, int stage)
else
timeout <<= 5;
- /* Get the timeout in units of ticks_per_sec. */
- timeout = get_ticks_per_sec() * timeout / 33000000;
+ /* Get the timeout in units of ticks_per_sec.
+ *
+ * ticks_per_sec is typically 10^9 == 0x3B9ACA00 (30 bits), with
+ * 20 bits of user supplied preload, and 15 bits of scale, the
+ * multiply here can exceed 64-bits, before we divide by 33MHz, so
+ * we use a higher-precision intermediate result.
+ */
+ timeout = muldiv64(get_ticks_per_sec(), timeout, 33000000);
i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);