]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
watchdog: sbsa_gwdt: clamp WOR value to hw max
authorJuuso Rinta <juuso.rinta@nokia.com>
Mon, 4 May 2026 09:34:34 +0000 (12:34 +0300)
committerStefan Roese <stefan.roese@mailbox.org>
Tue, 9 Jun 2026 09:51:19 +0000 (11:51 +0200)
The WOR register is 32 bits, so any tick count exceeding U32_MAX is
truncated by writel(). A large requested timeout can wrap to a small
value causing the watchdog to fire sooner than requested.

Clamp the calculated value to U32_MAX prior to writing the register so
over-large requests will be set to the maximum timeout value.

Found by code review.

Signed-off-by: Juuso Rinta <juuso.rinta@nokia.com>
Reviewed-by: Stefan Roese <stefan.roese@mailbox.org>
drivers/watchdog/sbsa_gwdt.c

index 807884c5bc73d20409a8cfd5dfa2f94fab3e5692..3a924cb2b9ac954e93597b43e81d2657f77c3dcf 100644 (file)
@@ -50,6 +50,7 @@ static int sbsa_gwdt_start(struct udevice *dev, u64 timeout, ulong flags)
 {
        struct sbsa_gwdt_priv *priv = dev_get_priv(dev);
        u32 clk;
+       u64 tout_wdog;
 
        /*
         * it work in the single stage mode in u-boot,
@@ -58,8 +59,13 @@ static int sbsa_gwdt_start(struct udevice *dev, u64 timeout, ulong flags)
         * to half value of timeout.
         */
        clk = get_tbclk();
-       writel(clk / (2 * 1000) * timeout,
-              priv->reg_control + SBSA_GWDT_WOR);
+
+       /* if requested timeout overflows, clamp it to u32_max */
+       tout_wdog = ((u64)clk * timeout) / (2 * 1000);
+       if (tout_wdog > U32_MAX)
+               tout_wdog = U32_MAX;
+
+       writel(tout_wdog, priv->reg_control + SBSA_GWDT_WOR);
 
        /* writing WCS will cause an explicit watchdog refresh */
        writel(SBSA_GWDT_WCS_EN, priv->reg_control + SBSA_GWDT_WCS);