2013-08-17 20:58:54

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 0/8] watchdog: w83627hf: Convert to watchdog infrastructure

Convert to watchdog infrastructure, cleanup, add support for additional
chips, and merge with W83697HF and W83697UG watchdog drivers.

Tested with W83627UHG, NCT6775, NCT6776.

Original idea was to prepare the driver for use as a client to an MFD driver,
but I found that requesting memory with request_muxed_region works just as well
and has less impact. v2 includes the knowledge gained from converting the
driver to an MFD client driver, but without the actual conversion.

With this set of patches, the watchdog driver for the supported chips
can be used together with the hwmon driver for those chips.

Wim, please consider merging this set of patches into 3.12. I need
both watchdog and hwmon driver running, which means I have to run
patched kernels which gets a bit annoying over time. If you don't
like the idea of merging the drivers for W83697HF and W83697UG
into this one, please drop patch 6 and 7 from the series.

v3: Reset watchdog trigger on startup
Rebased to v3.11-rc5

v2: Tested with W83627UHG
Retain timeout module parameter; use watchdog_init_timeout to set it
Eliminate some cosmetic changes
Drop spinlock.h include
Keep "initialized" message
Don't try to configure WDTO for W83627UHG and W83627EHF
Don't report the nowayout option with the 'initializing' message
Use request_muxed_region to reserve memory range only while needed
Add support for W83627S, W83627DHG-P, W83667HG, and NCT6779


2013-08-17 20:58:57

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 1/8] watchdog: w83627hf: Convert to watchdog infrastructure

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/Kconfig | 1 +
drivers/watchdog/w83627hf_wdt.c | 225 +++++++++------------------------------
2 files changed, 51 insertions(+), 175 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 362085d..c73db85 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -858,6 +858,7 @@ config VIA_WDT
config W83627HF_WDT
tristate "W83627HF/W83627DHG Watchdog Timer"
depends on X86
+ select WATCHDOG_CORE
---help---
This is the driver for the hardware watchdog on the W83627HF chipset
as used in Advantech PC-9578 and Tyan S2721-533 motherboards
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 92f1326..51a22ab 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -1,6 +1,9 @@
/*
* w83627hf/thf WDT driver
*
+ * (c) Copyright 2013 Guenter Roeck
+ * converted to watchdog infrastructure
+ *
* (c) Copyright 2007 Vlad Drukker <[email protected]>
* added support for W83627THF.
*
@@ -31,42 +34,27 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
-#include <linux/miscdevice.h>
#include <linux/watchdog.h>
-#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
-#include <linux/spinlock.h>
#include <linux/io.h>
-#include <linux/uaccess.h>
-

#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */

-static unsigned long wdt_is_open;
-static char expect_close;
-static DEFINE_SPINLOCK(io_lock);
-
/* You must set this - there is no sane way to probe for this board. */
static int wdt_io = 0x2E;
module_param(wdt_io, int, 0);
MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");

-static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+static int timeout; /* in seconds */
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. 1 <= timeout <= 255, default="
__MODULE_STRING(WATCHDOG_TIMEOUT) ".");

-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) ")");
-
/*
* Kernel methods.
*/
@@ -110,7 +98,7 @@ static void w83627hf_unselect_wd_register(void)
/* tyan motherboards seem to set F5 to 0x4C ?
* So explicitly init to appropriate value. */

-static void w83627hf_init(void)
+static void w83627hf_init(struct watchdog_device *wdog)
{
unsigned char t;

@@ -120,8 +108,8 @@ static void w83627hf_init(void)
t = inb_p(WDT_EFDR); /* read CRF6 */
if (t != 0) {
pr_info("Watchdog already running. Resetting timeout to %d sec\n",
- timeout);
- outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
+ wdog->timeout);
+ outb_p(wdog->timeout, WDT_EFDR); /* Write back to CRF6 */
}

outb_p(0xF5, WDT_EFER); /* Select CRF5 */
@@ -141,10 +129,8 @@ static void w83627hf_init(void)
w83627hf_unselect_wd_register();
}

-static void wdt_set_time(int timeout)
+static int wdt_set_time(unsigned int timeout)
{
- spin_lock(&io_lock);
-
w83627hf_select_wd_register();

outb_p(0xF6, WDT_EFER); /* Select CRF6 */
@@ -152,34 +138,30 @@ static void wdt_set_time(int timeout)

w83627hf_unselect_wd_register();

- spin_unlock(&io_lock);
+ return 0;
}

-static int wdt_ping(void)
+static int wdt_start(struct watchdog_device *wdog)
{
- wdt_set_time(timeout);
- return 0;
+ return wdt_set_time(wdog->timeout);
}

-static int wdt_disable(void)
+static int wdt_stop(struct watchdog_device *wdog)
{
- wdt_set_time(0);
- return 0;
+ return wdt_set_time(0);
}

-static int wdt_set_heartbeat(int t)
+static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
{
- if (t < 1 || t > 255)
- return -EINVAL;
- timeout = t;
+ wdt_set_time(timeout);
+ wdog->timeout = timeout;
+
return 0;
}

-static int wdt_get_time(void)
+static unsigned int wdt_get_time(struct watchdog_device *wdog)
{
- int timeleft;
-
- spin_lock(&io_lock);
+ unsigned int timeleft;

w83627hf_select_wd_register();

@@ -188,124 +170,17 @@ static int wdt_get_time(void)

w83627hf_unselect_wd_register();

- spin_unlock(&io_lock);
-
return timeleft;
}

-static ssize_t wdt_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- if (count) {
- if (!nowayout) {
- size_t i;
-
- expect_close = 0;
-
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 42;
- }
- }
- wdt_ping();
- }
- return count;
-}
-
-static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- int timeval;
- static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
- WDIOF_MAGICCLOSE,
- .firmware_version = 1,
- .identity = "W83627HF WDT",
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &ident, sizeof(ident)))
- return -EFAULT;
- break;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
- case WDIOC_SETOPTIONS:
- {
- int options, retval = -EINVAL;
-
- if (get_user(options, p))
- return -EFAULT;
- if (options & WDIOS_DISABLECARD) {
- wdt_disable();
- retval = 0;
- }
- if (options & WDIOS_ENABLECARD) {
- wdt_ping();
- retval = 0;
- }
- return retval;
- }
- case WDIOC_KEEPALIVE:
- wdt_ping();
- break;
- case WDIOC_SETTIMEOUT:
- if (get_user(timeval, p))
- return -EFAULT;
- if (wdt_set_heartbeat(timeval))
- return -EINVAL;
- wdt_ping();
- /* Fall */
- case WDIOC_GETTIMEOUT:
- return put_user(timeout, p);
- case WDIOC_GETTIMELEFT:
- timeval = wdt_get_time();
- return put_user(timeval, p);
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(0, &wdt_is_open))
- return -EBUSY;
- /*
- * Activate
- */
-
- wdt_ping();
- return nonseekable_open(inode, file);
-}
-
-static int wdt_close(struct inode *inode, struct file *file)
-{
- if (expect_close == 42)
- wdt_disable();
- else {
- pr_crit("Unexpected close, not stopping watchdog!\n");
- wdt_ping();
- }
- expect_close = 0;
- clear_bit(0, &wdt_is_open);
- return 0;
-}
-
/*
* Notifier for system down
*/
-
static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
void *unused)
{
if (code == SYS_DOWN || code == SYS_HALT)
- wdt_disable(); /* Turn the WDT off */
+ wdt_set_time(0); /* Turn the WDT off */

return NOTIFY_DONE;
}
@@ -314,19 +189,26 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
* Kernel Interfaces
*/

-static const struct file_operations wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = wdt_write,
- .unlocked_ioctl = wdt_ioctl,
- .open = wdt_open,
- .release = wdt_close,
+static struct watchdog_info wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+ .identity = "W83627HF Watchdog",
+};
+
+static struct watchdog_ops wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = wdt_start,
+ .stop = wdt_stop,
+ .ping = wdt_start,
+ .set_timeout = wdt_set_timeout,
+ .get_timeleft = wdt_get_time,
};

-static struct miscdevice wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &wdt_fops,
+static struct watchdog_device wdt_dev = {
+ .info = &wdt_info,
+ .ops = &wdt_ops,
+ .timeout = WATCHDOG_TIMEOUT,
+ .min_timeout = 1,
+ .max_timeout = 255,
};

/*
@@ -341,22 +223,19 @@ static struct notifier_block wdt_notifier = {
static int __init wdt_init(void)
{
int ret;
+ bool nowayout = WATCHDOG_NOWAYOUT;

pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");

- if (wdt_set_heartbeat(timeout)) {
- wdt_set_heartbeat(WATCHDOG_TIMEOUT);
- pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
- WATCHDOG_TIMEOUT);
- }
-
if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
pr_err("I/O address 0x%04x already in use\n", wdt_io);
- ret = -EIO;
- goto out;
+ return -EIO;
}

- w83627hf_init();
+ watchdog_init_timeout(&wdt_dev, timeout, NULL);
+ watchdog_set_nowayout(&wdt_dev, nowayout);
+
+ w83627hf_init(&wdt_dev);

ret = register_reboot_notifier(&wdt_notifier);
if (ret != 0) {
@@ -364,28 +243,25 @@ static int __init wdt_init(void)
goto unreg_regions;
}

- ret = misc_register(&wdt_miscdev);
- if (ret != 0) {
- pr_err("cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
+ ret = watchdog_register_device(&wdt_dev);
+ if (ret)
goto unreg_reboot;
- }

pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
+ wdt_dev.timeout, nowayout);

-out:
return ret;
+
unreg_reboot:
unregister_reboot_notifier(&wdt_notifier);
unreg_regions:
release_region(wdt_io, 1);
- goto out;
+ return ret;
}

static void __exit wdt_exit(void)
{
- misc_deregister(&wdt_miscdev);
+ watchdog_unregister_device(&wdt_dev);
unregister_reboot_notifier(&wdt_notifier);
release_region(wdt_io, 1);
}
@@ -396,4 +272,3 @@ module_exit(wdt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pádraig Brady <[email protected]>");
MODULE_DESCRIPTION("w83627hf/thf WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
--
1.7.9.7

2013-08-17 20:59:09

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 6/8] watchdog: w83627hf: Add support for W83697HF and W83697UG

Major difference is that the watchdog control and counter registers
are different on both chips.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/Kconfig | 2 ++
drivers/watchdog/w83627hf_wdt.c | 62 +++++++++++++++++++++++++++++++--------
2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 5d04ae4..9ec5f42 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -866,6 +866,8 @@ config W83627HF_WDT
W83637HF
W83667HG/HG-B
W83687THF
+ W83697HF
+ W83697UG
NCT6775
NCT6776
NCT6779
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index eb368f2..4c9f27a 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -45,10 +45,12 @@
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */

static int wdt_io;
+static int cr_wdt_timeout; /* WDT timeout register */
+static int cr_wdt_control; /* WDT control register */

-enum chips { w83627hf, w83627s, w83637hf, w83627thf, w83687thf,
- w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, w83667hg_b,
- nct6775, nct6776, nct6779 };
+enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
+ w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p,
+ w83667hg_b, nct6775, nct6776, nct6779 };

static int timeout; /* in seconds */
module_param(timeout, int, 0);
@@ -69,6 +71,8 @@ MODULE_PARM_DESC(timeout,

#define W83627HF_ID 0x52
#define W83627S_ID 0x59
+#define W83697HF_ID 0x60
+#define W83697UG_ID 0x68
#define W83637HF_ID 0x70
#define W83627THF_ID 0x82
#define W83687THF_ID 0x85
@@ -82,6 +86,12 @@ MODULE_PARM_DESC(timeout,
#define NCT6776_ID 0xc3
#define NCT6779_ID 0xc5

+#define W83627HF_WDT_TIMEOUT 0xf6
+#define W83697HF_WDT_TIMEOUT 0xf4
+
+#define W83627HF_WDT_CONTROL 0xf5
+#define W83697HF_WDT_CONTROL 0xf3
+
static void superio_outb(int reg, int val)
{
outb(reg, WDT_EFER);
@@ -138,6 +148,17 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
t = superio_inb(0x2B) & ~0x10;
superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
break;
+ case w83697hf:
+ /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
+ t = superio_inb(0x29) & ~0x60;
+ t |= 0x20;
+ superio_outb(0x29, t);
+ break;
+ case w83697ug:
+ /* Set pin 118 to WDTO# mode */
+ t = superio_inb(0x2b) & ~0x04;
+ superio_outb(0x2b, t);
+ break;
case w83627thf:
t = (superio_inb(0x2B) & ~0x08) | 0x04;
superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
@@ -146,10 +167,10 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
case w83627dhg_p:
t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
- t = superio_inb(0xF5);
+ t = superio_inb(cr_wdt_control);
t |= 0x02; /* enable the WDTO# output low pulse
* to the KBRST# pin */
- superio_outb(0xF5, t);
+ superio_outb(cr_wdt_control, t);
break;
case w83637hf:
break;
@@ -170,25 +191,25 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
* Don't touch its configuration, and hope the BIOS
* does the right thing.
*/
- t = superio_inb(0xF5);
+ t = superio_inb(cr_wdt_control);
t |= 0x02; /* enable the WDTO# output low pulse
* to the KBRST# pin */
- superio_outb(0xF5, t);
+ superio_outb(cr_wdt_control, t);
break;
default:
break;
}

- t = superio_inb(0xF6);
+ t = superio_inb(cr_wdt_timeout);
if (t != 0) {
pr_info("Watchdog already running. Resetting timeout to %d sec\n",
wdog->timeout);
- superio_outb(0xF6, wdog->timeout);
+ superio_outb(cr_wdt_timeout, wdog->timeout);
}

/* set second mode & disable keyboard turning off watchdog */
- t = superio_inb(0xF5) & ~0x0C;
- superio_outb(0xF5, t);
+ t = superio_inb(cr_wdt_control) & ~0x0C;
+ superio_outb(cr_wdt_control, t);

/* disable keyboard & mouse turning off watchdog */
t = superio_inb(0xF7) & ~0xC0;
@@ -208,7 +229,7 @@ static int wdt_set_time(unsigned int timeout)
return ret;

superio_select(W83627HF_LD_WDT);
- superio_outb(0xF6, timeout);
+ superio_outb(cr_wdt_timeout, timeout);
superio_exit();

return 0;
@@ -242,7 +263,7 @@ static unsigned int wdt_get_time(struct watchdog_device *wdog)
return 0;

superio_select(W83627HF_LD_WDT);
- timeleft = superio_inb(0xF6);
+ timeleft = superio_inb(cr_wdt_timeout);
superio_exit();

return timeleft;
@@ -300,6 +321,9 @@ static int wdt_find(int addr)
u8 val;
int ret;

+ cr_wdt_timeout = W83627HF_WDT_TIMEOUT;
+ cr_wdt_control = W83627HF_WDT_CONTROL;
+
ret = superio_enter();
if (ret)
return ret;
@@ -312,6 +336,16 @@ static int wdt_find(int addr)
case W83627S_ID:
ret = w83627s;
break;
+ case W83697HF_ID:
+ ret = w83697hf;
+ cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
+ cr_wdt_control = W83697HF_WDT_CONTROL;
+ break;
+ case W83697UG_ID:
+ ret = w83697ug;
+ cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
+ cr_wdt_control = W83697HF_WDT_CONTROL;
+ break;
case W83637HF_ID:
ret = w83637hf;
break;
@@ -368,6 +402,8 @@ static int __init wdt_init(void)
const char * const chip_name[] = {
"W83627HF",
"W83627S",
+ "W83697HF",
+ "W83697UG",
"W83637HF",
"W83627THF",
"W83687THF",
--
1.7.9.7

2013-08-17 20:59:01

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 3/8] watchdog: w83627hf: Enable watchdog device only if not already enabled

There is no need to enable the watchdog device if it is already enabled.
Also, when enabling the watchdog device, only set the watchdog device
enable bit and do not touch other bits; depending on the chip type,
those bits may enable other functionality.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/w83627hf_wdt.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index bb19368..13bad31 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -101,7 +101,9 @@ static void w83627hf_init(struct watchdog_device *wdog)
}

outb_p(0x30, WDT_EFER); /* select CR30 */
- outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+ t = inb(WDT_EFDR);
+ if (!(t & 0x01))
+ outb_p(t | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */

outb_p(0xF6, WDT_EFER); /* Select CRF6 */
t = inb_p(WDT_EFDR); /* read CRF6 */
--
1.7.9.7

2013-08-17 20:59:14

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 8/8] watchdog: w83627hf_wdt: Reset watchdog trigger during initialization

If the watchdog has already triggered for whatever reason, it won't restart
unless the trigger is reset.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/w83627hf_wdt.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 4c9f27a..5979c1c 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -211,8 +211,8 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
t = superio_inb(cr_wdt_control) & ~0x0C;
superio_outb(cr_wdt_control, t);

- /* disable keyboard & mouse turning off watchdog */
- t = superio_inb(0xF7) & ~0xC0;
+ /* reset trigger, disable keyboard & mouse turning off watchdog */
+ t = superio_inb(0xF7) & ~0xD0;
superio_outb(0xF7, t);

superio_exit();
--
1.7.9.7

2013-08-17 20:59:35

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 7/8] watchdog: Remove drivers for W83697HF and W83697UG

Since both chips are now supported by the w83627hf watchdog driver,
the chip specific drivers are no longer needed and can be removed.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/Kconfig | 30 ---
drivers/watchdog/Makefile | 2 -
drivers/watchdog/w83697hf_wdt.c | 461 ---------------------------------------
drivers/watchdog/w83697ug_wdt.c | 398 ---------------------------------
4 files changed, 891 deletions(-)
delete mode 100644 drivers/watchdog/w83697hf_wdt.c
delete mode 100644 drivers/watchdog/w83697ug_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9ec5f42..540803b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -881,36 +881,6 @@ config W83627HF_WDT

Most people will say N.

-config W83697HF_WDT
- tristate "W83697HF/W83697HG Watchdog Timer"
- depends on X86
- ---help---
- This is the driver for the hardware watchdog on the W83697HF/HG
- chipset as used in Dedibox/VIA motherboards (and likely others).
- This watchdog simply watches your kernel to make sure it doesn't
- freeze, and if it does, it reboots your computer after a certain
- amount of time.
-
- To compile this driver as a module, choose M here: the
- module will be called w83697hf_wdt.
-
- Most people will say N.
-
-config W83697UG_WDT
- tristate "W83697UG/W83697UF Watchdog Timer"
- depends on X86
- ---help---
- This is the driver for the hardware watchdog on the W83697UG/UF
- chipset as used in MSI Fuzzy CX700 VIA motherboards (and likely others).
- This watchdog simply watches your kernel to make sure it doesn't
- freeze, and if it does, it reboots your computer after a certain
- amount of time.
-
- To compile this driver as a module, choose M here: the
- module will be called w83697ug_wdt.
-
- Most people will say N.
-
config W83877F_WDT
tristate "W83877F (EMACS) Watchdog Timer"
depends on X86
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 2f26a0b..1807fdb 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -104,8 +104,6 @@ obj-$(CONFIG_SMSC_SCH311X_WDT) += sch311x_wdt.o
obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
obj-$(CONFIG_VIA_WDT) += via_wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
-obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
-obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
deleted file mode 100644
index cd9f3c1..0000000
--- a/drivers/watchdog/w83697hf_wdt.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * w83697hf/hg WDT driver
- *
- * (c) Copyright 2006 Samuel Tardieu <[email protected]>
- * (c) Copyright 2006 Marcus Junker <[email protected]>
- *
- * Based on w83627hf_wdt.c which is based on advantechwdt.c
- * which is based on wdt.c.
- * Original copyright messages:
- *
- * (c) Copyright 2003 Pádraig Brady <[email protected]>
- *
- * (c) Copyright 2000-2001 Marek Michalkiewicz <[email protected]>
- *
- * (c) Copyright 1996 Alan Cox <[email protected]>,
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Neither Marcus Junker nor ANDURAS AG admit liability nor provide
- * warranty for any of this software. This material is provided
- * "AS-IS" and at no charge.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-
-#define WATCHDOG_NAME "w83697hf/hg WDT"
-#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
-#define WATCHDOG_EARLY_DISABLE 1 /* Disable until userland kicks in */
-
-static unsigned long wdt_is_open;
-static char expect_close;
-static DEFINE_SPINLOCK(io_lock);
-
-/* You must set this - there is no sane way to probe for this board. */
-static int wdt_io = 0x2e;
-module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io,
- "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)");
-
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,
- "Watchdog timeout in seconds. 1<= timeout <=255 (default="
- __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-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) ")");
-
-static int early_disable = WATCHDOG_EARLY_DISABLE;
-module_param(early_disable, int, 0);
-MODULE_PARM_DESC(early_disable,
- "Watchdog gets disabled at boot time (default="
- __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")");
-
-/*
- * Kernel methods.
- */
-
-#define W83697HF_EFER (wdt_io + 0) /* Extended Function Enable Register */
-#define W83697HF_EFIR (wdt_io + 0) /* Extended Function Index Register
- (same as EFER) */
-#define W83697HF_EFDR (wdt_io + 1) /* Extended Function Data Register */
-
-static inline void w83697hf_unlock(void)
-{
- outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */
- outb_p(0x87, W83697HF_EFER); /* Again according to manual */
-}
-
-static inline void w83697hf_lock(void)
-{
- outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */
-}
-
-/*
- * The three functions w83697hf_get_reg(), w83697hf_set_reg() and
- * w83697hf_write_timeout() must be called with the device unlocked.
- */
-
-static unsigned char w83697hf_get_reg(unsigned char reg)
-{
- outb_p(reg, W83697HF_EFIR);
- return inb_p(W83697HF_EFDR);
-}
-
-static void w83697hf_set_reg(unsigned char reg, unsigned char data)
-{
- outb_p(reg, W83697HF_EFIR);
- outb_p(data, W83697HF_EFDR);
-}
-
-static void w83697hf_write_timeout(int timeout)
-{
- /* Write Timeout counter to CRF4 */
- w83697hf_set_reg(0xF4, timeout);
-}
-
-static void w83697hf_select_wdt(void)
-{
- w83697hf_unlock();
- w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */
-}
-
-static inline void w83697hf_deselect_wdt(void)
-{
- w83697hf_lock();
-}
-
-static void w83697hf_init(void)
-{
- unsigned char bbuf;
-
- w83697hf_select_wdt();
-
- bbuf = w83697hf_get_reg(0x29);
- bbuf &= ~0x60;
- bbuf |= 0x20;
-
- /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
- w83697hf_set_reg(0x29, bbuf);
-
- bbuf = w83697hf_get_reg(0xF3);
- bbuf &= ~0x04;
- w83697hf_set_reg(0xF3, bbuf); /* Count mode is seconds */
-
- w83697hf_deselect_wdt();
-}
-
-static void wdt_ping(void)
-{
- spin_lock(&io_lock);
- w83697hf_select_wdt();
-
- w83697hf_write_timeout(timeout);
-
- w83697hf_deselect_wdt();
- spin_unlock(&io_lock);
-}
-
-static void wdt_enable(void)
-{
- spin_lock(&io_lock);
- w83697hf_select_wdt();
-
- w83697hf_write_timeout(timeout);
- w83697hf_set_reg(0x30, 1); /* Enable timer */
-
- w83697hf_deselect_wdt();
- spin_unlock(&io_lock);
-}
-
-static void wdt_disable(void)
-{
- spin_lock(&io_lock);
- w83697hf_select_wdt();
-
- w83697hf_set_reg(0x30, 0); /* Disable timer */
- w83697hf_write_timeout(0);
-
- w83697hf_deselect_wdt();
- spin_unlock(&io_lock);
-}
-
-static unsigned char wdt_running(void)
-{
- unsigned char t;
-
- spin_lock(&io_lock);
- w83697hf_select_wdt();
-
- t = w83697hf_get_reg(0xF4); /* Read timer */
-
- w83697hf_deselect_wdt();
- spin_unlock(&io_lock);
-
- return t;
-}
-
-static int wdt_set_heartbeat(int t)
-{
- if (t < 1 || t > 255)
- return -EINVAL;
-
- timeout = t;
- return 0;
-}
-
-static ssize_t wdt_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- if (count) {
- if (!nowayout) {
- size_t i;
-
- expect_close = 0;
-
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 42;
- }
- }
- wdt_ping();
- }
- return count;
-}
-
-static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- int new_timeout;
- static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
- | WDIOF_MAGICCLOSE,
- .firmware_version = 1,
- .identity = "W83697HF WDT",
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &ident, sizeof(ident)))
- return -EFAULT;
- break;
-
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
-
- case WDIOC_SETOPTIONS:
- {
- int options, retval = -EINVAL;
-
- if (get_user(options, p))
- return -EFAULT;
-
- if (options & WDIOS_DISABLECARD) {
- wdt_disable();
- retval = 0;
- }
-
- if (options & WDIOS_ENABLECARD) {
- wdt_enable();
- retval = 0;
- }
-
- return retval;
- }
-
- case WDIOC_KEEPALIVE:
- wdt_ping();
- break;
-
- case WDIOC_SETTIMEOUT:
- if (get_user(new_timeout, p))
- return -EFAULT;
- if (wdt_set_heartbeat(new_timeout))
- return -EINVAL;
- wdt_ping();
- /* Fall */
-
- case WDIOC_GETTIMEOUT:
- return put_user(timeout, p);
-
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(0, &wdt_is_open))
- return -EBUSY;
- /*
- * Activate
- */
-
- wdt_enable();
- return nonseekable_open(inode, file);
-}
-
-static int wdt_close(struct inode *inode, struct file *file)
-{
- if (expect_close == 42)
- wdt_disable();
- else {
- pr_crit("Unexpected close, not stopping watchdog!\n");
- wdt_ping();
- }
- expect_close = 0;
- clear_bit(0, &wdt_is_open);
- return 0;
-}
-
-/*
- * Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- if (code == SYS_DOWN || code == SYS_HALT)
- wdt_disable(); /* Turn the WDT off */
-
- return NOTIFY_DONE;
-}
-
-/*
- * Kernel Interfaces
- */
-
-static const struct file_operations wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = wdt_write,
- .unlocked_ioctl = wdt_ioctl,
- .open = wdt_open,
- .release = wdt_close,
-};
-
-static struct miscdevice wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &wdt_fops,
-};
-
-/*
- * The WDT needs to learn about soft shutdowns in order to
- * turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
- .notifier_call = wdt_notify_sys,
-};
-
-static int w83697hf_check_wdt(void)
-{
- if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
- pr_err("I/O address 0x%x already in use\n", wdt_io);
- return -EIO;
- }
-
- pr_debug("Looking for watchdog at address 0x%x\n", wdt_io);
- w83697hf_unlock();
- if (w83697hf_get_reg(0x20) == 0x60) {
- pr_info("watchdog found at address 0x%x\n", wdt_io);
- w83697hf_lock();
- return 0;
- }
- /* Reprotect in case it was a compatible device */
- w83697hf_lock();
-
- pr_info("watchdog not found at address 0x%x\n", wdt_io);
- release_region(wdt_io, 2);
- return -EIO;
-}
-
-static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 };
-
-static int __init wdt_init(void)
-{
- int ret, i, found = 0;
-
- pr_info("WDT driver for W83697HF/HG initializing\n");
-
- if (wdt_io == 0) {
- /* we will autodetect the W83697HF/HG watchdog */
- for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) {
- wdt_io = w83697hf_ioports[i];
- if (!w83697hf_check_wdt())
- found++;
- }
- } else {
- if (!w83697hf_check_wdt())
- found++;
- }
-
- if (!found) {
- pr_err("No W83697HF/HG could be found\n");
- ret = -EIO;
- goto out;
- }
-
- w83697hf_init();
- if (early_disable) {
- if (wdt_running())
- pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
- wdt_disable();
- }
-
- if (wdt_set_heartbeat(timeout)) {
- wdt_set_heartbeat(WATCHDOG_TIMEOUT);
- pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
- WATCHDOG_TIMEOUT);
- }
-
- ret = register_reboot_notifier(&wdt_notifier);
- if (ret != 0) {
- pr_err("cannot register reboot notifier (err=%d)\n", ret);
- goto unreg_regions;
- }
-
- ret = misc_register(&wdt_miscdev);
- if (ret != 0) {
- pr_err("cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
- goto unreg_reboot;
- }
-
- pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
-
-out:
- return ret;
-unreg_reboot:
- unregister_reboot_notifier(&wdt_notifier);
-unreg_regions:
- release_region(wdt_io, 2);
- goto out;
-}
-
-static void __exit wdt_exit(void)
-{
- misc_deregister(&wdt_miscdev);
- unregister_reboot_notifier(&wdt_notifier);
- release_region(wdt_io, 2);
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marcus Junker <[email protected]>, "
- "Samuel Tardieu <[email protected]>");
-MODULE_DESCRIPTION("w83697hf/hg WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c
deleted file mode 100644
index 274be0b..0000000
--- a/drivers/watchdog/w83697ug_wdt.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * w83697ug/uf WDT driver
- *
- * (c) Copyright 2008 Flemming Fransen <[email protected]>
- * reused original code to support w83697ug/uf.
- *
- * Based on w83627hf_wdt.c which is based on advantechwdt.c
- * which is based on wdt.c.
- * Original copyright messages:
- *
- * (c) Copyright 2007 Vlad Drukker <[email protected]>
- * added support for W83627THF.
- *
- * (c) Copyright 2003 Pádraig Brady <[email protected]>
- *
- * (c) Copyright 2000-2001 Marek Michalkiewicz <[email protected]>
- *
- * (c) Copyright 1996 Alan Cox <[email protected]>, All Rights Reserved.
- * http://www.redhat.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- * warranty for any of this software. This material is provided
- * "AS-IS" and at no charge.
- *
- * (c) Copyright 1995 Alan Cox <[email protected]>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-
-#define WATCHDOG_NAME "w83697ug/uf WDT"
-#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
-
-static unsigned long wdt_is_open;
-static char expect_close;
-static DEFINE_SPINLOCK(io_lock);
-
-static int wdt_io = 0x2e;
-module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io, "w83697ug/uf WDT io port (default 0x2e)");
-
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,
- "Watchdog timeout in seconds. 1<= timeout <=255 (default="
- __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-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) ")");
-
-/*
- * Kernel methods.
- */
-
-#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */
-#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register
- (same as EFER) */
-#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
-
-static int w83697ug_select_wd_register(void)
-{
- unsigned char c;
- unsigned char version;
-
- outb_p(0x87, WDT_EFER); /* Enter extended function mode */
- outb_p(0x87, WDT_EFER); /* Again according to manual */
-
- outb(0x20, WDT_EFER); /* check chip version */
- version = inb(WDT_EFDR);
-
- if (version == 0x68) { /* W83697UG */
- pr_info("Watchdog chip version 0x%02x = W83697UG/UF found at 0x%04x\n",
- version, wdt_io);
-
- outb_p(0x2b, WDT_EFER);
- c = inb_p(WDT_EFDR); /* select WDT0 */
- c &= ~0x04;
- outb_p(0x2b, WDT_EFER);
- outb_p(c, WDT_EFDR); /* set pin118 to WDT0 */
-
- } else {
- pr_err("No W83697UG/UF could be found\n");
- return -ENODEV;
- }
-
- outb_p(0x07, WDT_EFER); /* point to logical device number reg */
- outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
- outb_p(0x30, WDT_EFER); /* select CR30 */
- c = inb_p(WDT_EFDR);
- outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
-
- return 0;
-}
-
-static void w83697ug_unselect_wd_register(void)
-{
- outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
-}
-
-static int w83697ug_init(void)
-{
- int ret;
- unsigned char t;
-
- ret = w83697ug_select_wd_register();
- if (ret != 0)
- return ret;
-
- outb_p(0xF6, WDT_EFER); /* Select CRF6 */
- t = inb_p(WDT_EFDR); /* read CRF6 */
- if (t != 0) {
- pr_info("Watchdog already running. Resetting timeout to %d sec\n",
- timeout);
- outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
- }
- outb_p(0xF5, WDT_EFER); /* Select CRF5 */
- t = inb_p(WDT_EFDR); /* read CRF5 */
- t &= ~0x0C; /* set second mode &
- disable keyboard turning off watchdog */
- outb_p(t, WDT_EFDR); /* Write back to CRF5 */
-
- w83697ug_unselect_wd_register();
- return 0;
-}
-
-static void wdt_ctrl(int timeout)
-{
- spin_lock(&io_lock);
-
- if (w83697ug_select_wd_register() < 0) {
- spin_unlock(&io_lock);
- return;
- }
-
- outb_p(0xF4, WDT_EFER); /* Select CRF4 */
- outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */
-
- w83697ug_unselect_wd_register();
-
- spin_unlock(&io_lock);
-}
-
-static int wdt_ping(void)
-{
- wdt_ctrl(timeout);
- return 0;
-}
-
-static int wdt_disable(void)
-{
- wdt_ctrl(0);
- return 0;
-}
-
-static int wdt_set_heartbeat(int t)
-{
- if (t < 1 || t > 255)
- return -EINVAL;
-
- timeout = t;
- return 0;
-}
-
-static ssize_t wdt_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- if (count) {
- if (!nowayout) {
- size_t i;
-
- expect_close = 0;
-
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 42;
- }
- }
- wdt_ping();
- }
- return count;
-}
-
-static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- int new_timeout;
- static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING |
- WDIOF_SETTIMEOUT |
- WDIOF_MAGICCLOSE,
- .firmware_version = 1,
- .identity = "W83697UG WDT",
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &ident, sizeof(ident)))
- return -EFAULT;
- break;
-
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
-
- case WDIOC_SETOPTIONS:
- {
- int options, retval = -EINVAL;
-
- if (get_user(options, p))
- return -EFAULT;
-
- if (options & WDIOS_DISABLECARD) {
- wdt_disable();
- retval = 0;
- }
-
- if (options & WDIOS_ENABLECARD) {
- wdt_ping();
- retval = 0;
- }
-
- return retval;
- }
-
- case WDIOC_KEEPALIVE:
- wdt_ping();
- break;
-
- case WDIOC_SETTIMEOUT:
- if (get_user(new_timeout, p))
- return -EFAULT;
- if (wdt_set_heartbeat(new_timeout))
- return -EINVAL;
- wdt_ping();
- /* Fall */
-
- case WDIOC_GETTIMEOUT:
- return put_user(timeout, p);
-
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(0, &wdt_is_open))
- return -EBUSY;
- /*
- * Activate
- */
-
- wdt_ping();
- return nonseekable_open(inode, file);
-}
-
-static int wdt_close(struct inode *inode, struct file *file)
-{
- if (expect_close == 42)
- wdt_disable();
- else {
- pr_crit("Unexpected close, not stopping watchdog!\n");
- wdt_ping();
- }
- expect_close = 0;
- clear_bit(0, &wdt_is_open);
- return 0;
-}
-
-/*
- * Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- if (code == SYS_DOWN || code == SYS_HALT)
- wdt_disable(); /* Turn the WDT off */
-
- return NOTIFY_DONE;
-}
-
-/*
- * Kernel Interfaces
- */
-
-static const struct file_operations wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = wdt_write,
- .unlocked_ioctl = wdt_ioctl,
- .open = wdt_open,
- .release = wdt_close,
-};
-
-static struct miscdevice wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &wdt_fops,
-};
-
-/*
- * The WDT needs to learn about soft shutdowns in order to
- * turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
- .notifier_call = wdt_notify_sys,
-};
-
-static int __init wdt_init(void)
-{
- int ret;
-
- pr_info("WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising\n");
-
- if (wdt_set_heartbeat(timeout)) {
- wdt_set_heartbeat(WATCHDOG_TIMEOUT);
- pr_info("timeout value must be 1<=timeout<=255, using %d\n",
- WATCHDOG_TIMEOUT);
- }
-
- if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
- pr_err("I/O address 0x%04x already in use\n", wdt_io);
- ret = -EIO;
- goto out;
- }
-
- ret = w83697ug_init();
- if (ret != 0)
- goto unreg_regions;
-
- ret = register_reboot_notifier(&wdt_notifier);
- if (ret != 0) {
- pr_err("cannot register reboot notifier (err=%d)\n", ret);
- goto unreg_regions;
- }
-
- ret = misc_register(&wdt_miscdev);
- if (ret != 0) {
- pr_err("cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
- goto unreg_reboot;
- }
-
- pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
-
-out:
- return ret;
-unreg_reboot:
- unregister_reboot_notifier(&wdt_notifier);
-unreg_regions:
- release_region(wdt_io, 1);
- goto out;
-}
-
-static void __exit wdt_exit(void)
-{
- misc_deregister(&wdt_miscdev);
- unregister_reboot_notifier(&wdt_notifier);
- release_region(wdt_io, 1);
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Flemming Frandsen <[email protected]>");
-MODULE_DESCRIPTION("w83697ug/uf WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
--
1.7.9.7

2013-08-17 20:59:05

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 4/8] watchdog: w83627hf: Use helper functions to access superio registers

Use helper functions named similar to other drivers to access
superio registers.

Request memory region only when needed, and use request_muxed_region().
This lets other devices (hwmon, gpio) use the same region.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/w83627hf_wdt.c | 132 ++++++++++++++++++++++-----------------
1 file changed, 76 insertions(+), 56 deletions(-)

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 13bad31..04cf20f 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -64,80 +64,102 @@ MODULE_PARM_DESC(timeout,
(same as EFER) */
#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */

-static void w83627hf_select_wd_register(void)
+#define W83627HF_LD_WDT 0x08
+
+static void superio_outb(int reg, int val)
+{
+ outb(reg, WDT_EFER);
+ outb(val, WDT_EFDR);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, WDT_EFER);
+ return inb(WDT_EFDR);
+}
+
+static int superio_enter(void)
{
+ if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME))
+ return -EBUSY;
+
outb_p(0x87, WDT_EFER); /* Enter extended function mode */
outb_p(0x87, WDT_EFER); /* Again according to manual */
- outb_p(0x07, WDT_EFER); /* point to logical device number reg */
- outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
+
+ return 0;
}

-static void w83627hf_unselect_wd_register(void)
+static void superio_select(int ld)
+{
+ superio_outb(0x07, ld);
+}
+
+static void superio_exit(void)
{
outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
+ release_region(wdt_io, 2);
}

/* tyan motherboards seem to set F5 to 0x4C ?
* So explicitly init to appropriate value. */

-static void w83627hf_init(struct watchdog_device *wdog)
+static int w83627hf_init(struct watchdog_device *wdog)
{
+ int ret;
unsigned char t;

- w83627hf_select_wd_register();
+ ret = superio_enter();
+ if (ret)
+ return ret;

- outb(0x20, WDT_EFER); /* check chip version */
- t = inb(WDT_EFDR);
+ superio_select(W83627HF_LD_WDT);
+ t = superio_inb(0x20); /* check chip version */
if (t == 0x82) { /* W83627THF */
- outb_p(0x2b, WDT_EFER); /* select GPIO3 */
- t = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
- outb_p(0x2b, WDT_EFER);
- outb_p(t, WDT_EFDR); /* set GPIO3 to WDT0 */
+ t = (superio_inb(0x2b) & 0xf7);
+ superio_outb(0x2b, t | 0x04); /* set GPIO3 to WDT0 */
} else if (t == 0x88 || t == 0xa0) { /* W83627EHF / W83627DHG */
- outb_p(0x2d, WDT_EFER); /* select GPIO5 */
- t = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */
- outb_p(0x2d, WDT_EFER);
- outb_p(t, WDT_EFDR); /* set GPIO5 to WDT0 */
+ t = superio_inb(0x2d);
+ superio_outb(0x2d, t & ~0x01); /* set GPIO5 to WDT0 */
}

- outb_p(0x30, WDT_EFER); /* select CR30 */
- t = inb(WDT_EFDR);
+ /* set CR30 bit 0 to activate GPIO2 */
+ t = superio_inb(0x30);
if (!(t & 0x01))
- outb_p(t | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+ superio_outb(0x30, t | 0x01);

- outb_p(0xF6, WDT_EFER); /* Select CRF6 */
- t = inb_p(WDT_EFDR); /* read CRF6 */
+ t = superio_inb(0xF6);
if (t != 0) {
pr_info("Watchdog already running. Resetting timeout to %d sec\n",
wdog->timeout);
- outb_p(wdog->timeout, WDT_EFDR); /* Write back to CRF6 */
+ superio_outb(0xF6, wdog->timeout);
}

- outb_p(0xF5, WDT_EFER); /* Select CRF5 */
- t = inb_p(WDT_EFDR); /* read CRF5 */
- t &= ~0x0C; /* set second mode & disable keyboard
- turning off watchdog */
- t |= 0x02; /* enable the WDTO# output low pulse
- to the KBRST# pin (PIN60) */
- outb_p(t, WDT_EFDR); /* Write back to CRF5 */
-
- outb_p(0xF7, WDT_EFER); /* Select CRF7 */
- t = inb_p(WDT_EFDR); /* read CRF7 */
- t &= ~0xC0; /* disable keyboard & mouse turning off
- watchdog */
- outb_p(t, WDT_EFDR); /* Write back to CRF7 */
-
- w83627hf_unselect_wd_register();
+ /* set second mode & disable keyboard turning off watchdog */
+ t = superio_inb(0xF5) & ~0x0C;
+ /* enable the WDTO# output low pulse to the KBRST# pin */
+ t |= 0x02;
+ superio_outb(0xF5, t);
+
+ /* disable keyboard & mouse turning off watchdog */
+ t = superio_inb(0xF7) & ~0xC0;
+ superio_outb(0xF7, t);
+
+ superio_exit();
+
+ return 0;
}

static int wdt_set_time(unsigned int timeout)
{
- w83627hf_select_wd_register();
+ int ret;

- outb_p(0xF6, WDT_EFER); /* Select CRF6 */
- outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */
+ ret = superio_enter();
+ if (ret)
+ return ret;

- w83627hf_unselect_wd_register();
+ superio_select(W83627HF_LD_WDT);
+ superio_outb(0xF6, timeout);
+ superio_exit();

return 0;
}
@@ -163,13 +185,15 @@ static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
static unsigned int wdt_get_time(struct watchdog_device *wdog)
{
unsigned int timeleft;
+ int ret;

- w83627hf_select_wd_register();
-
- outb_p(0xF6, WDT_EFER); /* Select CRF6 */
- timeleft = inb_p(WDT_EFDR); /* Read Timeout counter to CRF6 */
+ ret = superio_enter();
+ if (ret)
+ return 0;

- w83627hf_unselect_wd_register();
+ superio_select(W83627HF_LD_WDT);
+ timeleft = superio_inb(0xF6);
+ superio_exit();

return timeleft;
}
@@ -228,20 +252,19 @@ static int __init wdt_init(void)

pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");

- if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
- pr_err("I/O address 0x%04x already in use\n", wdt_io);
- return -EIO;
- }
-
watchdog_init_timeout(&wdt_dev, timeout, NULL);
watchdog_set_nowayout(&wdt_dev, nowayout);

- w83627hf_init(&wdt_dev);
+ ret = w83627hf_init(&wdt_dev);
+ if (ret) {
+ pr_err("failed to initialize watchdog (err=%d)\n", ret);
+ return ret;
+ }

ret = register_reboot_notifier(&wdt_notifier);
if (ret != 0) {
pr_err("cannot register reboot notifier (err=%d)\n", ret);
- goto unreg_regions;
+ return ret;
}

ret = watchdog_register_device(&wdt_dev);
@@ -255,8 +278,6 @@ static int __init wdt_init(void)

unreg_reboot:
unregister_reboot_notifier(&wdt_notifier);
-unreg_regions:
- release_region(wdt_io, 1);
return ret;
}

@@ -264,7 +285,6 @@ static void __exit wdt_exit(void)
{
watchdog_unregister_device(&wdt_dev);
unregister_reboot_notifier(&wdt_notifier);
- release_region(wdt_io, 1);
}

module_init(wdt_init);
--
1.7.9.7

2013-08-17 21:00:09

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 5/8] watchdog: w83627hf: Auto-detect IO address and supported chips

Instead of requiring the user to provide an IO address per module
parameter, auto-detect it as well as supported chips.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/Kconfig | 15 +++-
drivers/watchdog/w83627hf_wdt.c | 182 ++++++++++++++++++++++++++++++++++-----
2 files changed, 173 insertions(+), 24 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c73db85..5d04ae4 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -856,13 +856,20 @@ config VIA_WDT
Most people will say N.

config W83627HF_WDT
- tristate "W83627HF/W83627DHG Watchdog Timer"
+ tristate "Watchdog timer for W83627HF/W83627DHG and compatibles"
depends on X86
select WATCHDOG_CORE
---help---
- This is the driver for the hardware watchdog on the W83627HF chipset
- as used in Advantech PC-9578 and Tyan S2721-533 motherboards
- (and likely others). The driver also supports the W83627DHG chip.
+ This is the driver for the hardware watchdog on the following
+ Super I/O chips.
+ W83627DHG/DHG-P/EHF/EHG/F/G/HF/S/SF/THF/UHG/UG
+ W83637HF
+ W83667HG/HG-B
+ W83687THF
+ NCT6775
+ NCT6776
+ NCT6779
+
This watchdog simply watches your kernel to make sure it doesn't
freeze, and if it does, it reboots your computer after a certain
amount of time.
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 04cf20f..eb368f2 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -44,10 +44,11 @@
#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */

-/* You must set this - there is no sane way to probe for this board. */
-static int wdt_io = 0x2E;
-module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
+static int wdt_io;
+
+enum chips { w83627hf, w83627s, w83637hf, w83627thf, w83687thf,
+ w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, w83667hg_b,
+ nct6775, nct6776, nct6779 };

static int timeout; /* in seconds */
module_param(timeout, int, 0);
@@ -66,6 +67,21 @@ MODULE_PARM_DESC(timeout,

#define W83627HF_LD_WDT 0x08

+#define W83627HF_ID 0x52
+#define W83627S_ID 0x59
+#define W83637HF_ID 0x70
+#define W83627THF_ID 0x82
+#define W83687THF_ID 0x85
+#define W83627EHF_ID 0x88
+#define W83627DHG_ID 0xa0
+#define W83627UHG_ID 0xa2
+#define W83667HG_ID 0xa5
+#define W83627DHG_P_ID 0xb0
+#define W83667HG_B_ID 0xb3
+#define NCT6775_ID 0xb4
+#define NCT6776_ID 0xc3
+#define NCT6779_ID 0xc5
+
static void superio_outb(int reg, int val)
{
outb(reg, WDT_EFER);
@@ -100,10 +116,7 @@ static void superio_exit(void)
release_region(wdt_io, 2);
}

-/* tyan motherboards seem to set F5 to 0x4C ?
- * So explicitly init to appropriate value. */
-
-static int w83627hf_init(struct watchdog_device *wdog)
+static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
{
int ret;
unsigned char t;
@@ -113,20 +126,59 @@ static int w83627hf_init(struct watchdog_device *wdog)
return ret;

superio_select(W83627HF_LD_WDT);
- t = superio_inb(0x20); /* check chip version */
- if (t == 0x82) { /* W83627THF */
- t = (superio_inb(0x2b) & 0xf7);
- superio_outb(0x2b, t | 0x04); /* set GPIO3 to WDT0 */
- } else if (t == 0x88 || t == 0xa0) { /* W83627EHF / W83627DHG */
- t = superio_inb(0x2d);
- superio_outb(0x2d, t & ~0x01); /* set GPIO5 to WDT0 */
- }

/* set CR30 bit 0 to activate GPIO2 */
t = superio_inb(0x30);
if (!(t & 0x01))
superio_outb(0x30, t | 0x01);

+ switch (chip) {
+ case w83627hf:
+ case w83627s:
+ t = superio_inb(0x2B) & ~0x10;
+ superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
+ break;
+ case w83627thf:
+ t = (superio_inb(0x2B) & ~0x08) | 0x04;
+ superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
+ break;
+ case w83627dhg:
+ case w83627dhg_p:
+ t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
+ superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
+ t = superio_inb(0xF5);
+ t |= 0x02; /* enable the WDTO# output low pulse
+ * to the KBRST# pin */
+ superio_outb(0xF5, t);
+ break;
+ case w83637hf:
+ break;
+ case w83687thf:
+ t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */
+ superio_outb(0x2C, t);
+ break;
+ case w83627ehf:
+ case w83627uhg:
+ case w83667hg:
+ case w83667hg_b:
+ case nct6775:
+ case nct6776:
+ case nct6779:
+ /*
+ * These chips have a fixed WDTO# output pin (W83627UHG),
+ * or support more than one WDTO# output pin.
+ * Don't touch its configuration, and hope the BIOS
+ * does the right thing.
+ */
+ t = superio_inb(0xF5);
+ t |= 0x02; /* enable the WDTO# output low pulse
+ * to the KBRST# pin */
+ superio_outb(0xF5, t);
+ break;
+ default:
+ break;
+ }
+
t = superio_inb(0xF6);
if (t != 0) {
pr_info("Watchdog already running. Resetting timeout to %d sec\n",
@@ -136,8 +188,6 @@ static int w83627hf_init(struct watchdog_device *wdog)

/* set second mode & disable keyboard turning off watchdog */
t = superio_inb(0xF5) & ~0x0C;
- /* enable the WDTO# output low pulse to the KBRST# pin */
- t |= 0x02;
superio_outb(0xF5, t);

/* disable keyboard & mouse turning off watchdog */
@@ -245,17 +295,109 @@ static struct notifier_block wdt_notifier = {
.notifier_call = wdt_notify_sys,
};

+static int wdt_find(int addr)
+{
+ u8 val;
+ int ret;
+
+ ret = superio_enter();
+ if (ret)
+ return ret;
+ superio_select(W83627HF_LD_WDT);
+ val = superio_inb(0x20);
+ switch (val) {
+ case W83627HF_ID:
+ ret = w83627hf;
+ break;
+ case W83627S_ID:
+ ret = w83627s;
+ break;
+ case W83637HF_ID:
+ ret = w83637hf;
+ break;
+ case W83627THF_ID:
+ ret = w83627thf;
+ break;
+ case W83687THF_ID:
+ ret = w83687thf;
+ break;
+ case W83627EHF_ID:
+ ret = w83627ehf;
+ break;
+ case W83627DHG_ID:
+ ret = w83627dhg;
+ break;
+ case W83627DHG_P_ID:
+ ret = w83627dhg_p;
+ break;
+ case W83627UHG_ID:
+ ret = w83627uhg;
+ break;
+ case W83667HG_ID:
+ ret = w83667hg;
+ break;
+ case W83667HG_B_ID:
+ ret = w83667hg_b;
+ break;
+ case NCT6775_ID:
+ ret = nct6775;
+ break;
+ case NCT6776_ID:
+ ret = nct6776;
+ break;
+ case NCT6779_ID:
+ ret = nct6779;
+ break;
+ case 0xff:
+ ret = -ENODEV;
+ break;
+ default:
+ ret = -ENODEV;
+ pr_err("Unsupported chip ID: 0x%02x\n", val);
+ break;
+ }
+ superio_exit();
+ return ret;
+}
+
static int __init wdt_init(void)
{
int ret;
bool nowayout = WATCHDOG_NOWAYOUT;
+ int chip;
+ const char * const chip_name[] = {
+ "W83627HF",
+ "W83627S",
+ "W83637HF",
+ "W83627THF",
+ "W83687THF",
+ "W83627EHF",
+ "W83627DHG",
+ "W83627UHG",
+ "W83667HG",
+ "W83667DHG-P",
+ "W83667HG-B",
+ "NCT6775",
+ "NCT6776",
+ "NCT6779",
+ };
+
+ wdt_io = 0x2e;
+ chip = wdt_find(0x2e);
+ if (chip < 0) {
+ wdt_io = 0x4e;
+ chip = wdt_find(0x4e);
+ if (chip < 0)
+ return chip;
+ }

- pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");
+ pr_info("WDT driver for %s Super I/O chip initialising\n",
+ chip_name[chip]);

watchdog_init_timeout(&wdt_dev, timeout, NULL);
watchdog_set_nowayout(&wdt_dev, nowayout);

- ret = w83627hf_init(&wdt_dev);
+ ret = w83627hf_init(&wdt_dev, chip);
if (ret) {
pr_err("failed to initialize watchdog (err=%d)\n", ret);
return ret;
--
1.7.9.7

2013-08-17 21:00:49

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v3 2/8] watchdog: w83627hf: Enable watchdog only once

It is unnecessary to enable the logical device and WDT0 each time
the watchdog is accessed. Do it only once during initialization.

Signed-off-by: Guenter Roeck <[email protected]>
---
drivers/watchdog/w83627hf_wdt.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 51a22ab..bb19368 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -66,28 +66,10 @@ MODULE_PARM_DESC(timeout,

static void w83627hf_select_wd_register(void)
{
- unsigned char c;
outb_p(0x87, WDT_EFER); /* Enter extended function mode */
outb_p(0x87, WDT_EFER); /* Again according to manual */
-
- outb(0x20, WDT_EFER); /* check chip version */
- c = inb(WDT_EFDR);
- if (c == 0x82) { /* W83627THF */
- outb_p(0x2b, WDT_EFER); /* select GPIO3 */
- c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
- outb_p(0x2b, WDT_EFER);
- outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */
- } else if (c == 0x88 || c == 0xa0) { /* W83627EHF / W83627DHG */
- outb_p(0x2d, WDT_EFER); /* select GPIO5 */
- c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */
- outb_p(0x2d, WDT_EFER);
- outb_p(c, WDT_EFDR); /* set GPIO5 to WDT0 */
- }
-
outb_p(0x07, WDT_EFER); /* point to logical device number reg */
outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
- outb_p(0x30, WDT_EFER); /* select CR30 */
- outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
}

static void w83627hf_unselect_wd_register(void)
@@ -104,6 +86,23 @@ static void w83627hf_init(struct watchdog_device *wdog)

w83627hf_select_wd_register();

+ outb(0x20, WDT_EFER); /* check chip version */
+ t = inb(WDT_EFDR);
+ if (t == 0x82) { /* W83627THF */
+ outb_p(0x2b, WDT_EFER); /* select GPIO3 */
+ t = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
+ outb_p(0x2b, WDT_EFER);
+ outb_p(t, WDT_EFDR); /* set GPIO3 to WDT0 */
+ } else if (t == 0x88 || t == 0xa0) { /* W83627EHF / W83627DHG */
+ outb_p(0x2d, WDT_EFER); /* select GPIO5 */
+ t = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */
+ outb_p(0x2d, WDT_EFER);
+ outb_p(t, WDT_EFDR); /* set GPIO5 to WDT0 */
+ }
+
+ outb_p(0x30, WDT_EFER); /* select CR30 */
+ outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+
outb_p(0xF6, WDT_EFER); /* Select CRF6 */
t = inb_p(WDT_EFDR); /* read CRF6 */
if (t != 0) {
--
1.7.9.7

2013-10-28 21:58:02

by Wim Van Sebroeck

[permalink] [raw]
Subject: Re: [PATCH v3 1/8] watchdog: w83627hf: Convert to watchdog infrastructure

Hi Guenter,

> Signed-off-by: Guenter Roeck <[email protected]>
> ---
> drivers/watchdog/Kconfig | 1 +
> drivers/watchdog/w83627hf_wdt.c | 225 +++++++++------------------------------
> 2 files changed, 51 insertions(+), 175 deletions(-)
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 362085d..c73db85 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -858,6 +858,7 @@ config VIA_WDT
> config W83627HF_WDT
> tristate "W83627HF/W83627DHG Watchdog Timer"
> depends on X86
> + select WATCHDOG_CORE
> ---help---
> This is the driver for the hardware watchdog on the W83627HF chipset
> as used in Advantech PC-9578 and Tyan S2721-533 motherboards
> diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
> index 92f1326..51a22ab 100644
> --- a/drivers/watchdog/w83627hf_wdt.c
> +++ b/drivers/watchdog/w83627hf_wdt.c
> @@ -1,6 +1,9 @@
> /*
> * w83627hf/thf WDT driver
> *
> + * (c) Copyright 2013 Guenter Roeck
> + * converted to watchdog infrastructure
> + *
> * (c) Copyright 2007 Vlad Drukker <[email protected]>
> * added support for W83627THF.
> *
> @@ -31,42 +34,27 @@
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/types.h>
> -#include <linux/miscdevice.h>
> #include <linux/watchdog.h>
> -#include <linux/fs.h>
> #include <linux/ioport.h>
> #include <linux/notifier.h>
> #include <linux/reboot.h>
> #include <linux/init.h>
> -#include <linux/spinlock.h>
> #include <linux/io.h>
> -#include <linux/uaccess.h>
> -
>
> #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
> #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
>
> -static unsigned long wdt_is_open;
> -static char expect_close;
> -static DEFINE_SPINLOCK(io_lock);
> -
> /* You must set this - there is no sane way to probe for this board. */
> static int wdt_io = 0x2E;
> module_param(wdt_io, int, 0);
> MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
>
> -static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
> +static int timeout; /* in seconds */
> module_param(timeout, int, 0);
> MODULE_PARM_DESC(timeout,
> "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
> __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
>
> -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) ")");
> -

Why do you remove the nowayout module param?

Kind regards,
Wim.

> /*
> * Kernel methods.
> */
> @@ -110,7 +98,7 @@ static void w83627hf_unselect_wd_register(void)
> /* tyan motherboards seem to set F5 to 0x4C ?
> * So explicitly init to appropriate value. */
>
> -static void w83627hf_init(void)
> +static void w83627hf_init(struct watchdog_device *wdog)
> {
> unsigned char t;
>
> @@ -120,8 +108,8 @@ static void w83627hf_init(void)
> t = inb_p(WDT_EFDR); /* read CRF6 */
> if (t != 0) {
> pr_info("Watchdog already running. Resetting timeout to %d sec\n",
> - timeout);
> - outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
> + wdog->timeout);
> + outb_p(wdog->timeout, WDT_EFDR); /* Write back to CRF6 */
> }
>
> outb_p(0xF5, WDT_EFER); /* Select CRF5 */
> @@ -141,10 +129,8 @@ static void w83627hf_init(void)
> w83627hf_unselect_wd_register();
> }
>
> -static void wdt_set_time(int timeout)
> +static int wdt_set_time(unsigned int timeout)
> {
> - spin_lock(&io_lock);
> -
> w83627hf_select_wd_register();
>
> outb_p(0xF6, WDT_EFER); /* Select CRF6 */
> @@ -152,34 +138,30 @@ static void wdt_set_time(int timeout)
>
> w83627hf_unselect_wd_register();
>
> - spin_unlock(&io_lock);
> + return 0;
> }
>
> -static int wdt_ping(void)
> +static int wdt_start(struct watchdog_device *wdog)
> {
> - wdt_set_time(timeout);
> - return 0;
> + return wdt_set_time(wdog->timeout);
> }
>
> -static int wdt_disable(void)
> +static int wdt_stop(struct watchdog_device *wdog)
> {
> - wdt_set_time(0);
> - return 0;
> + return wdt_set_time(0);
> }
>
> -static int wdt_set_heartbeat(int t)
> +static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
> {
> - if (t < 1 || t > 255)
> - return -EINVAL;
> - timeout = t;
> + wdt_set_time(timeout);
> + wdog->timeout = timeout;
> +
> return 0;
> }
>
> -static int wdt_get_time(void)
> +static unsigned int wdt_get_time(struct watchdog_device *wdog)
> {
> - int timeleft;
> -
> - spin_lock(&io_lock);
> + unsigned int timeleft;
>
> w83627hf_select_wd_register();
>
> @@ -188,124 +170,17 @@ static int wdt_get_time(void)
>
> w83627hf_unselect_wd_register();
>
> - spin_unlock(&io_lock);
> -
> return timeleft;
> }
>
> -static ssize_t wdt_write(struct file *file, const char __user *buf,
> - size_t count, loff_t *ppos)
> -{
> - if (count) {
> - if (!nowayout) {
> - size_t i;
> -
> - expect_close = 0;
> -
> - for (i = 0; i != count; i++) {
> - char c;
> - if (get_user(c, buf + i))
> - return -EFAULT;
> - if (c == 'V')
> - expect_close = 42;
> - }
> - }
> - wdt_ping();
> - }
> - return count;
> -}
> -
> -static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> -{
> - void __user *argp = (void __user *)arg;
> - int __user *p = argp;
> - int timeval;
> - static const struct watchdog_info ident = {
> - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
> - WDIOF_MAGICCLOSE,
> - .firmware_version = 1,
> - .identity = "W83627HF WDT",
> - };
> -
> - switch (cmd) {
> - case WDIOC_GETSUPPORT:
> - if (copy_to_user(argp, &ident, sizeof(ident)))
> - return -EFAULT;
> - break;
> - case WDIOC_GETSTATUS:
> - case WDIOC_GETBOOTSTATUS:
> - return put_user(0, p);
> - case WDIOC_SETOPTIONS:
> - {
> - int options, retval = -EINVAL;
> -
> - if (get_user(options, p))
> - return -EFAULT;
> - if (options & WDIOS_DISABLECARD) {
> - wdt_disable();
> - retval = 0;
> - }
> - if (options & WDIOS_ENABLECARD) {
> - wdt_ping();
> - retval = 0;
> - }
> - return retval;
> - }
> - case WDIOC_KEEPALIVE:
> - wdt_ping();
> - break;
> - case WDIOC_SETTIMEOUT:
> - if (get_user(timeval, p))
> - return -EFAULT;
> - if (wdt_set_heartbeat(timeval))
> - return -EINVAL;
> - wdt_ping();
> - /* Fall */
> - case WDIOC_GETTIMEOUT:
> - return put_user(timeout, p);
> - case WDIOC_GETTIMELEFT:
> - timeval = wdt_get_time();
> - return put_user(timeval, p);
> - default:
> - return -ENOTTY;
> - }
> - return 0;
> -}
> -
> -static int wdt_open(struct inode *inode, struct file *file)
> -{
> - if (test_and_set_bit(0, &wdt_is_open))
> - return -EBUSY;
> - /*
> - * Activate
> - */
> -
> - wdt_ping();
> - return nonseekable_open(inode, file);
> -}
> -
> -static int wdt_close(struct inode *inode, struct file *file)
> -{
> - if (expect_close == 42)
> - wdt_disable();
> - else {
> - pr_crit("Unexpected close, not stopping watchdog!\n");
> - wdt_ping();
> - }
> - expect_close = 0;
> - clear_bit(0, &wdt_is_open);
> - return 0;
> -}
> -
> /*
> * Notifier for system down
> */
> -
> static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
> void *unused)
> {
> if (code == SYS_DOWN || code == SYS_HALT)
> - wdt_disable(); /* Turn the WDT off */
> + wdt_set_time(0); /* Turn the WDT off */
>
> return NOTIFY_DONE;
> }
> @@ -314,19 +189,26 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
> * Kernel Interfaces
> */
>
> -static const struct file_operations wdt_fops = {
> - .owner = THIS_MODULE,
> - .llseek = no_llseek,
> - .write = wdt_write,
> - .unlocked_ioctl = wdt_ioctl,
> - .open = wdt_open,
> - .release = wdt_close,
> +static struct watchdog_info wdt_info = {
> + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> + .identity = "W83627HF Watchdog",
> +};
> +
> +static struct watchdog_ops wdt_ops = {
> + .owner = THIS_MODULE,
> + .start = wdt_start,
> + .stop = wdt_stop,
> + .ping = wdt_start,
> + .set_timeout = wdt_set_timeout,
> + .get_timeleft = wdt_get_time,
> };
>
> -static struct miscdevice wdt_miscdev = {
> - .minor = WATCHDOG_MINOR,
> - .name = "watchdog",
> - .fops = &wdt_fops,
> +static struct watchdog_device wdt_dev = {
> + .info = &wdt_info,
> + .ops = &wdt_ops,
> + .timeout = WATCHDOG_TIMEOUT,
> + .min_timeout = 1,
> + .max_timeout = 255,
> };
>
> /*
> @@ -341,22 +223,19 @@ static struct notifier_block wdt_notifier = {
> static int __init wdt_init(void)
> {
> int ret;
> + bool nowayout = WATCHDOG_NOWAYOUT;
>
> pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");
>
> - if (wdt_set_heartbeat(timeout)) {
> - wdt_set_heartbeat(WATCHDOG_TIMEOUT);
> - pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
> - WATCHDOG_TIMEOUT);
> - }
> -
> if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
> pr_err("I/O address 0x%04x already in use\n", wdt_io);
> - ret = -EIO;
> - goto out;
> + return -EIO;
> }
>
> - w83627hf_init();
> + watchdog_init_timeout(&wdt_dev, timeout, NULL);
> + watchdog_set_nowayout(&wdt_dev, nowayout);
> +
> + w83627hf_init(&wdt_dev);
>
> ret = register_reboot_notifier(&wdt_notifier);
> if (ret != 0) {
> @@ -364,28 +243,25 @@ static int __init wdt_init(void)
> goto unreg_regions;
> }
>
> - ret = misc_register(&wdt_miscdev);
> - if (ret != 0) {
> - pr_err("cannot register miscdev on minor=%d (err=%d)\n",
> - WATCHDOG_MINOR, ret);
> + ret = watchdog_register_device(&wdt_dev);
> + if (ret)
> goto unreg_reboot;
> - }
>
> pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
> - timeout, nowayout);
> + wdt_dev.timeout, nowayout);
>
> -out:
> return ret;
> +
> unreg_reboot:
> unregister_reboot_notifier(&wdt_notifier);
> unreg_regions:
> release_region(wdt_io, 1);
> - goto out;
> + return ret;
> }
>
> static void __exit wdt_exit(void)
> {
> - misc_deregister(&wdt_miscdev);
> + watchdog_unregister_device(&wdt_dev);
> unregister_reboot_notifier(&wdt_notifier);
> release_region(wdt_io, 1);
> }
> @@ -396,4 +272,3 @@ module_exit(wdt_exit);
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("P?draig Brady <[email protected]>");
> MODULE_DESCRIPTION("w83627hf/thf WDT driver");
> -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
> --
> 1.7.9.7
>

2013-10-28 23:10:30

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v3 1/8] watchdog: w83627hf: Convert to watchdog infrastructure

On Mon, Oct 28, 2013 at 10:57:55PM +0100, Wim Van Sebroeck wrote:
> Hi Guenter,
>
> > Signed-off-by: Guenter Roeck <[email protected]>
> > ---
> > drivers/watchdog/Kconfig | 1 +
> > drivers/watchdog/w83627hf_wdt.c | 225 +++++++++------------------------------
> > 2 files changed, 51 insertions(+), 175 deletions(-)
> >
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index 362085d..c73db85 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -858,6 +858,7 @@ config VIA_WDT
> > config W83627HF_WDT
> > tristate "W83627HF/W83627DHG Watchdog Timer"
> > depends on X86
> > + select WATCHDOG_CORE
> > ---help---
> > This is the driver for the hardware watchdog on the W83627HF chipset
> > as used in Advantech PC-9578 and Tyan S2721-533 motherboards
> > diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
> > index 92f1326..51a22ab 100644
> > --- a/drivers/watchdog/w83627hf_wdt.c
> > +++ b/drivers/watchdog/w83627hf_wdt.c
> > @@ -1,6 +1,9 @@
> > /*
> > * w83627hf/thf WDT driver
> > *
> > + * (c) Copyright 2013 Guenter Roeck
> > + * converted to watchdog infrastructure
> > + *
> > * (c) Copyright 2007 Vlad Drukker <[email protected]>
> > * added support for W83627THF.
> > *
> > @@ -31,42 +34,27 @@
> > #include <linux/module.h>
> > #include <linux/moduleparam.h>
> > #include <linux/types.h>
> > -#include <linux/miscdevice.h>
> > #include <linux/watchdog.h>
> > -#include <linux/fs.h>
> > #include <linux/ioport.h>
> > #include <linux/notifier.h>
> > #include <linux/reboot.h>
> > #include <linux/init.h>
> > -#include <linux/spinlock.h>
> > #include <linux/io.h>
> > -#include <linux/uaccess.h>
> > -
> >
> > #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
> > #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
> >
> > -static unsigned long wdt_is_open;
> > -static char expect_close;
> > -static DEFINE_SPINLOCK(io_lock);
> > -
> > /* You must set this - there is no sane way to probe for this board. */
> > static int wdt_io = 0x2E;
> > module_param(wdt_io, int, 0);
> > MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
> >
> > -static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
> > +static int timeout; /* in seconds */
> > module_param(timeout, int, 0);
> > MODULE_PARM_DESC(timeout,
> > "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
> > __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
> >
> > -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) ")");
> > -
>
> Why do you remove the nowayout module param?
>
Hi Wim,

sorry, that is too long ago. I simply don't remember what drove me to do that.
Looking at other drivers, that doesn't seem to make much sense, does it ?

I'll be happy to resubmit the patch with the parameter restored, or submit
a patch on top of it to restore it. Please let me know what you prefer.

Thanks,
Guenter

2013-10-29 02:44:03

by Guenter Roeck

[permalink] [raw]
Subject: [PATCH v4] watchdog: w83627hf: Convert to watchdog infrastructure


Signed-off-by: Guenter Roeck <[email protected]>
---
v4: Restore 'nowayout' module parameter

The changes cause a trivial conflict with 'watchdog: w83627hf: Auto-detect
IO address and supported chips'. Please let me know if I should re-send
the entire series.

drivers/watchdog/Kconfig | 1 +
drivers/watchdog/w83627hf_wdt.c | 218 +++++++++------------------------------
2 files changed, 50 insertions(+), 169 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d1d53f3..dcaecd0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -868,6 +868,7 @@ config VIA_WDT
config W83627HF_WDT
tristate "W83627HF/W83627DHG Watchdog Timer"
depends on X86
+ select WATCHDOG_CORE
---help---
This is the driver for the hardware watchdog on the W83627HF chipset
as used in Advantech PC-9578 and Tyan S2721-533 motherboards
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 92f1326..e204c2b 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -1,6 +1,9 @@
/*
* w83627hf/thf WDT driver
*
+ * (c) Copyright 2013 Guenter Roeck
+ * converted to watchdog infrastructure
+ *
* (c) Copyright 2007 Vlad Drukker <[email protected]>
* added support for W83627THF.
*
@@ -31,31 +34,22 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
-#include <linux/miscdevice.h>
#include <linux/watchdog.h>
-#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
-#include <linux/spinlock.h>
#include <linux/io.h>
-#include <linux/uaccess.h>
-

#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */

-static unsigned long wdt_is_open;
-static char expect_close;
-static DEFINE_SPINLOCK(io_lock);
-
/* You must set this - there is no sane way to probe for this board. */
static int wdt_io = 0x2E;
module_param(wdt_io, int, 0);
MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");

-static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+static int timeout; /* in seconds */
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,
"Watchdog timeout in seconds. 1 <= timeout <= 255, default="
@@ -110,7 +104,7 @@ static void w83627hf_unselect_wd_register(void)
/* tyan motherboards seem to set F5 to 0x4C ?
* So explicitly init to appropriate value. */

-static void w83627hf_init(void)
+static void w83627hf_init(struct watchdog_device *wdog)
{
unsigned char t;

@@ -120,8 +114,8 @@ static void w83627hf_init(void)
t = inb_p(WDT_EFDR); /* read CRF6 */
if (t != 0) {
pr_info("Watchdog already running. Resetting timeout to %d sec\n",
- timeout);
- outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
+ wdog->timeout);
+ outb_p(wdog->timeout, WDT_EFDR); /* Write back to CRF6 */
}

outb_p(0xF5, WDT_EFER); /* Select CRF5 */
@@ -141,10 +135,8 @@ static void w83627hf_init(void)
w83627hf_unselect_wd_register();
}

-static void wdt_set_time(int timeout)
+static int wdt_set_time(unsigned int timeout)
{
- spin_lock(&io_lock);
-
w83627hf_select_wd_register();

outb_p(0xF6, WDT_EFER); /* Select CRF6 */
@@ -152,34 +144,30 @@ static void wdt_set_time(int timeout)

w83627hf_unselect_wd_register();

- spin_unlock(&io_lock);
+ return 0;
}

-static int wdt_ping(void)
+static int wdt_start(struct watchdog_device *wdog)
{
- wdt_set_time(timeout);
- return 0;
+ return wdt_set_time(wdog->timeout);
}

-static int wdt_disable(void)
+static int wdt_stop(struct watchdog_device *wdog)
{
- wdt_set_time(0);
- return 0;
+ return wdt_set_time(0);
}

-static int wdt_set_heartbeat(int t)
+static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
{
- if (t < 1 || t > 255)
- return -EINVAL;
- timeout = t;
+ wdt_set_time(timeout);
+ wdog->timeout = timeout;
+
return 0;
}

-static int wdt_get_time(void)
+static unsigned int wdt_get_time(struct watchdog_device *wdog)
{
- int timeleft;
-
- spin_lock(&io_lock);
+ unsigned int timeleft;

w83627hf_select_wd_register();

@@ -188,124 +176,17 @@ static int wdt_get_time(void)

w83627hf_unselect_wd_register();

- spin_unlock(&io_lock);
-
return timeleft;
}

-static ssize_t wdt_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- if (count) {
- if (!nowayout) {
- size_t i;
-
- expect_close = 0;
-
- for (i = 0; i != count; i++) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 42;
- }
- }
- wdt_ping();
- }
- return count;
-}
-
-static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- int timeval;
- static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
- WDIOF_MAGICCLOSE,
- .firmware_version = 1,
- .identity = "W83627HF WDT",
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &ident, sizeof(ident)))
- return -EFAULT;
- break;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
- case WDIOC_SETOPTIONS:
- {
- int options, retval = -EINVAL;
-
- if (get_user(options, p))
- return -EFAULT;
- if (options & WDIOS_DISABLECARD) {
- wdt_disable();
- retval = 0;
- }
- if (options & WDIOS_ENABLECARD) {
- wdt_ping();
- retval = 0;
- }
- return retval;
- }
- case WDIOC_KEEPALIVE:
- wdt_ping();
- break;
- case WDIOC_SETTIMEOUT:
- if (get_user(timeval, p))
- return -EFAULT;
- if (wdt_set_heartbeat(timeval))
- return -EINVAL;
- wdt_ping();
- /* Fall */
- case WDIOC_GETTIMEOUT:
- return put_user(timeout, p);
- case WDIOC_GETTIMELEFT:
- timeval = wdt_get_time();
- return put_user(timeval, p);
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(0, &wdt_is_open))
- return -EBUSY;
- /*
- * Activate
- */
-
- wdt_ping();
- return nonseekable_open(inode, file);
-}
-
-static int wdt_close(struct inode *inode, struct file *file)
-{
- if (expect_close == 42)
- wdt_disable();
- else {
- pr_crit("Unexpected close, not stopping watchdog!\n");
- wdt_ping();
- }
- expect_close = 0;
- clear_bit(0, &wdt_is_open);
- return 0;
-}
-
/*
* Notifier for system down
*/
-
static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
void *unused)
{
if (code == SYS_DOWN || code == SYS_HALT)
- wdt_disable(); /* Turn the WDT off */
+ wdt_set_time(0); /* Turn the WDT off */

return NOTIFY_DONE;
}
@@ -314,19 +195,26 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
* Kernel Interfaces
*/

-static const struct file_operations wdt_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = wdt_write,
- .unlocked_ioctl = wdt_ioctl,
- .open = wdt_open,
- .release = wdt_close,
+static struct watchdog_info wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+ .identity = "W83627HF Watchdog",
+};
+
+static struct watchdog_ops wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = wdt_start,
+ .stop = wdt_stop,
+ .ping = wdt_start,
+ .set_timeout = wdt_set_timeout,
+ .get_timeleft = wdt_get_time,
};

-static struct miscdevice wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &wdt_fops,
+static struct watchdog_device wdt_dev = {
+ .info = &wdt_info,
+ .ops = &wdt_ops,
+ .timeout = WATCHDOG_TIMEOUT,
+ .min_timeout = 1,
+ .max_timeout = 255,
};

/*
@@ -344,19 +232,15 @@ static int __init wdt_init(void)

pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");

- if (wdt_set_heartbeat(timeout)) {
- wdt_set_heartbeat(WATCHDOG_TIMEOUT);
- pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
- WATCHDOG_TIMEOUT);
- }
-
if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
pr_err("I/O address 0x%04x already in use\n", wdt_io);
- ret = -EIO;
- goto out;
+ return -EIO;
}

- w83627hf_init();
+ watchdog_init_timeout(&wdt_dev, timeout, NULL);
+ watchdog_set_nowayout(&wdt_dev, nowayout);
+
+ w83627hf_init(&wdt_dev);

ret = register_reboot_notifier(&wdt_notifier);
if (ret != 0) {
@@ -364,28 +248,25 @@ static int __init wdt_init(void)
goto unreg_regions;
}

- ret = misc_register(&wdt_miscdev);
- if (ret != 0) {
- pr_err("cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, ret);
+ ret = watchdog_register_device(&wdt_dev);
+ if (ret)
goto unreg_reboot;
- }

pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
- timeout, nowayout);
+ wdt_dev.timeout, nowayout);

-out:
return ret;
+
unreg_reboot:
unregister_reboot_notifier(&wdt_notifier);
unreg_regions:
release_region(wdt_io, 1);
- goto out;
+ return ret;
}

static void __exit wdt_exit(void)
{
- misc_deregister(&wdt_miscdev);
+ watchdog_unregister_device(&wdt_dev);
unregister_reboot_notifier(&wdt_notifier);
release_region(wdt_io, 1);
}
@@ -396,4 +277,3 @@ module_exit(wdt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("P?draig Brady <[email protected]>");
MODULE_DESCRIPTION("w83627hf/thf WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
--
1.7.9.7

2013-10-29 06:34:08

by Wim Van Sebroeck

[permalink] [raw]
Subject: Re: [PATCH v4] watchdog: w83627hf: Convert to watchdog infrastructure

Hi Guenter,

>
> Signed-off-by: Guenter Roeck <[email protected]>
> ---
> v4: Restore 'nowayout' module parameter
>
> The changes cause a trivial conflict with 'watchdog: w83627hf: Auto-detect
> IO address and supported chips'. Please let me know if I should re-send
> the entire series.

Let me review the other patches still before we do any re-sending.


Kind regards,
Wim.