075-mcfv4e_watchdog.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. From 3c6c80a04d6ca99c4f9fbb5e4f279bd644b2df48 Mon Sep 17 00:00:00 2001
  2. From: Kurt Mahan <[email protected]>
  3. Date: Tue, 8 Jul 2008 14:10:46 -0600
  4. Subject: [PATCH] Add Coldfire Watchdog support.
  5. LTIBName: mcfv4e-watchdog
  6. Signed-off-by: Kurt Mahan <[email protected]>
  7. ---
  8. drivers/watchdog/Kconfig | 9 ++
  9. drivers/watchdog/Makefile | 1 +
  10. drivers/watchdog/mcf_wdt.c | 220 ++++++++++++++++++++++++++++++++++++++++++++
  11. 3 files changed, 230 insertions(+), 0 deletions(-)
  12. create mode 100644 drivers/watchdog/mcf_wdt.c
  13. --- a/drivers/watchdog/Kconfig
  14. +++ b/drivers/watchdog/Kconfig
  15. @@ -672,6 +672,15 @@ config TXX9_WDT
  16. # PARISC Architecture
  17. +# ColdFire Architecture
  18. +
  19. +config COLDFIRE_WATCHDOG
  20. + tristate "ColdFire watchdog support"
  21. + depends on WATCHDOG
  22. + help
  23. + To compile this driver as a module, choose M here: the
  24. + module will be called softdog.
  25. +
  26. # POWERPC Architecture
  27. config MPC5200_WDT
  28. --- a/drivers/watchdog/Makefile
  29. +++ b/drivers/watchdog/Makefile
  30. @@ -86,6 +86,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc
  31. # M32R Architecture
  32. # M68K Architecture
  33. +obj-$(CONFIG_COLDFIRE_WATCHDOG) += mcf_wdt.o
  34. # M68KNOMMU Architecture
  35. --- /dev/null
  36. +++ b/drivers/watchdog/mcf_wdt.c
  37. @@ -0,0 +1,220 @@
  38. +/*
  39. + * drivers/watchdog/mcf_wdt.c
  40. + *
  41. + * Watchdog driver for ColdFire processors
  42. + *
  43. + * Adapted from the IXP4xx watchdog driver.
  44. + * The original version carries these notices:
  45. + *
  46. + * Author: Deepak Saxena <[email protected]>
  47. + *
  48. + * Copyright 2004 (c) MontaVista, Software, Inc.
  49. + * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <[email protected]>
  50. + *
  51. + * This file is licensed under the terms of the GNU General Public
  52. + * License version 2. This program is licensed "as is" without any
  53. + * warranty of any kind, whether express or implied.
  54. + */
  55. +
  56. +#include <linux/module.h>
  57. +#include <linux/moduleparam.h>
  58. +#include <linux/types.h>
  59. +#include <linux/kernel.h>
  60. +#include <linux/fs.h>
  61. +#include <linux/miscdevice.h>
  62. +#include <linux/watchdog.h>
  63. +#include <linux/init.h>
  64. +#include <linux/bitops.h>
  65. +
  66. +#include <asm-m68k/uaccess.h>
  67. +#include <asm-m68k/coldfire.h>
  68. +#include <asm-m68k/m5485gpt.h>
  69. +
  70. +static int nowayout;
  71. +static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */
  72. +static unsigned long wdt_status;
  73. +
  74. +#define WDT_IN_USE 0
  75. +#define WDT_OK_TO_CLOSE 1
  76. +
  77. +static unsigned long wdt_tick_rate;
  78. +
  79. +static void
  80. +wdt_enable(void)
  81. +{
  82. + MCF_GPT_GMS0 = 0;
  83. + MCF_GPT_GCIR0 = MCF_GPT_GCIR_PRE(heartbeat*wdt_tick_rate) |
  84. + MCF_GPT_GCIR_CNT(0xffff);
  85. + MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN |
  86. + MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS_GPIO;
  87. +}
  88. +
  89. +static void
  90. +wdt_disable(void)
  91. +{
  92. + MCF_GPT_GMS0 = 0;
  93. +}
  94. +
  95. +static void
  96. +wdt_keepalive(void)
  97. +{
  98. + MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS0;
  99. +}
  100. +
  101. +static int
  102. +mcf_wdt_open(struct inode *inode, struct file *file)
  103. +{
  104. + if (test_and_set_bit(WDT_IN_USE, &wdt_status))
  105. + return -EBUSY;
  106. +
  107. + clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
  108. +
  109. + wdt_enable();
  110. +
  111. + return nonseekable_open(inode, file);
  112. +}
  113. +
  114. +static ssize_t
  115. +mcf_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
  116. +{
  117. + if (len) {
  118. + if (!nowayout) {
  119. + size_t i;
  120. +
  121. + clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
  122. +
  123. + for (i = 0; i != len; i++) {
  124. + char c;
  125. +
  126. + if (get_user(c, data + i))
  127. + return -EFAULT;
  128. + if (c == 'V')
  129. + set_bit(WDT_OK_TO_CLOSE, &wdt_status);
  130. + }
  131. + }
  132. + wdt_keepalive();
  133. + }
  134. +
  135. + return len;
  136. +}
  137. +
  138. +
  139. +static struct watchdog_info ident = {
  140. + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
  141. + WDIOF_KEEPALIVEPING,
  142. + .identity = "Coldfire Watchdog",
  143. +};
  144. +
  145. +static int
  146. +mcf_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
  147. + unsigned long arg)
  148. +{
  149. + int ret = -ENOIOCTLCMD;
  150. + int time;
  151. +
  152. + switch (cmd) {
  153. + case WDIOC_GETSUPPORT:
  154. + ret = copy_to_user((struct watchdog_info *)arg, &ident,
  155. + sizeof(ident)) ? -EFAULT : 0;
  156. + break;
  157. +
  158. + case WDIOC_GETSTATUS:
  159. + ret = put_user(0, (int *)arg);
  160. + break;
  161. +
  162. + case WDIOC_GETBOOTSTATUS:
  163. + ret = put_user(0, (int *)arg);
  164. + break;
  165. +
  166. + case WDIOC_SETTIMEOUT:
  167. + ret = get_user(time, (int *)arg);
  168. + if (ret)
  169. + break;
  170. +
  171. + if (time <= 0 || time > 30) {
  172. + ret = -EINVAL;
  173. + break;
  174. + }
  175. +
  176. + heartbeat = time;
  177. + wdt_enable();
  178. + /* Fall through */
  179. +
  180. + case WDIOC_GETTIMEOUT:
  181. + ret = put_user(heartbeat, (int *)arg);
  182. + break;
  183. +
  184. + case WDIOC_KEEPALIVE:
  185. + wdt_keepalive();
  186. + ret = 0;
  187. + break;
  188. + }
  189. +
  190. + return ret;
  191. +}
  192. +
  193. +static int
  194. +mcf_wdt_release(struct inode *inode, struct file *file)
  195. +{
  196. + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
  197. + wdt_disable();
  198. + } else {
  199. + printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - "
  200. + "timer will not stop\n");
  201. + }
  202. +
  203. + clear_bit(WDT_IN_USE, &wdt_status);
  204. + clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
  205. +
  206. + return 0;
  207. +}
  208. +
  209. +
  210. +static struct file_operations mcf_wdt_fops = {
  211. + .owner = THIS_MODULE,
  212. + .llseek = no_llseek,
  213. + .write = mcf_wdt_write,
  214. + .ioctl = mcf_wdt_ioctl,
  215. + .open = mcf_wdt_open,
  216. + .release = mcf_wdt_release,
  217. +};
  218. +
  219. +static struct miscdevice mcf_wdt_miscdev = {
  220. + .minor = WATCHDOG_MINOR,
  221. + .name = "watchdog",
  222. + .fops = &mcf_wdt_fops,
  223. +};
  224. +
  225. +static int __init mcf_wdt_init(void)
  226. +{
  227. + wdt_tick_rate = MCF_BUSCLK/0xffff;
  228. +#ifdef CONFIG_WATCHDOG_NOWAYOUT
  229. + nowayout = 1;
  230. +#else
  231. + nowayout = 0;
  232. +#endif
  233. + printk("ColdFire watchdog driver is loaded.\n");
  234. +
  235. + return misc_register(&mcf_wdt_miscdev);
  236. +}
  237. +
  238. +static void __exit mcf_wdt_exit(void)
  239. +{
  240. + misc_deregister(&mcf_wdt_miscdev);
  241. +}
  242. +
  243. +module_init(mcf_wdt_init);
  244. +module_exit(mcf_wdt_exit);
  245. +
  246. +MODULE_AUTHOR("Deepak Saxena");
  247. +MODULE_DESCRIPTION("ColdFire Watchdog");
  248. +
  249. +module_param(heartbeat, int, 0);
  250. +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
  251. +
  252. +module_param(nowayout, int, 0);
  253. +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
  254. +
  255. +MODULE_LICENSE("GPL");
  256. +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
  257. +