On i.MX7ulp the driver assumes a clock tick rate of 1kHz. This is only true though when the /256 prescaler is disabled. To fix this we disable the prescaler on i.MX7ulp while keeping it enabled on i.MX93. We derived this bug from U-Boot, the Kernel does this correctly and has the same code as we introduce here now. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/watchdog/imxulp-wdt.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/imxulp-wdt.c b/drivers/watchdog/imxulp-wdt.c index 84d558b812..5a89876175 100644 --- a/drivers/watchdog/imxulp-wdt.c +++ b/drivers/watchdog/imxulp-wdt.c @@ -16,14 +16,16 @@ #include <asm/system.h> struct imxulp_socdata { + bool prescaler_enable; unsigned int rate; }; struct imxulp_wd { struct watchdog wd; void __iomem *base; - unsigned int rate; + bool prescaler_enable; struct device *dev; + const struct imxulp_socdata *socdata; }; #define REFRESH_WORD0 0xA602 /* 1st refresh word */ @@ -72,10 +74,13 @@ static int imxulp_watchdog_set_timeout(struct watchdog *wd, unsigned int timeout while (!(readl(imxwd->base + WDOG_CS) & WDOG_CS_ULK)) ; - writel(timeout * imxwd->rate, imxwd->base + WDOG_TOVAL); + writel(timeout * imxwd->socdata->rate, imxwd->base + WDOG_TOVAL); + + if (imxwd->socdata->prescaler_enable) + cmd32 |= WDOG_CS_PRES; writel(cmd32 | WDOG_CS_EN | WDOG_CS_UPDATE | WDOG_CS_LPO_CLK | - WDOG_CS_FLG | WDOG_CS_PRES | WDOG_CS_INT, imxwd->base + WDOG_CS); + WDOG_CS_FLG | WDOG_CS_INT, imxwd->base + WDOG_CS); /* Wait WDOG reconfiguration */ while (!(readl(imxwd->base + WDOG_CS) & WDOG_CS_RCS)) @@ -115,10 +120,10 @@ static int imxulp_wd_probe(struct device *dev) if (IS_ERR(iores)) return dev_err_probe(dev, PTR_ERR(iores), "could not get memory region\n"); - imxwd->rate = socdata->rate; + imxwd->socdata = socdata; imxwd->base = IOMEM(iores->start); imxwd->wd.set_timeout = imxulp_watchdog_set_timeout; - imxwd->wd.timeout_max = 0xffff / imxwd->rate; + imxwd->wd.timeout_max = 0xffff / imxwd->socdata->rate; imxwd->wd.hwdev = dev; imxwd->wd.running = imxulp_wd_running(imxwd); @@ -130,10 +135,12 @@ static int imxulp_wd_probe(struct device *dev) } static struct imxulp_socdata imx7ulp_wd_socdata = { + .prescaler_enable = false, .rate = CLK_RATE_1KHZ, }; static struct imxulp_socdata imx93_wd_socdata = { + .prescaler_enable = true, .rate = CLK_RATE_32KHZ, }; -- 2.39.2