Skip to content

Commit

Permalink
Merge tag 'linux-watchdog-4.18-rc1' of git://www.linux-watchdog.org/l…
Browse files Browse the repository at this point in the history
…inux-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
  • Loading branch information
Linus Torvalds committed Jun 11, 2018
2 parents e16c479 + 16a7eec commit a2b7ab4
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 60 deletions.
23 changes: 16 additions & 7 deletions Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
Renesas Watchdog Timer (WDT) Controller

Required properties:
- compatible : Should be "renesas,<soctype>-wdt", and
"renesas,rcar-gen3-wdt" or "renesas,rza-wdt" as fallback.
- compatible : Must be "renesas,<soctype>-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.
Expand Down
6 changes: 2 additions & 4 deletions drivers/watchdog/cadence_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
10 changes: 0 additions & 10 deletions drivers/watchdog/da9062_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down
73 changes: 62 additions & 11 deletions drivers/watchdog/da9063_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/watchdog/hpwdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 0 additions & 18 deletions drivers/watchdog/mena21_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ enum a21_wdt_gpios {

struct a21_wdt_drv {
struct watchdog_device wdt;
struct mutex lock;
unsigned gpios[NUM_GPIOS];
};

Expand All @@ -55,40 +54,28 @@ 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;
}

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;
}

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;
}

Expand All @@ -108,17 +95,13 @@ 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
gpio_set_value(drv->gpios[GPIO_WD_FAST], 0);

wdt->timeout = timeout;

mutex_unlock(&drv->lock);

return 0;
}

Expand Down Expand Up @@ -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);
Expand Down
6 changes: 2 additions & 4 deletions drivers/watchdog/of_xilinx_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion drivers/watchdog/renesas_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
14 changes: 14 additions & 0 deletions drivers/watchdog/sp805_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 2 additions & 4 deletions drivers/watchdog/wdat_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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))
Expand Down

0 comments on commit a2b7ab4

Please sign in to comment.