wdog.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/slab.h>
  5. #include <linux/fs.h>
  6. #include <linux/cdev.h>
  7. #include <linux/version.h>
  8. #include <asm/uaccess.h>
  9. #include <asm/io.h>
  10. #include "wdog.h"
  11. struct cdev *cdev_siswdog;
  12. void siswdog_stimeout(int devno, int preferred_timeout)
  13. {
  14. DebugPrint("[WDOG] setting timeout for wdog[%d] \n", devno);
  15. if((devno < 1) || (devno > 2)){
  16. DebugPrint("[WDOG] Error -- There's NO WAY to set wdog[%d] timeout !! \n", devno);
  17. return;
  18. }
  19. if(devno == 1){
  20. #if 0
  21. __u32 temp = readl((__u32 *)WDT1_Ctl_Reg) & 0xe0000000;
  22. DebugPrint("[WDOG] setting timeout for wdog[%d] : %d us \n", devno, preferred_timeout);
  23. writel((preferred_timeout & 0x1fffffff), (__u32 *)WDT1_Ctl_Reg);
  24. writel(temp | (preferred_timeout & 0x1fffffff), (__u32 *)WDT1_Ctl_Reg);
  25. #endif
  26. } else if(devno == 2){
  27. __u32 temp = readl((__u32 *)WDT2_Ctl_Reg) & 0xe0000000;
  28. DebugPrint("[WDOG] setting timeout for wdog[%d] : %d ms \n", devno, preferred_timeout);
  29. writel((preferred_timeout & 0x1fffffff), (__u32 *)WDT2_Ctl_Reg);
  30. writel(temp | (preferred_timeout & 0x1fffffff), (__u32 *)WDT2_Ctl_Reg);
  31. }
  32. }
  33. void siswdog_keepalive(int devno)
  34. {
  35. if(devno == 0){
  36. set_bit(WDT0_Refresh_bit, (void *)(WDT0_Ctl_Reg));
  37. } else if(devno == 1){
  38. set_bit(WDT1_Refresh_bit, (void *)(WDT0_Ctl_Reg));
  39. } else if(devno == 2){
  40. set_bit(WDT2_Refresh_bit, (void *)(WDT0_Ctl_Reg));
  41. }
  42. }
  43. EXPORT_SYMBOL(siswdog_keepalive);
  44. #if 1
  45. void siswdog_remove(int devno)
  46. {
  47. // keep-alive the Watch Dog here for the critical case
  48. siswdog_keepalive(devno);
  49. if(devno == 0){
  50. set_bit(WDT0_Disable_bit, (void *)(WDT0_Ctl_Reg));
  51. } else if(devno == 1){
  52. clear_bit(WDT1_Eisable_bit, (void *)(WDT1_Ctl_Reg));
  53. } else if(devno == 2){
  54. clear_bit(WDT2_Eisable_bit, (void *)(WDT2_Ctl_Reg));
  55. } else if(devno == 3){
  56. //writel(0, (__u32 *)0xbe0f030c); // clear the Watch Dog 3
  57. }
  58. }
  59. EXPORT_SYMBOL(siswdog_remove);
  60. #endif
  61. void siswdog_add(int devno, int preferred_timeout)
  62. {
  63. siswdog_stimeout(devno, preferred_timeout);
  64. // enable the Watch Dog
  65. if(devno == 0){
  66. clear_bit(WDT0_Disable_bit, (void *)(WDT0_Ctl_Reg));
  67. } else if(devno == 1){
  68. set_bit(WDT1_Eisable_bit, (void *)(WDT1_Ctl_Reg));
  69. } else if(devno == 2){
  70. set_bit(WDT2_Eisable_bit, (void *)(WDT2_Ctl_Reg));
  71. }
  72. #if 0
  73. else if(devno == 3){
  74. writel(SISWDOG3_WarmReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "Warm Reset" at once
  75. } else if(devno == 4){
  76. writel(SISWDOG3_ColdReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "Cold Reset" at once
  77. } else if(devno == 5){
  78. writel(SISWDOG3_RTCReset, (__u32 *)WDT3_Ctl_Reg); // set the Watch Dog 3 to "RTC Reset" at once
  79. }
  80. #endif
  81. // keep-alive the Watch Dog here for the critical case
  82. siswdog_keepalive(devno);
  83. }
  84. EXPORT_SYMBOL(siswdog_add);
  85. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8)
  86. long siswdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  87. #else
  88. ssize_t siswdog_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
  89. #endif
  90. {
  91. siswdog_ioctl_data parameter;
  92. switch(cmd){
  93. case SISWDOG_ADD:
  94. copy_from_user(&parameter, (void *)arg, sizeof(siswdog_ioctl_data));
  95. siswdog_add(parameter.devno, parameter.preferred_timeout);
  96. break;
  97. #if 1
  98. case SISWDOG_REMOVE:
  99. siswdog_remove(arg);
  100. break;
  101. #endif
  102. case SISWDOG_KEEPALIVE:
  103. siswdog_keepalive(arg);
  104. break;
  105. default:
  106. break;
  107. }
  108. return 0;
  109. }
  110. struct file_operations siswdog_fops = {
  111. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8))
  112. .unlocked_ioctl = siswdog_ioctl,
  113. #else
  114. .ioctl = siswdog_ioctl,
  115. #endif
  116. .owner = THIS_MODULE,
  117. };
  118. int siswdog_init(void){
  119. int ret = 0;
  120. int devno = MKDEV(SISWDOG_DEV_MAJOR, 130);
  121. cdev_siswdog = cdev_alloc();
  122. cdev_siswdog->owner = THIS_MODULE;
  123. cdev_siswdog->ops = &siswdog_fops;
  124. ret = cdev_add(cdev_siswdog, devno, 1);
  125. if (ret)
  126. {
  127. printk("\n====[%s, %d], init fail!!! err = %d\n",__FUNCTION__,__LINE__, ret);
  128. return -EIO;
  129. }
  130. *(volatile unsigned int *)(WDT1_Ctl_Reg) = (*(volatile unsigned int *)(WDT1_Ctl_Reg) & ~(0x3 << 29)) | SISWDOG_ColdReset;
  131. *(volatile unsigned int *)(WDT2_Ctl_Reg) = (*(volatile unsigned int *)(WDT2_Ctl_Reg) & ~(0x3 << 29)) | SISWDOG_ColdReset;
  132. return 0;
  133. }
  134. #if 0
  135. void siswdog_exit(void){
  136. cdev_del(cdev_siswdog);
  137. }
  138. #endif
  139. #ifndef INIT_BY_KMF
  140. module_init(siswdog_init);
  141. module_exit(siswdog_exit);
  142. #endif
  143. MODULE_LICENSE("Dual BSD/GPL");