* [PATCH v2 0/2] watchdog: dw_wdt: one bug fix and restart handler support @ 2014-09-23 7:42 Jisheng Zhang 2014-09-23 7:42 ` [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() Jisheng Zhang 2014-09-23 7:42 ` [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support Jisheng Zhang 0 siblings, 2 replies; 7+ messages in thread From: Jisheng Zhang @ 2014-09-23 7:42 UTC (permalink / raw) To: linux-arm-kernel These patches are intend to improve dw_wdt in the following two aspects: Firstly, the TOP_INIT, ie bit 4-7 of the WDOG_TIMEOUT_RANGE_REG_OFFSET register may be zero at reset on some HW, so the timeout period may be very short, thus we will see immediate system reset after openning the watchdog. Fix this problem by also initialising the TOP_INIT when setting TOP. Secondly, the WDT can also be used to reboot the system with the help of recently introduced restart handler. Tested on Marvell BG2Q DMP board. Changes since v1: - add some wait to let the reset catch, suggested by Guenter Roeck - setting TOP_INIT as well when setting TOP in function dw_wdt_set_top to fix the reboot soon issue. Jisheng Zhang (2): watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() watchdog: dw_wdt: add restart handler support drivers/watchdog/dw_wdt.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) -- 2.1.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() 2014-09-23 7:42 [PATCH v2 0/2] watchdog: dw_wdt: one bug fix and restart handler support Jisheng Zhang @ 2014-09-23 7:42 ` Jisheng Zhang 2014-09-23 18:27 ` Guenter Roeck 2014-09-23 7:42 ` [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support Jisheng Zhang 1 sibling, 1 reply; 7+ messages in thread From: Jisheng Zhang @ 2014-09-23 7:42 UTC (permalink / raw) To: linux-arm-kernel The TOP_INIT, ie bit 4-7 of the WDOG_TIMEOUT_RANGE_REG_OFFSET register may be zero, so the timeout period may be very short after initialization is done, thus the system may be reset soon after enabling. We fix this problem by also initialising the TOP_INIT when setting TOP in function dw_wdt_set_top(). Signed-off-by: Jisheng Zhang <jszhang@marvell.com> --- drivers/watchdog/dw_wdt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 9f21029..449c885 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -40,6 +40,7 @@ #define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 +#define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 #define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c #define WDOG_COUNTER_RESTART_KICK_VALUE 0x76 @@ -106,7 +107,8 @@ static int dw_wdt_set_top(unsigned top_s) } /* Set the new value in the watchdog. */ - writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); + writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT, + dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); dw_wdt_set_next_heartbeat(); -- 2.1.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() 2014-09-23 7:42 ` [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() Jisheng Zhang @ 2014-09-23 18:27 ` Guenter Roeck 0 siblings, 0 replies; 7+ messages in thread From: Guenter Roeck @ 2014-09-23 18:27 UTC (permalink / raw) To: linux-arm-kernel On Tue, Sep 23, 2014 at 03:42:11PM +0800, Jisheng Zhang wrote: > The TOP_INIT, ie bit 4-7 of the WDOG_TIMEOUT_RANGE_REG_OFFSET register > may be zero, so the timeout period may be very short after initialization > is done, thus the system may be reset soon after enabling. We fix this > problem by also initialising the TOP_INIT when setting TOP in function > dw_wdt_set_top(). > > Signed-off-by: Jisheng Zhang <jszhang@marvell.com> That should do it. Reviewed-by: Guenter Roeck <linux@roeck-us.net> > --- > drivers/watchdog/dw_wdt.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c > index 9f21029..449c885 100644 > --- a/drivers/watchdog/dw_wdt.c > +++ b/drivers/watchdog/dw_wdt.c > @@ -40,6 +40,7 @@ > #define WDOG_CONTROL_REG_OFFSET 0x00 > #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 > #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 > +#define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 > #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 > #define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c > #define WDOG_COUNTER_RESTART_KICK_VALUE 0x76 > @@ -106,7 +107,8 @@ static int dw_wdt_set_top(unsigned top_s) > } > > /* Set the new value in the watchdog. */ > - writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); > + writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT, > + dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); > > dw_wdt_set_next_heartbeat(); > > -- > 2.1.0 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support 2014-09-23 7:42 [PATCH v2 0/2] watchdog: dw_wdt: one bug fix and restart handler support Jisheng Zhang 2014-09-23 7:42 ` [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() Jisheng Zhang @ 2014-09-23 7:42 ` Jisheng Zhang 2014-09-23 18:31 ` Guenter Roeck 1 sibling, 1 reply; 7+ messages in thread From: Jisheng Zhang @ 2014-09-23 7:42 UTC (permalink / raw) To: linux-arm-kernel The kernel core now provides an API to trigger a system restart. Register with it to support restarting the system via. watchdog. Signed-off-by: Jisheng Zhang <jszhang@marvell.com> --- drivers/watchdog/dw_wdt.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 449c885..9e577a6 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -21,6 +21,7 @@ #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/fs.h> @@ -29,9 +30,11 @@ #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/notifier.h> #include <linux/of.h> #include <linux/pm.h> #include <linux/platform_device.h> +#include <linux/reboot.h> #include <linux/spinlock.h> #include <linux/timer.h> #include <linux/uaccess.h> @@ -63,6 +66,7 @@ static struct { unsigned long next_heartbeat; struct timer_list timer; int expect_close; + struct notifier_block restart_handler; } dw_wdt; static inline int dw_wdt_is_enabled(void) @@ -121,6 +125,26 @@ static void dw_wdt_keepalive(void) WDOG_COUNTER_RESTART_REG_OFFSET); } +static int dw_wdt_restart_handle(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + u32 val; + + writel(0, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); + val = readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); + if (val & WDOG_CONTROL_REG_WDT_EN_MASK) + writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs + + WDOG_COUNTER_RESTART_REG_OFFSET); + else + writel(WDOG_CONTROL_REG_WDT_EN_MASK, + dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); + + /* wait for reset to assert... */ + mdelay(500); + + return NOTIFY_DONE; +} + static void dw_wdt_ping(unsigned long data) { if (time_before(jiffies, dw_wdt.next_heartbeat) || @@ -316,6 +340,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) if (ret) goto out_disable_clk; + dw_wdt.restart_handler.notifier_call = dw_wdt_restart_handle; + dw_wdt.restart_handler.priority = 128; + ret = register_restart_handler(&dw_wdt.restart_handler); + if (ret) + pr_warn("cannot register restart handler\n"); + dw_wdt_set_next_heartbeat(); setup_timer(&dw_wdt.timer, dw_wdt_ping, 0); mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT); @@ -330,6 +360,8 @@ out_disable_clk: static int dw_wdt_drv_remove(struct platform_device *pdev) { + unregister_restart_handler(&dw_wdt.restart_handler); + misc_deregister(&dw_wdt_miscdev); clk_disable_unprepare(dw_wdt.clk); -- 2.1.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support 2014-09-23 7:42 ` [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support Jisheng Zhang @ 2014-09-23 18:31 ` Guenter Roeck 2014-09-24 1:11 ` Jisheng Zhang 0 siblings, 1 reply; 7+ messages in thread From: Guenter Roeck @ 2014-09-23 18:31 UTC (permalink / raw) To: linux-arm-kernel On Tue, Sep 23, 2014 at 03:42:12PM +0800, Jisheng Zhang wrote: > The kernel core now provides an API to trigger a system restart. > Register with it to support restarting the system via. watchdog. > > Signed-off-by: Jisheng Zhang <jszhang@marvell.com> > --- > drivers/watchdog/dw_wdt.c | 32 ++++++++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c > index 449c885..9e577a6 100644 > --- a/drivers/watchdog/dw_wdt.c > +++ b/drivers/watchdog/dw_wdt.c > @@ -21,6 +21,7 @@ > > #include <linux/bitops.h> > #include <linux/clk.h> > +#include <linux/delay.h> > #include <linux/device.h> > #include <linux/err.h> > #include <linux/fs.h> > @@ -29,9 +30,11 @@ > #include <linux/miscdevice.h> > #include <linux/module.h> > #include <linux/moduleparam.h> > +#include <linux/notifier.h> > #include <linux/of.h> > #include <linux/pm.h> > #include <linux/platform_device.h> > +#include <linux/reboot.h> > #include <linux/spinlock.h> > #include <linux/timer.h> > #include <linux/uaccess.h> > @@ -63,6 +66,7 @@ static struct { > unsigned long next_heartbeat; > struct timer_list timer; > int expect_close; > + struct notifier_block restart_handler; > } dw_wdt; > > static inline int dw_wdt_is_enabled(void) > @@ -121,6 +125,26 @@ static void dw_wdt_keepalive(void) > WDOG_COUNTER_RESTART_REG_OFFSET); > } > > +static int dw_wdt_restart_handle(struct notifier_block *this, > + unsigned long mode, void *cmd) > +{ > + u32 val; > + > + writel(0, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); > + val = readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); > + if (val & WDOG_CONTROL_REG_WDT_EN_MASK) > + writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs + > + WDOG_COUNTER_RESTART_REG_OFFSET); > + else > + writel(WDOG_CONTROL_REG_WDT_EN_MASK, > + dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); > + > + /* wait for reset to assert... */ > + mdelay(500); > + > + return NOTIFY_DONE; > +} > + > static void dw_wdt_ping(unsigned long data) > { > if (time_before(jiffies, dw_wdt.next_heartbeat) || > @@ -316,6 +340,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) > if (ret) > goto out_disable_clk; > > + dw_wdt.restart_handler.notifier_call = dw_wdt_restart_handle; > + dw_wdt.restart_handler.priority = 128; > + ret = register_restart_handler(&dw_wdt.restart_handler); > + if (ret) > + pr_warn("cannot register restart handler\n"); Please use dev_warn(&pdev->dev, ...). Thanks, Guenter > + > dw_wdt_set_next_heartbeat(); > setup_timer(&dw_wdt.timer, dw_wdt_ping, 0); > mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT); > @@ -330,6 +360,8 @@ out_disable_clk: > > static int dw_wdt_drv_remove(struct platform_device *pdev) > { > + unregister_restart_handler(&dw_wdt.restart_handler); > + > misc_deregister(&dw_wdt_miscdev); > > clk_disable_unprepare(dw_wdt.clk); > -- > 2.1.0 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support 2014-09-23 18:31 ` Guenter Roeck @ 2014-09-24 1:11 ` Jisheng Zhang 2014-09-24 1:40 ` Guenter Roeck 0 siblings, 1 reply; 7+ messages in thread From: Jisheng Zhang @ 2014-09-24 1:11 UTC (permalink / raw) To: linux-arm-kernel Dear Guenter, On Tue, 23 Sep 2014 11:31:59 -0700 Guenter Roeck <linux@roeck-us.net> wrote: > On Tue, Sep 23, 2014 at 03:42:12PM +0800, Jisheng Zhang wrote: > > The kernel core now provides an API to trigger a system restart. > > Register with it to support restarting the system via. watchdog. > > > > Signed-off-by: Jisheng Zhang <jszhang@marvell.com> > > --- > > drivers/watchdog/dw_wdt.c | 32 ++++++++++++++++++++++++++++++++ > > 1 file changed, 32 insertions(+) > > > > diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c > > index 449c885..9e577a6 100644 > > --- a/drivers/watchdog/dw_wdt.c > > +++ b/drivers/watchdog/dw_wdt.c > > @@ -21,6 +21,7 @@ > > > > #include <linux/bitops.h> > > #include <linux/clk.h> > > +#include <linux/delay.h> > > #include <linux/device.h> > > #include <linux/err.h> > > #include <linux/fs.h> > > @@ -29,9 +30,11 @@ > > #include <linux/miscdevice.h> > > #include <linux/module.h> > > #include <linux/moduleparam.h> > > +#include <linux/notifier.h> > > #include <linux/of.h> > > #include <linux/pm.h> > > #include <linux/platform_device.h> > > +#include <linux/reboot.h> > > #include <linux/spinlock.h> > > #include <linux/timer.h> > > #include <linux/uaccess.h> > > @@ -63,6 +66,7 @@ static struct { > > unsigned long next_heartbeat; > > struct timer_list timer; > > int expect_close; > > + struct notifier_block restart_handler; > > } dw_wdt; > > > > static inline int dw_wdt_is_enabled(void) > > @@ -121,6 +125,26 @@ static void dw_wdt_keepalive(void) > > WDOG_COUNTER_RESTART_REG_OFFSET); > > } > > > > +static int dw_wdt_restart_handle(struct notifier_block *this, > > + unsigned long mode, void *cmd) > > +{ > > + u32 val; > > + > > + writel(0, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); > > + val = readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); > > + if (val & WDOG_CONTROL_REG_WDT_EN_MASK) > > + writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs + > > + WDOG_COUNTER_RESTART_REG_OFFSET); > > + else > > + writel(WDOG_CONTROL_REG_WDT_EN_MASK, > > + dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); > > + > > + /* wait for reset to assert... */ > > + mdelay(500); > > + > > + return NOTIFY_DONE; > > +} > > + > > static void dw_wdt_ping(unsigned long data) > > { > > if (time_before(jiffies, dw_wdt.next_heartbeat) || > > @@ -316,6 +340,12 @@ static int dw_wdt_drv_probe(struct platform_device > > *pdev) if (ret) > > goto out_disable_clk; > > > > + dw_wdt.restart_handler.notifier_call = dw_wdt_restart_handle; > > + dw_wdt.restart_handler.priority = 128; > > + ret = register_restart_handler(&dw_wdt.restart_handler); > > + if (ret) > > + pr_warn("cannot register restart handler\n"); > > Please use dev_warn(&pdev->dev, ...). Yep, that's what I thought when patching the code. But the original source is using pr_*(), so I use pr_warn() to keep unification. Is there any better solution? Thanks for your review, Jisheng > > Thanks, > Guenter > > > + > > dw_wdt_set_next_heartbeat(); > > setup_timer(&dw_wdt.timer, dw_wdt_ping, 0); > > mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT); > > @@ -330,6 +360,8 @@ out_disable_clk: > > > > static int dw_wdt_drv_remove(struct platform_device *pdev) > > { > > + unregister_restart_handler(&dw_wdt.restart_handler); > > + > > misc_deregister(&dw_wdt_miscdev); > > > > clk_disable_unprepare(dw_wdt.clk); > > -- > > 2.1.0 > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-watchdog" > > in the body of a message to majordomo at vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support 2014-09-24 1:11 ` Jisheng Zhang @ 2014-09-24 1:40 ` Guenter Roeck 0 siblings, 0 replies; 7+ messages in thread From: Guenter Roeck @ 2014-09-24 1:40 UTC (permalink / raw) To: linux-arm-kernel On 09/23/2014 06:11 PM, Jisheng Zhang wrote: [ ... ] >>> + dw_wdt.restart_handler.notifier_call = dw_wdt_restart_handle; >>> + dw_wdt.restart_handler.priority = 128; >>> + ret = register_restart_handler(&dw_wdt.restart_handler); >>> + if (ret) >>> + pr_warn("cannot register restart handler\n"); >> >> Please use dev_warn(&pdev->dev, ...). > > Yep, that's what I thought when patching the code. But the original source is > using pr_*(), so I use pr_warn() to keep unification. Is there any better > solution? > Good point. Makes sense, then, to leave that as cleanup. Reviewed-by: Guenter Roeck <linux@roeck-us.net> ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-09-24 1:40 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-09-23 7:42 [PATCH v2 0/2] watchdog: dw_wdt: one bug fix and restart handler support Jisheng Zhang 2014-09-23 7:42 ` [PATCH v2 1/2] watchdog: dw_wdt: initialise TOP_INIT in dw_wdt_set_top() Jisheng Zhang 2014-09-23 18:27 ` Guenter Roeck 2014-09-23 7:42 ` [PATCH v2 2/2] watchdog: dw_wdt: add restart handler support Jisheng Zhang 2014-09-23 18:31 ` Guenter Roeck 2014-09-24 1:11 ` Jisheng Zhang 2014-09-24 1:40 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).