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
					
				|  | @ -61,20 +61,24 @@ static void init_watchdog_dev(struct udevice *dev) | ||||||
| 
 | 
 | ||||||
| int initr_watchdog(void) | int initr_watchdog(void) | ||||||
| { | { | ||||||
| 	/*
 | 	struct udevice *dev; | ||||||
| 	 * Init watchdog: This will call the probe function of the | 	struct uclass *uc; | ||||||
| 	 * watchdog driver, enabling the use of the device | 	int ret; | ||||||
| 	 */ | 
 | ||||||
| 	if (uclass_get_device_by_seq(UCLASS_WDT, 0, | 	ret = uclass_get(UCLASS_WDT, &uc); | ||||||
| 				     (struct udevice **)&gd->watchdog_dev)) { | 	if (ret) { | ||||||
| 		debug("WDT:   Not found by seq!\n"); | 		log_debug("Error getting UCLASS_WDT: %d\n", ret); | ||||||
| 		if (uclass_get_device(UCLASS_WDT, 0, | 		return 0; | ||||||
| 				      (struct udevice **)&gd->watchdog_dev)) { | 	} | ||||||
| 			printf("WDT:   Not found!\n"); | 
 | ||||||
| 			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; | 	gd->flags |= GD_FLG_WDT_READY; | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -182,22 +186,34 @@ void watchdog_reset(void) | ||||||
| { | { | ||||||
| 	struct wdt_priv *priv; | 	struct wdt_priv *priv; | ||||||
| 	struct udevice *dev; | 	struct udevice *dev; | ||||||
|  | 	struct uclass *uc; | ||||||
| 	ulong now; | 	ulong now; | ||||||
| 
 | 
 | ||||||
| 	/* Exit if GD is not ready or watchdog is not initialized yet */ | 	/* Exit if GD is not ready or watchdog is not initialized yet */ | ||||||
| 	if (!gd || !(gd->flags & GD_FLG_WDT_READY)) | 	if (!gd || !(gd->flags & GD_FLG_WDT_READY)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	dev = gd->watchdog_dev; | 	if (uclass_get(UCLASS_WDT, &uc)) | ||||||
| 	priv = dev_get_uclass_priv(dev); |  | ||||||
| 	if (!priv->running) |  | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	/* Do not reset the watchdog too often */ | 	/*
 | ||||||
| 	now = get_timer(0); | 	 * All devices bound to the wdt uclass should have been probed | ||||||
| 	if (time_after_eq(now, priv->next_reset)) { | 	 * in initr_watchdog(). But just in case something went wrong, | ||||||
| 		priv->next_reset = now + priv->reset_period; | 	 * check device_active() before accessing the uclass private | ||||||
| 		wdt_reset(dev); | 	 * 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 | #endif | ||||||
|  |  | ||||||
|  | @ -447,12 +447,6 @@ struct global_data { | ||||||
| 	 */ | 	 */ | ||||||
| 	fdt_addr_t translation_offset; | 	fdt_addr_t translation_offset; | ||||||
| #endif | #endif | ||||||
| #if CONFIG_IS_ENABLED(WDT) |  | ||||||
| 	/**
 |  | ||||||
| 	 * @watchdog_dev: watchdog device |  | ||||||
| 	 */ |  | ||||||
| 	struct udevice *watchdog_dev; |  | ||||||
| #endif |  | ||||||
| #ifdef CONFIG_GENERATE_ACPI_TABLE | #ifdef CONFIG_GENERATE_ACPI_TABLE | ||||||
| 	/**
 | 	/**
 | ||||||
| 	 * @acpi_ctx: ACPI context pointer | 	 * @acpi_ctx: ACPI context pointer | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue