summaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>2014-02-11 00:00:24 +0100
committerJason Cooper <jason@lakedaemon.net>2014-02-22 04:43:12 +0100
commite97662e1e28da0da0702db213931d8f9a580970a (patch)
treecf93017104e32a727ff19fd2ef96233c5f98632e /drivers/watchdog
parentwatchdog: orion: Make sure the watchdog is initially stopped (diff)
downloadlinux-e97662e1e28da0da0702db213931d8f9a580970a.tar.xz
linux-e97662e1e28da0da0702db213931d8f9a580970a.zip
watchdog: orion: Handle the interrupt so it's properly acked
DT-enabled plaforms, where the irqchip driver for the brigde interrupt controller is available, can handle the watchdog IRQ properly. Therefore, request the interrupt and add a dummy handler that merely calls panic(). This is done in order to have an initial 'ack' of the interruption, which clears the watchdog state. Furthermore, since some platforms don't have such IRQ, this commit makes the interrupt specification optional. Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Tested-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Acked-by: Wim Van Sebroeck <wim@iguana.be> Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/orion_wdt.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index e10b0b1accce..b7067acd43a2 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/watchdog.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -119,10 +120,16 @@ static struct watchdog_device orion_wdt = {
.min_timeout = 1,
};
+static irqreturn_t orion_wdt_irq(int irq, void *devid)
+{
+ panic("Watchdog Timeout");
+ return IRQ_HANDLED;
+}
+
static int orion_wdt_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, irq;
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
@@ -161,6 +168,21 @@ static int orion_wdt_probe(struct platform_device *pdev)
if (!orion_wdt_enabled())
orion_wdt_stop(&orion_wdt);
+ /* Request the IRQ only after the watchdog is disabled */
+ irq = platform_get_irq(pdev, 0);
+ if (irq > 0) {
+ /*
+ * Not all supported platforms specify an interrupt for the
+ * watchdog, so let's make it optional.
+ */
+ ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
+ pdev->name, &orion_wdt);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ goto disable_clk;
+ }
+ }
+
watchdog_set_nowayout(&orion_wdt, nowayout);
ret = watchdog_register_device(&orion_wdt);
if (ret)