xref: /openbmc/linux/drivers/watchdog/iTCO_wdt.c (revision 96de0e252cedffad61b3cb5e05662c591898e69a)
1 /*
2  *	intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
3  *
4  *	(c) Copyright 2006-2007 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  *	82801AA  (ICH)       : document number 290655-003, 290677-014,
18  *	82801AB  (ICHO)      : document number 290655-003, 290677-014,
19  *	82801BA  (ICH2)      : document number 290687-002, 298242-027,
20  *	82801BAM (ICH2-M)    : document number 290687-002, 298242-027,
21  *	82801CA  (ICH3-S)    : document number 290733-003, 290739-013,
22  *	82801CAM (ICH3-M)    : document number 290716-001, 290718-007,
23  *	82801DB  (ICH4)      : document number 290744-001, 290745-020,
24  *	82801DBM (ICH4-M)    : document number 252337-001, 252663-005,
25  *	82801E   (C-ICH)     : document number 273599-001, 273645-002,
26  *	82801EB  (ICH5)      : document number 252516-001, 252517-003,
27  *	82801ER  (ICH5R)     : document number 252516-001, 252517-003,
28  *	82801FB  (ICH6)      : document number 301473-002, 301474-007,
29  *	82801FR  (ICH6R)     : document number 301473-002, 301474-007,
30  *	82801FBM (ICH6-M)    : document number 301473-002, 301474-007,
31  *	82801FW  (ICH6W)     : document number 301473-001, 301474-007,
32  *	82801FRW (ICH6RW)    : document number 301473-001, 301474-007,
33  *	82801GB  (ICH7)      : document number 307013-002, 307014-009,
34  *	82801GR  (ICH7R)     : document number 307013-002, 307014-009,
35  *	82801GDH (ICH7DH)    : document number 307013-002, 307014-009,
36  *	82801GBM (ICH7-M)    : document number 307013-002, 307014-009,
37  *	82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
38  *	82801HB  (ICH8)      : document number 313056-002, 313057-004,
39  *	82801HR  (ICH8R)     : document number 313056-002, 313057-004,
40  *	82801HH  (ICH8DH)    : document number 313056-002, 313057-004,
41  *	82801HO  (ICH8DO)    : document number 313056-002, 313057-004,
42  *	82801IB  (ICH9)      : document number 316972-001, 316973-001,
43  *	82801IR  (ICH9R)     : document number 316972-001, 316973-001,
44  *	82801IH  (ICH9DH)    : document number 316972-001, 316973-001,
45  *	6300ESB  (6300ESB)   : document number 300641-003, 300884-010,
46  *	631xESB  (631xESB)   : document number 313082-001, 313075-005,
47  *	632xESB  (632xESB)   : document number 313082-001, 313075-005
48  */
49 
50 /*
51  *	Includes, defines, variables, module parameters, ...
52  */
53 
54 /* Module and version information */
55 #define DRV_NAME        "iTCO_wdt"
56 #define DRV_VERSION     "1.02"
57 #define DRV_RELDATE     "26-Jul-2007"
58 #define PFX		DRV_NAME ": "
59 
60 /* Includes */
61 #include <linux/module.h>		/* For module specific items */
62 #include <linux/moduleparam.h>		/* For new moduleparam's */
63 #include <linux/types.h>		/* For standard types (like size_t) */
64 #include <linux/errno.h>		/* For the -ENODEV/... values */
65 #include <linux/kernel.h>		/* For printk/panic/... */
66 #include <linux/miscdevice.h>		/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
67 #include <linux/watchdog.h>		/* For the watchdog specific items */
68 #include <linux/init.h>			/* For __init/__exit/... */
69 #include <linux/fs.h>			/* For file operations */
70 #include <linux/platform_device.h>	/* For platform_driver framework */
71 #include <linux/pci.h>			/* For pci functions */
72 #include <linux/ioport.h>		/* For io-port access */
73 #include <linux/spinlock.h>		/* For spin_lock/spin_unlock/... */
74 
75 #include <asm/uaccess.h>		/* For copy_to_user/put_user/... */
76 #include <asm/io.h>			/* For inb/outb/... */
77 
78 /* TCO related info */
79 enum iTCO_chipsets {
80 	TCO_ICH = 0,	/* ICH */
81 	TCO_ICH0,	/* ICH0 */
82 	TCO_ICH2,	/* ICH2 */
83 	TCO_ICH2M,	/* ICH2-M */
84 	TCO_ICH3,	/* ICH3-S */
85 	TCO_ICH3M,	/* ICH3-M */
86 	TCO_ICH4,	/* ICH4 */
87 	TCO_ICH4M,	/* ICH4-M */
88 	TCO_CICH,	/* C-ICH */
89 	TCO_ICH5,	/* ICH5 & ICH5R */
90 	TCO_6300ESB,	/* 6300ESB */
91 	TCO_ICH6,	/* ICH6 & ICH6R */
92 	TCO_ICH6M,	/* ICH6-M */
93 	TCO_ICH6W,	/* ICH6W & ICH6RW */
94 	TCO_ICH7,	/* ICH7 & ICH7R */
95 	TCO_ICH7M,	/* ICH7-M */
96 	TCO_ICH7MDH,	/* ICH7-M DH */
97 	TCO_ICH8,	/* ICH8 & ICH8R */
98 	TCO_ICH8DH,	/* ICH8DH */
99 	TCO_ICH8DO,	/* ICH8DO */
100 	TCO_ICH9,	/* ICH9 */
101 	TCO_ICH9R,	/* ICH9R */
102 	TCO_ICH9DH,	/* ICH9DH */
103 	TCO_631XESB,	/* 631xESB/632xESB */
104 };
105 
106 static struct {
107 	char *name;
108 	unsigned int iTCO_version;
109 } iTCO_chipset_info[] __devinitdata = {
110 	{"ICH", 1},
111 	{"ICH0", 1},
112 	{"ICH2", 1},
113 	{"ICH2-M", 1},
114 	{"ICH3-S", 1},
115 	{"ICH3-M", 1},
116 	{"ICH4", 1},
117 	{"ICH4-M", 1},
118 	{"C-ICH", 1},
119 	{"ICH5 or ICH5R", 1},
120 	{"6300ESB", 1},
121 	{"ICH6 or ICH6R", 2},
122 	{"ICH6-M", 2},
123 	{"ICH6W or ICH6RW", 2},
124 	{"ICH7 or ICH7R", 2},
125 	{"ICH7-M", 2},
126 	{"ICH7-M DH", 2},
127 	{"ICH8 or ICH8R", 2},
128 	{"ICH8DH", 2},
129 	{"ICH8DO", 2},
130 	{"ICH9", 2},
131 	{"ICH9R", 2},
132 	{"ICH9DH", 2},
133 	{"631xESB/632xESB", 2},
134 	{NULL,0}
135 };
136 
137 /*
138  * This data only exists for exporting the supported PCI ids
139  * via MODULE_DEVICE_TABLE.  We do not actually register a
140  * pci_driver, because the I/O Controller Hub has also other
141  * functions that probably will be registered by other drivers.
142  */
143 static struct pci_device_id iTCO_wdt_pci_tbl[] = {
144 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH     },
145 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0    },
146 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2    },
147 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M   },
148 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3    },
149 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M   },
150 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4    },
151 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M   },
152 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH    },
153 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5    },
154 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB },
155 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6    },
156 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M   },
157 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W   },
158 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7    },
159 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M   },
160 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
161 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8    },
162 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH  },
163 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO  },
164 	{ PCI_VENDOR_ID_INTEL, 0x2918,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9    },
165 	{ PCI_VENDOR_ID_INTEL, 0x2916,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R    },
166 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH    },
167 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
168 	{ PCI_VENDOR_ID_INTEL, 0x2671,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
169 	{ PCI_VENDOR_ID_INTEL, 0x2672,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
170 	{ PCI_VENDOR_ID_INTEL, 0x2673,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
171 	{ PCI_VENDOR_ID_INTEL, 0x2674,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
172 	{ PCI_VENDOR_ID_INTEL, 0x2675,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
173 	{ PCI_VENDOR_ID_INTEL, 0x2676,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
174 	{ PCI_VENDOR_ID_INTEL, 0x2677,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
175 	{ PCI_VENDOR_ID_INTEL, 0x2678,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
176 	{ PCI_VENDOR_ID_INTEL, 0x2679,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
177 	{ PCI_VENDOR_ID_INTEL, 0x267a,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
178 	{ PCI_VENDOR_ID_INTEL, 0x267b,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
179 	{ PCI_VENDOR_ID_INTEL, 0x267c,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
180 	{ PCI_VENDOR_ID_INTEL, 0x267d,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
181 	{ PCI_VENDOR_ID_INTEL, 0x267e,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
182 	{ PCI_VENDOR_ID_INTEL, 0x267f,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
183 	{ 0, },			/* End of list */
184 };
185 MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
186 
187 /* Address definitions for the TCO */
188 #define	TCOBASE		iTCO_wdt_private.ACPIBASE + 0x60	/* TCO base address                */
189 #define	SMI_EN		iTCO_wdt_private.ACPIBASE + 0x30	/* SMI Control and Enable Register */
190 
191 #define TCO_RLD		TCOBASE + 0x00	/* TCO Timer Reload and Current Value */
192 #define TCOv1_TMR	TCOBASE + 0x01	/* TCOv1 Timer Initial Value	*/
193 #define	TCO_DAT_IN	TCOBASE + 0x02	/* TCO Data In Register		*/
194 #define	TCO_DAT_OUT	TCOBASE + 0x03	/* TCO Data Out Register	*/
195 #define	TCO1_STS	TCOBASE + 0x04	/* TCO1 Status Register		*/
196 #define	TCO2_STS	TCOBASE + 0x06	/* TCO2 Status Register		*/
197 #define TCO1_CNT	TCOBASE + 0x08	/* TCO1 Control Register	*/
198 #define TCO2_CNT	TCOBASE + 0x0a	/* TCO2 Control Register	*/
199 #define TCOv2_TMR	TCOBASE + 0x12	/* TCOv2 Timer Initial Value	*/
200 
201 /* internal variables */
202 static unsigned long is_active;
203 static char expect_release;
204 static struct {				/* this is private data for the iTCO_wdt device */
205 	unsigned int iTCO_version;	/* TCO version/generation */
206 	unsigned long ACPIBASE;		/* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
207 	unsigned long __iomem *gcs;	/* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */
208 	spinlock_t io_lock;		/* the lock for io operations */
209 	struct pci_dev *pdev;		/* the PCI-device */
210 } iTCO_wdt_private;
211 
212 static struct platform_device *iTCO_wdt_platform_device;	/* the watchdog platform device */
213 
214 /* module parameters */
215 #define WATCHDOG_HEARTBEAT 30	/* 30 sec default heartbeat */
216 static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
217 module_param(heartbeat, int, 0);
218 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
219 
220 static int nowayout = WATCHDOG_NOWAYOUT;
221 module_param(nowayout, int, 0);
222 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
223 
224 /* iTCO Vendor Specific Support hooks */
225 #ifdef CONFIG_ITCO_VENDOR_SUPPORT
226 extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
227 extern void iTCO_vendor_pre_stop(unsigned long);
228 extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
229 extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
230 extern int iTCO_vendor_check_noreboot_on(void);
231 #else
232 #define iTCO_vendor_pre_start(acpibase, heartbeat)	{}
233 #define iTCO_vendor_pre_stop(acpibase)			{}
234 #define iTCO_vendor_pre_keepalive(acpibase,heartbeat)	{}
235 #define iTCO_vendor_pre_set_heartbeat(heartbeat)	{}
236 #define iTCO_vendor_check_noreboot_on()			1	/* 1=check noreboot; 0=don't check */
237 #endif
238 
239 /*
240  * Some TCO specific functions
241  */
242 
243 static inline unsigned int seconds_to_ticks(int seconds)
244 {
245 	/* the internal timer is stored as ticks which decrement
246 	 * every 0.6 seconds */
247 	return (seconds * 10) / 6;
248 }
249 
250 static void iTCO_wdt_set_NO_REBOOT_bit(void)
251 {
252 	u32 val32;
253 
254 	/* Set the NO_REBOOT bit: this disables reboots */
255 	if (iTCO_wdt_private.iTCO_version == 2) {
256 		val32 = readl(iTCO_wdt_private.gcs);
257 		val32 |= 0x00000020;
258 		writel(val32, iTCO_wdt_private.gcs);
259 	} else if (iTCO_wdt_private.iTCO_version == 1) {
260 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
261 		val32 |= 0x00000002;
262 		pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
263 	}
264 }
265 
266 static int iTCO_wdt_unset_NO_REBOOT_bit(void)
267 {
268 	int ret = 0;
269 	u32 val32;
270 
271 	/* Unset the NO_REBOOT bit: this enables reboots */
272 	if (iTCO_wdt_private.iTCO_version == 2) {
273 		val32 = readl(iTCO_wdt_private.gcs);
274 		val32 &= 0xffffffdf;
275 		writel(val32, iTCO_wdt_private.gcs);
276 
277 		val32 = readl(iTCO_wdt_private.gcs);
278 		if (val32 & 0x00000020)
279 			ret = -EIO;
280 	} else if (iTCO_wdt_private.iTCO_version == 1) {
281 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
282 		val32 &= 0xfffffffd;
283 		pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
284 
285 		pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
286 		if (val32 & 0x00000002)
287 			ret = -EIO;
288 	}
289 
290 	return ret; /* returns: 0 = OK, -EIO = Error */
291 }
292 
293 static int iTCO_wdt_start(void)
294 {
295 	unsigned int val;
296 
297 	spin_lock(&iTCO_wdt_private.io_lock);
298 
299 	iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
300 
301 	/* disable chipset's NO_REBOOT bit */
302 	if (iTCO_wdt_unset_NO_REBOOT_bit()) {
303 		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
304 		return -EIO;
305 	}
306 
307 	/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
308 	val = inw(TCO1_CNT);
309 	val &= 0xf7ff;
310 	outw(val, TCO1_CNT);
311 	val = inw(TCO1_CNT);
312 	spin_unlock(&iTCO_wdt_private.io_lock);
313 
314 	if (val & 0x0800)
315 		return -1;
316 	return 0;
317 }
318 
319 static int iTCO_wdt_stop(void)
320 {
321 	unsigned int val;
322 
323 	spin_lock(&iTCO_wdt_private.io_lock);
324 
325 	iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
326 
327 	/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
328 	val = inw(TCO1_CNT);
329 	val |= 0x0800;
330 	outw(val, TCO1_CNT);
331 	val = inw(TCO1_CNT);
332 
333 	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
334 	iTCO_wdt_set_NO_REBOOT_bit();
335 
336 	spin_unlock(&iTCO_wdt_private.io_lock);
337 
338 	if ((val & 0x0800) == 0)
339 		return -1;
340 	return 0;
341 }
342 
343 static int iTCO_wdt_keepalive(void)
344 {
345 	spin_lock(&iTCO_wdt_private.io_lock);
346 
347 	iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
348 
349 	/* Reload the timer by writing to the TCO Timer Counter register */
350 	if (iTCO_wdt_private.iTCO_version == 2) {
351 		outw(0x01, TCO_RLD);
352 	} else if (iTCO_wdt_private.iTCO_version == 1) {
353 		outb(0x01, TCO_RLD);
354 	}
355 
356 	spin_unlock(&iTCO_wdt_private.io_lock);
357 	return 0;
358 }
359 
360 static int iTCO_wdt_set_heartbeat(int t)
361 {
362 	unsigned int val16;
363 	unsigned char val8;
364 	unsigned int tmrval;
365 
366 	tmrval = seconds_to_ticks(t);
367 	/* from the specs: */
368 	/* "Values of 0h-3h are ignored and should not be attempted" */
369 	if (tmrval < 0x04)
370 		return -EINVAL;
371 	if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
372 	    ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
373 		return -EINVAL;
374 
375 	iTCO_vendor_pre_set_heartbeat(tmrval);
376 
377 	/* Write new heartbeat to watchdog */
378 	if (iTCO_wdt_private.iTCO_version == 2) {
379 		spin_lock(&iTCO_wdt_private.io_lock);
380 		val16 = inw(TCOv2_TMR);
381 		val16 &= 0xfc00;
382 		val16 |= tmrval;
383 		outw(val16, TCOv2_TMR);
384 		val16 = inw(TCOv2_TMR);
385 		spin_unlock(&iTCO_wdt_private.io_lock);
386 
387 		if ((val16 & 0x3ff) != tmrval)
388 			return -EINVAL;
389 	} else if (iTCO_wdt_private.iTCO_version == 1) {
390 		spin_lock(&iTCO_wdt_private.io_lock);
391 		val8 = inb(TCOv1_TMR);
392 		val8 &= 0xc0;
393 		val8 |= (tmrval & 0xff);
394 		outb(val8, TCOv1_TMR);
395 		val8 = inb(TCOv1_TMR);
396 		spin_unlock(&iTCO_wdt_private.io_lock);
397 
398 		if ((val8 & 0x3f) != tmrval)
399 			return -EINVAL;
400 	}
401 
402 	heartbeat = t;
403 	return 0;
404 }
405 
406 static int iTCO_wdt_get_timeleft (int *time_left)
407 {
408 	unsigned int val16;
409 	unsigned char val8;
410 
411 	/* read the TCO Timer */
412 	if (iTCO_wdt_private.iTCO_version == 2) {
413 		spin_lock(&iTCO_wdt_private.io_lock);
414 		val16 = inw(TCO_RLD);
415 		val16 &= 0x3ff;
416 		spin_unlock(&iTCO_wdt_private.io_lock);
417 
418 		*time_left = (val16 * 6) / 10;
419 	} else if (iTCO_wdt_private.iTCO_version == 1) {
420 		spin_lock(&iTCO_wdt_private.io_lock);
421 		val8 = inb(TCO_RLD);
422 		val8 &= 0x3f;
423 		spin_unlock(&iTCO_wdt_private.io_lock);
424 
425 		*time_left = (val8 * 6) / 10;
426 	} else
427 		return -EINVAL;
428 	return 0;
429 }
430 
431 /*
432  *	/dev/watchdog handling
433  */
434 
435 static int iTCO_wdt_open (struct inode *inode, struct file *file)
436 {
437 	/* /dev/watchdog can only be opened once */
438 	if (test_and_set_bit(0, &is_active))
439 		return -EBUSY;
440 
441 	/*
442 	 *      Reload and activate timer
443 	 */
444 	iTCO_wdt_keepalive();
445 	iTCO_wdt_start();
446 	return nonseekable_open(inode, file);
447 }
448 
449 static int iTCO_wdt_release (struct inode *inode, struct file *file)
450 {
451 	/*
452 	 *      Shut off the timer.
453 	 */
454 	if (expect_release == 42) {
455 		iTCO_wdt_stop();
456 	} else {
457 		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
458 		iTCO_wdt_keepalive();
459 	}
460 	clear_bit(0, &is_active);
461 	expect_release = 0;
462 	return 0;
463 }
464 
465 static ssize_t iTCO_wdt_write (struct file *file, const char __user *data,
466 			      size_t len, loff_t * ppos)
467 {
468 	/* See if we got the magic character 'V' and reload the timer */
469 	if (len) {
470 		if (!nowayout) {
471 			size_t i;
472 
473 			/* note: just in case someone wrote the magic character
474 			 * five months ago... */
475 			expect_release = 0;
476 
477 			/* scan to see whether or not we got the magic character */
478 			for (i = 0; i != len; i++) {
479 				char c;
480 				if (get_user(c, data+i))
481 					return -EFAULT;
482 				if (c == 'V')
483 					expect_release = 42;
484 			}
485 		}
486 
487 		/* someone wrote to us, we should reload the timer */
488 		iTCO_wdt_keepalive();
489 	}
490 	return len;
491 }
492 
493 static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
494 			  unsigned int cmd, unsigned long arg)
495 {
496 	int new_options, retval = -EINVAL;
497 	int new_heartbeat;
498 	void __user *argp = (void __user *)arg;
499 	int __user *p = argp;
500 	static struct watchdog_info ident = {
501 		.options =		WDIOF_SETTIMEOUT |
502 					WDIOF_KEEPALIVEPING |
503 					WDIOF_MAGICCLOSE,
504 		.firmware_version =	0,
505 		.identity =		DRV_NAME,
506 	};
507 
508 	switch (cmd) {
509 		case WDIOC_GETSUPPORT:
510 			return copy_to_user(argp, &ident,
511 				sizeof (ident)) ? -EFAULT : 0;
512 
513 		case WDIOC_GETSTATUS:
514 		case WDIOC_GETBOOTSTATUS:
515 			return put_user(0, p);
516 
517 		case WDIOC_KEEPALIVE:
518 			iTCO_wdt_keepalive();
519 			return 0;
520 
521 		case WDIOC_SETOPTIONS:
522 		{
523 			if (get_user(new_options, p))
524 				return -EFAULT;
525 
526 			if (new_options & WDIOS_DISABLECARD) {
527 				iTCO_wdt_stop();
528 				retval = 0;
529 			}
530 
531 			if (new_options & WDIOS_ENABLECARD) {
532 				iTCO_wdt_keepalive();
533 				iTCO_wdt_start();
534 				retval = 0;
535 			}
536 
537 			return retval;
538 		}
539 
540 		case WDIOC_SETTIMEOUT:
541 		{
542 			if (get_user(new_heartbeat, p))
543 				return -EFAULT;
544 
545 			if (iTCO_wdt_set_heartbeat(new_heartbeat))
546 				return -EINVAL;
547 
548 			iTCO_wdt_keepalive();
549 			/* Fall */
550 		}
551 
552 		case WDIOC_GETTIMEOUT:
553 			return put_user(heartbeat, p);
554 
555 		case WDIOC_GETTIMELEFT:
556 		{
557 			int time_left;
558 
559 			if (iTCO_wdt_get_timeleft(&time_left))
560 				return -EINVAL;
561 
562 			return put_user(time_left, p);
563 		}
564 
565 		default:
566 			return -ENOTTY;
567 	}
568 }
569 
570 /*
571  *	Kernel Interfaces
572  */
573 
574 static const struct file_operations iTCO_wdt_fops = {
575 	.owner =	THIS_MODULE,
576 	.llseek =	no_llseek,
577 	.write =	iTCO_wdt_write,
578 	.ioctl =	iTCO_wdt_ioctl,
579 	.open =		iTCO_wdt_open,
580 	.release =	iTCO_wdt_release,
581 };
582 
583 static struct miscdevice iTCO_wdt_miscdev = {
584 	.minor =	WATCHDOG_MINOR,
585 	.name =		"watchdog",
586 	.fops =		&iTCO_wdt_fops,
587 };
588 
589 /*
590  *	Init & exit routines
591  */
592 
593 static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
594 {
595 	int ret;
596 	u32 base_address;
597 	unsigned long RCBA;
598 	unsigned long val32;
599 
600 	/*
601 	 *      Find the ACPI/PM base I/O address which is the base
602 	 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
603 	 *      ACPIBASE is bits [15:7] from 0x40-0x43
604 	 */
605 	pci_read_config_dword(pdev, 0x40, &base_address);
606 	base_address &= 0x0000ff80;
607 	if (base_address == 0x00000000) {
608 		/* Something's wrong here, ACPIBASE has to be set */
609 		printk(KERN_ERR PFX "failed to get TCOBASE address\n");
610 		pci_dev_put(pdev);
611 		return -ENODEV;
612 	}
613 	iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version;
614 	iTCO_wdt_private.ACPIBASE = base_address;
615 	iTCO_wdt_private.pdev = pdev;
616 
617 	/* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */
618 	/* To get access to it you have to read RCBA from PCI Config space 0xf0
619 	   and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */
620 	if (iTCO_wdt_private.iTCO_version == 2) {
621 		pci_read_config_dword(pdev, 0xf0, &base_address);
622 		RCBA = base_address & 0xffffc000;
623 		iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4);
624 	}
625 
626 	/* Check chipset's NO_REBOOT bit */
627 	if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
628 		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
629 		ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
630 		goto out;
631 	}
632 
633 	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
634 	iTCO_wdt_set_NO_REBOOT_bit();
635 
636 	/* Set the TCO_EN bit in SMI_EN register */
637 	if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
638 		printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
639 			SMI_EN );
640 		ret = -EIO;
641 		goto out;
642 	}
643 	val32 = inl(SMI_EN);
644 	val32 &= 0xffffdfff;	/* Turn off SMI clearing watchdog */
645 	outl(val32, SMI_EN);
646 	release_region(SMI_EN, 4);
647 
648 	/* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */
649 	if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) {
650 		printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n",
651 			TCOBASE);
652 		ret = -EIO;
653 		goto out;
654 	}
655 
656 	printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
657 		iTCO_chipset_info[ent->driver_data].name,
658 		iTCO_chipset_info[ent->driver_data].iTCO_version,
659 		TCOBASE);
660 
661 	/* Clear out the (probably old) status */
662 	outb(0, TCO1_STS);
663 	outb(3, TCO2_STS);
664 
665 	/* Make sure the watchdog is not running */
666 	iTCO_wdt_stop();
667 
668 	/* Check that the heartbeat value is within it's range ; if not reset to the default */
669 	if (iTCO_wdt_set_heartbeat(heartbeat)) {
670 		iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
671 		printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n",
672 			heartbeat);
673 	}
674 
675 	ret = misc_register(&iTCO_wdt_miscdev);
676 	if (ret != 0) {
677 		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
678 			WATCHDOG_MINOR, ret);
679 		goto unreg_region;
680 	}
681 
682 	printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
683 		heartbeat, nowayout);
684 
685 	return 0;
686 
687 unreg_region:
688 	release_region (TCOBASE, 0x20);
689 out:
690 	if (iTCO_wdt_private.iTCO_version == 2)
691 		iounmap(iTCO_wdt_private.gcs);
692 	pci_dev_put(iTCO_wdt_private.pdev);
693 	iTCO_wdt_private.ACPIBASE = 0;
694 	return ret;
695 }
696 
697 static void iTCO_wdt_cleanup(void)
698 {
699 	/* Stop the timer before we leave */
700 	if (!nowayout)
701 		iTCO_wdt_stop();
702 
703 	/* Deregister */
704 	misc_deregister(&iTCO_wdt_miscdev);
705 	release_region(TCOBASE, 0x20);
706 	if (iTCO_wdt_private.iTCO_version == 2)
707 		iounmap(iTCO_wdt_private.gcs);
708 	pci_dev_put(iTCO_wdt_private.pdev);
709 	iTCO_wdt_private.ACPIBASE = 0;
710 }
711 
712 static int iTCO_wdt_probe(struct platform_device *dev)
713 {
714 	int found = 0;
715 	struct pci_dev *pdev = NULL;
716 	const struct pci_device_id *ent;
717 
718 	spin_lock_init(&iTCO_wdt_private.io_lock);
719 
720 	for_each_pci_dev(pdev) {
721 		ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
722 		if (ent) {
723 			if (!(iTCO_wdt_init(pdev, ent, dev))) {
724 				found++;
725 				break;
726 			}
727 		}
728 	}
729 
730 	if (!found) {
731 		printk(KERN_INFO PFX "No card detected\n");
732 		return -ENODEV;
733 	}
734 
735 	return 0;
736 }
737 
738 static int iTCO_wdt_remove(struct platform_device *dev)
739 {
740 	if (iTCO_wdt_private.ACPIBASE)
741 		iTCO_wdt_cleanup();
742 
743 	return 0;
744 }
745 
746 static void iTCO_wdt_shutdown(struct platform_device *dev)
747 {
748 	iTCO_wdt_stop();
749 }
750 
751 #define iTCO_wdt_suspend NULL
752 #define iTCO_wdt_resume  NULL
753 
754 static struct platform_driver iTCO_wdt_driver = {
755 	.probe          = iTCO_wdt_probe,
756 	.remove         = iTCO_wdt_remove,
757 	.shutdown       = iTCO_wdt_shutdown,
758 	.suspend        = iTCO_wdt_suspend,
759 	.resume         = iTCO_wdt_resume,
760 	.driver         = {
761 		.owner  = THIS_MODULE,
762 		.name   = DRV_NAME,
763 	},
764 };
765 
766 static int __init iTCO_wdt_init_module(void)
767 {
768 	int err;
769 
770 	printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n",
771 		DRV_VERSION, DRV_RELDATE);
772 
773 	err = platform_driver_register(&iTCO_wdt_driver);
774 	if (err)
775 		return err;
776 
777 	iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
778 	if (IS_ERR(iTCO_wdt_platform_device)) {
779 		err = PTR_ERR(iTCO_wdt_platform_device);
780 		goto unreg_platform_driver;
781 	}
782 
783 	return 0;
784 
785 unreg_platform_driver:
786 	platform_driver_unregister(&iTCO_wdt_driver);
787 	return err;
788 }
789 
790 static void __exit iTCO_wdt_cleanup_module(void)
791 {
792 	platform_device_unregister(iTCO_wdt_platform_device);
793 	platform_driver_unregister(&iTCO_wdt_driver);
794 	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
795 }
796 
797 module_init(iTCO_wdt_init_module);
798 module_exit(iTCO_wdt_cleanup_module);
799 
800 MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
801 MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
802 MODULE_VERSION(DRV_VERSION);
803 MODULE_LICENSE("GPL");
804 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
805