提交 a2b7ab45 编写于 作者: L Linus Torvalds

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
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.
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -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);
......
......@@ -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))
......
......@@ -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",
......
......@@ -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);
......
......@@ -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))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册