diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-11 12:26:07 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-11 12:26:07 -0700 |
commit | a2b7ab45b8905b9c1813b0212e82a39d5c081c8a (patch) | |
tree | baa08d60c773c39ff12062df6a6bd887c5398649 /drivers | |
parent | e16c4790de39dc861b749674c2a9319507f6f64f (diff) | |
parent | 16a7eec2fcd020c73cf0ca38bf774775167d22eb (diff) |
Merge tag 'linux-watchdog-4.18-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
"Core:
- simplify getting .drvdata
renesas_wdt:
- add support for the R8A77965 WDT and R-Car Gen2
- remove R-Car M2-W ES2.x from blacklist
sp805:
- add restart handler
hpwdt:
- claim NMIs generated by iLO5
mena21_wdt:
- drop unnecessary mutex lock
da9062 & da9063:
- fixes and general cleanups"
* tag 'linux-watchdog-4.18-rc1' of git://www.linux-watchdog.org/linux-watchdog:
watchdog: da9063: remove duplicated timeout_to_sel calls
watchdog: da9063: rename helper function to avoid misunderstandings
watchdog: da9062: remove unused code
watchdog: da9063: Fix timeout handling during probe
watchdog: da9063: Fix updating timeout value
watchdog: da9063: Fix setting/changing timeout
dt-bindings: watchdog: renesas-wdt: Add R-Car Gen2 support
watchdog: mena21_wdt: Drop unnecessary mutex lock
watchdog: renesas-wdt: Add support for the R8A77965 WDT
watchdog: hpwdt: Claim NMIs generated by iLO5
watchdog: sp805: add restart handler
watchdog: renesas-wdt: Remove R-Car M2-W ES2.x from blacklist
watchdog: simplify getting .drvdata
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/watchdog/cadence_wdt.c | 6 | ||||
-rw-r--r-- | drivers/watchdog/da9062_wdt.c | 10 | ||||
-rw-r--r-- | drivers/watchdog/da9063_wdt.c | 73 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/mena21_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/of_xilinx_wdt.c | 6 | ||||
-rw-r--r-- | drivers/watchdog/renesas_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 14 | ||||
-rw-r--r-- | drivers/watchdog/wdat_wdt.c | 6 |
9 files changed, 84 insertions, 53 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/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)) |