mpc8xx_wdt.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
  3. *
  4. * Author: Florian Schirmer <jolt@tuxbox.org>
  5. *
  6. * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
  7. * the terms of the GNU General Public License version 2. This program
  8. * is licensed "as is" without any warranty of any kind, whether express
  9. * or implied.
  10. */
  11. #include <linux/config.h>
  12. #include <linux/fs.h>
  13. #include <linux/init.h>
  14. #include <linux/kernel.h>
  15. #include <linux/miscdevice.h>
  16. #include <linux/module.h>
  17. #include <linux/watchdog.h>
  18. #include <asm/8xx_immap.h>
  19. #include <asm/uaccess.h>
  20. #include <asm/io.h>
  21. #include <syslib/m8xx_wdt.h>
  22. static unsigned long wdt_opened;
  23. static int wdt_status;
  24. static void mpc8xx_wdt_handler_disable(void)
  25. {
  26. volatile uint __iomem *piscr;
  27. piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
  28. if (!m8xx_has_internal_rtc)
  29. m8xx_wdt_stop_timer();
  30. else
  31. out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
  32. printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
  33. }
  34. static void mpc8xx_wdt_handler_enable(void)
  35. {
  36. volatile uint __iomem *piscr;
  37. piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
  38. if (!m8xx_has_internal_rtc)
  39. m8xx_wdt_install_timer();
  40. else
  41. out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
  42. printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
  43. }
  44. static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
  45. {
  46. if (test_and_set_bit(0, &wdt_opened))
  47. return -EBUSY;
  48. m8xx_wdt_reset();
  49. mpc8xx_wdt_handler_disable();
  50. return 0;
  51. }
  52. static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
  53. {
  54. m8xx_wdt_reset();
  55. #if !defined(CONFIG_WATCHDOG_NOWAYOUT)
  56. mpc8xx_wdt_handler_enable();
  57. #endif
  58. clear_bit(0, &wdt_opened);
  59. return 0;
  60. }
  61. static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
  62. loff_t * ppos)
  63. {
  64. if (len)
  65. m8xx_wdt_reset();
  66. return len;
  67. }
  68. static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
  69. unsigned int cmd, unsigned long arg)
  70. {
  71. int timeout;
  72. static struct watchdog_info info = {
  73. .options = WDIOF_KEEPALIVEPING,
  74. .firmware_version = 0,
  75. .identity = "MPC8xx watchdog",
  76. };
  77. switch (cmd) {
  78. case WDIOC_GETSUPPORT:
  79. if (copy_to_user((void *)arg, &info, sizeof(info)))
  80. return -EFAULT;
  81. break;
  82. case WDIOC_GETSTATUS:
  83. case WDIOC_GETBOOTSTATUS:
  84. if (put_user(wdt_status, (int *)arg))
  85. return -EFAULT;
  86. wdt_status &= ~WDIOF_KEEPALIVEPING;
  87. break;
  88. case WDIOC_GETTEMP:
  89. return -EOPNOTSUPP;
  90. case WDIOC_SETOPTIONS:
  91. return -EOPNOTSUPP;
  92. case WDIOC_KEEPALIVE:
  93. m8xx_wdt_reset();
  94. wdt_status |= WDIOF_KEEPALIVEPING;
  95. break;
  96. case WDIOC_SETTIMEOUT:
  97. return -EOPNOTSUPP;
  98. case WDIOC_GETTIMEOUT:
  99. timeout = m8xx_wdt_get_timeout();
  100. if (put_user(timeout, (int *)arg))
  101. return -EFAULT;
  102. break;
  103. default:
  104. return -ENOIOCTLCMD;
  105. }
  106. return 0;
  107. }
  108. static struct file_operations mpc8xx_wdt_fops = {
  109. .owner = THIS_MODULE,
  110. .llseek = no_llseek,
  111. .write = mpc8xx_wdt_write,
  112. .ioctl = mpc8xx_wdt_ioctl,
  113. .open = mpc8xx_wdt_open,
  114. .release = mpc8xx_wdt_release,
  115. };
  116. static struct miscdevice mpc8xx_wdt_miscdev = {
  117. .minor = WATCHDOG_MINOR,
  118. .name = "watchdog",
  119. .fops = &mpc8xx_wdt_fops,
  120. };
  121. static int __init mpc8xx_wdt_init(void)
  122. {
  123. return misc_register(&mpc8xx_wdt_miscdev);
  124. }
  125. static void __exit mpc8xx_wdt_exit(void)
  126. {
  127. misc_deregister(&mpc8xx_wdt_miscdev);
  128. m8xx_wdt_reset();
  129. mpc8xx_wdt_handler_enable();
  130. }
  131. module_init(mpc8xx_wdt_init);
  132. module_exit(mpc8xx_wdt_exit);
  133. MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
  134. MODULE_DESCRIPTION("MPC8xx watchdog driver");
  135. MODULE_LICENSE("GPL");
  136. MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);