130-watchdog.patch 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. --- /dev/null
  2. +++ b/drivers/watchdog/ar2315-wtd.c
  3. @@ -0,0 +1,209 @@
  4. +/*
  5. + * This program is free software; you can redistribute it and/or modify
  6. + * it under the terms of the GNU General Public License as published by
  7. + * the Free Software Foundation; either version 2 of the License, or
  8. + * (at your option) any later version.
  9. + *
  10. + * This program is distributed in the hope that it will be useful,
  11. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. + * GNU General Public License for more details.
  14. + *
  15. + * You should have received a copy of the GNU General Public License
  16. + * along with this program; if not, see <http://www.gnu.org/licenses/>.
  17. + *
  18. + * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
  19. + * Based on EP93xx and ifxmips wdt driver
  20. + */
  21. +
  22. +#include <linux/interrupt.h>
  23. +#include <linux/module.h>
  24. +#include <linux/moduleparam.h>
  25. +#include <linux/types.h>
  26. +#include <linux/miscdevice.h>
  27. +#include <linux/watchdog.h>
  28. +#include <linux/fs.h>
  29. +#include <linux/ioport.h>
  30. +#include <linux/notifier.h>
  31. +#include <linux/reboot.h>
  32. +#include <linux/init.h>
  33. +#include <linux/platform_device.h>
  34. +#include <linux/io.h>
  35. +#include <linux/uaccess.h>
  36. +
  37. +#define DRIVER_NAME "ar2315-wdt"
  38. +
  39. +#define CLOCK_RATE 40000000
  40. +#define HEARTBEAT(x) (x < 1 || x > 90 ? 20 : x)
  41. +
  42. +#define WDT_REG_TIMER 0x00
  43. +#define WDT_REG_CTRL 0x04
  44. +
  45. +#define WDT_CTRL_ACT_NONE 0x00000000 /* No action */
  46. +#define WDT_CTRL_ACT_NMI 0x00000001 /* NMI on watchdog */
  47. +#define WDT_CTRL_ACT_RESET 0x00000002 /* reset on watchdog */
  48. +
  49. +static int wdt_timeout = 20;
  50. +static int started;
  51. +static int in_use;
  52. +static void __iomem *wdt_base;
  53. +
  54. +static inline void ar2315_wdt_wr(unsigned reg, u32 val)
  55. +{
  56. + iowrite32(val, wdt_base + reg);
  57. +}
  58. +
  59. +static void
  60. +ar2315_wdt_enable(void)
  61. +{
  62. + ar2315_wdt_wr(WDT_REG_TIMER, wdt_timeout * CLOCK_RATE);
  63. +}
  64. +
  65. +static ssize_t
  66. +ar2315_wdt_write(struct file *file, const char __user *data, size_t len,
  67. + loff_t *ppos)
  68. +{
  69. + if (len)
  70. + ar2315_wdt_enable();
  71. + return len;
  72. +}
  73. +
  74. +static int
  75. +ar2315_wdt_open(struct inode *inode, struct file *file)
  76. +{
  77. + if (in_use)
  78. + return -EBUSY;
  79. + ar2315_wdt_enable();
  80. + in_use = 1;
  81. + started = 1;
  82. + return nonseekable_open(inode, file);
  83. +}
  84. +
  85. +static int
  86. +ar2315_wdt_release(struct inode *inode, struct file *file)
  87. +{
  88. + in_use = 0;
  89. + return 0;
  90. +}
  91. +
  92. +static irqreturn_t
  93. +ar2315_wdt_interrupt(int irq, void *dev)
  94. +{
  95. + struct platform_device *pdev = (struct platform_device *)dev;
  96. +
  97. + if (started) {
  98. + dev_crit(&pdev->dev, "watchdog expired, rebooting system\n");
  99. + emergency_restart();
  100. + } else {
  101. + ar2315_wdt_wr(WDT_REG_CTRL, 0);
  102. + ar2315_wdt_wr(WDT_REG_TIMER, 0);
  103. + }
  104. + return IRQ_HANDLED;
  105. +}
  106. +
  107. +static struct watchdog_info ident = {
  108. + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
  109. + .identity = "ar2315 Watchdog",
  110. +};
  111. +
  112. +static long
  113. +ar2315_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  114. +{
  115. + int new_wdt_timeout;
  116. + int ret = -ENOIOCTLCMD;
  117. +
  118. + switch (cmd) {
  119. + case WDIOC_GETSUPPORT:
  120. + ret = copy_to_user((void __user *)arg, &ident, sizeof(ident)) ?
  121. + -EFAULT : 0;
  122. + break;
  123. + case WDIOC_KEEPALIVE:
  124. + ar2315_wdt_enable();
  125. + ret = 0;
  126. + break;
  127. + case WDIOC_SETTIMEOUT:
  128. + ret = get_user(new_wdt_timeout, (int __user *)arg);
  129. + if (ret)
  130. + break;
  131. + wdt_timeout = HEARTBEAT(new_wdt_timeout);
  132. + ar2315_wdt_enable();
  133. + break;
  134. + case WDIOC_GETTIMEOUT:
  135. + ret = put_user(wdt_timeout, (int __user *)arg);
  136. + break;
  137. + }
  138. + return ret;
  139. +}
  140. +
  141. +static const struct file_operations ar2315_wdt_fops = {
  142. + .owner = THIS_MODULE,
  143. + .llseek = no_llseek,
  144. + .write = ar2315_wdt_write,
  145. + .unlocked_ioctl = ar2315_wdt_ioctl,
  146. + .open = ar2315_wdt_open,
  147. + .release = ar2315_wdt_release,
  148. +};
  149. +
  150. +static struct miscdevice ar2315_wdt_miscdev = {
  151. + .minor = WATCHDOG_MINOR,
  152. + .name = "watchdog",
  153. + .fops = &ar2315_wdt_fops,
  154. +};
  155. +
  156. +static int
  157. +ar2315_wdt_probe(struct platform_device *dev)
  158. +{
  159. + struct resource *mem_res, *irq_res;
  160. + int ret = 0;
  161. +
  162. + if (wdt_base)
  163. + return -EBUSY;
  164. +
  165. + irq_res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
  166. + if (!irq_res) {
  167. + dev_err(&dev->dev, "no IRQ resource\n");
  168. + return -ENOENT;
  169. + }
  170. +
  171. + mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  172. + wdt_base = devm_ioremap_resource(&dev->dev, mem_res);
  173. + if (IS_ERR(wdt_base))
  174. + return PTR_ERR(wdt_base);
  175. +
  176. + ret = devm_request_irq(&dev->dev, irq_res->start, ar2315_wdt_interrupt,
  177. + 0, DRIVER_NAME, dev);
  178. + if (ret) {
  179. + dev_err(&dev->dev, "failed to register inetrrupt\n");
  180. + goto out;
  181. + }
  182. +
  183. + ret = misc_register(&ar2315_wdt_miscdev);
  184. + if (ret)
  185. + dev_err(&dev->dev, "failed to register miscdev\n");
  186. +
  187. +out:
  188. + return ret;
  189. +}
  190. +
  191. +static int
  192. +ar2315_wdt_remove(struct platform_device *dev)
  193. +{
  194. + misc_deregister(&ar2315_wdt_miscdev);
  195. + return 0;
  196. +}
  197. +
  198. +static struct platform_driver ar2315_wdt_driver = {
  199. + .probe = ar2315_wdt_probe,
  200. + .remove = ar2315_wdt_remove,
  201. + .driver = {
  202. + .name = DRIVER_NAME,
  203. + .owner = THIS_MODULE,
  204. + },
  205. +};
  206. +
  207. +module_platform_driver(ar2315_wdt_driver);
  208. +
  209. +MODULE_DESCRIPTION("Atheros AR2315 hardware watchdog driver");
  210. +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
  211. +MODULE_LICENSE("GPL");
  212. +MODULE_ALIAS("platform:" DRIVER_NAME);
  213. --- a/drivers/watchdog/Kconfig
  214. +++ b/drivers/watchdog/Kconfig
  215. @@ -1345,6 +1345,13 @@ config RALINK_WDT
  216. help
  217. Hardware driver for the Ralink SoC Watchdog Timer.
  218. +config AR2315_WDT
  219. + tristate "Atheros AR2315+ WiSoCs Watchdog Timer"
  220. + depends on ATH25
  221. + help
  222. + Hardware driver for the built-in watchdog timer on the Atheros
  223. + AR2315/AR2316 WiSoCs.
  224. +
  225. # PARISC Architecture
  226. # POWERPC Architecture
  227. --- a/drivers/watchdog/Makefile
  228. +++ b/drivers/watchdog/Makefile
  229. @@ -143,6 +143,7 @@ obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
  230. obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
  231. obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
  232. obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
  233. +obj-$(CONFIG_AR2315_WDT) += ar2315-wtd.o
  234. obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
  235. obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
  236. octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
  237. --- a/arch/mips/ath25/ar2315.c
  238. +++ b/arch/mips/ath25/ar2315.c
  239. @@ -220,6 +220,24 @@ static struct platform_device ar2315_gpi
  240. .num_resources = ARRAY_SIZE(ar2315_gpio_res)
  241. };
  242. +static struct resource ar2315_wdt_res[] = {
  243. + {
  244. + .flags = IORESOURCE_MEM,
  245. + .start = AR2315_RST_BASE + AR2315_WDT_TIMER,
  246. + .end = AR2315_RST_BASE + AR2315_WDT_TIMER + 8 - 1,
  247. + },
  248. + {
  249. + .flags = IORESOURCE_IRQ,
  250. + }
  251. +};
  252. +
  253. +static struct platform_device ar2315_wdt = {
  254. + .id = 0,
  255. + .name = "ar2315-wdt",
  256. + .resource = ar2315_wdt_res,
  257. + .num_resources = ARRAY_SIZE(ar2315_wdt_res)
  258. +};
  259. +
  260. static struct resource ar2315_spiflash_res[] = {
  261. {
  262. .name = "spiflash_read",
  263. @@ -252,6 +270,11 @@ void __init ar2315_init_devices(void)
  264. ar2315_gpio_res[1].end = ar2315_gpio_res[1].start;
  265. platform_device_register(&ar2315_gpio);
  266. + ar2315_wdt_res[1].start = irq_create_mapping(ar2315_misc_irq_domain,
  267. + AR2315_MISC_IRQ_WATCHDOG);
  268. + ar2315_wdt_res[1].end = ar2315_wdt_res[1].start;
  269. + platform_device_register(&ar2315_wdt);
  270. +
  271. platform_device_register(&ar2315_spiflash);
  272. ar2315_eth_data.macaddr = ath25_board.config->enet0_mac;