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 <juuso.rinta@nokia.com> Reviewed-by: Stefan Roese <stefan.roese@mailbox.org>
This commit is contained in:
committed by
Stefan Roese
parent
d62801d094
commit
1a489a1a43
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user