This patch integrates the watchdog triggering into the recently added
cyclic infrastructure. Each watchdog device that shall be triggered
registers it's own cyclic function. This way, multiple watchdog devices
are still supported, each via a cyclic function with separate trigger
intervals.
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Tom Rini <trini@konsulko.com> [am335x_evm, mx6cuboxi, rpi_3,dra7xx_evm, pine64_plus, am65x_evm, j721e_evm]
config WATCHDOG
bool "Enable U-Boot watchdog reset"
depends on !HW_WATCHDOG
config WATCHDOG
bool "Enable U-Boot watchdog reset"
depends on !HW_WATCHDOG
help
This option enables U-Boot watchdog support where U-Boot is using
watchdog_reset function to service watchdog device in U-Boot. Enable
help
This option enables U-Boot watchdog support where U-Boot is using
watchdog_reset function to service watchdog device in U-Boot. Enable
bool "Enable driver model for watchdog timer drivers"
depends on DM
imply WATCHDOG
bool "Enable driver model for watchdog timer drivers"
depends on DM
imply WATCHDOG
help
Enable driver model for watchdog timer. At the moment the API
is very simple and only supports four operations:
help
Enable driver model for watchdog timer. At the moment the API
is very simple and only supports four operations:
#define LOG_CATEGORY UCLASS_WDT
#include <common.h>
#define LOG_CATEGORY UCLASS_WDT
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <hang.h>
#include <dm.h>
#include <errno.h>
#include <hang.h>
bool running;
/* No autostart */
bool noautostart;
bool running;
/* No autostart */
bool noautostart;
+
+ struct cyclic_info *cyclic;
+static void wdt_cyclic(void *ctx)
+{
+ struct udevice *dev = ctx;
+ struct wdt_priv *priv;
+
+ if (!device_active(dev))
+ return;
+
+ priv = dev_get_uclass_priv(dev);
+ if (!priv->running)
+ return;
+
+ wdt_reset(dev);
+}
+
static void init_watchdog_dev(struct udevice *dev)
{
struct wdt_priv *priv;
static void init_watchdog_dev(struct udevice *dev)
{
struct wdt_priv *priv;
printf("WDT: Failed to start %s\n", dev->name);
return;
}
printf("WDT: Failed to start %s\n", dev->name);
return;
}
-
- printf("WDT: Started %s with%s servicing (%ds timeout)\n", dev->name,
- IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out", priv->timeout);
}
int initr_watchdog(void)
}
int initr_watchdog(void)
ret = ops->start(dev, timeout_ms, flags);
if (ret == 0) {
struct wdt_priv *priv = dev_get_uclass_priv(dev);
ret = ops->start(dev, timeout_ms, flags);
if (ret == 0) {
struct wdt_priv *priv = dev_get_uclass_priv(dev);
+
+ memset(str, 0, 16);
+ if (IS_ENABLED(CONFIG_WATCHDOG)) {
+ /* Register the watchdog driver as a cyclic function */
+ priv->cyclic = cyclic_register(wdt_cyclic,
+ priv->reset_period * 1000,
+ dev->name, dev);
+ if (!priv->cyclic) {
+ printf("cyclic_register for %s failed\n",
+ dev->name);
+ return -ENODEV;
+ } else {
+ snprintf(str, 16, "every %ldms",
+ priv->reset_period);
+ }
+ }
+
+ printf("WDT: Started %s with%s servicing %s (%ds timeout)\n",
+ dev->name, IS_ENABLED(CONFIG_WATCHDOG) ? "" : "out",
+ str, priv->timeout);
*/
void watchdog_reset(void)
{
*/
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;
-
- if (uclass_get(UCLASS_WDT, &uc))
- return;
-
- * 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.
+ * Empty function for now. The actual WDT handling is now done in
+ * the cyclic function instead.
- 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);
- }
- }