xref: /openbmc/linux/drivers/watchdog/iTCO_wdt.c (revision 4800cd83)
1 /*
2  *	intel TCO Watchdog Driver
3  *
4  *	(c) Copyright 2006-2010 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  *	The TCO watchdog is implemented in the following I/O controller hubs:
16  *	(See the intel documentation on http://developer.intel.com.)
17  *	document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
18  *	document number 290687-002, 298242-027: 82801BA (ICH2)
19  *	document number 290733-003, 290739-013: 82801CA (ICH3-S)
20  *	document number 290716-001, 290718-007: 82801CAM (ICH3-M)
21  *	document number 290744-001, 290745-025: 82801DB (ICH4)
22  *	document number 252337-001, 252663-008: 82801DBM (ICH4-M)
23  *	document number 273599-001, 273645-002: 82801E (C-ICH)
24  *	document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R)
25  *	document number 300641-004, 300884-013: 6300ESB
26  *	document number 301473-002, 301474-026: 82801F (ICH6)
27  *	document number 313082-001, 313075-006: 631xESB, 632xESB
28  *	document number 307013-003, 307014-024: 82801G (ICH7)
29  *	document number 322896-001, 322897-001: NM10
30  *	document number 313056-003, 313057-017: 82801H (ICH8)
31  *	document number 316972-004, 316973-012: 82801I (ICH9)
32  *	document number 319973-002, 319974-002: 82801J (ICH10)
33  *	document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
34  *	document number 320066-003, 320257-008: EP80597 (IICH)
35  *	document number 324645-001, 324646-001: Cougar Point (CPT)
36  *	document number TBD                   : Patsburg (PBG)
37  *	document number TBD                   : DH89xxCC
38  */
39 
40 /*
41  *	Includes, defines, variables, module parameters, ...
42  */
43 
44 /* Module and version information */
45 #define DRV_NAME	"iTCO_wdt"
46 #define DRV_VERSION	"1.06"
47 #define PFX		DRV_NAME ": "
48 
49 /* Includes */
50 #include <linux/module.h>		/* For module specific items */
51 #include <linux/moduleparam.h>		/* For new moduleparam's */
52 #include <linux/types.h>		/* For standard types (like size_t) */
53 #include <linux/errno.h>		/* For the -ENODEV/... values */
54 #include <linux/kernel.h>		/* For printk/panic/... */
55 #include <linux/miscdevice.h>		/* For MODULE_ALIAS_MISCDEV
56 							(WATCHDOG_MINOR) */
57 #include <linux/watchdog.h>		/* For the watchdog specific items */
58 #include <linux/init.h>			/* For __init/__exit/... */
59 #include <linux/fs.h>			/* For file operations */
60 #include <linux/platform_device.h>	/* For platform_driver framework */
61 #include <linux/pci.h>			/* For pci functions */
62 #include <linux/ioport.h>		/* For io-port access */
63 #include <linux/spinlock.h>		/* For spin_lock/spin_unlock/... */
64 #include <linux/uaccess.h>		/* For copy_to_user/put_user/... */
65 #include <linux/io.h>			/* For inb/outb/... */
66 
67 #include "iTCO_vendor.h"
68 
69 /* TCO related info */
70 enum iTCO_chipsets {
71 	TCO_ICH = 0,	/* ICH */
72 	TCO_ICH0,	/* ICH0 */
73 	TCO_ICH2,	/* ICH2 */
74 	TCO_ICH2M,	/* ICH2-M */
75 	TCO_ICH3,	/* ICH3-S */
76 	TCO_ICH3M,	/* ICH3-M */
77 	TCO_ICH4,	/* ICH4 */
78 	TCO_ICH4M,	/* ICH4-M */
79 	TCO_CICH,	/* C-ICH */
80 	TCO_ICH5,	/* ICH5 & ICH5R */
81 	TCO_6300ESB,	/* 6300ESB */
82 	TCO_ICH6,	/* ICH6 & ICH6R */
83 	TCO_ICH6M,	/* ICH6-M */
84 	TCO_ICH6W,	/* ICH6W & ICH6RW */
85 	TCO_631XESB,	/* 631xESB/632xESB */
86 	TCO_ICH7,	/* ICH7 & ICH7R */
87 	TCO_ICH7DH,	/* ICH7DH */
88 	TCO_ICH7M,	/* ICH7-M & ICH7-U */
89 	TCO_ICH7MDH,	/* ICH7-M DH */
90 	TCO_NM10,	/* NM10 */
91 	TCO_ICH8,	/* ICH8 & ICH8R */
92 	TCO_ICH8DH,	/* ICH8DH */
93 	TCO_ICH8DO,	/* ICH8DO */
94 	TCO_ICH8M,	/* ICH8M */
95 	TCO_ICH8ME,	/* ICH8M-E */
96 	TCO_ICH9,	/* ICH9 */
97 	TCO_ICH9R,	/* ICH9R */
98 	TCO_ICH9DH,	/* ICH9DH */
99 	TCO_ICH9DO,	/* ICH9DO */
100 	TCO_ICH9M,	/* ICH9M */
101 	TCO_ICH9ME,	/* ICH9M-E */
102 	TCO_ICH10,	/* ICH10 */
103 	TCO_ICH10R,	/* ICH10R */
104 	TCO_ICH10D,	/* ICH10D */
105 	TCO_ICH10DO,	/* ICH10DO */
106 	TCO_PCH,	/* PCH Desktop Full Featured */
107 	TCO_PCHM,	/* PCH Mobile Full Featured */
108 	TCO_P55,	/* P55 */
109 	TCO_PM55,	/* PM55 */
110 	TCO_H55,	/* H55 */
111 	TCO_QM57,	/* QM57 */
112 	TCO_H57,	/* H57 */
113 	TCO_HM55,	/* HM55 */
114 	TCO_Q57,	/* Q57 */
115 	TCO_HM57,	/* HM57 */
116 	TCO_PCHMSFF,	/* PCH Mobile SFF Full Featured */
117 	TCO_QS57,	/* QS57 */
118 	TCO_3400,	/* 3400 */
119 	TCO_3420,	/* 3420 */
120 	TCO_3450,	/* 3450 */
121 	TCO_EP80579,	/* EP80579 */
122 	TCO_CPT1,	/* Cougar Point */
123 	TCO_CPT2,	/* Cougar Point Desktop */
124 	TCO_CPT3,	/* Cougar Point Mobile */
125 	TCO_CPT4,	/* Cougar Point */
126 	TCO_CPT5,	/* Cougar Point */
127 	TCO_CPT6,	/* Cougar Point */
128 	TCO_CPT7,	/* Cougar Point */
129 	TCO_CPT8,	/* Cougar Point */
130 	TCO_CPT9,	/* Cougar Point */
131 	TCO_CPT10,	/* Cougar Point */
132 	TCO_CPT11,	/* Cougar Point */
133 	TCO_CPT12,	/* Cougar Point */
134 	TCO_CPT13,	/* Cougar Point */
135 	TCO_CPT14,	/* Cougar Point */
136 	TCO_CPT15,	/* Cougar Point */
137 	TCO_CPT16,	/* Cougar Point */
138 	TCO_CPT17,	/* Cougar Point */
139 	TCO_CPT18,	/* Cougar Point */
140 	TCO_CPT19,	/* Cougar Point */
141 	TCO_CPT20,	/* Cougar Point */
142 	TCO_CPT21,	/* Cougar Point */
143 	TCO_CPT22,	/* Cougar Point */
144 	TCO_CPT23,	/* Cougar Point */
145 	TCO_CPT24,	/* Cougar Point */
146 	TCO_CPT25,	/* Cougar Point */
147 	TCO_CPT26,	/* Cougar Point */
148 	TCO_CPT27,	/* Cougar Point */
149 	TCO_CPT28,	/* Cougar Point */
150 	TCO_CPT29,	/* Cougar Point */
151 	TCO_CPT30,	/* Cougar Point */
152 	TCO_CPT31,	/* Cougar Point */
153 	TCO_PBG1,	/* Patsburg */
154 	TCO_PBG2,	/* Patsburg */
155 	TCO_DH89XXCC,	/* DH89xxCC */
156 };
157 
158 static struct {
159 	char *name;
160 	unsigned int iTCO_version;
161 } iTCO_chipset_info[] __devinitdata = {
162 	{"ICH", 1},
163 	{"ICH0", 1},
164 	{"ICH2", 1},
165 	{"ICH2-M", 1},
166 	{"ICH3-S", 1},
167 	{"ICH3-M", 1},
168 	{"ICH4", 1},
169 	{"ICH4-M", 1},
170 	{"C-ICH", 1},
171 	{"ICH5 or ICH5R", 1},
172 	{"6300ESB", 1},
173 	{"ICH6 or ICH6R", 2},
174 	{"ICH6-M", 2},
175 	{"ICH6W or ICH6RW", 2},
176 	{"631xESB/632xESB", 2},
177 	{"ICH7 or ICH7R", 2},
178 	{"ICH7DH", 2},
179 	{"ICH7-M or ICH7-U", 2},
180 	{"ICH7-M DH", 2},
181 	{"NM10", 2},
182 	{"ICH8 or ICH8R", 2},
183 	{"ICH8DH", 2},
184 	{"ICH8DO", 2},
185 	{"ICH8M", 2},
186 	{"ICH8M-E", 2},
187 	{"ICH9", 2},
188 	{"ICH9R", 2},
189 	{"ICH9DH", 2},
190 	{"ICH9DO", 2},
191 	{"ICH9M", 2},
192 	{"ICH9M-E", 2},
193 	{"ICH10", 2},
194 	{"ICH10R", 2},
195 	{"ICH10D", 2},
196 	{"ICH10DO", 2},
197 	{"PCH Desktop Full Featured", 2},
198 	{"PCH Mobile Full Featured", 2},
199 	{"P55", 2},
200 	{"PM55", 2},
201 	{"H55", 2},
202 	{"QM57", 2},
203 	{"H57", 2},
204 	{"HM55", 2},
205 	{"Q57", 2},
206 	{"HM57", 2},
207 	{"PCH Mobile SFF Full Featured", 2},
208 	{"QS57", 2},
209 	{"3400", 2},
210 	{"3420", 2},
211 	{"3450", 2},
212 	{"EP80579", 2},
213 	{"Cougar Point", 2},
214 	{"Cougar Point", 2},
215 	{"Cougar Point", 2},
216 	{"Cougar Point", 2},
217 	{"Cougar Point", 2},
218 	{"Cougar Point", 2},
219 	{"Cougar Point", 2},
220 	{"Cougar Point", 2},
221 	{"Cougar Point", 2},
222 	{"Cougar Point", 2},
223 	{"Cougar Point", 2},
224 	{"Cougar Point", 2},
225 	{"Cougar Point", 2},
226 	{"Cougar Point", 2},
227 	{"Cougar Point", 2},
228 	{"Cougar Point", 2},
229 	{"Cougar Point", 2},
230 	{"Cougar Point", 2},
231 	{"Cougar Point", 2},
232 	{"Cougar Point", 2},
233 	{"Cougar Point", 2},
234 	{"Cougar Point", 2},
235 	{"Cougar Point", 2},
236 	{"Cougar Point", 2},
237 	{"Cougar Point", 2},
238 	{"Cougar Point", 2},
239 	{"Cougar Point", 2},
240 	{"Cougar Point", 2},
241 	{"Cougar Point", 2},
242 	{"Cougar Point", 2},
243 	{"Cougar Point", 2},
244 	{"Patsburg", 2},
245 	{"Patsburg", 2},
246 	{"DH89xxCC", 2},
247 	{NULL, 0}
248 };
249 
250 #define ITCO_PCI_DEVICE(dev, data) 	\
251 	.vendor = PCI_VENDOR_ID_INTEL,	\
252 	.device = dev,			\
253 	.subvendor = PCI_ANY_ID,	\
254 	.subdevice = PCI_ANY_ID,	\
255 	.class = 0,			\
256 	.class_mask = 0,		\
257 	.driver_data = data
258 
259 /*
260  * This data only exists for exporting the supported PCI ids
261  * via MODULE_DEVICE_TABLE.  We do not actually register a
262  * pci_driver, because the I/O Controller Hub has also other
263  * functions that probably will be registered by other drivers.
264  */
265 static struct pci_device_id iTCO_wdt_pci_tbl[] = {
266 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0,	TCO_ICH)},
267 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0,	TCO_ICH0)},
268 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0,	TCO_ICH2)},
269 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10,	TCO_ICH2M)},
270 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0,	TCO_ICH3)},
271 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12,	TCO_ICH3M)},
272 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0,	TCO_ICH4)},
273 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12,	TCO_ICH4M)},
274 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0,		TCO_CICH)},
275 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0,	TCO_ICH5)},
276 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1,		TCO_6300ESB)},
277 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0,		TCO_ICH6)},
278 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1,		TCO_ICH6M)},
279 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2,		TCO_ICH6W)},
280 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0,		TCO_631XESB)},
281 	{ ITCO_PCI_DEVICE(0x2671,				TCO_631XESB)},
282 	{ ITCO_PCI_DEVICE(0x2672,				TCO_631XESB)},
283 	{ ITCO_PCI_DEVICE(0x2673,				TCO_631XESB)},
284 	{ ITCO_PCI_DEVICE(0x2674,				TCO_631XESB)},
285 	{ ITCO_PCI_DEVICE(0x2675,				TCO_631XESB)},
286 	{ ITCO_PCI_DEVICE(0x2676,				TCO_631XESB)},
287 	{ ITCO_PCI_DEVICE(0x2677,				TCO_631XESB)},
288 	{ ITCO_PCI_DEVICE(0x2678,				TCO_631XESB)},
289 	{ ITCO_PCI_DEVICE(0x2679,				TCO_631XESB)},
290 	{ ITCO_PCI_DEVICE(0x267a,				TCO_631XESB)},
291 	{ ITCO_PCI_DEVICE(0x267b,				TCO_631XESB)},
292 	{ ITCO_PCI_DEVICE(0x267c,				TCO_631XESB)},
293 	{ ITCO_PCI_DEVICE(0x267d,				TCO_631XESB)},
294 	{ ITCO_PCI_DEVICE(0x267e,				TCO_631XESB)},
295 	{ ITCO_PCI_DEVICE(0x267f,				TCO_631XESB)},
296 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0,		TCO_ICH7)},
297 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30,		TCO_ICH7DH)},
298 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1,		TCO_ICH7M)},
299 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31,		TCO_ICH7MDH)},
300 	{ ITCO_PCI_DEVICE(0x27bc,				TCO_NM10)},
301 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0,		TCO_ICH8)},
302 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2,		TCO_ICH8DH)},
303 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3,		TCO_ICH8DO)},
304 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4,		TCO_ICH8M)},
305 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1,		TCO_ICH8ME)},
306 	{ ITCO_PCI_DEVICE(0x2918,				TCO_ICH9)},
307 	{ ITCO_PCI_DEVICE(0x2916,				TCO_ICH9R)},
308 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2,		TCO_ICH9DH)},
309 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4,		TCO_ICH9DO)},
310 	{ ITCO_PCI_DEVICE(0x2919,				TCO_ICH9M)},
311 	{ ITCO_PCI_DEVICE(0x2917,				TCO_ICH9ME)},
312 	{ ITCO_PCI_DEVICE(0x3a18,				TCO_ICH10)},
313 	{ ITCO_PCI_DEVICE(0x3a16,				TCO_ICH10R)},
314 	{ ITCO_PCI_DEVICE(0x3a1a,				TCO_ICH10D)},
315 	{ ITCO_PCI_DEVICE(0x3a14,				TCO_ICH10DO)},
316 	{ ITCO_PCI_DEVICE(0x3b00,				TCO_PCH)},
317 	{ ITCO_PCI_DEVICE(0x3b01,				TCO_PCHM)},
318 	{ ITCO_PCI_DEVICE(0x3b02,				TCO_P55)},
319 	{ ITCO_PCI_DEVICE(0x3b03,				TCO_PM55)},
320 	{ ITCO_PCI_DEVICE(0x3b06,				TCO_H55)},
321 	{ ITCO_PCI_DEVICE(0x3b07,				TCO_QM57)},
322 	{ ITCO_PCI_DEVICE(0x3b08,				TCO_H57)},
323 	{ ITCO_PCI_DEVICE(0x3b09,				TCO_HM55)},
324 	{ ITCO_PCI_DEVICE(0x3b0a,				TCO_Q57)},
325 	{ ITCO_PCI_DEVICE(0x3b0b,				TCO_HM57)},
326 	{ ITCO_PCI_DEVICE(0x3b0d,				TCO_PCHMSFF)},
327 	{ ITCO_PCI_DEVICE(0x3b0f,				TCO_QS57)},
328 	{ ITCO_PCI_DEVICE(0x3b12,				TCO_3400)},
329 	{ ITCO_PCI_DEVICE(0x3b14,				TCO_3420)},
330 	{ ITCO_PCI_DEVICE(0x3b16,				TCO_3450)},
331 	{ ITCO_PCI_DEVICE(0x5031,				TCO_EP80579)},
332 	{ ITCO_PCI_DEVICE(0x1c41,				TCO_CPT1)},
333 	{ ITCO_PCI_DEVICE(0x1c42,				TCO_CPT2)},
334 	{ ITCO_PCI_DEVICE(0x1c43,				TCO_CPT3)},
335 	{ ITCO_PCI_DEVICE(0x1c44,				TCO_CPT4)},
336 	{ ITCO_PCI_DEVICE(0x1c45,				TCO_CPT5)},
337 	{ ITCO_PCI_DEVICE(0x1c46,				TCO_CPT6)},
338 	{ ITCO_PCI_DEVICE(0x1c47,				TCO_CPT7)},
339 	{ ITCO_PCI_DEVICE(0x1c48,				TCO_CPT8)},
340 	{ ITCO_PCI_DEVICE(0x1c49,				TCO_CPT9)},
341 	{ ITCO_PCI_DEVICE(0x1c4a,				TCO_CPT10)},
342 	{ ITCO_PCI_DEVICE(0x1c4b,				TCO_CPT11)},
343 	{ ITCO_PCI_DEVICE(0x1c4c,				TCO_CPT12)},
344 	{ ITCO_PCI_DEVICE(0x1c4d,				TCO_CPT13)},
345 	{ ITCO_PCI_DEVICE(0x1c4e,				TCO_CPT14)},
346 	{ ITCO_PCI_DEVICE(0x1c4f,				TCO_CPT15)},
347 	{ ITCO_PCI_DEVICE(0x1c50,				TCO_CPT16)},
348 	{ ITCO_PCI_DEVICE(0x1c51,				TCO_CPT17)},
349 	{ ITCO_PCI_DEVICE(0x1c52,				TCO_CPT18)},
350 	{ ITCO_PCI_DEVICE(0x1c53,				TCO_CPT19)},
351 	{ ITCO_PCI_DEVICE(0x1c54,				TCO_CPT20)},
352 	{ ITCO_PCI_DEVICE(0x1c55,				TCO_CPT21)},
353 	{ ITCO_PCI_DEVICE(0x1c56,				TCO_CPT22)},
354 	{ ITCO_PCI_DEVICE(0x1c57,				TCO_CPT23)},
355 	{ ITCO_PCI_DEVICE(0x1c58,				TCO_CPT24)},
356 	{ ITCO_PCI_DEVICE(0x1c59,				TCO_CPT25)},
357 	{ ITCO_PCI_DEVICE(0x1c5a,				TCO_CPT26)},
358 	{ ITCO_PCI_DEVICE(0x1c5b,				TCO_CPT27)},
359 	{ ITCO_PCI_DEVICE(0x1c5c,				TCO_CPT28)},
360 	{ ITCO_PCI_DEVICE(0x1c5d,				TCO_CPT29)},
361 	{ ITCO_PCI_DEVICE(0x1c5e,				TCO_CPT30)},
362 	{ ITCO_PCI_DEVICE(0x1c5f,				TCO_CPT31)},
363 	{ ITCO_PCI_DEVICE(0x1d40,				TCO_PBG1)},
364 	{ ITCO_PCI_DEVICE(0x1d41,				TCO_PBG2)},
365 	{ ITCO_PCI_DEVICE(0x2310,				TCO_DH89XXCC)},
366 	{ 0, },			/* End of list */
367 };
368 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
369 
370 /* Address definitions for the TCO */
371 /* TCO base address */
372 #define TCOBASE		(iTCO_wdt_private.ACPIBASE + 0x60)
373 /* SMI Control and Enable Register */
374 #define SMI_EN		(iTCO_wdt_private.ACPIBASE + 0x30)
375 
376 #define TCO_RLD		(TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */
377 #define TCOv1_TMR	(TCOBASE + 0x01) /* TCOv1 Timer Initial Value	*/
378 #define TCO_DAT_IN	(TCOBASE + 0x02) /* TCO Data In Register	*/
379 #define TCO_DAT_OUT	(TCOBASE + 0x03) /* TCO Data Out Register	*/
380 #define TCO1_STS	(TCOBASE + 0x04) /* TCO1 Status Register	*/
381 #define TCO2_STS	(TCOBASE + 0x06) /* TCO2 Status Register	*/
382 #define TCO1_CNT	(TCOBASE + 0x08) /* TCO1 Control Register	*/
383 #define TCO2_CNT	(TCOBASE + 0x0a) /* TCO2 Control Register	*/
384 #define TCOv2_TMR	(TCOBASE + 0x12) /* TCOv2 Timer Initial Value	*/
385 
386 /* internal variables */
387 static unsigned long is_active;
388 static char expect_release;
389 static struct {		/* this is private data for the iTCO_wdt device */
390 	/* TCO version/generation */
391 	unsigned int iTCO_version;
392 	/* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
393 	unsigned long ACPIBASE;
394 	/* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
395 	unsigned long __iomem *gcs;
396 	/* the lock for io operations */
397 	spinlock_t io_lock;
398 	/* the PCI-device */
399 	struct pci_dev *pdev;
400 } iTCO_wdt_private;
401 
402 /* the watchdog platform device */
403 static struct platform_device *iTCO_wdt_platform_device;
404 
405 /* module parameters */
406 #define WATCHDOG_HEARTBEAT 30	/* 30 sec default heartbeat */
407 static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
408 module_param(heartbeat, int, 0);
409 MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
410 	"5..76 (TCO v1) or 3..614 (TCO v2), default="
411 				__MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
412 
413 static int nowayout = WATCHDOG_NOWAYOUT;
414 module_param(nowayout, int, 0);
415 MODULE_PARM_DESC(nowayout,
416 	"Watchdog cannot be stopped once started (default="
417 				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
418 
419 /*
420  * Some TCO specific functions
421  */
422 
423 static inline unsigned int seconds_to_ticks(int seconds)
424 {
425 	/* the internal timer is stored as ticks which decrement
426 	 * every 0.6 seconds */
427 	return (seconds * 10) / 6;
428 }
429 
430 static void iTCO_wdt_set_NO_REBOOT_bit(void)
431 {
432 	u32 val32;
433 
434 	/* Set the NO_REBOOT bit: this disables reboots */
435 	if (iTCO_wdt_private.iTCO_version == 2) {
436 		val32 = readl(iTCO_wdt_private.gcs);
437 		val32 |= 0x00000020;
438 		writel(val32, iTCO_wdt_private.gcs);
439 	} else if (iTCO_wdt_private.iTCO_version == 1) {
440 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
441 		val32 |= 0x00000002;
442 		pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
443 	}
444 }
445 
446 static int iTCO_wdt_unset_NO_REBOOT_bit(void)
447 {
448 	int ret = 0;
449 	u32 val32;
450 
451 	/* Unset the NO_REBOOT bit: this enables reboots */
452 	if (iTCO_wdt_private.iTCO_version == 2) {
453 		val32 = readl(iTCO_wdt_private.gcs);
454 		val32 &= 0xffffffdf;
455 		writel(val32, iTCO_wdt_private.gcs);
456 
457 		val32 = readl(iTCO_wdt_private.gcs);
458 		if (val32 & 0x00000020)
459 			ret = -EIO;
460 	} else if (iTCO_wdt_private.iTCO_version == 1) {
461 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
462 		val32 &= 0xfffffffd;
463 		pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
464 
465 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
466 		if (val32 & 0x00000002)
467 			ret = -EIO;
468 	}
469 
470 	return ret; /* returns: 0 = OK, -EIO = Error */
471 }
472 
473 static int iTCO_wdt_start(void)
474 {
475 	unsigned int val;
476 
477 	spin_lock(&iTCO_wdt_private.io_lock);
478 
479 	iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
480 
481 	/* disable chipset's NO_REBOOT bit */
482 	if (iTCO_wdt_unset_NO_REBOOT_bit()) {
483 		spin_unlock(&iTCO_wdt_private.io_lock);
484 		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
485 					"reboot disabled by hardware/BIOS\n");
486 		return -EIO;
487 	}
488 
489 	/* Force the timer to its reload value by writing to the TCO_RLD
490 	   register */
491 	if (iTCO_wdt_private.iTCO_version == 2)
492 		outw(0x01, TCO_RLD);
493 	else if (iTCO_wdt_private.iTCO_version == 1)
494 		outb(0x01, TCO_RLD);
495 
496 	/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
497 	val = inw(TCO1_CNT);
498 	val &= 0xf7ff;
499 	outw(val, TCO1_CNT);
500 	val = inw(TCO1_CNT);
501 	spin_unlock(&iTCO_wdt_private.io_lock);
502 
503 	if (val & 0x0800)
504 		return -1;
505 	return 0;
506 }
507 
508 static int iTCO_wdt_stop(void)
509 {
510 	unsigned int val;
511 
512 	spin_lock(&iTCO_wdt_private.io_lock);
513 
514 	iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
515 
516 	/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
517 	val = inw(TCO1_CNT);
518 	val |= 0x0800;
519 	outw(val, TCO1_CNT);
520 	val = inw(TCO1_CNT);
521 
522 	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
523 	iTCO_wdt_set_NO_REBOOT_bit();
524 
525 	spin_unlock(&iTCO_wdt_private.io_lock);
526 
527 	if ((val & 0x0800) == 0)
528 		return -1;
529 	return 0;
530 }
531 
532 static int iTCO_wdt_keepalive(void)
533 {
534 	spin_lock(&iTCO_wdt_private.io_lock);
535 
536 	iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
537 
538 	/* Reload the timer by writing to the TCO Timer Counter register */
539 	if (iTCO_wdt_private.iTCO_version == 2)
540 		outw(0x01, TCO_RLD);
541 	else if (iTCO_wdt_private.iTCO_version == 1) {
542 		/* Reset the timeout status bit so that the timer
543 		 * needs to count down twice again before rebooting */
544 		outw(0x0008, TCO1_STS);	/* write 1 to clear bit */
545 
546 		outb(0x01, TCO_RLD);
547 	}
548 
549 	spin_unlock(&iTCO_wdt_private.io_lock);
550 	return 0;
551 }
552 
553 static int iTCO_wdt_set_heartbeat(int t)
554 {
555 	unsigned int val16;
556 	unsigned char val8;
557 	unsigned int tmrval;
558 
559 	tmrval = seconds_to_ticks(t);
560 
561 	/* For TCO v1 the timer counts down twice before rebooting */
562 	if (iTCO_wdt_private.iTCO_version == 1)
563 		tmrval /= 2;
564 
565 	/* from the specs: */
566 	/* "Values of 0h-3h are ignored and should not be attempted" */
567 	if (tmrval < 0x04)
568 		return -EINVAL;
569 	if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
570 	    ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
571 		return -EINVAL;
572 
573 	iTCO_vendor_pre_set_heartbeat(tmrval);
574 
575 	/* Write new heartbeat to watchdog */
576 	if (iTCO_wdt_private.iTCO_version == 2) {
577 		spin_lock(&iTCO_wdt_private.io_lock);
578 		val16 = inw(TCOv2_TMR);
579 		val16 &= 0xfc00;
580 		val16 |= tmrval;
581 		outw(val16, TCOv2_TMR);
582 		val16 = inw(TCOv2_TMR);
583 		spin_unlock(&iTCO_wdt_private.io_lock);
584 
585 		if ((val16 & 0x3ff) != tmrval)
586 			return -EINVAL;
587 	} else if (iTCO_wdt_private.iTCO_version == 1) {
588 		spin_lock(&iTCO_wdt_private.io_lock);
589 		val8 = inb(TCOv1_TMR);
590 		val8 &= 0xc0;
591 		val8 |= (tmrval & 0xff);
592 		outb(val8, TCOv1_TMR);
593 		val8 = inb(TCOv1_TMR);
594 		spin_unlock(&iTCO_wdt_private.io_lock);
595 
596 		if ((val8 & 0x3f) != tmrval)
597 			return -EINVAL;
598 	}
599 
600 	heartbeat = t;
601 	return 0;
602 }
603 
604 static int iTCO_wdt_get_timeleft(int *time_left)
605 {
606 	unsigned int val16;
607 	unsigned char val8;
608 
609 	/* read the TCO Timer */
610 	if (iTCO_wdt_private.iTCO_version == 2) {
611 		spin_lock(&iTCO_wdt_private.io_lock);
612 		val16 = inw(TCO_RLD);
613 		val16 &= 0x3ff;
614 		spin_unlock(&iTCO_wdt_private.io_lock);
615 
616 		*time_left = (val16 * 6) / 10;
617 	} else if (iTCO_wdt_private.iTCO_version == 1) {
618 		spin_lock(&iTCO_wdt_private.io_lock);
619 		val8 = inb(TCO_RLD);
620 		val8 &= 0x3f;
621 		if (!(inw(TCO1_STS) & 0x0008))
622 			val8 += (inb(TCOv1_TMR) & 0x3f);
623 		spin_unlock(&iTCO_wdt_private.io_lock);
624 
625 		*time_left = (val8 * 6) / 10;
626 	} else
627 		return -EINVAL;
628 	return 0;
629 }
630 
631 /*
632  *	/dev/watchdog handling
633  */
634 
635 static int iTCO_wdt_open(struct inode *inode, struct file *file)
636 {
637 	/* /dev/watchdog can only be opened once */
638 	if (test_and_set_bit(0, &is_active))
639 		return -EBUSY;
640 
641 	/*
642 	 *      Reload and activate timer
643 	 */
644 	iTCO_wdt_start();
645 	return nonseekable_open(inode, file);
646 }
647 
648 static int iTCO_wdt_release(struct inode *inode, struct file *file)
649 {
650 	/*
651 	 *      Shut off the timer.
652 	 */
653 	if (expect_release == 42) {
654 		iTCO_wdt_stop();
655 	} else {
656 		printk(KERN_CRIT PFX
657 			"Unexpected close, not stopping watchdog!\n");
658 		iTCO_wdt_keepalive();
659 	}
660 	clear_bit(0, &is_active);
661 	expect_release = 0;
662 	return 0;
663 }
664 
665 static ssize_t iTCO_wdt_write(struct file *file, const char __user *data,
666 			      size_t len, loff_t *ppos)
667 {
668 	/* See if we got the magic character 'V' and reload the timer */
669 	if (len) {
670 		if (!nowayout) {
671 			size_t i;
672 
673 			/* note: just in case someone wrote the magic
674 			   character five months ago... */
675 			expect_release = 0;
676 
677 			/* scan to see whether or not we got the
678 			   magic character */
679 			for (i = 0; i != len; i++) {
680 				char c;
681 				if (get_user(c, data + i))
682 					return -EFAULT;
683 				if (c == 'V')
684 					expect_release = 42;
685 			}
686 		}
687 
688 		/* someone wrote to us, we should reload the timer */
689 		iTCO_wdt_keepalive();
690 	}
691 	return len;
692 }
693 
694 static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
695 							unsigned long arg)
696 {
697 	int new_options, retval = -EINVAL;
698 	int new_heartbeat;
699 	void __user *argp = (void __user *)arg;
700 	int __user *p = argp;
701 	static const struct watchdog_info ident = {
702 		.options =		WDIOF_SETTIMEOUT |
703 					WDIOF_KEEPALIVEPING |
704 					WDIOF_MAGICCLOSE,
705 		.firmware_version =	0,
706 		.identity =		DRV_NAME,
707 	};
708 
709 	switch (cmd) {
710 	case WDIOC_GETSUPPORT:
711 		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
712 	case WDIOC_GETSTATUS:
713 	case WDIOC_GETBOOTSTATUS:
714 		return put_user(0, p);
715 
716 	case WDIOC_SETOPTIONS:
717 	{
718 		if (get_user(new_options, p))
719 			return -EFAULT;
720 
721 		if (new_options & WDIOS_DISABLECARD) {
722 			iTCO_wdt_stop();
723 			retval = 0;
724 		}
725 		if (new_options & WDIOS_ENABLECARD) {
726 			iTCO_wdt_keepalive();
727 			iTCO_wdt_start();
728 			retval = 0;
729 		}
730 		return retval;
731 	}
732 	case WDIOC_KEEPALIVE:
733 		iTCO_wdt_keepalive();
734 		return 0;
735 
736 	case WDIOC_SETTIMEOUT:
737 	{
738 		if (get_user(new_heartbeat, p))
739 			return -EFAULT;
740 		if (iTCO_wdt_set_heartbeat(new_heartbeat))
741 			return -EINVAL;
742 		iTCO_wdt_keepalive();
743 		/* Fall */
744 	}
745 	case WDIOC_GETTIMEOUT:
746 		return put_user(heartbeat, p);
747 	case WDIOC_GETTIMELEFT:
748 	{
749 		int time_left;
750 		if (iTCO_wdt_get_timeleft(&time_left))
751 			return -EINVAL;
752 		return put_user(time_left, p);
753 	}
754 	default:
755 		return -ENOTTY;
756 	}
757 }
758 
759 /*
760  *	Kernel Interfaces
761  */
762 
763 static const struct file_operations iTCO_wdt_fops = {
764 	.owner =		THIS_MODULE,
765 	.llseek =		no_llseek,
766 	.write =		iTCO_wdt_write,
767 	.unlocked_ioctl =	iTCO_wdt_ioctl,
768 	.open =			iTCO_wdt_open,
769 	.release =		iTCO_wdt_release,
770 };
771 
772 static struct miscdevice iTCO_wdt_miscdev = {
773 	.minor =	WATCHDOG_MINOR,
774 	.name =		"watchdog",
775 	.fops =		&iTCO_wdt_fops,
776 };
777 
778 /*
779  *	Init & exit routines
780  */
781 
782 static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
783 		const struct pci_device_id *ent, struct platform_device *dev)
784 {
785 	int ret;
786 	u32 base_address;
787 	unsigned long RCBA;
788 	unsigned long val32;
789 
790 	/*
791 	 *      Find the ACPI/PM base I/O address which is the base
792 	 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
793 	 *      ACPIBASE is bits [15:7] from 0x40-0x43
794 	 */
795 	pci_read_config_dword(pdev, 0x40, &base_address);
796 	base_address &= 0x0000ff80;
797 	if (base_address == 0x00000000) {
798 		/* Something's wrong here, ACPIBASE has to be set */
799 		printk(KERN_ERR PFX "failed to get TCOBASE address, "
800 					"device disabled by hardware/BIOS\n");
801 		return -ENODEV;
802 	}
803 	iTCO_wdt_private.iTCO_version =
804 			iTCO_chipset_info[ent->driver_data].iTCO_version;
805 	iTCO_wdt_private.ACPIBASE = base_address;
806 	iTCO_wdt_private.pdev = pdev;
807 
808 	/* Get the Memory-Mapped GCS register, we need it for the
809 	   NO_REBOOT flag (TCO v2). To get access to it you have to
810 	   read RCBA from PCI Config space 0xf0 and use it as base.
811 	   GCS = RCBA + ICH6_GCS(0x3410). */
812 	if (iTCO_wdt_private.iTCO_version == 2) {
813 		pci_read_config_dword(pdev, 0xf0, &base_address);
814 		if ((base_address & 1) == 0) {
815 			printk(KERN_ERR PFX "RCBA is disabled by hardware"
816 						"/BIOS, device disabled\n");
817 			ret = -ENODEV;
818 			goto out;
819 		}
820 		RCBA = base_address & 0xffffc000;
821 		iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
822 	}
823 
824 	/* Check chipset's NO_REBOOT bit */
825 	if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
826 		printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
827 					"device disabled by hardware/BIOS\n");
828 		ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
829 		goto out_unmap;
830 	}
831 
832 	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
833 	iTCO_wdt_set_NO_REBOOT_bit();
834 
835 	/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
836 	if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
837 		printk(KERN_ERR PFX
838 			"I/O address 0x%04lx already in use, "
839 						"device disabled\n", SMI_EN);
840 		ret = -EIO;
841 		goto out_unmap;
842 	}
843 	/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
844 	val32 = inl(SMI_EN);
845 	val32 &= 0xffffdfff;	/* Turn off SMI clearing watchdog */
846 	outl(val32, SMI_EN);
847 
848 	/* The TCO I/O registers reside in a 32-byte range pointed to
849 	   by the TCOBASE value */
850 	if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
851 		printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
852 						"device disabled\n", TCOBASE);
853 		ret = -EIO;
854 		goto unreg_smi_en;
855 	}
856 
857 	printk(KERN_INFO PFX
858 		"Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
859 			iTCO_chipset_info[ent->driver_data].name,
860 			iTCO_chipset_info[ent->driver_data].iTCO_version,
861 			TCOBASE);
862 
863 	/* Clear out the (probably old) status */
864 	outw(0x0008, TCO1_STS);	/* Clear the Time Out Status bit */
865 	outw(0x0002, TCO2_STS);	/* Clear SECOND_TO_STS bit */
866 	outw(0x0004, TCO2_STS);	/* Clear BOOT_STS bit */
867 
868 	/* Make sure the watchdog is not running */
869 	iTCO_wdt_stop();
870 
871 	/* Check that the heartbeat value is within it's range;
872 	   if not reset to the default */
873 	if (iTCO_wdt_set_heartbeat(heartbeat)) {
874 		iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
875 		printk(KERN_INFO PFX
876 			"timeout value out of range, using %d\n", heartbeat);
877 	}
878 
879 	ret = misc_register(&iTCO_wdt_miscdev);
880 	if (ret != 0) {
881 		printk(KERN_ERR PFX
882 			"cannot register miscdev on minor=%d (err=%d)\n",
883 							WATCHDOG_MINOR, ret);
884 		goto unreg_region;
885 	}
886 
887 	printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
888 							heartbeat, nowayout);
889 
890 	return 0;
891 
892 unreg_region:
893 	release_region(TCOBASE, 0x20);
894 unreg_smi_en:
895 	release_region(SMI_EN, 4);
896 out_unmap:
897 	if (iTCO_wdt_private.iTCO_version == 2)
898 		iounmap(iTCO_wdt_private.gcs);
899 out:
900 	iTCO_wdt_private.ACPIBASE = 0;
901 	return ret;
902 }
903 
904 static void __devexit iTCO_wdt_cleanup(void)
905 {
906 	/* Stop the timer before we leave */
907 	if (!nowayout)
908 		iTCO_wdt_stop();
909 
910 	/* Deregister */
911 	misc_deregister(&iTCO_wdt_miscdev);
912 	release_region(TCOBASE, 0x20);
913 	release_region(SMI_EN, 4);
914 	if (iTCO_wdt_private.iTCO_version == 2)
915 		iounmap(iTCO_wdt_private.gcs);
916 	pci_dev_put(iTCO_wdt_private.pdev);
917 	iTCO_wdt_private.ACPIBASE = 0;
918 }
919 
920 static int __devinit iTCO_wdt_probe(struct platform_device *dev)
921 {
922 	int ret = -ENODEV;
923 	int found = 0;
924 	struct pci_dev *pdev = NULL;
925 	const struct pci_device_id *ent;
926 
927 	spin_lock_init(&iTCO_wdt_private.io_lock);
928 
929 	for_each_pci_dev(pdev) {
930 		ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
931 		if (ent) {
932 			found++;
933 			ret = iTCO_wdt_init(pdev, ent, dev);
934 			if (!ret)
935 				break;
936 		}
937 	}
938 
939 	if (!found)
940 		printk(KERN_INFO PFX "No device detected.\n");
941 
942 	return ret;
943 }
944 
945 static int __devexit iTCO_wdt_remove(struct platform_device *dev)
946 {
947 	if (iTCO_wdt_private.ACPIBASE)
948 		iTCO_wdt_cleanup();
949 
950 	return 0;
951 }
952 
953 static void iTCO_wdt_shutdown(struct platform_device *dev)
954 {
955 	iTCO_wdt_stop();
956 }
957 
958 #define iTCO_wdt_suspend NULL
959 #define iTCO_wdt_resume  NULL
960 
961 static struct platform_driver iTCO_wdt_driver = {
962 	.probe          = iTCO_wdt_probe,
963 	.remove         = __devexit_p(iTCO_wdt_remove),
964 	.shutdown       = iTCO_wdt_shutdown,
965 	.suspend        = iTCO_wdt_suspend,
966 	.resume         = iTCO_wdt_resume,
967 	.driver         = {
968 		.owner  = THIS_MODULE,
969 		.name   = DRV_NAME,
970 	},
971 };
972 
973 static int __init iTCO_wdt_init_module(void)
974 {
975 	int err;
976 
977 	printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
978 		DRV_VERSION);
979 
980 	err = platform_driver_register(&iTCO_wdt_driver);
981 	if (err)
982 		return err;
983 
984 	iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
985 								-1, NULL, 0);
986 	if (IS_ERR(iTCO_wdt_platform_device)) {
987 		err = PTR_ERR(iTCO_wdt_platform_device);
988 		goto unreg_platform_driver;
989 	}
990 
991 	return 0;
992 
993 unreg_platform_driver:
994 	platform_driver_unregister(&iTCO_wdt_driver);
995 	return err;
996 }
997 
998 static void __exit iTCO_wdt_cleanup_module(void)
999 {
1000 	platform_device_unregister(iTCO_wdt_platform_device);
1001 	platform_driver_unregister(&iTCO_wdt_driver);
1002 	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
1003 }
1004 
1005 module_init(iTCO_wdt_init_module);
1006 module_exit(iTCO_wdt_cleanup_module);
1007 
1008 MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
1009 MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
1010 MODULE_VERSION(DRV_VERSION);
1011 MODULE_LICENSE("GPL");
1012 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
1013