aboutsummaryrefslogtreecommitdiff
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorStefan Roese2022-08-18 13:22:46 +0200
committerStefan Roese2022-09-18 10:26:04 +0200
commitc2fd0ca1a8226903e6e00f970c58f23742d6a418 (patch)
treeafec965947a5b85ef729eca44c8317eb4954c238 /drivers/watchdog
parentd219fc06b30d4b1ac4fac6c40b2ca69cb5ecf642 (diff)
watchdog: Integrate watchdog triggering into the cyclic framework
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]
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/wdt-uclass.c73
2 files changed, 43 insertions, 32 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50e6a1efba5..e55deaf906b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -3,6 +3,7 @@ menu "Watchdog Timer Support"
config WATCHDOG
bool "Enable U-Boot watchdog reset"
depends on !HW_WATCHDOG
+ select CYCLIC
help
This option enables U-Boot watchdog support where U-Boot is using
watchdog_reset function to service watchdog device in U-Boot. Enable
@@ -74,6 +75,7 @@ config WDT
bool "Enable driver model for watchdog timer drivers"
depends on DM
imply WATCHDOG
+ select CYCLIC
help
Enable driver model for watchdog timer. At the moment the API
is very simple and only supports four operations:
diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c
index dbf556467d3..3f342cd99fd 100644
--- a/drivers/watchdog/wdt-uclass.c
+++ b/drivers/watchdog/wdt-uclass.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY UCLASS_WDT
#include <common.h>
+#include <cyclic.h>
#include <dm.h>
#include <errno.h>
#include <hang.h>
@@ -38,8 +39,25 @@ struct wdt_priv {
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;
@@ -64,9 +82,6 @@ static void init_watchdog_dev(struct udevice *dev)
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)
@@ -105,8 +120,29 @@ int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
ret = ops->start(dev, timeout_ms, flags);
if (ret == 0) {
struct wdt_priv *priv = dev_get_uclass_priv(dev);
+ char str[16];
priv->running = true;
+
+ 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);
}
return ret;
@@ -194,37 +230,10 @@ int wdt_expire_now(struct udevice *dev, ulong flags)
*/
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);
- }
- }
}
#endif