Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
it87_wdt.c
Go to the documentation of this file.
1 /*
2  * Watchdog Timer Driver
3  * for ITE IT87xx Environment Control - Low Pin Count Input / Output
4  *
5  * (c) Copyright 2007 Oliver Schuster <[email protected]>
6  *
7  * Based on softdog.c by Alan Cox,
8  * 83977f_wdt.c by Jose Goncalves,
9  * it87.c by Chris Gauthron, Jean Delvare
10  *
11  * Data-sheets: Publicly available at the ITE website
12  * http://www.ite.com.tw/
13  *
14  * Support of the watchdog timers, which are available on
15  * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726
16  * and IT8728.
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version
21  * 2 of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32 
33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34 
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/types.h>
38 #include <linux/kernel.h>
39 #include <linux/fs.h>
40 #include <linux/miscdevice.h>
41 #include <linux/init.h>
42 #include <linux/ioport.h>
43 #include <linux/watchdog.h>
44 #include <linux/notifier.h>
45 #include <linux/reboot.h>
46 #include <linux/uaccess.h>
47 #include <linux/io.h>
48 
49 
50 #define WATCHDOG_VERSION "1.14"
51 #define WATCHDOG_NAME "IT87 WDT"
52 #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
53 #define WD_MAGIC 'V'
54 
55 /* Defaults for Module Parameter */
56 #define DEFAULT_NOGAMEPORT 0
57 #define DEFAULT_EXCLUSIVE 1
58 #define DEFAULT_TIMEOUT 60
59 #define DEFAULT_TESTMODE 0
60 #define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT
61 
62 /* IO Ports */
63 #define REG 0x2e
64 #define VAL 0x2f
65 
66 /* Logical device Numbers LDN */
67 #define GPIO 0x07
68 #define GAMEPORT 0x09
69 #define CIR 0x0a
70 
71 /* Configuration Registers and Functions */
72 #define LDNREG 0x07
73 #define CHIPID 0x20
74 #define CHIPREV 0x22
75 #define ACTREG 0x30
76 #define BASEREG 0x60
77 
78 /* Chip Id numbers */
79 #define NO_DEV_ID 0xffff
80 #define IT8702_ID 0x8702
81 #define IT8705_ID 0x8705
82 #define IT8712_ID 0x8712
83 #define IT8716_ID 0x8716
84 #define IT8718_ID 0x8718
85 #define IT8720_ID 0x8720
86 #define IT8721_ID 0x8721
87 #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
88 #define IT8728_ID 0x8728
89 
90 /* GPIO Configuration Registers LDN=0x07 */
91 #define WDTCTRL 0x71
92 #define WDTCFG 0x72
93 #define WDTVALLSB 0x73
94 #define WDTVALMSB 0x74
95 
96 /* GPIO Bits WDTCTRL */
97 #define WDT_CIRINT 0x80
98 #define WDT_MOUSEINT 0x40
99 #define WDT_KYBINT 0x20
100 #define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721, it8728 */
101 #define WDT_FORCE 0x02
102 #define WDT_ZERO 0x01
103 
104 /* GPIO Bits WDTCFG */
105 #define WDT_TOV1 0x80
106 #define WDT_KRST 0x40
107 #define WDT_TOVE 0x20
108 #define WDT_PWROK 0x10 /* not in it8721 */
109 #define WDT_INT_MASK 0x0f
110 
111 /* CIR Configuration Register LDN=0x0a */
112 #define CIR_ILS 0x70
113 
114 /* The default Base address is not always available, we use this */
115 #define CIR_BASE 0x0208
116 
117 /* CIR Controller */
118 #define CIR_DR(b) (b)
119 #define CIR_IER(b) (b + 1)
120 #define CIR_RCR(b) (b + 2)
121 #define CIR_TCR1(b) (b + 3)
122 #define CIR_TCR2(b) (b + 4)
123 #define CIR_TSR(b) (b + 5)
124 #define CIR_RSR(b) (b + 6)
125 #define CIR_BDLR(b) (b + 5)
126 #define CIR_BDHR(b) (b + 6)
127 #define CIR_IIR(b) (b + 7)
128 
129 /* Default Base address of Game port */
130 #define GP_BASE_DEFAULT 0x0201
131 
132 /* wdt_status */
133 #define WDTS_TIMER_RUN 0
134 #define WDTS_DEV_OPEN 1
135 #define WDTS_KEEPALIVE 2
136 #define WDTS_LOCKED 3
137 #define WDTS_USE_GP 4
138 #define WDTS_EXPECTED 5
139 
140 static unsigned int base, gpact, ciract, max_units, chip_type;
141 static unsigned long wdt_status;
142 
143 static int nogameport = DEFAULT_NOGAMEPORT;
144 static int exclusive = DEFAULT_EXCLUSIVE;
145 static int timeout = DEFAULT_TIMEOUT;
146 static int testmode = DEFAULT_TESTMODE;
147 static bool nowayout = DEFAULT_NOWAYOUT;
148 
149 module_param(nogameport, int, 0);
150 MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
152 module_param(exclusive, int, 0);
153 MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default="
155 module_param(timeout, int, 0);
156 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
158 module_param(testmode, int, 0);
159 MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
161 module_param(nowayout, bool, 0);
162 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
164 
165 /* Superio Chip */
166 
167 static inline int superio_enter(void)
168 {
169  /*
170  * Try to reserve REG and REG + 1 for exclusive access.
171  */
173  return -EBUSY;
174 
175  outb(0x87, REG);
176  outb(0x01, REG);
177  outb(0x55, REG);
178  outb(0x55, REG);
179  return 0;
180 }
181 
182 static inline void superio_exit(void)
183 {
184  outb(0x02, REG);
185  outb(0x02, VAL);
186  release_region(REG, 2);
187 }
188 
189 static inline void superio_select(int ldn)
190 {
191  outb(LDNREG, REG);
192  outb(ldn, VAL);
193 }
194 
195 static inline int superio_inb(int reg)
196 {
197  outb(reg, REG);
198  return inb(VAL);
199 }
200 
201 static inline void superio_outb(int val, int reg)
202 {
203  outb(reg, REG);
204  outb(val, VAL);
205 }
206 
207 static inline int superio_inw(int reg)
208 {
209  int val;
210  outb(reg++, REG);
211  val = inb(VAL) << 8;
212  outb(reg, REG);
213  val |= inb(VAL);
214  return val;
215 }
216 
217 static inline void superio_outw(int val, int reg)
218 {
219  outb(reg++, REG);
220  outb(val >> 8, VAL);
221  outb(reg, REG);
222  outb(val, VAL);
223 }
224 
225 /* Internal function, should be called after superio_select(GPIO) */
226 static void wdt_update_timeout(void)
227 {
228  unsigned char cfg = WDT_KRST;
229  int tm = timeout;
230 
231  if (testmode)
232  cfg = 0;
233 
234  if (tm <= max_units)
235  cfg |= WDT_TOV1;
236  else
237  tm /= 60;
238 
239  if (chip_type != IT8721_ID)
240  cfg |= WDT_PWROK;
241 
242  superio_outb(cfg, WDTCFG);
243  superio_outb(tm, WDTVALLSB);
244  if (max_units > 255)
245  superio_outb(tm>>8, WDTVALMSB);
246 }
247 
248 static int wdt_round_time(int t)
249 {
250  t += 59;
251  t -= t % 60;
252  return t;
253 }
254 
255 /* watchdog timer handling */
256 
257 static void wdt_keepalive(void)
258 {
259  if (test_bit(WDTS_USE_GP, &wdt_status))
260  inb(base);
261  else
262  /* The timer reloads with around 5 msec delay */
263  outb(0x55, CIR_DR(base));
264  set_bit(WDTS_KEEPALIVE, &wdt_status);
265 }
266 
267 static int wdt_start(void)
268 {
269  int ret = superio_enter();
270  if (ret)
271  return ret;
272 
274  if (test_bit(WDTS_USE_GP, &wdt_status))
275  superio_outb(WDT_GAMEPORT, WDTCTRL);
276  else
277  superio_outb(WDT_CIRINT, WDTCTRL);
278  wdt_update_timeout();
279 
280  superio_exit();
281 
282  return 0;
283 }
284 
285 static int wdt_stop(void)
286 {
287  int ret = superio_enter();
288  if (ret)
289  return ret;
290 
292  superio_outb(0x00, WDTCTRL);
293  superio_outb(WDT_TOV1, WDTCFG);
294  superio_outb(0x00, WDTVALLSB);
295  if (max_units > 255)
296  superio_outb(0x00, WDTVALMSB);
297 
298  superio_exit();
299  return 0;
300 }
301 
312 static int wdt_set_timeout(int t)
313 {
314  if (t < 1 || t > max_units * 60)
315  return -EINVAL;
316 
317  if (t > max_units)
318  timeout = wdt_round_time(t);
319  else
320  timeout = t;
321 
322  if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
323  int ret = superio_enter();
324  if (ret)
325  return ret;
326 
328  wdt_update_timeout();
329  superio_exit();
330  }
331  return 0;
332 }
333 
347 static int wdt_get_status(int *status)
348 {
349  *status = 0;
350  if (testmode) {
351  int ret = superio_enter();
352  if (ret)
353  return ret;
354 
356  if (superio_inb(WDTCTRL) & WDT_ZERO) {
357  superio_outb(0x00, WDTCTRL);
358  clear_bit(WDTS_TIMER_RUN, &wdt_status);
359  *status |= WDIOF_CARDRESET;
360  }
361 
362  superio_exit();
363  }
364  if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status))
365  *status |= WDIOF_KEEPALIVEPING;
366  if (test_bit(WDTS_EXPECTED, &wdt_status))
367  *status |= WDIOF_MAGICCLOSE;
368  return 0;
369 }
370 
371 /* /dev/watchdog handling */
372 
383 static int wdt_open(struct inode *inode, struct file *file)
384 {
385  if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status))
386  return -EBUSY;
387  if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
388  int ret;
389  if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status))
390  __module_get(THIS_MODULE);
391 
392  ret = wdt_start();
393  if (ret) {
394  clear_bit(WDTS_LOCKED, &wdt_status);
395  clear_bit(WDTS_TIMER_RUN, &wdt_status);
396  clear_bit(WDTS_DEV_OPEN, &wdt_status);
397  return ret;
398  }
399  }
400  return nonseekable_open(inode, file);
401 }
402 
416 static int wdt_release(struct inode *inode, struct file *file)
417 {
418  if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
419  if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) {
420  int ret = wdt_stop();
421  if (ret) {
422  /*
423  * Stop failed. Just keep the watchdog alive
424  * and hope nothing bad happens.
425  */
426  set_bit(WDTS_EXPECTED, &wdt_status);
427  wdt_keepalive();
428  return ret;
429  }
430  clear_bit(WDTS_TIMER_RUN, &wdt_status);
431  } else {
432  wdt_keepalive();
433  pr_crit("unexpected close, not stopping watchdog!\n");
434  }
435  }
436  clear_bit(WDTS_DEV_OPEN, &wdt_status);
437  return 0;
438 }
439 
453 static ssize_t wdt_write(struct file *file, const char __user *buf,
454  size_t count, loff_t *ppos)
455 {
456  if (count) {
457  clear_bit(WDTS_EXPECTED, &wdt_status);
458  wdt_keepalive();
459  }
460  if (!nowayout) {
461  size_t ofs;
462 
463  /* note: just in case someone wrote the magic character long ago */
464  for (ofs = 0; ofs != count; ofs++) {
465  char c;
466  if (get_user(c, buf + ofs))
467  return -EFAULT;
468  if (c == WD_MAGIC)
469  set_bit(WDTS_EXPECTED, &wdt_status);
470  }
471  }
472  return count;
473 }
474 
475 static const struct watchdog_info ident = {
477  .firmware_version = 1,
478  .identity = WATCHDOG_NAME,
479 };
480 
493 static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
494 {
495  int rc = 0, status, new_options, new_timeout;
496  union {
497  struct watchdog_info __user *ident;
498  int __user *i;
499  } uarg;
500 
501  uarg.i = (int __user *)arg;
502 
503  switch (cmd) {
504  case WDIOC_GETSUPPORT:
505  return copy_to_user(uarg.ident,
506  &ident, sizeof(ident)) ? -EFAULT : 0;
507 
508  case WDIOC_GETSTATUS:
509  rc = wdt_get_status(&status);
510  if (rc)
511  return rc;
512  return put_user(status, uarg.i);
513 
514  case WDIOC_GETBOOTSTATUS:
515  return put_user(0, uarg.i);
516 
517  case WDIOC_KEEPALIVE:
518  wdt_keepalive();
519  return 0;
520 
521  case WDIOC_SETOPTIONS:
522  if (get_user(new_options, uarg.i))
523  return -EFAULT;
524 
525  switch (new_options) {
526  case WDIOS_DISABLECARD:
527  if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
528  rc = wdt_stop();
529  if (rc)
530  return rc;
531  }
532  clear_bit(WDTS_TIMER_RUN, &wdt_status);
533  return 0;
534 
535  case WDIOS_ENABLECARD:
536  if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
537  rc = wdt_start();
538  if (rc) {
539  clear_bit(WDTS_TIMER_RUN, &wdt_status);
540  return rc;
541  }
542  }
543  return 0;
544 
545  default:
546  return -EFAULT;
547  }
548 
549  case WDIOC_SETTIMEOUT:
550  if (get_user(new_timeout, uarg.i))
551  return -EFAULT;
552  rc = wdt_set_timeout(new_timeout);
553  case WDIOC_GETTIMEOUT:
554  if (put_user(timeout, uarg.i))
555  return -EFAULT;
556  return rc;
557 
558  default:
559  return -ENOTTY;
560  }
561 }
562 
563 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
564  void *unused)
565 {
566  if (code == SYS_DOWN || code == SYS_HALT)
567  wdt_stop();
568  return NOTIFY_DONE;
569 }
570 
571 static const struct file_operations wdt_fops = {
572  .owner = THIS_MODULE,
573  .llseek = no_llseek,
574  .write = wdt_write,
575  .unlocked_ioctl = wdt_ioctl,
576  .open = wdt_open,
577  .release = wdt_release,
578 };
579 
580 static struct miscdevice wdt_miscdev = {
581  .minor = WATCHDOG_MINOR,
582  .name = "watchdog",
583  .fops = &wdt_fops,
584 };
585 
586 static struct notifier_block wdt_notifier = {
587  .notifier_call = wdt_notify_sys,
588 };
589 
590 static int __init it87_wdt_init(void)
591 {
592  int rc = 0;
593  int try_gameport = !nogameport;
594  u8 chip_rev;
595  int gp_rreq_fail = 0;
596 
597  wdt_status = 0;
598 
599  rc = superio_enter();
600  if (rc)
601  return rc;
602 
603  chip_type = superio_inw(CHIPID);
604  chip_rev = superio_inb(CHIPREV) & 0x0f;
605  superio_exit();
606 
607  switch (chip_type) {
608  case IT8702_ID:
609  max_units = 255;
610  break;
611  case IT8712_ID:
612  max_units = (chip_rev < 8) ? 255 : 65535;
613  break;
614  case IT8716_ID:
615  case IT8726_ID:
616  max_units = 65535;
617  break;
618  case IT8718_ID:
619  case IT8720_ID:
620  case IT8721_ID:
621  case IT8728_ID:
622  max_units = 65535;
623  try_gameport = 0;
624  break;
625  case IT8705_ID:
626  pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
627  chip_type, chip_rev);
628  return -ENODEV;
629  case NO_DEV_ID:
630  pr_err("no device\n");
631  return -ENODEV;
632  default:
633  pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
634  chip_type, chip_rev);
635  return -ENODEV;
636  }
637 
638  rc = superio_enter();
639  if (rc)
640  return rc;
641 
643  superio_outb(WDT_TOV1, WDTCFG);
644  superio_outb(0x00, WDTCTRL);
645 
646  /* First try to get Gameport support */
647  if (try_gameport) {
649  base = superio_inw(BASEREG);
650  if (!base) {
652  superio_outw(base, BASEREG);
653  }
654  gpact = superio_inb(ACTREG);
655  superio_outb(0x01, ACTREG);
656  if (request_region(base, 1, WATCHDOG_NAME))
657  set_bit(WDTS_USE_GP, &wdt_status);
658  else
659  gp_rreq_fail = 1;
660  }
661 
662  /* If we haven't Gameport support, try to get CIR support */
663  if (!test_bit(WDTS_USE_GP, &wdt_status)) {
665  if (gp_rreq_fail)
666  pr_err("I/O Address 0x%04x and 0x%04x already in use\n",
667  base, CIR_BASE);
668  else
669  pr_err("I/O Address 0x%04x already in use\n",
670  CIR_BASE);
671  rc = -EIO;
672  goto err_out;
673  }
674  base = CIR_BASE;
675 
677  superio_outw(base, BASEREG);
678  superio_outb(0x00, CIR_ILS);
679  ciract = superio_inb(ACTREG);
680  superio_outb(0x01, ACTREG);
681  if (gp_rreq_fail) {
683  superio_outb(gpact, ACTREG);
684  }
685  }
686 
687  if (timeout < 1 || timeout > max_units * 60) {
689  pr_warn("Timeout value out of range, use default %d sec\n",
691  }
692 
693  if (timeout > max_units)
694  timeout = wdt_round_time(timeout);
695 
696  rc = register_reboot_notifier(&wdt_notifier);
697  if (rc) {
698  pr_err("Cannot register reboot notifier (err=%d)\n", rc);
699  goto err_out_region;
700  }
701 
702  rc = misc_register(&wdt_miscdev);
703  if (rc) {
704  pr_err("Cannot register miscdev on minor=%d (err=%d)\n",
705  wdt_miscdev.minor, rc);
706  goto err_out_reboot;
707  }
708 
709  /* Initialize CIR to use it as keepalive source */
710  if (!test_bit(WDTS_USE_GP, &wdt_status)) {
711  outb(0x00, CIR_RCR(base));
712  outb(0xc0, CIR_TCR1(base));
713  outb(0x5c, CIR_TCR2(base));
714  outb(0x10, CIR_IER(base));
715  outb(0x00, CIR_BDHR(base));
716  outb(0x01, CIR_BDLR(base));
717  outb(0x09, CIR_IER(base));
718  }
719 
720  pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d exclusive=%d nogameport=%d)\n",
721  chip_type, chip_rev, timeout,
722  nowayout, testmode, exclusive, nogameport);
723 
724  superio_exit();
725  return 0;
726 
727 err_out_reboot:
728  unregister_reboot_notifier(&wdt_notifier);
729 err_out_region:
730  release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
731  if (!test_bit(WDTS_USE_GP, &wdt_status)) {
733  superio_outb(ciract, ACTREG);
734  }
735 err_out:
736  if (try_gameport) {
738  superio_outb(gpact, ACTREG);
739  }
740 
741  superio_exit();
742  return rc;
743 }
744 
745 static void __exit it87_wdt_exit(void)
746 {
747  if (superio_enter() == 0) {
749  superio_outb(0x00, WDTCTRL);
750  superio_outb(0x00, WDTCFG);
751  superio_outb(0x00, WDTVALLSB);
752  if (max_units > 255)
753  superio_outb(0x00, WDTVALMSB);
754  if (test_bit(WDTS_USE_GP, &wdt_status)) {
756  superio_outb(gpact, ACTREG);
757  } else {
759  superio_outb(ciract, ACTREG);
760  }
761  superio_exit();
762  }
763 
764  misc_deregister(&wdt_miscdev);
765  unregister_reboot_notifier(&wdt_notifier);
766  release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
767 }
768 
769 module_init(it87_wdt_init);
770 module_exit(it87_wdt_exit);
771 
772 MODULE_AUTHOR("Oliver Schuster");
773 MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
774 MODULE_LICENSE("GPL");