summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-25 10:19:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-25 10:19:17 -0700
commit1f93d2abf488c6a41bdd5e6caf80b559493eea8d (patch)
tree6c81f37167ee42fed575d48e2fcc6dc92ec1d79f /drivers/watchdog
parent48dd7cefa010b704eb2532a2883798fd6d703a0e (diff)
parent540be8b2add1a18a4289b11c1a9b6956eb846630 (diff)
downloadop-kernel-dev-1f93d2abf488c6a41bdd5e6caf80b559493eea8d.zip
op-kernel-dev-1f93d2abf488c6a41bdd5e6caf80b559493eea8d.tar.gz
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: - add support for Fintek F81865 Super-IO chip - add support for watchdogs (RWDT and SWDT) found on RCar Gen3 based SoCs from Renesas - octeon: Handle the FROZEN hot plug notifier actions - f71808e_wdt fixes and cleanups - some small improvements in code and documentation * git://www.linux-watchdog.org/linux-watchdog: MAINTAINERS: Add file patterns for watchdog device tree bindings Documentation: Add ebc-c384_wdt watchdog-parameters.txt entry watchdog: shwdt: Use setup_timer() watchdog: cpwd: Use setup_timer() arm64: defconfig: enable Renesas Watchdog Timer watchdog: renesas-wdt: add driver watchdog: remove error message when unable to allocate watchdog device watchdog: f71808e_wdt: Fix WDTMOUT_STS register read watchdog: f71808e_wdt: Fix typo watchdog: f71808e_wdt: Add F81865 support watchdog: sp5100_tco: properly check for new register layouts watchdog: core: Fix circular locking dependency watchdog: core: fix trivial typo in a comment watchdog: hpwdt: Adjust documentation to match latest kernel module parameters. watchdog: imx2_wdt: add external reset support via dt prop watchdog: octeon: Handle the FROZEN hot plug notifier actions. watchdog: qcom: Report reboot reason
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/cpwd.c4
-rw-r--r--drivers/watchdog/f71808e_wdt.c30
-rw-r--r--drivers/watchdog/imx2_wdt.c19
-rw-r--r--drivers/watchdog/jz4740_wdt.c4
-rw-r--r--drivers/watchdog/octeon-wdt-main.c2
-rw-r--r--drivers/watchdog/qcom-wdt.c7
-rw-r--r--drivers/watchdog/renesas_wdt.c213
-rw-r--r--drivers/watchdog/shwdt.c4
-rw-r--r--drivers/watchdog/sp5100_tco.c15
-rw-r--r--drivers/watchdog/watchdog_core.c2
-rw-r--r--drivers/watchdog/watchdog_dev.c1
13 files changed, 284 insertions, 26 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 5b45e27..b54f26c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -661,6 +661,14 @@ config ATLAS7_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called atlas7_wdt.
+config RENESAS_WDT
+ tristate "Renesas WDT Watchdog"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ select WATCHDOG_CORE
+ help
+ This driver adds watchdog support for the integrated watchdogs in the
+ Renesas R-Car and other SH-Mobile SoCs (usually named RWDT or SWDT).
+
# AVR32 Architecture
config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 9bde095..a46e7c1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
+obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 0200768..71ee079 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -611,9 +611,7 @@ static int cpwd_probe(struct platform_device *op)
}
if (p->broken) {
- init_timer(&cpwd_timer);
- cpwd_timer.function = cpwd_brokentimer;
- cpwd_timer.data = (unsigned long) p;
+ setup_timer(&cpwd_timer, cpwd_brokentimer, (unsigned long)p);
cpwd_timer.expires = WD_BTIMEOUT;
pr_info("PLD defect workaround enabled for model %s\n",
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index 016bd93..d4ba262 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -38,7 +38,7 @@
#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */
#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
-#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */
+#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
#define SIO_REG_LDSEL 0x07 /* Logical device select */
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
@@ -59,6 +59,7 @@
#define SIO_F71869A_ID 0x1007 /* Chipset ID */
#define SIO_F71882_ID 0x0541 /* Chipset ID */
#define SIO_F71889_ID 0x0723 /* Chipset ID */
+#define SIO_F81865_ID 0x0704 /* Chipset ID */
#define F71808FG_REG_WDO_CONF 0xf0
#define F71808FG_REG_WDT_CONF 0xf5
@@ -66,11 +67,14 @@
#define F71808FG_FLAG_WDOUT_EN 7
-#define F71808FG_FLAG_WDTMOUT_STS 5
+#define F71808FG_FLAG_WDTMOUT_STS 6
#define F71808FG_FLAG_WD_EN 5
#define F71808FG_FLAG_WD_PULSE 4
#define F71808FG_FLAG_WD_UNIT 3
+#define F81865_REG_WDO_CONF 0xfa
+#define F81865_FLAG_WDOUT_EN 0
+
/* Default values */
#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */
#define WATCHDOG_MAX_TIMEOUT (60 * 255)
@@ -112,7 +116,7 @@ module_param(start_withtimeout, uint, 0);
MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with"
" given initial timeout. Zero (default) disables this feature.");
-enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg };
+enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg, f81865 };
static const char *f71808e_names[] = {
"f71808fg",
@@ -121,6 +125,7 @@ static const char *f71808e_names[] = {
"f71869",
"f71882fg",
"f71889fg",
+ "f81865",
};
/* Super-I/O Function prototypes */
@@ -360,6 +365,11 @@ static int watchdog_start(void)
superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf);
break;
+ case f81865:
+ /* Set pin 70 to WDTRST# */
+ superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 5);
+ break;
+
default:
/*
* 'default' label to shut up the compiler and catch
@@ -371,8 +381,13 @@ static int watchdog_start(void)
superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0);
- superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF,
- F71808FG_FLAG_WDOUT_EN);
+
+ if (watchdog.type == f81865)
+ superio_set_bit(watchdog.sioaddr, F81865_REG_WDO_CONF,
+ F81865_FLAG_WDOUT_EN);
+ else
+ superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF,
+ F71808FG_FLAG_WDOUT_EN);
superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
F71808FG_FLAG_WD_EN);
@@ -655,7 +670,7 @@ static int __init watchdog_init(int sioaddr)
superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF);
- watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS;
+ watchdog.caused_reboot = wdt_conf & BIT(F71808FG_FLAG_WDTMOUT_STS);
superio_exit(sioaddr);
@@ -770,6 +785,9 @@ static int __init f71808e_find(int sioaddr)
/* Confirmed (by datasheet) not to have a watchdog. */
err = -ENODEV;
goto exit;
+ case SIO_F81865_ID:
+ watchdog.type = f81865;
+ break;
default:
pr_info("Unrecognized Fintek device: %04x\n",
(unsigned int)devid);
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 331aed8..62f346b 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -37,6 +37,8 @@
#define IMX2_WDT_WCR 0x00 /* Control Register */
#define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */
+#define IMX2_WDT_WCR_WDA (1 << 5) /* -> External Reset WDOG_B */
+#define IMX2_WDT_WCR_SRS (1 << 4) /* -> Software Reset Signal */
#define IMX2_WDT_WCR_WRE (1 << 3) /* -> WDOG Reset Enable */
#define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */
#define IMX2_WDT_WCR_WDZST (1 << 0) /* -> Watchdog timer Suspend */
@@ -59,6 +61,7 @@ struct imx2_wdt_device {
struct clk *clk;
struct regmap *regmap;
struct watchdog_device wdog;
+ bool ext_reset;
};
static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -83,6 +86,12 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
unsigned int wcr_enable = IMX2_WDT_WCR_WDE;
+ /* Use internal reset or external - not both */
+ if (wdev->ext_reset)
+ wcr_enable |= IMX2_WDT_WCR_SRS; /* do not assert int reset */
+ else
+ wcr_enable |= IMX2_WDT_WCR_WDA; /* do not assert ext-reset */
+
/* Assert SRS signal */
regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
/*
@@ -112,8 +121,12 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog)
val |= IMX2_WDT_WCR_WDZST;
/* Strip the old watchdog Time-Out value */
val &= ~IMX2_WDT_WCR_WT;
- /* Generate reset if WDOG times out */
- val &= ~IMX2_WDT_WCR_WRE;
+ /* Generate internal chip-level reset if WDOG times out */
+ if (!wdev->ext_reset)
+ val &= ~IMX2_WDT_WCR_WRE;
+ /* Or if external-reset assert WDOG_B reset only on time-out */
+ else
+ val |= IMX2_WDT_WCR_WRE;
/* Keep Watchdog Disabled */
val &= ~IMX2_WDT_WCR_WDE;
/* Set the watchdog's Time-Out value */
@@ -230,6 +243,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val);
wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
+ wdev->ext_reset = of_property_read_bool(pdev->dev.of_node,
+ "fsl,ext-reset-output");
wdog->timeout = clamp_t(unsigned, timeout, 1, IMX2_WDT_MAX_TIME);
if (wdog->timeout != timeout)
dev_warn(&pdev->dev, "Initial timeout out of range! Clamped from %u to %u\n",
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 6a7d5c3..c8d51dd 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -160,10 +160,8 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct jz4740_wdt_drvdata),
GFP_KERNEL);
- if (!drvdata) {
- dev_err(&pdev->dev, "Unable to alloacate watchdog device\n");
+ if (!drvdata)
return -ENOMEM;
- }
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
heartbeat = DEFAULT_HEARTBEAT;
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 14521c8..b55981f 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -431,7 +431,7 @@ static int octeon_wdt_cpu_callback(struct notifier_block *nfb,
{
unsigned int cpu = (unsigned long)hcpu;
- switch (action) {
+ switch (action & ~CPU_TASKS_FROZEN) {
case CPU_DOWN_PREPARE:
octeon_wdt_disable_interrupt(cpu);
break;
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
index 20563cc..a043fa4 100644
--- a/drivers/watchdog/qcom-wdt.c
+++ b/drivers/watchdog/qcom-wdt.c
@@ -21,6 +21,7 @@
#define WDT_RST 0x38
#define WDT_EN 0x40
+#define WDT_STS 0x44
#define WDT_BITE_TIME 0x5C
struct qcom_wdt {
@@ -108,7 +109,8 @@ static const struct watchdog_ops qcom_wdt_ops = {
static const struct watchdog_info qcom_wdt_info = {
.options = WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
- | WDIOF_SETTIMEOUT,
+ | WDIOF_SETTIMEOUT
+ | WDIOF_CARDRESET,
.identity = KBUILD_MODNAME,
};
@@ -171,6 +173,9 @@ static int qcom_wdt_probe(struct platform_device *pdev)
wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
wdt->wdd.parent = &pdev->dev;
+ if (readl(wdt->base + WDT_STS) & 1)
+ wdt->wdd.bootstatus = WDIOF_CARDRESET;
+
/*
* If 'timeout-sec' unspecified in devicetree, assume a 30 second
* default, unless the max timeout is less than 30 seconds, then use
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
new file mode 100644
index 0000000..cf61c92
--- /dev/null
+++ b/drivers/watchdog/renesas_wdt.c
@@ -0,0 +1,213 @@
+/*
+ * Watchdog driver for Renesas WDT watchdog
+ *
+ * Copyright (C) 2015-16 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
+ * Copyright (C) 2015-16 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/watchdog.h>
+
+#define RWTCNT 0
+#define RWTCSRA 4
+#define RWTCSRA_WOVF BIT(4)
+#define RWTCSRA_WRFLG BIT(5)
+#define RWTCSRA_TME BIT(7)
+
+#define RWDT_DEFAULT_TIMEOUT 60U
+
+static const unsigned int clk_divs[] = { 1, 4, 16, 32, 64, 128, 1024 };
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct rwdt_priv {
+ void __iomem *base;
+ struct watchdog_device wdev;
+ struct clk *clk;
+ unsigned int clks_per_sec;
+ u8 cks;
+};
+
+static void rwdt_write(struct rwdt_priv *priv, u32 val, unsigned int reg)
+{
+ if (reg == RWTCNT)
+ val |= 0x5a5a0000;
+ else
+ val |= 0xa5a5a500;
+
+ writel_relaxed(val, priv->base + reg);
+}
+
+static int rwdt_init_timeout(struct watchdog_device *wdev)
+{
+ struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
+
+ rwdt_write(priv, 65536 - wdev->timeout * priv->clks_per_sec, RWTCNT);
+
+ return 0;
+}
+
+static int rwdt_start(struct watchdog_device *wdev)
+{
+ struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
+
+ clk_prepare_enable(priv->clk);
+
+ rwdt_write(priv, priv->cks, RWTCSRA);
+ rwdt_init_timeout(wdev);
+
+ while (readb_relaxed(priv->base + RWTCSRA) & RWTCSRA_WRFLG)
+ cpu_relax();
+
+ rwdt_write(priv, priv->cks | RWTCSRA_TME, RWTCSRA);
+
+ return 0;
+}
+
+static int rwdt_stop(struct watchdog_device *wdev)
+{
+ struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
+
+ rwdt_write(priv, priv->cks, RWTCSRA);
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static unsigned int rwdt_get_timeleft(struct watchdog_device *wdev)
+{
+ struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
+ u16 val = readw_relaxed(priv->base + RWTCNT);
+
+ return DIV_ROUND_CLOSEST(65536 - val, priv->clks_per_sec);
+}
+
+static const struct watchdog_info rwdt_ident = {
+ .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+ .identity = "Renesas WDT Watchdog",
+};
+
+static const struct watchdog_ops rwdt_ops = {
+ .owner = THIS_MODULE,
+ .start = rwdt_start,
+ .stop = rwdt_stop,
+ .ping = rwdt_init_timeout,
+ .get_timeleft = rwdt_get_timeleft,
+};
+
+static int rwdt_probe(struct platform_device *pdev)
+{
+ struct rwdt_priv *priv;
+ struct resource *res;
+ unsigned long rate;
+ unsigned int clks_per_sec;
+ int ret, i;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ rate = clk_get_rate(priv->clk);
+ if (!rate)
+ return -ENOENT;
+
+ for (i = ARRAY_SIZE(clk_divs) - 1; i >= 0; i--) {
+ clks_per_sec = DIV_ROUND_UP(rate, clk_divs[i]);
+ if (clks_per_sec) {
+ priv->clks_per_sec = clks_per_sec;
+ priv->cks = i;
+ break;
+ }
+ }
+
+ if (!clks_per_sec) {
+ dev_err(&pdev->dev, "Can't find suitable clock divider\n");
+ return -ERANGE;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ priv->wdev.info = &rwdt_ident,
+ priv->wdev.ops = &rwdt_ops,
+ priv->wdev.parent = &pdev->dev;
+ priv->wdev.min_timeout = 1;
+ priv->wdev.max_timeout = 65536 / clks_per_sec;
+ priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT);
+
+ platform_set_drvdata(pdev, priv);
+ watchdog_set_drvdata(&priv->wdev, priv);
+ watchdog_set_nowayout(&priv->wdev, nowayout);
+
+ /* This overrides the default timeout only if DT configuration was found */
+ ret = watchdog_init_timeout(&priv->wdev, 0, &pdev->dev);
+ if (ret)
+ dev_warn(&pdev->dev, "Specified timeout value invalid, using default\n");
+
+ ret = watchdog_register_device(&priv->wdev);
+ if (ret < 0) {
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rwdt_remove(struct platform_device *pdev)
+{
+ struct rwdt_priv *priv = platform_get_drvdata(pdev);
+
+ watchdog_unregister_device(&priv->wdev);
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+/*
+ * This driver does also fit for R-Car Gen2 (r8a779[0-4]) WDT. However, for SMP
+ * to work there, one also needs a RESET (RST) driver which does not exist yet
+ * due to HW issues. This needs to be solved before adding compatibles here.
+ */
+static const struct of_device_id rwdt_ids[] = {
+ { .compatible = "renesas,rcar-gen3-wdt", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rwdt_ids);
+
+static struct platform_driver rwdt_driver = {
+ .driver = {
+ .name = "renesas_wdt",
+ .of_match_table = rwdt_ids,
+ },
+ .probe = rwdt_probe,
+ .remove = rwdt_remove,
+};
+module_platform_driver(rwdt_driver);
+
+MODULE_DESCRIPTION("Renesas WDT Watchdog Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index f908121..517a733 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -275,9 +275,7 @@ static int sh_wdt_probe(struct platform_device *pdev)
return rc;
}
- init_timer(&wdt->timer);
- wdt->timer.function = sh_wdt_ping;
- wdt->timer.data = (unsigned long)wdt;
+ setup_timer(&wdt->timer, sh_wdt_ping, (unsigned long)wdt);
wdt->timer.expires = next_ping_period(clock_division_ratio);
dev_info(&pdev->dev, "initialized.\n");
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 6467b91..028618c 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -73,6 +73,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
/*
* Some TCO specific functions
*/
+
+static bool tco_has_sp5100_reg_layout(struct pci_dev *dev)
+{
+ return dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
+ dev->revision < 0x40;
+}
+
static void tco_timer_start(void)
{
u32 val;
@@ -129,7 +136,7 @@ static void tco_timer_enable(void)
{
int val;
- if (sp5100_tco_pci->revision >= 0x40) {
+ if (!tco_has_sp5100_reg_layout(sp5100_tco_pci)) {
/* For SB800 or later */
/* Set the Watchdog timer resolution to 1 sec */
outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG);
@@ -342,8 +349,7 @@ static unsigned char sp5100_tco_setupdevice(void)
/*
* Determine type of southbridge chipset.
*/
- if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
- sp5100_tco_pci->revision < 0x40) {
+ if (tco_has_sp5100_reg_layout(sp5100_tco_pci)) {
dev_name = SP5100_DEVNAME;
index_reg = SP5100_IO_PM_INDEX_REG;
data_reg = SP5100_IO_PM_DATA_REG;
@@ -388,8 +394,7 @@ static unsigned char sp5100_tco_setupdevice(void)
* Secondly, Find the watchdog timer MMIO address
* from SBResource_MMIO register.
*/
- if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
- sp5100_tco_pci->revision < 0x40) {
+ if (tco_has_sp5100_reg_layout(sp5100_tco_pci)) {
/* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
pci_read_config_dword(sp5100_tco_pci,
SP5100_SB_RESOURCE_MMIO_BASE, &val);
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 981a668..7c3ba58 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -104,7 +104,7 @@ static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
* timeout module parameter (if it is valid value) or the timeout-sec property
* (only if it is a valid value and the timeout_parm is out of bounds).
* If none of them are valid then we keep the old value (which should normally
- * be the default timeout value.
+ * be the default timeout value).
*
* A zero is returned on success and -EINVAL for failure.
*/
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index e2c5abb..3595cff 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -736,7 +736,6 @@ static int watchdog_release(struct inode *inode, struct file *file)
watchdog_ping(wdd);
}
- cancel_delayed_work_sync(&wd_data->work);
watchdog_update_worker(wdd);
/* make sure that /dev/watchdog can be re-opened */
OpenPOWER on IntegriCloud