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>
This commit is contained in:
parent
1c5aedcd9a
commit
492ee6b8d0
2 changed files with 37 additions and 27 deletions
|
@ -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
|
||||
|
|
|
@ -447,12 +447,6 @@ struct global_data {
|
|||
*/
|
||||
fdt_addr_t translation_offset;
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(WDT)
|
||||
/**
|
||||
* @watchdog_dev: watchdog device
|
||||
*/
|
||||
struct udevice *watchdog_dev;
|
||||
#endif
|
||||
#ifdef CONFIG_GENERATE_ACPI_TABLE
|
||||
/**
|
||||
* @acpi_ctx: ACPI context pointer
|
||||
|
|
Loading…
Reference in a new issue