aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-18 11:42:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-18 11:42:47 -0500
commit928fce2f6d8152d897790c1a5bbeef5642f69e0e (patch)
treebb8b583bae3b76c94c274bbea47d07c00847f465
parenta5ac1fb13c1265f942ea1d24c43b42d76c1660c2 (diff)
parent94613431619b555ac1299634efabde2ffd0eb2b4 (diff)
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: "This adds the following new drivers: - ImgTec PDC Watchdog Timer Driver, - Mediatek SoC integrated watchdog Add support for BCM5301X, IT8783, NCT6791 and NCT6792 WDT's Add bcm47xx_wdt and da9063 restart handlers and contains overall improvements and fixes" * git://www.linux-watchdog.org/linux-watchdog: watchdog: bcm47xx_wdt.c: allow enabling on BCM5301X arch watchdog: jz4740: Add DT support dt: watchdog: Add DT binding documentation for jz4740 watchdog timer watchdog: dw_wdt: Try to get a 30 second watchdog by default watchdog: dw_wdt: pat the watchdog before enabling it watchdog: w83627hf_wdt: Add support for NCT6791 and NCT6792 watchdog: bcm47xx_wdt.c: add restart handler support watchdog: gpio_wdt: Add "always_running" feature to GPIO watchdog watchdog: da9063: Add restart handler support ARM: mediatek: dts: Add bindings for watchdog watchdog: Add driver for Mediatek watchdog watchdog: Fix omap watchdogs to enable the magic close bit watchdog: rt2880_wdt: minor clean up watchdog: hpwdt: Fix initialization message in hpwdt.c watchdog: it87_wdt: add IT8783 ID watchdog: imx2: Constify struct regmap_config and watchdog_ops DT: watchdog: Add ImgTec PDC Watchdog Timer binding documentation watchdog: ImgTec PDC Watchdog Timer Driver
-rw-r--r--Documentation/devicetree/bindings/watchdog/gpio-wdt.txt5
-rw-r--r--Documentation/devicetree/bindings/watchdog/imgpdc-wdt.txt19
-rw-r--r--Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt12
-rw-r--r--Documentation/devicetree/bindings/watchdog/mtk-wdt.txt13
-rw-r--r--drivers/watchdog/Kconfig25
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/bcm47xx_wdt.c21
-rw-r--r--drivers/watchdog/da9063_wdt.c32
-rw-r--r--drivers/watchdog/dw_wdt.c32
-rw-r--r--drivers/watchdog/gpio_wdt.c37
-rw-r--r--drivers/watchdog/hpwdt.c2
-rw-r--r--drivers/watchdog/imgpdc_wdt.c289
-rw-r--r--drivers/watchdog/imx2_wdt.c4
-rw-r--r--drivers/watchdog/it87_wdt.c6
-rw-r--r--drivers/watchdog/jz4740_wdt.c10
-rw-r--r--drivers/watchdog/mtk_wdt.c251
-rw-r--r--drivers/watchdog/omap_wdt.c2
-rw-r--r--drivers/watchdog/retu_wdt.c2
-rw-r--r--drivers/watchdog/rt2880_wdt.c9
-rw-r--r--drivers/watchdog/twl4030_wdt.c2
-rw-r--r--drivers/watchdog/w83627hf_wdt.c14
-rw-r--r--include/linux/bcm47xx_wdt.h1
22 files changed, 758 insertions, 32 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/gpio-wdt.txt b/Documentation/devicetree/bindings/watchdog/gpio-wdt.txt
index 37afec194949..198794963786 100644
--- a/Documentation/devicetree/bindings/watchdog/gpio-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/gpio-wdt.txt
@@ -13,6 +13,11 @@ Required Properties:
13 by the GPIO flags. 13 by the GPIO flags.
14- hw_margin_ms: Maximum time to reset watchdog circuit (milliseconds). 14- hw_margin_ms: Maximum time to reset watchdog circuit (milliseconds).
15 15
16Optional Properties:
17- always-running: If the watchdog timer cannot be disabled, add this flag to
18 have the driver keep toggling the signal without a client. It will only cease
19 to toggle the signal when the device is open and the timeout elapsed.
20
16Example: 21Example:
17 watchdog: watchdog { 22 watchdog: watchdog {
18 /* ADM706 */ 23 /* ADM706 */
diff --git a/Documentation/devicetree/bindings/watchdog/imgpdc-wdt.txt b/Documentation/devicetree/bindings/watchdog/imgpdc-wdt.txt
new file mode 100644
index 000000000000..b2fa11fd43de
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/imgpdc-wdt.txt
@@ -0,0 +1,19 @@
1*ImgTec PowerDown Controller (PDC) Watchdog Timer (WDT)
2
3Required properties:
4- compatible : Should be "img,pdc-wdt"
5- reg : Should contain WDT registers location and length
6- clocks: Must contain an entry for each entry in clock-names.
7- clock-names: Should contain "wdt" and "sys"; the watchdog counter
8 clock and register interface clock respectively.
9- interrupts : Should contain WDT interrupt
10
11Examples:
12
13watchdog@18102100 {
14 compatible = "img,pdc-wdt";
15 reg = <0x18102100 0x100>;
16 clocks = <&pdc_wdt_clk>, <&sys_clk>;
17 clock-names = "wdt", "sys";
18 interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
19};
diff --git a/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt b/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt
new file mode 100644
index 000000000000..e27763ef0049
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt
@@ -0,0 +1,12 @@
1Ingenic Watchdog Timer (WDT) Controller for JZ4740
2
3Required properties:
4compatible: "ingenic,jz4740-watchdog"
5reg: Register address and length for watchdog registers
6
7Example:
8
9watchdog: jz4740-watchdog@0x10002000 {
10 compatible = "ingenic,jz4740-watchdog";
11 reg = <0x10002000 0x100>;
12};
diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
new file mode 100644
index 000000000000..af9eb5b8a253
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
@@ -0,0 +1,13 @@
1Mediatek SoCs Watchdog timer
2
3Required properties:
4
5- compatible : should be "mediatek,mt6589-wdt"
6- reg : Specifies base physical address and size of the registers.
7
8Example:
9
10wdt: watchdog@010000000 {
11 compatible = "mediatek,mt6589-wdt";
12 reg = <0x10000000 0x18>;
13};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 08f41add1461..16f202350997 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -505,6 +505,16 @@ config MESON_WATCHDOG
505 To compile this driver as a module, choose M here: the 505 To compile this driver as a module, choose M here: the
506 module will be called meson_wdt. 506 module will be called meson_wdt.
507 507
508config MEDIATEK_WATCHDOG
509 tristate "Mediatek SoCs watchdog support"
510 depends on ARCH_MEDIATEK
511 select WATCHDOG_CORE
512 help
513 Say Y here to include support for the watchdog timer
514 in Mediatek SoCs.
515 To compile this driver as a module, choose M here: the
516 module will be called mtk_wdt.
517
508# AVR32 Architecture 518# AVR32 Architecture
509 519
510config AT32AP700X_WDT 520config AT32AP700X_WDT
@@ -1005,6 +1015,8 @@ config W83627HF_WDT
1005 NCT6775 1015 NCT6775
1006 NCT6776 1016 NCT6776
1007 NCT6779 1017 NCT6779
1018 NCT6791
1019 NCT6792
1008 1020
1009 This watchdog simply watches your kernel to make sure it doesn't 1021 This watchdog simply watches your kernel to make sure it doesn't
1010 freeze, and if it does, it reboots your computer after a certain 1022 freeze, and if it does, it reboots your computer after a certain
@@ -1101,7 +1113,7 @@ config ATH79_WDT
1101 1113
1102config BCM47XX_WDT 1114config BCM47XX_WDT
1103 tristate "Broadcom BCM47xx Watchdog Timer" 1115 tristate "Broadcom BCM47xx Watchdog Timer"
1104 depends on BCM47XX 1116 depends on BCM47XX || ARCH_BCM_5301X
1105 select WATCHDOG_CORE 1117 select WATCHDOG_CORE
1106 help 1118 help
1107 Hardware driver for the Broadcom BCM47xx Watchdog Timer. 1119 Hardware driver for the Broadcom BCM47xx Watchdog Timer.
@@ -1235,6 +1247,17 @@ config BCM_KONA_WDT_DEBUG
1235 1247
1236 If in doubt, say 'N'. 1248 If in doubt, say 'N'.
1237 1249
1250config IMGPDC_WDT
1251 tristate "Imagination Technologies PDC Watchdog Timer"
1252 depends on HAS_IOMEM
1253 depends on METAG || MIPS || COMPILE_TEST
1254 help
1255 Driver for Imagination Technologies PowerDown Controller
1256 Watchdog Timer.
1257
1258 To compile this driver as a loadable module, choose M here.
1259 The module will be called imgpdc_wdt.
1260
1238config LANTIQ_WDT 1261config LANTIQ_WDT
1239 tristate "Lantiq SoC watchdog" 1262 tristate "Lantiq SoC watchdog"
1240 depends on LANTIQ 1263 depends on LANTIQ
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index c569ec8f8a76..5c19294d1c30 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
63obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o 63obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
64obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o 64obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
65obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o 65obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
66obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
66 67
67# AVR32 Architecture 68# AVR32 Architecture
68obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o 69obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -142,6 +143,7 @@ obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
142octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o 143octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
143obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o 144obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
144obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o 145obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
146obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
145 147
146# PARISC Architecture 148# PARISC Architecture
147 149
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 9816485f6825..b28a072abf78 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -169,6 +169,17 @@ static int bcm47xx_wdt_notify_sys(struct notifier_block *this,
169 return NOTIFY_DONE; 169 return NOTIFY_DONE;
170} 170}
171 171
172static int bcm47xx_wdt_restart(struct notifier_block *this, unsigned long mode,
173 void *cmd)
174{
175 struct bcm47xx_wdt *wdt;
176
177 wdt = container_of(this, struct bcm47xx_wdt, restart_handler);
178 wdt->timer_set(wdt, 1);
179
180 return NOTIFY_DONE;
181}
182
172static struct watchdog_ops bcm47xx_wdt_soft_ops = { 183static struct watchdog_ops bcm47xx_wdt_soft_ops = {
173 .owner = THIS_MODULE, 184 .owner = THIS_MODULE,
174 .start = bcm47xx_wdt_soft_start, 185 .start = bcm47xx_wdt_soft_start,
@@ -209,15 +220,23 @@ static int bcm47xx_wdt_probe(struct platform_device *pdev)
209 if (ret) 220 if (ret)
210 goto err_timer; 221 goto err_timer;
211 222
212 ret = watchdog_register_device(&wdt->wdd); 223 wdt->restart_handler.notifier_call = &bcm47xx_wdt_restart;
224 wdt->restart_handler.priority = 64;
225 ret = register_restart_handler(&wdt->restart_handler);
213 if (ret) 226 if (ret)
214 goto err_notifier; 227 goto err_notifier;
215 228
229 ret = watchdog_register_device(&wdt->wdd);
230 if (ret)
231 goto err_handler;
232
216 dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n", 233 dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n",
217 timeout, nowayout ? ", nowayout" : "", 234 timeout, nowayout ? ", nowayout" : "",
218 soft ? ", Software Timer" : ""); 235 soft ? ", Software Timer" : "");
219 return 0; 236 return 0;
220 237
238err_handler:
239 unregister_restart_handler(&wdt->restart_handler);
221err_notifier: 240err_notifier:
222 unregister_reboot_notifier(&wdt->notifier); 241 unregister_reboot_notifier(&wdt->notifier);
223err_timer: 242err_timer:
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index 2cd6b2c2dd2a..e2fe2ebdebd4 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -20,6 +20,7 @@
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/mfd/da9063/registers.h> 21#include <linux/mfd/da9063/registers.h>
22#include <linux/mfd/da9063/core.h> 22#include <linux/mfd/da9063/core.h>
23#include <linux/reboot.h>
23#include <linux/regmap.h> 24#include <linux/regmap.h>
24 25
25/* 26/*
@@ -38,6 +39,7 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
38struct da9063_watchdog { 39struct da9063_watchdog {
39 struct da9063 *da9063; 40 struct da9063 *da9063;
40 struct watchdog_device wdtdev; 41 struct watchdog_device wdtdev;
42 struct notifier_block restart_handler;
41}; 43};
42 44
43static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs) 45static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
@@ -119,6 +121,23 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
119 return ret; 121 return ret;
120} 122}
121 123
124static int da9063_wdt_restart_handler(struct notifier_block *this,
125 unsigned long mode, void *cmd)
126{
127 struct da9063_watchdog *wdt = container_of(this,
128 struct da9063_watchdog,
129 restart_handler);
130 int ret;
131
132 ret = regmap_write(wdt->da9063->regmap, DA9063_REG_CONTROL_F,
133 DA9063_SHUTDOWN);
134 if (ret)
135 dev_alert(wdt->da9063->dev, "Failed to shutdown (err = %d)\n",
136 ret);
137
138 return NOTIFY_DONE;
139}
140
122static const struct watchdog_info da9063_watchdog_info = { 141static const struct watchdog_info da9063_watchdog_info = {
123 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 142 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
124 .identity = "DA9063 Watchdog", 143 .identity = "DA9063 Watchdog",
@@ -163,14 +182,25 @@ static int da9063_wdt_probe(struct platform_device *pdev)
163 dev_set_drvdata(&pdev->dev, wdt); 182 dev_set_drvdata(&pdev->dev, wdt);
164 183
165 ret = watchdog_register_device(&wdt->wdtdev); 184 ret = watchdog_register_device(&wdt->wdtdev);
185 if (ret)
186 return ret;
166 187
167 return ret; 188 wdt->restart_handler.notifier_call = da9063_wdt_restart_handler;
189 wdt->restart_handler.priority = 128;
190 ret = register_restart_handler(&wdt->restart_handler);
191 if (ret)
192 dev_err(wdt->da9063->dev,
193 "Failed to register restart handler (err = %d)\n", ret);
194
195 return 0;
168} 196}
169 197
170static int da9063_wdt_remove(struct platform_device *pdev) 198static int da9063_wdt_remove(struct platform_device *pdev)
171{ 199{
172 struct da9063_watchdog *wdt = dev_get_drvdata(&pdev->dev); 200 struct da9063_watchdog *wdt = dev_get_drvdata(&pdev->dev);
173 201
202 unregister_restart_handler(&wdt->restart_handler);
203
174 watchdog_unregister_device(&wdt->wdtdev); 204 watchdog_unregister_device(&wdt->wdtdev);
175 205
176 return 0; 206 return 0;
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index b34a2e4e4e43..d0bb9499d12c 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -51,6 +51,8 @@
51/* The maximum TOP (timeout period) value that can be set in the watchdog. */ 51/* The maximum TOP (timeout period) value that can be set in the watchdog. */
52#define DW_WDT_MAX_TOP 15 52#define DW_WDT_MAX_TOP 15
53 53
54#define DW_WDT_DEFAULT_SECONDS 30
55
54static bool nowayout = WATCHDOG_NOWAYOUT; 56static bool nowayout = WATCHDOG_NOWAYOUT;
55module_param(nowayout, bool, 0); 57module_param(nowayout, bool, 0);
56MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 58MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
@@ -96,6 +98,12 @@ static inline void dw_wdt_set_next_heartbeat(void)
96 dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ; 98 dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ;
97} 99}
98 100
101static void dw_wdt_keepalive(void)
102{
103 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
104 WDOG_COUNTER_RESTART_REG_OFFSET);
105}
106
99static int dw_wdt_set_top(unsigned top_s) 107static int dw_wdt_set_top(unsigned top_s)
100{ 108{
101 int i, top_val = DW_WDT_MAX_TOP; 109 int i, top_val = DW_WDT_MAX_TOP;
@@ -110,21 +118,27 @@ static int dw_wdt_set_top(unsigned top_s)
110 break; 118 break;
111 } 119 }
112 120
113 /* Set the new value in the watchdog. */ 121 /*
122 * Set the new value in the watchdog. Some versions of dw_wdt
123 * have have TOPINIT in the TIMEOUT_RANGE register (as per
124 * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we
125 * effectively get a pat of the watchdog right here.
126 */
114 writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT, 127 writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
115 dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 128 dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
116 129
130 /*
131 * Add an explicit pat to handle versions of the watchdog that
132 * don't have TOPINIT. This won't hurt on versions that have
133 * it.
134 */
135 dw_wdt_keepalive();
136
117 dw_wdt_set_next_heartbeat(); 137 dw_wdt_set_next_heartbeat();
118 138
119 return dw_wdt_top_in_seconds(top_val); 139 return dw_wdt_top_in_seconds(top_val);
120} 140}
121 141
122static void dw_wdt_keepalive(void)
123{
124 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
125 WDOG_COUNTER_RESTART_REG_OFFSET);
126}
127
128static int dw_wdt_restart_handle(struct notifier_block *this, 142static int dw_wdt_restart_handle(struct notifier_block *this,
129 unsigned long mode, void *cmd) 143 unsigned long mode, void *cmd)
130{ 144{
@@ -167,9 +181,9 @@ static int dw_wdt_open(struct inode *inode, struct file *filp)
167 if (!dw_wdt_is_enabled()) { 181 if (!dw_wdt_is_enabled()) {
168 /* 182 /*
169 * The watchdog is not currently enabled. Set the timeout to 183 * The watchdog is not currently enabled. Set the timeout to
170 * the maximum and then start it. 184 * something reasonable and then start it.
171 */ 185 */
172 dw_wdt_set_top(DW_WDT_MAX_TOP); 186 dw_wdt_set_top(DW_WDT_DEFAULT_SECONDS);
173 writel(WDOG_CONTROL_REG_WDT_EN_MASK, 187 writel(WDOG_CONTROL_REG_WDT_EN_MASK,
174 dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); 188 dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
175 } 189 }
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index bbdb19b45332..cbc313d37c59 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -31,6 +31,8 @@ struct gpio_wdt_priv {
31 int gpio; 31 int gpio;
32 bool active_low; 32 bool active_low;
33 bool state; 33 bool state;
34 bool always_running;
35 bool armed;
34 unsigned int hw_algo; 36 unsigned int hw_algo;
35 unsigned int hw_margin; 37 unsigned int hw_margin;
36 unsigned long last_jiffies; 38 unsigned long last_jiffies;
@@ -48,14 +50,20 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv)
48 gpio_direction_input(priv->gpio); 50 gpio_direction_input(priv->gpio);
49} 51}
50 52
51static int gpio_wdt_start(struct watchdog_device *wdd) 53static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv)
52{ 54{
53 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
54
55 priv->state = priv->active_low; 55 priv->state = priv->active_low;
56 gpio_direction_output(priv->gpio, priv->state); 56 gpio_direction_output(priv->gpio, priv->state);
57 priv->last_jiffies = jiffies; 57 priv->last_jiffies = jiffies;
58 mod_timer(&priv->timer, priv->last_jiffies + priv->hw_margin); 58 mod_timer(&priv->timer, priv->last_jiffies + priv->hw_margin);
59}
60
61static int gpio_wdt_start(struct watchdog_device *wdd)
62{
63 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
64
65 gpio_wdt_start_impl(priv);
66 priv->armed = true;
59 67
60 return 0; 68 return 0;
61} 69}
@@ -64,8 +72,11 @@ static int gpio_wdt_stop(struct watchdog_device *wdd)
64{ 72{
65 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); 73 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
66 74
67 mod_timer(&priv->timer, 0); 75 priv->armed = false;
68 gpio_wdt_disable(priv); 76 if (!priv->always_running) {
77 mod_timer(&priv->timer, 0);
78 gpio_wdt_disable(priv);
79 }
69 80
70 return 0; 81 return 0;
71} 82}
@@ -91,8 +102,8 @@ static void gpio_wdt_hwping(unsigned long data)
91 struct watchdog_device *wdd = (struct watchdog_device *)data; 102 struct watchdog_device *wdd = (struct watchdog_device *)data;
92 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); 103 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
93 104
94 if (time_after(jiffies, priv->last_jiffies + 105 if (priv->armed && time_after(jiffies, priv->last_jiffies +
95 msecs_to_jiffies(wdd->timeout * 1000))) { 106 msecs_to_jiffies(wdd->timeout * 1000))) {
96 dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n"); 107 dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n");
97 return; 108 return;
98 } 109 }
@@ -197,6 +208,9 @@ static int gpio_wdt_probe(struct platform_device *pdev)
197 /* Use safe value (1/2 of real timeout) */ 208 /* Use safe value (1/2 of real timeout) */
198 priv->hw_margin = msecs_to_jiffies(hw_margin / 2); 209 priv->hw_margin = msecs_to_jiffies(hw_margin / 2);
199 210
211 priv->always_running = of_property_read_bool(pdev->dev.of_node,
212 "always-running");
213
200 watchdog_set_drvdata(&priv->wdd, priv); 214 watchdog_set_drvdata(&priv->wdd, priv);
201 215
202 priv->wdd.info = &gpio_wdt_ident; 216 priv->wdd.info = &gpio_wdt_ident;
@@ -216,8 +230,15 @@ static int gpio_wdt_probe(struct platform_device *pdev)
216 priv->notifier.notifier_call = gpio_wdt_notify_sys; 230 priv->notifier.notifier_call = gpio_wdt_notify_sys;
217 ret = register_reboot_notifier(&priv->notifier); 231 ret = register_reboot_notifier(&priv->notifier);
218 if (ret) 232 if (ret)
219 watchdog_unregister_device(&priv->wdd); 233 goto error_unregister;
220 234
235 if (priv->always_running)
236 gpio_wdt_start_impl(priv);
237
238 return 0;
239
240error_unregister:
241 watchdog_unregister_device(&priv->wdd);
221 return ret; 242 return ret;
222} 243}
223 244
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 75d2243b94f5..ada3e44f9932 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -745,7 +745,7 @@ static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
745 745
746 dev_info(&dev->dev, 746 dev_info(&dev->dev,
747 "HP Watchdog Timer Driver: NMI decoding initialized" 747 "HP Watchdog Timer Driver: NMI decoding initialized"
748 ", allow kernel dump: %s (default = 0/OFF)\n", 748 ", allow kernel dump: %s (default = 1/ON)\n",
749 (allow_kdump == 0) ? "OFF" : "ON"); 749 (allow_kdump == 0) ? "OFF" : "ON");
750 return 0; 750 return 0;
751 751
diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c
new file mode 100644
index 000000000000..c8def68d9e4c
--- /dev/null
+++ b/drivers/watchdog/imgpdc_wdt.c
@@ -0,0 +1,289 @@
1/*
2 * Imagination Technologies PowerDown Controller Watchdog Timer.
3 *
4 * Copyright (c) 2014 Imagination Technologies Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * Based on drivers/watchdog/sunxi_wdt.c Copyright (c) 2013 Carlo Caione
11 * 2012 Henrik Nordstrom
12 */
13
14#include <linux/clk.h>
15#include <linux/io.h>
16#include <linux/log2.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/slab.h>
20#include <linux/watchdog.h>
21
22/* registers */
23#define PDC_WDT_SOFT_RESET 0x00
24#define PDC_WDT_CONFIG 0x04
25 #define PDC_WDT_CONFIG_ENABLE BIT(31)
26 #define PDC_WDT_CONFIG_DELAY_MASK 0x1f
27
28#define PDC_WDT_TICKLE1 0x08
29#define PDC_WDT_TICKLE1_MAGIC 0xabcd1234
30#define PDC_WDT_TICKLE2 0x0c
31#define PDC_WDT_TICKLE2_MAGIC 0x4321dcba
32
33#define PDC_WDT_TICKLE_STATUS_MASK 0x7
34#define PDC_WDT_TICKLE_STATUS_SHIFT 0
35#define PDC_WDT_TICKLE_STATUS_HRESET 0x0 /* Hard reset */
36#define PDC_WDT_TICKLE_STATUS_TIMEOUT 0x1 /* Timeout */
37#define PDC_WDT_TICKLE_STATUS_TICKLE 0x2 /* Tickled incorrectly */
38#define PDC_WDT_TICKLE_STATUS_SRESET 0x3 /* Soft reset */
39#define PDC_WDT_TICKLE_STATUS_USER 0x4 /* User reset */
40
41/* Timeout values are in seconds */
42#define PDC_WDT_MIN_TIMEOUT 1
43#define PDC_WDT_DEF_TIMEOUT 64
44
45static int heartbeat;
46module_param(heartbeat, int, 0);
47MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
48 "(default = " __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
49
50static bool nowayout = WATCHDOG_NOWAYOUT;
51module_param(nowayout, bool, 0);
52MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
53 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
54
55struct pdc_wdt_dev {
56 struct watchdog_device wdt_dev;
57 struct clk *wdt_clk;
58 struct clk *sys_clk;
59 void __iomem *base;
60};
61
62static int pdc_wdt_keepalive(struct watchdog_device *wdt_dev)
63{
64 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
65
66 writel(PDC_WDT_TICKLE1_MAGIC, wdt->base + PDC_WDT_TICKLE1);
67 writel(PDC_WDT_TICKLE2_MAGIC, wdt->base + PDC_WDT_TICKLE2);
68
69 return 0;
70}
71
72static int pdc_wdt_stop(struct watchdog_device *wdt_dev)
73{
74 unsigned int val;
75 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
76
77 val = readl(wdt->base + PDC_WDT_CONFIG);
78 val &= ~PDC_WDT_CONFIG_ENABLE;
79 writel(val, wdt->base + PDC_WDT_CONFIG);
80
81 /* Must tickle to finish the stop */
82 pdc_wdt_keepalive(wdt_dev);
83
84 return 0;
85}
86
87static int pdc_wdt_set_timeout(struct watchdog_device *wdt_dev,
88 unsigned int new_timeout)
89{
90 unsigned int val;
91 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
92 unsigned long clk_rate = clk_get_rate(wdt->wdt_clk);
93
94 wdt->wdt_dev.timeout = new_timeout;
95
96 val = readl(wdt->base + PDC_WDT_CONFIG) & ~PDC_WDT_CONFIG_DELAY_MASK;
97 val |= order_base_2(new_timeout * clk_rate) - 1;
98 writel(val, wdt->base + PDC_WDT_CONFIG);
99
100 return 0;
101}
102
103/* Start the watchdog timer (delay should already be set) */
104static int pdc_wdt_start(struct watchdog_device *wdt_dev)
105{
106 unsigned int val;
107 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
108
109 val = readl(wdt->base + PDC_WDT_CONFIG);
110 val |= PDC_WDT_CONFIG_ENABLE;
111 writel(val, wdt->base + PDC_WDT_CONFIG);
112
113 return 0;
114}
115
116static struct watchdog_info pdc_wdt_info = {
117 .identity = "IMG PDC Watchdog",
118 .options = WDIOF_SETTIMEOUT |
119 WDIOF_KEEPALIVEPING |
120 WDIOF_MAGICCLOSE,
121};
122
123static const struct watchdog_ops pdc_wdt_ops = {
124 .owner = THIS_MODULE,
125 .start = pdc_wdt_start,
126 .stop = pdc_wdt_stop,
127 .ping = pdc_wdt_keepalive,
128 .set_timeout = pdc_wdt_set_timeout,
129};
130
131static int pdc_wdt_probe(struct platform_device *pdev)
132{
133 int ret, val;
134 unsigned long clk_rate;
135 struct resource *res;
136 struct pdc_wdt_dev *pdc_wdt;
137
138 pdc_wdt = devm_kzalloc(&pdev->dev, sizeof(*pdc_wdt), GFP_KERNEL);
139 if (!pdc_wdt)
140 return -ENOMEM;
141
142 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
143 pdc_wdt->base = devm_ioremap_resource(&pdev->dev, res);
144 if (IS_ERR(pdc_wdt->base))
145 return PTR_ERR(pdc_wdt->base);
146
147 pdc_wdt->sys_clk = devm_clk_get(&pdev->dev, "sys");
148 if (IS_ERR(pdc_wdt->sys_clk)) {
149 dev_err(&pdev->dev, "failed to get the sys clock\n");
150 return PTR_ERR(pdc_wdt->sys_clk);
151 }
152
153 pdc_wdt->wdt_clk = devm_clk_get(&pdev->dev, "wdt");
154 if (IS_ERR(pdc_wdt->wdt_clk)) {
155 dev_err(&pdev->dev, "failed to get the wdt clock\n");
156 return PTR_ERR(pdc_wdt->wdt_clk);
157 }
158
159 ret = clk_prepare_enable(pdc_wdt->sys_clk);
160 if (ret) {
161 dev_err(&pdev->dev, "could not prepare or enable sys clock\n");
162 return ret;
163 }
164
165 ret = clk_prepare_enable(pdc_wdt->wdt_clk);
166 if (ret) {
167 dev_err(&pdev->dev, "could not prepare or enable wdt clock\n");
168 goto disable_sys_clk;
169 }
170
171 /* We use the clock rate to calculate the max timeout */
172 clk_rate = clk_get_rate(pdc_wdt->wdt_clk);
173 if (clk_rate == 0) {
174 dev_err(&pdev->dev, "failed to get clock rate\n");
175 ret = -EINVAL;
176 goto disable_wdt_clk;
177 }
178
179 if (order_base_2(clk_rate) > PDC_WDT_CONFIG_DELAY_MASK + 1) {
180 dev_err(&pdev->dev, "invalid clock rate\n");
181 ret = -EINVAL;
182 goto disable_wdt_clk;
183 }
184
185 if (order_base_2(clk_rate) == 0)
186 pdc_wdt->wdt_dev.min_timeout = PDC_WDT_MIN_TIMEOUT + 1;
187 else
188 pdc_wdt->wdt_dev.min_timeout = PDC_WDT_MIN_TIMEOUT;
189
190 pdc_wdt->wdt_dev.info = &pdc_wdt_info;
191 pdc_wdt->wdt_dev.ops = &pdc_wdt_ops;
192 pdc_wdt->wdt_dev.max_timeout = 1 << PDC_WDT_CONFIG_DELAY_MASK;
193 pdc_wdt->wdt_dev.parent = &pdev->dev;
194
195 ret = watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev);
196 if (ret < 0) {
197 pdc_wdt->wdt_dev.timeout = pdc_wdt->wdt_dev.max_timeout;
198 dev_warn(&pdev->dev,
199 "Initial timeout out of range! setting max timeout\n");
200 }
201
202 pdc_wdt_stop(&pdc_wdt->wdt_dev);
203
204 /* Find what caused the last reset */
205 val = readl(pdc_wdt->base + PDC_WDT_TICKLE1);
206 val = (val & PDC_WDT_TICKLE_STATUS_MASK) >> PDC_WDT_TICKLE_STATUS_SHIFT;
207 switch (val) {
208 case PDC_WDT_TICKLE_STATUS_TICKLE:
209 case PDC_WDT_TICKLE_STATUS_TIMEOUT:
210 pdc_wdt->wdt_dev.bootstatus |= WDIOF_CARDRESET;
211 dev_info(&pdev->dev,
212 "watchdog module last reset due to timeout\n");
213 break;
214 case PDC_WDT_TICKLE_STATUS_HRESET:
215 dev_info(&pdev->dev,
216 "watchdog module last reset due to hard reset\n");
217 break;
218 case PDC_WDT_TICKLE_STATUS_SRESET:
219 dev_info(&pdev->dev,
220 "watchdog module last reset due to soft reset\n");
221 break;
222 case PDC_WDT_TICKLE_STATUS_USER:
223 dev_info(&pdev->dev,
224 "watchdog module last reset due to user reset\n");
225 break;
226 default:
227 dev_info(&pdev->dev,
228 "contains an illegal status code (%08x)\n", val);
229 break;
230 }
231
232 watchdog_set_nowayout(&pdc_wdt->wdt_dev, nowayout);
233
234 platform_set_drvdata(pdev, pdc_wdt);
235 watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
236
237 ret = watchdog_register_device(&pdc_wdt->wdt_dev);
238 if (ret)
239 goto disable_wdt_clk;
240
241 return 0;
242
243disable_wdt_clk:
244 clk_disable_unprepare(pdc_wdt->wdt_clk);
245disable_sys_clk:
246 clk_disable_unprepare(pdc_wdt->sys_clk);
247 return ret;
248}
249
250static void pdc_wdt_shutdown(struct platform_device *pdev)
251{
252 struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev);
253
254 pdc_wdt_stop(&pdc_wdt->wdt_dev);
255}
256
257static int pdc_wdt_remove(struct platform_device *pdev)
258{
259 struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev);
260
261 pdc_wdt_stop(&pdc_wdt->wdt_dev);
262 watchdog_unregister_device(&pdc_wdt->wdt_dev);
263 clk_disable_unprepare(pdc_wdt->wdt_clk);
264 clk_disable_unprepare(pdc_wdt->sys_clk);
265
266 return 0;
267}
268
269static const struct of_device_id pdc_wdt_match[] = {
270 { .compatible = "img,pdc-wdt" },
271 {}
272};
273MODULE_DEVICE_TABLE(of, pdc_wdt_match);
274
275static struct platform_driver pdc_wdt_driver = {
276 .driver = {
277 .name = "imgpdc-wdt",
278 .of_match_table = pdc_wdt_match,
279 },
280 .probe = pdc_wdt_probe,
281 .remove = pdc_wdt_remove,
282 .shutdown = pdc_wdt_shutdown,
283};
284module_platform_driver(pdc_wdt_driver);
285
286MODULE_AUTHOR("Jude Abraham <Jude.Abraham@imgtec.com>");
287MODULE_AUTHOR("Naidu Tellapati <Naidu.Tellapati@imgtec.com>");
288MODULE_DESCRIPTION("Imagination Technologies PDC Watchdog Timer Driver");
289MODULE_LICENSE("GPL v2");
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 5142bbabe027..5e6d808d358a 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -205,7 +205,7 @@ static inline void imx2_wdt_ping_if_active(struct watchdog_device *wdog)
205 } 205 }
206} 206}
207 207
208static struct watchdog_ops imx2_wdt_ops = { 208static const struct watchdog_ops imx2_wdt_ops = {
209 .owner = THIS_MODULE, 209 .owner = THIS_MODULE,
210 .start = imx2_wdt_start, 210 .start = imx2_wdt_start,
211 .stop = imx2_wdt_stop, 211 .stop = imx2_wdt_stop,
@@ -213,7 +213,7 @@ static struct watchdog_ops imx2_wdt_ops = {
213 .set_timeout = imx2_wdt_set_timeout, 213 .set_timeout = imx2_wdt_set_timeout,
214}; 214};
215 215
216static struct regmap_config imx2_wdt_regmap_config = { 216static const struct regmap_config imx2_wdt_regmap_config = {
217 .reg_bits = 16, 217 .reg_bits = 16,
218 .reg_stride = 2, 218 .reg_stride = 2,
219 .val_bits = 16, 219 .val_bits = 16,
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index 0b93739c0106..e54839b12650 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -12,8 +12,8 @@
12 * http://www.ite.com.tw/ 12 * http://www.ite.com.tw/
13 * 13 *
14 * Support of the watchdog timers, which are available on 14 * Support of the watchdog timers, which are available on
15 * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 15 * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726,
16 * and IT8728. 16 * IT8728 and IT8783.
17 * 17 *
18 * This program is free software; you can redistribute it and/or 18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License 19 * modify it under the terms of the GNU General Public License
@@ -87,6 +87,7 @@
87#define IT8721_ID 0x8721 87#define IT8721_ID 0x8721
88#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 88#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
89#define IT8728_ID 0x8728 89#define IT8728_ID 0x8728
90#define IT8783_ID 0x8783
90 91
91/* GPIO Configuration Registers LDN=0x07 */ 92/* GPIO Configuration Registers LDN=0x07 */
92#define WDTCTRL 0x71 93#define WDTCTRL 0x71
@@ -633,6 +634,7 @@ static int __init it87_wdt_init(void)
633 case IT8720_ID: 634 case IT8720_ID:
634 case IT8721_ID: 635 case IT8721_ID:
635 case IT8728_ID: 636 case IT8728_ID:
637 case IT8783_ID:
636 max_units = 65535; 638 max_units = 65535;
637 try_gameport = 0; 639 try_gameport = 0;
638 break; 640 break;
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 18e41afa4da3..4c2cc09c0c57 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -24,6 +24,7 @@
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/of.h>
27 28
28#include <asm/mach-jz4740/timer.h> 29#include <asm/mach-jz4740/timer.h>
29 30
@@ -142,6 +143,14 @@ static const struct watchdog_ops jz4740_wdt_ops = {
142 .set_timeout = jz4740_wdt_set_timeout, 143 .set_timeout = jz4740_wdt_set_timeout,
143}; 144};
144 145
146#ifdef CONFIG_OF
147static const struct of_device_id jz4740_wdt_of_matches[] = {
148 { .compatible = "ingenic,jz4740-watchdog", },
149 { /* sentinel */ }
150};
151MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches)
152#endif
153
145static int jz4740_wdt_probe(struct platform_device *pdev) 154static int jz4740_wdt_probe(struct platform_device *pdev)
146{ 155{
147 struct jz4740_wdt_drvdata *drvdata; 156 struct jz4740_wdt_drvdata *drvdata;
@@ -211,6 +220,7 @@ static struct platform_driver jz4740_wdt_driver = {
211 .remove = jz4740_wdt_remove, 220 .remove = jz4740_wdt_remove,
212 .driver = { 221 .driver = {
213 .name = "jz4740-wdt", 222 .name = "jz4740-wdt",
223 .of_match_table = of_match_ptr(jz4740_wdt_of_matches),
214 }, 224 },
215}; 225};
216 226
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
new file mode 100644
index 000000000000..a87f6df6e85f
--- /dev/null
+++ b/drivers/watchdog/mtk_wdt.c
@@ -0,0 +1,251 @@
1/*
2 * Mediatek Watchdog Driver
3 *
4 * Copyright (C) 2014 Matthias Brugger
5 *
6 * Matthias Brugger <matthias.bgg@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * Based on sunxi_wdt.c
19 */
20
21#include <linux/err.h>
22#include <linux/init.h>
23#include <linux/io.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/of.h>
28#include <linux/platform_device.h>
29#include <linux/types.h>
30#include <linux/watchdog.h>
31#include <linux/notifier.h>
32#include <linux/reboot.h>
33#include <linux/delay.h>
34
35#define WDT_MAX_TIMEOUT 31
36#define WDT_MIN_TIMEOUT 1
37#define WDT_LENGTH_TIMEOUT(n) ((n) << 5)
38
39#define WDT_LENGTH 0x04
40#define WDT_LENGTH_KEY 0x8
41
42#define WDT_RST 0x08
43#define WDT_RST_RELOAD 0x1971
44
45#define WDT_MODE 0x00
46#define WDT_MODE_EN (1 << 0)
47#define WDT_MODE_EXT_POL_LOW (0 << 1)
48#define WDT_MODE_EXT_POL_HIGH (1 << 1)
49#define WDT_MODE_EXRST_EN (1 << 2)
50#define WDT_MODE_IRQ_EN (1 << 3)
51#define WDT_MODE_AUTO_START (1 << 4)
52#define WDT_MODE_DUAL_EN (1 << 6)
53#define WDT_MODE_KEY 0x22000000
54
55#define WDT_SWRST 0x14
56#define WDT_SWRST_KEY 0x1209
57
58#define DRV_NAME "mtk-wdt"
59#define DRV_VERSION "1.0"
60
61static bool nowayout = WATCHDOG_NOWAYOUT;
62static unsigned int timeout = WDT_MAX_TIMEOUT;
63
64struct mtk_wdt_dev {
65 struct watchdog_device wdt_dev;
66 void __iomem *wdt_base;
67 struct notifier_block restart_handler;
68};
69
70static int mtk_reset_handler(struct notifier_block *this, unsigned long mode,
71 void *cmd)
72{
73 struct mtk_wdt_dev *mtk_wdt;
74 void __iomem *wdt_base;
75
76 mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler);
77 wdt_base = mtk_wdt->wdt_base;
78
79 while (1) {
80 writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
81 mdelay(5);
82 }
83
84 return NOTIFY_DONE;
85}
86
87static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
88{
89 struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
90 void __iomem *wdt_base = mtk_wdt->wdt_base;
91
92 iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST);
93
94 return 0;
95}
96
97static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
98 unsigned int timeout)
99{
100 struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
101 void __iomem *wdt_base = mtk_wdt->wdt_base;
102 u32 reg;
103
104 wdt_dev->timeout = timeout;
105
106 /*
107 * One bit is the value of 512 ticks
108 * The clock has 32 KHz
109 */
110 reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY;
111 iowrite32(reg, wdt_base + WDT_LENGTH);
112
113 mtk_wdt_ping(wdt_dev);
114
115 return 0;
116}
117
118static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
119{
120 struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
121 void __iomem *wdt_base = mtk_wdt->wdt_base;
122 u32 reg;
123
124 reg = readl(wdt_base + WDT_MODE);
125 reg &= ~WDT_MODE_EN;
126 iowrite32(reg, wdt_base + WDT_MODE);
127
128 return 0;
129}
130
131static int mtk_wdt_start(struct watchdog_device *wdt_dev)
132{
133 u32 reg;
134 struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
135 void __iomem *wdt_base = mtk_wdt->wdt_base;
136 u32 ret;
137
138 ret = mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
139 if (ret < 0)
140 return ret;
141
142 reg = ioread32(wdt_base + WDT_MODE);
143 reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
144 reg |= (WDT_MODE_EN | WDT_MODE_KEY);
145 iowrite32(reg, wdt_base + WDT_MODE);
146
147 return 0;
148}
149
150static const struct watchdog_info mtk_wdt_info = {
151 .identity = DRV_NAME,
152 .options = WDIOF_SETTIMEOUT |
153 WDIOF_KEEPALIVEPING |
154 WDIOF_MAGICCLOSE,
155};
156
157static const struct watchdog_ops mtk_wdt_ops = {
158 .owner = THIS_MODULE,
159 .start = mtk_wdt_start,
160 .stop = mtk_wdt_stop,
161 .ping = mtk_wdt_ping,
162 .set_timeout = mtk_wdt_set_timeout,
163};
164
165static int mtk_wdt_probe(struct platform_device *pdev)
166{
167 struct mtk_wdt_dev *mtk_wdt;
168 struct resource *res;
169 int err;
170
171 mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL);
172 if (!mtk_wdt)
173 return -ENOMEM;
174
175 platform_set_drvdata(pdev, mtk_wdt);
176
177 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
178 mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res);
179 if (IS_ERR(mtk_wdt->wdt_base))
180 return PTR_ERR(mtk_wdt->wdt_base);
181
182 mtk_wdt->wdt_dev.info = &mtk_wdt_info;
183 mtk_wdt->wdt_dev.ops = &mtk_wdt_ops;
184 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
185 mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT;
186 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
187 mtk_wdt->wdt_dev.parent = &pdev->dev;
188
189 watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev);
190 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout);
191
192 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt);
193
194 mtk_wdt_stop(&mtk_wdt->wdt_dev);
195
196 err = watchdog_register_device(&mtk_wdt->wdt_dev);
197 if (unlikely(err))
198 return err;
199
200 mtk_wdt->restart_handler.notifier_call = mtk_reset_handler;
201 mtk_wdt->restart_handler.priority = 128;
202 err = register_restart_handler(&mtk_wdt->restart_handler);
203 if (err)
204 dev_warn(&pdev->dev,
205 "cannot register restart handler (err=%d)\n", err);
206
207 dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
208 mtk_wdt->wdt_dev.timeout, nowayout);
209
210 return 0;
211}
212
213static int mtk_wdt_remove(struct platform_device *pdev)
214{
215 struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
216
217 unregister_restart_handler(&mtk_wdt->restart_handler);
218
219 watchdog_unregister_device(&mtk_wdt->wdt_dev);
220
221 return 0;
222}
223
224static const struct of_device_id mtk_wdt_dt_ids[] = {
225 { .compatible = "mediatek,mt6589-wdt" },
226 { /* sentinel */ }
227};
228MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
229
230static struct platform_driver mtk_wdt_driver = {
231 .probe = mtk_wdt_probe,
232 .remove = mtk_wdt_remove,
233 .driver = {
234 .name = DRV_NAME,
235 .of_match_table = mtk_wdt_dt_ids,
236 },
237};
238
239module_platform_driver(mtk_wdt_driver);
240
241module_param(timeout, uint, 0);
242MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds");
243
244module_param(nowayout, bool, 0);
245MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
246 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
247
248MODULE_LICENSE("GPL");
249MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>");
250MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver");
251MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 9f2709db61ca..1e6be9e40577 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -189,7 +189,7 @@ static int omap_wdt_set_timeout(struct watchdog_device *wdog,
189} 189}
190 190
191static const struct watchdog_info omap_wdt_info = { 191static const struct watchdog_info omap_wdt_info = {
192 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 192 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
193 .identity = "OMAP Watchdog", 193 .identity = "OMAP Watchdog",
194}; 194};
195 195
diff --git a/drivers/watchdog/retu_wdt.c b/drivers/watchdog/retu_wdt.c
index a7a0695971e4..b7c68e275aeb 100644
--- a/drivers/watchdog/retu_wdt.c
+++ b/drivers/watchdog/retu_wdt.c
@@ -94,7 +94,7 @@ static int retu_wdt_set_timeout(struct watchdog_device *wdog,
94} 94}
95 95
96static const struct watchdog_info retu_wdt_info = { 96static const struct watchdog_info retu_wdt_info = {
97 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 97 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
98 .identity = "Retu watchdog", 98 .identity = "Retu watchdog",
99}; 99};
100 100
diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c
index 11aad5b7aafe..a6f7e2e29beb 100644
--- a/drivers/watchdog/rt2880_wdt.c
+++ b/drivers/watchdog/rt2880_wdt.c
@@ -45,6 +45,7 @@
45static struct clk *rt288x_wdt_clk; 45static struct clk *rt288x_wdt_clk;
46static unsigned long rt288x_wdt_freq; 46static unsigned long rt288x_wdt_freq;
47static void __iomem *rt288x_wdt_base; 47static void __iomem *rt288x_wdt_base;
48static struct reset_control *rt288x_wdt_reset;
48 49
49static bool nowayout = WATCHDOG_NOWAYOUT; 50static bool nowayout = WATCHDOG_NOWAYOUT;
50module_param(nowayout, bool, 0); 51module_param(nowayout, bool, 0);
@@ -151,16 +152,18 @@ static int rt288x_wdt_probe(struct platform_device *pdev)
151 if (IS_ERR(rt288x_wdt_clk)) 152 if (IS_ERR(rt288x_wdt_clk))
152 return PTR_ERR(rt288x_wdt_clk); 153 return PTR_ERR(rt288x_wdt_clk);
153 154
154 device_reset(&pdev->dev); 155 rt288x_wdt_reset = devm_reset_control_get(&pdev->dev, NULL);
156 if (!IS_ERR(rt288x_wdt_reset))
157 reset_control_deassert(rt288x_wdt_reset);
155 158
156 rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE; 159 rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE;
157 160
158 rt288x_wdt_dev.dev = &pdev->dev; 161 rt288x_wdt_dev.dev = &pdev->dev;
159 rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause(); 162 rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause();
160
161 rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq); 163 rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq);
162 rt288x_wdt_dev.timeout = rt288x_wdt_dev.max_timeout;
163 164
165 watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout,
166 &pdev->dev);
164 watchdog_set_nowayout(&rt288x_wdt_dev, nowayout); 167 watchdog_set_nowayout(&rt288x_wdt_dev, nowayout);
165 168
166 ret = watchdog_register_device(&rt288x_wdt_dev); 169 ret = watchdog_register_device(&rt288x_wdt_dev);
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index 12c15903d098..2c1db6fa9a27 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -57,7 +57,7 @@ static int twl4030_wdt_set_timeout(struct watchdog_device *wdt,
57} 57}
58 58
59static const struct watchdog_info twl4030_wdt_info = { 59static const struct watchdog_info twl4030_wdt_info = {
60 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 60 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
61 .identity = "TWL4030 Watchdog", 61 .identity = "TWL4030 Watchdog",
62}; 62};
63 63
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 7165704a3e33..5824e25eebbb 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -50,7 +50,7 @@ static int cr_wdt_control; /* WDT control register */
50 50
51enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf, 51enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
52 w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p, 52 w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg, w83627dhg_p,
53 w83667hg_b, nct6775, nct6776, nct6779 }; 53 w83667hg_b, nct6775, nct6776, nct6779, nct6791, nct6792 };
54 54
55static int timeout; /* in seconds */ 55static int timeout; /* in seconds */
56module_param(timeout, int, 0); 56module_param(timeout, int, 0);
@@ -95,6 +95,8 @@ MODULE_PARM_DESC(early_disable, "Disable watchdog at boot time (default=0)");
95#define NCT6775_ID 0xb4 95#define NCT6775_ID 0xb4
96#define NCT6776_ID 0xc3 96#define NCT6776_ID 0xc3
97#define NCT6779_ID 0xc5 97#define NCT6779_ID 0xc5
98#define NCT6791_ID 0xc8
99#define NCT6792_ID 0xc9
98 100
99#define W83627HF_WDT_TIMEOUT 0xf6 101#define W83627HF_WDT_TIMEOUT 0xf6
100#define W83697HF_WDT_TIMEOUT 0xf4 102#define W83697HF_WDT_TIMEOUT 0xf4
@@ -195,6 +197,8 @@ static int w83627hf_init(struct watchdog_device *wdog, enum chips chip)
195 case nct6775: 197 case nct6775:
196 case nct6776: 198 case nct6776:
197 case nct6779: 199 case nct6779:
200 case nct6791:
201 case nct6792:
198 /* 202 /*
199 * These chips have a fixed WDTO# output pin (W83627UHG), 203 * These chips have a fixed WDTO# output pin (W83627UHG),
200 * or support more than one WDTO# output pin. 204 * or support more than one WDTO# output pin.
@@ -395,6 +399,12 @@ static int wdt_find(int addr)
395 case NCT6779_ID: 399 case NCT6779_ID:
396 ret = nct6779; 400 ret = nct6779;
397 break; 401 break;
402 case NCT6791_ID:
403 ret = nct6791;
404 break;
405 case NCT6792_ID:
406 ret = nct6792;
407 break;
398 case 0xff: 408 case 0xff:
399 ret = -ENODEV; 409 ret = -ENODEV;
400 break; 410 break;
@@ -428,6 +438,8 @@ static int __init wdt_init(void)
428 "NCT6775", 438 "NCT6775",
429 "NCT6776", 439 "NCT6776",
430 "NCT6779", 440 "NCT6779",
441 "NCT6791",
442 "NCT6792",
431 }; 443 };
432 444
433 wdt_io = 0x2e; 445 wdt_io = 0x2e;
diff --git a/include/linux/bcm47xx_wdt.h b/include/linux/bcm47xx_wdt.h
index b708786d4cbf..5582c211f594 100644
--- a/include/linux/bcm47xx_wdt.h
+++ b/include/linux/bcm47xx_wdt.h
@@ -16,6 +16,7 @@ struct bcm47xx_wdt {
16 16
17 struct watchdog_device wdd; 17 struct watchdog_device wdd;
18 struct notifier_block notifier; 18 struct notifier_block notifier;
19 struct notifier_block restart_handler;
19 20
20 struct timer_list soft_timer; 21 struct timer_list soft_timer;
21 atomic_t soft_ticks; 22 atomic_t soft_ticks;