diff options
author | Fabrizio Castro <fabrizio.castro@bp.renesas.com> | 2018-07-26 18:42:42 +0100 |
---|---|---|
committer | Ben Hutchings <ben.hutchings@codethink.co.uk> | 2018-08-24 19:17:47 +0100 |
commit | 9ddc8b6eb47b66b8cf52d26e49c8a1b01040072d (patch) | |
tree | af863fd728b02d24e0fda87673535cc6de9499a2 | |
parent | b5eaded2fc039eda5d51b984e172137a4ec30bec (diff) | |
download | linux-cip-9ddc8b6eb47b66b8cf52d26e49c8a1b01040072d.tar.gz |
watchdog: renesas_wdt: Add restart handler
On iWave's boards iwg20d and iwg22d the only way to reboot the system is
by means of the watchdog.
This patch adds a restart handler to rwdt_ops, and also makes sure we
keep its priority to the lowest level, in order to not override other
more effective handlers.
Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
(cherry picked from commit 089bcaa87e772beb005068a5ef28c71bb895d01d)
(changed restart handler implementation as .restart is not available
from struct watchdog_ops)
Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Biju Das <biju.das@bp.renesas.com>
[bwh: Delete rogue semi-colon in rwdt_remove()]
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
-rw-r--r-- | drivers/watchdog/renesas_wdt.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c index 87f3e57c9f62c1..22f068f04cde82 100644 --- a/drivers/watchdog/renesas_wdt.c +++ b/drivers/watchdog/renesas_wdt.c @@ -17,6 +17,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/watchdog.h> +#include <linux/notifier.h> +#include <linux/reboot.h> #define RWTCNT 0 #define RWTCSRA 4 @@ -51,6 +53,7 @@ struct rwdt_priv { unsigned long clk_rate; u16 time_left; u8 cks; + struct notifier_block restart_handler; }; static void rwdt_write(struct rwdt_priv *priv, u32 val, unsigned int reg) @@ -114,6 +117,18 @@ static unsigned int rwdt_get_timeleft(struct watchdog_device *wdev) return DIV_BY_CLKS_PER_SEC(priv, 65536 - val); } +static int rwdt_restart(struct notifier_block *this, unsigned long mode, + void *cmd) +{ + struct rwdt_priv *priv = container_of(this, struct rwdt_priv, + restart_handler); + + rwdt_start(&priv->wdev); + rwdt_write(priv, 0xffff, RWTCNT); + + return NOTIFY_DONE; +} + static const struct watchdog_info rwdt_ident = { .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, .identity = "Renesas WDT Watchdog", @@ -194,6 +209,15 @@ static int rwdt_probe(struct platform_device *pdev) if (ret < 0) goto out_pm_disable; + priv->restart_handler.notifier_call = rwdt_restart; + priv->restart_handler.priority = 0; + ret = register_restart_handler(&priv->restart_handler); + if (ret) { + dev_err(&pdev->dev, "can't register restart handler (err=%d)\n", + ret); + priv->restart_handler.notifier_call = NULL; + } + return 0; out_pm_disable: @@ -205,6 +229,8 @@ static int rwdt_remove(struct platform_device *pdev) { struct rwdt_priv *priv = platform_get_drvdata(pdev); + if (priv->restart_handler.notifier_call) + unregister_restart_handler(&priv->restart_handler); watchdog_unregister_device(&priv->wdev); pm_runtime_disable(&pdev->dev); |