diff options
author | Rasmus Villemoes | 2021-08-19 11:57:03 +0200 |
---|---|---|
committer | Stefan Roese | 2021-08-31 12:04:03 +0200 |
commit | 492ee6b8d0e780a2ded5d9df7efc916eb4913734 (patch) | |
tree | 883f8efe008fd52f02dfb7649c980316b5abb6ac /drivers | |
parent | 1c5aedcd9ac419199983e5e0ef398170843f6976 (diff) |
watchdog: wdt-uclass.c: handle all DM watchdogs in watchdog_reset()
A board can have and make use of more than one watchdog device, say
one built into the SOC and an external gpio-petted one. Having
wdt-uclass only handle the first is both a little arbitrary and
unexpected.
So change initr_watchdog() so we visit (probe) all DM watchdog
devices, and call the init_watchdog_dev helper for each.
Similarly let watchdog_reset() loop over the whole uclass - each
having their own ratelimiting metadata, and a separate "is this device
running" flag.
This gets rid of the watchdog_dev member of struct global_data. We
do, however, still need the GD_FLG_WDT_READY set in
initr_watchdog(). This is because watchdog_reset() can get called
before DM is ready, and I don't think we can call uclass_get() that
early.
The current code just returns 0 if "getting" the first device fails -
that can of course happen because there are no devices, but it could
also happen if its ->probe call failed. In keeping with that, continue
with the handling of the remaining devices even if one fails to
probe. This is also why we cannot use uclass_probe_all().
If desired, it's possible to later add a per-device "u-boot,autostart"
boolean property, so that one can do CONFIG_WATCHDOG_AUTOSTART
per-device.
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/watchdog/wdt-uclass.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c index 5b1c0df5d6d..7570710c4d9 100644 --- a/drivers/watchdog/wdt-uclass.c +++ b/drivers/watchdog/wdt-uclass.c @@ -61,20 +61,24 @@ static void init_watchdog_dev(struct udevice *dev) int initr_watchdog(void) { - /* - * Init watchdog: This will call the probe function of the - * watchdog driver, enabling the use of the device - */ - if (uclass_get_device_by_seq(UCLASS_WDT, 0, - (struct udevice **)&gd->watchdog_dev)) { - debug("WDT: Not found by seq!\n"); - if (uclass_get_device(UCLASS_WDT, 0, - (struct udevice **)&gd->watchdog_dev)) { - printf("WDT: Not found!\n"); - return 0; + struct udevice *dev; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_WDT, &uc); + if (ret) { + log_debug("Error getting UCLASS_WDT: %d\n", ret); + return 0; + } + + uclass_foreach_dev(dev, uc) { + ret = device_probe(dev); + if (ret) { + log_debug("Error probing %s: %d\n", dev->name, ret); + continue; } + init_watchdog_dev(dev); } - init_watchdog_dev(gd->watchdog_dev); gd->flags |= GD_FLG_WDT_READY; return 0; @@ -182,22 +186,34 @@ void watchdog_reset(void) { struct wdt_priv *priv; struct udevice *dev; + struct uclass *uc; ulong now; /* Exit if GD is not ready or watchdog is not initialized yet */ if (!gd || !(gd->flags & GD_FLG_WDT_READY)) return; - dev = gd->watchdog_dev; - priv = dev_get_uclass_priv(dev); - if (!priv->running) + if (uclass_get(UCLASS_WDT, &uc)) return; - /* Do not reset the watchdog too often */ - now = get_timer(0); - if (time_after_eq(now, priv->next_reset)) { - priv->next_reset = now + priv->reset_period; - wdt_reset(dev); + /* + * All devices bound to the wdt uclass should have been probed + * in initr_watchdog(). But just in case something went wrong, + * check device_active() before accessing the uclass private + * data. + */ + uclass_foreach_dev(dev, uc) { + if (!device_active(dev)) + continue; + priv = dev_get_uclass_priv(dev); + if (!priv->running) + continue; + /* Do not reset the watchdog too often */ + now = get_timer(0); + if (time_after_eq(now, priv->next_reset)) { + priv->next_reset = now + priv->reset_period; + wdt_reset(dev); + } } } #endif |