diff options
-rw-r--r-- | drivers/watchdog/sunxi_wdt.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index 693b9d2c6e39..60deb9d304c0 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
@@ -22,9 +23,12 @@ | |||
22 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
23 | #include <linux/of.h> | 24 | #include <linux/of.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/reboot.h> | ||
25 | #include <linux/types.h> | 27 | #include <linux/types.h> |
26 | #include <linux/watchdog.h> | 28 | #include <linux/watchdog.h> |
27 | 29 | ||
30 | #include <asm/system_misc.h> | ||
31 | |||
28 | #define WDT_MAX_TIMEOUT 16 | 32 | #define WDT_MAX_TIMEOUT 16 |
29 | #define WDT_MIN_TIMEOUT 1 | 33 | #define WDT_MIN_TIMEOUT 1 |
30 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) | 34 | #define WDT_MODE_TIMEOUT(n) ((n) << 3) |
@@ -70,6 +74,26 @@ static const int wdt_timeout_map[] = { | |||
70 | [16] = 0xB, /* 16s */ | 74 | [16] = 0xB, /* 16s */ |
71 | }; | 75 | }; |
72 | 76 | ||
77 | static void __iomem *reboot_wdt_base; | ||
78 | |||
79 | static void sun4i_wdt_restart(enum reboot_mode mode, const char *cmd) | ||
80 | { | ||
81 | /* Enable timer and set reset bit in the watchdog */ | ||
82 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, reboot_wdt_base + WDT_MODE); | ||
83 | |||
84 | /* | ||
85 | * Restart the watchdog. The default (and lowest) interval | ||
86 | * value for the watchdog is 0.5s. | ||
87 | */ | ||
88 | writel(WDT_CTRL_RELOAD, reboot_wdt_base + WDT_CTRL); | ||
89 | |||
90 | while (1) { | ||
91 | mdelay(5); | ||
92 | writel(WDT_MODE_EN | WDT_MODE_RST_EN, | ||
93 | reboot_wdt_base + WDT_MODE); | ||
94 | } | ||
95 | } | ||
96 | |||
73 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) | 97 | static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) |
74 | { | 98 | { |
75 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); | 99 | struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); |
@@ -181,6 +205,9 @@ static int sunxi_wdt_probe(struct platform_device *pdev) | |||
181 | if (unlikely(err)) | 205 | if (unlikely(err)) |
182 | return err; | 206 | return err; |
183 | 207 | ||
208 | reboot_wdt_base = sunxi_wdt->wdt_base; | ||
209 | arm_pm_restart = sun4i_wdt_restart; | ||
210 | |||
184 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", | 211 | dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", |
185 | sunxi_wdt->wdt_dev.timeout, nowayout); | 212 | sunxi_wdt->wdt_dev.timeout, nowayout); |
186 | 213 | ||
@@ -191,6 +218,8 @@ static int sunxi_wdt_remove(struct platform_device *pdev) | |||
191 | { | 218 | { |
192 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); | 219 | struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); |
193 | 220 | ||
221 | arm_pm_restart = NULL; | ||
222 | |||
194 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); | 223 | watchdog_unregister_device(&sunxi_wdt->wdt_dev); |
195 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); | 224 | watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL); |
196 | 225 | ||