[WATCHDOG] Add iTCO vendor specific support

Add vendor specific support to the intel TCO timer based watchdog
devices. At this moment we only have additional support for some
SuperMicro Inc. motherboards.

Signed-off-by: Robert Seretny <lkpatches@paypc.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index b6f29cb..7eac922 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -48,8 +48,8 @@
 
 /* Module and version information */
 #define DRV_NAME        "iTCO_wdt"
-#define DRV_VERSION     "1.00"
-#define DRV_RELDATE     "08-Oct-2006"
+#define DRV_VERSION     "1.01"
+#define DRV_RELDATE     "11-Nov-2006"
 #define PFX		DRV_NAME ": "
 
 /* Includes */
@@ -189,6 +189,21 @@
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
+/* iTCO Vendor Specific Support hooks */
+#ifdef CONFIG_ITCO_VENDOR_SUPPORT
+extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_stop(unsigned long);
+extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
+extern int iTCO_vendor_check_noreboot_on(void);
+#else
+#define iTCO_vendor_pre_start(acpibase, heartbeat)	{}
+#define iTCO_vendor_pre_stop(acpibase)			{}
+#define iTCO_vendor_pre_keepalive(acpibase,heartbeat)	{}
+#define iTCO_vendor_pre_set_heartbeat(heartbeat)	{}
+#define iTCO_vendor_check_noreboot_on()			1	/* 1=check noreboot; 0=don't check */
+#endif
+
 /*
  * Some TCO specific functions
  */
@@ -249,6 +264,8 @@
 
 	spin_lock(&iTCO_wdt_private.io_lock);
 
+	iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
+
 	/* disable chipset's NO_REBOOT bit */
 	if (iTCO_wdt_unset_NO_REBOOT_bit()) {
 		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
@@ -273,6 +290,8 @@
 
 	spin_lock(&iTCO_wdt_private.io_lock);
 
+	iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
+
 	/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
 	val = inw(TCO1_CNT);
 	val |= 0x0800;
@@ -293,6 +312,8 @@
 {
 	spin_lock(&iTCO_wdt_private.io_lock);
 
+	iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
+
 	/* Reload the timer by writing to the TCO Timer Counter register */
 	if (iTCO_wdt_private.iTCO_version == 2) {
 		outw(0x01, TCO_RLD);
@@ -319,6 +340,8 @@
 	    ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
 		return -EINVAL;
 
+	iTCO_vendor_pre_set_heartbeat(tmrval);
+
 	/* Write new heartbeat to watchdog */
 	if (iTCO_wdt_private.iTCO_version == 2) {
 		spin_lock(&iTCO_wdt_private.io_lock);
@@ -569,7 +592,7 @@
 	}
 
 	/* Check chipset's NO_REBOOT bit */
-	if (iTCO_wdt_unset_NO_REBOOT_bit()) {
+	if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
 		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
 		ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
 		goto out;