diff options
-rw-r--r-- | drivers/char/watchdog/w83697hf_wdt.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index f62f17238712..4e0bd4e714e3 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c | |||
@@ -49,9 +49,9 @@ static char expect_close; | |||
49 | static spinlock_t io_lock; | 49 | static spinlock_t io_lock; |
50 | 50 | ||
51 | /* You must set this - there is no sane way to probe for this board. */ | 51 | /* You must set this - there is no sane way to probe for this board. */ |
52 | static int wdt_io = 0x2E; | 52 | static int wdt_io = 0x2e; |
53 | module_param(wdt_io, int, 0); | 53 | module_param(wdt_io, int, 0); |
54 | MODULE_PARM_DESC(wdt_io, "w83697hf WDT io port (default 0x2E)"); | 54 | MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)"); |
55 | 55 | ||
56 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 56 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
57 | module_param(timeout, int, 0); | 57 | module_param(timeout, int, 0); |
@@ -331,28 +331,62 @@ static struct notifier_block wdt_notifier = { | |||
331 | .notifier_call = wdt_notify_sys, | 331 | .notifier_call = wdt_notify_sys, |
332 | }; | 332 | }; |
333 | 333 | ||
334 | static int | ||
335 | w83697hf_check_wdt(void) | ||
336 | { | ||
337 | if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { | ||
338 | printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io); | ||
339 | return -EIO; | ||
340 | } | ||
341 | |||
342 | printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io); | ||
343 | w83697hf_unlock(); | ||
344 | if (w83697hf_get_reg(0x20) == 0x60) { | ||
345 | printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io); | ||
346 | w83697hf_lock(); | ||
347 | return 0; | ||
348 | } | ||
349 | w83697hf_lock(); /* Reprotect in case it was a compatible device */ | ||
350 | |||
351 | printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); | ||
352 | release_region(wdt_io, 2); | ||
353 | return -EIO; | ||
354 | } | ||
355 | |||
334 | static int __init | 356 | static int __init |
335 | wdt_init(void) | 357 | wdt_init(void) |
336 | { | 358 | { |
337 | int ret; | 359 | int ret, autodetect; |
338 | 360 | ||
339 | spin_lock_init(&io_lock); | 361 | spin_lock_init(&io_lock); |
340 | 362 | ||
341 | printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); | 363 | printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); |
342 | 364 | ||
365 | autodetect = wdt_io == 0; | ||
366 | if (autodetect) | ||
367 | wdt_io = 0x2e; | ||
368 | |||
369 | if (!w83697hf_check_wdt()) | ||
370 | goto found; | ||
371 | |||
372 | if (autodetect) { | ||
373 | wdt_io = 0x4e; | ||
374 | if (!w83697hf_check_wdt()) | ||
375 | goto found; | ||
376 | } | ||
377 | |||
378 | printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); | ||
379 | ret = -EIO; | ||
380 | goto out; | ||
381 | |||
382 | found: | ||
383 | |||
343 | if (wdt_set_heartbeat(timeout)) { | 384 | if (wdt_set_heartbeat(timeout)) { |
344 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 385 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |
345 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", | 386 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", |
346 | WATCHDOG_TIMEOUT); | 387 | WATCHDOG_TIMEOUT); |
347 | } | 388 | } |
348 | 389 | ||
349 | if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { | ||
350 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
351 | wdt_io); | ||
352 | ret = -EIO; | ||
353 | goto out; | ||
354 | } | ||
355 | |||
356 | w83697hf_init(); | 390 | w83697hf_init(); |
357 | 391 | ||
358 | ret = register_reboot_notifier(&wdt_notifier); | 392 | ret = register_reboot_notifier(&wdt_notifier); |