Commit 40046d1a authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-watchdog.bkbits.net/linux-2.6-watchdog

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 4bd146ff 841b4bc2
...@@ -72,7 +72,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON ...@@ -72,7 +72,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
static void static void
wdt_ctrl(int timeout) w83627hf_select_wd_register(void)
{ {
outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Enter extended function mode */
outb_p(0x87, WDT_EFER); /* Again according to manual */ outb_p(0x87, WDT_EFER); /* Again according to manual */
...@@ -81,23 +81,64 @@ wdt_ctrl(int timeout) ...@@ -81,23 +81,64 @@ wdt_ctrl(int timeout)
outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
outb_p(0x30, WDT_EFER); /* select CR30 */ outb_p(0x30, WDT_EFER); /* select CR30 */
outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
}
static void
w83627hf_unselect_wd_register(void)
{
outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
}
/* tyan motherboards seem to set F5 to 0x4C ?
* So explicitly init to appropriate value. */
static void
w83627hf_init(void)
{
unsigned char t;
w83627hf_select_wd_register();
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 */
w83627hf_unselect_wd_register();
}
static void
wdt_ctrl(int timeout)
{
w83627hf_select_wd_register();
outb_p(0xF6, WDT_EFER); /* Select CRF6 */ outb_p(0xF6, WDT_EFER); /* Select CRF6 */
outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */
outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ w83627hf_unselect_wd_register();
} }
static void static int
wdt_ping(void) wdt_ping(void)
{ {
wdt_ctrl(timeout); wdt_ctrl(timeout);
return 0;
} }
static void static int
wdt_disable(void) wdt_disable(void)
{ {
wdt_ctrl(0); wdt_ctrl(0);
return 0;
}
static int
wdt_set_heartbeat(int t)
{
if ((t < 1) || (t > 63))
return -EINVAL;
timeout = t;
return 0;
} }
static ssize_t static ssize_t
...@@ -134,7 +175,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -134,7 +175,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static struct watchdog_info ident = { static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
.identity = "Advantech WDT", .identity = "W83627HF WDT",
}; };
switch (cmd) { switch (cmd) {
...@@ -154,9 +195,8 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -154,9 +195,8 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
if (get_user(new_timeout, (int *)arg)) if (get_user(new_timeout, (int *)arg))
return -EFAULT; return -EFAULT;
if ((new_timeout < 1) || (new_timeout > 63)) if (wdt_set_heartbeat(new_timeout))
return -EINVAL; return -EINVAL;
timeout = new_timeout;
wdt_ping(); wdt_ping();
/* Fall */ /* Fall */
...@@ -211,8 +251,8 @@ wdt_close(struct inode *inode, struct file *file) ...@@ -211,8 +251,8 @@ wdt_close(struct inode *inode, struct file *file)
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
wdt_ping(); wdt_ping();
} }
clear_bit(0, &wdt_is_open);
expect_close = 0; expect_close = 0;
clear_bit(0, &wdt_is_open);
return 0; return 0;
} }
...@@ -266,10 +306,10 @@ wdt_init(void) ...@@ -266,10 +306,10 @@ wdt_init(void)
printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n");
if (timeout < 1 || timeout > 63) { if (wdt_set_heartbeat(timeout)) {
timeout = WATCHDOG_TIMEOUT; wdt_set_heartbeat(WATCHDOG_TIMEOUT);
printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n", printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n",
timeout); WATCHDOG_TIMEOUT);
} }
if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
...@@ -279,6 +319,8 @@ wdt_init(void) ...@@ -279,6 +319,8 @@ wdt_init(void)
goto out; goto out;
} }
w83627hf_init();
ret = register_reboot_notifier(&wdt_notifier); ret = register_reboot_notifier(&wdt_notifier);
if (ret != 0) { if (ret != 0) {
printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment