summaryrefslogtreecommitdiff
path: root/drivers/watchdog/imx8_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/imx8_wdt.c')
-rw-r--r--drivers/watchdog/imx8_wdt.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/watchdog/imx8_wdt.c b/drivers/watchdog/imx8_wdt.c
index 7a855012366a..357e49e57e82 100644
--- a/drivers/watchdog/imx8_wdt.c
+++ b/drivers/watchdog/imx8_wdt.c
@@ -35,7 +35,8 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
static unsigned int timeout = DEFAULT_TIMEOUT;
module_param(timeout, uint, 0000);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds 1<= timeout <="
+ __MODULE_STRING(MAX_TIMEOUT) " (default="
__MODULE_STRING(DEFAULT_TIMEOUT) ")");
static struct watchdog_device imx8_wdd;
@@ -73,6 +74,8 @@ static int imx8_wdt_start(struct watchdog_device *wdog)
if (res.a0)
return res.a0;
+ dev_dbg(wdog->parent, "Watchdog started\n");
+
return 0;
}
@@ -83,6 +86,8 @@ static int imx8_wdt_stop(struct watchdog_device *wdog)
arm_smccc_smc(FSL_SIP_SRTC, FSL_SIP_SRTC_STOP_WDOG, 0, 0, 0, 0, 0, 0,
&res);
+ dev_dbg(wdog->parent, "Watchdog stopped\n");
+
return res.a0;
}
@@ -96,6 +101,8 @@ static int imx8_wdt_set_timeout(struct watchdog_device *wdog,
arm_smccc_smc(FSL_SIP_SRTC, FSL_SIP_SRTC_SET_TIMEOUT_WDOG,
timeout * 1000, 0, 0, 0, 0, 0, &res);
+ dev_dbg(wdog->parent, "Set timeout to %d seconds\n", timeout);
+
return res.a0;
}
@@ -104,9 +111,16 @@ static int imx8_wdt_set_pretimeout(struct watchdog_device *wdog,
{
struct arm_smccc_res res;
+ /*
+ * SCU firmware calculates pretimeout based on current time
+ * stamp instead of watchdog timeout stamp, need to convert
+ * the pretimeout to SCU firmware's timeout value.
+ */
arm_smccc_smc(FSL_SIP_SRTC, FSL_SIP_SRTC_SET_PRETIME_WDOG,
- new_pretimeout * 1000, 0, 0, 0, 0, 0,
- &res);
+ (wdog->timeout - new_pretimeout) * 1000, 0, 0, 0,
+ 0, 0, &res);
+
+ dev_dbg(wdog->parent, "Set pretimeout to %d seconds\n", new_pretimeout);
return res.a0;
}
@@ -174,20 +188,33 @@ static int imx8_wdt_probe(struct platform_device *pdev)
wdt->parent = &pdev->dev;
watchdog_set_drvdata(wdt, NULL);
- err = watchdog_init_timeout(wdt, DEFAULT_TIMEOUT, &pdev->dev);
+ err = watchdog_init_timeout(wdt, timeout, &pdev->dev);
if (err) {
- dev_err(&pdev->dev, "Failed to init the wdog timeout:%d\n",
- err);
+ dev_err(&pdev->dev, "Failed to init watchdog timeout:%d\n", err);
return err;
}
err = watchdog_register_device(wdt);
if (err) {
- dev_err(&pdev->dev, "Failed to register watchdog device\n");
+ dev_err(&pdev->dev, "Failed to register watchdog device: %d\n", err);
return err;
}
- return register_scu_notifier(&imx8_wdt_notifier);
+ err = register_scu_notifier(&imx8_wdt_notifier);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register scu notifier: %d\n", err);
+ goto scu_err;
+ }
+
+ dev_info(&pdev->dev, "initialized (timeout=%d sec, nowayout=%d)\n",
+ timeout, nowayout);
+
+ return 0;
+
+scu_err:
+ watchdog_unregister_device(wdt);
+
+ return err;
}
static int imx8_wdt_remove(struct platform_device *pdev)
@@ -196,6 +223,8 @@ static int imx8_wdt_remove(struct platform_device *pdev)
imx8_wdt_stop(wdt);
+ unregister_scu_notifier(&imx8_wdt_notifier);
+
watchdog_unregister_device(wdt);
return 0;