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