The advantech boards have multiple watchdog types, so this wasn't accepted as is into 2.4. I updated the patch for 2.6 which was accepted. diff -Naru linux-2.4.20/drivers/char/advantechwdt.c linux-2.4.20-pb/drivers/char/advantechwdt.c --- linux-2.4.20/drivers/char/advantechwdt.c 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.20-pb/drivers/char/advantechwdt.c 2003-10-14 15:48:30.000000000 +0100 @@ -22,6 +22,9 @@ * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * + * 04-Oct-2003 Pádraig Brady + * Changed to work on PCM-9578 (W83627HF) */ #include @@ -43,19 +46,10 @@ static unsigned long advwdt_is_open; static char adv_expect_close; -/* - * You must set these - there is no sane way to probe for this board. - * - * To enable or restart, write the timeout value in seconds (1 to 63) - * to I/O port wdt_start. To disable, read I/O port wdt_stop. - * Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but - * check your manual (at least the PCA-6159 seems to be different - - * the manual says wdt_stop is 0x43, not 0x443). - * (0x43 is also a write-only control register for the 8254 timer!) - */ - -static int wdt_stop = 0x443; -static int wdt_start = 0x443; +static int wdt_io = 0x2E; +#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ +#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ +#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ static int wd_margin = 60; /* 60 sec default timeout */ @@ -76,14 +70,12 @@ static int __init adv_setup(char *str) { - int ints[4]; + int ints[3]; str = get_options(str, ARRAY_SIZE(ints), ints); if(ints[0] > 0){ - wdt_stop = ints[1]; - if(ints[0] > 1) - wdt_start = ints[2]; + wdt_io = ints[1]; } return 1; @@ -93,22 +85,36 @@ #endif /* !MODULE */ -MODULE_PARM(wdt_stop, "i"); -MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)"); -MODULE_PARM(wdt_start, "i"); -MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)"); +MODULE_PARM(wdt_io, "i"); +MODULE_PARM_DESC(wdt_io, "Advantech WDT io port (default 0x2E)"); + +static void +advwdt_ctrl(int timeout) +{ + outb_p(0x87, WDT_EFER); /* Enter extended function mode */ + outb_p(0x87, WDT_EFER); /* Again according to manual */ + + outb_p(0x07, WDT_EFER); /* point to logical device number reg */ + 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 */ + + 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 */ +} static void advwdt_ping(void) { - /* Write a watchdog value */ - outb_p(wd_margin, wdt_start); + advwdt_ctrl(wd_margin); } static void advwdt_disable(void) { - inb_p(wdt_stop); + advwdt_ctrl(0); } static ssize_t @@ -132,7 +138,7 @@ adv_expect_close = 42; } } - advwdt_ping(); + advwdt_ping(); } return count; } @@ -278,9 +284,7 @@ printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); misc_register(&advwdt_miscdev); - if(wdt_stop != wdt_start) - request_region(wdt_stop, 1, "Advantech WDT"); - request_region(wdt_start, 1, "Advantech WDT"); + request_region(wdt_io, 1, "Advantech WDT"); register_reboot_notifier(&advwdt_notifier); return 0; } @@ -290,17 +294,15 @@ { misc_deregister(&advwdt_miscdev); unregister_reboot_notifier(&advwdt_notifier); - if(wdt_stop != wdt_start) - release_region(wdt_stop,1); - release_region(wdt_start,1); + release_region(wdt_io,1); } module_init(advwdt_init); module_exit(advwdt_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marek Michalkiewicz "); -MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver"); +MODULE_AUTHOR("Pádraig Brady "); +MODULE_DESCRIPTION("Advantech Single Board Computer (9578) WDT driver"); EXPORT_NO_SYMBOLS; /* end of advantechwdt.c */