diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt index 74b2f03c151553f5ce78fd89373f07b09549b2c8..f24d802b8056f6c6a726a758561ef471cbec4933 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt @@ -1,18 +1,27 @@ Renesas Watchdog Timer (WDT) Controller Required properties: -- compatible : Should be "renesas,-wdt", and - "renesas,rcar-gen3-wdt" or "renesas,rza-wdt" as fallback. + - compatible : Must be "renesas,-wdt", followed by a generic + fallback compatible string when compatible with the generic + version. Examples with soctypes are: - - "renesas,r7s72100-wdt" (RZ/A1) + - "renesas,r8a7743-wdt" (RZ/G1M) + - "renesas,r8a7745-wdt" (RZ/G1E) + - "renesas,r8a7790-wdt" (R-Car H2) + - "renesas,r8a7791-wdt" (R-Car M2-W) + - "renesas,r8a7792-wdt" (R-Car V2H) + - "renesas,r8a7793-wdt" (R-Car M2-N) + - "renesas,r8a7794-wdt" (R-Car E2) - "renesas,r8a7795-wdt" (R-Car H3) - "renesas,r8a7796-wdt" (R-Car M3-W) + - "renesas,r8a77965-wdt" (R-Car M3-N) - "renesas,r8a77970-wdt" (R-Car V3M) - "renesas,r8a77995-wdt" (R-Car D3) - - When compatible with the generic version, nodes must list the SoC-specific - version corresponding to the platform first, followed by the generic - version. + - "renesas,r7s72100-wdt" (RZ/A1) + The generic compatible string must be: + - "renesas,rza-wdt" for RZ/A + - "renesas,rcar-gen2-wdt" for R-Car Gen2 and RZ/G + - "renesas,rcar-gen3-wdt" for R-Car Gen3 - reg : Should contain WDT registers location and length - clocks : the clock feeding the watchdog timer. diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index 3ec1f418837d1af8f3e0eb325e7198ce7ae39939..c3924356d1731153847b82147b58f70f76a5a382 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 a001782bbfdb1a066a5528a36d529f85ec051562..fe169d8e1fb2f2c75b4dca8d8af6e83dd462123b 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 b17ac1bb1f28eda4525093664a846bc2317c4ca5..384dca16af8b36bf2e51f8ed6bfeb5ca82e30e06 100644 --- a/drivers/watchdog/da9063_wdt.c +++ b/drivers/watchdog/da9063_wdt.c @@ -45,8 +45,46 @@ 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); } @@ -54,11 +92,9 @@ static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int 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 a43ab2cecca2748d23e3d064ca55390ddffe386f..9dc62a4614512fb8faeb2e937bc085d2bec16f3c 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 25d5d2b8cfbe98b9b1654eaacae855fdc79efa35..0be7f50e8ff940d441feac339f8f106d805c91a3 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 4acbe05e27bb809923dcab3512753624ad6c6c6c..d3f7eb0466782f4b386895cf509c54213a31819d 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 514db5cc159511254f62c2eb86714a2ecddb978f..88d81feba4e60087fe52b85b7438b83f0dbc07a8 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 03805bc5d67ad515769b29be60bb722355fa0da9..9849db0743a75cd5739294eb71fa2af1aedb467c 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 0da9943d405f8ff89efc87a0cf6df5ff43df9d6f..56ad19608a9bed0ae43ffaa87e59c71ee85d104e 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))