From bb02c662d641d51ea8c3ae9c828e89fbcfe04ba7 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:20 -0300 Subject: watchdog: orion: Add clock error handling This commit adds a check for clk_prepare_enable success and introduces an error path to disable the clock properly. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index f7722a4..7f19fa3 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -151,17 +151,24 @@ static int orion_wdt_probe(struct platform_device *pdev) clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); - return -ENODEV; + return PTR_ERR(clk); } - clk_prepare_enable(clk); + ret = clk_prepare_enable(clk); + if (ret) + return ret; wdt_tclk = clk_get_rate(clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + if (!res) { + ret = -ENODEV; + goto disable_clk; + } + wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!wdt_reg) - return -ENOMEM; + if (!wdt_reg) { + ret = -ENOMEM; + goto disable_clk; + } wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; @@ -171,14 +178,16 @@ static int orion_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(&orion_wdt, nowayout); ret = watchdog_register_device(&orion_wdt); - if (ret) { - clk_disable_unprepare(clk); - return ret; - } + if (ret) + goto disable_clk; pr_info("Initial timeout %d sec%s\n", orion_wdt.timeout, nowayout ? ", nowayout" : ""); return 0; + +disable_clk: + clk_disable_unprepare(clk); + return ret; } static int orion_wdt_remove(struct platform_device *pdev) -- cgit v1.1 From fc8cd2ac0ad8fca1ca4699da53e635b3e9cc35ed Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:21 -0300 Subject: watchdog: orion: Use atomic access for shared registers Since the timer control register is shared with the clocksource driver, use the recently introduced atomic_io_clear_set() to access such register. Given the watchdog core already provides serialization for all the watchdog ops, this commit allows to remove the spinlock entirely. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 42 +++++------------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 7f19fa3..b92a991 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -46,25 +45,16 @@ static unsigned int wdt_max_duration; /* (seconds) */ static struct clk *clk; static unsigned int wdt_tclk; static void __iomem *wdt_reg; -static DEFINE_SPINLOCK(wdt_lock); static int orion_wdt_ping(struct watchdog_device *wdt_dev) { - spin_lock(&wdt_lock); - /* Reload watchdog duration */ writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); - - spin_unlock(&wdt_lock); return 0; } static int orion_wdt_start(struct watchdog_device *wdt_dev) { - u32 reg; - - spin_lock(&wdt_lock); - /* Set watchdog duration */ writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); @@ -72,48 +62,26 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) writel(~WDT_INT_REQ, BRIDGE_CAUSE); /* Enable watchdog timer */ - reg = readl(wdt_reg + TIMER_CTRL); - reg |= WDT_EN; - writel(reg, wdt_reg + TIMER_CTRL); + atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); /* Enable reset on watchdog */ - reg = readl(RSTOUTn_MASK); - reg |= WDT_RESET_OUT_EN; - writel(reg, RSTOUTn_MASK); - - spin_unlock(&wdt_lock); + atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); return 0; } static int orion_wdt_stop(struct watchdog_device *wdt_dev) { - u32 reg; - - spin_lock(&wdt_lock); - /* Disable reset on watchdog */ - reg = readl(RSTOUTn_MASK); - reg &= ~WDT_RESET_OUT_EN; - writel(reg, RSTOUTn_MASK); + atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0); /* Disable watchdog timer */ - reg = readl(wdt_reg + TIMER_CTRL); - reg &= ~WDT_EN; - writel(reg, wdt_reg + TIMER_CTRL); - - spin_unlock(&wdt_lock); + atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0); return 0; } static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) { - unsigned int time_left; - - spin_lock(&wdt_lock); - time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk; - spin_unlock(&wdt_lock); - - return time_left; + return readl(wdt_reg + WDT_VAL) / wdt_tclk; } static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, -- cgit v1.1 From e0e931ac15bb977dcfd690cdfd6f5b1d44a5155d Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:22 -0300 Subject: watchdog: orion: Remove unused macros These are not used anywhere so it's safe to remove them. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index b92a991..6746033 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -33,8 +33,6 @@ #define WDT_VAL 0x0024 #define WDT_MAX_CYCLE_COUNT 0xffffffff -#define WDT_IN_USE 0 -#define WDT_OK_TO_CLOSE 1 #define WDT_RESET_OUT_EN BIT(1) #define WDT_INT_REQ BIT(3) -- cgit v1.1 From d9d0c53dac7757aa198b1bd60c56f996c78c7ff7 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:23 -0300 Subject: watchdog: orion: Make sure the watchdog is initially stopped Having the watchdog initially fully stopped is important to avoid any spurious watchdog triggers, in case the registers are not in its reset state. If the watchdog rstout is enabled and the watchdog counter running, this initial stop is not performed, to comply with the 'nowayout' parameter. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 6746033..e10b0b1 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -77,6 +77,16 @@ static int orion_wdt_stop(struct watchdog_device *wdt_dev) return 0; } +static int orion_wdt_enabled(void) +{ + bool enabled, running; + + enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN; + running = readl(wdt_reg + TIMER_CTRL) & WDT_EN; + + return enabled && running; +} + static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) { return readl(wdt_reg + WDT_VAL) / wdt_tclk; @@ -142,6 +152,15 @@ static int orion_wdt_probe(struct platform_device *pdev) orion_wdt.max_timeout = wdt_max_duration; watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev); + /* + * Let's make sure the watchdog is fully stopped, unless it's + * explicitly enabled. This may be the case if the module was + * removed and re-insterted, or if the bootloader explicitly + * set a running watchdog before booting the kernel. + */ + if (!orion_wdt_enabled()) + orion_wdt_stop(&orion_wdt); + watchdog_set_nowayout(&orion_wdt, nowayout); ret = watchdog_register_device(&orion_wdt); if (ret) -- cgit v1.1 From e97662e1e28da0da0702db213931d8f9a580970a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:24 -0300 Subject: 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 Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index e10b0b1..b7067ac 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -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) -- cgit v1.1 From 868eb61602d9c020fc9e21b42f3ccd301b36b94d Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:25 -0300 Subject: watchdog: orion: Make RSTOUT register a separate resource In order to support other SoC, it's required to distinguish the 'control' timer register, from the 'rstout' register that enables system reset on watchdog expiration. To prevent a compatibility break, this commit adds a fallback to a hardcoded RSTOUT address. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 47 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index b7067ac..6061b83 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -26,6 +26,12 @@ #include #include +/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ +#define ORION_RSTOUT_MASK_OFFSET 0x20108 + +/* Internal registers can be configured at any 1 MiB aligned address */ +#define INTERNAL_REGS_MASK ~(SZ_1M - 1) + /* * Watchdog timer block registers. */ @@ -44,6 +50,7 @@ static unsigned int wdt_max_duration; /* (seconds) */ static struct clk *clk; static unsigned int wdt_tclk; static void __iomem *wdt_reg; +static void __iomem *wdt_rstout; static int orion_wdt_ping(struct watchdog_device *wdt_dev) { @@ -64,14 +71,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); /* Enable reset on watchdog */ - atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); + atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); return 0; } static int orion_wdt_stop(struct watchdog_device *wdt_dev) { /* Disable reset on watchdog */ - atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0); + atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0); /* Disable watchdog timer */ atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0); @@ -82,7 +89,7 @@ static int orion_wdt_enabled(void) { bool enabled, running; - enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN; + enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN; running = readl(wdt_reg + TIMER_CTRL) & WDT_EN; return enabled && running; @@ -126,6 +133,33 @@ static irqreturn_t orion_wdt_irq(int irq, void *devid) return IRQ_HANDLED; } +/* + * The original devicetree binding for this driver specified only + * one memory resource, so in order to keep DT backwards compatibility + * we try to fallback to a hardcoded register address, if the resource + * is missing from the devicetree. + */ +static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev, + phys_addr_t internal_regs) +{ + struct resource *res; + phys_addr_t rstout; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) + return devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + + /* This workaround works only for "orion-wdt", DT-enabled */ + if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt")) + return NULL; + + rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET; + + WARN(1, FW_BUG "falling back to harcoded RSTOUT reg 0x%x\n", rstout); + return devm_ioremap(&pdev->dev, rstout, 0x4); +} + static int orion_wdt_probe(struct platform_device *pdev) { struct resource *res; @@ -153,6 +187,13 @@ static int orion_wdt_probe(struct platform_device *pdev) goto disable_clk; } + wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start & + INTERNAL_REGS_MASK); + if (!wdt_rstout) { + ret = -ENODEV; + goto disable_clk; + } + wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; orion_wdt.timeout = wdt_max_duration; -- cgit v1.1 From 40edc9813b9bc5d7628b821f1dad7fc87e101066 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:26 -0300 Subject: watchdog: orion: Remove unneeded BRIDGE_CAUSE clear After adding the IRQ request, the BRIDGE_CAUSE bit should be cleared by the bridge interrupt controller. There's no longer a need to do it in the watchdog driver, so we can simply remove it. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 6061b83..65aa655 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -24,7 +24,6 @@ #include #include #include -#include /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ #define ORION_RSTOUT_MASK_OFFSET 0x20108 @@ -42,7 +41,6 @@ #define WDT_MAX_CYCLE_COUNT 0xffffffff #define WDT_RESET_OUT_EN BIT(1) -#define WDT_INT_REQ BIT(3) static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ @@ -64,9 +62,6 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) /* Set watchdog duration */ writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); - /* Clear watchdog timer interrupt */ - writel(~WDT_INT_REQ, BRIDGE_CAUSE); - /* Enable watchdog timer */ atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); -- cgit v1.1 From b89a9c400ba8ab44ff1a734b4f64735550acf083 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:27 -0300 Subject: watchdog: orion: Introduce an orion_watchdog device structure In order to prepare to support multiple compatible-strings, this commit adds a device structure to hold the driver's state. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 114 ++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 45 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 65aa655..9d3a5b9 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -44,55 +44,66 @@ static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ -static unsigned int wdt_max_duration; /* (seconds) */ -static struct clk *clk; -static unsigned int wdt_tclk; -static void __iomem *wdt_reg; -static void __iomem *wdt_rstout; + +struct orion_watchdog { + struct watchdog_device wdt; + void __iomem *reg; + void __iomem *rstout; + unsigned long clk_rate; + struct clk *clk; +}; static int orion_wdt_ping(struct watchdog_device *wdt_dev) { + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); /* Reload watchdog duration */ - writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); + writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); return 0; } static int orion_wdt_start(struct watchdog_device *wdt_dev) { + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + /* Set watchdog duration */ - writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); + writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); /* Enable watchdog timer */ - atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); + atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, WDT_EN); /* Enable reset on watchdog */ - atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); + atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); + return 0; } static int orion_wdt_stop(struct watchdog_device *wdt_dev) { + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + /* Disable reset on watchdog */ - atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0); + atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, 0); /* Disable watchdog timer */ - atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0); + atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, 0); + return 0; } -static int orion_wdt_enabled(void) +static int orion_wdt_enabled(struct orion_watchdog *dev) { bool enabled, running; - enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN; - running = readl(wdt_reg + TIMER_CTRL) & WDT_EN; + enabled = readl(dev->rstout) & WDT_RESET_OUT_EN; + running = readl(dev->reg + TIMER_CTRL) & WDT_EN; return enabled && running; } static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) { - return readl(wdt_reg + WDT_VAL) / wdt_tclk; + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + return readl(dev->reg + WDT_VAL) / dev->clk_rate; } static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, @@ -116,12 +127,6 @@ static const struct watchdog_ops orion_wdt_ops = { .get_timeleft = orion_wdt_get_timeleft, }; -static struct watchdog_device orion_wdt = { - .info = &orion_wdt_info, - .ops = &orion_wdt_ops, - .min_timeout = 1, -}; - static irqreturn_t orion_wdt_irq(int irq, void *devid) { panic("Watchdog Timeout"); @@ -157,18 +162,29 @@ static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev, static int orion_wdt_probe(struct platform_device *pdev) { + struct orion_watchdog *dev; + unsigned int wdt_max_duration; /* (seconds) */ struct resource *res; int ret, irq; - clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { + dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog), + GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->wdt.info = &orion_wdt_info; + dev->wdt.ops = &orion_wdt_ops; + dev->wdt.min_timeout = 1; + + dev->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) { dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); - return PTR_ERR(clk); + return PTR_ERR(dev->clk); } - ret = clk_prepare_enable(clk); + ret = clk_prepare_enable(dev->clk); if (ret) return ret; - wdt_tclk = clk_get_rate(clk); + dev->clk_rate = clk_get_rate(dev->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -176,24 +192,28 @@ static int orion_wdt_probe(struct platform_device *pdev) goto disable_clk; } - wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!wdt_reg) { + dev->reg = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!dev->reg) { ret = -ENOMEM; goto disable_clk; } - wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start & - INTERNAL_REGS_MASK); - if (!wdt_rstout) { + dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & + INTERNAL_REGS_MASK); + if (!dev->rstout) { ret = -ENODEV; goto disable_clk; } - wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; + wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; + + dev->wdt.timeout = wdt_max_duration; + dev->wdt.max_timeout = wdt_max_duration; + watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); - orion_wdt.timeout = wdt_max_duration; - orion_wdt.max_timeout = wdt_max_duration; - watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev); + platform_set_drvdata(pdev, &dev->wdt); + watchdog_set_drvdata(&dev->wdt, dev); /* * Let's make sure the watchdog is fully stopped, unless it's @@ -201,8 +221,8 @@ static int orion_wdt_probe(struct platform_device *pdev) * removed and re-insterted, or if the bootloader explicitly * set a running watchdog before booting the kernel. */ - if (!orion_wdt_enabled()) - orion_wdt_stop(&orion_wdt); + if (!orion_wdt_enabled(dev)) + orion_wdt_stop(&dev->wdt); /* Request the IRQ only after the watchdog is disabled */ irq = platform_get_irq(pdev, 0); @@ -212,37 +232,41 @@ static int orion_wdt_probe(struct platform_device *pdev) * watchdog, so let's make it optional. */ ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0, - pdev->name, &orion_wdt); + pdev->name, dev); 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); + watchdog_set_nowayout(&dev->wdt, nowayout); + ret = watchdog_register_device(&dev->wdt); if (ret) goto disable_clk; pr_info("Initial timeout %d sec%s\n", - orion_wdt.timeout, nowayout ? ", nowayout" : ""); + dev->wdt.timeout, nowayout ? ", nowayout" : ""); return 0; disable_clk: - clk_disable_unprepare(clk); + clk_disable_unprepare(dev->clk); return ret; } static int orion_wdt_remove(struct platform_device *pdev) { - watchdog_unregister_device(&orion_wdt); - clk_disable_unprepare(clk); + struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + + watchdog_unregister_device(wdt_dev); + clk_disable_unprepare(dev->clk); return 0; } static void orion_wdt_shutdown(struct platform_device *pdev) { - orion_wdt_stop(&orion_wdt); + struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); + orion_wdt_stop(wdt_dev); } static const struct of_device_id orion_wdt_of_match_table[] = { -- cgit v1.1 From fc723856a42196779bc9a09f1fef997395f8a7d8 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:28 -0300 Subject: watchdog: orion: Introduce per-compatible of_device_id data This commit adds an orion_watchdog_data structure to hold compatible-data information. This allows to remove the driver-wide definition and to be able to add support for multiple compatible-strings in the future. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 9d3a5b9..b220e34 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -24,6 +24,7 @@ #include #include #include +#include /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ #define ORION_RSTOUT_MASK_OFFSET 0x20108 @@ -35,29 +36,33 @@ * Watchdog timer block registers. */ #define TIMER_CTRL 0x0000 -#define WDT_EN 0x0010 -#define WDT_VAL 0x0024 #define WDT_MAX_CYCLE_COUNT 0xffffffff -#define WDT_RESET_OUT_EN BIT(1) - static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ +struct orion_watchdog_data { + int wdt_counter_offset; + int wdt_enable_bit; + int rstout_enable_bit; +}; + struct orion_watchdog { struct watchdog_device wdt; void __iomem *reg; void __iomem *rstout; unsigned long clk_rate; struct clk *clk; + const struct orion_watchdog_data *data; }; static int orion_wdt_ping(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); /* Reload watchdog duration */ - writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); + writel(dev->clk_rate * wdt_dev->timeout, + dev->reg + dev->data->wdt_counter_offset); return 0; } @@ -66,13 +71,16 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); /* Set watchdog duration */ - writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL); + writel(dev->clk_rate * wdt_dev->timeout, + dev->reg + dev->data->wdt_counter_offset); /* Enable watchdog timer */ - atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, WDT_EN); + atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, + dev->data->wdt_enable_bit); /* Enable reset on watchdog */ - atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); + atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, + dev->data->rstout_enable_bit); return 0; } @@ -82,10 +90,10 @@ static int orion_wdt_stop(struct watchdog_device *wdt_dev) struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); /* Disable reset on watchdog */ - atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, 0); + atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0); /* Disable watchdog timer */ - atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, 0); + atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0); return 0; } @@ -94,8 +102,8 @@ static int orion_wdt_enabled(struct orion_watchdog *dev) { bool enabled, running; - enabled = readl(dev->rstout) & WDT_RESET_OUT_EN; - running = readl(dev->reg + TIMER_CTRL) & WDT_EN; + enabled = readl(dev->rstout) & dev->data->rstout_enable_bit; + running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit; return enabled && running; } @@ -103,7 +111,7 @@ static int orion_wdt_enabled(struct orion_watchdog *dev) static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); - return readl(dev->reg + WDT_VAL) / dev->clk_rate; + return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate; } static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, @@ -160,9 +168,25 @@ static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev, return devm_ioremap(&pdev->dev, rstout, 0x4); } +static const struct orion_watchdog_data orion_data = { + .rstout_enable_bit = BIT(1), + .wdt_enable_bit = BIT(4), + .wdt_counter_offset = 0x24, +}; + +static const struct of_device_id orion_wdt_of_match_table[] = { + { + .compatible = "marvell,orion-wdt", + .data = &orion_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); + static int orion_wdt_probe(struct platform_device *pdev) { struct orion_watchdog *dev; + const struct of_device_id *match; unsigned int wdt_max_duration; /* (seconds) */ struct resource *res; int ret, irq; @@ -172,9 +196,15 @@ static int orion_wdt_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; + match = of_match_device(orion_wdt_of_match_table, &pdev->dev); + if (!match) + /* Default legacy match */ + match = &orion_wdt_of_match_table[0]; + dev->wdt.info = &orion_wdt_info; dev->wdt.ops = &orion_wdt_ops; dev->wdt.min_timeout = 1; + dev->data = match->data; dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { @@ -269,12 +299,6 @@ static void orion_wdt_shutdown(struct platform_device *pdev) orion_wdt_stop(wdt_dev); } -static const struct of_device_id orion_wdt_of_match_table[] = { - { .compatible = "marvell,orion-wdt", }, - {}, -}; -MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); - static struct platform_driver orion_wdt_driver = { .probe = orion_wdt_probe, .remove = orion_wdt_remove, -- cgit v1.1 From 1924227bcda1d1844b8cc54b557b85a1d9b323f0 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:29 -0300 Subject: watchdog: orion: Add per-compatible clock initialization Following the introduction of the compatible-data field, it's now possible to further abstract the clock initialization. This will allow to support SoC with a different clock setup. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index b220e34..b48fd08 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -42,10 +42,14 @@ static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ +struct orion_watchdog; + struct orion_watchdog_data { int wdt_counter_offset; int wdt_enable_bit; int rstout_enable_bit; + int (*clock_init)(struct platform_device *, + struct orion_watchdog *); }; struct orion_watchdog { @@ -57,6 +61,22 @@ struct orion_watchdog { const struct orion_watchdog_data *data; }; +static int orion_wdt_clock_init(struct platform_device *pdev, + struct orion_watchdog *dev) +{ + int ret; + + dev->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); + ret = clk_prepare_enable(dev->clk); + if (ret) + return ret; + + dev->clk_rate = clk_get_rate(dev->clk); + return 0; +} + static int orion_wdt_ping(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); @@ -172,6 +192,7 @@ static const struct orion_watchdog_data orion_data = { .rstout_enable_bit = BIT(1), .wdt_enable_bit = BIT(4), .wdt_counter_offset = 0x24, + .clock_init = orion_wdt_clock_init, }; static const struct of_device_id orion_wdt_of_match_table[] = { @@ -206,34 +227,24 @@ static int orion_wdt_probe(struct platform_device *pdev) dev->wdt.min_timeout = 1; dev->data = match->data; - dev->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); - return PTR_ERR(dev->clk); - } - ret = clk_prepare_enable(dev->clk); - if (ret) - return ret; - dev->clk_rate = clk_get_rate(dev->clk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - goto disable_clk; - } + if (!res) + return -ENODEV; dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!dev->reg) { - ret = -ENOMEM; - goto disable_clk; - } + if (!dev->reg) + return -ENOMEM; dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & INTERNAL_REGS_MASK); - if (!dev->rstout) { - ret = -ENODEV; - goto disable_clk; + if (!dev->rstout) + return -ENODEV; + + ret = dev->data->clock_init(pdev, dev); + if (ret) { + dev_err(&pdev->dev, "cannot initialize clock\n"); + return ret; } wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; -- cgit v1.1 From 490d8e3cbf60cc4ad874caa8c07e67e14c25a1af Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:30 -0300 Subject: watchdog: orion: Add per-compatible watchdog start implementation To handle differences between SoCs this commit adds per-compatible string start() function for the watchdog kick-off. This is preparation work and makes no functionality changes to the current driver. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index b48fd08..3925297 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -50,6 +50,7 @@ struct orion_watchdog_data { int rstout_enable_bit; int (*clock_init)(struct platform_device *, struct orion_watchdog *); + int (*start)(struct watchdog_device *); }; struct orion_watchdog { @@ -86,7 +87,7 @@ static int orion_wdt_ping(struct watchdog_device *wdt_dev) return 0; } -static int orion_wdt_start(struct watchdog_device *wdt_dev) +static int orion_start(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); @@ -105,6 +106,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) return 0; } +static int orion_wdt_start(struct watchdog_device *wdt_dev) +{ + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + + /* There are some per-SoC quirks to handle */ + return dev->data->start(wdt_dev); +} + static int orion_wdt_stop(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); @@ -193,6 +202,7 @@ static const struct orion_watchdog_data orion_data = { .wdt_enable_bit = BIT(4), .wdt_counter_offset = 0x24, .clock_init = orion_wdt_clock_init, + .start = orion_start, }; static const struct of_device_id orion_wdt_of_match_table[] = { -- cgit v1.1 From 463f96e0cdacce5be9bfdd4cc81e7225347cdc31 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:31 -0300 Subject: watchdog: orion: Add support for Armada 370 and Armada XP SoC Using the added infrastructure for handling SoC differences, this commit adds support for the watchdog controller available in Armada 370 and Armada XP SoCs. Also, and because the AXP clock initialization uses of_clk_get_by_name, this commit changes the orion clock initialization to use clk_get() and adds a proper clk_put() on the common exit/error paths. Reviewed-by: Guenter Roeck Tested-by: Sebastian Hesselbarth Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/orion_wdt.c | 106 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 3925297..15321aa 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -36,9 +36,17 @@ * Watchdog timer block registers. */ #define TIMER_CTRL 0x0000 +#define TIMER_A370_STATUS 0x04 #define WDT_MAX_CYCLE_COUNT 0xffffffff +#define WDT_A370_RATIO_MASK(v) ((v) << 16) +#define WDT_A370_RATIO_SHIFT 5 +#define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT) + +#define WDT_AXP_FIXED_ENABLE_BIT BIT(10) +#define WDT_A370_EXPIRED BIT(31) + static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ @@ -67,12 +75,60 @@ static int orion_wdt_clock_init(struct platform_device *pdev, { int ret; - dev->clk = devm_clk_get(&pdev->dev, NULL); + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) return PTR_ERR(dev->clk); ret = clk_prepare_enable(dev->clk); - if (ret) + if (ret) { + clk_put(dev->clk); return ret; + } + + dev->clk_rate = clk_get_rate(dev->clk); + return 0; +} + +static int armada370_wdt_clock_init(struct platform_device *pdev, + struct orion_watchdog *dev) +{ + int ret; + + dev->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); + ret = clk_prepare_enable(dev->clk); + if (ret) { + clk_put(dev->clk); + return ret; + } + + /* Setup watchdog input clock */ + atomic_io_modify(dev->reg + TIMER_CTRL, + WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT), + WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT)); + + dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO; + return 0; +} + +static int armadaxp_wdt_clock_init(struct platform_device *pdev, + struct orion_watchdog *dev) +{ + int ret; + + dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed"); + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); + ret = clk_prepare_enable(dev->clk); + if (ret) { + clk_put(dev->clk); + return ret; + } + + /* Enable the fixed watchdog clock input */ + atomic_io_modify(dev->reg + TIMER_CTRL, + WDT_AXP_FIXED_ENABLE_BIT, + WDT_AXP_FIXED_ENABLE_BIT); dev->clk_rate = clk_get_rate(dev->clk); return 0; @@ -87,6 +143,26 @@ static int orion_wdt_ping(struct watchdog_device *wdt_dev) return 0; } +static int armada370_start(struct watchdog_device *wdt_dev) +{ + struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); + + /* Set watchdog duration */ + writel(dev->clk_rate * wdt_dev->timeout, + dev->reg + dev->data->wdt_counter_offset); + + /* Clear the watchdog expiration bit */ + atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0); + + /* Enable watchdog timer */ + atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, + dev->data->wdt_enable_bit); + + atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, + dev->data->rstout_enable_bit); + return 0; +} + static int orion_start(struct watchdog_device *wdt_dev) { struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); @@ -205,11 +281,35 @@ static const struct orion_watchdog_data orion_data = { .start = orion_start, }; +static const struct orion_watchdog_data armada370_data = { + .rstout_enable_bit = BIT(8), + .wdt_enable_bit = BIT(8), + .wdt_counter_offset = 0x34, + .clock_init = armada370_wdt_clock_init, + .start = armada370_start, +}; + +static const struct orion_watchdog_data armadaxp_data = { + .rstout_enable_bit = BIT(8), + .wdt_enable_bit = BIT(8), + .wdt_counter_offset = 0x34, + .clock_init = armadaxp_wdt_clock_init, + .start = armada370_start, +}; + static const struct of_device_id orion_wdt_of_match_table[] = { { .compatible = "marvell,orion-wdt", .data = &orion_data, }, + { + .compatible = "marvell,armada-370-wdt", + .data = &armada370_data, + }, + { + .compatible = "marvell,armada-xp-wdt", + .data = &armadaxp_data, + }, {}, }; MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); @@ -301,6 +401,7 @@ static int orion_wdt_probe(struct platform_device *pdev) disable_clk: clk_disable_unprepare(dev->clk); + clk_put(dev->clk); return ret; } @@ -311,6 +412,7 @@ static int orion_wdt_remove(struct platform_device *pdev) watchdog_unregister_device(wdt_dev); clk_disable_unprepare(dev->clk); + clk_put(dev->clk); return 0; } -- cgit v1.1 From 59416745bb8cbe32daf805f768418353168b0664 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 10 Feb 2014 20:00:35 -0300 Subject: watchdog: orion: Enable the build on ARCH_MVEBU After adding support for Armada 370/XP SoC let's enable the build on these platforms. Reviewed-by: Guenter Roeck Tested-by: Willy Tarreau Signed-off-by: Ezequiel Garcia Acked-by: Wim Van Sebroeck Tested-By: Jason Gunthorpe Signed-off-by: Jason Cooper --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4c4c566..2dda6c0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -291,7 +291,7 @@ config DAVINCI_WATCHDOG config ORION_WATCHDOG tristate "Orion watchdog" - depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE + depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU select WATCHDOG_CORE help Say Y here if to include support for the watchdog timer -- cgit v1.1