wdt285.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Intel 21285 watchdog driver
  3.  * Copyright (c) Phil Blundell <pb@nexus.co.uk>, 1998
  4.  *
  5.  * based on
  6.  *
  7.  * SoftDog 0.05: A Software Watchdog Device
  8.  *
  9.  * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
  10.  *
  11.  * This program is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU General Public License
  13.  * as published by the Free Software Foundation; either version
  14.  * 2 of the License, or (at your option) any later version.
  15.  *
  16.  */
  17.  
  18. #include <linux/module.h>
  19. #include <linux/types.h>
  20. #include <linux/kernel.h>
  21. #include <linux/fs.h>
  22. #include <linux/mm.h>
  23. #include <linux/miscdevice.h>
  24. #include <linux/watchdog.h>
  25. #include <linux/reboot.h>
  26. #include <linux/init.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/smp_lock.h>
  29. #include <asm/irq.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/hardware.h>
  32. #include <asm/mach-types.h>
  33. #include <asm/hardware/dec21285.h>
  34. /*
  35.  * Define this to stop the watchdog actually rebooting the machine.
  36.  */
  37. #undef ONLY_TESTING
  38. #define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
  39. #define FCLK (50*1000*1000) /* 50MHz */
  40. static int soft_margin = TIMER_MARGIN; /* in seconds */
  41. static int timer_alive;
  42. #ifdef ONLY_TESTING
  43. /*
  44.  * If the timer expires..
  45.  */
  46. static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs)
  47. {
  48. printk(KERN_CRIT "Watchdog: Would Reboot.n");
  49. *CSR_TIMER4_CNTL = 0;
  50. *CSR_TIMER4_CLR = 0;
  51. }
  52. #endif
  53. static void watchdog_ping(void)
  54. {
  55. /*
  56.  * Refresh the timer.
  57.  */
  58. *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256);
  59. }
  60. /*
  61.  * Allow only one person to hold it open
  62.  */
  63.  
  64. static int watchdog_open(struct inode *inode, struct file *file)
  65. {
  66. if(timer_alive)
  67. return -EBUSY;
  68. /*
  69.  * Ahead watchdog factor ten, Mr Sulu
  70.  */
  71. *CSR_TIMER4_CLR = 0;
  72. watchdog_ping();
  73. *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD 
  74. | TIMER_CNTL_DIV256;
  75. #ifdef ONLY_TESTING
  76. request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
  77. #else
  78. *CSR_SA110_CNTL |= 1 << 13;
  79. MOD_INC_USE_COUNT;
  80. #endif
  81. timer_alive = 1;
  82. return 0;
  83. }
  84. static int watchdog_release(struct inode *inode, struct file *file)
  85. {
  86. #ifdef ONLY_TESTING
  87. lock_kernel();
  88. free_irq(IRQ_TIMER4, NULL);
  89. timer_alive = 0;
  90. unlock_kernel();
  91. #else
  92. /*
  93.  * It's irreversible!
  94.  */
  95. #endif
  96. return 0;
  97. }
  98. static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  99. {
  100. /*  Can't seek (pwrite) on this device  */
  101. if (ppos != &file->f_pos)
  102. return -ESPIPE;
  103. /*
  104.  * Refresh the timer.
  105.  */
  106. if(len)
  107. {
  108. watchdog_ping();
  109. return 1;
  110. }
  111. return 0;
  112. }
  113. static int watchdog_ioctl(struct inode *inode, struct file *file,
  114. unsigned int cmd, unsigned long arg)
  115. {
  116. int i, new_margin;
  117. static struct watchdog_info ident=
  118. {
  119. WDIOF_SETTIMEOUT,
  120. 0,
  121. "Footbridge Watchdog"
  122. };
  123. switch(cmd)
  124. {
  125. default:
  126. return -ENOTTY;
  127. case WDIOC_GETSUPPORT:
  128. i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
  129. if (i)
  130. return i;
  131. else
  132. return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
  133. case WDIOC_GETSTATUS:
  134. case WDIOC_GETBOOTSTATUS:
  135. return put_user(0,(int *)arg);
  136. case WDIOC_KEEPALIVE:
  137. watchdog_ping();
  138. return 0;
  139. case WDIOC_SETTIMEOUT:
  140. if (get_user(new_margin, (int *)arg))
  141. return -EFAULT;
  142. /* Arbitrary, can't find the card's limits */
  143. if ((new_margin < 0) || (new_margin > 60))
  144. return -EINVAL;
  145. soft_margin = new_margin;
  146. watchdog_ping();
  147. /* Fall */
  148. case WDIOC_GETTIMEOUT:
  149. return put_user(soft_margin, (int *)arg);
  150. }
  151. }
  152. static struct file_operations watchdog_fops=
  153. {
  154. owner: THIS_MODULE,
  155. write: watchdog_write,
  156. ioctl: watchdog_ioctl,
  157. open: watchdog_open,
  158. release: watchdog_release,
  159. };
  160. static struct miscdevice watchdog_miscdev=
  161. {
  162. WATCHDOG_MINOR,
  163. "watchdog",
  164. &watchdog_fops
  165. };
  166. static int __init footbridge_watchdog_init(void)
  167. {
  168. if (machine_is_netwinder())
  169. return -ENODEV;
  170. misc_register(&watchdog_miscdev);
  171. printk("Footbridge Watchdog Timer: 0.01, timer margin: %d secn", 
  172.        soft_margin);
  173. if (machine_is_cats())
  174. printk("Warning: Watchdog reset may not work on this machine.n");
  175. return 0;
  176. }
  177. static void __exit footbridge_watchdog_exit(void)
  178. {
  179. misc_deregister(&watchdog_miscdev);
  180. }
  181. EXPORT_NO_SYMBOLS;
  182. MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
  183. MODULE_DESCRIPTION("21285 watchdog driver");
  184. MODULE_LICENSE("GPL");
  185. MODULE_PARM(soft_margin,"i");
  186. MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
  187. module_init(footbridge_watchdog_init);
  188. module_exit(footbridge_watchdog_exit);