1d0173278SGuenter Roeck // SPDX-License-Identifier: GPL-2.0+ 2e033351dSWim Van Sebroeck /* 3e033351dSWim Van Sebroeck * intel TCO vendor specific watchdog driver support 4e033351dSWim Van Sebroeck * 512d60e28SWim Van Sebroeck * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. 6e033351dSWim Van Sebroeck * 7e033351dSWim Van Sebroeck * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor 8e033351dSWim Van Sebroeck * provide warranty for any of this software. This material is 9e033351dSWim Van Sebroeck * provided "AS-IS" and at no charge. 10e033351dSWim Van Sebroeck */ 11e033351dSWim Van Sebroeck 12e033351dSWim Van Sebroeck /* 13e033351dSWim Van Sebroeck * Includes, defines, variables, module parameters, ... 14e033351dSWim Van Sebroeck */ 15e033351dSWim Van Sebroeck 1627c766aaSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1727c766aaSJoe Perches 18e033351dSWim Van Sebroeck /* Module and version information */ 19e033351dSWim Van Sebroeck #define DRV_NAME "iTCO_vendor_support" 2055e8ddecSWim Van Sebroeck #define DRV_VERSION "1.04" 21e033351dSWim Van Sebroeck 22e033351dSWim Van Sebroeck /* Includes */ 23e033351dSWim Van Sebroeck #include <linux/module.h> /* For module specific items */ 24e033351dSWim Van Sebroeck #include <linux/moduleparam.h> /* For new moduleparam's */ 25e033351dSWim Van Sebroeck #include <linux/types.h> /* For standard types (like size_t) */ 26e033351dSWim Van Sebroeck #include <linux/errno.h> /* For the -ENODEV/... values */ 27e033351dSWim Van Sebroeck #include <linux/kernel.h> /* For printk/panic/... */ 28e033351dSWim Van Sebroeck #include <linux/init.h> /* For __init/__exit/... */ 29e033351dSWim Van Sebroeck #include <linux/ioport.h> /* For io-port access */ 300e6fa3fbSAlan Cox #include <linux/io.h> /* For inb/outb/... */ 310e6fa3fbSAlan Cox 320e6fa3fbSAlan Cox #include "iTCO_vendor.h" 33e033351dSWim Van Sebroeck 34e033351dSWim Van Sebroeck /* List of vendor support modes */ 350e6fa3fbSAlan Cox /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ 360e6fa3fbSAlan Cox #define SUPERMICRO_OLD_BOARD 1 372c05318aSJean Delvare /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems - no longer supported */ 380e6fa3fbSAlan Cox #define SUPERMICRO_NEW_BOARD 2 3955e8ddecSWim Van Sebroeck /* Broken BIOS */ 4055e8ddecSWim Van Sebroeck #define BROKEN_BIOS 911 41e033351dSWim Van Sebroeck 42*7ca6ee38SMika Westerberg int iTCO_vendorsupport; 43*7ca6ee38SMika Westerberg EXPORT_SYMBOL(iTCO_vendorsupport); 44*7ca6ee38SMika Westerberg 45*7ca6ee38SMika Westerberg module_param_named(vendorsupport, iTCO_vendorsupport, int, 0); 46143a2e54SWim Van Sebroeck MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=" 472c05318aSJean Delvare "0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS"); 48e033351dSWim Van Sebroeck 49e033351dSWim Van Sebroeck /* 50e033351dSWim Van Sebroeck * Vendor Specific Support 51e033351dSWim Van Sebroeck */ 52e033351dSWim Van Sebroeck 53e033351dSWim Van Sebroeck /* 54e033351dSWim Van Sebroeck * Vendor Support: 1 55e033351dSWim Van Sebroeck * Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE 56e033351dSWim Van Sebroeck * iTCO chipset: ICH2 57e033351dSWim Van Sebroeck * 58e033351dSWim Van Sebroeck * Code contributed by: R. Seretny <lkpatches@paypc.com> 59e033351dSWim Van Sebroeck * Documentation obtained by R. Seretny from SuperMicro Technical Support 60e033351dSWim Van Sebroeck * 61e033351dSWim Van Sebroeck * To enable Watchdog function: 62e033351dSWim Van Sebroeck * BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes 63e033351dSWim Van Sebroeck * This setting enables SMI to clear the watchdog expired flag. 64e033351dSWim Van Sebroeck * If BIOS or CPU fail which may cause SMI hang, then system will 65e033351dSWim Van Sebroeck * reboot. When application starts to use watchdog function, 66e033351dSWim Van Sebroeck * application has to take over the control from SMI. 67e033351dSWim Van Sebroeck * 68e033351dSWim Van Sebroeck * For P3TSSE, J36 jumper needs to be removed to enable the Watchdog 69e033351dSWim Van Sebroeck * function. 70e033351dSWim Van Sebroeck * 71e033351dSWim Van Sebroeck * Note: The system will reboot when Expire Flag is set TWICE. 72e033351dSWim Van Sebroeck * So, if the watchdog timer is 20 seconds, then the maximum hang 73e033351dSWim Van Sebroeck * time is about 40 seconds, and the minimum hang time is about 74e033351dSWim Van Sebroeck * 20.6 seconds. 75e033351dSWim Van Sebroeck */ 76e033351dSWim Van Sebroeck 77887c8ec7SAaron Sierra static void supermicro_old_pre_start(struct resource *smires) 7812d60e28SWim Van Sebroeck { 7912d60e28SWim Van Sebroeck unsigned long val32; 8012d60e28SWim Van Sebroeck 8112d60e28SWim Van Sebroeck /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ 82887c8ec7SAaron Sierra val32 = inl(smires->start); 8312d60e28SWim Van Sebroeck val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ 84887c8ec7SAaron Sierra outl(val32, smires->start); /* Needed to activate watchdog */ 8512d60e28SWim Van Sebroeck } 8612d60e28SWim Van Sebroeck 87887c8ec7SAaron Sierra static void supermicro_old_pre_stop(struct resource *smires) 8812d60e28SWim Van Sebroeck { 8912d60e28SWim Van Sebroeck unsigned long val32; 9012d60e28SWim Van Sebroeck 9112d60e28SWim Van Sebroeck /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ 92887c8ec7SAaron Sierra val32 = inl(smires->start); 9312d60e28SWim Van Sebroeck val32 |= 0x00002000; /* Turn on SMI clearing watchdog */ 94887c8ec7SAaron Sierra outl(val32, smires->start); /* Needed to deactivate watchdog */ 9512d60e28SWim Van Sebroeck } 9612d60e28SWim Van Sebroeck 97e033351dSWim Van Sebroeck /* 9855e8ddecSWim Van Sebroeck * Vendor Support: 911 9955e8ddecSWim Van Sebroeck * Board: Some Intel ICHx based motherboards 10055e8ddecSWim Van Sebroeck * iTCO chipset: ICH7+ 10155e8ddecSWim Van Sebroeck * 10255e8ddecSWim Van Sebroeck * Some Intel motherboards have a broken BIOS implementation: i.e. 10355e8ddecSWim Van Sebroeck * the SMI handler clear's the TIMEOUT bit in the TC01_STS register 10455e8ddecSWim Van Sebroeck * and does not reload the time. Thus the TCO watchdog does not reboot 10555e8ddecSWim Van Sebroeck * the system. 10655e8ddecSWim Van Sebroeck * 10755e8ddecSWim Van Sebroeck * These are the conclusions of Andriy Gapon <avg@icyb.net.ua> after 10855e8ddecSWim Van Sebroeck * debugging: the SMI handler is quite simple - it tests value in 10955e8ddecSWim Van Sebroeck * TCO1_CNT against 0x800, i.e. checks TCO_TMR_HLT. If the bit is set 11055e8ddecSWim Van Sebroeck * the handler goes into an infinite loop, apparently to allow the 11155e8ddecSWim Van Sebroeck * second timeout and reboot. Otherwise it simply clears TIMEOUT bit 11255e8ddecSWim Van Sebroeck * in TCO1_STS and that's it. 11355e8ddecSWim Van Sebroeck * So the logic seems to be reversed, because it is hard to see how 11455e8ddecSWim Van Sebroeck * TIMEOUT can get set to 1 and SMI generated when TCO_TMR_HLT is set 11555e8ddecSWim Van Sebroeck * (other than a transitional effect). 11655e8ddecSWim Van Sebroeck * 11755e8ddecSWim Van Sebroeck * The only fix found to get the motherboard(s) to reboot is to put 11855e8ddecSWim Van Sebroeck * the glb_smi_en bit to 0. This is a dirty hack that bypasses the 11955e8ddecSWim Van Sebroeck * broken code by disabling Global SMI. 12055e8ddecSWim Van Sebroeck * 12155e8ddecSWim Van Sebroeck * WARNING: globally disabling SMI could possibly lead to dramatic 12255e8ddecSWim Van Sebroeck * problems, especially on laptops! I.e. various ACPI things where 12355e8ddecSWim Van Sebroeck * SMI is used for communication between OS and firmware. 12455e8ddecSWim Van Sebroeck * 12555e8ddecSWim Van Sebroeck * Don't use this fix if you don't need to!!! 12655e8ddecSWim Van Sebroeck */ 12755e8ddecSWim Van Sebroeck 128887c8ec7SAaron Sierra static void broken_bios_start(struct resource *smires) 12955e8ddecSWim Van Sebroeck { 13055e8ddecSWim Van Sebroeck unsigned long val32; 13155e8ddecSWim Van Sebroeck 132887c8ec7SAaron Sierra val32 = inl(smires->start); 13355e8ddecSWim Van Sebroeck /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# 13455e8ddecSWim Van Sebroeck Bit 0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */ 13555e8ddecSWim Van Sebroeck val32 &= 0xffffdffe; 136887c8ec7SAaron Sierra outl(val32, smires->start); 13755e8ddecSWim Van Sebroeck } 13855e8ddecSWim Van Sebroeck 139887c8ec7SAaron Sierra static void broken_bios_stop(struct resource *smires) 14055e8ddecSWim Van Sebroeck { 14155e8ddecSWim Van Sebroeck unsigned long val32; 14255e8ddecSWim Van Sebroeck 143887c8ec7SAaron Sierra val32 = inl(smires->start); 14455e8ddecSWim Van Sebroeck /* Bit 13: TCO_EN -> 1 = Enables TCO logic generating an SMI# 14555e8ddecSWim Van Sebroeck Bit 0: GBL_SMI_EN -> 1 = Turn global SMI on again. */ 14655e8ddecSWim Van Sebroeck val32 |= 0x00002001; 147887c8ec7SAaron Sierra outl(val32, smires->start); 14855e8ddecSWim Van Sebroeck } 14955e8ddecSWim Van Sebroeck 15055e8ddecSWim Van Sebroeck /* 151e033351dSWim Van Sebroeck * Generic Support Functions 152e033351dSWim Van Sebroeck */ 153e033351dSWim Van Sebroeck 154887c8ec7SAaron Sierra void iTCO_vendor_pre_start(struct resource *smires, 155e033351dSWim Van Sebroeck unsigned int heartbeat) 156e033351dSWim Van Sebroeck { 157*7ca6ee38SMika Westerberg switch (iTCO_vendorsupport) { 15855e8ddecSWim Van Sebroeck case SUPERMICRO_OLD_BOARD: 159887c8ec7SAaron Sierra supermicro_old_pre_start(smires); 16055e8ddecSWim Van Sebroeck break; 16155e8ddecSWim Van Sebroeck case BROKEN_BIOS: 162887c8ec7SAaron Sierra broken_bios_start(smires); 16355e8ddecSWim Van Sebroeck break; 16455e8ddecSWim Van Sebroeck } 165e033351dSWim Van Sebroeck } 166e033351dSWim Van Sebroeck EXPORT_SYMBOL(iTCO_vendor_pre_start); 167e033351dSWim Van Sebroeck 168887c8ec7SAaron Sierra void iTCO_vendor_pre_stop(struct resource *smires) 169e033351dSWim Van Sebroeck { 170*7ca6ee38SMika Westerberg switch (iTCO_vendorsupport) { 17155e8ddecSWim Van Sebroeck case SUPERMICRO_OLD_BOARD: 172887c8ec7SAaron Sierra supermicro_old_pre_stop(smires); 17355e8ddecSWim Van Sebroeck break; 17455e8ddecSWim Van Sebroeck case BROKEN_BIOS: 175887c8ec7SAaron Sierra broken_bios_stop(smires); 17655e8ddecSWim Van Sebroeck break; 17755e8ddecSWim Van Sebroeck } 178e033351dSWim Van Sebroeck } 179e033351dSWim Van Sebroeck EXPORT_SYMBOL(iTCO_vendor_pre_stop); 180e033351dSWim Van Sebroeck 181e033351dSWim Van Sebroeck int iTCO_vendor_check_noreboot_on(void) 182e033351dSWim Van Sebroeck { 183*7ca6ee38SMika Westerberg switch (iTCO_vendorsupport) { 184e033351dSWim Van Sebroeck case SUPERMICRO_OLD_BOARD: 185e033351dSWim Van Sebroeck return 0; 186e033351dSWim Van Sebroeck default: 187e033351dSWim Van Sebroeck return 1; 188e033351dSWim Van Sebroeck } 189e033351dSWim Van Sebroeck } 190e033351dSWim Van Sebroeck EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); 191e033351dSWim Van Sebroeck 192e033351dSWim Van Sebroeck static int __init iTCO_vendor_init_module(void) 193e033351dSWim Van Sebroeck { 194*7ca6ee38SMika Westerberg if (iTCO_vendorsupport == SUPERMICRO_NEW_BOARD) { 1952c05318aSJean Delvare pr_warn("Option vendorsupport=%d is no longer supported, " 1962c05318aSJean Delvare "please use the w83627hf_wdt driver instead\n", 1972c05318aSJean Delvare SUPERMICRO_NEW_BOARD); 1982c05318aSJean Delvare return -EINVAL; 1992c05318aSJean Delvare } 200*7ca6ee38SMika Westerberg pr_info("vendor-support=%d\n", iTCO_vendorsupport); 201e033351dSWim Van Sebroeck return 0; 202e033351dSWim Van Sebroeck } 203e033351dSWim Van Sebroeck 204e033351dSWim Van Sebroeck static void __exit iTCO_vendor_exit_module(void) 205e033351dSWim Van Sebroeck { 20627c766aaSJoe Perches pr_info("Module Unloaded\n"); 207e033351dSWim Van Sebroeck } 208e033351dSWim Van Sebroeck 209e033351dSWim Van Sebroeck module_init(iTCO_vendor_init_module); 210e033351dSWim Van Sebroeck module_exit(iTCO_vendor_exit_module); 211e033351dSWim Van Sebroeck 212143a2e54SWim Van Sebroeck MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, " 213143a2e54SWim Van Sebroeck "R. Seretny <lkpatches@paypc.com>"); 214e033351dSWim Van Sebroeck MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support"); 215e033351dSWim Van Sebroeck MODULE_VERSION(DRV_VERSION); 216e033351dSWim Van Sebroeck MODULE_LICENSE("GPL"); 217