summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJuuso Rinta <[email protected]>2026-05-04 12:34:34 +0300
committerStefan Roese <[email protected]>2026-06-09 11:51:19 +0200
commit1a489a1a4375237ce1cabf7f95e2c57506350e7f (patch)
treed6ed9e9b91324d9e4206ac3a51e5323b36c6c0db /drivers
parentd62801d09441acfebe2c8b7da66de70e6e5ad492 (diff)
watchdog: sbsa_gwdt: clamp WOR value to hw max
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 <[email protected]> Reviewed-by: Stefan Roese <[email protected]>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/watchdog/sbsa_gwdt.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index 807884c5bc7..3a924cb2b9a 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -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);