summaryrefslogtreecommitdiff
path: root/drivers/watchdog/dw_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/dw_wdt.c')
-rw-r--r--drivers/watchdog/dw_wdt.c64
1 files changed, 22 insertions, 42 deletions
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index cd578843277e..c3fbb6068c52 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -218,7 +218,7 @@ static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s)
/*
* Set the new value in the watchdog. Some versions of dw_wdt
- * have have TOPINIT in the TIMEOUT_RANGE register (as per
+ * have TOPINIT in the TIMEOUT_RANGE register (as per
* CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we
* effectively get a pat of the watchdog right here.
*/
@@ -375,7 +375,6 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid)
return IRQ_HANDLED;
}
-#ifdef CONFIG_PM_SLEEP
static int dw_wdt_suspend(struct device *dev)
{
struct dw_wdt *dw_wdt = dev_get_drvdata(dev);
@@ -410,9 +409,8 @@ static int dw_wdt_resume(struct device *dev)
return 0;
}
-#endif /* CONFIG_PM_SLEEP */
-static SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume);
/*
* In case if DW WDT IP core is synthesized with fixed TOP feature disabled the
@@ -568,22 +566,16 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
* to the common timer/bus clocks configuration, in which the very
* first found clock supply both timer and APB signals.
*/
- dw_wdt->clk = devm_clk_get(dev, "tclk");
+ dw_wdt->clk = devm_clk_get_enabled(dev, "tclk");
if (IS_ERR(dw_wdt->clk)) {
- dw_wdt->clk = devm_clk_get(dev, NULL);
+ dw_wdt->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(dw_wdt->clk))
return PTR_ERR(dw_wdt->clk);
}
- ret = clk_prepare_enable(dw_wdt->clk);
- if (ret)
- return ret;
-
dw_wdt->rate = clk_get_rate(dw_wdt->clk);
- if (dw_wdt->rate == 0) {
- ret = -EINVAL;
- goto out_disable_clk;
- }
+ if (dw_wdt->rate == 0)
+ return -EINVAL;
/*
* Request APB clock if device is configured with async clocks mode.
@@ -592,21 +584,13 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
* so the pclk phandle reference is left optional. If it couldn't be
* found we consider the device configured in synchronous clocks mode.
*/
- dw_wdt->pclk = devm_clk_get_optional(dev, "pclk");
- if (IS_ERR(dw_wdt->pclk)) {
- ret = PTR_ERR(dw_wdt->pclk);
- goto out_disable_clk;
- }
-
- ret = clk_prepare_enable(dw_wdt->pclk);
- if (ret)
- goto out_disable_clk;
+ dw_wdt->pclk = devm_clk_get_optional_enabled(dev, "pclk");
+ if (IS_ERR(dw_wdt->pclk))
+ return PTR_ERR(dw_wdt->pclk);
dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
- if (IS_ERR(dw_wdt->rst)) {
- ret = PTR_ERR(dw_wdt->rst);
- goto out_disable_pclk;
- }
+ if (IS_ERR(dw_wdt->rst))
+ return PTR_ERR(dw_wdt->rst);
/* Enable normal reset without pre-timeout by default. */
dw_wdt_update_mode(dw_wdt, DW_WDT_RMOD_RESET);
@@ -623,12 +607,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
IRQF_SHARED | IRQF_TRIGGER_RISING,
pdev->name, dw_wdt);
if (ret)
- goto out_disable_pclk;
+ return ret;
dw_wdt->wdd.info = &dw_wdt_pt_ident;
} else {
if (ret == -EPROBE_DEFER)
- goto out_disable_pclk;
+ return ret;
dw_wdt->wdd.info = &dw_wdt_ident;
}
@@ -637,7 +621,7 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
ret = dw_wdt_init_timeouts(dw_wdt, dev);
if (ret)
- goto out_disable_clk;
+ goto out_assert_rst;
wdd = &dw_wdt->wdd;
wdd->ops = &dw_wdt_ops;
@@ -660,29 +644,29 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
} else {
wdd->timeout = DW_WDT_DEFAULT_SECONDS;
watchdog_init_timeout(wdd, 0, dev);
+ /* Limit timeout value to hardware constraints. */
+ dw_wdt_set_timeout(wdd, wdd->timeout);
}
platform_set_drvdata(pdev, dw_wdt);
watchdog_set_restart_priority(wdd, 128);
+ watchdog_stop_on_reboot(wdd);
ret = watchdog_register_device(wdd);
if (ret)
- goto out_disable_pclk;
+ goto out_assert_rst;
dw_wdt_dbgfs_init(dw_wdt);
return 0;
-out_disable_pclk:
- clk_disable_unprepare(dw_wdt->pclk);
-
-out_disable_clk:
- clk_disable_unprepare(dw_wdt->clk);
+out_assert_rst:
+ reset_control_assert(dw_wdt->rst);
return ret;
}
-static int dw_wdt_drv_remove(struct platform_device *pdev)
+static void dw_wdt_drv_remove(struct platform_device *pdev)
{
struct dw_wdt *dw_wdt = platform_get_drvdata(pdev);
@@ -690,10 +674,6 @@ static int dw_wdt_drv_remove(struct platform_device *pdev)
watchdog_unregister_device(&dw_wdt->wdd);
reset_control_assert(dw_wdt->rst);
- clk_disable_unprepare(dw_wdt->pclk);
- clk_disable_unprepare(dw_wdt->clk);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -710,7 +690,7 @@ static struct platform_driver dw_wdt_driver = {
.driver = {
.name = "dw_wdt",
.of_match_table = of_match_ptr(dw_wdt_of_match),
- .pm = &dw_wdt_pm_ops,
+ .pm = pm_sleep_ptr(&dw_wdt_pm_ops),
},
};