summaryrefslogtreecommitdiff
path: root/drivers/watchdog/mt7621_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/mt7621_wdt.c')
-rw-r--r--drivers/watchdog/mt7621_wdt.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c
index db38f8017218..5c4a764717c4 100644
--- a/drivers/watchdog/mt7621_wdt.c
+++ b/drivers/watchdog/mt7621_wdt.c
@@ -105,6 +105,11 @@ static int mt7621_wdt_bootcause(void)
return 0;
}
+static int mt7621_wdt_is_running(struct watchdog_device *w)
+{
+ return !!(rt_wdt_r32(TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE);
+}
+
static const struct watchdog_info mt7621_wdt_info = {
.identity = "Mediatek Watchdog",
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
@@ -128,7 +133,6 @@ static struct watchdog_device mt7621_wdt_dev = {
static int mt7621_wdt_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mt7621_wdt_base = devm_ioremap_resource(&pdev->dev, res);
@@ -144,17 +148,22 @@ static int mt7621_wdt_probe(struct platform_device *pdev)
watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout,
&pdev->dev);
watchdog_set_nowayout(&mt7621_wdt_dev, nowayout);
-
- ret = watchdog_register_device(&mt7621_wdt_dev);
-
- return 0;
-}
-
-static int mt7621_wdt_remove(struct platform_device *pdev)
-{
- watchdog_unregister_device(&mt7621_wdt_dev);
-
- return 0;
+ if (mt7621_wdt_is_running(&mt7621_wdt_dev)) {
+ /*
+ * Make sure to apply timeout from watchdog core, taking
+ * the prescaler of this driver here into account (the
+ * boot loader might be using a different prescaler).
+ *
+ * To avoid spurious resets because of different scaling,
+ * we first disable the watchdog, set the new prescaler
+ * and timeout, and then re-enable the watchdog.
+ */
+ mt7621_wdt_stop(&mt7621_wdt_dev);
+ mt7621_wdt_start(&mt7621_wdt_dev);
+ set_bit(WDOG_HW_RUNNING, &mt7621_wdt_dev.status);
+ }
+
+ return devm_watchdog_register_device(&pdev->dev, &mt7621_wdt_dev);
}
static void mt7621_wdt_shutdown(struct platform_device *pdev)
@@ -170,7 +179,6 @@ MODULE_DEVICE_TABLE(of, mt7621_wdt_match);
static struct platform_driver mt7621_wdt_driver = {
.probe = mt7621_wdt_probe,
- .remove = mt7621_wdt_remove,
.shutdown = mt7621_wdt_shutdown,
.driver = {
.name = KBUILD_MODNAME,