mpc8xx_wdt.c 3.7 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/fs.h>
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/miscdevice.h>
  15. #include <linux/module.h>
  16. #include <linux/watchdog.h>
  17. #include <asm/8xx_immap.h>
  18. #include <linux/uaccess.h>
  19. #include <linux/io.h>
  20. #include <syslib/m8xx_wdt.h>
  21. static unsigned long wdt_opened;
  22. static int wdt_status;
  23. static spinlock_t wdt_lock;
  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 nonseekable_open(inode, file);
  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,
  62. size_t len, loff_t *ppos)
  63. {
  64. if (len) {
  65. spin_lock(&wdt_lock);
  66. m8xx_wdt_reset();
  67. spin_unlock(&wdt_lock);
  68. }
  69. return len;
  70. }
  71. static long mpc8xx_wdt_ioctl(struct file *file,
  72. unsigned int cmd, unsigned long arg)
  73. {
  74. int timeout;
  75. static struct watchdog_info info = {
  76. .options = WDIOF_KEEPALIVEPING,
  77. .firmware_version = 0,
  78. .identity = "MPC8xx watchdog",
  79. };
  80. switch (cmd) {
  81. case WDIOC_GETSUPPORT:
  82. if (copy_to_user((void *)arg, &info, sizeof(info)))
  83. return -EFAULT;
  84. break;
  85. case WDIOC_GETSTATUS:
  86. case WDIOC_GETBOOTSTATUS:
  87. if (put_user(wdt_status, (int *)arg))
  88. return -EFAULT;
  89. wdt_status &= ~WDIOF_KEEPALIVEPING;
  90. break;
  91. case WDIOC_GETTEMP:
  92. return -EOPNOTSUPP;
  93. case WDIOC_SETOPTIONS:
  94. return -EOPNOTSUPP;
  95. case WDIOC_KEEPALIVE:
  96. spin_lock(&wdt_lock);
  97. m8xx_wdt_reset();
  98. wdt_status |= WDIOF_KEEPALIVEPING;
  99. spin_unlock(&wdt_lock);
  100. break;
  101. case WDIOC_SETTIMEOUT:
  102. return -EOPNOTSUPP;
  103. case WDIOC_GETTIMEOUT:
  104. spin_lock(&wdt_lock);
  105. timeout = m8xx_wdt_get_timeout();
  106. spin_unlock(&wdt_lock);
  107. if (put_user(timeout, (int *)arg))
  108. return -EFAULT;
  109. break;
  110. default:
  111. return -ENOTTY;
  112. }
  113. return 0;
  114. }
  115. static const struct file_operations mpc8xx_wdt_fops = {
  116. .owner = THIS_MODULE,
  117. .llseek = no_llseek,
  118. .write = mpc8xx_wdt_write,
  119. .unlocked_ioctl = mpc8xx_wdt_ioctl,
  120. .open = mpc8xx_wdt_open,
  121. .release = mpc8xx_wdt_release,
  122. };
  123. static struct miscdevice mpc8xx_wdt_miscdev = {
  124. .minor = WATCHDOG_MINOR,
  125. .name = "watchdog",
  126. .fops = &mpc8xx_wdt_fops,
  127. };
  128. static int __init mpc8xx_wdt_init(void)
  129. {
  130. spin_lock_init(&wdt_lock);
  131. return misc_register(&mpc8xx_wdt_miscdev);
  132. }
  133. static void __exit mpc8xx_wdt_exit(void)
  134. {
  135. misc_deregister(&mpc8xx_wdt_miscdev);
  136. m8xx_wdt_reset();
  137. mpc8xx_wdt_handler_enable();
  138. }
  139. module_init(mpc8xx_wdt_init);
  140. module_exit(mpc8xx_wdt_exit);
  141. MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
  142. MODULE_DESCRIPTION("MPC8xx watchdog driver");
  143. MODULE_LICENSE("GPL");
  144. MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);