watchdog: digicolor: Avoid division by zero

clk_get_rate() could return 0.  Avoid a division by zero panic.

Since get_timeleft() cannot propagate errors, check the clock rate early
in probe() and cache the rate in the driver data as it is unlikely to
change at runtime.

Fixes: 336694a01d ("watchdog: digicolor: driver for Conexant Digicolor CX92755 SoC")
Cc: stable@vger.kernel.org
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Acked-by: Baruch Siach <baruch@tkos.co.il>
Link: https://patch.msgid.link/20260913064851.8239-2-tzungbi@kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Tzung-Bi Shih 2026-09-13 14:48:49 +08:00 committed by Guenter Roeck
parent 88f1136340
commit 400cb663ca

View File

@ -25,6 +25,7 @@ struct dc_wdt {
void __iomem *base;
struct clk *clk;
spinlock_t lock;
unsigned long rate;
};
static unsigned timeout;
@ -61,7 +62,7 @@ static int dc_wdt_start(struct watchdog_device *wdog)
{
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
dc_wdt_set(wdt, wdog->timeout * clk_get_rate(wdt->clk));
dc_wdt_set(wdt, wdog->timeout * wdt->rate);
return 0;
}
@ -79,7 +80,7 @@ static int dc_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t)
{
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
dc_wdt_set(wdt, t * clk_get_rate(wdt->clk));
dc_wdt_set(wdt, t * wdt->rate);
wdog->timeout = t;
return 0;
@ -90,7 +91,7 @@ static unsigned int dc_wdt_get_timeleft(struct watchdog_device *wdog)
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
uint32_t count = readl_relaxed(wdt->base + TIMER_A_COUNT);
return count / clk_get_rate(wdt->clk);
return count / wdt->rate;
}
static const struct watchdog_ops dc_wdt_ops = {
@ -130,7 +131,11 @@ static int dc_wdt_probe(struct platform_device *pdev)
wdt->clk = devm_clk_get(dev, NULL);
if (IS_ERR(wdt->clk))
return PTR_ERR(wdt->clk);
dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk);
wdt->rate = clk_get_rate(wdt->clk);
if (!wdt->rate)
return -EINVAL;
dc_wdt_wdd.max_timeout = U32_MAX / wdt->rate;
dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout;
dc_wdt_wdd.parent = dev;