1 /* 2 * intel TCO vendor specific watchdog driver support 3 * 4 * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 * 11 * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor 12 * provide warranty for any of this software. This material is 13 * provided "AS-IS" and at no charge. 14 */ 15 16 /* 17 * Includes, defines, variables, module parameters, ... 18 */ 19 20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 21 22 /* Module and version information */ 23 #define DRV_NAME "iTCO_vendor_support" 24 #define DRV_VERSION "1.04" 25 26 /* Includes */ 27 #include <linux/module.h> /* For module specific items */ 28 #include <linux/moduleparam.h> /* For new moduleparam's */ 29 #include <linux/types.h> /* For standard types (like size_t) */ 30 #include <linux/errno.h> /* For the -ENODEV/... values */ 31 #include <linux/kernel.h> /* For printk/panic/... */ 32 #include <linux/init.h> /* For __init/__exit/... */ 33 #include <linux/ioport.h> /* For io-port access */ 34 #include <linux/io.h> /* For inb/outb/... */ 35 36 #include "iTCO_vendor.h" 37 38 /* List of vendor support modes */ 39 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ 40 #define SUPERMICRO_OLD_BOARD 1 41 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems - no longer supported */ 42 #define SUPERMICRO_NEW_BOARD 2 43 /* Broken BIOS */ 44 #define BROKEN_BIOS 911 45 46 static int vendorsupport; 47 module_param(vendorsupport, int, 0); 48 MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=" 49 "0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS"); 50 51 /* 52 * Vendor Specific Support 53 */ 54 55 /* 56 * Vendor Support: 1 57 * Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE 58 * iTCO chipset: ICH2 59 * 60 * Code contributed by: R. Seretny <lkpatches@paypc.com> 61 * Documentation obtained by R. Seretny from SuperMicro Technical Support 62 * 63 * To enable Watchdog function: 64 * BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes 65 * This setting enables SMI to clear the watchdog expired flag. 66 * If BIOS or CPU fail which may cause SMI hang, then system will 67 * reboot. When application starts to use watchdog function, 68 * application has to take over the control from SMI. 69 * 70 * For P3TSSE, J36 jumper needs to be removed to enable the Watchdog 71 * function. 72 * 73 * Note: The system will reboot when Expire Flag is set TWICE. 74 * So, if the watchdog timer is 20 seconds, then the maximum hang 75 * time is about 40 seconds, and the minimum hang time is about 76 * 20.6 seconds. 77 */ 78 79 static void supermicro_old_pre_start(struct resource *smires) 80 { 81 unsigned long val32; 82 83 /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ 84 val32 = inl(smires->start); 85 val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ 86 outl(val32, smires->start); /* Needed to activate watchdog */ 87 } 88 89 static void supermicro_old_pre_stop(struct resource *smires) 90 { 91 unsigned long val32; 92 93 /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ 94 val32 = inl(smires->start); 95 val32 |= 0x00002000; /* Turn on SMI clearing watchdog */ 96 outl(val32, smires->start); /* Needed to deactivate watchdog */ 97 } 98 99 /* 100 * Vendor Support: 911 101 * Board: Some Intel ICHx based motherboards 102 * iTCO chipset: ICH7+ 103 * 104 * Some Intel motherboards have a broken BIOS implementation: i.e. 105 * the SMI handler clear's the TIMEOUT bit in the TC01_STS register 106 * and does not reload the time. Thus the TCO watchdog does not reboot 107 * the system. 108 * 109 * These are the conclusions of Andriy Gapon <avg@icyb.net.ua> after 110 * debugging: the SMI handler is quite simple - it tests value in 111 * TCO1_CNT against 0x800, i.e. checks TCO_TMR_HLT. If the bit is set 112 * the handler goes into an infinite loop, apparently to allow the 113 * second timeout and reboot. Otherwise it simply clears TIMEOUT bit 114 * in TCO1_STS and that's it. 115 * So the logic seems to be reversed, because it is hard to see how 116 * TIMEOUT can get set to 1 and SMI generated when TCO_TMR_HLT is set 117 * (other than a transitional effect). 118 * 119 * The only fix found to get the motherboard(s) to reboot is to put 120 * the glb_smi_en bit to 0. This is a dirty hack that bypasses the 121 * broken code by disabling Global SMI. 122 * 123 * WARNING: globally disabling SMI could possibly lead to dramatic 124 * problems, especially on laptops! I.e. various ACPI things where 125 * SMI is used for communication between OS and firmware. 126 * 127 * Don't use this fix if you don't need to!!! 128 */ 129 130 static void broken_bios_start(struct resource *smires) 131 { 132 unsigned long val32; 133 134 val32 = inl(smires->start); 135 /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# 136 Bit 0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */ 137 val32 &= 0xffffdffe; 138 outl(val32, smires->start); 139 } 140 141 static void broken_bios_stop(struct resource *smires) 142 { 143 unsigned long val32; 144 145 val32 = inl(smires->start); 146 /* Bit 13: TCO_EN -> 1 = Enables TCO logic generating an SMI# 147 Bit 0: GBL_SMI_EN -> 1 = Turn global SMI on again. */ 148 val32 |= 0x00002001; 149 outl(val32, smires->start); 150 } 151 152 /* 153 * Generic Support Functions 154 */ 155 156 void iTCO_vendor_pre_start(struct resource *smires, 157 unsigned int heartbeat) 158 { 159 switch (vendorsupport) { 160 case SUPERMICRO_OLD_BOARD: 161 supermicro_old_pre_start(smires); 162 break; 163 case BROKEN_BIOS: 164 broken_bios_start(smires); 165 break; 166 } 167 } 168 EXPORT_SYMBOL(iTCO_vendor_pre_start); 169 170 void iTCO_vendor_pre_stop(struct resource *smires) 171 { 172 switch (vendorsupport) { 173 case SUPERMICRO_OLD_BOARD: 174 supermicro_old_pre_stop(smires); 175 break; 176 case BROKEN_BIOS: 177 broken_bios_stop(smires); 178 break; 179 } 180 } 181 EXPORT_SYMBOL(iTCO_vendor_pre_stop); 182 183 int iTCO_vendor_check_noreboot_on(void) 184 { 185 switch (vendorsupport) { 186 case SUPERMICRO_OLD_BOARD: 187 return 0; 188 default: 189 return 1; 190 } 191 } 192 EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); 193 194 static int __init iTCO_vendor_init_module(void) 195 { 196 if (vendorsupport == SUPERMICRO_NEW_BOARD) { 197 pr_warn("Option vendorsupport=%d is no longer supported, " 198 "please use the w83627hf_wdt driver instead\n", 199 SUPERMICRO_NEW_BOARD); 200 return -EINVAL; 201 } 202 pr_info("vendor-support=%d\n", vendorsupport); 203 return 0; 204 } 205 206 static void __exit iTCO_vendor_exit_module(void) 207 { 208 pr_info("Module Unloaded\n"); 209 } 210 211 module_init(iTCO_vendor_init_module); 212 module_exit(iTCO_vendor_exit_module); 213 214 MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, " 215 "R. Seretny <lkpatches@paypc.com>"); 216 MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support"); 217 MODULE_VERSION(DRV_VERSION); 218 MODULE_LICENSE("GPL"); 219 220