[WATCHDOG] w83697hf/hg WDT driver - patch 10
authorSamuel Tardieu <sam@rfc1149.net>
Thu, 7 Sep 2006 09:57:00 +0000 (11:57 +0200)
committerWim Van Sebroeck <wim@iguana.be>
Wed, 4 Oct 2006 20:45:11 +0000 (22:45 +0200)
This is patch 10 in the series of patches that converts
Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's
w83697hf/hg watchdog driver.

This patch contains following changes:
 - check whether the device is really present
   (we *can* probe for the device now).

Signed-off-by: Samuel Tardieu <sam@rfc1149.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
drivers/char/watchdog/w83697hf_wdt.c

index f62f172387121d2840e23d370983db2ed5965e95..4e0bd4e714e3581e394483f229dbc2b0e4f618d0 100644 (file)
@@ -49,9 +49,9 @@ static char expect_close;
 static spinlock_t io_lock;
 
 /* You must set this - there is no sane way to probe for this board. */
-static int wdt_io = 0x2E;
+static int wdt_io = 0x2e;
 module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io, "w83697hf WDT io port (default 0x2E)");
+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);
@@ -331,28 +331,62 @@ 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)) {
+               printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io);
+               return -EIO;
+       }
+
+       printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io);
+       w83697hf_unlock();
+       if (w83697hf_get_reg(0x20) == 0x60) {
+               printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io);
+               w83697hf_lock();
+               return 0;
+       }
+       w83697hf_lock();        /* Reprotect in case it was a compatible device */
+
+       printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
+       release_region(wdt_io, 2);
+       return -EIO;
+}
+
 static int __init
 wdt_init(void)
 {
-       int ret;
+       int ret, autodetect;
 
        spin_lock_init(&io_lock);
 
        printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
 
+       autodetect = wdt_io == 0;
+       if (autodetect)
+               wdt_io = 0x2e;
+
+       if (!w83697hf_check_wdt())
+               goto found;
+
+       if (autodetect) {
+               wdt_io = 0x4e;
+               if (!w83697hf_check_wdt())
+                       goto found;
+       }
+
+       printk (KERN_ERR PFX "No W83697HF/HG could be found\n");
+       ret = -EIO;
+       goto out;
+
+found:
+
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
                printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n",
                        WATCHDOG_TIMEOUT);
        }
 
-       if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
-               ret = -EIO;
-               goto out;
-       }
-
        w83697hf_init();
 
        ret = register_reboot_notifier(&wdt_notifier);