[WATCHDOG] w83697hf/hg WDT driver - patch 15
[pandora-kernel.git] / drivers / char / watchdog / w83697hf_wdt.c
index 4e0bd4e..78b6540 100644 (file)
@@ -83,8 +83,8 @@ w83697hf_lock(void)
 }
 
 /*
- *     The two functions w83697hf_get_reg() and w83697hf_set_reg()
- *     must be called with the device unlocked.
+ *     The three functions w83697hf_get_reg(), w83697hf_set_reg() and
+ *     w83697hf_write_timeout() must be called with the device unlocked.
  */
 
 static unsigned char
@@ -102,18 +102,20 @@ w83697hf_set_reg(unsigned char reg, unsigned char data)
 }
 
 static void
-w83697hf_select_wd_register(void)
+w83697hf_write_timeout(int timeout)
 {
-       w83697hf_unlock();
-
-       w83697hf_set_reg(0x29, 0x20);   /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
+       w83697hf_set_reg(0xF4, timeout);        /* Write Timeout counter to CRF4 */
+}
 
+static void
+w83697hf_select_wdt(void)
+{
+       w83697hf_unlock();
        w83697hf_set_reg(0x07, 0x08);   /* Switch to logic device 8 (GPIO2) */
-       w83697hf_set_reg(0x30, 0x01);   /* Enable timer/activate GPIO2 via bit 0 */
 }
 
-static void
-w83697hf_unselect_wd_register(void)
+static inline void
+w83697hf_deselect_wdt(void)
 {
        w83697hf_lock();
 }
@@ -121,47 +123,60 @@ w83697hf_unselect_wd_register(void)
 static void
 w83697hf_init(void)
 {
-       unsigned char t;
+       unsigned char bbuf;
 
-       w83697hf_select_wd_register();
+       w83697hf_select_wdt();
 
-       t = w83697hf_get_reg(0xF3);     /* Read CRF3 */
-       if (t != 0) {
-               printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout);
-               w83697hf_set_reg(0xF3, timeout);        /* Write new timeout */
-       }
-       t = w83697hf_get_reg(0xF4);     /* Read CRF4 */
-       t&=~0x0C;                       /* set second mode & disable keyboard turning off watchdog */
-       w83697hf_set_reg(0xF4, t);      /* Write back to CRF4 */
+       bbuf = w83697hf_get_reg(0x29);
+       bbuf &= ~0x60;
+       bbuf |= 0x20;
+       w83697hf_set_reg(0x29, bbuf);   /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
 
-       w83697hf_unselect_wd_register();
+       bbuf = w83697hf_get_reg(0xF3);
+       bbuf &= ~0x04;
+       w83697hf_set_reg(0xF3, bbuf);   /* Count mode is seconds */
+
+       w83697hf_deselect_wdt();
 }
 
-static void
-wdt_ctrl(int timeout)
+static int
+wdt_ping(void)
 {
        spin_lock(&io_lock);
+       w83697hf_select_wdt();
 
-       w83697hf_select_wd_register();
-
-       w83697hf_set_reg(0xF4, timeout);        /* Write Timeout counter to CRF4 */
-
-       w83697hf_unselect_wd_register();
+       w83697hf_write_timeout(timeout);
 
+       w83697hf_deselect_wdt();
        spin_unlock(&io_lock);
+       return 0;
 }
 
 static int
-wdt_ping(void)
+wdt_enable(void)
 {
-       wdt_ctrl(timeout);
+       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);
        return 0;
 }
 
 static int
 wdt_disable(void)
 {
-       wdt_ctrl(0);
+       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);
        return 0;
 }
 
@@ -248,7 +263,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                }
 
                if (options & WDIOS_ENABLECARD) {
-                       wdt_ping();
+                       wdt_enable();
                        retval = 0;
                }
 
@@ -270,7 +285,7 @@ wdt_open(struct inode *inode, struct file *file)
         *      Activate
         */
 
-       wdt_ping();
+       wdt_enable();
        return nonseekable_open(inode, file);
 }
 
@@ -380,6 +395,8 @@ wdt_init(void)
        goto out;
 
 found:
+       w83697hf_init();
+       wdt_disable();  /* Disable watchdog until first use */
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
@@ -387,8 +404,6 @@ found:
                        WATCHDOG_TIMEOUT);
        }
 
-       w83697hf_init();
-
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",