aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/i6300esb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/i6300esb.c')
-rw-r--r--drivers/watchdog/i6300esb.c101
1 files changed, 64 insertions, 37 deletions
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 74f951c18b90..2dbe83570d65 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -13,7 +13,7 @@
13 * 13 *
14 * The timer is implemented in the following I/O controller hubs: 14 * The timer is implemented in the following I/O controller hubs:
15 * (See the intel documentation on http://developer.intel.com.) 15 * (See the intel documentation on http://developer.intel.com.)
16 * 6300ESB chip : document number 300641-003 16 * 6300ESB chip : document number 300641-004
17 * 17 *
18 * 2004YYZZ Ross Biro 18 * 2004YYZZ Ross Biro
19 * Initial version 0.01 19 * Initial version 0.01
@@ -34,7 +34,7 @@
34#include <linux/mm.h> 34#include <linux/mm.h>
35#include <linux/miscdevice.h> 35#include <linux/miscdevice.h>
36#include <linux/watchdog.h> 36#include <linux/watchdog.h>
37#include <linux/reboot.h> 37#include <linux/platform_device.h>
38#include <linux/init.h> 38#include <linux/init.h>
39#include <linux/pci.h> 39#include <linux/pci.h>
40#include <linux/ioport.h> 40#include <linux/ioport.h>
@@ -42,7 +42,7 @@
42#include <linux/io.h> 42#include <linux/io.h>
43 43
44/* Module and version information */ 44/* Module and version information */
45#define ESB_VERSION "0.03" 45#define ESB_VERSION "0.04"
46#define ESB_MODULE_NAME "i6300ESB timer" 46#define ESB_MODULE_NAME "i6300ESB timer"
47#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION 47#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
48#define PFX ESB_MODULE_NAME ": " 48#define PFX ESB_MODULE_NAME ": "
@@ -81,6 +81,7 @@ static unsigned long timer_alive;
81static struct pci_dev *esb_pci; 81static struct pci_dev *esb_pci;
82static unsigned short triggered; /* The status of the watchdog upon boot */ 82static unsigned short triggered; /* The status of the watchdog upon boot */
83static char esb_expect_close; 83static char esb_expect_close;
84static struct platform_device *esb_platform_device;
84 85
85/* module parameters */ 86/* module parameters */
86/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ 87/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
@@ -114,13 +115,18 @@ static inline void esb_unlock_registers(void)
114 writeb(ESB_UNLOCK2, ESB_RELOAD_REG); 115 writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
115} 116}
116 117
117static void esb_timer_start(void) 118static int esb_timer_start(void)
118{ 119{
119 u8 val; 120 u8 val;
120 121
122 spin_lock(&esb_lock);
123 esb_unlock_registers();
124 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
121 /* Enable or Enable + Lock? */ 125 /* Enable or Enable + Lock? */
122 val = 0x02 | (nowayout ? 0x01 : 0x00); 126 val = 0x02 | (nowayout ? 0x01 : 0x00);
123 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); 127 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
128 spin_unlock(&esb_lock);
129 return 0;
124} 130}
125 131
126static int esb_timer_stop(void) 132static int esb_timer_stop(void)
@@ -207,7 +213,6 @@ static int esb_open(struct inode *inode, struct file *file)
207 return -EBUSY; 213 return -EBUSY;
208 214
209 /* Reload and activate timer */ 215 /* Reload and activate timer */
210 esb_timer_keepalive();
211 esb_timer_start(); 216 esb_timer_start();
212 217
213 return nonseekable_open(inode, file); 218 return nonseekable_open(inode, file);
@@ -240,7 +245,8 @@ static ssize_t esb_write(struct file *file, const char __user *data,
240 * five months ago... */ 245 * five months ago... */
241 esb_expect_close = 0; 246 esb_expect_close = 0;
242 247
243 /* scan to see whether or not we got the magic character */ 248 /* scan to see whether or not we got the
249 * magic character */
244 for (i = 0; i != len; i++) { 250 for (i = 0; i != len; i++) {
245 char c; 251 char c;
246 if (get_user(c, data + i)) 252 if (get_user(c, data + i))
@@ -292,7 +298,6 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
292 } 298 }
293 299
294 if (new_options & WDIOS_ENABLECARD) { 300 if (new_options & WDIOS_ENABLECARD) {
295 esb_timer_keepalive();
296 esb_timer_start(); 301 esb_timer_start();
297 retval = 0; 302 retval = 0;
298 } 303 }
@@ -319,19 +324,6 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
319} 324}
320 325
321/* 326/*
322 * Notify system
323 */
324
325static int esb_notify_sys(struct notifier_block *this,
326 unsigned long code, void *unused)
327{
328 if (code == SYS_DOWN || code == SYS_HALT)
329 esb_timer_stop(); /* Turn the WDT off */
330
331 return NOTIFY_DONE;
332}
333
334/*
335 * Kernel Interfaces 327 * Kernel Interfaces
336 */ 328 */
337 329
@@ -350,10 +342,6 @@ static struct miscdevice esb_miscdev = {
350 .fops = &esb_fops, 342 .fops = &esb_fops,
351}; 343};
352 344
353static struct notifier_block esb_notifier = {
354 .notifier_call = esb_notify_sys,
355};
356
357/* 345/*
358 * Data for PCI driver interface 346 * Data for PCI driver interface
359 * 347 *
@@ -372,7 +360,7 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
372 * Init & exit routines 360 * Init & exit routines
373 */ 361 */
374 362
375static unsigned char __init esb_getdevice(void) 363static unsigned char __devinit esb_getdevice(void)
376{ 364{
377 u8 val1; 365 u8 val1;
378 unsigned short val2; 366 unsigned short val2;
@@ -443,7 +431,7 @@ err_devput:
443 return 0; 431 return 0;
444} 432}
445 433
446static int __init watchdog_init(void) 434static int __devinit esb_probe(struct platform_device *dev)
447{ 435{
448 int ret; 436 int ret;
449 437
@@ -459,19 +447,13 @@ static int __init watchdog_init(void)
459 "heartbeat value must be 1<heartbeat<2046, using %d\n", 447 "heartbeat value must be 1<heartbeat<2046, using %d\n",
460 heartbeat); 448 heartbeat);
461 } 449 }
462 ret = register_reboot_notifier(&esb_notifier);
463 if (ret != 0) {
464 printk(KERN_ERR PFX
465 "cannot register reboot notifier (err=%d)\n", ret);
466 goto err_unmap;
467 }
468 450
469 ret = misc_register(&esb_miscdev); 451 ret = misc_register(&esb_miscdev);
470 if (ret != 0) { 452 if (ret != 0) {
471 printk(KERN_ERR PFX 453 printk(KERN_ERR PFX
472 "cannot register miscdev on minor=%d (err=%d)\n", 454 "cannot register miscdev on minor=%d (err=%d)\n",
473 WATCHDOG_MINOR, ret); 455 WATCHDOG_MINOR, ret);
474 goto err_notifier; 456 goto err_unmap;
475 } 457 }
476 esb_timer_stop(); 458 esb_timer_stop();
477 printk(KERN_INFO PFX 459 printk(KERN_INFO PFX
@@ -479,8 +461,6 @@ static int __init watchdog_init(void)
479 BASEADDR, heartbeat, nowayout); 461 BASEADDR, heartbeat, nowayout);
480 return 0; 462 return 0;
481 463
482err_notifier:
483 unregister_reboot_notifier(&esb_notifier);
484err_unmap: 464err_unmap:
485 iounmap(BASEADDR); 465 iounmap(BASEADDR);
486/* err_release: */ 466/* err_release: */
@@ -492,7 +472,7 @@ err_unmap:
492 return ret; 472 return ret;
493} 473}
494 474
495static void __exit watchdog_cleanup(void) 475static int __devexit esb_remove(struct platform_device *dev)
496{ 476{
497 /* Stop the timer before we leave */ 477 /* Stop the timer before we leave */
498 if (!nowayout) 478 if (!nowayout)
@@ -500,11 +480,58 @@ static void __exit watchdog_cleanup(void)
500 480
501 /* Deregister */ 481 /* Deregister */
502 misc_deregister(&esb_miscdev); 482 misc_deregister(&esb_miscdev);
503 unregister_reboot_notifier(&esb_notifier);
504 iounmap(BASEADDR); 483 iounmap(BASEADDR);
505 pci_release_region(esb_pci, 0); 484 pci_release_region(esb_pci, 0);
506 pci_disable_device(esb_pci); 485 pci_disable_device(esb_pci);
507 pci_dev_put(esb_pci); 486 pci_dev_put(esb_pci);
487 return 0;
488}
489
490static void esb_shutdown(struct platform_device *dev)
491{
492 esb_timer_stop();
493}
494
495static struct platform_driver esb_platform_driver = {
496 .probe = esb_probe,
497 .remove = __devexit_p(esb_remove),
498 .shutdown = esb_shutdown,
499 .driver = {
500 .owner = THIS_MODULE,
501 .name = ESB_MODULE_NAME,
502 },
503};
504
505static int __init watchdog_init(void)
506{
507 int err;
508
509 printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
510 ESB_VERSION);
511
512 err = platform_driver_register(&esb_platform_driver);
513 if (err)
514 return err;
515
516 esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME,
517 -1, NULL, 0);
518 if (IS_ERR(esb_platform_device)) {
519 err = PTR_ERR(esb_platform_device);
520 goto unreg_platform_driver;
521 }
522
523 return 0;
524
525unreg_platform_driver:
526 platform_driver_unregister(&esb_platform_driver);
527 return err;
528}
529
530static void __exit watchdog_cleanup(void)
531{
532 platform_device_unregister(esb_platform_device);
533 platform_driver_unregister(&esb_platform_driver);
534 printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
508} 535}
509 536
510module_init(watchdog_init); 537module_init(watchdog_init);