Blame view

drivers/watchdog/iTCO_vendor_support.c 6.35 KB
d01732789   Guenter Roeck   watchdog: convert...
1
  // SPDX-License-Identifier: GPL-2.0+
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
2
3
4
  /*
   *	intel TCO vendor specific watchdog driver support
   *
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
5
   *	(c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
6
   *
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
7
8
9
10
11
12
13
14
   *	Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
   *	provide warranty for any of this software. This material is
   *	provided "AS-IS" and at no charge.
   */
  
  /*
   *	Includes, defines, variables, module parameters, ...
   */
27c766aaa   Joe Perches   watchdog: Use pr_...
15
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
16
  /* Module and version information */
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
17
  #define DRV_NAME	"iTCO_vendor_support"
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
18
  #define DRV_VERSION	"1.04"
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
19
20
21
22
23
24
25
26
27
  
  /* Includes */
  #include <linux/module.h>		/* For module specific items */
  #include <linux/moduleparam.h>		/* For new moduleparam's */
  #include <linux/types.h>		/* For standard types (like size_t) */
  #include <linux/errno.h>		/* For the -ENODEV/... values */
  #include <linux/kernel.h>		/* For printk/panic/... */
  #include <linux/init.h>			/* For __init/__exit/... */
  #include <linux/ioport.h>		/* For io-port access */
0e6fa3fb3   Alan Cox   [WATCHDOG 18/57] ...
28
29
30
  #include <linux/io.h>			/* For inb/outb/... */
  
  #include "iTCO_vendor.h"
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
31

e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
32
  /* List of vendor support modes */
0e6fa3fb3   Alan Cox   [WATCHDOG 18/57] ...
33
34
  /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
  #define SUPERMICRO_OLD_BOARD	1
2c05318ad   Jean Delvare   watchdog: iTCO_wd...
35
  /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems - no longer supported */
0e6fa3fb3   Alan Cox   [WATCHDOG 18/57] ...
36
  #define SUPERMICRO_NEW_BOARD	2
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
37
38
  /* Broken BIOS */
  #define BROKEN_BIOS		911
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
39

7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
40
41
42
43
  int iTCO_vendorsupport;
  EXPORT_SYMBOL(iTCO_vendorsupport);
  
  module_param_named(vendorsupport, iTCO_vendorsupport, int, 0);
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
44
  MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default="
2c05318ad   Jean Delvare   watchdog: iTCO_wd...
45
  			"0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS");
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  
  /*
   *	Vendor Specific Support
   */
  
  /*
   *	Vendor Support: 1
   *	Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE
   *	iTCO chipset: ICH2
   *
   *	Code contributed by: R. Seretny <lkpatches@paypc.com>
   *	Documentation obtained by R. Seretny from SuperMicro Technical Support
   *
   *	To enable Watchdog function:
   *	    BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes
   *	    This setting enables SMI to clear the watchdog expired flag.
   *	    If BIOS or CPU fail which may cause SMI hang, then system will
   *	    reboot. When application starts to use watchdog function,
   *	    application has to take over the control from SMI.
   *
   *	    For P3TSSE, J36 jumper needs to be removed to enable the Watchdog
   *	    function.
   *
   *	    Note: The system will reboot when Expire Flag is set TWICE.
   *	    So, if the watchdog timer is 20 seconds, then the maximum hang
   *	    time is about 40 seconds, and the minimum hang time is about
   *	    20.6 seconds.
   */
887c8ec72   Aaron Sierra   watchdog: Convert...
74
  static void supermicro_old_pre_start(struct resource *smires)
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
75
76
77
78
  {
  	unsigned long val32;
  
  	/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
887c8ec72   Aaron Sierra   watchdog: Convert...
79
  	val32 = inl(smires->start);
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
80
  	val32 &= 0xffffdfff;	/* Turn off SMI clearing watchdog */
887c8ec72   Aaron Sierra   watchdog: Convert...
81
  	outl(val32, smires->start);	/* Needed to activate watchdog */
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
82
  }
887c8ec72   Aaron Sierra   watchdog: Convert...
83
  static void supermicro_old_pre_stop(struct resource *smires)
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
84
85
86
87
  {
  	unsigned long val32;
  
  	/* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
887c8ec72   Aaron Sierra   watchdog: Convert...
88
  	val32 = inl(smires->start);
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
89
  	val32 |= 0x00002000;	/* Turn on SMI clearing watchdog */
887c8ec72   Aaron Sierra   watchdog: Convert...
90
  	outl(val32, smires->start);	/* Needed to deactivate watchdog */
12d60e28b   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
91
  }
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
92
  /*
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
   *	Vendor Support: 911
   *	Board: Some Intel ICHx based motherboards
   *	iTCO chipset: ICH7+
   *
   *	Some Intel motherboards have a broken BIOS implementation: i.e.
   *	the SMI handler clear's the TIMEOUT bit in the TC01_STS register
   *	and does not reload the time. Thus the TCO watchdog does not reboot
   *	the system.
   *
   *	These are the conclusions of Andriy Gapon <avg@icyb.net.ua> after
   *	debugging: the SMI handler is quite simple - it tests value in
   *	TCO1_CNT against 0x800, i.e. checks TCO_TMR_HLT. If the bit is set
   *	the handler goes into an infinite loop, apparently to allow the
   *	second timeout and reboot. Otherwise it simply clears TIMEOUT bit
   *	in TCO1_STS and that's it.
   *	So the logic seems to be reversed, because it is hard to see how
   *	TIMEOUT can get set to 1 and SMI generated when TCO_TMR_HLT is set
   *	(other than a transitional effect).
   *
   *	The only fix found to get the motherboard(s) to reboot is to put
   *	the glb_smi_en bit to 0. This is a dirty hack that bypasses the
   *	broken code by disabling Global SMI.
   *
   *	WARNING: globally disabling SMI could possibly lead to dramatic
   *	problems, especially on laptops! I.e. various ACPI things where
   *	SMI is used for communication between OS and firmware.
   *
   *	Don't use this fix if you don't need to!!!
   */
887c8ec72   Aaron Sierra   watchdog: Convert...
122
  static void broken_bios_start(struct resource *smires)
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
123
124
  {
  	unsigned long val32;
887c8ec72   Aaron Sierra   watchdog: Convert...
125
  	val32 = inl(smires->start);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
126
127
128
  	/* Bit 13: TCO_EN     -> 0 = Disables TCO logic generating an SMI#
  	   Bit  0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */
  	val32 &= 0xffffdffe;
887c8ec72   Aaron Sierra   watchdog: Convert...
129
  	outl(val32, smires->start);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
130
  }
887c8ec72   Aaron Sierra   watchdog: Convert...
131
  static void broken_bios_stop(struct resource *smires)
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
132
133
  {
  	unsigned long val32;
887c8ec72   Aaron Sierra   watchdog: Convert...
134
  	val32 = inl(smires->start);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
135
136
137
  	/* Bit 13: TCO_EN     -> 1 = Enables TCO logic generating an SMI#
  	   Bit  0: GBL_SMI_EN -> 1 = Turn global SMI on again. */
  	val32 |= 0x00002001;
887c8ec72   Aaron Sierra   watchdog: Convert...
138
  	outl(val32, smires->start);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
139
140
141
  }
  
  /*
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
142
143
   *	Generic Support Functions
   */
887c8ec72   Aaron Sierra   watchdog: Convert...
144
  void iTCO_vendor_pre_start(struct resource *smires,
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
145
146
  			   unsigned int heartbeat)
  {
7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
147
  	switch (iTCO_vendorsupport) {
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
148
  	case SUPERMICRO_OLD_BOARD:
887c8ec72   Aaron Sierra   watchdog: Convert...
149
  		supermicro_old_pre_start(smires);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
150
  		break;
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
151
  	case BROKEN_BIOS:
887c8ec72   Aaron Sierra   watchdog: Convert...
152
  		broken_bios_start(smires);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
153
154
  		break;
  	}
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
155
156
  }
  EXPORT_SYMBOL(iTCO_vendor_pre_start);
887c8ec72   Aaron Sierra   watchdog: Convert...
157
  void iTCO_vendor_pre_stop(struct resource *smires)
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
158
  {
7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
159
  	switch (iTCO_vendorsupport) {
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
160
  	case SUPERMICRO_OLD_BOARD:
887c8ec72   Aaron Sierra   watchdog: Convert...
161
  		supermicro_old_pre_stop(smires);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
162
  		break;
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
163
  	case BROKEN_BIOS:
887c8ec72   Aaron Sierra   watchdog: Convert...
164
  		broken_bios_stop(smires);
55e8ddece   Wim Van Sebroeck   [WATCHDOG] iTCO_w...
165
166
  		break;
  	}
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
167
168
  }
  EXPORT_SYMBOL(iTCO_vendor_pre_stop);
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
169
170
  int iTCO_vendor_check_noreboot_on(void)
  {
7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
171
  	switch (iTCO_vendorsupport) {
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
172
173
174
175
176
177
178
179
180
181
  	case SUPERMICRO_OLD_BOARD:
  		return 0;
  	default:
  		return 1;
  	}
  }
  EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
  
  static int __init iTCO_vendor_init_module(void)
  {
7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
182
  	if (iTCO_vendorsupport == SUPERMICRO_NEW_BOARD) {
2c05318ad   Jean Delvare   watchdog: iTCO_wd...
183
184
185
186
187
188
  		pr_warn("Option vendorsupport=%d is no longer supported, "
  			"please use the w83627hf_wdt driver instead
  ",
  			SUPERMICRO_NEW_BOARD);
  		return -EINVAL;
  	}
7ca6ee389   Mika Westerberg   watchdog: iTCO_wd...
189
190
  	pr_info("vendor-support=%d
  ", iTCO_vendorsupport);
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
191
192
193
194
195
  	return 0;
  }
  
  static void __exit iTCO_vendor_exit_module(void)
  {
27c766aaa   Joe Perches   watchdog: Use pr_...
196
197
  	pr_info("Module Unloaded
  ");
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
198
199
200
201
  }
  
  module_init(iTCO_vendor_init_module);
  module_exit(iTCO_vendor_exit_module);
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
202
203
  MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, "
  		"R. Seretny <lkpatches@paypc.com>");
e033351d5   Wim Van Sebroeck   [WATCHDOG] Add iT...
204
205
206
  MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support");
  MODULE_VERSION(DRV_VERSION);
  MODULE_LICENSE("GPL");