[U-Boot] [PATCH 1/4 v4] watchdog: Implement generic watchdog_reset() version
Chris Packham
judge.packham at gmail.com
Sun Feb 23 20:37:58 CET 2020
Hi Stefan,
Just noticed something when updating our internal u-boot repo
On Fri, Apr 12, 2019 at 2:00 AM Stefan Roese <sr at denx.de> wrote:
>
> This patch tries to implement a generic watchdog_reset() function that
> can be used by all boards that want to service the watchdog device in
> U-Boot. This watchdog servicing is enabled via CONFIG_WATCHDOG.
>
> Without this approach, new boards or platforms needed to implement a
> board specific version of this functionality, mostly copy'ing the same
> code over and over again into their board or platforms code base.
>
> With this new generic function, the scattered other functions are now
> removed to be replaced by the generic one. The new version also enables
> the configuration of the watchdog timeout via the DT "timeout-sec"
> property (if enabled via CONFIG_OF_CONTROL).
>
> This patch also adds a new flag to the GD flags, to flag that the
> watchdog is ready to use and adds the pointer to the watchdog device
> to the GD. This enables us to remove the global "watchdog_dev"
> variable, which was prone to cause problems because of its potentially
> very early use in watchdog_reset(), even before the BSS is cleared.
<snip>
> diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
> index 23b7e3360d..bbfac4f0f9 100644
> --- a/drivers/watchdog/wdt-uclass.c
> +++ b/drivers/watchdog/wdt-uclass.c
> @@ -10,6 +10,8 @@
> #include <dm/device-internal.h>
> #include <dm/lists.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
> int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
> {
> const struct wdt_ops *ops = device_get_ops(dev);
> @@ -63,6 +65,30 @@ int wdt_expire_now(struct udevice *dev, ulong flags)
> return ret;
> }
>
> +#if defined(CONFIG_WATCHDOG)
> +/*
> + * Called by macro WATCHDOG_RESET. This function be called *very* early,
> + * so we need to make sure, that the watchdog driver is ready before using
> + * it in this function.
> + */
> +void watchdog_reset(void)
> +{
> + static ulong next_reset;
> + ulong now;
> +
> + /* Exit if GD is not ready or watchdog is not initialized yet */
> + if (!gd || !(gd->flags & GD_FLG_WDT_READY))
> + return;
> +
> + /* Do not reset the watchdog too often */
> + now = get_timer(0);
> + if (now > next_reset) {
If the counter wraps we stop tickling the watchdog and the board will
reset. On our 32-bit arm boards this is only about 72 minutes so it
got noticed in production testing. The fix we had in our board code
was:
+#ifndef time_after
+#define time_after(a,b) \
+ ((long)((b) - (a)) < 0)
+#endif
@@ -202,7 +208,7 @@ void watchdog_reset(void)
now = timer_get_us();
/* Do not reset the watchdog too often */
- if (now > next_reset) {
+ if (time_after(now, next_reset)) {
wdt_reset(watchdog_dev);
next_reset = now + 1000;
}
I'll send a proper patch (gmail will eat the whitespace in the inline diff).
> + next_reset = now + 1000; /* reset every 1000ms */
> + wdt_reset(gd->watchdog_dev);
> + }
> +}
> +#endif
> +
> static int wdt_post_bind(struct udevice *dev)
> {
> #if defined(CONFIG_NEEDS_MANUAL_RELOC)
More information about the U-Boot
mailing list