summaryrefslogtreecommitdiff
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/cadence_wdt.c6
-rw-r--r--drivers/watchdog/da9062_wdt.c10
-rw-r--r--drivers/watchdog/da9063_wdt.c73
-rw-r--r--drivers/watchdog/hpwdt.c2
-rw-r--r--drivers/watchdog/jz4740_wdt.c42
-rw-r--r--drivers/watchdog/mena21_wdt.c18
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c6
-rw-r--r--drivers/watchdog/renesas_wdt.c2
-rw-r--r--drivers/watchdog/sp805_wdt.c14
-rw-r--r--drivers/watchdog/wdat_wdt.c6
10 files changed, 100 insertions, 79 deletions
diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c
index 3ec1f418837d..c3924356d173 100644
--- a/drivers/watchdog/cadence_wdt.c
+++ b/drivers/watchdog/cadence_wdt.c
@@ -418,8 +418,7 @@ static void cdns_wdt_shutdown(struct platform_device *pdev)
*/
static int __maybe_unused cdns_wdt_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+ struct cdns_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->cdns_wdt_device)) {
cdns_wdt_stop(&wdt->cdns_wdt_device);
@@ -438,8 +437,7 @@ static int __maybe_unused cdns_wdt_suspend(struct device *dev)
static int __maybe_unused cdns_wdt_resume(struct device *dev)
{
int ret;
- struct platform_device *pdev = to_platform_device(dev);
- struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+ struct cdns_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->cdns_wdt_device)) {
ret = clk_prepare_enable(wdt->clk);
diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c
index a001782bbfdb..fe169d8e1fb2 100644
--- a/drivers/watchdog/da9062_wdt.c
+++ b/drivers/watchdog/da9062_wdt.c
@@ -30,14 +30,8 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
struct da9062_watchdog {
struct da9062 *hw;
struct watchdog_device wdtdev;
- unsigned long j_time_stamp;
};
-static void da9062_set_window_start(struct da9062_watchdog *wdt)
-{
- wdt->j_time_stamp = jiffies;
-}
-
static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
{
unsigned int i;
@@ -59,8 +53,6 @@ static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
DA9062AA_WATCHDOG_MASK,
DA9062AA_WATCHDOG_MASK);
- da9062_set_window_start(wdt);
-
return ret;
}
@@ -232,8 +224,6 @@ static int da9062_wdt_probe(struct platform_device *pdev)
return ret;
}
- da9062_set_window_start(wdt);
-
return da9062_wdt_ping(&wdt->wdtdev);
}
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index b17ac1bb1f28..384dca16af8b 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -45,20 +45,56 @@ static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
return DA9063_TWDSCALE_MAX;
}
-static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
+/*
+ * Return 0 if watchdog is disabled, else non zero.
+ */
+static unsigned int da9063_wdt_is_running(struct da9063 *da9063)
+{
+ unsigned int val;
+
+ regmap_read(da9063->regmap, DA9063_REG_CONTROL_D, &val);
+
+ return val & DA9063_TWDSCALE_MASK;
+}
+
+static int da9063_wdt_disable_timer(struct da9063 *da9063)
{
return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
+ DA9063_TWDSCALE_MASK,
+ DA9063_TWDSCALE_DISABLE);
+}
+
+static int
+da9063_wdt_update_timeout(struct da9063 *da9063, unsigned int timeout)
+{
+ unsigned int regval;
+ int ret;
+
+ /*
+ * The watchdog triggers a reboot if a timeout value is already
+ * programmed because the timeout value combines two functions
+ * in one: indicating the counter limit and starting the watchdog.
+ * The watchdog must be disabled to be able to change the timeout
+ * value if the watchdog is already running. Then we can set the
+ * new timeout value which enables the watchdog again.
+ */
+ ret = da9063_wdt_disable_timer(da9063);
+ if (ret)
+ return ret;
+
+ usleep_range(150, 300);
+ regval = da9063_wdt_timeout_to_sel(timeout);
+
+ return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
DA9063_TWDSCALE_MASK, regval);
}
static int da9063_wdt_start(struct watchdog_device *wdd)
{
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- unsigned int selector;
int ret;
- selector = da9063_wdt_timeout_to_sel(wdd->timeout);
- ret = _da9063_wdt_set_timeout(da9063, selector);
+ ret = da9063_wdt_update_timeout(da9063, wdd->timeout);
if (ret)
dev_err(da9063->dev, "Watchdog failed to start (err = %d)\n",
ret);
@@ -71,8 +107,7 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
int ret;
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
- DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
+ ret = da9063_wdt_disable_timer(da9063);
if (ret)
dev_alert(da9063->dev, "Watchdog failed to stop (err = %d)\n",
ret);
@@ -98,16 +133,26 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- unsigned int selector;
- int ret;
+ int ret = 0;
+
+ /*
+ * There are two cases when a set_timeout() will be called:
+ * 1. The watchdog is off and someone wants to set the timeout for the
+ * further use.
+ * 2. The watchdog is already running and a new timeout value should be
+ * set.
+ *
+ * The watchdog can't store a timeout value not equal zero without
+ * enabling the watchdog, so the timeout must be buffered by the driver.
+ */
+ if (watchdog_active(wdd))
+ ret = da9063_wdt_update_timeout(da9063, timeout);
- selector = da9063_wdt_timeout_to_sel(timeout);
- ret = _da9063_wdt_set_timeout(da9063, selector);
if (ret)
dev_err(da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
ret);
else
- wdd->timeout = wdt_timeout[selector];
+ wdd->timeout = wdt_timeout[da9063_wdt_timeout_to_sel(timeout)];
return ret;
}
@@ -171,6 +216,12 @@ static int da9063_wdt_probe(struct platform_device *pdev)
watchdog_set_drvdata(wdd, da9063);
+ /* Change the timeout to the default value if the watchdog is running */
+ if (da9063_wdt_is_running(da9063)) {
+ da9063_wdt_update_timeout(da9063, DA9063_WDG_TIMEOUT);
+ set_bit(WDOG_HW_RUNNING, &wdd->status);
+ }
+
return devm_watchdog_register_device(&pdev->dev, wdd);
}
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a43ab2cecca2..9dc62a461451 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -159,7 +159,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
"3. OA Forward Progress Log\n"
"4. iLO Event Log";
- if (ilo5 && ulReason == NMI_UNKNOWN && mynmi)
+ if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi)
return NMI_DONE;
if (ilo5 && !pretimeout)
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index aafbeb96561b..ec4d99a830ba 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -124,12 +124,20 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev)
{
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
- jz4740_timer_disable_watchdog();
writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+ jz4740_timer_disable_watchdog();
return 0;
}
+static int jz4740_wdt_restart(struct watchdog_device *wdt_dev,
+ unsigned long action, void *data)
+{
+ wdt_dev->timeout = 0;
+ jz4740_wdt_start(wdt_dev);
+ return 0;
+}
+
static const struct watchdog_info jz4740_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "jz4740 Watchdog",
@@ -141,6 +149,7 @@ static const struct watchdog_ops jz4740_wdt_ops = {
.stop = jz4740_wdt_stop,
.ping = jz4740_wdt_ping,
.set_timeout = jz4740_wdt_set_timeout,
+ .restart = jz4740_wdt_restart,
};
#ifdef CONFIG_OF
@@ -179,45 +188,26 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drvdata->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(drvdata->base)) {
- ret = PTR_ERR(drvdata->base);
- goto err_out;
- }
+ if (IS_ERR(drvdata->base))
+ return PTR_ERR(drvdata->base);
- drvdata->rtc_clk = clk_get(&pdev->dev, "rtc");
+ drvdata->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
if (IS_ERR(drvdata->rtc_clk)) {
dev_err(&pdev->dev, "cannot find RTC clock\n");
- ret = PTR_ERR(drvdata->rtc_clk);
- goto err_out;
+ return PTR_ERR(drvdata->rtc_clk);
}
- ret = watchdog_register_device(&drvdata->wdt);
+ ret = devm_watchdog_register_device(&pdev->dev, &drvdata->wdt);
if (ret < 0)
- goto err_disable_clk;
+ return ret;
platform_set_drvdata(pdev, drvdata);
- return 0;
-
-err_disable_clk:
- clk_put(drvdata->rtc_clk);
-err_out:
- return ret;
-}
-
-static int jz4740_wdt_remove(struct platform_device *pdev)
-{
- struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
-
- jz4740_wdt_stop(&drvdata->wdt);
- watchdog_unregister_device(&drvdata->wdt);
- clk_put(drvdata->rtc_clk);
return 0;
}
static struct platform_driver jz4740_wdt_driver = {
.probe = jz4740_wdt_probe,
- .remove = jz4740_wdt_remove,
.driver = {
.name = "jz4740-wdt",
.of_match_table = of_match_ptr(jz4740_wdt_of_matches),
diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c
index 25d5d2b8cfbe..0be7f50e8ff9 100644
--- a/drivers/watchdog/mena21_wdt.c
+++ b/drivers/watchdog/mena21_wdt.c
@@ -31,7 +31,6 @@ enum a21_wdt_gpios {
struct a21_wdt_drv {
struct watchdog_device wdt;
- struct mutex lock;
unsigned gpios[NUM_GPIOS];
};
@@ -55,12 +54,8 @@ static int a21_wdt_start(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_ENAB], 1);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -68,12 +63,8 @@ static int a21_wdt_stop(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_ENAB], 0);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -81,14 +72,10 @@ static int a21_wdt_ping(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_TRIG], 0);
ndelay(10);
gpio_set_value(drv->gpios[GPIO_WD_TRIG], 1);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -108,8 +95,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
return -EINVAL;
}
- mutex_lock(&drv->lock);
-
if (timeout == 1)
gpio_set_value(drv->gpios[GPIO_WD_FAST], 1);
else
@@ -117,8 +102,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
wdt->timeout = timeout;
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -191,7 +174,6 @@ static int a21_wdt_probe(struct platform_device *pdev)
return ret;
}
- mutex_init(&drv->lock);
watchdog_init_timeout(&a21_wdt, 30, &pdev->dev);
watchdog_set_nowayout(&a21_wdt, nowayout);
watchdog_set_drvdata(&a21_wdt, drv);
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 4acbe05e27bb..d3f7eb046678 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -268,8 +268,7 @@ static int xwdt_remove(struct platform_device *pdev)
*/
static int __maybe_unused xwdt_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xwdt_device *xdev = platform_get_drvdata(pdev);
+ struct xwdt_device *xdev = dev_get_drvdata(dev);
if (watchdog_active(&xdev->xilinx_wdt_wdd))
xilinx_wdt_stop(&xdev->xilinx_wdt_wdd);
@@ -285,8 +284,7 @@ static int __maybe_unused xwdt_suspend(struct device *dev)
*/
static int __maybe_unused xwdt_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xwdt_device *xdev = platform_get_drvdata(pdev);
+ struct xwdt_device *xdev = dev_get_drvdata(dev);
int ret = 0;
if (watchdog_active(&xdev->xilinx_wdt_wdd))
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index 514db5cc1595..88d81feba4e6 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -146,7 +146,7 @@ static const struct soc_device_attribute rwdt_quirks_match[] = {
.data = (void *)1, /* needs single CPU */
}, {
.soc_id = "r8a7791",
- .revision = "ES[12].*",
+ .revision = "ES1.*",
.data = (void *)1, /* needs single CPU */
}, {
.soc_id = "r8a7792",
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 03805bc5d67a..9849db0743a7 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -121,6 +121,18 @@ static unsigned int wdt_timeleft(struct watchdog_device *wdd)
return div_u64(load, rate);
}
+static int
+wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
+{
+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ writel_relaxed(0, wdt->base + WDTCONTROL);
+ writel_relaxed(0, wdt->base + WDTLOAD);
+ writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
+
+ return 0;
+}
+
static int wdt_config(struct watchdog_device *wdd, bool ping)
{
struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
@@ -197,6 +209,7 @@ static const struct watchdog_ops wdt_ops = {
.ping = wdt_ping,
.set_timeout = wdt_setload,
.get_timeleft = wdt_timeleft,
+ .restart = wdt_restart,
};
static int
@@ -230,6 +243,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&wdt->lock);
watchdog_set_nowayout(&wdt->wdd, nowayout);
watchdog_set_drvdata(&wdt->wdd, wdt);
+ watchdog_set_restart_priority(&wdt->wdd, 128);
wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT);
ret = watchdog_register_device(&wdt->wdd);
diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c
index 0da9943d405f..56ad19608a9b 100644
--- a/drivers/watchdog/wdat_wdt.c
+++ b/drivers/watchdog/wdat_wdt.c
@@ -447,8 +447,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int wdat_wdt_suspend_noirq(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+ struct wdat_wdt *wdat = dev_get_drvdata(dev);
int ret;
if (!watchdog_active(&wdat->wdd))
@@ -475,8 +474,7 @@ static int wdat_wdt_suspend_noirq(struct device *dev)
static int wdat_wdt_resume_noirq(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+ struct wdat_wdt *wdat = dev_get_drvdata(dev);
int ret;
if (!watchdog_active(&wdat->wdd))