aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorAndrew Paprocki <andrew@ishiboo.com>2008-02-10 22:11:15 -0500
committerWim Van Sebroeck <wim@iguana.be>2008-03-06 06:10:07 -0500
commit5e69960865ab6033a129f9ee35264adb2a1cfc94 (patch)
tree0fac0e3ffbbe1e9b2e097bf13e9d4ddd10c357c2 /drivers/watchdog
parentd7fe321eeba58f0a37cc4324d10e52092be457e0 (diff)
[WATCHDOG] it8712f_wdt support for 16-bit timeout values, WDIOC_GETSTATUS
This patch adds support for 16-bit watchdog timeout values which are available in chip revisions >= 0x08. Values <= 65535 are seconds precision, otherwise minutes precision is used up to a maximum value of 3932100. Added implementation for WDIOC_GETSTATUS which checks the WDT status bit in the WDT control register. Signed-off-by: Andrew Paprocki <andrew@ishiboo.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/it8712f_wdt.c78
1 files changed, 64 insertions, 14 deletions
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 1b6d7d1b715d..1efcad3b6fca 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -7,7 +7,8 @@
7 * 7 *
8 * drivers/char/watchdog/scx200_wdt.c 8 * drivers/char/watchdog/scx200_wdt.c
9 * drivers/hwmon/it87.c 9 * drivers/hwmon/it87.c
10 * IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf 10 * IT8712F EC-LPC I/O Preliminary Specification 0.8.2
11 * IT8712F EC-LPC I/O Preliminary Specification 0.9.3
11 * 12 *
12 * This program is free software; you can redistribute it and/or 13 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as 14 * modify it under the terms of the GNU General Public License as
@@ -40,6 +41,7 @@ MODULE_DESCRIPTION("IT8712F Watchdog Driver");
40MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
41MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 42MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
42 43
44static int max_units = 255;
43static int margin = 60; /* in seconds */ 45static int margin = 60; /* in seconds */
44module_param(margin, int, 0); 46module_param(margin, int, 0);
45MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); 47MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
@@ -51,6 +53,7 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
51static struct semaphore it8712f_wdt_sem; 53static struct semaphore it8712f_wdt_sem;
52static unsigned expect_close; 54static unsigned expect_close;
53static spinlock_t io_lock; 55static spinlock_t io_lock;
56static unsigned char revision;
54 57
55/* Dog Food address - We use the game port address */ 58/* Dog Food address - We use the game port address */
56static unsigned short address; 59static unsigned short address;
@@ -108,6 +111,15 @@ superio_inw(int reg)
108 return val; 111 return val;
109} 112}
110 113
114static void
115superio_outw(int val, int reg)
116{
117 outb(reg++, REG);
118 outb((val >> 8) & 0xff, VAL);
119 outb(reg, REG);
120 outb(val & 0xff, VAL);
121}
122
111static inline void 123static inline void
112superio_select(int ldn) 124superio_select(int ldn)
113{ 125{
@@ -143,15 +155,33 @@ static void
143it8712f_wdt_update_margin(void) 155it8712f_wdt_update_margin(void)
144{ 156{
145 int config = WDT_OUT_KRST | WDT_OUT_PWROK; 157 int config = WDT_OUT_KRST | WDT_OUT_PWROK;
146 158 int units = margin;
147 printk(KERN_INFO NAME ": timer margin %d seconds\n", margin); 159
148 160 /* Switch to minutes precision if the configured margin
149 /* The timeout register only has 8bits wide */ 161 * value does not fit within the register width.
150 if (margin < 256) 162 */
151 config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */ 163 if (units <= max_units) {
164 config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
165 printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
166 } else {
167 units /= 60;
168 printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
169 }
152 superio_outb(config, WDT_CONFIG); 170 superio_outb(config, WDT_CONFIG);
153 171
154 superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT); 172 if (revision >= 0x08)
173 superio_outw(units, WDT_TIMEOUT);
174 else
175 superio_outb(units, WDT_TIMEOUT);
176}
177
178static int
179it8712f_wdt_get_status(void)
180{
181 if (superio_inb(WDT_CONTROL) & 0x01)
182 return WDIOF_CARDRESET;
183 else
184 return 0;
155} 185}
156 186
157static void 187static void
@@ -234,7 +264,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
234 .firmware_version = 1, 264 .firmware_version = 1,
235 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 265 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
236 }; 266 };
237 int new_margin; 267 int value;
238 268
239 switch (cmd) { 269 switch (cmd) {
240 default: 270 default:
@@ -244,17 +274,27 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
244 return -EFAULT; 274 return -EFAULT;
245 return 0; 275 return 0;
246 case WDIOC_GETSTATUS: 276 case WDIOC_GETSTATUS:
277 superio_enter();
278 superio_select(LDN_GPIO);
279
280 value = it8712f_wdt_get_status();
281
282 superio_exit();
283
284 return put_user(value, p);
247 case WDIOC_GETBOOTSTATUS: 285 case WDIOC_GETBOOTSTATUS:
248 return put_user(0, p); 286 return put_user(0, p);
249 case WDIOC_KEEPALIVE: 287 case WDIOC_KEEPALIVE:
250 it8712f_wdt_ping(); 288 it8712f_wdt_ping();
251 return 0; 289 return 0;
252 case WDIOC_SETTIMEOUT: 290 case WDIOC_SETTIMEOUT:
253 if (get_user(new_margin, p)) 291 if (get_user(value, p))
254 return -EFAULT; 292 return -EFAULT;
255 if (new_margin < 1) 293 if (value < 1)
294 return -EINVAL;
295 if (value > (max_units * 60))
256 return -EINVAL; 296 return -EINVAL;
257 margin = new_margin; 297 margin = value;
258 superio_enter(); 298 superio_enter();
259 superio_select(LDN_GPIO); 299 superio_select(LDN_GPIO);
260 300
@@ -262,6 +302,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
262 302
263 superio_exit(); 303 superio_exit();
264 it8712f_wdt_ping(); 304 it8712f_wdt_ping();
305 /* Fall through */
265 case WDIOC_GETTIMEOUT: 306 case WDIOC_GETTIMEOUT:
266 if (put_user(margin, p)) 307 if (put_user(margin, p))
267 return -EFAULT; 308 return -EFAULT;
@@ -336,9 +377,18 @@ it8712f_wdt_find(unsigned short *address)
336 } 377 }
337 378
338 err = 0; 379 err = 0;
339 printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - " 380 revision = superio_inb(DEVREV) & 0x0f;
381
382 /* Later revisions have 16-bit values per datasheet 0.9.1 */
383 if (revision >= 0x08)
384 max_units = 65535;
385
386 if (margin > (max_units * 60))
387 margin = (max_units * 60);
388
389 printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
340 "using DogFood address 0x%x\n", 390 "using DogFood address 0x%x\n",
341 chip_type, superio_inb(DEVREV) & 0x0f, *address); 391 chip_type, revision, *address);
342 392
343exit: 393exit:
344 superio_exit(); 394 superio_exit();