1 /*
2  *	w83627hf/thf WDT driver
3  *
4  *	(c) Copyright 2013 Guenter Roeck
5  *		converted to watchdog infrastructure
6  *
7  *	(c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
8  *		added support for W83627THF.
9  *
10  *	(c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
11  *
12  *	Based on advantechwdt.c which is based on wdt.c.
13  *	Original copyright messages:
14  *
15  *	(c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
16  *
17  *	(c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
18  *						All Rights Reserved.
19  *
20  *	This program is free software; you can redistribute it and/or
21  *	modify it under the terms of the GNU General Public License
22  *	as published by the Free Software Foundation; either version
23  *	2 of the License, or (at your option) any later version.
24  *
25  *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
26  *	warranty for any of this software. This material is provided
27  *	"AS-IS" and at no charge.
28  *
29  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
30  */
31 
32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33 
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/types.h>
37 #include <linux/watchdog.h>
38 #include <linux/ioport.h>
39 #include <linux/init.h>
40 #include <linux/io.h>
41 
42 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
43 #define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
44 
45 static int wdt_io;
46 static int cr_wdt_timeout;	/* WDT timeout register */
47 static int cr_wdt_control;	/* WDT control register */
48 static int cr_wdt_csr;		/* WDT control & status register */
49 
50 enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
51 	     w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p,
52 	     w83667hg_b, nct6775, nct6776, nct6779, nct6791, nct6792, nct6102 };
53 
54 static int timeout;			/* in seconds */
55 module_param(timeout, int, 0);
56 MODULE_PARM_DESC(timeout,
57 		"Watchdog timeout in seconds. 1 <= timeout <= 255, default="
58 				__MODULE_STRING(WATCHDOG_TIMEOUT) ".");
59 
60 static bool nowayout = WATCHDOG_NOWAYOUT;
61 module_param(nowayout, bool, 0);
62 MODULE_PARM_DESC(nowayout,
63 		"Watchdog cannot be stopped once started (default="
64 				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
65 
66 static int early_disable;
67 module_param(early_disable, int, 0);
68 MODULE_PARM_DESC(early_disable, "Disable watchdog at boot time (default=0)");
69 
70 /*
71  *	Kernel methods.
72  */
73 
74 #define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
75 #define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register
76 							(same as EFER) */
77 #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
78 
79 #define W83627HF_LD_WDT		0x08
80 
81 #define W83627HF_ID		0x52
82 #define W83627S_ID		0x59
83 #define W83697HF_ID		0x60
84 #define W83697UG_ID		0x68
85 #define W83637HF_ID		0x70
86 #define W83627THF_ID		0x82
87 #define W83687THF_ID		0x85
88 #define W83627EHF_ID		0x88
89 #define W83627DHG_ID		0xa0
90 #define W83627UHG_ID		0xa2
91 #define W83667HG_ID		0xa5
92 #define W83627DHG_P_ID		0xb0
93 #define W83667HG_B_ID		0xb3
94 #define NCT6775_ID		0xb4
95 #define NCT6776_ID		0xc3
96 #define NCT6102_ID		0xc4
97 #define NCT6779_ID		0xc5
98 #define NCT6791_ID		0xc8
99 #define NCT6792_ID		0xc9
100 
101 #define W83627HF_WDT_TIMEOUT	0xf6
102 #define W83697HF_WDT_TIMEOUT	0xf4
103 #define NCT6102D_WDT_TIMEOUT	0xf1
104 
105 #define W83627HF_WDT_CONTROL	0xf5
106 #define W83697HF_WDT_CONTROL	0xf3
107 #define NCT6102D_WDT_CONTROL	0xf0
108 
109 #define W836X7HF_WDT_CSR	0xf7
110 #define NCT6102D_WDT_CSR	0xf2
111 
112 static void superio_outb(int reg, int val)
113 {
114 	outb(reg, WDT_EFER);
115 	outb(val, WDT_EFDR);
116 }
117 
118 static inline int superio_inb(int reg)
119 {
120 	outb(reg, WDT_EFER);
121 	return inb(WDT_EFDR);
122 }
123 
124 static int superio_enter(void)
125 {
126 	if (!request_muxed_region(wdt_io, 2, WATCHDOG_NAME))
127 		return -EBUSY;
128 
129 	outb_p(0x87, WDT_EFER); /* Enter extended function mode */
130 	outb_p(0x87, WDT_EFER); /* Again according to manual */
131 
132 	return 0;
133 }
134 
135 static void superio_select(int ld)
136 {
137 	superio_outb(0x07, ld);
138 }
139 
140 static void superio_exit(void)
141 {
142 	outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
143 	release_region(wdt_io, 2);
144 }
145 
146 static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
147 {
148 	int ret;
149 	unsigned char t;
150 
151 	ret = superio_enter();
152 	if (ret)
153 		return ret;
154 
155 	superio_select(W83627HF_LD_WDT);
156 
157 	/* set CR30 bit 0 to activate GPIO2 */
158 	t = superio_inb(0x30);
159 	if (!(t & 0x01))
160 		superio_outb(0x30, t | 0x01);
161 
162 	switch (chip) {
163 	case w83627hf:
164 	case w83627s:
165 		t = superio_inb(0x2B) & ~0x10;
166 		superio_outb(0x2B, t); /* set GPIO24 to WDT0 */
167 		break;
168 	case w83697hf:
169 		/* Set pin 119 to WDTO# mode (= CR29, WDT0) */
170 		t = superio_inb(0x29) & ~0x60;
171 		t |= 0x20;
172 		superio_outb(0x29, t);
173 		break;
174 	case w83697ug:
175 		/* Set pin 118 to WDTO# mode */
176 		t = superio_inb(0x2b) & ~0x04;
177 		superio_outb(0x2b, t);
178 		break;
179 	case w83627thf:
180 		t = (superio_inb(0x2B) & ~0x08) | 0x04;
181 		superio_outb(0x2B, t); /* set GPIO3 to WDT0 */
182 		break;
183 	case w83627dhg:
184 	case w83627dhg_p:
185 		t = superio_inb(0x2D) & ~0x01; /* PIN77 -> WDT0# */
186 		superio_outb(0x2D, t); /* set GPIO5 to WDT0 */
187 		t = superio_inb(cr_wdt_control);
188 		t |= 0x02;	/* enable the WDTO# output low pulse
189 				 * to the KBRST# pin */
190 		superio_outb(cr_wdt_control, t);
191 		break;
192 	case w83637hf:
193 		break;
194 	case w83687thf:
195 		t = superio_inb(0x2C) & ~0x80; /* PIN47 -> WDT0# */
196 		superio_outb(0x2C, t);
197 		break;
198 	case w83627ehf:
199 	case w83627uhg:
200 	case w83667hg:
201 	case w83667hg_b:
202 	case nct6775:
203 	case nct6776:
204 	case nct6779:
205 	case nct6791:
206 	case nct6792:
207 	case nct6102:
208 		/*
209 		 * These chips have a fixed WDTO# output pin (W83627UHG),
210 		 * or support more than one WDTO# output pin.
211 		 * Don't touch its configuration, and hope the BIOS
212 		 * does the right thing.
213 		 */
214 		t = superio_inb(cr_wdt_control);
215 		t |= 0x02;	/* enable the WDTO# output low pulse
216 				 * to the KBRST# pin */
217 		superio_outb(cr_wdt_control, t);
218 		break;
219 	default:
220 		break;
221 	}
222 
223 	t = superio_inb(cr_wdt_timeout);
224 	if (t != 0) {
225 		if (early_disable) {
226 			pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
227 			superio_outb(cr_wdt_timeout, 0);
228 		} else {
229 			pr_info("Watchdog already running. Resetting timeout to %d sec\n",
230 				wdog->timeout);
231 			superio_outb(cr_wdt_timeout, wdog->timeout);
232 		}
233 	}
234 
235 	/* set second mode & disable keyboard turning off watchdog */
236 	t = superio_inb(cr_wdt_control) & ~0x0C;
237 	superio_outb(cr_wdt_control, t);
238 
239 	/* reset trigger, disable keyboard & mouse turning off watchdog */
240 	t = superio_inb(cr_wdt_csr) & ~0xD0;
241 	superio_outb(cr_wdt_csr, t);
242 
243 	superio_exit();
244 
245 	return 0;
246 }
247 
248 static int wdt_set_time(unsigned int timeout)
249 {
250 	int ret;
251 
252 	ret = superio_enter();
253 	if (ret)
254 		return ret;
255 
256 	superio_select(W83627HF_LD_WDT);
257 	superio_outb(cr_wdt_timeout, timeout);
258 	superio_exit();
259 
260 	return 0;
261 }
262 
263 static int wdt_start(struct watchdog_device *wdog)
264 {
265 	return wdt_set_time(wdog->timeout);
266 }
267 
268 static int wdt_stop(struct watchdog_device *wdog)
269 {
270 	return wdt_set_time(0);
271 }
272 
273 static int wdt_set_timeout(struct watchdog_device *wdog, unsigned int timeout)
274 {
275 	wdog->timeout = timeout;
276 
277 	return 0;
278 }
279 
280 static unsigned int wdt_get_time(struct watchdog_device *wdog)
281 {
282 	unsigned int timeleft;
283 	int ret;
284 
285 	ret = superio_enter();
286 	if (ret)
287 		return 0;
288 
289 	superio_select(W83627HF_LD_WDT);
290 	timeleft = superio_inb(cr_wdt_timeout);
291 	superio_exit();
292 
293 	return timeleft;
294 }
295 
296 /*
297  *	Kernel Interfaces
298  */
299 
300 static struct watchdog_info wdt_info = {
301 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
302 	.identity = "W83627HF Watchdog",
303 };
304 
305 static struct watchdog_ops wdt_ops = {
306 	.owner = THIS_MODULE,
307 	.start = wdt_start,
308 	.stop = wdt_stop,
309 	.set_timeout = wdt_set_timeout,
310 	.get_timeleft = wdt_get_time,
311 };
312 
313 static struct watchdog_device wdt_dev = {
314 	.info = &wdt_info,
315 	.ops = &wdt_ops,
316 	.timeout = WATCHDOG_TIMEOUT,
317 	.min_timeout = 1,
318 	.max_timeout = 255,
319 };
320 
321 /*
322  *	The WDT needs to learn about soft shutdowns in order to
323  *	turn the timebomb registers off.
324  */
325 
326 static int wdt_find(int addr)
327 {
328 	u8 val;
329 	int ret;
330 
331 	cr_wdt_timeout = W83627HF_WDT_TIMEOUT;
332 	cr_wdt_control = W83627HF_WDT_CONTROL;
333 	cr_wdt_csr = W836X7HF_WDT_CSR;
334 
335 	ret = superio_enter();
336 	if (ret)
337 		return ret;
338 	superio_select(W83627HF_LD_WDT);
339 	val = superio_inb(0x20);
340 	switch (val) {
341 	case W83627HF_ID:
342 		ret = w83627hf;
343 		break;
344 	case W83627S_ID:
345 		ret = w83627s;
346 		break;
347 	case W83697HF_ID:
348 		ret = w83697hf;
349 		cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
350 		cr_wdt_control = W83697HF_WDT_CONTROL;
351 		break;
352 	case W83697UG_ID:
353 		ret = w83697ug;
354 		cr_wdt_timeout = W83697HF_WDT_TIMEOUT;
355 		cr_wdt_control = W83697HF_WDT_CONTROL;
356 		break;
357 	case W83637HF_ID:
358 		ret = w83637hf;
359 		break;
360 	case W83627THF_ID:
361 		ret = w83627thf;
362 		break;
363 	case W83687THF_ID:
364 		ret = w83687thf;
365 		break;
366 	case W83627EHF_ID:
367 		ret = w83627ehf;
368 		break;
369 	case W83627DHG_ID:
370 		ret = w83627dhg;
371 		break;
372 	case W83627DHG_P_ID:
373 		ret = w83627dhg_p;
374 		break;
375 	case W83627UHG_ID:
376 		ret = w83627uhg;
377 		break;
378 	case W83667HG_ID:
379 		ret = w83667hg;
380 		break;
381 	case W83667HG_B_ID:
382 		ret = w83667hg_b;
383 		break;
384 	case NCT6775_ID:
385 		ret = nct6775;
386 		break;
387 	case NCT6776_ID:
388 		ret = nct6776;
389 		break;
390 	case NCT6779_ID:
391 		ret = nct6779;
392 		break;
393 	case NCT6791_ID:
394 		ret = nct6791;
395 		break;
396 	case NCT6792_ID:
397 		ret = nct6792;
398 		break;
399 	case NCT6102_ID:
400 		ret = nct6102;
401 		cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
402 		cr_wdt_control = NCT6102D_WDT_CONTROL;
403 		cr_wdt_csr = NCT6102D_WDT_CSR;
404 		break;
405 	case 0xff:
406 		ret = -ENODEV;
407 		break;
408 	default:
409 		ret = -ENODEV;
410 		pr_err("Unsupported chip ID: 0x%02x\n", val);
411 		break;
412 	}
413 	superio_exit();
414 	return ret;
415 }
416 
417 static int __init wdt_init(void)
418 {
419 	int ret;
420 	int chip;
421 	const char * const chip_name[] = {
422 		"W83627HF",
423 		"W83627S",
424 		"W83697HF",
425 		"W83697UG",
426 		"W83637HF",
427 		"W83627THF",
428 		"W83687THF",
429 		"W83627EHF",
430 		"W83627DHG",
431 		"W83627UHG",
432 		"W83667HG",
433 		"W83667DHG-P",
434 		"W83667HG-B",
435 		"NCT6775",
436 		"NCT6776",
437 		"NCT6779",
438 		"NCT6791",
439 		"NCT6792",
440 		"NCT6102",
441 	};
442 
443 	wdt_io = 0x2e;
444 	chip = wdt_find(0x2e);
445 	if (chip < 0) {
446 		wdt_io = 0x4e;
447 		chip = wdt_find(0x4e);
448 		if (chip < 0)
449 			return chip;
450 	}
451 
452 	pr_info("WDT driver for %s Super I/O chip initialising\n",
453 		chip_name[chip]);
454 
455 	watchdog_init_timeout(&wdt_dev, timeout, NULL);
456 	watchdog_set_nowayout(&wdt_dev, nowayout);
457 	watchdog_stop_on_reboot(&wdt_dev);
458 
459 	ret = w83627hf_init(&wdt_dev, chip);
460 	if (ret) {
461 		pr_err("failed to initialize watchdog (err=%d)\n", ret);
462 		return ret;
463 	}
464 
465 	ret = watchdog_register_device(&wdt_dev);
466 	if (ret)
467 		return ret;
468 
469 	pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
470 		wdt_dev.timeout, nowayout);
471 
472 	return ret;
473 }
474 
475 static void __exit wdt_exit(void)
476 {
477 	watchdog_unregister_device(&wdt_dev);
478 }
479 
480 module_init(wdt_init);
481 module_exit(wdt_exit);
482 
483 MODULE_LICENSE("GPL");
484 MODULE_AUTHOR("Pádraig  Brady <P@draigBrady.com>");
485 MODULE_DESCRIPTION("w83627hf/thf WDT driver");
486