aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-07-01 22:33:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-01 22:33:16 -0400
commit93899e39e86bfc021a190a9c26e8e516561f2756 (patch)
treec01fe48641d2a81acfa083748ef267a9607e84af /drivers/watchdog
parent5f1201d515819e7cfaaac3f0a30ff7b556261386 (diff)
parentb2102eb36e7909c779e46f66595fda75aa219f4c (diff)
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: "This contains: - new driver for ST's LPC Watchdog - new driver for Conexant Digicolor CX92755 SoC - new driver for DA9062 watchdog - Addition of the watchdog registration deferral mechanism - several improvements on omap_wdt - several improvements and reboot-support for imgpdc_wdt - max63xx_wdt improvements - imx2_wdt improvements - dw_wdt improvements - and other small improvements and fixes" * git://www.linux-watchdog.org/linux-watchdog: (37 commits) watchdog: omap_wdt: early_enable module parameter watchdog: gpio_wdt: Add option for early registration watchdog: watchdog_core: Add watchdog registration deferral mechanism watchdog: max63xx: dynamically allocate device watchdog: imx2_wdt: Disable previously acquired clock on error path watchdog: imx2_wdt: Check for clk_prepare_enable() error watchdog: hpwdt: Add support for WDIOC_SETOPTIONS watchdog: docs: omap_wdt also understands nowayout watchdog: omap_wdt: implement get_timeleft watchdog: da9062: DA9062 watchdog driver watchdog: imx2_wdt: set watchdog parent device watchdog: mena21_wdt: Fix possible NULL pointer dereference watchdog: dw_wdt: keepalive the watchdog at write time watchdog: dw_wdt: No need for a spinlock watchdog: imx2_wdt: also set wdog->timeout to new_timeout watchdog: Allow compile test of GPIO consumers if !GPIOLIB watchdog: cadence: Add dependency on HAS_IOMEM watchdog: max63xx_wdt: Constify platform_device_id watchdog: MAX63XX_WATCHDOG does not depend on ARM watchdog: imgpdc: Add some documentation about the timeout ...
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig36
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/at91sam9_wdt.c4
-rw-r--r--drivers/watchdog/da9062_wdt.c253
-rw-r--r--drivers/watchdog/digicolor_wdt.c205
-rw-r--r--drivers/watchdog/dw_wdt.c8
-rw-r--r--drivers/watchdog/gpio_wdt.c9
-rw-r--r--drivers/watchdog/hpwdt.c16
-rw-r--r--drivers/watchdog/imgpdc_wdt.c84
-rw-r--r--drivers/watchdog/imx2_wdt.c18
-rw-r--r--drivers/watchdog/max63xx_wdt.c172
-rw-r--r--drivers/watchdog/mena21_wdt.c5
-rw-r--r--drivers/watchdog/omap_wdt.c92
-rw-r--r--drivers/watchdog/omap_wdt.h1
-rw-r--r--drivers/watchdog/st_lpc_wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c118
16 files changed, 870 insertions, 155 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 262647bbc614..241fafde42cb 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1,3 +1,4 @@
1
1# 2#
2# Watchdog device configuration 3# Watchdog device configuration
3# 4#
@@ -96,6 +97,15 @@ config DA9063_WATCHDOG
96 97
97 This driver can be built as a module. The module name is da9063_wdt. 98 This driver can be built as a module. The module name is da9063_wdt.
98 99
100config DA9062_WATCHDOG
101 tristate "Dialog DA9062 Watchdog"
102 depends on MFD_DA9062
103 select WATCHDOG_CORE
104 help
105 Support for the watchdog in the DA9062 PMIC.
106
107 This driver can be built as a module. The module name is da9062_wdt.
108
99config GPIO_WATCHDOG 109config GPIO_WATCHDOG
100 tristate "Watchdog device controlled through GPIO-line" 110 tristate "Watchdog device controlled through GPIO-line"
101 depends on OF_GPIO 111 depends on OF_GPIO
@@ -104,6 +114,17 @@ config GPIO_WATCHDOG
104 If you say yes here you get support for watchdog device 114 If you say yes here you get support for watchdog device
105 controlled through GPIO-line. 115 controlled through GPIO-line.
106 116
117config GPIO_WATCHDOG_ARCH_INITCALL
118 bool "Register the watchdog as early as possible"
119 depends on GPIO_WATCHDOG=y
120 help
121 In some situations, the default initcall level (module_init)
122 in not early enough in the boot process to avoid the watchdog
123 to be triggered.
124 If you say yes here, the initcall level would be raised to
125 arch_initcall.
126 If in doubt, say N.
127
107config MENF21BMC_WATCHDOG 128config MENF21BMC_WATCHDOG
108 tristate "MEN 14F021P00 BMC Watchdog" 129 tristate "MEN 14F021P00 BMC Watchdog"
109 depends on MFD_MENF21BMC 130 depends on MFD_MENF21BMC
@@ -169,6 +190,7 @@ config AT91SAM9X_WATCHDOG
169 190
170config CADENCE_WATCHDOG 191config CADENCE_WATCHDOG
171 tristate "Cadence Watchdog Timer" 192 tristate "Cadence Watchdog Timer"
193 depends on HAS_IOMEM
172 select WATCHDOG_CORE 194 select WATCHDOG_CORE
173 help 195 help
174 Say Y here if you want to include support for the watchdog 196 Say Y here if you want to include support for the watchdog
@@ -408,7 +430,7 @@ config TS72XX_WATCHDOG
408 430
409config MAX63XX_WATCHDOG 431config MAX63XX_WATCHDOG
410 tristate "Max63xx watchdog" 432 tristate "Max63xx watchdog"
411 depends on ARM && HAS_IOMEM 433 depends on HAS_IOMEM
412 select WATCHDOG_CORE 434 select WATCHDOG_CORE
413 help 435 help
414 Support for memory mapped max63{69,70,71,72,73,74} watchdog timer. 436 Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
@@ -526,6 +548,16 @@ config MEDIATEK_WATCHDOG
526 To compile this driver as a module, choose M here: the 548 To compile this driver as a module, choose M here: the
527 module will be called mtk_wdt. 549 module will be called mtk_wdt.
528 550
551config DIGICOLOR_WATCHDOG
552 tristate "Conexant Digicolor SoCs watchdog support"
553 depends on ARCH_DIGICOLOR
554 select WATCHDOG_CORE
555 help
556 Say Y here to include support for the watchdog timer
557 in Conexant Digicolor SoCs.
558 To compile this driver as a module, choose M here: the
559 module will be called digicolor_wdt.
560
529# AVR32 Architecture 561# AVR32 Architecture
530 562
531config AT32AP700X_WDT 563config AT32AP700X_WDT
@@ -1355,7 +1387,7 @@ config BOOKE_WDT_DEFAULT_TIMEOUT
1355config MEN_A21_WDT 1387config MEN_A21_WDT
1356 tristate "MEN A21 VME CPU Carrier Board Watchdog Timer" 1388 tristate "MEN A21 VME CPU Carrier Board Watchdog Timer"
1357 select WATCHDOG_CORE 1389 select WATCHDOG_CORE
1358 depends on GPIOLIB 1390 depends on GPIOLIB || COMPILE_TEST
1359 help 1391 help
1360 Watchdog driver for MEN A21 VMEbus CPU Carrier Boards. 1392 Watchdog driver for MEN A21 VMEbus CPU Carrier Boards.
1361 1393
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index d98768c7d928..59ea9a1b8e76 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
65obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o 65obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
66obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o 66obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
67obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o 67obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
68obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
68 69
69# AVR32 Architecture 70# AVR32 Architecture
70obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o 71obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -180,6 +181,7 @@ obj-$(CONFIG_XEN_WDT) += xen_wdt.o
180# Architecture Independent 181# Architecture Independent
181obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o 182obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
182obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o 183obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
184obj-$(CONFIG_DA9062_WATCHDOG) += da9062_wdt.o
183obj-$(CONFIG_DA9063_WATCHDOG) += da9063_wdt.o 185obj-$(CONFIG_DA9063_WATCHDOG) += da9063_wdt.o
184obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o 186obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o
185obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 187obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 1443b3c391de..e4698f7c5f93 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -40,9 +40,9 @@
40#define DRV_NAME "AT91SAM9 Watchdog" 40#define DRV_NAME "AT91SAM9 Watchdog"
41 41
42#define wdt_read(wdt, field) \ 42#define wdt_read(wdt, field) \
43 __raw_readl((wdt)->base + (field)) 43 readl_relaxed((wdt)->base + (field))
44#define wdt_write(wtd, field, val) \ 44#define wdt_write(wtd, field, val) \
45 __raw_writel((val), (wdt)->base + (field)) 45 writel_relaxed((val), (wdt)->base + (field))
46 46
47/* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, 47/* AT91SAM9 watchdog runs a 12bit counter @ 256Hz,
48 * use this to convert a watchdog 48 * use this to convert a watchdog
diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c
new file mode 100644
index 000000000000..b3a870ce85be
--- /dev/null
+++ b/drivers/watchdog/da9062_wdt.c
@@ -0,0 +1,253 @@
1/*
2 * da9062_wdt.c - WDT device driver for DA9062
3 * Copyright (C) 2015 Dialog Semiconductor Ltd.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/watchdog.h>
19#include <linux/platform_device.h>
20#include <linux/uaccess.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/jiffies.h>
24#include <linux/mfd/da9062/registers.h>
25#include <linux/mfd/da9062/core.h>
26#include <linux/regmap.h>
27#include <linux/of.h>
28
29static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
30#define DA9062_TWDSCALE_DISABLE 0
31#define DA9062_TWDSCALE_MIN 1
32#define DA9062_TWDSCALE_MAX (ARRAY_SIZE(wdt_timeout) - 1)
33#define DA9062_WDT_MIN_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MIN]
34#define DA9062_WDT_MAX_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MAX]
35#define DA9062_WDG_DEFAULT_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MAX-1]
36#define DA9062_RESET_PROTECTION_MS 300
37
38struct da9062_watchdog {
39 struct da9062 *hw;
40 struct watchdog_device wdtdev;
41 unsigned long j_time_stamp;
42};
43
44static void da9062_set_window_start(struct da9062_watchdog *wdt)
45{
46 wdt->j_time_stamp = jiffies;
47}
48
49static void da9062_apply_window_protection(struct da9062_watchdog *wdt)
50{
51 unsigned long delay = msecs_to_jiffies(DA9062_RESET_PROTECTION_MS);
52 unsigned long timeout = wdt->j_time_stamp + delay;
53 unsigned long now = jiffies;
54 unsigned int diff_ms;
55
56 /* if time-limit has not elapsed then wait for remainder */
57 if (time_before(now, timeout)) {
58 diff_ms = jiffies_to_msecs(timeout-now);
59 dev_dbg(wdt->hw->dev,
60 "Kicked too quickly. Delaying %u msecs\n", diff_ms);
61 msleep(diff_ms);
62 }
63}
64
65static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
66{
67 unsigned int i;
68
69 for (i = DA9062_TWDSCALE_MIN; i <= DA9062_TWDSCALE_MAX; i++) {
70 if (wdt_timeout[i] >= secs)
71 return i;
72 }
73
74 return DA9062_TWDSCALE_MAX;
75}
76
77static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
78{
79 int ret;
80
81 da9062_apply_window_protection(wdt);
82
83 ret = regmap_update_bits(wdt->hw->regmap,
84 DA9062AA_CONTROL_F,
85 DA9062AA_WATCHDOG_MASK,
86 DA9062AA_WATCHDOG_MASK);
87
88 da9062_set_window_start(wdt);
89
90 return ret;
91}
92
93static int da9062_wdt_update_timeout_register(struct da9062_watchdog *wdt,
94 unsigned int regval)
95{
96 struct da9062 *chip = wdt->hw;
97 int ret;
98
99 ret = da9062_reset_watchdog_timer(wdt);
100 if (ret)
101 return ret;
102
103 return regmap_update_bits(chip->regmap,
104 DA9062AA_CONTROL_D,
105 DA9062AA_TWDSCALE_MASK,
106 regval);
107}
108
109static int da9062_wdt_start(struct watchdog_device *wdd)
110{
111 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
112 unsigned int selector;
113 int ret;
114
115 selector = da9062_wdt_timeout_to_sel(wdt->wdtdev.timeout);
116 ret = da9062_wdt_update_timeout_register(wdt, selector);
117 if (ret)
118 dev_err(wdt->hw->dev, "Watchdog failed to start (err = %d)\n",
119 ret);
120
121 return ret;
122}
123
124static int da9062_wdt_stop(struct watchdog_device *wdd)
125{
126 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
127 int ret;
128
129 ret = da9062_reset_watchdog_timer(wdt);
130 if (ret) {
131 dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n",
132 ret);
133 return ret;
134 }
135
136 ret = regmap_update_bits(wdt->hw->regmap,
137 DA9062AA_CONTROL_D,
138 DA9062AA_TWDSCALE_MASK,
139 DA9062_TWDSCALE_DISABLE);
140 if (ret)
141 dev_err(wdt->hw->dev, "Watchdog failed to stop (err = %d)\n",
142 ret);
143
144 return ret;
145}
146
147static int da9062_wdt_ping(struct watchdog_device *wdd)
148{
149 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
150 int ret;
151
152 ret = da9062_reset_watchdog_timer(wdt);
153 if (ret)
154 dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n",
155 ret);
156
157 return ret;
158}
159
160static int da9062_wdt_set_timeout(struct watchdog_device *wdd,
161 unsigned int timeout)
162{
163 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
164 unsigned int selector;
165 int ret;
166
167 selector = da9062_wdt_timeout_to_sel(timeout);
168 ret = da9062_wdt_update_timeout_register(wdt, selector);
169 if (ret)
170 dev_err(wdt->hw->dev, "Failed to set watchdog timeout (err = %d)\n",
171 ret);
172 else
173 wdd->timeout = wdt_timeout[selector];
174
175 return ret;
176}
177
178static const struct watchdog_info da9062_watchdog_info = {
179 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
180 .identity = "DA9062 WDT",
181};
182
183static const struct watchdog_ops da9062_watchdog_ops = {
184 .owner = THIS_MODULE,
185 .start = da9062_wdt_start,
186 .stop = da9062_wdt_stop,
187 .ping = da9062_wdt_ping,
188 .set_timeout = da9062_wdt_set_timeout,
189};
190
191static int da9062_wdt_probe(struct platform_device *pdev)
192{
193 int ret;
194 struct da9062 *chip;
195 struct da9062_watchdog *wdt;
196
197 chip = dev_get_drvdata(pdev->dev.parent);
198 if (!chip)
199 return -EINVAL;
200
201 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
202 if (!wdt)
203 return -ENOMEM;
204
205 wdt->hw = chip;
206
207 wdt->wdtdev.info = &da9062_watchdog_info;
208 wdt->wdtdev.ops = &da9062_watchdog_ops;
209 wdt->wdtdev.min_timeout = DA9062_WDT_MIN_TIMEOUT;
210 wdt->wdtdev.max_timeout = DA9062_WDT_MAX_TIMEOUT;
211 wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT;
212 wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
213
214 watchdog_set_drvdata(&wdt->wdtdev, wdt);
215 dev_set_drvdata(&pdev->dev, wdt);
216
217 ret = watchdog_register_device(&wdt->wdtdev);
218 if (ret < 0) {
219 dev_err(wdt->hw->dev,
220 "watchdog registration failed (%d)\n", ret);
221 return ret;
222 }
223
224 da9062_set_window_start(wdt);
225
226 ret = da9062_wdt_ping(&wdt->wdtdev);
227 if (ret < 0)
228 watchdog_unregister_device(&wdt->wdtdev);
229
230 return ret;
231}
232
233static int da9062_wdt_remove(struct platform_device *pdev)
234{
235 struct da9062_watchdog *wdt = dev_get_drvdata(&pdev->dev);
236
237 watchdog_unregister_device(&wdt->wdtdev);
238 return 0;
239}
240
241static struct platform_driver da9062_wdt_driver = {
242 .probe = da9062_wdt_probe,
243 .remove = da9062_wdt_remove,
244 .driver = {
245 .name = "da9062-watchdog",
246 },
247};
248module_platform_driver(da9062_wdt_driver);
249
250MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
251MODULE_DESCRIPTION("WDT device driver for Dialog DA9062");
252MODULE_LICENSE("GPL");
253MODULE_ALIAS("platform:da9062-watchdog");
diff --git a/drivers/watchdog/digicolor_wdt.c b/drivers/watchdog/digicolor_wdt.c
new file mode 100644
index 000000000000..31d8e4936611
--- /dev/null
+++ b/drivers/watchdog/digicolor_wdt.c
@@ -0,0 +1,205 @@
1/*
2 * Watchdog driver for Conexant Digicolor
3 *
4 * Copyright (C) 2015 Paradox Innovation 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 as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/types.h>
13#include <linux/module.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16#include <linux/clk.h>
17#include <linux/watchdog.h>
18#include <linux/reboot.h>
19#include <linux/platform_device.h>
20#include <linux/of_address.h>
21
22#define TIMER_A_CONTROL 0
23#define TIMER_A_COUNT 4
24
25#define TIMER_A_ENABLE_COUNT BIT(0)
26#define TIMER_A_ENABLE_WATCHDOG BIT(1)
27
28struct dc_wdt {
29 void __iomem *base;
30 struct clk *clk;
31 struct notifier_block restart_handler;
32 spinlock_t lock;
33};
34
35static unsigned timeout;
36module_param(timeout, uint, 0);
37MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
38
39static void dc_wdt_set(struct dc_wdt *wdt, u32 ticks)
40{
41 unsigned long flags;
42
43 spin_lock_irqsave(&wdt->lock, flags);
44
45 writel_relaxed(0, wdt->base + TIMER_A_CONTROL);
46 writel_relaxed(ticks, wdt->base + TIMER_A_COUNT);
47 writel_relaxed(TIMER_A_ENABLE_COUNT | TIMER_A_ENABLE_WATCHDOG,
48 wdt->base + TIMER_A_CONTROL);
49
50 spin_unlock_irqrestore(&wdt->lock, flags);
51}
52
53static int dc_restart_handler(struct notifier_block *this, unsigned long mode,
54 void *cmd)
55{
56 struct dc_wdt *wdt = container_of(this, struct dc_wdt, restart_handler);
57
58 dc_wdt_set(wdt, 1);
59 /* wait for reset to assert... */
60 mdelay(500);
61
62 return NOTIFY_DONE;
63}
64
65static int dc_wdt_start(struct watchdog_device *wdog)
66{
67 struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
68
69 dc_wdt_set(wdt, wdog->timeout * clk_get_rate(wdt->clk));
70
71 return 0;
72}
73
74static int dc_wdt_stop(struct watchdog_device *wdog)
75{
76 struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
77
78 writel_relaxed(0, wdt->base + TIMER_A_CONTROL);
79
80 return 0;
81}
82
83static int dc_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t)
84{
85 struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
86
87 dc_wdt_set(wdt, t * clk_get_rate(wdt->clk));
88 wdog->timeout = t;
89
90 return 0;
91}
92
93static unsigned int dc_wdt_get_timeleft(struct watchdog_device *wdog)
94{
95 struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
96 uint32_t count = readl_relaxed(wdt->base + TIMER_A_COUNT);
97
98 return count / clk_get_rate(wdt->clk);
99}
100
101static struct watchdog_ops dc_wdt_ops = {
102 .owner = THIS_MODULE,
103 .start = dc_wdt_start,
104 .stop = dc_wdt_stop,
105 .set_timeout = dc_wdt_set_timeout,
106 .get_timeleft = dc_wdt_get_timeleft,
107};
108
109static struct watchdog_info dc_wdt_info = {
110 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE
111 | WDIOF_KEEPALIVEPING,
112 .identity = "Conexant Digicolor Watchdog",
113};
114
115static struct watchdog_device dc_wdt_wdd = {
116 .info = &dc_wdt_info,
117 .ops = &dc_wdt_ops,
118 .min_timeout = 1,
119};
120
121static int dc_wdt_probe(struct platform_device *pdev)
122{
123 struct device *dev = &pdev->dev;
124 struct device_node *np = dev->of_node;
125 struct dc_wdt *wdt;
126 int ret;
127
128 wdt = devm_kzalloc(dev, sizeof(struct dc_wdt), GFP_KERNEL);
129 if (!wdt)
130 return -ENOMEM;
131 platform_set_drvdata(pdev, wdt);
132
133 wdt->base = of_iomap(np, 0);
134 if (!wdt->base) {
135 dev_err(dev, "Failed to remap watchdog regs");
136 return -ENODEV;
137 }
138
139 wdt->clk = devm_clk_get(&pdev->dev, NULL);
140 if (IS_ERR(wdt->clk)) {
141 ret = PTR_ERR(wdt->clk);
142 goto err_iounmap;
143 }
144 dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk);
145 dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout;
146
147 spin_lock_init(&wdt->lock);
148
149 watchdog_set_drvdata(&dc_wdt_wdd, wdt);
150 watchdog_init_timeout(&dc_wdt_wdd, timeout, dev);
151 ret = watchdog_register_device(&dc_wdt_wdd);
152 if (ret) {
153 dev_err(dev, "Failed to register watchdog device");
154 goto err_iounmap;
155 }
156
157 wdt->restart_handler.notifier_call = dc_restart_handler;
158 wdt->restart_handler.priority = 128;
159 ret = register_restart_handler(&wdt->restart_handler);
160 if (ret)
161 dev_warn(&pdev->dev, "cannot register restart handler\n");
162
163 return 0;
164
165err_iounmap:
166 iounmap(wdt->base);
167 return ret;
168}
169
170static int dc_wdt_remove(struct platform_device *pdev)
171{
172 struct dc_wdt *wdt = platform_get_drvdata(pdev);
173
174 unregister_restart_handler(&wdt->restart_handler);
175 watchdog_unregister_device(&dc_wdt_wdd);
176 iounmap(wdt->base);
177
178 return 0;
179}
180
181static void dc_wdt_shutdown(struct platform_device *pdev)
182{
183 dc_wdt_stop(&dc_wdt_wdd);
184}
185
186static const struct of_device_id dc_wdt_of_match[] = {
187 { .compatible = "cnxt,cx92755-wdt", },
188 {},
189};
190MODULE_DEVICE_TABLE(of, dc_wdt_of_match);
191
192static struct platform_driver dc_wdt_driver = {
193 .probe = dc_wdt_probe,
194 .remove = dc_wdt_remove,
195 .shutdown = dc_wdt_shutdown,
196 .driver = {
197 .name = "digicolor-wdt",
198 .of_match_table = dc_wdt_of_match,
199 },
200};
201module_platform_driver(dc_wdt_driver);
202
203MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
204MODULE_DESCRIPTION("Driver for Conexant Digicolor watchdog timer");
205MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index d0bb9499d12c..6ea0634345e9 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -35,7 +35,6 @@
35#include <linux/pm.h> 35#include <linux/pm.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/reboot.h> 37#include <linux/reboot.h>
38#include <linux/spinlock.h>
39#include <linux/timer.h> 38#include <linux/timer.h>
40#include <linux/uaccess.h> 39#include <linux/uaccess.h>
41#include <linux/watchdog.h> 40#include <linux/watchdog.h>
@@ -61,7 +60,6 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
61#define WDT_TIMEOUT (HZ / 2) 60#define WDT_TIMEOUT (HZ / 2)
62 61
63static struct { 62static struct {
64 spinlock_t lock;
65 void __iomem *regs; 63 void __iomem *regs;
66 struct clk *clk; 64 struct clk *clk;
67 unsigned long in_use; 65 unsigned long in_use;
@@ -177,7 +175,6 @@ static int dw_wdt_open(struct inode *inode, struct file *filp)
177 /* Make sure we don't get unloaded. */ 175 /* Make sure we don't get unloaded. */
178 __module_get(THIS_MODULE); 176 __module_get(THIS_MODULE);
179 177
180 spin_lock(&dw_wdt.lock);
181 if (!dw_wdt_is_enabled()) { 178 if (!dw_wdt_is_enabled()) {
182 /* 179 /*
183 * The watchdog is not currently enabled. Set the timeout to 180 * The watchdog is not currently enabled. Set the timeout to
@@ -190,8 +187,6 @@ static int dw_wdt_open(struct inode *inode, struct file *filp)
190 187
191 dw_wdt_set_next_heartbeat(); 188 dw_wdt_set_next_heartbeat();
192 189
193 spin_unlock(&dw_wdt.lock);
194
195 return nonseekable_open(inode, filp); 190 return nonseekable_open(inode, filp);
196} 191}
197 192
@@ -220,6 +215,7 @@ static ssize_t dw_wdt_write(struct file *filp, const char __user *buf,
220 } 215 }
221 216
222 dw_wdt_set_next_heartbeat(); 217 dw_wdt_set_next_heartbeat();
218 dw_wdt_keepalive();
223 mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT); 219 mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT);
224 220
225 return len; 221 return len;
@@ -348,8 +344,6 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
348 if (ret) 344 if (ret)
349 return ret; 345 return ret;
350 346
351 spin_lock_init(&dw_wdt.lock);
352
353 ret = misc_register(&dw_wdt_miscdev); 347 ret = misc_register(&dw_wdt_miscdev);
354 if (ret) 348 if (ret)
355 goto out_disable_clk; 349 goto out_disable_clk;
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index cbc313d37c59..1687cc2d7122 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -267,7 +267,16 @@ static struct platform_driver gpio_wdt_driver = {
267 .probe = gpio_wdt_probe, 267 .probe = gpio_wdt_probe,
268 .remove = gpio_wdt_remove, 268 .remove = gpio_wdt_remove,
269}; 269};
270
271#ifdef CONFIG_GPIO_WATCHDOG_ARCH_INITCALL
272static int __init gpio_wdt_init(void)
273{
274 return platform_driver_register(&gpio_wdt_driver);
275}
276arch_initcall(gpio_wdt_init);
277#else
270module_platform_driver(gpio_wdt_driver); 278module_platform_driver(gpio_wdt_driver);
279#endif
271 280
272MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); 281MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
273MODULE_DESCRIPTION("GPIO Watchdog"); 282MODULE_DESCRIPTION("GPIO Watchdog");
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index ada3e44f9932..286369d4f0f5 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -588,7 +588,7 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd,
588{ 588{
589 void __user *argp = (void __user *)arg; 589 void __user *argp = (void __user *)arg;
590 int __user *p = argp; 590 int __user *p = argp;
591 int new_margin; 591 int new_margin, options;
592 int ret = -ENOTTY; 592 int ret = -ENOTTY;
593 593
594 switch (cmd) { 594 switch (cmd) {
@@ -608,6 +608,20 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd,
608 ret = 0; 608 ret = 0;
609 break; 609 break;
610 610
611 case WDIOC_SETOPTIONS:
612 ret = get_user(options, p);
613 if (ret)
614 break;
615
616 if (options & WDIOS_DISABLECARD)
617 hpwdt_stop();
618
619 if (options & WDIOS_ENABLECARD) {
620 hpwdt_start();
621 hpwdt_ping();
622 }
623 break;
624
611 case WDIOC_SETTIMEOUT: 625 case WDIOC_SETTIMEOUT:
612 ret = get_user(new_margin, p); 626 ret = get_user(new_margin, p);
613 if (ret) 627 if (ret)
diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c
index 0deaa4f971f5..0f73621827ab 100644
--- a/drivers/watchdog/imgpdc_wdt.c
+++ b/drivers/watchdog/imgpdc_wdt.c
@@ -9,6 +9,35 @@
9 * 9 *
10 * Based on drivers/watchdog/sunxi_wdt.c Copyright (c) 2013 Carlo Caione 10 * Based on drivers/watchdog/sunxi_wdt.c Copyright (c) 2013 Carlo Caione
11 * 2012 Henrik Nordstrom 11 * 2012 Henrik Nordstrom
12 *
13 * Notes
14 * -----
15 * The timeout value is rounded to the next power of two clock cycles.
16 * This is configured using the PDC_WDT_CONFIG register, according to this
17 * formula:
18 *
19 * timeout = 2^(delay + 1) clock cycles
20 *
21 * Where 'delay' is the value written in PDC_WDT_CONFIG register.
22 *
23 * Therefore, the hardware only allows to program watchdog timeouts, expressed
24 * as a power of two number of watchdog clock cycles. The current implementation
25 * guarantees that the actual watchdog timeout will be _at least_ the value
26 * programmed in the imgpdg_wdt driver.
27 *
28 * The following table shows how the user-configured timeout relates
29 * to the actual hardware timeout (watchdog clock @ 40000 Hz):
30 *
31 * input timeout | WD_DELAY | actual timeout
32 * -----------------------------------
33 * 10 | 18 | 13 seconds
34 * 20 | 19 | 26 seconds
35 * 30 | 20 | 52 seconds
36 * 60 | 21 | 104 seconds
37 *
38 * Albeit coarse, this granularity would suffice most watchdog uses.
39 * If the platform allows it, the user should be able to change the watchdog
40 * clock rate and achieve a finer timeout granularity.
12 */ 41 */
13 42
14#include <linux/clk.h> 43#include <linux/clk.h>
@@ -16,6 +45,7 @@
16#include <linux/log2.h> 45#include <linux/log2.h>
17#include <linux/module.h> 46#include <linux/module.h>
18#include <linux/platform_device.h> 47#include <linux/platform_device.h>
48#include <linux/reboot.h>
19#include <linux/slab.h> 49#include <linux/slab.h>
20#include <linux/watchdog.h> 50#include <linux/watchdog.h>
21 51
@@ -42,7 +72,7 @@
42#define PDC_WDT_MIN_TIMEOUT 1 72#define PDC_WDT_MIN_TIMEOUT 1
43#define PDC_WDT_DEF_TIMEOUT 64 73#define PDC_WDT_DEF_TIMEOUT 64
44 74
45static int heartbeat = PDC_WDT_DEF_TIMEOUT; 75static int heartbeat;
46module_param(heartbeat, int, 0); 76module_param(heartbeat, int, 0);
47MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds " 77MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds "
48 "(default=" __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")"); 78 "(default=" __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
@@ -57,6 +87,7 @@ struct pdc_wdt_dev {
57 struct clk *wdt_clk; 87 struct clk *wdt_clk;
58 struct clk *sys_clk; 88 struct clk *sys_clk;
59 void __iomem *base; 89 void __iomem *base;
90 struct notifier_block restart_handler;
60}; 91};
61 92
62static int pdc_wdt_keepalive(struct watchdog_device *wdt_dev) 93static int pdc_wdt_keepalive(struct watchdog_device *wdt_dev)
@@ -84,18 +115,24 @@ static int pdc_wdt_stop(struct watchdog_device *wdt_dev)
84 return 0; 115 return 0;
85} 116}
86 117
118static void __pdc_wdt_set_timeout(struct pdc_wdt_dev *wdt)
119{
120 unsigned long clk_rate = clk_get_rate(wdt->wdt_clk);
121 unsigned int val;
122
123 val = readl(wdt->base + PDC_WDT_CONFIG) & ~PDC_WDT_CONFIG_DELAY_MASK;
124 val |= order_base_2(wdt->wdt_dev.timeout * clk_rate) - 1;
125 writel(val, wdt->base + PDC_WDT_CONFIG);
126}
127
87static int pdc_wdt_set_timeout(struct watchdog_device *wdt_dev, 128static int pdc_wdt_set_timeout(struct watchdog_device *wdt_dev,
88 unsigned int new_timeout) 129 unsigned int new_timeout)
89{ 130{
90 unsigned int val;
91 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev); 131 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
92 unsigned long clk_rate = clk_get_rate(wdt->wdt_clk);
93 132
94 wdt->wdt_dev.timeout = new_timeout; 133 wdt->wdt_dev.timeout = new_timeout;
95 134
96 val = readl(wdt->base + PDC_WDT_CONFIG) & ~PDC_WDT_CONFIG_DELAY_MASK; 135 __pdc_wdt_set_timeout(wdt);
97 val |= order_base_2(new_timeout * clk_rate) - 1;
98 writel(val, wdt->base + PDC_WDT_CONFIG);
99 136
100 return 0; 137 return 0;
101} 138}
@@ -106,6 +143,8 @@ static int pdc_wdt_start(struct watchdog_device *wdt_dev)
106 unsigned int val; 143 unsigned int val;
107 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev); 144 struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev);
108 145
146 __pdc_wdt_set_timeout(wdt);
147
109 val = readl(wdt->base + PDC_WDT_CONFIG); 148 val = readl(wdt->base + PDC_WDT_CONFIG);
110 val |= PDC_WDT_CONFIG_ENABLE; 149 val |= PDC_WDT_CONFIG_ENABLE;
111 writel(val, wdt->base + PDC_WDT_CONFIG); 150 writel(val, wdt->base + PDC_WDT_CONFIG);
@@ -128,8 +167,21 @@ static const struct watchdog_ops pdc_wdt_ops = {
128 .set_timeout = pdc_wdt_set_timeout, 167 .set_timeout = pdc_wdt_set_timeout,
129}; 168};
130 169
170static int pdc_wdt_restart(struct notifier_block *this, unsigned long mode,
171 void *cmd)
172{
173 struct pdc_wdt_dev *wdt = container_of(this, struct pdc_wdt_dev,
174 restart_handler);
175
176 /* Assert SOFT_RESET */
177 writel(0x1, wdt->base + PDC_WDT_SOFT_RESET);
178
179 return NOTIFY_OK;
180}
181
131static int pdc_wdt_probe(struct platform_device *pdev) 182static int pdc_wdt_probe(struct platform_device *pdev)
132{ 183{
184 u64 div;
133 int ret, val; 185 int ret, val;
134 unsigned long clk_rate; 186 unsigned long clk_rate;
135 struct resource *res; 187 struct resource *res;
@@ -189,16 +241,15 @@ static int pdc_wdt_probe(struct platform_device *pdev)
189 241
190 pdc_wdt->wdt_dev.info = &pdc_wdt_info; 242 pdc_wdt->wdt_dev.info = &pdc_wdt_info;
191 pdc_wdt->wdt_dev.ops = &pdc_wdt_ops; 243 pdc_wdt->wdt_dev.ops = &pdc_wdt_ops;
192 pdc_wdt->wdt_dev.max_timeout = 1 << PDC_WDT_CONFIG_DELAY_MASK; 244
245 div = 1ULL << (PDC_WDT_CONFIG_DELAY_MASK + 1);
246 do_div(div, clk_rate);
247 pdc_wdt->wdt_dev.max_timeout = div;
248 pdc_wdt->wdt_dev.timeout = PDC_WDT_DEF_TIMEOUT;
193 pdc_wdt->wdt_dev.parent = &pdev->dev; 249 pdc_wdt->wdt_dev.parent = &pdev->dev;
194 watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt); 250 watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
195 251
196 ret = watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev); 252 watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev);
197 if (ret < 0) {
198 pdc_wdt->wdt_dev.timeout = pdc_wdt->wdt_dev.max_timeout;
199 dev_warn(&pdev->dev,
200 "Initial timeout out of range! setting max timeout\n");
201 }
202 253
203 pdc_wdt_stop(&pdc_wdt->wdt_dev); 254 pdc_wdt_stop(&pdc_wdt->wdt_dev);
204 255
@@ -238,6 +289,13 @@ static int pdc_wdt_probe(struct platform_device *pdev)
238 if (ret) 289 if (ret)
239 goto disable_wdt_clk; 290 goto disable_wdt_clk;
240 291
292 pdc_wdt->restart_handler.notifier_call = pdc_wdt_restart;
293 pdc_wdt->restart_handler.priority = 128;
294 ret = register_restart_handler(&pdc_wdt->restart_handler);
295 if (ret)
296 dev_warn(&pdev->dev, "failed to register restart handler: %d\n",
297 ret);
298
241 return 0; 299 return 0;
242 300
243disable_wdt_clk: 301disable_wdt_clk:
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 5e6d808d358a..0bb1a1d1b170 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -166,6 +166,8 @@ static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
166{ 166{
167 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 167 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
168 168
169 wdog->timeout = new_timeout;
170
169 regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT, 171 regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
170 WDOG_SEC_TO_COUNT(new_timeout)); 172 WDOG_SEC_TO_COUNT(new_timeout));
171 return 0; 173 return 0;
@@ -256,8 +258,11 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
256 wdog->ops = &imx2_wdt_ops; 258 wdog->ops = &imx2_wdt_ops;
257 wdog->min_timeout = 1; 259 wdog->min_timeout = 1;
258 wdog->max_timeout = IMX2_WDT_MAX_TIME; 260 wdog->max_timeout = IMX2_WDT_MAX_TIME;
261 wdog->parent = &pdev->dev;
259 262
260 clk_prepare_enable(wdev->clk); 263 ret = clk_prepare_enable(wdev->clk);
264 if (ret)
265 return ret;
261 266
262 regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val); 267 regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val);
263 wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; 268 wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
@@ -286,7 +291,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
286 ret = watchdog_register_device(wdog); 291 ret = watchdog_register_device(wdog);
287 if (ret) { 292 if (ret) {
288 dev_err(&pdev->dev, "cannot register watchdog device\n"); 293 dev_err(&pdev->dev, "cannot register watchdog device\n");
289 return ret; 294 goto disable_clk;
290 } 295 }
291 296
292 wdev->restart_handler.notifier_call = imx2_restart_handler; 297 wdev->restart_handler.notifier_call = imx2_restart_handler;
@@ -299,6 +304,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
299 wdog->timeout, nowayout); 304 wdog->timeout, nowayout);
300 305
301 return 0; 306 return 0;
307
308disable_clk:
309 clk_disable_unprepare(wdev->clk);
310 return ret;
302} 311}
303 312
304static int __exit imx2_wdt_remove(struct platform_device *pdev) 313static int __exit imx2_wdt_remove(struct platform_device *pdev)
@@ -362,8 +371,11 @@ static int imx2_wdt_resume(struct device *dev)
362{ 371{
363 struct watchdog_device *wdog = dev_get_drvdata(dev); 372 struct watchdog_device *wdog = dev_get_drvdata(dev);
364 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 373 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
374 int ret;
365 375
366 clk_prepare_enable(wdev->clk); 376 ret = clk_prepare_enable(wdev->clk);
377 if (ret)
378 return ret;
367 379
368 if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) { 380 if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) {
369 /* 381 /*
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 08da3114accb..f36ca4be0720 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -39,10 +39,22 @@ static bool nowayout = WATCHDOG_NOWAYOUT;
39#define MAX6369_WDSET (7 << 0) 39#define MAX6369_WDSET (7 << 0)
40#define MAX6369_WDI (1 << 3) 40#define MAX6369_WDI (1 << 3)
41 41
42static DEFINE_SPINLOCK(io_lock); 42#define MAX6369_WDSET_DISABLED 3
43 43
44static int nodelay; 44static int nodelay;
45static void __iomem *wdt_base; 45
46struct max63xx_wdt {
47 struct watchdog_device wdd;
48 const struct max63xx_timeout *timeout;
49
50 /* memory mapping */
51 void __iomem *base;
52 spinlock_t lock;
53
54 /* WDI and WSET bits write access routines */
55 void (*ping)(struct max63xx_wdt *wdt);
56 void (*set)(struct max63xx_wdt *wdt, u8 set);
57};
46 58
47/* 59/*
48 * The timeout values used are actually the absolute minimum the chip 60 * The timeout values used are actually the absolute minimum the chip
@@ -59,25 +71,25 @@ static void __iomem *wdt_base;
59 71
60/* Timeouts in second */ 72/* Timeouts in second */
61struct max63xx_timeout { 73struct max63xx_timeout {
62 u8 wdset; 74 const u8 wdset;
63 u8 tdelay; 75 const u8 tdelay;
64 u8 twd; 76 const u8 twd;
65}; 77};
66 78
67static struct max63xx_timeout max6369_table[] = { 79static const struct max63xx_timeout max6369_table[] = {
68 { 5, 1, 1 }, 80 { 5, 1, 1 },
69 { 6, 10, 10 }, 81 { 6, 10, 10 },
70 { 7, 60, 60 }, 82 { 7, 60, 60 },
71 { }, 83 { },
72}; 84};
73 85
74static struct max63xx_timeout max6371_table[] = { 86static const struct max63xx_timeout max6371_table[] = {
75 { 6, 60, 3 }, 87 { 6, 60, 3 },
76 { 7, 60, 60 }, 88 { 7, 60, 60 },
77 { }, 89 { },
78}; 90};
79 91
80static struct max63xx_timeout max6373_table[] = { 92static const struct max63xx_timeout max6373_table[] = {
81 { 2, 60, 1 }, 93 { 2, 60, 1 },
82 { 5, 0, 1 }, 94 { 5, 0, 1 },
83 { 1, 3, 3 }, 95 { 1, 3, 3 },
@@ -86,8 +98,6 @@ static struct max63xx_timeout max6373_table[] = {
86 { }, 98 { },
87}; 99};
88 100
89static struct max63xx_timeout *current_timeout;
90
91static struct max63xx_timeout * 101static struct max63xx_timeout *
92max63xx_select_timeout(struct max63xx_timeout *table, int value) 102max63xx_select_timeout(struct max63xx_timeout *table, int value)
93{ 103{
@@ -108,59 +118,32 @@ max63xx_select_timeout(struct max63xx_timeout *table, int value)
108 118
109static int max63xx_wdt_ping(struct watchdog_device *wdd) 119static int max63xx_wdt_ping(struct watchdog_device *wdd)
110{ 120{
111 u8 val; 121 struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd);
112
113 spin_lock(&io_lock);
114 122
115 val = __raw_readb(wdt_base); 123 wdt->ping(wdt);
116
117 __raw_writeb(val | MAX6369_WDI, wdt_base);
118 __raw_writeb(val & ~MAX6369_WDI, wdt_base);
119
120 spin_unlock(&io_lock);
121 return 0; 124 return 0;
122} 125}
123 126
124static int max63xx_wdt_start(struct watchdog_device *wdd) 127static int max63xx_wdt_start(struct watchdog_device *wdd)
125{ 128{
126 struct max63xx_timeout *entry = watchdog_get_drvdata(wdd); 129 struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd);
127 u8 val;
128 130
129 spin_lock(&io_lock); 131 wdt->set(wdt, wdt->timeout->wdset);
130
131 val = __raw_readb(wdt_base);
132 val &= ~MAX6369_WDSET;
133 val |= entry->wdset;
134 __raw_writeb(val, wdt_base);
135
136 spin_unlock(&io_lock);
137 132
138 /* check for a edge triggered startup */ 133 /* check for a edge triggered startup */
139 if (entry->tdelay == 0) 134 if (wdt->timeout->tdelay == 0)
140 max63xx_wdt_ping(wdd); 135 wdt->ping(wdt);
141 return 0; 136 return 0;
142} 137}
143 138
144static int max63xx_wdt_stop(struct watchdog_device *wdd) 139static int max63xx_wdt_stop(struct watchdog_device *wdd)
145{ 140{
146 u8 val; 141 struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd);
147 142
148 spin_lock(&io_lock); 143 wdt->set(wdt, MAX6369_WDSET_DISABLED);
149
150 val = __raw_readb(wdt_base);
151 val &= ~MAX6369_WDSET;
152 val |= 3;
153 __raw_writeb(val, wdt_base);
154
155 spin_unlock(&io_lock);
156 return 0; 144 return 0;
157} 145}
158 146
159static const struct watchdog_info max63xx_wdt_info = {
160 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
161 .identity = "max63xx Watchdog",
162};
163
164static const struct watchdog_ops max63xx_wdt_ops = { 147static const struct watchdog_ops max63xx_wdt_ops = {
165 .owner = THIS_MODULE, 148 .owner = THIS_MODULE,
166 .start = max63xx_wdt_start, 149 .start = max63xx_wdt_start,
@@ -168,53 +151,108 @@ static const struct watchdog_ops max63xx_wdt_ops = {
168 .ping = max63xx_wdt_ping, 151 .ping = max63xx_wdt_ping,
169}; 152};
170 153
171static struct watchdog_device max63xx_wdt_dev = { 154static const struct watchdog_info max63xx_wdt_info = {
172 .info = &max63xx_wdt_info, 155 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
173 .ops = &max63xx_wdt_ops, 156 .identity = "max63xx Watchdog",
174}; 157};
175 158
159static void max63xx_mmap_ping(struct max63xx_wdt *wdt)
160{
161 u8 val;
162
163 spin_lock(&wdt->lock);
164
165 val = __raw_readb(wdt->base);
166
167 __raw_writeb(val | MAX6369_WDI, wdt->base);
168 __raw_writeb(val & ~MAX6369_WDI, wdt->base);
169
170 spin_unlock(&wdt->lock);
171}
172
173static void max63xx_mmap_set(struct max63xx_wdt *wdt, u8 set)
174{
175 u8 val;
176
177 spin_lock(&wdt->lock);
178
179 val = __raw_readb(wdt->base);
180 val &= ~MAX6369_WDSET;
181 val |= set & MAX6369_WDSET;
182 __raw_writeb(val, wdt->base);
183
184 spin_unlock(&wdt->lock);
185}
186
187static int max63xx_mmap_init(struct platform_device *p, struct max63xx_wdt *wdt)
188{
189 struct resource *mem = platform_get_resource(p, IORESOURCE_MEM, 0);
190
191 wdt->base = devm_ioremap_resource(&p->dev, mem);
192 if (IS_ERR(wdt->base))
193 return PTR_ERR(wdt->base);
194
195 spin_lock_init(&wdt->lock);
196
197 wdt->ping = max63xx_mmap_ping;
198 wdt->set = max63xx_mmap_set;
199 return 0;
200}
201
176static int max63xx_wdt_probe(struct platform_device *pdev) 202static int max63xx_wdt_probe(struct platform_device *pdev)
177{ 203{
178 struct resource *wdt_mem; 204 struct max63xx_wdt *wdt;
179 struct max63xx_timeout *table; 205 struct max63xx_timeout *table;
206 int err;
207
208 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
209 if (!wdt)
210 return -ENOMEM;
180 211
181 table = (struct max63xx_timeout *)pdev->id_entry->driver_data; 212 table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
182 213
183 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 214 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
184 heartbeat = DEFAULT_HEARTBEAT; 215 heartbeat = DEFAULT_HEARTBEAT;
185 216
186 dev_info(&pdev->dev, "requesting %ds heartbeat\n", heartbeat); 217 wdt->timeout = max63xx_select_timeout(table, heartbeat);
187 current_timeout = max63xx_select_timeout(table, heartbeat); 218 if (!wdt->timeout) {
188 219 dev_err(&pdev->dev, "unable to satisfy %ds heartbeat request\n",
189 if (!current_timeout) { 220 heartbeat);
190 dev_err(&pdev->dev, "unable to satisfy heartbeat request\n");
191 return -EINVAL; 221 return -EINVAL;
192 } 222 }
193 223
194 dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n", 224 err = max63xx_mmap_init(pdev, wdt);
195 current_timeout->twd, current_timeout->tdelay); 225 if (err)
226 return err;
227
228 platform_set_drvdata(pdev, &wdt->wdd);
229 watchdog_set_drvdata(&wdt->wdd, wdt);
196 230
197 heartbeat = current_timeout->twd; 231 wdt->wdd.parent = &pdev->dev;
232 wdt->wdd.timeout = wdt->timeout->twd;
233 wdt->wdd.info = &max63xx_wdt_info;
234 wdt->wdd.ops = &max63xx_wdt_ops;
198 235
199 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 236 watchdog_set_nowayout(&wdt->wdd, nowayout);
200 wdt_base = devm_ioremap_resource(&pdev->dev, wdt_mem);
201 if (IS_ERR(wdt_base))
202 return PTR_ERR(wdt_base);
203 237
204 max63xx_wdt_dev.timeout = heartbeat; 238 err = watchdog_register_device(&wdt->wdd);
205 watchdog_set_nowayout(&max63xx_wdt_dev, nowayout); 239 if (err)
206 watchdog_set_drvdata(&max63xx_wdt_dev, current_timeout); 240 return err;
207 241
208 return watchdog_register_device(&max63xx_wdt_dev); 242 dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n",
243 wdt->timeout->twd, wdt->timeout->tdelay);
244 return 0;
209} 245}
210 246
211static int max63xx_wdt_remove(struct platform_device *pdev) 247static int max63xx_wdt_remove(struct platform_device *pdev)
212{ 248{
213 watchdog_unregister_device(&max63xx_wdt_dev); 249 struct watchdog_device *wdd = platform_get_drvdata(pdev);
250
251 watchdog_unregister_device(wdd);
214 return 0; 252 return 0;
215} 253}
216 254
217static struct platform_device_id max63xx_id_table[] = { 255static const struct platform_device_id max63xx_id_table[] = {
218 { "max6369_wdt", (kernel_ulong_t)max6369_table, }, 256 { "max6369_wdt", (kernel_ulong_t)max6369_table, },
219 { "max6370_wdt", (kernel_ulong_t)max6369_table, }, 257 { "max6370_wdt", (kernel_ulong_t)max6369_table, },
220 { "max6371_wdt", (kernel_ulong_t)max6371_table, }, 258 { "max6371_wdt", (kernel_ulong_t)max6371_table, },
diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c
index 96dbba980579..d193a5e79c38 100644
--- a/drivers/watchdog/mena21_wdt.c
+++ b/drivers/watchdog/mena21_wdt.c
@@ -208,14 +208,15 @@ static int a21_wdt_probe(struct platform_device *pdev)
208 else if (reset == 7) 208 else if (reset == 7)
209 a21_wdt.bootstatus |= WDIOF_EXTERN2; 209 a21_wdt.bootstatus |= WDIOF_EXTERN2;
210 210
211 drv->wdt = a21_wdt;
212 dev_set_drvdata(&pdev->dev, drv);
213
211 ret = watchdog_register_device(&a21_wdt); 214 ret = watchdog_register_device(&a21_wdt);
212 if (ret) { 215 if (ret) {
213 dev_err(&pdev->dev, "Cannot register watchdog device\n"); 216 dev_err(&pdev->dev, "Cannot register watchdog device\n");
214 goto err_register_wd; 217 goto err_register_wd;
215 } 218 }
216 219
217 dev_set_drvdata(&pdev->dev, drv);
218
219 dev_info(&pdev->dev, "MEN A21 watchdog timer driver enabled\n"); 220 dev_info(&pdev->dev, "MEN A21 watchdog timer driver enabled\n");
220 221
221 return 0; 222 return 0;
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 1e6be9e40577..de911c7e477c 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -53,7 +53,15 @@ static unsigned timer_margin;
53module_param(timer_margin, uint, 0); 53module_param(timer_margin, uint, 0);
54MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); 54MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
55 55
56#define to_omap_wdt_dev(_wdog) container_of(_wdog, struct omap_wdt_dev, wdog)
57
58static bool early_enable;
59module_param(early_enable, bool, 0);
60MODULE_PARM_DESC(early_enable,
61 "Watchdog is started on module insertion (default=0)");
62
56struct omap_wdt_dev { 63struct omap_wdt_dev {
64 struct watchdog_device wdog;
57 void __iomem *base; /* physical */ 65 void __iomem *base; /* physical */
58 struct device *dev; 66 struct device *dev;
59 bool omap_wdt_users; 67 bool omap_wdt_users;
@@ -123,7 +131,7 @@ static void omap_wdt_set_timer(struct omap_wdt_dev *wdev,
123 131
124static int omap_wdt_start(struct watchdog_device *wdog) 132static int omap_wdt_start(struct watchdog_device *wdog)
125{ 133{
126 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 134 struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
127 void __iomem *base = wdev->base; 135 void __iomem *base = wdev->base;
128 136
129 mutex_lock(&wdev->lock); 137 mutex_lock(&wdev->lock);
@@ -132,6 +140,13 @@ static int omap_wdt_start(struct watchdog_device *wdog)
132 140
133 pm_runtime_get_sync(wdev->dev); 141 pm_runtime_get_sync(wdev->dev);
134 142
143 /*
144 * Make sure the watchdog is disabled. This is unfortunately required
145 * because writing to various registers with the watchdog running has no
146 * effect.
147 */
148 omap_wdt_disable(wdev);
149
135 /* initialize prescaler */ 150 /* initialize prescaler */
136 while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01) 151 while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01)
137 cpu_relax(); 152 cpu_relax();
@@ -151,7 +166,7 @@ static int omap_wdt_start(struct watchdog_device *wdog)
151 166
152static int omap_wdt_stop(struct watchdog_device *wdog) 167static int omap_wdt_stop(struct watchdog_device *wdog)
153{ 168{
154 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 169 struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
155 170
156 mutex_lock(&wdev->lock); 171 mutex_lock(&wdev->lock);
157 omap_wdt_disable(wdev); 172 omap_wdt_disable(wdev);
@@ -163,7 +178,7 @@ static int omap_wdt_stop(struct watchdog_device *wdog)
163 178
164static int omap_wdt_ping(struct watchdog_device *wdog) 179static int omap_wdt_ping(struct watchdog_device *wdog)
165{ 180{
166 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 181 struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
167 182
168 mutex_lock(&wdev->lock); 183 mutex_lock(&wdev->lock);
169 omap_wdt_reload(wdev); 184 omap_wdt_reload(wdev);
@@ -175,7 +190,7 @@ static int omap_wdt_ping(struct watchdog_device *wdog)
175static int omap_wdt_set_timeout(struct watchdog_device *wdog, 190static int omap_wdt_set_timeout(struct watchdog_device *wdog,
176 unsigned int timeout) 191 unsigned int timeout)
177{ 192{
178 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 193 struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
179 194
180 mutex_lock(&wdev->lock); 195 mutex_lock(&wdev->lock);
181 omap_wdt_disable(wdev); 196 omap_wdt_disable(wdev);
@@ -188,6 +203,16 @@ static int omap_wdt_set_timeout(struct watchdog_device *wdog,
188 return 0; 203 return 0;
189} 204}
190 205
206static unsigned int omap_wdt_get_timeleft(struct watchdog_device *wdog)
207{
208 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
209 void __iomem *base = wdev->base;
210 u32 value;
211
212 value = readl_relaxed(base + OMAP_WATCHDOG_CRR);
213 return GET_WCCR_SECS(value);
214}
215
191static const struct watchdog_info omap_wdt_info = { 216static const struct watchdog_info omap_wdt_info = {
192 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 217 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
193 .identity = "OMAP Watchdog", 218 .identity = "OMAP Watchdog",
@@ -199,21 +224,16 @@ static const struct watchdog_ops omap_wdt_ops = {
199 .stop = omap_wdt_stop, 224 .stop = omap_wdt_stop,
200 .ping = omap_wdt_ping, 225 .ping = omap_wdt_ping,
201 .set_timeout = omap_wdt_set_timeout, 226 .set_timeout = omap_wdt_set_timeout,
227 .get_timeleft = omap_wdt_get_timeleft,
202}; 228};
203 229
204static int omap_wdt_probe(struct platform_device *pdev) 230static int omap_wdt_probe(struct platform_device *pdev)
205{ 231{
206 struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev); 232 struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev);
207 struct watchdog_device *omap_wdt;
208 struct resource *res; 233 struct resource *res;
209 struct omap_wdt_dev *wdev; 234 struct omap_wdt_dev *wdev;
210 u32 rs;
211 int ret; 235 int ret;
212 236
213 omap_wdt = devm_kzalloc(&pdev->dev, sizeof(*omap_wdt), GFP_KERNEL);
214 if (!omap_wdt)
215 return -ENOMEM;
216
217 wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL); 237 wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
218 if (!wdev) 238 if (!wdev)
219 return -ENOMEM; 239 return -ENOMEM;
@@ -229,35 +249,30 @@ static int omap_wdt_probe(struct platform_device *pdev)
229 if (IS_ERR(wdev->base)) 249 if (IS_ERR(wdev->base))
230 return PTR_ERR(wdev->base); 250 return PTR_ERR(wdev->base);
231 251
232 omap_wdt->info = &omap_wdt_info; 252 wdev->wdog.info = &omap_wdt_info;
233 omap_wdt->ops = &omap_wdt_ops; 253 wdev->wdog.ops = &omap_wdt_ops;
234 omap_wdt->min_timeout = TIMER_MARGIN_MIN; 254 wdev->wdog.min_timeout = TIMER_MARGIN_MIN;
235 omap_wdt->max_timeout = TIMER_MARGIN_MAX; 255 wdev->wdog.max_timeout = TIMER_MARGIN_MAX;
236 256
237 if (timer_margin >= TIMER_MARGIN_MIN && 257 if (watchdog_init_timeout(&wdev->wdog, timer_margin, &pdev->dev) < 0)
238 timer_margin <= TIMER_MARGIN_MAX) 258 wdev->wdog.timeout = TIMER_MARGIN_DEFAULT;
239 omap_wdt->timeout = timer_margin;
240 else
241 omap_wdt->timeout = TIMER_MARGIN_DEFAULT;
242 259
243 watchdog_set_drvdata(omap_wdt, wdev); 260 watchdog_set_nowayout(&wdev->wdog, nowayout);
244 watchdog_set_nowayout(omap_wdt, nowayout);
245 261
246 platform_set_drvdata(pdev, omap_wdt); 262 platform_set_drvdata(pdev, wdev);
247 263
248 pm_runtime_enable(wdev->dev); 264 pm_runtime_enable(wdev->dev);
249 pm_runtime_get_sync(wdev->dev); 265 pm_runtime_get_sync(wdev->dev);
250 266
251 if (pdata && pdata->read_reset_sources) 267 if (pdata && pdata->read_reset_sources) {
252 rs = pdata->read_reset_sources(); 268 u32 rs = pdata->read_reset_sources();
253 else 269 if (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT))
254 rs = 0; 270 wdev->wdog.bootstatus = WDIOF_CARDRESET;
255 omap_wdt->bootstatus = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ? 271 }
256 WDIOF_CARDRESET : 0;
257 272
258 omap_wdt_disable(wdev); 273 omap_wdt_disable(wdev);
259 274
260 ret = watchdog_register_device(omap_wdt); 275 ret = watchdog_register_device(&wdev->wdog);
261 if (ret) { 276 if (ret) {
262 pm_runtime_disable(wdev->dev); 277 pm_runtime_disable(wdev->dev);
263 return ret; 278 return ret;
@@ -265,17 +280,19 @@ static int omap_wdt_probe(struct platform_device *pdev)
265 280
266 pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", 281 pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n",
267 readl_relaxed(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 282 readl_relaxed(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
268 omap_wdt->timeout); 283 wdev->wdog.timeout);
269 284
270 pm_runtime_put_sync(wdev->dev); 285 pm_runtime_put_sync(wdev->dev);
271 286
287 if (early_enable)
288 omap_wdt_start(&wdev->wdog);
289
272 return 0; 290 return 0;
273} 291}
274 292
275static void omap_wdt_shutdown(struct platform_device *pdev) 293static void omap_wdt_shutdown(struct platform_device *pdev)
276{ 294{
277 struct watchdog_device *wdog = platform_get_drvdata(pdev); 295 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
278 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
279 296
280 mutex_lock(&wdev->lock); 297 mutex_lock(&wdev->lock);
281 if (wdev->omap_wdt_users) { 298 if (wdev->omap_wdt_users) {
@@ -287,11 +304,10 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
287 304
288static int omap_wdt_remove(struct platform_device *pdev) 305static int omap_wdt_remove(struct platform_device *pdev)
289{ 306{
290 struct watchdog_device *wdog = platform_get_drvdata(pdev); 307 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
291 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
292 308
293 pm_runtime_disable(wdev->dev); 309 pm_runtime_disable(wdev->dev);
294 watchdog_unregister_device(wdog); 310 watchdog_unregister_device(&wdev->wdog);
295 311
296 return 0; 312 return 0;
297} 313}
@@ -306,8 +322,7 @@ static int omap_wdt_remove(struct platform_device *pdev)
306 322
307static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) 323static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
308{ 324{
309 struct watchdog_device *wdog = platform_get_drvdata(pdev); 325 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
310 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
311 326
312 mutex_lock(&wdev->lock); 327 mutex_lock(&wdev->lock);
313 if (wdev->omap_wdt_users) { 328 if (wdev->omap_wdt_users) {
@@ -321,8 +336,7 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
321 336
322static int omap_wdt_resume(struct platform_device *pdev) 337static int omap_wdt_resume(struct platform_device *pdev)
323{ 338{
324 struct watchdog_device *wdog = platform_get_drvdata(pdev); 339 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
325 struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
326 340
327 mutex_lock(&wdev->lock); 341 mutex_lock(&wdev->lock);
328 if (wdev->omap_wdt_users) { 342 if (wdev->omap_wdt_users) {
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index 09b774cf75b9..42f31ec5e90d 100644
--- a/drivers/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
@@ -50,5 +50,6 @@
50 50
51#define PTV 0 /* prescale */ 51#define PTV 0 /* prescale */
52#define GET_WLDR_VAL(secs) (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1) 52#define GET_WLDR_VAL(secs) (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
53#define GET_WCCR_SECS(val) ((0xffffffff - (val) + 1) / (32768/(1<<PTV)))
53 54
54#endif /* _OMAP_WATCHDOG_H */ 55#endif /* _OMAP_WATCHDOG_H */
diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c
index f32be155212a..6785afdc0fca 100644
--- a/drivers/watchdog/st_lpc_wdt.c
+++ b/drivers/watchdog/st_lpc_wdt.c
@@ -197,7 +197,7 @@ static int st_wdog_probe(struct platform_device *pdev)
197 return -EINVAL; 197 return -EINVAL;
198 } 198 }
199 199
200 /* LPC can either run in RTC or WDT mode */ 200 /* LPC can either run as a Clocksource or in RTC or WDT mode */
201 if (mode != ST_LPC_MODE_WDT) 201 if (mode != ST_LPC_MODE_WDT)
202 return -ENODEV; 202 return -ENODEV;
203 203
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index cec9b559647d..1a8059455413 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -43,6 +43,45 @@
43static DEFINE_IDA(watchdog_ida); 43static DEFINE_IDA(watchdog_ida);
44static struct class *watchdog_class; 44static struct class *watchdog_class;
45 45
46/*
47 * Deferred Registration infrastructure.
48 *
49 * Sometimes watchdog drivers needs to be loaded as soon as possible,
50 * for example when it's impossible to disable it. To do so,
51 * raising the initcall level of the watchdog driver is a solution.
52 * But in such case, the miscdev is maybe not ready (subsys_initcall), and
53 * watchdog_core need miscdev to register the watchdog as a char device.
54 *
55 * The deferred registration infrastructure offer a way for the watchdog
56 * subsystem to register a watchdog properly, even before miscdev is ready.
57 */
58
59static DEFINE_MUTEX(wtd_deferred_reg_mutex);
60static LIST_HEAD(wtd_deferred_reg_list);
61static bool wtd_deferred_reg_done;
62
63static int watchdog_deferred_registration_add(struct watchdog_device *wdd)
64{
65 list_add_tail(&wdd->deferred,
66 &wtd_deferred_reg_list);
67 return 0;
68}
69
70static void watchdog_deferred_registration_del(struct watchdog_device *wdd)
71{
72 struct list_head *p, *n;
73 struct watchdog_device *wdd_tmp;
74
75 list_for_each_safe(p, n, &wtd_deferred_reg_list) {
76 wdd_tmp = list_entry(p, struct watchdog_device,
77 deferred);
78 if (wdd_tmp == wdd) {
79 list_del(&wdd_tmp->deferred);
80 break;
81 }
82 }
83}
84
46static void watchdog_check_min_max_timeout(struct watchdog_device *wdd) 85static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
47{ 86{
48 /* 87 /*
@@ -98,17 +137,7 @@ int watchdog_init_timeout(struct watchdog_device *wdd,
98} 137}
99EXPORT_SYMBOL_GPL(watchdog_init_timeout); 138EXPORT_SYMBOL_GPL(watchdog_init_timeout);
100 139
101/** 140static int __watchdog_register_device(struct watchdog_device *wdd)
102 * watchdog_register_device() - register a watchdog device
103 * @wdd: watchdog device
104 *
105 * Register a watchdog device with the kernel so that the
106 * watchdog timer can be accessed from userspace.
107 *
108 * A zero is returned on success and a negative errno code for
109 * failure.
110 */
111int watchdog_register_device(struct watchdog_device *wdd)
112{ 141{
113 int ret, id, devno; 142 int ret, id, devno;
114 143
@@ -164,16 +193,33 @@ int watchdog_register_device(struct watchdog_device *wdd)
164 193
165 return 0; 194 return 0;
166} 195}
167EXPORT_SYMBOL_GPL(watchdog_register_device);
168 196
169/** 197/**
170 * watchdog_unregister_device() - unregister a watchdog device 198 * watchdog_register_device() - register a watchdog device
171 * @wdd: watchdog device to unregister 199 * @wdd: watchdog device
172 * 200 *
173 * Unregister a watchdog device that was previously successfully 201 * Register a watchdog device with the kernel so that the
174 * registered with watchdog_register_device(). 202 * watchdog timer can be accessed from userspace.
203 *
204 * A zero is returned on success and a negative errno code for
205 * failure.
175 */ 206 */
176void watchdog_unregister_device(struct watchdog_device *wdd) 207
208int watchdog_register_device(struct watchdog_device *wdd)
209{
210 int ret;
211
212 mutex_lock(&wtd_deferred_reg_mutex);
213 if (wtd_deferred_reg_done)
214 ret = __watchdog_register_device(wdd);
215 else
216 ret = watchdog_deferred_registration_add(wdd);
217 mutex_unlock(&wtd_deferred_reg_mutex);
218 return ret;
219}
220EXPORT_SYMBOL_GPL(watchdog_register_device);
221
222static void __watchdog_unregister_device(struct watchdog_device *wdd)
177{ 223{
178 int ret; 224 int ret;
179 int devno; 225 int devno;
@@ -189,8 +235,43 @@ void watchdog_unregister_device(struct watchdog_device *wdd)
189 ida_simple_remove(&watchdog_ida, wdd->id); 235 ida_simple_remove(&watchdog_ida, wdd->id);
190 wdd->dev = NULL; 236 wdd->dev = NULL;
191} 237}
238
239/**
240 * watchdog_unregister_device() - unregister a watchdog device
241 * @wdd: watchdog device to unregister
242 *
243 * Unregister a watchdog device that was previously successfully
244 * registered with watchdog_register_device().
245 */
246
247void watchdog_unregister_device(struct watchdog_device *wdd)
248{
249 mutex_lock(&wtd_deferred_reg_mutex);
250 if (wtd_deferred_reg_done)
251 __watchdog_unregister_device(wdd);
252 else
253 watchdog_deferred_registration_del(wdd);
254 mutex_unlock(&wtd_deferred_reg_mutex);
255}
256
192EXPORT_SYMBOL_GPL(watchdog_unregister_device); 257EXPORT_SYMBOL_GPL(watchdog_unregister_device);
193 258
259static int __init watchdog_deferred_registration(void)
260{
261 mutex_lock(&wtd_deferred_reg_mutex);
262 wtd_deferred_reg_done = true;
263 while (!list_empty(&wtd_deferred_reg_list)) {
264 struct watchdog_device *wdd;
265
266 wdd = list_first_entry(&wtd_deferred_reg_list,
267 struct watchdog_device, deferred);
268 list_del(&wdd->deferred);
269 __watchdog_register_device(wdd);
270 }
271 mutex_unlock(&wtd_deferred_reg_mutex);
272 return 0;
273}
274
194static int __init watchdog_init(void) 275static int __init watchdog_init(void)
195{ 276{
196 int err; 277 int err;
@@ -207,6 +288,7 @@ static int __init watchdog_init(void)
207 return err; 288 return err;
208 } 289 }
209 290
291 watchdog_deferred_registration();
210 return 0; 292 return 0;
211} 293}
212 294
@@ -217,7 +299,7 @@ static void __exit watchdog_exit(void)
217 ida_destroy(&watchdog_ida); 299 ida_destroy(&watchdog_ida);
218} 300}
219 301
220subsys_initcall(watchdog_init); 302subsys_initcall_sync(watchdog_init);
221module_exit(watchdog_exit); 303module_exit(watchdog_exit);
222 304
223MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>"); 305MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");