The wdt_start function may be called with a timeout greater than the hardware-supported maximum. This in turn can result to bogus print, e.g. Started <watchdog@> with servicing every 1000ms (60s timeout)
Add a uclass get_timeout operation and helper so drivers can report the effective timeout. When available, the startup print now shows both actual and requested timeout values, e.g. Started <watchdog@> with servicing every 1000ms (10s timeout, requested 60s) Signed-off-by: Juuso Rinta <[email protected]> --- drivers/watchdog/wdt-uclass.c | 35 +++++++++++++++++++++++++++++++++-- include/wdt.h | 22 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c index 438833b2245..c9ce5c07afd 100644 --- a/drivers/watchdog/wdt-uclass.c +++ b/drivers/watchdog/wdt-uclass.c @@ -116,10 +116,28 @@ int initr_watchdog(void) return 0; } +int wdt_get_timeout(struct udevice *dev, u64 *timeout_ms) +{ + const struct wdt_ops *ops = device_get_ops(dev); + u64 tout_val; + int ret; + + if (!ops->get_timeout) + return -ENOSYS; + + ret = ops->get_timeout(dev, &tout_val); + if (ret == 0) + *timeout_ms = tout_val; + + return ret; +} + int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { const struct wdt_ops *ops = device_get_ops(dev); int ret; + u64 effective_timeout = timeout_ms; + char requested_timeout[32]; if (!ops->start) return -ENOSYS; @@ -143,9 +161,22 @@ int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) } priv->running = true; - printf("WDT: Started %s with%s servicing %s (%ds timeout)\n", + + /* Get the effective timeout from driver if supported */ + memset(requested_timeout, 0, 32); + if (wdt_get_timeout(dev, &effective_timeout) == 0) { + u32 effective_s = (u32)lldiv(effective_timeout, 1000); + u32 requested_s = (u32)lldiv(timeout_ms, 1000); + + if (effective_s != requested_s) { + snprintf(requested_timeout, 32, ", requested %ds", + requested_s); + } + } + + printf("WDT: Started %s with%s servicing %s (%ds timeout%s)\n", dev->name, IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out", - str, (u32)lldiv(timeout_ms, 1000)); + str, (u32)lldiv(effective_timeout, 1000), requested_timeout); } return ret; diff --git a/include/wdt.h b/include/wdt.h index 1ef656585c4..5c38eba3a5a 100644 --- a/include/wdt.h +++ b/include/wdt.h @@ -74,6 +74,19 @@ int wdt_reset(struct udevice *dev); */ int wdt_expire_now(struct udevice *dev, ulong flags); +/* + * Get the effective timeout in milliseconds. + * + * The effective value may differ from the value passed to wdt_start() + * if the hardware has rounded and/or clamped it. + * + * @dev: WDT device + * @timeout_ms: A pointer where the effective timeout in milliseconds + * is returned to. On error, the value is left unchanged. + * @return 0 if OK -ve on error + */ +int wdt_get_timeout(struct udevice *dev, u64 *timeout_ms); + /* * struct wdt_ops - Driver model wdt operations * @@ -120,6 +133,15 @@ struct wdt_ops { * @return 0 if OK -ve on error. May not return. */ int (*expire_now)(struct udevice *dev, ulong flags); + /* + * Get the effective timeout in milliseconds (optional) + * + * @dev: WDT device + * @timeout_ms: Location to store timeout in milliseconds, + * written only on success + * @return 0 if OK -ve on error + */ + int (*get_timeout)(struct udevice *dev, u64 *timeout_ms); }; int initr_watchdog(void); -- 2.39.2

