diff options
| author | Juuso Rinta <[email protected]> | 2026-05-04 12:34:34 +0300 |
|---|---|---|
| committer | Stefan Roese <[email protected]> | 2026-06-09 11:51:19 +0200 |
| commit | 1a489a1a4375237ce1cabf7f95e2c57506350e7f (patch) | |
| tree | d6ed9e9b91324d9e4206ac3a51e5323b36c6c0db /drivers | |
| parent | d62801d09441acfebe2c8b7da66de70e6e5ad492 (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.c | 10 |
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); |
