diff options
Diffstat (limited to 'drivers/watchdog/imx8_wdt.c')
-rw-r--r-- | drivers/watchdog/imx8_wdt.c | 45 |
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; |