Blame view

drivers/watchdog/it8712f_wdt.c 9.96 KB
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
1
2
3
4
5
6
7
8
9
  /*
   *	IT8712F "Smart Guardian" Watchdog support
   *
   *	Copyright (c) 2006-2007 Jorge Boncompte - DTI2 <jorge@dti2.net>
   *
   *	Based on info and code taken from:
   *
   *	drivers/char/watchdog/scx200_wdt.c
   *	drivers/hwmon/it87.c
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
10
11
   *	IT8712F EC-LPC I/O Preliminary Specification 0.8.2
   *	IT8712F EC-LPC I/O Preliminary Specification 0.9.3
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
12
13
14
15
16
17
18
19
20
21
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License as
   *	published by the Free Software Foundation; either version 2 of the
   *	License, or (at your option) any later version.
   *
   *	The author(s) of this software shall not be held liable for damages
   *	of any nature resulting due to the use of this software. This
   *	software is provided AS-IS with no warranties.
   */
27c766aaa   Joe Perches   watchdog: Use pr_...
22
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
23
24
25
26
27
28
29
30
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/init.h>
  #include <linux/miscdevice.h>
  #include <linux/watchdog.h>
  #include <linux/notifier.h>
  #include <linux/reboot.h>
  #include <linux/fs.h>
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
31
  #include <linux/spinlock.h>
d6547378d   Alan Cox   it8712f_wdt: Lock...
32
33
  #include <linux/uaccess.h>
  #include <linux/io.h>
226028688   Wim Van Sebroeck   watchdog: it8712f...
34
  #include <linux/ioport.h>
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
35

27c766aaa   Joe Perches   watchdog: Use pr_...
36
  #define DEBUG
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
37
38
39
40
41
  #define NAME "it8712f_wdt"
  
  MODULE_AUTHOR("Jorge Boncompte - DTI2 <jorge@dti2.net>");
  MODULE_DESCRIPTION("IT8712F Watchdog Driver");
  MODULE_LICENSE("GPL");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
42

5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
43
  static int max_units = 255;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
44
45
46
  static int margin = 60;		/* in seconds */
  module_param(margin, int, 0);
  MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
86a1e1896   Wim Van Sebroeck   watchdog: nowayou...
47
48
  static bool nowayout = WATCHDOG_NOWAYOUT;
  module_param(nowayout, bool, 0);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
49
  MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
d6547378d   Alan Cox   it8712f_wdt: Lock...
50
  static unsigned long wdt_open;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
51
  static unsigned expect_close;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
52
  static unsigned char revision;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  
  /* Dog Food address - We use the game port address */
  static unsigned short address;
  
  #define	REG		0x2e	/* The register to read/write */
  #define	VAL		0x2f	/* The value to read/write */
  
  #define	LDN		0x07	/* Register: Logical device select */
  #define	DEVID		0x20	/* Register: Device ID */
  #define	DEVREV		0x22	/* Register: Device Revision */
  #define ACT_REG		0x30	/* LDN Register: Activation */
  #define BASE_REG	0x60	/* LDN Register: Base address */
  
  #define IT8712F_DEVID	0x8712
  
  #define LDN_GPIO	0x07	/* GPIO and Watch Dog Timer */
5f3b27569   Wim Van Sebroeck   watchdog: cleanup...
69
  #define LDN_GAME	0x09	/* Game Port */
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
70
71
72
73
  
  #define WDT_CONTROL	0x71	/* WDT Register: Control */
  #define WDT_CONFIG	0x72	/* WDT Register: Configuration */
  #define WDT_TIMEOUT	0x73	/* WDT Register: Timeout Value */
f0fc10745   Timo Juhani Lindfors   watchdog: it8712f...
74
75
76
77
  #define WDT_RESET_GAME	0x10	/* Reset timer on read or write to game port */
  #define WDT_RESET_KBD	0x20	/* Reset timer on keyboard interrupt */
  #define WDT_RESET_MOUSE	0x40	/* Reset timer on mouse interrupt */
  #define WDT_RESET_CIR	0x80	/* Reset timer on consumer IR interrupt */
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
78
79
  
  #define WDT_UNIT_SEC	0x80	/* If 0 in MINUTES */
f0fc10745   Timo Juhani Lindfors   watchdog: it8712f...
80
81
  #define WDT_OUT_PWROK	0x10	/* Pulse PWROK on timeout */
  #define WDT_OUT_KRST	0x40	/* Pulse reset on timeout */
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
82

a422088db   Timo Juhani Lindfors   watchdog: it8712f...
83
84
85
86
87
88
89
  static int wdt_control_reg = WDT_RESET_GAME;
  module_param(wdt_control_reg, int, 0);
  MODULE_PARM_DESC(wdt_control_reg, "Value to write to watchdog control "
  		"register. The default WDT_RESET_GAME resets the timer on "
  		"game port reads that this driver generates. You can also "
  		"use KBD, MOUSE or CIR if you have some external way to "
  		"generate those interrupts.");
d6547378d   Alan Cox   it8712f_wdt: Lock...
90
  static int superio_inb(int reg)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
91
92
93
94
  {
  	outb(reg, REG);
  	return inb(VAL);
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
95
  static void superio_outb(int val, int reg)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
96
97
98
99
  {
  	outb(reg, REG);
  	outb(val, VAL);
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
100
  static int superio_inw(int reg)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
101
102
103
104
105
106
107
108
  {
  	int val;
  	outb(reg++, REG);
  	val = inb(VAL) << 8;
  	outb(reg, REG);
  	val |= inb(VAL);
  	return val;
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
109
  static inline void superio_select(int ldn)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
110
111
112
113
  {
  	outb(LDN, REG);
  	outb(ldn, VAL);
  }
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
114
  static inline int superio_enter(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
115
  {
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
116
117
118
119
120
  	/*
  	 * Try to reserve REG and REG + 1 for exclusive access.
  	 */
  	if (!request_muxed_region(REG, 2, NAME))
  		return -EBUSY;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
121
122
123
124
  	outb(0x87, REG);
  	outb(0x01, REG);
  	outb(0x55, REG);
  	outb(0x55, REG);
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
125
  	return 0;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
126
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
127
  static inline void superio_exit(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
128
129
130
  {
  	outb(0x02, REG);
  	outb(0x02, VAL);
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
131
  	release_region(REG, 2);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
132
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
133
  static inline void it8712f_wdt_ping(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
134
  {
a422088db   Timo Juhani Lindfors   watchdog: it8712f...
135
136
  	if (wdt_control_reg & WDT_RESET_GAME)
  		inb(address);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
137
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
138
  static void it8712f_wdt_update_margin(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
139
140
  {
  	int config = WDT_OUT_KRST | WDT_OUT_PWROK;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
141
142
143
144
145
146
147
  	int units = margin;
  
  	/* Switch to minutes precision if the configured margin
  	 * value does not fit within the register width.
  	 */
  	if (units <= max_units) {
  		config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
27c766aaa   Joe Perches   watchdog: Use pr_...
148
149
  		pr_info("timer margin %d seconds
  ", units);
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
150
151
  	} else {
  		units /= 60;
27c766aaa   Joe Perches   watchdog: Use pr_...
152
153
  		pr_info("timer margin %d minutes
  ", units);
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
154
  	}
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
155
  	superio_outb(config, WDT_CONFIG);
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
156
  	if (revision >= 0x08)
0e45adb8f   Oliver Schuster   [WATCHDOG] Fix it...
157
158
  		superio_outb(units >> 8, WDT_TIMEOUT + 1);
  	superio_outb(units, WDT_TIMEOUT);
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
159
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
160
  static int it8712f_wdt_get_status(void)
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
161
162
163
164
165
  {
  	if (superio_inb(WDT_CONTROL) & 0x01)
  		return WDIOF_CARDRESET;
  	else
  		return 0;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
166
  }
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
167
  static int it8712f_wdt_enable(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
168
  {
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
169
170
171
  	int ret = superio_enter();
  	if (ret)
  		return ret;
27c766aaa   Joe Perches   watchdog: Use pr_...
172
173
  	pr_debug("enabling watchdog timer
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
174
  	superio_select(LDN_GPIO);
a422088db   Timo Juhani Lindfors   watchdog: it8712f...
175
  	superio_outb(wdt_control_reg, WDT_CONTROL);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
176
177
178
179
180
181
  
  	it8712f_wdt_update_margin();
  
  	superio_exit();
  
  	it8712f_wdt_ping();
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
182
183
  
  	return 0;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
184
  }
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
185
  static int it8712f_wdt_disable(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
186
  {
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
187
188
189
  	int ret = superio_enter();
  	if (ret)
  		return ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
190

27c766aaa   Joe Perches   watchdog: Use pr_...
191
192
  	pr_debug("disabling watchdog timer
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
193
194
195
196
  	superio_select(LDN_GPIO);
  
  	superio_outb(0, WDT_CONFIG);
  	superio_outb(0, WDT_CONTROL);
cc1020f15   Andrew Paprocki   [WATCHDOG] it8712...
197
198
  	if (revision >= 0x08)
  		superio_outb(0, WDT_TIMEOUT + 1);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
199
200
201
  	superio_outb(0, WDT_TIMEOUT);
  
  	superio_exit();
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
202
  	return 0;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
203
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
204
  static int it8712f_wdt_notify(struct notifier_block *this,
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
205
206
207
208
209
210
211
212
213
214
215
216
  		    unsigned long code, void *unused)
  {
  	if (code == SYS_HALT || code == SYS_POWER_OFF)
  		if (!nowayout)
  			it8712f_wdt_disable();
  
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block it8712f_wdt_notifier = {
  	.notifier_call = it8712f_wdt_notify,
  };
d6547378d   Alan Cox   it8712f_wdt: Lock...
217
218
  static ssize_t it8712f_wdt_write(struct file *file, const char __user *data,
  					size_t len, loff_t *ppos)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
219
220
221
222
223
224
225
226
227
228
  {
  	/* check for a magic close character */
  	if (len) {
  		size_t i;
  
  		it8712f_wdt_ping();
  
  		expect_close = 0;
  		for (i = 0; i < len; ++i) {
  			char c;
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
229
  			if (get_user(c, data + i))
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
230
231
232
233
234
235
236
237
  				return -EFAULT;
  			if (c == 'V')
  				expect_close = 42;
  		}
  	}
  
  	return len;
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
238
239
  static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
  							unsigned long arg)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
240
241
242
  {
  	void __user *argp = (void __user *)arg;
  	int __user *p = argp;
42747d712   Wim Van Sebroeck   [WATCHDOG] watchd...
243
  	static const struct watchdog_info ident = {
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
244
245
  		.identity = "IT8712F Watchdog",
  		.firmware_version = 1,
e73a78027   Wim Van Sebroeck   [WATCHDOG] Correc...
246
247
  		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
  						WDIOF_MAGICCLOSE,
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
248
  	};
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
249
  	int value;
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
250
  	int ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
251
252
  
  	switch (cmd) {
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
253
254
255
256
257
  	case WDIOC_GETSUPPORT:
  		if (copy_to_user(argp, &ident, sizeof(ident)))
  			return -EFAULT;
  		return 0;
  	case WDIOC_GETSTATUS:
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
258
259
260
  		ret = superio_enter();
  		if (ret)
  			return ret;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
261
262
263
264
265
266
267
  		superio_select(LDN_GPIO);
  
  		value = it8712f_wdt_get_status();
  
  		superio_exit();
  
  		return put_user(value, p);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
268
269
270
271
272
273
  	case WDIOC_GETBOOTSTATUS:
  		return put_user(0, p);
  	case WDIOC_KEEPALIVE:
  		it8712f_wdt_ping();
  		return 0;
  	case WDIOC_SETTIMEOUT:
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
274
  		if (get_user(value, p))
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
275
  			return -EFAULT;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
276
277
278
  		if (value < 1)
  			return -EINVAL;
  		if (value > (max_units * 60))
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
279
  			return -EINVAL;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
280
  		margin = value;
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
281
282
283
  		ret = superio_enter();
  		if (ret)
  			return ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
284
285
286
287
288
289
  		superio_select(LDN_GPIO);
  
  		it8712f_wdt_update_margin();
  
  		superio_exit();
  		it8712f_wdt_ping();
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
290
  		/* Fall through */
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
291
292
293
294
  	case WDIOC_GETTIMEOUT:
  		if (put_user(margin, p))
  			return -EFAULT;
  		return 0;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
295
296
  	default:
  		return -ENOTTY;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
297
298
  	}
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
299
  static int it8712f_wdt_open(struct inode *inode, struct file *file)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
300
  {
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
301
  	int ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
302
  	/* only allow one at a time */
d6547378d   Alan Cox   it8712f_wdt: Lock...
303
  	if (test_and_set_bit(0, &wdt_open))
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
304
  		return -EBUSY;
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
305
306
307
308
  
  	ret = it8712f_wdt_enable();
  	if (ret)
  		return ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
309
310
  	return nonseekable_open(inode, file);
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
311
  static int it8712f_wdt_release(struct inode *inode, struct file *file)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
312
313
  {
  	if (expect_close != 42) {
27c766aaa   Joe Perches   watchdog: Use pr_...
314
315
  		pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
316
  	} else if (!nowayout) {
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
317
  		if (it8712f_wdt_disable())
27c766aaa   Joe Perches   watchdog: Use pr_...
318
319
  			pr_warn("Watchdog disable failed
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
320
321
  	}
  	expect_close = 0;
d6547378d   Alan Cox   it8712f_wdt: Lock...
322
  	clear_bit(0, &wdt_open);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
323
324
325
  
  	return 0;
  }
b47a166ed   Jan Engelhardt   [WATCHDOG] consti...
326
  static const struct file_operations it8712f_wdt_fops = {
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
327
328
329
  	.owner = THIS_MODULE,
  	.llseek = no_llseek,
  	.write = it8712f_wdt_write,
d6547378d   Alan Cox   it8712f_wdt: Lock...
330
  	.unlocked_ioctl = it8712f_wdt_ioctl,
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
331
332
333
334
335
336
337
338
339
  	.open = it8712f_wdt_open,
  	.release = it8712f_wdt_release,
  };
  
  static struct miscdevice it8712f_wdt_miscdev = {
  	.minor = WATCHDOG_MINOR,
  	.name = "watchdog",
  	.fops = &it8712f_wdt_fops,
  };
d6547378d   Alan Cox   it8712f_wdt: Lock...
340
  static int __init it8712f_wdt_find(unsigned short *address)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
341
342
343
  {
  	int err = -ENODEV;
  	int chip_type;
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
344
345
346
  	int ret = superio_enter();
  	if (ret)
  		return ret;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
347

38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
348
349
350
351
352
353
354
  	chip_type = superio_inw(DEVID);
  	if (chip_type != IT8712F_DEVID)
  		goto exit;
  
  	superio_select(LDN_GAME);
  	superio_outb(1, ACT_REG);
  	if (!(superio_inb(ACT_REG) & 0x01)) {
27c766aaa   Joe Perches   watchdog: Use pr_...
355
356
  		pr_err("Device not activated, skipping
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
357
358
359
360
361
  		goto exit;
  	}
  
  	*address = superio_inw(BASE_REG);
  	if (*address == 0) {
27c766aaa   Joe Perches   watchdog: Use pr_...
362
363
  		pr_err("Base address not set, skipping
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
364
365
366
367
  		goto exit;
  	}
  
  	err = 0;
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
368
369
370
371
372
373
374
375
  	revision = superio_inb(DEVREV) & 0x0f;
  
  	/* Later revisions have 16-bit values per datasheet 0.9.1 */
  	if (revision >= 0x08)
  		max_units = 65535;
  
  	if (margin > (max_units * 60))
  		margin = (max_units * 60);
27c766aaa   Joe Perches   watchdog: Use pr_...
376
377
  	pr_info("Found IT%04xF chip revision %d - using DogFood address 0x%x
  ",
5e6996086   Andrew Paprocki   [WATCHDOG] it8712...
378
  		chip_type, revision, *address);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
379
380
381
382
383
  
  exit:
  	superio_exit();
  	return err;
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
384
  static int __init it8712f_wdt_init(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
385
386
  {
  	int err = 0;
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
387
388
389
390
  	if (it8712f_wdt_find(&address))
  		return -ENODEV;
  
  	if (!request_region(address, 1, "IT8712F Watchdog")) {
27c766aaa   Joe Perches   watchdog: Use pr_...
391
392
  		pr_warn("watchdog I/O region busy
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
393
394
  		return -EBUSY;
  	}
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
395
396
  	err = it8712f_wdt_disable();
  	if (err) {
27c766aaa   Joe Perches   watchdog: Use pr_...
397
398
  		pr_err("unable to disable watchdog timer
  ");
a134b8256   Nat Gurumoorthy   watchdog: Use "re...
399
400
  		goto out;
  	}
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
401

38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
402
403
  	err = register_reboot_notifier(&it8712f_wdt_notifier);
  	if (err) {
27c766aaa   Joe Perches   watchdog: Use pr_...
404
405
  		pr_err("unable to register reboot notifier
  ");
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
406
407
408
409
410
  		goto out;
  	}
  
  	err = misc_register(&it8712f_wdt_miscdev);
  	if (err) {
27c766aaa   Joe Perches   watchdog: Use pr_...
411
412
413
  		pr_err("cannot register miscdev on minor=%d (err=%d)
  ",
  		       WATCHDOG_MINOR, err);
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
414
415
416
417
418
419
420
421
422
423
424
425
  		goto reboot_out;
  	}
  
  	return 0;
  
  
  reboot_out:
  	unregister_reboot_notifier(&it8712f_wdt_notifier);
  out:
  	release_region(address, 1);
  	return err;
  }
d6547378d   Alan Cox   it8712f_wdt: Lock...
426
  static void __exit it8712f_wdt_exit(void)
38ff6fd2f   Jorge Boncompte [DTI2]   [WATCHDOG] IT8212...
427
428
429
430
431
432
433
434
  {
  	misc_deregister(&it8712f_wdt_miscdev);
  	unregister_reboot_notifier(&it8712f_wdt_notifier);
  	release_region(address, 1);
  }
  
  module_init(it8712f_wdt_init);
  module_exit(it8712f_wdt_exit);