summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/sp805_wdt.c
diff options
context:
space:
mode:
authorRay Jui <ray.jui@broadcom.com>2018-05-28 20:01:35 +0200
committerWim Van Sebroeck <wim@linux-watchdog.org>2018-08-02 15:57:11 +0200
commitfa5072ed8f530df5a04511721d19b61a6cf8c96c (patch)
treed7a1dd98aea48ac19aae6e4b18fc3142201e4d03 /drivers/watchdog/sp805_wdt.c
parentwatchdog: sp805: add 'timeout-sec' DT property support (diff)
downloadlinux-fa5072ed8f530df5a04511721d19b61a6cf8c96c.tar.xz
linux-fa5072ed8f530df5a04511721d19b61a6cf8c96c.zip
watchdog: sp805: set WDOG_HW_RUNNING when appropriate
If the watchdog hardware is already enabled during the boot process, when the Linux watchdog driver loads, it should reset the watchdog and tell the watchdog framework. As a result, ping can be generated from the watchdog framework, until the userspace watchdog daemon takes over control Signed-off-by: Ray Jui <ray.jui@broadcom.com> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com> Reviewed-by: Scott Branden <scott.branden@broadcom.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
Diffstat (limited to 'drivers/watchdog/sp805_wdt.c')
-rw-r--r--drivers/watchdog/sp805_wdt.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index b240195597c1..b202138b7ecb 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -42,6 +42,7 @@
/* control register masks */
#define INT_ENABLE (1 << 0)
#define RESET_ENABLE (1 << 1)
+ #define ENABLE_MASK (INT_ENABLE | RESET_ENABLE)
#define WDTINTCLR 0x00C
#define WDTRIS 0x010
#define WDTMIS 0x014
@@ -74,6 +75,15 @@ module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
"Set to 1 to keep watchdog running after device release");
+/* returns true if wdt is running; otherwise returns false */
+static bool wdt_is_running(struct watchdog_device *wdd)
+{
+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
+ u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
+
+ return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
+}
+
/* This routine finds load value that will reset system in required timout */
static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
{
@@ -253,6 +263,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
wdt_setload(&wdt->wdd, wdt->wdd.timeout);
+ /*
+ * If HW is already running, enable/reset the wdt and set the running
+ * bit to tell the wdt subsystem
+ */
+ if (wdt_is_running(&wdt->wdd)) {
+ wdt_enable(&wdt->wdd);
+ set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
+ }
+
ret = watchdog_register_device(&wdt->wdd);
if (ret) {
dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",