patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / char / watchdog / w83627hf_wdt.c
index bbf8d06..7a12930 100644 (file)
@@ -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 */
 
 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); /* Again according to manual */
@@ -81,23 +81,64 @@ wdt_ctrl(int timeout)
        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)
+{
+       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(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_ctrl(timeout);
+       return 0;
 }
 
-static void
+static int
 wdt_disable(void)
 {
        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
@@ -134,7 +175,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        static struct watchdog_info ident = {
                .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
                .firmware_version = 1,
-               .identity = "Advantech WDT",
+               .identity = "W83627HF WDT",
        };
 
        switch (cmd) {
@@ -154,9 +195,8 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case WDIOC_SETTIMEOUT:
          if (get_user(new_timeout, (int *)arg))
                  return -EFAULT;
-         if ((new_timeout < 1) || (new_timeout > 63))
+         if (wdt_set_heartbeat(new_timeout))
                  return -EINVAL;
-         timeout = new_timeout;
          wdt_ping();
          /* Fall */
 
@@ -211,8 +251,8 @@ wdt_close(struct inode *inode, struct file *file)
                printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
-       clear_bit(0, &wdt_is_open);
        expect_close = 0;
+       clear_bit(0, &wdt_is_open);
        return 0;
 }
 
@@ -264,12 +304,12 @@ wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
+       printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n");
 
-       if (timeout < 1 || timeout > 63) {
-               timeout = WATCHDOG_TIMEOUT;
-               printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
-                       timeout);
+       if (wdt_set_heartbeat(timeout)) {
+               wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
@@ -279,6 +319,8 @@ wdt_init(void)
                goto out;
        }
 
+       w83627hf_init();
+
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",