orion_wdt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*
  2. * drivers/watchdog/orion_wdt.c
  3. *
  4. * Watchdog driver for Orion/Kirkwood processors
  5. *
  6. * Author: Sylver Bruneau <[email protected]>
  7. *
  8. * This file is licensed under the terms of the GNU General Public
  9. * License version 2. This program is licensed "as is" without any
  10. * warranty of any kind, whether express or implied.
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/module.h>
  14. #include <linux/moduleparam.h>
  15. #include <linux/types.h>
  16. #include <linux/kernel.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/watchdog.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/io.h>
  21. #include <linux/clk.h>
  22. #include <linux/err.h>
  23. #include <linux/of.h>
  24. #include <linux/of_device.h>
  25. /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
  26. #define ORION_RSTOUT_MASK_OFFSET 0x20108
  27. /* Internal registers can be configured at any 1 MiB aligned address */
  28. #define INTERNAL_REGS_MASK ~(SZ_1M - 1)
  29. /*
  30. * Watchdog timer block registers.
  31. */
  32. #define TIMER_CTRL 0x0000
  33. #define TIMER1_FIXED_ENABLE_BIT BIT(12)
  34. #define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
  35. #define TIMER1_ENABLE_BIT BIT(2)
  36. #define TIMER_A370_STATUS 0x0004
  37. #define WDT_A370_EXPIRED BIT(31)
  38. #define TIMER1_STATUS_BIT BIT(8)
  39. #define TIMER1_VAL_OFF 0x001c
  40. #define WDT_MAX_CYCLE_COUNT 0xffffffff
  41. #define WDT_A370_RATIO_MASK(v) ((v) << 16)
  42. #define WDT_A370_RATIO_SHIFT 5
  43. #define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT)
  44. static bool nowayout = WATCHDOG_NOWAYOUT;
  45. static int heartbeat; /* module parameter (seconds) */
  46. struct orion_watchdog;
  47. struct orion_watchdog_data {
  48. int wdt_counter_offset;
  49. int wdt_enable_bit;
  50. int rstout_enable_bit;
  51. int rstout_mask_bit;
  52. int (*clock_init)(struct platform_device *,
  53. struct orion_watchdog *);
  54. int (*enabled)(struct orion_watchdog *);
  55. int (*start)(struct watchdog_device *);
  56. int (*stop)(struct watchdog_device *);
  57. };
  58. struct orion_watchdog {
  59. struct watchdog_device wdt;
  60. void __iomem *reg;
  61. void __iomem *rstout;
  62. void __iomem *rstout_mask;
  63. unsigned long clk_rate;
  64. struct clk *clk;
  65. const struct orion_watchdog_data *data;
  66. };
  67. static int orion_wdt_clock_init(struct platform_device *pdev,
  68. struct orion_watchdog *dev)
  69. {
  70. int ret;
  71. dev->clk = clk_get(&pdev->dev, NULL);
  72. if (IS_ERR(dev->clk))
  73. return PTR_ERR(dev->clk);
  74. ret = clk_prepare_enable(dev->clk);
  75. if (ret) {
  76. clk_put(dev->clk);
  77. return ret;
  78. }
  79. dev->clk_rate = clk_get_rate(dev->clk);
  80. return 0;
  81. }
  82. static int armada370_wdt_clock_init(struct platform_device *pdev,
  83. struct orion_watchdog *dev)
  84. {
  85. int ret;
  86. dev->clk = clk_get(&pdev->dev, NULL);
  87. if (IS_ERR(dev->clk))
  88. return PTR_ERR(dev->clk);
  89. ret = clk_prepare_enable(dev->clk);
  90. if (ret) {
  91. clk_put(dev->clk);
  92. return ret;
  93. }
  94. /* Setup watchdog input clock */
  95. atomic_io_modify(dev->reg + TIMER_CTRL,
  96. WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
  97. WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
  98. dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
  99. return 0;
  100. }
  101. static int armada375_wdt_clock_init(struct platform_device *pdev,
  102. struct orion_watchdog *dev)
  103. {
  104. int ret;
  105. dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
  106. if (!IS_ERR(dev->clk)) {
  107. ret = clk_prepare_enable(dev->clk);
  108. if (ret) {
  109. clk_put(dev->clk);
  110. return ret;
  111. }
  112. atomic_io_modify(dev->reg + TIMER_CTRL,
  113. WDT_AXP_FIXED_ENABLE_BIT,
  114. WDT_AXP_FIXED_ENABLE_BIT);
  115. dev->clk_rate = clk_get_rate(dev->clk);
  116. return 0;
  117. }
  118. /* Mandatory fallback for proper devicetree backward compatibility */
  119. dev->clk = clk_get(&pdev->dev, NULL);
  120. if (IS_ERR(dev->clk))
  121. return PTR_ERR(dev->clk);
  122. ret = clk_prepare_enable(dev->clk);
  123. if (ret) {
  124. clk_put(dev->clk);
  125. return ret;
  126. }
  127. atomic_io_modify(dev->reg + TIMER_CTRL,
  128. WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
  129. WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
  130. dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
  131. return 0;
  132. }
  133. static int armadaxp_wdt_clock_init(struct platform_device *pdev,
  134. struct orion_watchdog *dev)
  135. {
  136. int ret;
  137. u32 val;
  138. dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
  139. if (IS_ERR(dev->clk))
  140. return PTR_ERR(dev->clk);
  141. ret = clk_prepare_enable(dev->clk);
  142. if (ret) {
  143. clk_put(dev->clk);
  144. return ret;
  145. }
  146. /* Fix the wdt and timer1 clock frequency to 25MHz */
  147. val = WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT;
  148. atomic_io_modify(dev->reg + TIMER_CTRL, val, val);
  149. dev->clk_rate = clk_get_rate(dev->clk);
  150. return 0;
  151. }
  152. static int orion_wdt_ping(struct watchdog_device *wdt_dev)
  153. {
  154. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  155. /* Reload watchdog duration */
  156. writel(dev->clk_rate * wdt_dev->timeout,
  157. dev->reg + dev->data->wdt_counter_offset);
  158. if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
  159. writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
  160. dev->reg + TIMER1_VAL_OFF);
  161. return 0;
  162. }
  163. static int armada375_start(struct watchdog_device *wdt_dev)
  164. {
  165. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  166. u32 reg;
  167. /* Set watchdog duration */
  168. writel(dev->clk_rate * wdt_dev->timeout,
  169. dev->reg + dev->data->wdt_counter_offset);
  170. if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
  171. writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
  172. dev->reg + TIMER1_VAL_OFF);
  173. /* Clear the watchdog expiration bit */
  174. atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
  175. /* Enable watchdog timer */
  176. reg = dev->data->wdt_enable_bit;
  177. if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
  178. reg |= TIMER1_ENABLE_BIT;
  179. atomic_io_modify(dev->reg + TIMER_CTRL, reg, reg);
  180. /* Enable reset on watchdog */
  181. reg = readl(dev->rstout);
  182. reg |= dev->data->rstout_enable_bit;
  183. writel(reg, dev->rstout);
  184. atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit, 0);
  185. return 0;
  186. }
  187. static int armada370_start(struct watchdog_device *wdt_dev)
  188. {
  189. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  190. u32 reg;
  191. /* Set watchdog duration */
  192. writel(dev->clk_rate * wdt_dev->timeout,
  193. dev->reg + dev->data->wdt_counter_offset);
  194. /* Clear the watchdog expiration bit */
  195. atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
  196. /* Enable watchdog timer */
  197. reg = dev->data->wdt_enable_bit;
  198. if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
  199. reg |= TIMER1_ENABLE_BIT;
  200. atomic_io_modify(dev->reg + TIMER_CTRL, reg, reg);
  201. /* Enable reset on watchdog */
  202. reg = readl(dev->rstout);
  203. reg |= dev->data->rstout_enable_bit;
  204. writel(reg, dev->rstout);
  205. return 0;
  206. }
  207. static int orion_start(struct watchdog_device *wdt_dev)
  208. {
  209. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  210. /* Set watchdog duration */
  211. writel(dev->clk_rate * wdt_dev->timeout,
  212. dev->reg + dev->data->wdt_counter_offset);
  213. /* Enable watchdog timer */
  214. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
  215. dev->data->wdt_enable_bit);
  216. /* Enable reset on watchdog */
  217. atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
  218. dev->data->rstout_enable_bit);
  219. return 0;
  220. }
  221. static int orion_wdt_start(struct watchdog_device *wdt_dev)
  222. {
  223. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  224. /* There are some per-SoC quirks to handle */
  225. return dev->data->start(wdt_dev);
  226. }
  227. static int orion_stop(struct watchdog_device *wdt_dev)
  228. {
  229. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  230. /* Disable reset on watchdog */
  231. atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
  232. /* Disable watchdog timer */
  233. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
  234. return 0;
  235. }
  236. static int armada375_stop(struct watchdog_device *wdt_dev)
  237. {
  238. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  239. u32 reg, mask;
  240. /* Disable reset on watchdog */
  241. atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit,
  242. dev->data->rstout_mask_bit);
  243. reg = readl(dev->rstout);
  244. reg &= ~dev->data->rstout_enable_bit;
  245. writel(reg, dev->rstout);
  246. /* Disable watchdog timer */
  247. mask = dev->data->wdt_enable_bit;
  248. if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
  249. mask |= TIMER1_ENABLE_BIT;
  250. atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
  251. return 0;
  252. }
  253. static int armada370_stop(struct watchdog_device *wdt_dev)
  254. {
  255. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  256. u32 reg, mask;
  257. /* Disable reset on watchdog */
  258. reg = readl(dev->rstout);
  259. reg &= ~dev->data->rstout_enable_bit;
  260. writel(reg, dev->rstout);
  261. /* Disable watchdog timer */
  262. mask = dev->data->wdt_enable_bit;
  263. if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
  264. mask |= TIMER1_ENABLE_BIT;
  265. atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
  266. return 0;
  267. }
  268. static int orion_wdt_stop(struct watchdog_device *wdt_dev)
  269. {
  270. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  271. return dev->data->stop(wdt_dev);
  272. }
  273. static int orion_enabled(struct orion_watchdog *dev)
  274. {
  275. bool enabled, running;
  276. enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
  277. running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
  278. return enabled && running;
  279. }
  280. static int armada375_enabled(struct orion_watchdog *dev)
  281. {
  282. bool masked, enabled, running;
  283. masked = readl(dev->rstout_mask) & dev->data->rstout_mask_bit;
  284. enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
  285. running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
  286. return !masked && enabled && running;
  287. }
  288. static int orion_wdt_enabled(struct watchdog_device *wdt_dev)
  289. {
  290. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  291. return dev->data->enabled(dev);
  292. }
  293. static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
  294. {
  295. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  296. return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
  297. }
  298. static struct watchdog_info orion_wdt_info = {
  299. .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
  300. .identity = "Orion Watchdog",
  301. };
  302. static const struct watchdog_ops orion_wdt_ops = {
  303. .owner = THIS_MODULE,
  304. .start = orion_wdt_start,
  305. .stop = orion_wdt_stop,
  306. .ping = orion_wdt_ping,
  307. .get_timeleft = orion_wdt_get_timeleft,
  308. };
  309. static irqreturn_t orion_wdt_irq(int irq, void *devid)
  310. {
  311. panic("Watchdog Timeout");
  312. return IRQ_HANDLED;
  313. }
  314. static irqreturn_t orion_wdt_pre_irq(int irq, void *devid)
  315. {
  316. struct orion_watchdog *dev = devid;
  317. atomic_io_modify(dev->reg + TIMER_A370_STATUS,
  318. TIMER1_STATUS_BIT, 0);
  319. watchdog_notify_pretimeout(&dev->wdt);
  320. return IRQ_HANDLED;
  321. }
  322. /*
  323. * The original devicetree binding for this driver specified only
  324. * one memory resource, so in order to keep DT backwards compatibility
  325. * we try to fallback to a hardcoded register address, if the resource
  326. * is missing from the devicetree.
  327. */
  328. static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
  329. phys_addr_t internal_regs)
  330. {
  331. struct resource *res;
  332. phys_addr_t rstout;
  333. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  334. if (res)
  335. return devm_ioremap(&pdev->dev, res->start,
  336. resource_size(res));
  337. rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
  338. WARN(1, FW_BUG "falling back to hardcoded RSTOUT reg %pa\n", &rstout);
  339. return devm_ioremap(&pdev->dev, rstout, 0x4);
  340. }
  341. static const struct orion_watchdog_data orion_data = {
  342. .rstout_enable_bit = BIT(1),
  343. .wdt_enable_bit = BIT(4),
  344. .wdt_counter_offset = 0x24,
  345. .clock_init = orion_wdt_clock_init,
  346. .enabled = orion_enabled,
  347. .start = orion_start,
  348. .stop = orion_stop,
  349. };
  350. static const struct orion_watchdog_data armada370_data = {
  351. .rstout_enable_bit = BIT(8),
  352. .wdt_enable_bit = BIT(8),
  353. .wdt_counter_offset = 0x34,
  354. .clock_init = armada370_wdt_clock_init,
  355. .enabled = orion_enabled,
  356. .start = armada370_start,
  357. .stop = armada370_stop,
  358. };
  359. static const struct orion_watchdog_data armadaxp_data = {
  360. .rstout_enable_bit = BIT(8),
  361. .wdt_enable_bit = BIT(8),
  362. .wdt_counter_offset = 0x34,
  363. .clock_init = armadaxp_wdt_clock_init,
  364. .enabled = orion_enabled,
  365. .start = armada370_start,
  366. .stop = armada370_stop,
  367. };
  368. static const struct orion_watchdog_data armada375_data = {
  369. .rstout_enable_bit = BIT(8),
  370. .rstout_mask_bit = BIT(10),
  371. .wdt_enable_bit = BIT(8),
  372. .wdt_counter_offset = 0x34,
  373. .clock_init = armada375_wdt_clock_init,
  374. .enabled = armada375_enabled,
  375. .start = armada375_start,
  376. .stop = armada375_stop,
  377. };
  378. static const struct orion_watchdog_data armada380_data = {
  379. .rstout_enable_bit = BIT(8),
  380. .rstout_mask_bit = BIT(10),
  381. .wdt_enable_bit = BIT(8),
  382. .wdt_counter_offset = 0x34,
  383. .clock_init = armadaxp_wdt_clock_init,
  384. .enabled = armada375_enabled,
  385. .start = armada375_start,
  386. .stop = armada375_stop,
  387. };
  388. static const struct of_device_id orion_wdt_of_match_table[] = {
  389. {
  390. .compatible = "marvell,orion-wdt",
  391. .data = &orion_data,
  392. },
  393. {
  394. .compatible = "marvell,armada-370-wdt",
  395. .data = &armada370_data,
  396. },
  397. {
  398. .compatible = "marvell,armada-xp-wdt",
  399. .data = &armadaxp_data,
  400. },
  401. {
  402. .compatible = "marvell,armada-375-wdt",
  403. .data = &armada375_data,
  404. },
  405. {
  406. .compatible = "marvell,armada-380-wdt",
  407. .data = &armada380_data,
  408. },
  409. {},
  410. };
  411. MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
  412. static int orion_wdt_get_regs(struct platform_device *pdev,
  413. struct orion_watchdog *dev)
  414. {
  415. struct device_node *node = pdev->dev.of_node;
  416. struct resource *res;
  417. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  418. if (!res)
  419. return -ENODEV;
  420. dev->reg = devm_ioremap(&pdev->dev, res->start,
  421. resource_size(res));
  422. if (!dev->reg)
  423. return -ENOMEM;
  424. /* Each supported compatible has some RSTOUT register quirk */
  425. if (of_device_is_compatible(node, "marvell,orion-wdt")) {
  426. dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
  427. INTERNAL_REGS_MASK);
  428. if (!dev->rstout)
  429. return -ENODEV;
  430. } else if (of_device_is_compatible(node, "marvell,armada-370-wdt") ||
  431. of_device_is_compatible(node, "marvell,armada-xp-wdt")) {
  432. /* Dedicated RSTOUT register, can be requested. */
  433. dev->rstout = devm_platform_ioremap_resource(pdev, 1);
  434. if (IS_ERR(dev->rstout))
  435. return PTR_ERR(dev->rstout);
  436. } else if (of_device_is_compatible(node, "marvell,armada-375-wdt") ||
  437. of_device_is_compatible(node, "marvell,armada-380-wdt")) {
  438. /* Dedicated RSTOUT register, can be requested. */
  439. dev->rstout = devm_platform_ioremap_resource(pdev, 1);
  440. if (IS_ERR(dev->rstout))
  441. return PTR_ERR(dev->rstout);
  442. res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
  443. if (!res)
  444. return -ENODEV;
  445. dev->rstout_mask = devm_ioremap(&pdev->dev, res->start,
  446. resource_size(res));
  447. if (!dev->rstout_mask)
  448. return -ENOMEM;
  449. } else {
  450. return -ENODEV;
  451. }
  452. return 0;
  453. }
  454. static int orion_wdt_probe(struct platform_device *pdev)
  455. {
  456. struct orion_watchdog *dev;
  457. const struct of_device_id *match;
  458. unsigned int wdt_max_duration; /* (seconds) */
  459. int ret, irq;
  460. dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog),
  461. GFP_KERNEL);
  462. if (!dev)
  463. return -ENOMEM;
  464. match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
  465. if (!match)
  466. /* Default legacy match */
  467. match = &orion_wdt_of_match_table[0];
  468. dev->wdt.info = &orion_wdt_info;
  469. dev->wdt.ops = &orion_wdt_ops;
  470. dev->wdt.min_timeout = 1;
  471. dev->data = match->data;
  472. ret = orion_wdt_get_regs(pdev, dev);
  473. if (ret)
  474. return ret;
  475. ret = dev->data->clock_init(pdev, dev);
  476. if (ret) {
  477. dev_err(&pdev->dev, "cannot initialize clock\n");
  478. return ret;
  479. }
  480. wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
  481. dev->wdt.timeout = wdt_max_duration;
  482. dev->wdt.max_timeout = wdt_max_duration;
  483. dev->wdt.parent = &pdev->dev;
  484. watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev);
  485. platform_set_drvdata(pdev, &dev->wdt);
  486. watchdog_set_drvdata(&dev->wdt, dev);
  487. /*
  488. * Let's make sure the watchdog is fully stopped, unless it's
  489. * explicitly enabled. This may be the case if the module was
  490. * removed and re-inserted, or if the bootloader explicitly
  491. * set a running watchdog before booting the kernel.
  492. */
  493. if (!orion_wdt_enabled(&dev->wdt))
  494. orion_wdt_stop(&dev->wdt);
  495. else
  496. set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
  497. /* Request the IRQ only after the watchdog is disabled */
  498. irq = platform_get_irq_optional(pdev, 0);
  499. if (irq > 0) {
  500. /*
  501. * Not all supported platforms specify an interrupt for the
  502. * watchdog, so let's make it optional.
  503. */
  504. ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
  505. pdev->name, dev);
  506. if (ret < 0) {
  507. dev_err(&pdev->dev, "failed to request IRQ\n");
  508. goto disable_clk;
  509. }
  510. }
  511. /* Optional 2nd interrupt for pretimeout */
  512. irq = platform_get_irq_optional(pdev, 1);
  513. if (irq > 0) {
  514. orion_wdt_info.options |= WDIOF_PRETIMEOUT;
  515. ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
  516. 0, pdev->name, dev);
  517. if (ret < 0) {
  518. dev_err(&pdev->dev, "failed to request IRQ\n");
  519. goto disable_clk;
  520. }
  521. }
  522. watchdog_set_nowayout(&dev->wdt, nowayout);
  523. ret = watchdog_register_device(&dev->wdt);
  524. if (ret)
  525. goto disable_clk;
  526. pr_info("Initial timeout %d sec%s\n",
  527. dev->wdt.timeout, nowayout ? ", nowayout" : "");
  528. return 0;
  529. disable_clk:
  530. clk_disable_unprepare(dev->clk);
  531. clk_put(dev->clk);
  532. return ret;
  533. }
  534. static int orion_wdt_remove(struct platform_device *pdev)
  535. {
  536. struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
  537. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  538. watchdog_unregister_device(wdt_dev);
  539. clk_disable_unprepare(dev->clk);
  540. clk_put(dev->clk);
  541. return 0;
  542. }
  543. static void orion_wdt_shutdown(struct platform_device *pdev)
  544. {
  545. struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
  546. orion_wdt_stop(wdt_dev);
  547. }
  548. static struct platform_driver orion_wdt_driver = {
  549. .probe = orion_wdt_probe,
  550. .remove = orion_wdt_remove,
  551. .shutdown = orion_wdt_shutdown,
  552. .driver = {
  553. .name = "orion_wdt",
  554. .of_match_table = orion_wdt_of_match_table,
  555. },
  556. };
  557. module_platform_driver(orion_wdt_driver);
  558. MODULE_AUTHOR("Sylver Bruneau <[email protected]>");
  559. MODULE_DESCRIPTION("Orion Processor Watchdog");
  560. module_param(heartbeat, int, 0);
  561. MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds");
  562. module_param(nowayout, bool, 0);
  563. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  564. __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  565. MODULE_LICENSE("GPL v2");
  566. MODULE_ALIAS("platform:orion_wdt");