Hi Guenter, On 11/21/19 10:53 AM, Guenter Roeck wrote: > On 11/21/19 12:28 AM, Christophe Roullier wrote: >> If the watchdog hardware is already enabled during the boot process, >> when the Linux watchdog driver loads, it should reset the watchdog and >> tell the watchdog framework. As a result, ping can be generated from >> the watchdog framework (if CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set), >> until the userspace watchdog daemon takes over control >> > > This is not what the code is doing. It sets the WDOG_HW_RUNNING flag > unconditionally, no matter if the watchdog is already running or not. > It also changes the semantic of the rest of the code, as well as > functionality. The code in start_timeout no longer waits, and the ping > code explicitly (re-)enables the watchdog. > > If you want an option to start the watchdog at probe time > unconditionally, > please add a module parameter to do it. Otherwise you'll need to check if > it is indeed enabled before setting WDOG_HW_RUNNING, and in that case it > should not be necessary to re-enable it. It should also not be necessary > to split the start function. With our IWDG IP, there is no way to read values from hardware (if it is running or not) We are in same case of intel-mid_wdt.c driver, we have Uboot which can leaves the watchdog running. So we need to force the kicking of our watchdog. Thanks Christophe > > Thanks, > Guenter > >> Fixes:4332d113c66a ("watchdog: Add STM32 IWDG driver") >> Signed-off-by: Christophe Roullier <christophe.roullier@xxxxxx> >> --- >> drivers/watchdog/stm32_iwdg.c | 57 ++++++++++++++++++++++++----------- >> 1 file changed, 40 insertions(+), 17 deletions(-) >> >> diff --git a/drivers/watchdog/stm32_iwdg.c >> b/drivers/watchdog/stm32_iwdg.c >> index a3a329011a06..2b3be3b1c15b 100644 >> --- a/drivers/watchdog/stm32_iwdg.c >> +++ b/drivers/watchdog/stm32_iwdg.c >> @@ -87,8 +87,23 @@ static inline void reg_write(void __iomem *base, >> u32 reg, u32 val) >> static int stm32_iwdg_start(struct watchdog_device *wdd) >> { >> struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd); >> - u32 tout, presc, iwdg_rlr, iwdg_pr, iwdg_sr; >> - int ret; >> + >> + dev_dbg(wdd->parent, "%s\n", __func__); >> + >> + /* Start the watchdog */ >> + reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE); >> + >> + /* reload watchdog */ >> + reg_write(wdt->regs, IWDG_KR, KR_KEY_RELOAD); >> + >> + set_bit(WDOG_HW_RUNNING, &wdd->status); >> + return 0; >> +} >> + >> +static int stm32_iwdg_setprescaler(struct watchdog_device *wdd) >> +{ >> + struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd); >> + u32 tout, presc, iwdg_rlr, iwdg_pr; >> dev_dbg(wdd->parent, "%s\n", __func__); >> @@ -108,19 +123,6 @@ static int stm32_iwdg_start(struct >> watchdog_device *wdd) >> /* set prescaler & reload registers */ >> reg_write(wdt->regs, IWDG_PR, iwdg_pr); >> reg_write(wdt->regs, IWDG_RLR, iwdg_rlr); >> - reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE); >> - >> - /* wait for the registers to be updated (max 100ms) */ >> - ret = readl_relaxed_poll_timeout(wdt->regs + IWDG_SR, iwdg_sr, >> - !(iwdg_sr & (SR_PVU | SR_RVU)), >> - SLEEP_US, TIMEOUT_US); >> - if (ret) { >> - dev_err(wdd->parent, "Fail to set prescaler, reload regs\n"); >> - return ret; >> - } >> - >> - /* reload watchdog */ >> - reg_write(wdt->regs, IWDG_KR, KR_KEY_RELOAD); >> return 0; >> } >> @@ -131,6 +133,9 @@ static int stm32_iwdg_ping(struct watchdog_device >> *wdd) >> dev_dbg(wdd->parent, "%s\n", __func__); >> + /* Start the watchdog */ >> + reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE); >> + >> /* reload watchdog */ >> reg_write(wdt->regs, IWDG_KR, KR_KEY_RELOAD); >> @@ -140,12 +145,21 @@ static int stm32_iwdg_ping(struct >> watchdog_device *wdd) >> static int stm32_iwdg_set_timeout(struct watchdog_device *wdd, >> unsigned int timeout) >> { >> + int ret; >> + >> dev_dbg(wdd->parent, "%s timeout: %d sec\n", __func__, timeout); >> wdd->timeout = timeout; >> - if (watchdog_active(wdd)) >> - return stm32_iwdg_start(wdd); >> + if (watchdog_active(wdd)) { >> + ret = stm32_iwdg_setprescaler(wdd); >> + if (ret) { >> + dev_err(wdd->parent, "failed to set prescaler\n"); >> + return ret; >> + } else { >> + return stm32_iwdg_start(wdd); >> + } >> + } >> return 0; >> } >> @@ -262,12 +276,21 @@ static int stm32_iwdg_probe(struct >> platform_device *pdev) >> watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT); >> watchdog_init_timeout(wdd, 0, dev); >> + /* Make sure the watchdog is serviced */ >> + set_bit(WDOG_HW_RUNNING, &wdd->status); >> + >> ret = devm_watchdog_register_device(dev, wdd); >> if (ret) >> return ret; >> platform_set_drvdata(pdev, wdt); >> + ret = stm32_iwdg_setprescaler(wdd); >> + if (ret) { >> + dev_err(dev, "failed to set prescaler\n"); >> + return ret; >> + } >> + >> return 0; >> } >> >