orion_wdt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /*
  2. * drivers/watchdog/orion_wdt.c
  3. *
  4. * Watchdog driver for Orion/Kirkwood processors
  5. *
  6. * Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
  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 freqency 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. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
  198. dev->data->wdt_enable_bit);
  199. /* Enable reset on watchdog */
  200. reg = readl(dev->rstout);
  201. reg |= dev->data->rstout_enable_bit;
  202. writel(reg, dev->rstout);
  203. return 0;
  204. }
  205. static int orion_start(struct watchdog_device *wdt_dev)
  206. {
  207. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  208. /* Set watchdog duration */
  209. writel(dev->clk_rate * wdt_dev->timeout,
  210. dev->reg + dev->data->wdt_counter_offset);
  211. /* Enable watchdog timer */
  212. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
  213. dev->data->wdt_enable_bit);
  214. /* Enable reset on watchdog */
  215. atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
  216. dev->data->rstout_enable_bit);
  217. return 0;
  218. }
  219. static int orion_wdt_start(struct watchdog_device *wdt_dev)
  220. {
  221. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  222. /* There are some per-SoC quirks to handle */
  223. return dev->data->start(wdt_dev);
  224. }
  225. static int orion_stop(struct watchdog_device *wdt_dev)
  226. {
  227. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  228. /* Disable reset on watchdog */
  229. atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
  230. /* Disable watchdog timer */
  231. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
  232. return 0;
  233. }
  234. static int armada375_stop(struct watchdog_device *wdt_dev)
  235. {
  236. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  237. u32 reg, mask;
  238. /* Disable reset on watchdog */
  239. atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit,
  240. dev->data->rstout_mask_bit);
  241. reg = readl(dev->rstout);
  242. reg &= ~dev->data->rstout_enable_bit;
  243. writel(reg, dev->rstout);
  244. /* Disable watchdog timer */
  245. mask = dev->data->wdt_enable_bit;
  246. if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
  247. mask |= TIMER1_ENABLE_BIT;
  248. atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
  249. return 0;
  250. }
  251. static int armada370_stop(struct watchdog_device *wdt_dev)
  252. {
  253. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  254. u32 reg;
  255. /* Disable reset on watchdog */
  256. reg = readl(dev->rstout);
  257. reg &= ~dev->data->rstout_enable_bit;
  258. writel(reg, dev->rstout);
  259. /* Disable watchdog timer */
  260. atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
  261. return 0;
  262. }
  263. static int orion_wdt_stop(struct watchdog_device *wdt_dev)
  264. {
  265. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  266. return dev->data->stop(wdt_dev);
  267. }
  268. static int orion_enabled(struct orion_watchdog *dev)
  269. {
  270. bool enabled, running;
  271. enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
  272. running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
  273. return enabled && running;
  274. }
  275. static int armada375_enabled(struct orion_watchdog *dev)
  276. {
  277. bool masked, enabled, running;
  278. masked = readl(dev->rstout_mask) & dev->data->rstout_mask_bit;
  279. enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
  280. running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
  281. return !masked && enabled && running;
  282. }
  283. static int orion_wdt_enabled(struct watchdog_device *wdt_dev)
  284. {
  285. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  286. return dev->data->enabled(dev);
  287. }
  288. static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
  289. {
  290. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  291. return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
  292. }
  293. static struct watchdog_info orion_wdt_info = {
  294. .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
  295. .identity = "Orion Watchdog",
  296. };
  297. static const struct watchdog_ops orion_wdt_ops = {
  298. .owner = THIS_MODULE,
  299. .start = orion_wdt_start,
  300. .stop = orion_wdt_stop,
  301. .ping = orion_wdt_ping,
  302. .get_timeleft = orion_wdt_get_timeleft,
  303. };
  304. static irqreturn_t orion_wdt_irq(int irq, void *devid)
  305. {
  306. panic("Watchdog Timeout");
  307. return IRQ_HANDLED;
  308. }
  309. static irqreturn_t orion_wdt_pre_irq(int irq, void *devid)
  310. {
  311. struct orion_watchdog *dev = devid;
  312. atomic_io_modify(dev->reg + TIMER_A370_STATUS,
  313. TIMER1_STATUS_BIT, 0);
  314. watchdog_notify_pretimeout(&dev->wdt);
  315. return IRQ_HANDLED;
  316. }
  317. /*
  318. * The original devicetree binding for this driver specified only
  319. * one memory resource, so in order to keep DT backwards compatibility
  320. * we try to fallback to a hardcoded register address, if the resource
  321. * is missing from the devicetree.
  322. */
  323. static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
  324. phys_addr_t internal_regs)
  325. {
  326. struct resource *res;
  327. phys_addr_t rstout;
  328. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  329. if (res)
  330. return devm_ioremap(&pdev->dev, res->start,
  331. resource_size(res));
  332. rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
  333. WARN(1, FW_BUG "falling back to hardcoded RSTOUT reg %pa\n", &rstout);
  334. return devm_ioremap(&pdev->dev, rstout, 0x4);
  335. }
  336. static const struct orion_watchdog_data orion_data = {
  337. .rstout_enable_bit = BIT(1),
  338. .wdt_enable_bit = BIT(4),
  339. .wdt_counter_offset = 0x24,
  340. .clock_init = orion_wdt_clock_init,
  341. .enabled = orion_enabled,
  342. .start = orion_start,
  343. .stop = orion_stop,
  344. };
  345. static const struct orion_watchdog_data armada370_data = {
  346. .rstout_enable_bit = BIT(8),
  347. .wdt_enable_bit = BIT(8),
  348. .wdt_counter_offset = 0x34,
  349. .clock_init = armada370_wdt_clock_init,
  350. .enabled = orion_enabled,
  351. .start = armada370_start,
  352. .stop = armada370_stop,
  353. };
  354. static const struct orion_watchdog_data armadaxp_data = {
  355. .rstout_enable_bit = BIT(8),
  356. .wdt_enable_bit = BIT(8),
  357. .wdt_counter_offset = 0x34,
  358. .clock_init = armadaxp_wdt_clock_init,
  359. .enabled = orion_enabled,
  360. .start = armada370_start,
  361. .stop = armada370_stop,
  362. };
  363. static const struct orion_watchdog_data armada375_data = {
  364. .rstout_enable_bit = BIT(8),
  365. .rstout_mask_bit = BIT(10),
  366. .wdt_enable_bit = BIT(8),
  367. .wdt_counter_offset = 0x34,
  368. .clock_init = armada375_wdt_clock_init,
  369. .enabled = armada375_enabled,
  370. .start = armada375_start,
  371. .stop = armada375_stop,
  372. };
  373. static const struct orion_watchdog_data armada380_data = {
  374. .rstout_enable_bit = BIT(8),
  375. .rstout_mask_bit = BIT(10),
  376. .wdt_enable_bit = BIT(8),
  377. .wdt_counter_offset = 0x34,
  378. .clock_init = armadaxp_wdt_clock_init,
  379. .enabled = armada375_enabled,
  380. .start = armada375_start,
  381. .stop = armada375_stop,
  382. };
  383. static const struct of_device_id orion_wdt_of_match_table[] = {
  384. {
  385. .compatible = "marvell,orion-wdt",
  386. .data = &orion_data,
  387. },
  388. {
  389. .compatible = "marvell,armada-370-wdt",
  390. .data = &armada370_data,
  391. },
  392. {
  393. .compatible = "marvell,armada-xp-wdt",
  394. .data = &armadaxp_data,
  395. },
  396. {
  397. .compatible = "marvell,armada-375-wdt",
  398. .data = &armada375_data,
  399. },
  400. {
  401. .compatible = "marvell,armada-380-wdt",
  402. .data = &armada380_data,
  403. },
  404. {},
  405. };
  406. MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
  407. static int orion_wdt_get_regs(struct platform_device *pdev,
  408. struct orion_watchdog *dev)
  409. {
  410. struct device_node *node = pdev->dev.of_node;
  411. struct resource *res;
  412. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  413. if (!res)
  414. return -ENODEV;
  415. dev->reg = devm_ioremap(&pdev->dev, res->start,
  416. resource_size(res));
  417. if (!dev->reg)
  418. return -ENOMEM;
  419. /* Each supported compatible has some RSTOUT register quirk */
  420. if (of_device_is_compatible(node, "marvell,orion-wdt")) {
  421. dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
  422. INTERNAL_REGS_MASK);
  423. if (!dev->rstout)
  424. return -ENODEV;
  425. } else if (of_device_is_compatible(node, "marvell,armada-370-wdt") ||
  426. of_device_is_compatible(node, "marvell,armada-xp-wdt")) {
  427. /* Dedicated RSTOUT register, can be requested. */
  428. dev->rstout = devm_platform_ioremap_resource(pdev, 1);
  429. if (IS_ERR(dev->rstout))
  430. return PTR_ERR(dev->rstout);
  431. } else if (of_device_is_compatible(node, "marvell,armada-375-wdt") ||
  432. of_device_is_compatible(node, "marvell,armada-380-wdt")) {
  433. /* Dedicated RSTOUT register, can be requested. */
  434. dev->rstout = devm_platform_ioremap_resource(pdev, 1);
  435. if (IS_ERR(dev->rstout))
  436. return PTR_ERR(dev->rstout);
  437. res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
  438. if (!res)
  439. return -ENODEV;
  440. dev->rstout_mask = devm_ioremap(&pdev->dev, res->start,
  441. resource_size(res));
  442. if (!dev->rstout_mask)
  443. return -ENOMEM;
  444. } else {
  445. return -ENODEV;
  446. }
  447. return 0;
  448. }
  449. static int orion_wdt_probe(struct platform_device *pdev)
  450. {
  451. struct orion_watchdog *dev;
  452. const struct of_device_id *match;
  453. unsigned int wdt_max_duration; /* (seconds) */
  454. int ret, irq;
  455. dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog),
  456. GFP_KERNEL);
  457. if (!dev)
  458. return -ENOMEM;
  459. match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
  460. if (!match)
  461. /* Default legacy match */
  462. match = &orion_wdt_of_match_table[0];
  463. dev->wdt.info = &orion_wdt_info;
  464. dev->wdt.ops = &orion_wdt_ops;
  465. dev->wdt.min_timeout = 1;
  466. dev->data = match->data;
  467. ret = orion_wdt_get_regs(pdev, dev);
  468. if (ret)
  469. return ret;
  470. ret = dev->data->clock_init(pdev, dev);
  471. if (ret) {
  472. dev_err(&pdev->dev, "cannot initialize clock\n");
  473. return ret;
  474. }
  475. wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
  476. dev->wdt.timeout = wdt_max_duration;
  477. dev->wdt.max_timeout = wdt_max_duration;
  478. dev->wdt.parent = &pdev->dev;
  479. watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev);
  480. platform_set_drvdata(pdev, &dev->wdt);
  481. watchdog_set_drvdata(&dev->wdt, dev);
  482. /*
  483. * Let's make sure the watchdog is fully stopped, unless it's
  484. * explicitly enabled. This may be the case if the module was
  485. * removed and re-inserted, or if the bootloader explicitly
  486. * set a running watchdog before booting the kernel.
  487. */
  488. if (!orion_wdt_enabled(&dev->wdt))
  489. orion_wdt_stop(&dev->wdt);
  490. else
  491. set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
  492. /* Request the IRQ only after the watchdog is disabled */
  493. irq = platform_get_irq_optional(pdev, 0);
  494. if (irq > 0) {
  495. /*
  496. * Not all supported platforms specify an interrupt for the
  497. * watchdog, so let's make it optional.
  498. */
  499. ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
  500. pdev->name, dev);
  501. if (ret < 0) {
  502. dev_err(&pdev->dev, "failed to request IRQ\n");
  503. goto disable_clk;
  504. }
  505. }
  506. /* Optional 2nd interrupt for pretimeout */
  507. irq = platform_get_irq_optional(pdev, 1);
  508. if (irq > 0) {
  509. orion_wdt_info.options |= WDIOF_PRETIMEOUT;
  510. ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
  511. 0, pdev->name, dev);
  512. if (ret < 0) {
  513. dev_err(&pdev->dev, "failed to request IRQ\n");
  514. goto disable_clk;
  515. }
  516. }
  517. watchdog_set_nowayout(&dev->wdt, nowayout);
  518. ret = watchdog_register_device(&dev->wdt);
  519. if (ret)
  520. goto disable_clk;
  521. pr_info("Initial timeout %d sec%s\n",
  522. dev->wdt.timeout, nowayout ? ", nowayout" : "");
  523. return 0;
  524. disable_clk:
  525. clk_disable_unprepare(dev->clk);
  526. clk_put(dev->clk);
  527. return ret;
  528. }
  529. static int orion_wdt_remove(struct platform_device *pdev)
  530. {
  531. struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
  532. struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
  533. watchdog_unregister_device(wdt_dev);
  534. clk_disable_unprepare(dev->clk);
  535. clk_put(dev->clk);
  536. return 0;
  537. }
  538. static void orion_wdt_shutdown(struct platform_device *pdev)
  539. {
  540. struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
  541. orion_wdt_stop(wdt_dev);
  542. }
  543. static struct platform_driver orion_wdt_driver = {
  544. .probe = orion_wdt_probe,
  545. .remove = orion_wdt_remove,
  546. .shutdown = orion_wdt_shutdown,
  547. .driver = {
  548. .name = "orion_wdt",
  549. .of_match_table = orion_wdt_of_match_table,
  550. },
  551. };
  552. module_platform_driver(orion_wdt_driver);
  553. MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
  554. MODULE_DESCRIPTION("Orion Processor Watchdog");
  555. module_param(heartbeat, int, 0);
  556. MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds");
  557. module_param(nowayout, bool, 0);
  558. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  559. __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  560. MODULE_LICENSE("GPL v2");
  561. MODULE_ALIAS("platform:orion_wdt");