blob: 68a9d9cc2eb8337a8c7edb498083acc9f37ec29a [file] [log] [blame]
Wim Van Sebroecke0333512006-11-12 18:05:09 +01001/*
2 * intel TCO vendor specific watchdog driver support
3 *
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +00004 * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
Wim Van Sebroecke0333512006-11-12 18:05:09 +01005 *
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
Joe Perches27c766a2012-02-15 15:06:19 -080020#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
Wim Van Sebroecke0333512006-11-12 18:05:09 +010022/* Module and version information */
Wim Van Sebroeck7944d3a2008-08-06 20:19:41 +000023#define DRV_NAME "iTCO_vendor_support"
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +000024#define DRV_VERSION "1.04"
Wim Van Sebroecke0333512006-11-12 18:05:09 +010025
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 */
Alan Cox0e6fa3f2008-05-19 14:06:25 +010034#include <linux/io.h> /* For inb/outb/... */
35
36#include "iTCO_vendor.h"
Wim Van Sebroecke0333512006-11-12 18:05:09 +010037
Wim Van Sebroecke0333512006-11-12 18:05:09 +010038/* List of vendor support modes */
Alan Cox0e6fa3f2008-05-19 14:06:25 +010039/* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
40#define SUPERMICRO_OLD_BOARD 1
Jean Delvare2c053182018-08-31 15:06:10 +020041/* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems - no longer supported */
Alan Cox0e6fa3f2008-05-19 14:06:25 +010042#define SUPERMICRO_NEW_BOARD 2
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +000043/* Broken BIOS */
44#define BROKEN_BIOS 911
Wim Van Sebroecke0333512006-11-12 18:05:09 +010045
Alan Cox0e6fa3f2008-05-19 14:06:25 +010046static int vendorsupport;
Wim Van Sebroecke0333512006-11-12 18:05:09 +010047module_param(vendorsupport, int, 0);
Wim Van Sebroeck143a2e52009-03-18 08:35:09 +000048MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default="
Jean Delvare2c053182018-08-31 15:06:10 +020049 "0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS");
Wim Van Sebroecke0333512006-11-12 18:05:09 +010050
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
Aaron Sierra887c8ec2012-04-20 14:14:11 -050079static void supermicro_old_pre_start(struct resource *smires)
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000080{
81 unsigned long val32;
82
83 /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
Aaron Sierra887c8ec2012-04-20 14:14:11 -050084 val32 = inl(smires->start);
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000085 val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
Aaron Sierra887c8ec2012-04-20 14:14:11 -050086 outl(val32, smires->start); /* Needed to activate watchdog */
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000087}
88
Aaron Sierra887c8ec2012-04-20 14:14:11 -050089static void supermicro_old_pre_stop(struct resource *smires)
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000090{
91 unsigned long val32;
92
93 /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
Aaron Sierra887c8ec2012-04-20 14:14:11 -050094 val32 = inl(smires->start);
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000095 val32 |= 0x00002000; /* Turn on SMI clearing watchdog */
Aaron Sierra887c8ec2012-04-20 14:14:11 -050096 outl(val32, smires->start); /* Needed to deactivate watchdog */
Wim Van Sebroeck12d60e22009-01-28 20:51:04 +000097}
98
Wim Van Sebroecke0333512006-11-12 18:05:09 +010099/*
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000100 * 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
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500130static void broken_bios_start(struct resource *smires)
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000131{
132 unsigned long val32;
133
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500134 val32 = inl(smires->start);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000135 /* 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;
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500138 outl(val32, smires->start);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000139}
140
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500141static void broken_bios_stop(struct resource *smires)
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000142{
143 unsigned long val32;
144
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500145 val32 = inl(smires->start);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000146 /* 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;
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500149 outl(val32, smires->start);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000150}
151
152/*
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100153 * Generic Support Functions
154 */
155
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500156void iTCO_vendor_pre_start(struct resource *smires,
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100157 unsigned int heartbeat)
158{
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000159 switch (vendorsupport) {
160 case SUPERMICRO_OLD_BOARD:
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500161 supermicro_old_pre_start(smires);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000162 break;
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000163 case BROKEN_BIOS:
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500164 broken_bios_start(smires);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000165 break;
166 }
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100167}
168EXPORT_SYMBOL(iTCO_vendor_pre_start);
169
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500170void iTCO_vendor_pre_stop(struct resource *smires)
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100171{
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000172 switch (vendorsupport) {
173 case SUPERMICRO_OLD_BOARD:
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500174 supermicro_old_pre_stop(smires);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000175 break;
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000176 case BROKEN_BIOS:
Aaron Sierra887c8ec2012-04-20 14:14:11 -0500177 broken_bios_stop(smires);
Wim Van Sebroeck55e8dde2009-06-08 17:41:51 +0000178 break;
179 }
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100180}
181EXPORT_SYMBOL(iTCO_vendor_pre_stop);
182
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100183int iTCO_vendor_check_noreboot_on(void)
184{
Alan Cox0e6fa3f2008-05-19 14:06:25 +0100185 switch (vendorsupport) {
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100186 case SUPERMICRO_OLD_BOARD:
187 return 0;
188 default:
189 return 1;
190 }
191}
192EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
193
194static int __init iTCO_vendor_init_module(void)
195{
Jean Delvare2c053182018-08-31 15:06:10 +0200196 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 }
Joe Perches27c766a2012-02-15 15:06:19 -0800202 pr_info("vendor-support=%d\n", vendorsupport);
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100203 return 0;
204}
205
206static void __exit iTCO_vendor_exit_module(void)
207{
Joe Perches27c766a2012-02-15 15:06:19 -0800208 pr_info("Module Unloaded\n");
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100209}
210
211module_init(iTCO_vendor_init_module);
212module_exit(iTCO_vendor_exit_module);
213
Wim Van Sebroeck143a2e52009-03-18 08:35:09 +0000214MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, "
215 "R. Seretny <lkpatches@paypc.com>");
Wim Van Sebroecke0333512006-11-12 18:05:09 +0100216MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support");
217MODULE_VERSION(DRV_VERSION);
218MODULE_LICENSE("GPL");
219