diff options
| author | Guenter Roeck <linux@roeck-us.net> | 2014-09-25 20:03:17 -0400 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2014-09-26 03:00:42 -0400 |
| commit | d20a1d90acf61f69a6474fce7e9656d36bd8ba80 (patch) | |
| tree | 1287181ec40f4bc9e06733a33662b388f5848c24 | |
| parent | 87ffc69e4b05f6e98e2b7a42f23132ed3662450a (diff) | |
watchdog: sunxi: register restart handler with kernel restart handler
The kernel core now provides an API to trigger a system restart. Register
with it instead of setting arm_pm_restart.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jonas Jensen <jonas.jensen@gmail.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
| -rw-r--r-- | drivers/watchdog/sunxi_wdt.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index 60deb9d304c0..480bb557f353 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c | |||
| @@ -21,14 +21,13 @@ | |||
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
| 24 | #include <linux/notifier.h> | ||
| 24 | #include <linux/of.h> | 25 | #include <linux/of.h> |
| 25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 26 | #include <linux/reboot.h> | 27 | #include <linux/reboot.h> |
| 27 | #include <linux/types.h> | 28 | #include <linux/types.h> |
| 28 | #include <linux/watchdog.h> | 29 | #include <linux/watchdog.h> |
| 29 | 30 | ||
| 30 | #include <asm/system_misc.h> | ||
| 31 | |||
| 32 | #define WDT_MAX_TIMEOUT 16 | 31 | #define WDT_MAX_TIMEOUT 16 |
| 33 | #define WDT_MIN_TIMEOUT 1 | 32 | #define WDT_MIN_TIMEOUT 1 |
| 34 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) | 33 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) |
| @@ -50,6 +49,7 @@ static unsigned int timeout = WDT_MAX_TIMEOUT; | |||
| 50 | struct sunxi_wdt_dev { | 49 | struct sunxi_wdt_dev { |
| 51 | struct watchdog_device wdt_dev; | 50 | struct watchdog_device wdt_dev; |
| 52 | void __iomem *wdt_base; | 51 | void __iomem *wdt_base; |
| 52 | struct notifier_block restart_handler; | ||
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* | 55 | /* |
| @@ -74,24 +74,29 @@ static const int wdt_timeout_map[] = { | |||
| 74 | [16] = 0xB, /* 16s */ | 74 | [16] = 0xB, /* 16s */ |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | static void __iomem *reboot_wdt_base; | ||
| 78 | 77 | ||
| 79 | static void sun4i_wdt_restart(enum reboot_mode mode, const char *cmd) | 78 | static int sunxi_restart_handle(struct notifier_block *this, unsigned long mode, |
| 79 | void *cmd) | ||
| 80 | { | 80 | { |
| 81 | struct sunxi_wdt_dev *sunxi_wdt = container_of(this, | ||
| 82 | struct sunxi_wdt_dev, | ||
| 83 | restart_handler); | ||
| 84 | void __iomem *wdt_base = sunxi_wdt->wdt_base; | ||
| 85 | |||
| 81 | /* Enable timer and set reset bit in the watchdog */ | 86 | /* Enable timer and set reset bit in the watchdog */ |
| 82 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, reboot_wdt_base + WDT_MODE); | 87 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, wdt_base + WDT_MODE); |
| 83 | 88 | ||
| 84 | /* | 89 | /* |
| 85 | * Restart the watchdog. The default (and lowest) interval | 90 | * Restart the watchdog. The default (and lowest) interval |
| 86 | * value for the watchdog is 0.5s. | 91 | * value for the watchdog is 0.5s. |
| 87 | */ | 92 | */ |
| 88 | writel(WDT_CTRL_RELOAD, reboot_wdt_base + WDT_CTRL); | 93 | writel(WDT_CTRL_RELOAD, wdt_base + WDT_CTRL); |
| 89 | 94 | ||
| 90 | while (1) { | 95 | while (1) { |
| 91 | mdelay(5); | 96 | mdelay(5); |
| 92 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, | 97 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, wdt_base + WDT_MODE); |
| 93 | reboot_wdt_base + WDT_MODE); | ||
| 94 | } | 98 | } |
| 99 | return NOTIFY_DONE; | ||
| 95 | } | 100 | } |
| 96 | 101 | ||
| 97 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) | 102 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) |
| @@ -205,8 +210,12 @@ static int sunxi_wdt_probe(struct platform_device *pdev) | |||
| 205 | if (unlikely(err)) | 210 | if (unlikely(err)) |
| 206 | return err; | 211 | return err; |
| 207 | 212 | ||
| 208 | reboot_wdt_base = sunxi_wdt->wdt_base; | 213 | sunxi_wdt->restart_handler.notifier_call = sunxi_restart_handle; |
| 209 | arm_pm_restart = sun4i_wdt_restart; | 214 | sunxi_wdt->restart_handler.priority = 128; |
| 215 | err = register_restart_handler(&sunxi_wdt->restart_handler); | ||
| 216 | if (err) | ||
| 217 | dev_err(&pdev->dev, | ||
| 218 | "cannot register restart handler (err=%d)\n", err); | ||
| 210 | 219 | ||
| 211 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", | 220 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", |
| 212 | sunxi_wdt->wdt_dev.timeout, nowayout); | 221 | sunxi_wdt->wdt_dev.timeout, nowayout); |
| @@ -218,7 +227,7 @@ static int sunxi_wdt_remove(struct platform_device *pdev) | |||
| 218 | { | 227 | { |
| 219 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); | 228 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); |
| 220 | 229 | ||
| 221 | arm_pm_restart = NULL; | 230 | unregister_restart_handler(&sunxi_wdt->restart_handler); |
| 222 | 231 | ||
| 223 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); | 232 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); |
| 224 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); | 233 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); |
