diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 18:12:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 18:12:59 -0400 |
commit | 51a73ba5f409ef6f419c8ec3a0d1257633500aaa (patch) | |
tree | 7bd3d8c4b9b6de178342bd48636b85da79ddbd18 | |
parent | e91eb6204fb826116453e43d4f5cf0f666bf46fe (diff) | |
parent | 6551881c86c791237a3bebf11eb3bd70b60ea782 (diff) |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- new driver for NXP LPC18xx Watchdog Timer
- new driver for SAMA5D4 watchdog timer
- add support for MCP79 to nv_tco driver
- clean-up and improvement of the mpc8xxx watchdog driver
- improvements to gpio-wdt
- at91sam9_wdt clock improvements
... and other small fixes and improvements
* git://www.linux-watchdog.org/linux-watchdog: (25 commits)
Watchdog: Fix parent of watchdog_devices
watchdog: at91rm9200: Correct check for syscon_node_to_regmap() errors
watchdog: at91sam9: get and use slow clock
Documentation: dt: binding: atmel-sama5d4-wdt: for SAMA5D4 watchdog driver
watchdog: add a driver to support SAMA5D4 watchdog timer
watchdog: mpc8xxx: allow to compile for MPC512x
watchdog: mpc8xxx: use better error code when watchdog cannot be enabled
watchdog: mpc8xxx: use dynamic memory for device specific data
watchdog: mpc8xxx: use devm_ioremap_resource to map memory
watchdog: mpc8xxx: make use of of_device_get_match_data
watchdog: mpc8xxx: simplify registration
watchdog: mpc8xxx: remove dead code
watchdog: lpc18xx_wdt_get_timeleft() can be static
DT: watchdog: Add NXP LPC18xx Watchdog Timer binding documentation
watchdog: NXP LPC18xx Watchdog Timer Driver
watchdog: gpio-wdt: ping already at startup for always running devices
watchdog: gpio-wdt: be more strict about hw_algo matching
Documentation: watchdog: at91sam9_wdt: add clocks property
watchdog: booke_wdt: Use infrastructure to check timeout limits
watchdog: (nv_tco) add support for MCP79
...
53 files changed, 916 insertions, 135 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt new file mode 100644 index 000000000000..f7cc7c060910 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt | |||
@@ -0,0 +1,35 @@ | |||
1 | * Atmel SAMA5D4 Watchdog Timer (WDT) Controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "atmel,sama5d4-wdt" | ||
5 | - reg: base physical address and length of memory mapped region. | ||
6 | |||
7 | Optional properties: | ||
8 | - timeout-sec: watchdog timeout value (in seconds). | ||
9 | - interrupts: interrupt number to the CPU. | ||
10 | - atmel,watchdog-type: should be "hardware" or "software". | ||
11 | "hardware": enable watchdog fault reset. A watchdog fault triggers | ||
12 | watchdog reset. | ||
13 | "software": enable watchdog fault interrupt. A watchdog fault asserts | ||
14 | watchdog interrupt. | ||
15 | - atmel,idle-halt: present if you want to stop the watchdog when the CPU is | ||
16 | in idle state. | ||
17 | CAUTION: This property should be used with care, it actually makes the | ||
18 | watchdog not counting when the CPU is in idle state, therefore the | ||
19 | watchdog reset time depends on mean CPU usage and will not reset at all | ||
20 | if the CPU stop working while it is in idle state, which is probably | ||
21 | not what you want. | ||
22 | - atmel,dbg-halt: present if you want to stop the watchdog when the CPU is | ||
23 | in debug state. | ||
24 | |||
25 | Example: | ||
26 | watchdog@fc068640 { | ||
27 | compatible = "atmel,sama5d4-wdt"; | ||
28 | reg = <0xfc068640 0x10>; | ||
29 | interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>; | ||
30 | timeout-sec = <10>; | ||
31 | atmel,watchdog-type = "hardware"; | ||
32 | atmel,dbg-halt; | ||
33 | atmel,idle-halt; | ||
34 | status = "okay"; | ||
35 | }; | ||
diff --git a/Documentation/devicetree/bindings/watchdog/lpc18xx-wdt.txt b/Documentation/devicetree/bindings/watchdog/lpc18xx-wdt.txt new file mode 100644 index 000000000000..09f6b24969e0 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/lpc18xx-wdt.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | * NXP LPC18xx Watchdog Timer (WDT) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "nxp,lpc1850-wwdt" | ||
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 "wdtclk" and "reg"; the watchdog counter | ||
8 | clock and register interface clock respectively. | ||
9 | - interrupts: Should contain WDT interrupt | ||
10 | |||
11 | Examples: | ||
12 | |||
13 | watchdog@40080000 { | ||
14 | compatible = "nxp,lpc1850-wwdt"; | ||
15 | reg = <0x40080000 0x24>; | ||
16 | clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_WWDT>; | ||
17 | clock-names = "wdtclk", "reg"; | ||
18 | interrupts = <49>; | ||
19 | }; | ||
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c index 3da822967ee0..fcdde8fc98be 100644 --- a/Documentation/watchdog/src/watchdog-test.c +++ b/Documentation/watchdog/src/watchdog-test.c | |||
@@ -41,6 +41,7 @@ static void term(int sig) | |||
41 | int main(int argc, char *argv[]) | 41 | int main(int argc, char *argv[]) |
42 | { | 42 | { |
43 | int flags; | 43 | int flags; |
44 | unsigned int ping_rate = 1; | ||
44 | 45 | ||
45 | fd = open("/dev/watchdog", O_WRONLY); | 46 | fd = open("/dev/watchdog", O_WRONLY); |
46 | 47 | ||
@@ -63,22 +64,33 @@ int main(int argc, char *argv[]) | |||
63 | fprintf(stderr, "Watchdog card enabled.\n"); | 64 | fprintf(stderr, "Watchdog card enabled.\n"); |
64 | fflush(stderr); | 65 | fflush(stderr); |
65 | goto end; | 66 | goto end; |
67 | } else if (!strncasecmp(argv[1], "-t", 2) && argv[2]) { | ||
68 | flags = atoi(argv[2]); | ||
69 | ioctl(fd, WDIOC_SETTIMEOUT, &flags); | ||
70 | fprintf(stderr, "Watchdog timeout set to %u seconds.\n", flags); | ||
71 | fflush(stderr); | ||
72 | goto end; | ||
73 | } else if (!strncasecmp(argv[1], "-p", 2) && argv[2]) { | ||
74 | ping_rate = strtoul(argv[2], NULL, 0); | ||
75 | fprintf(stderr, "Watchdog ping rate set to %u seconds.\n", ping_rate); | ||
76 | fflush(stderr); | ||
66 | } else { | 77 | } else { |
67 | fprintf(stderr, "-d to disable, -e to enable.\n"); | 78 | fprintf(stderr, "-d to disable, -e to enable, -t <n> to set " \ |
79 | "the timeout,\n-p <n> to set the ping rate, and \n"); | ||
68 | fprintf(stderr, "run by itself to tick the card.\n"); | 80 | fprintf(stderr, "run by itself to tick the card.\n"); |
69 | fflush(stderr); | 81 | fflush(stderr); |
70 | goto end; | 82 | goto end; |
71 | } | 83 | } |
72 | } else { | ||
73 | fprintf(stderr, "Watchdog Ticking Away!\n"); | ||
74 | fflush(stderr); | ||
75 | } | 84 | } |
76 | 85 | ||
86 | fprintf(stderr, "Watchdog Ticking Away!\n"); | ||
87 | fflush(stderr); | ||
88 | |||
77 | signal(SIGINT, term); | 89 | signal(SIGINT, term); |
78 | 90 | ||
79 | while(1) { | 91 | while(1) { |
80 | keep_alive(); | 92 | keep_alive(); |
81 | sleep(1); | 93 | sleep(ping_rate); |
82 | } | 94 | } |
83 | end: | 95 | end: |
84 | close(fd); | 96 | close(fd); |
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 2bc0f5089f82..b346638833b0 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c | |||
@@ -364,6 +364,7 @@ int mei_watchdog_register(struct mei_device *dev) | |||
364 | 364 | ||
365 | int ret; | 365 | int ret; |
366 | 366 | ||
367 | amt_wd_dev.parent = dev->dev; | ||
367 | /* unlock to perserve correct locking order */ | 368 | /* unlock to perserve correct locking order */ |
368 | mutex_unlock(&dev->device_lock); | 369 | mutex_unlock(&dev->device_lock); |
369 | ret = watchdog_register_device(&amt_wd_dev); | 370 | ret = watchdog_register_device(&amt_wd_dev); |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 55c4b5b0a317..c68edc16aa54 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -188,6 +188,15 @@ config AT91SAM9X_WATCHDOG | |||
188 | Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will | 188 | Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will |
189 | reboot your system when the timeout is reached. | 189 | reboot your system when the timeout is reached. |
190 | 190 | ||
191 | config SAMA5D4_WATCHDOG | ||
192 | tristate "Atmel SAMA5D4 Watchdog Timer" | ||
193 | depends on ARCH_AT91 | ||
194 | select WATCHDOG_CORE | ||
195 | help | ||
196 | Atmel SAMA5D4 watchdog timer is embedded into SAMA5D4 chips. | ||
197 | Its Watchdog Timer Mode Register can be written more than once. | ||
198 | This will reboot your system when the timeout is reached. | ||
199 | |||
191 | config CADENCE_WATCHDOG | 200 | config CADENCE_WATCHDOG |
192 | tristate "Cadence Watchdog Timer" | 201 | tristate "Cadence Watchdog Timer" |
193 | depends on HAS_IOMEM | 202 | depends on HAS_IOMEM |
@@ -558,6 +567,17 @@ config DIGICOLOR_WATCHDOG | |||
558 | To compile this driver as a module, choose M here: the | 567 | To compile this driver as a module, choose M here: the |
559 | module will be called digicolor_wdt. | 568 | module will be called digicolor_wdt. |
560 | 569 | ||
570 | config LPC18XX_WATCHDOG | ||
571 | tristate "LPC18xx/43xx Watchdog" | ||
572 | depends on ARCH_LPC18XX || COMPILE_TEST | ||
573 | select WATCHDOG_CORE | ||
574 | help | ||
575 | Say Y here if to include support for the watchdog timer | ||
576 | in NXP LPC SoCs family, which includes LPC18xx/LPC43xx | ||
577 | processors. | ||
578 | To compile this driver as a module, choose M here: the | ||
579 | module will be called lpc18xx_wdt. | ||
580 | |||
561 | # AVR32 Architecture | 581 | # AVR32 Architecture |
562 | 582 | ||
563 | config AT32AP700X_WDT | 583 | config AT32AP700X_WDT |
@@ -1334,7 +1354,7 @@ config MPC5200_WDT | |||
1334 | 1354 | ||
1335 | config 8xxx_WDT | 1355 | config 8xxx_WDT |
1336 | tristate "MPC8xxx Platform Watchdog Timer" | 1356 | tristate "MPC8xxx Platform Watchdog Timer" |
1337 | depends on PPC_8xx || PPC_83xx || PPC_86xx | 1357 | depends on PPC_8xx || PPC_83xx || PPC_86xx || PPC_MPC512x |
1338 | select WATCHDOG_CORE | 1358 | select WATCHDOG_CORE |
1339 | help | 1359 | help |
1340 | This driver is for a SoC level watchdog that exists on some | 1360 | This driver is for a SoC level watchdog that exists on some |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 59ea9a1b8e76..0c616e3f67bb 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | |||
41 | obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o | 41 | obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o |
42 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o | 42 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o |
43 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | 43 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o |
44 | obj-$(CONFIG_SAMA5D4_WATCHDOG) += sama5d4_wdt.o | ||
44 | obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o | 45 | obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o |
45 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | 46 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o |
46 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 47 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
@@ -66,6 +67,7 @@ obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o | |||
66 | obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o | 67 | obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o |
67 | obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o | 68 | obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o |
68 | obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o | 69 | obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o |
70 | obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o | ||
69 | 71 | ||
70 | # AVR32 Architecture | 72 | # AVR32 Architecture |
71 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 73 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index 9ba1153465ae..e12a797cb820 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c | |||
@@ -244,7 +244,7 @@ static int at91wdt_probe(struct platform_device *pdev) | |||
244 | } | 244 | } |
245 | 245 | ||
246 | regmap_st = syscon_node_to_regmap(parent->of_node); | 246 | regmap_st = syscon_node_to_regmap(parent->of_node); |
247 | if (!regmap_st) | 247 | if (IS_ERR(regmap_st)) |
248 | return -ENODEV; | 248 | return -ENODEV; |
249 | 249 | ||
250 | res = misc_register(&at91wdt_miscdev); | 250 | res = misc_register(&at91wdt_miscdev); |
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index e4698f7c5f93..7e6acaf3ece4 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | 19 | ||
20 | #include <linux/clk.h> | ||
20 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
@@ -90,6 +91,7 @@ struct at91wdt { | |||
90 | unsigned long heartbeat; /* WDT heartbeat in jiffies */ | 91 | unsigned long heartbeat; /* WDT heartbeat in jiffies */ |
91 | bool nowayout; | 92 | bool nowayout; |
92 | unsigned int irq; | 93 | unsigned int irq; |
94 | struct clk *sclk; | ||
93 | }; | 95 | }; |
94 | 96 | ||
95 | /* ......................................................................... */ | 97 | /* ......................................................................... */ |
@@ -352,15 +354,25 @@ static int __init at91wdt_probe(struct platform_device *pdev) | |||
352 | if (IS_ERR(wdt->base)) | 354 | if (IS_ERR(wdt->base)) |
353 | return PTR_ERR(wdt->base); | 355 | return PTR_ERR(wdt->base); |
354 | 356 | ||
357 | wdt->sclk = devm_clk_get(&pdev->dev, NULL); | ||
358 | if (IS_ERR(wdt->sclk)) | ||
359 | return PTR_ERR(wdt->sclk); | ||
360 | |||
361 | err = clk_prepare_enable(wdt->sclk); | ||
362 | if (err) { | ||
363 | dev_err(&pdev->dev, "Could not enable slow clock\n"); | ||
364 | return err; | ||
365 | } | ||
366 | |||
355 | if (pdev->dev.of_node) { | 367 | if (pdev->dev.of_node) { |
356 | err = of_at91wdt_init(pdev->dev.of_node, wdt); | 368 | err = of_at91wdt_init(pdev->dev.of_node, wdt); |
357 | if (err) | 369 | if (err) |
358 | return err; | 370 | goto err_clk; |
359 | } | 371 | } |
360 | 372 | ||
361 | err = at91_wdt_init(pdev, wdt); | 373 | err = at91_wdt_init(pdev, wdt); |
362 | if (err) | 374 | if (err) |
363 | return err; | 375 | goto err_clk; |
364 | 376 | ||
365 | platform_set_drvdata(pdev, wdt); | 377 | platform_set_drvdata(pdev, wdt); |
366 | 378 | ||
@@ -368,6 +380,11 @@ static int __init at91wdt_probe(struct platform_device *pdev) | |||
368 | wdt->wdd.timeout, wdt->nowayout); | 380 | wdt->wdd.timeout, wdt->nowayout); |
369 | 381 | ||
370 | return 0; | 382 | return 0; |
383 | |||
384 | err_clk: | ||
385 | clk_disable_unprepare(wdt->sclk); | ||
386 | |||
387 | return err; | ||
371 | } | 388 | } |
372 | 389 | ||
373 | static int __exit at91wdt_remove(struct platform_device *pdev) | 390 | static int __exit at91wdt_remove(struct platform_device *pdev) |
@@ -377,6 +394,7 @@ static int __exit at91wdt_remove(struct platform_device *pdev) | |||
377 | 394 | ||
378 | pr_warn("I quit now, hardware will probably reboot!\n"); | 395 | pr_warn("I quit now, hardware will probably reboot!\n"); |
379 | del_timer(&wdt->timer); | 396 | del_timer(&wdt->timer); |
397 | clk_disable_unprepare(wdt->sclk); | ||
380 | 398 | ||
381 | return 0; | 399 | return 0; |
382 | } | 400 | } |
diff --git a/drivers/watchdog/at91sam9_wdt.h b/drivers/watchdog/at91sam9_wdt.h index c6fbb2e6c41b..b79a83b467ce 100644 --- a/drivers/watchdog/at91sam9_wdt.h +++ b/drivers/watchdog/at91sam9_wdt.h | |||
@@ -22,11 +22,13 @@ | |||
22 | 22 | ||
23 | #define AT91_WDT_MR 0x04 /* Watchdog Mode Register */ | 23 | #define AT91_WDT_MR 0x04 /* Watchdog Mode Register */ |
24 | #define AT91_WDT_WDV (0xfff << 0) /* Counter Value */ | 24 | #define AT91_WDT_WDV (0xfff << 0) /* Counter Value */ |
25 | #define AT91_WDT_SET_WDV(x) ((x) & AT91_WDT_WDV) | ||
25 | #define AT91_WDT_WDFIEN (1 << 12) /* Fault Interrupt Enable */ | 26 | #define AT91_WDT_WDFIEN (1 << 12) /* Fault Interrupt Enable */ |
26 | #define AT91_WDT_WDRSTEN (1 << 13) /* Reset Processor */ | 27 | #define AT91_WDT_WDRSTEN (1 << 13) /* Reset Processor */ |
27 | #define AT91_WDT_WDRPROC (1 << 14) /* Timer Restart */ | 28 | #define AT91_WDT_WDRPROC (1 << 14) /* Timer Restart */ |
28 | #define AT91_WDT_WDDIS (1 << 15) /* Watchdog Disable */ | 29 | #define AT91_WDT_WDDIS (1 << 15) /* Watchdog Disable */ |
29 | #define AT91_WDT_WDD (0xfff << 16) /* Delta Value */ | 30 | #define AT91_WDT_WDD (0xfff << 16) /* Delta Value */ |
31 | #define AT91_WDT_SET_WDD(x) (((x) << 16) & AT91_WDT_WDD) | ||
30 | #define AT91_WDT_WDDBGHLT (1 << 28) /* Debug Halt */ | 32 | #define AT91_WDT_WDDBGHLT (1 << 28) /* Debug Halt */ |
31 | #define AT91_WDT_WDIDLEHLT (1 << 29) /* Idle Halt */ | 33 | #define AT91_WDT_WDIDLEHLT (1 << 29) /* Idle Halt */ |
32 | 34 | ||
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index 7116968dee12..66c3e656a616 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c | |||
@@ -182,6 +182,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) | |||
182 | watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt); | 182 | watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt); |
183 | watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); | 183 | watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); |
184 | watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout); | 184 | watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout); |
185 | bcm2835_wdt_wdd.parent = &pdev->dev; | ||
185 | err = watchdog_register_device(&bcm2835_wdt_wdd); | 186 | err = watchdog_register_device(&bcm2835_wdt_wdd); |
186 | if (err) { | 187 | if (err) { |
187 | dev_err(dev, "Failed to register watchdog device"); | 188 | dev_err(dev, "Failed to register watchdog device"); |
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index b28a072abf78..4064a43f1360 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c | |||
@@ -209,6 +209,7 @@ static int bcm47xx_wdt_probe(struct platform_device *pdev) | |||
209 | 209 | ||
210 | wdt->wdd.info = &bcm47xx_wdt_info; | 210 | wdt->wdd.info = &bcm47xx_wdt_info; |
211 | wdt->wdd.timeout = WDT_DEFAULT_TIME; | 211 | wdt->wdd.timeout = WDT_DEFAULT_TIME; |
212 | wdt->wdd.parent = &pdev->dev; | ||
212 | ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout); | 213 | ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout); |
213 | if (ret) | 214 | if (ret) |
214 | goto err_timer; | 215 | goto err_timer; |
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 22d8ae65772a..e0c98423f2c9 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c | |||
@@ -319,6 +319,7 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) | |||
319 | spin_lock_init(&wdt->lock); | 319 | spin_lock_init(&wdt->lock); |
320 | platform_set_drvdata(pdev, wdt); | 320 | platform_set_drvdata(pdev, wdt); |
321 | watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); | 321 | watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); |
322 | bcm_kona_wdt_wdd.parent = &pdev->dev; | ||
322 | 323 | ||
323 | ret = bcm_kona_wdt_set_timeout_reg(&bcm_kona_wdt_wdd, 0); | 324 | ret = bcm_kona_wdt_set_timeout_reg(&bcm_kona_wdt_wdd, 0); |
324 | if (ret) { | 325 | if (ret) { |
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index e96b09b135c8..04da4b66c75e 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c | |||
@@ -186,8 +186,6 @@ static int booke_wdt_stop(struct watchdog_device *wdog) | |||
186 | static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, | 186 | static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, |
187 | unsigned int timeout) | 187 | unsigned int timeout) |
188 | { | 188 | { |
189 | if (timeout > MAX_WDT_TIMEOUT) | ||
190 | return -EINVAL; | ||
191 | wdt_dev->timeout = timeout; | 189 | wdt_dev->timeout = timeout; |
192 | booke_wdt_set(wdt_dev); | 190 | booke_wdt_set(wdt_dev); |
193 | 191 | ||
@@ -211,7 +209,6 @@ static struct watchdog_device booke_wdt_dev = { | |||
211 | .info = &booke_wdt_info, | 209 | .info = &booke_wdt_info, |
212 | .ops = &booke_wdt_ops, | 210 | .ops = &booke_wdt_ops, |
213 | .min_timeout = 1, | 211 | .min_timeout = 1, |
214 | .max_timeout = 0xFFFF | ||
215 | }; | 212 | }; |
216 | 213 | ||
217 | static void __exit booke_wdt_exit(void) | 214 | static void __exit booke_wdt_exit(void) |
@@ -229,6 +226,7 @@ static int __init booke_wdt_init(void) | |||
229 | booke_wdt_set_timeout(&booke_wdt_dev, | 226 | booke_wdt_set_timeout(&booke_wdt_dev, |
230 | period_to_sec(booke_wdt_period)); | 227 | period_to_sec(booke_wdt_period)); |
231 | watchdog_set_nowayout(&booke_wdt_dev, nowayout); | 228 | watchdog_set_nowayout(&booke_wdt_dev, nowayout); |
229 | booke_wdt_dev.max_timeout = MAX_WDT_TIMEOUT; | ||
232 | if (booke_wdt_enabled) | 230 | if (booke_wdt_enabled) |
233 | booke_wdt_start(&booke_wdt_dev); | 231 | booke_wdt_start(&booke_wdt_dev); |
234 | 232 | ||
diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c index ce12f437f195..a099b77fc0b9 100644 --- a/drivers/watchdog/coh901327_wdt.c +++ b/drivers/watchdog/coh901327_wdt.c | |||
@@ -358,6 +358,7 @@ static int __init coh901327_probe(struct platform_device *pdev) | |||
358 | if (ret < 0) | 358 | if (ret < 0) |
359 | coh901327_wdt.timeout = 60; | 359 | coh901327_wdt.timeout = 60; |
360 | 360 | ||
361 | coh901327_wdt.parent = &pdev->dev; | ||
361 | ret = watchdog_register_device(&coh901327_wdt); | 362 | ret = watchdog_register_device(&coh901327_wdt); |
362 | if (ret == 0) | 363 | if (ret == 0) |
363 | dev_info(&pdev->dev, | 364 | dev_info(&pdev->dev, |
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c index 2e9589652e1e..67e67977bd29 100644 --- a/drivers/watchdog/da9052_wdt.c +++ b/drivers/watchdog/da9052_wdt.c | |||
@@ -195,6 +195,7 @@ static int da9052_wdt_probe(struct platform_device *pdev) | |||
195 | da9052_wdt->timeout = DA9052_DEF_TIMEOUT; | 195 | da9052_wdt->timeout = DA9052_DEF_TIMEOUT; |
196 | da9052_wdt->info = &da9052_wdt_info; | 196 | da9052_wdt->info = &da9052_wdt_info; |
197 | da9052_wdt->ops = &da9052_wdt_ops; | 197 | da9052_wdt->ops = &da9052_wdt_ops; |
198 | da9052_wdt->parent = &pdev->dev; | ||
198 | watchdog_set_drvdata(da9052_wdt, driver_data); | 199 | watchdog_set_drvdata(da9052_wdt, driver_data); |
199 | 200 | ||
200 | kref_init(&driver_data->kref); | 201 | kref_init(&driver_data->kref); |
diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c index 495089d8dbfe..04d1430d93d2 100644 --- a/drivers/watchdog/da9055_wdt.c +++ b/drivers/watchdog/da9055_wdt.c | |||
@@ -161,6 +161,7 @@ static int da9055_wdt_probe(struct platform_device *pdev) | |||
161 | da9055_wdt->timeout = DA9055_DEF_TIMEOUT; | 161 | da9055_wdt->timeout = DA9055_DEF_TIMEOUT; |
162 | da9055_wdt->info = &da9055_wdt_info; | 162 | da9055_wdt->info = &da9055_wdt_info; |
163 | da9055_wdt->ops = &da9055_wdt_ops; | 163 | da9055_wdt->ops = &da9055_wdt_ops; |
164 | da9055_wdt->parent = &pdev->dev; | ||
164 | watchdog_set_nowayout(da9055_wdt, nowayout); | 165 | watchdog_set_nowayout(da9055_wdt, nowayout); |
165 | watchdog_set_drvdata(da9055_wdt, driver_data); | 166 | watchdog_set_drvdata(da9055_wdt, driver_data); |
166 | 167 | ||
diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index b3a870ce85be..7386111220d5 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c | |||
@@ -210,6 +210,7 @@ static int da9062_wdt_probe(struct platform_device *pdev) | |||
210 | wdt->wdtdev.max_timeout = DA9062_WDT_MAX_TIMEOUT; | 210 | wdt->wdtdev.max_timeout = DA9062_WDT_MAX_TIMEOUT; |
211 | wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT; | 211 | wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT; |
212 | wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; | 212 | wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; |
213 | wdt->wdtdev.parent = &pdev->dev; | ||
213 | 214 | ||
214 | watchdog_set_drvdata(&wdt->wdtdev, wdt); | 215 | watchdog_set_drvdata(&wdt->wdtdev, wdt); |
215 | dev_set_drvdata(&pdev->dev, wdt); | 216 | dev_set_drvdata(&pdev->dev, wdt); |
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c index e2fe2ebdebd4..6bf130bd863d 100644 --- a/drivers/watchdog/da9063_wdt.c +++ b/drivers/watchdog/da9063_wdt.c | |||
@@ -175,6 +175,7 @@ static int da9063_wdt_probe(struct platform_device *pdev) | |||
175 | wdt->wdtdev.min_timeout = DA9063_WDT_MIN_TIMEOUT; | 175 | wdt->wdtdev.min_timeout = DA9063_WDT_MIN_TIMEOUT; |
176 | wdt->wdtdev.max_timeout = DA9063_WDT_MAX_TIMEOUT; | 176 | wdt->wdtdev.max_timeout = DA9063_WDT_MAX_TIMEOUT; |
177 | wdt->wdtdev.timeout = DA9063_WDG_TIMEOUT; | 177 | wdt->wdtdev.timeout = DA9063_WDG_TIMEOUT; |
178 | wdt->wdtdev.parent = &pdev->dev; | ||
178 | 179 | ||
179 | wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; | 180 | wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; |
180 | 181 | ||
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index cfdf8a408aea..17454ca653f4 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c | |||
@@ -179,6 +179,7 @@ static int davinci_wdt_probe(struct platform_device *pdev) | |||
179 | wdd->min_timeout = 1; | 179 | wdd->min_timeout = 1; |
180 | wdd->max_timeout = MAX_HEARTBEAT; | 180 | wdd->max_timeout = MAX_HEARTBEAT; |
181 | wdd->timeout = DEFAULT_HEARTBEAT; | 181 | wdd->timeout = DEFAULT_HEARTBEAT; |
182 | wdd->parent = &pdev->dev; | ||
182 | 183 | ||
183 | watchdog_init_timeout(wdd, heartbeat, dev); | 184 | watchdog_init_timeout(wdd, heartbeat, dev); |
184 | 185 | ||
diff --git a/drivers/watchdog/digicolor_wdt.c b/drivers/watchdog/digicolor_wdt.c index 31d8e4936611..50abe1bf62a5 100644 --- a/drivers/watchdog/digicolor_wdt.c +++ b/drivers/watchdog/digicolor_wdt.c | |||
@@ -143,6 +143,7 @@ static int dc_wdt_probe(struct platform_device *pdev) | |||
143 | } | 143 | } |
144 | dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk); | 144 | dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk); |
145 | dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout; | 145 | dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout; |
146 | dc_wdt_wdd.parent = &pdev->dev; | ||
146 | 147 | ||
147 | spin_lock_init(&wdt->lock); | 148 | spin_lock_init(&wdt->lock); |
148 | 149 | ||
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 7a2cc7191c58..0a4d7cc05d54 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c | |||
@@ -132,6 +132,7 @@ static int ep93xx_wdt_probe(struct platform_device *pdev) | |||
132 | val = readl(mmio_base + EP93XX_WATCHDOG); | 132 | val = readl(mmio_base + EP93XX_WATCHDOG); |
133 | ep93xx_wdt_wdd.bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0; | 133 | ep93xx_wdt_wdd.bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0; |
134 | ep93xx_wdt_wdd.timeout = timeout; | 134 | ep93xx_wdt_wdd.timeout = timeout; |
135 | ep93xx_wdt_wdd.parent = &pdev->dev; | ||
135 | 136 | ||
136 | watchdog_set_nowayout(&ep93xx_wdt_wdd, nowayout); | 137 | watchdog_set_nowayout(&ep93xx_wdt_wdd, nowayout); |
137 | 138 | ||
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 1687cc2d7122..90d59d3f38a3 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c | |||
@@ -50,12 +50,41 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv) | |||
50 | gpio_direction_input(priv->gpio); | 50 | gpio_direction_input(priv->gpio); |
51 | } | 51 | } |
52 | 52 | ||
53 | static void gpio_wdt_hwping(unsigned long data) | ||
54 | { | ||
55 | struct watchdog_device *wdd = (struct watchdog_device *)data; | ||
56 | struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); | ||
57 | |||
58 | if (priv->armed && time_after(jiffies, priv->last_jiffies + | ||
59 | msecs_to_jiffies(wdd->timeout * 1000))) { | ||
60 | dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n"); | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | /* Restart timer */ | ||
65 | mod_timer(&priv->timer, jiffies + priv->hw_margin); | ||
66 | |||
67 | switch (priv->hw_algo) { | ||
68 | case HW_ALGO_TOGGLE: | ||
69 | /* Toggle output pin */ | ||
70 | priv->state = !priv->state; | ||
71 | gpio_set_value_cansleep(priv->gpio, priv->state); | ||
72 | break; | ||
73 | case HW_ALGO_LEVEL: | ||
74 | /* Pulse */ | ||
75 | gpio_set_value_cansleep(priv->gpio, !priv->active_low); | ||
76 | udelay(1); | ||
77 | gpio_set_value_cansleep(priv->gpio, priv->active_low); | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | |||
53 | static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv) | 82 | static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv) |
54 | { | 83 | { |
55 | priv->state = priv->active_low; | 84 | priv->state = priv->active_low; |
56 | gpio_direction_output(priv->gpio, priv->state); | 85 | gpio_direction_output(priv->gpio, priv->state); |
57 | priv->last_jiffies = jiffies; | 86 | priv->last_jiffies = jiffies; |
58 | mod_timer(&priv->timer, priv->last_jiffies + priv->hw_margin); | 87 | gpio_wdt_hwping((unsigned long)&priv->wdd); |
59 | } | 88 | } |
60 | 89 | ||
61 | static int gpio_wdt_start(struct watchdog_device *wdd) | 90 | static int gpio_wdt_start(struct watchdog_device *wdd) |
@@ -97,35 +126,6 @@ static int gpio_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) | |||
97 | return gpio_wdt_ping(wdd); | 126 | return gpio_wdt_ping(wdd); |
98 | } | 127 | } |
99 | 128 | ||
100 | static void gpio_wdt_hwping(unsigned long data) | ||
101 | { | ||
102 | struct watchdog_device *wdd = (struct watchdog_device *)data; | ||
103 | struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); | ||
104 | |||
105 | if (priv->armed && time_after(jiffies, priv->last_jiffies + | ||
106 | msecs_to_jiffies(wdd->timeout * 1000))) { | ||
107 | dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n"); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | /* Restart timer */ | ||
112 | mod_timer(&priv->timer, jiffies + priv->hw_margin); | ||
113 | |||
114 | switch (priv->hw_algo) { | ||
115 | case HW_ALGO_TOGGLE: | ||
116 | /* Toggle output pin */ | ||
117 | priv->state = !priv->state; | ||
118 | gpio_set_value_cansleep(priv->gpio, priv->state); | ||
119 | break; | ||
120 | case HW_ALGO_LEVEL: | ||
121 | /* Pulse */ | ||
122 | gpio_set_value_cansleep(priv->gpio, !priv->active_low); | ||
123 | udelay(1); | ||
124 | gpio_set_value_cansleep(priv->gpio, priv->active_low); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code, | 129 | static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code, |
130 | void *unused) | 130 | void *unused) |
131 | { | 131 | { |
@@ -182,10 +182,10 @@ static int gpio_wdt_probe(struct platform_device *pdev) | |||
182 | ret = of_property_read_string(pdev->dev.of_node, "hw_algo", &algo); | 182 | ret = of_property_read_string(pdev->dev.of_node, "hw_algo", &algo); |
183 | if (ret) | 183 | if (ret) |
184 | return ret; | 184 | return ret; |
185 | if (!strncmp(algo, "toggle", 6)) { | 185 | if (!strcmp(algo, "toggle")) { |
186 | priv->hw_algo = HW_ALGO_TOGGLE; | 186 | priv->hw_algo = HW_ALGO_TOGGLE; |
187 | f = GPIOF_IN; | 187 | f = GPIOF_IN; |
188 | } else if (!strncmp(algo, "level", 5)) { | 188 | } else if (!strcmp(algo, "level")) { |
189 | priv->hw_algo = HW_ALGO_LEVEL; | 189 | priv->hw_algo = HW_ALGO_LEVEL; |
190 | f = priv->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; | 190 | f = priv->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; |
191 | } else { | 191 | } else { |
@@ -217,6 +217,7 @@ static int gpio_wdt_probe(struct platform_device *pdev) | |||
217 | priv->wdd.ops = &gpio_wdt_ops; | 217 | priv->wdd.ops = &gpio_wdt_ops; |
218 | priv->wdd.min_timeout = SOFT_TIMEOUT_MIN; | 218 | priv->wdd.min_timeout = SOFT_TIMEOUT_MIN; |
219 | priv->wdd.max_timeout = SOFT_TIMEOUT_MAX; | 219 | priv->wdd.max_timeout = SOFT_TIMEOUT_MAX; |
220 | priv->wdd.parent = &pdev->dev; | ||
220 | 221 | ||
221 | if (watchdog_init_timeout(&priv->wdd, 0, &pdev->dev) < 0) | 222 | if (watchdog_init_timeout(&priv->wdd, 0, &pdev->dev) < 0) |
222 | priv->wdd.timeout = SOFT_TIMEOUT_DEF; | 223 | priv->wdd.timeout = SOFT_TIMEOUT_DEF; |
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c index 9bc39ae51624..78c2541f5d52 100644 --- a/drivers/watchdog/ie6xx_wdt.c +++ b/drivers/watchdog/ie6xx_wdt.c | |||
@@ -267,6 +267,7 @@ static int ie6xx_wdt_probe(struct platform_device *pdev) | |||
267 | 267 | ||
268 | ie6xx_wdt_dev.timeout = timeout; | 268 | ie6xx_wdt_dev.timeout = timeout; |
269 | watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); | 269 | watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); |
270 | ie6xx_wdt_dev.parent = &pdev->dev; | ||
270 | 271 | ||
271 | spin_lock_init(&ie6xx_wdt_data.unlock_sequence); | 272 | spin_lock_init(&ie6xx_wdt_data.unlock_sequence); |
272 | 273 | ||
diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c index 0f73621827ab..15ab07230960 100644 --- a/drivers/watchdog/imgpdc_wdt.c +++ b/drivers/watchdog/imgpdc_wdt.c | |||
@@ -316,6 +316,7 @@ static int pdc_wdt_remove(struct platform_device *pdev) | |||
316 | { | 316 | { |
317 | struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev); | 317 | struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev); |
318 | 318 | ||
319 | unregister_restart_handler(&pdc_wdt->restart_handler); | ||
319 | pdc_wdt_stop(&pdc_wdt->wdt_dev); | 320 | pdc_wdt_stop(&pdc_wdt->wdt_dev); |
320 | watchdog_unregister_device(&pdc_wdt->wdt_dev); | 321 | watchdog_unregister_device(&pdc_wdt->wdt_dev); |
321 | clk_disable_unprepare(pdc_wdt->wdt_clk); | 322 | clk_disable_unprepare(pdc_wdt->wdt_clk); |
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 84f6701c391f..0a436b5d1e84 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c | |||
@@ -137,6 +137,7 @@ static int mid_wdt_probe(struct platform_device *pdev) | |||
137 | wdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN; | 137 | wdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN; |
138 | wdt_dev->max_timeout = MID_WDT_TIMEOUT_MAX; | 138 | wdt_dev->max_timeout = MID_WDT_TIMEOUT_MAX; |
139 | wdt_dev->timeout = MID_WDT_DEFAULT_TIMEOUT; | 139 | wdt_dev->timeout = MID_WDT_DEFAULT_TIMEOUT; |
140 | wdt_dev->parent = &pdev->dev; | ||
140 | 141 | ||
141 | watchdog_set_drvdata(wdt_dev, &pdev->dev); | 142 | watchdog_set_drvdata(wdt_dev, &pdev->dev); |
142 | platform_set_drvdata(pdev, wdt_dev); | 143 | platform_set_drvdata(pdev, wdt_dev); |
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 4c2cc09c0c57..6a7d5c365438 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c | |||
@@ -174,6 +174,7 @@ static int jz4740_wdt_probe(struct platform_device *pdev) | |||
174 | jz4740_wdt->timeout = heartbeat; | 174 | jz4740_wdt->timeout = heartbeat; |
175 | jz4740_wdt->min_timeout = 1; | 175 | jz4740_wdt->min_timeout = 1; |
176 | jz4740_wdt->max_timeout = MAX_HEARTBEAT; | 176 | jz4740_wdt->max_timeout = MAX_HEARTBEAT; |
177 | jz4740_wdt->parent = &pdev->dev; | ||
177 | watchdog_set_nowayout(jz4740_wdt, nowayout); | 178 | watchdog_set_nowayout(jz4740_wdt, nowayout); |
178 | watchdog_set_drvdata(jz4740_wdt, drvdata); | 179 | watchdog_set_drvdata(jz4740_wdt, drvdata); |
179 | 180 | ||
diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c new file mode 100644 index 000000000000..ab7b8b185d99 --- /dev/null +++ b/drivers/watchdog/lpc18xx_wdt.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * NXP LPC18xx Watchdog Timer (WDT) | ||
3 | * | ||
4 | * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.com> | ||
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 | * Notes | ||
11 | * ----- | ||
12 | * The Watchdog consists of a fixed divide-by-4 clock pre-scaler and a 24-bit | ||
13 | * counter which decrements on every clock cycle. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/watchdog.h> | ||
23 | |||
24 | /* Registers */ | ||
25 | #define LPC18XX_WDT_MOD 0x00 | ||
26 | #define LPC18XX_WDT_MOD_WDEN BIT(0) | ||
27 | #define LPC18XX_WDT_MOD_WDRESET BIT(1) | ||
28 | |||
29 | #define LPC18XX_WDT_TC 0x04 | ||
30 | #define LPC18XX_WDT_TC_MIN 0xff | ||
31 | #define LPC18XX_WDT_TC_MAX 0xffffff | ||
32 | |||
33 | #define LPC18XX_WDT_FEED 0x08 | ||
34 | #define LPC18XX_WDT_FEED_MAGIC1 0xaa | ||
35 | #define LPC18XX_WDT_FEED_MAGIC2 0x55 | ||
36 | |||
37 | #define LPC18XX_WDT_TV 0x0c | ||
38 | |||
39 | /* Clock pre-scaler */ | ||
40 | #define LPC18XX_WDT_CLK_DIV 4 | ||
41 | |||
42 | /* Timeout values in seconds */ | ||
43 | #define LPC18XX_WDT_DEF_TIMEOUT 30U | ||
44 | |||
45 | static int heartbeat; | ||
46 | module_param(heartbeat, int, 0); | ||
47 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds (default=" | ||
48 | __MODULE_STRING(LPC18XX_WDT_DEF_TIMEOUT) ")"); | ||
49 | |||
50 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
51 | module_param(nowayout, bool, 0); | ||
52 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | ||
53 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
54 | |||
55 | struct lpc18xx_wdt_dev { | ||
56 | struct watchdog_device wdt_dev; | ||
57 | struct clk *reg_clk; | ||
58 | struct clk *wdt_clk; | ||
59 | unsigned long clk_rate; | ||
60 | void __iomem *base; | ||
61 | struct timer_list timer; | ||
62 | struct notifier_block restart_handler; | ||
63 | spinlock_t lock; | ||
64 | }; | ||
65 | |||
66 | static int lpc18xx_wdt_feed(struct watchdog_device *wdt_dev) | ||
67 | { | ||
68 | struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); | ||
69 | unsigned long flags; | ||
70 | |||
71 | /* | ||
72 | * An abort condition will occur if an interrupt happens during the feed | ||
73 | * sequence. | ||
74 | */ | ||
75 | spin_lock_irqsave(&lpc18xx_wdt->lock, flags); | ||
76 | writel(LPC18XX_WDT_FEED_MAGIC1, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
77 | writel(LPC18XX_WDT_FEED_MAGIC2, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
78 | spin_unlock_irqrestore(&lpc18xx_wdt->lock, flags); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void lpc18xx_wdt_timer_feed(unsigned long data) | ||
84 | { | ||
85 | struct watchdog_device *wdt_dev = (struct watchdog_device *)data; | ||
86 | struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); | ||
87 | |||
88 | lpc18xx_wdt_feed(wdt_dev); | ||
89 | |||
90 | /* Use safe value (1/2 of real timeout) */ | ||
91 | mod_timer(&lpc18xx_wdt->timer, jiffies + | ||
92 | msecs_to_jiffies((wdt_dev->timeout * MSEC_PER_SEC) / 2)); | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Since LPC18xx Watchdog cannot be disabled in hardware, we must keep feeding | ||
97 | * it with a timer until userspace watchdog software takes over. | ||
98 | */ | ||
99 | static int lpc18xx_wdt_stop(struct watchdog_device *wdt_dev) | ||
100 | { | ||
101 | lpc18xx_wdt_timer_feed((unsigned long)wdt_dev); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static void __lpc18xx_wdt_set_timeout(struct lpc18xx_wdt_dev *lpc18xx_wdt) | ||
107 | { | ||
108 | unsigned int val; | ||
109 | |||
110 | val = DIV_ROUND_UP(lpc18xx_wdt->wdt_dev.timeout * lpc18xx_wdt->clk_rate, | ||
111 | LPC18XX_WDT_CLK_DIV); | ||
112 | writel(val, lpc18xx_wdt->base + LPC18XX_WDT_TC); | ||
113 | } | ||
114 | |||
115 | static int lpc18xx_wdt_set_timeout(struct watchdog_device *wdt_dev, | ||
116 | unsigned int new_timeout) | ||
117 | { | ||
118 | struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); | ||
119 | |||
120 | lpc18xx_wdt->wdt_dev.timeout = new_timeout; | ||
121 | __lpc18xx_wdt_set_timeout(lpc18xx_wdt); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static unsigned int lpc18xx_wdt_get_timeleft(struct watchdog_device *wdt_dev) | ||
127 | { | ||
128 | struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); | ||
129 | unsigned int val; | ||
130 | |||
131 | val = readl(lpc18xx_wdt->base + LPC18XX_WDT_TV); | ||
132 | return (val * LPC18XX_WDT_CLK_DIV) / lpc18xx_wdt->clk_rate; | ||
133 | } | ||
134 | |||
135 | static int lpc18xx_wdt_start(struct watchdog_device *wdt_dev) | ||
136 | { | ||
137 | struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); | ||
138 | unsigned int val; | ||
139 | |||
140 | if (timer_pending(&lpc18xx_wdt->timer)) | ||
141 | del_timer(&lpc18xx_wdt->timer); | ||
142 | |||
143 | val = readl(lpc18xx_wdt->base + LPC18XX_WDT_MOD); | ||
144 | val |= LPC18XX_WDT_MOD_WDEN; | ||
145 | val |= LPC18XX_WDT_MOD_WDRESET; | ||
146 | writel(val, lpc18xx_wdt->base + LPC18XX_WDT_MOD); | ||
147 | |||
148 | /* | ||
149 | * Setting the WDEN bit in the WDMOD register is not sufficient to | ||
150 | * enable the Watchdog. A valid feed sequence must be completed after | ||
151 | * setting WDEN before the Watchdog is capable of generating a reset. | ||
152 | */ | ||
153 | lpc18xx_wdt_feed(wdt_dev); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct watchdog_info lpc18xx_wdt_info = { | ||
159 | .identity = "NXP LPC18xx Watchdog", | ||
160 | .options = WDIOF_SETTIMEOUT | | ||
161 | WDIOF_KEEPALIVEPING | | ||
162 | WDIOF_MAGICCLOSE, | ||
163 | }; | ||
164 | |||
165 | static const struct watchdog_ops lpc18xx_wdt_ops = { | ||
166 | .owner = THIS_MODULE, | ||
167 | .start = lpc18xx_wdt_start, | ||
168 | .stop = lpc18xx_wdt_stop, | ||
169 | .ping = lpc18xx_wdt_feed, | ||
170 | .set_timeout = lpc18xx_wdt_set_timeout, | ||
171 | .get_timeleft = lpc18xx_wdt_get_timeleft, | ||
172 | }; | ||
173 | |||
174 | static int lpc18xx_wdt_restart(struct notifier_block *this, unsigned long mode, | ||
175 | void *cmd) | ||
176 | { | ||
177 | struct lpc18xx_wdt_dev *lpc18xx_wdt = container_of(this, | ||
178 | struct lpc18xx_wdt_dev, restart_handler); | ||
179 | unsigned long flags; | ||
180 | int val; | ||
181 | |||
182 | /* | ||
183 | * Incorrect feed sequence causes immediate watchdog reset if enabled. | ||
184 | */ | ||
185 | spin_lock_irqsave(&lpc18xx_wdt->lock, flags); | ||
186 | |||
187 | val = readl(lpc18xx_wdt->base + LPC18XX_WDT_MOD); | ||
188 | val |= LPC18XX_WDT_MOD_WDEN; | ||
189 | val |= LPC18XX_WDT_MOD_WDRESET; | ||
190 | writel(val, lpc18xx_wdt->base + LPC18XX_WDT_MOD); | ||
191 | |||
192 | writel(LPC18XX_WDT_FEED_MAGIC1, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
193 | writel(LPC18XX_WDT_FEED_MAGIC2, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
194 | |||
195 | writel(LPC18XX_WDT_FEED_MAGIC1, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
196 | writel(LPC18XX_WDT_FEED_MAGIC1, lpc18xx_wdt->base + LPC18XX_WDT_FEED); | ||
197 | |||
198 | spin_unlock_irqrestore(&lpc18xx_wdt->lock, flags); | ||
199 | |||
200 | return NOTIFY_OK; | ||
201 | } | ||
202 | |||
203 | static int lpc18xx_wdt_probe(struct platform_device *pdev) | ||
204 | { | ||
205 | struct lpc18xx_wdt_dev *lpc18xx_wdt; | ||
206 | struct device *dev = &pdev->dev; | ||
207 | struct resource *res; | ||
208 | int ret; | ||
209 | |||
210 | lpc18xx_wdt = devm_kzalloc(dev, sizeof(*lpc18xx_wdt), GFP_KERNEL); | ||
211 | if (!lpc18xx_wdt) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
215 | lpc18xx_wdt->base = devm_ioremap_resource(dev, res); | ||
216 | if (IS_ERR(lpc18xx_wdt->base)) | ||
217 | return PTR_ERR(lpc18xx_wdt->base); | ||
218 | |||
219 | lpc18xx_wdt->reg_clk = devm_clk_get(dev, "reg"); | ||
220 | if (IS_ERR(lpc18xx_wdt->reg_clk)) { | ||
221 | dev_err(dev, "failed to get the reg clock\n"); | ||
222 | return PTR_ERR(lpc18xx_wdt->reg_clk); | ||
223 | } | ||
224 | |||
225 | lpc18xx_wdt->wdt_clk = devm_clk_get(dev, "wdtclk"); | ||
226 | if (IS_ERR(lpc18xx_wdt->wdt_clk)) { | ||
227 | dev_err(dev, "failed to get the wdt clock\n"); | ||
228 | return PTR_ERR(lpc18xx_wdt->wdt_clk); | ||
229 | } | ||
230 | |||
231 | ret = clk_prepare_enable(lpc18xx_wdt->reg_clk); | ||
232 | if (ret) { | ||
233 | dev_err(dev, "could not prepare or enable sys clock\n"); | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | ret = clk_prepare_enable(lpc18xx_wdt->wdt_clk); | ||
238 | if (ret) { | ||
239 | dev_err(dev, "could not prepare or enable wdt clock\n"); | ||
240 | goto disable_reg_clk; | ||
241 | } | ||
242 | |||
243 | /* We use the clock rate to calculate timeouts */ | ||
244 | lpc18xx_wdt->clk_rate = clk_get_rate(lpc18xx_wdt->wdt_clk); | ||
245 | if (lpc18xx_wdt->clk_rate == 0) { | ||
246 | dev_err(dev, "failed to get clock rate\n"); | ||
247 | ret = -EINVAL; | ||
248 | goto disable_wdt_clk; | ||
249 | } | ||
250 | |||
251 | lpc18xx_wdt->wdt_dev.info = &lpc18xx_wdt_info; | ||
252 | lpc18xx_wdt->wdt_dev.ops = &lpc18xx_wdt_ops; | ||
253 | |||
254 | lpc18xx_wdt->wdt_dev.min_timeout = DIV_ROUND_UP(LPC18XX_WDT_TC_MIN * | ||
255 | LPC18XX_WDT_CLK_DIV, lpc18xx_wdt->clk_rate); | ||
256 | |||
257 | lpc18xx_wdt->wdt_dev.max_timeout = (LPC18XX_WDT_TC_MAX * | ||
258 | LPC18XX_WDT_CLK_DIV) / lpc18xx_wdt->clk_rate; | ||
259 | |||
260 | lpc18xx_wdt->wdt_dev.timeout = min(lpc18xx_wdt->wdt_dev.max_timeout, | ||
261 | LPC18XX_WDT_DEF_TIMEOUT); | ||
262 | |||
263 | spin_lock_init(&lpc18xx_wdt->lock); | ||
264 | |||
265 | lpc18xx_wdt->wdt_dev.parent = dev; | ||
266 | watchdog_set_drvdata(&lpc18xx_wdt->wdt_dev, lpc18xx_wdt); | ||
267 | |||
268 | ret = watchdog_init_timeout(&lpc18xx_wdt->wdt_dev, heartbeat, dev); | ||
269 | |||
270 | __lpc18xx_wdt_set_timeout(lpc18xx_wdt); | ||
271 | |||
272 | setup_timer(&lpc18xx_wdt->timer, lpc18xx_wdt_timer_feed, | ||
273 | (unsigned long)&lpc18xx_wdt->wdt_dev); | ||
274 | |||
275 | watchdog_set_nowayout(&lpc18xx_wdt->wdt_dev, nowayout); | ||
276 | |||
277 | platform_set_drvdata(pdev, lpc18xx_wdt); | ||
278 | |||
279 | ret = watchdog_register_device(&lpc18xx_wdt->wdt_dev); | ||
280 | if (ret) | ||
281 | goto disable_wdt_clk; | ||
282 | |||
283 | lpc18xx_wdt->restart_handler.notifier_call = lpc18xx_wdt_restart; | ||
284 | lpc18xx_wdt->restart_handler.priority = 128; | ||
285 | ret = register_restart_handler(&lpc18xx_wdt->restart_handler); | ||
286 | if (ret) | ||
287 | dev_warn(dev, "failed to register restart handler: %d\n", ret); | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | disable_wdt_clk: | ||
292 | clk_disable_unprepare(lpc18xx_wdt->wdt_clk); | ||
293 | disable_reg_clk: | ||
294 | clk_disable_unprepare(lpc18xx_wdt->reg_clk); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static void lpc18xx_wdt_shutdown(struct platform_device *pdev) | ||
299 | { | ||
300 | struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); | ||
301 | |||
302 | lpc18xx_wdt_stop(&lpc18xx_wdt->wdt_dev); | ||
303 | } | ||
304 | |||
305 | static int lpc18xx_wdt_remove(struct platform_device *pdev) | ||
306 | { | ||
307 | struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); | ||
308 | |||
309 | unregister_restart_handler(&lpc18xx_wdt->restart_handler); | ||
310 | |||
311 | dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); | ||
312 | del_timer(&lpc18xx_wdt->timer); | ||
313 | |||
314 | watchdog_unregister_device(&lpc18xx_wdt->wdt_dev); | ||
315 | clk_disable_unprepare(lpc18xx_wdt->wdt_clk); | ||
316 | clk_disable_unprepare(lpc18xx_wdt->reg_clk); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static const struct of_device_id lpc18xx_wdt_match[] = { | ||
322 | { .compatible = "nxp,lpc1850-wwdt" }, | ||
323 | {} | ||
324 | }; | ||
325 | MODULE_DEVICE_TABLE(of, lpc18xx_wdt_match); | ||
326 | |||
327 | static struct platform_driver lpc18xx_wdt_driver = { | ||
328 | .driver = { | ||
329 | .name = "lpc18xx-wdt", | ||
330 | .of_match_table = lpc18xx_wdt_match, | ||
331 | }, | ||
332 | .probe = lpc18xx_wdt_probe, | ||
333 | .remove = lpc18xx_wdt_remove, | ||
334 | .shutdown = lpc18xx_wdt_shutdown, | ||
335 | }; | ||
336 | module_platform_driver(lpc18xx_wdt_driver); | ||
337 | |||
338 | MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>"); | ||
339 | MODULE_DESCRIPTION("NXP LPC18xx Watchdog Timer Driver"); | ||
340 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c index d193a5e79c38..69013007dc47 100644 --- a/drivers/watchdog/mena21_wdt.c +++ b/drivers/watchdog/mena21_wdt.c | |||
@@ -197,6 +197,7 @@ static int a21_wdt_probe(struct platform_device *pdev) | |||
197 | watchdog_init_timeout(&a21_wdt, 30, &pdev->dev); | 197 | watchdog_init_timeout(&a21_wdt, 30, &pdev->dev); |
198 | watchdog_set_nowayout(&a21_wdt, nowayout); | 198 | watchdog_set_nowayout(&a21_wdt, nowayout); |
199 | watchdog_set_drvdata(&a21_wdt, drv); | 199 | watchdog_set_drvdata(&a21_wdt, drv); |
200 | a21_wdt.parent = &pdev->dev; | ||
200 | 201 | ||
201 | reset = a21_wdt_get_bootstatus(drv); | 202 | reset = a21_wdt_get_bootstatus(drv); |
202 | if (reset == 2) | 203 | if (reset == 2) |
diff --git a/drivers/watchdog/menf21bmc_wdt.c b/drivers/watchdog/menf21bmc_wdt.c index 59f0913c7341..3aefddebb386 100644 --- a/drivers/watchdog/menf21bmc_wdt.c +++ b/drivers/watchdog/menf21bmc_wdt.c | |||
@@ -130,6 +130,7 @@ static int menf21bmc_wdt_probe(struct platform_device *pdev) | |||
130 | drv_data->wdt.info = &menf21bmc_wdt_info; | 130 | drv_data->wdt.info = &menf21bmc_wdt_info; |
131 | drv_data->wdt.min_timeout = BMC_WD_TIMEOUT_MIN; | 131 | drv_data->wdt.min_timeout = BMC_WD_TIMEOUT_MIN; |
132 | drv_data->wdt.max_timeout = BMC_WD_TIMEOUT_MAX; | 132 | drv_data->wdt.max_timeout = BMC_WD_TIMEOUT_MAX; |
133 | drv_data->wdt.parent = &pdev->dev; | ||
133 | drv_data->i2c_client = i2c_client; | 134 | drv_data->i2c_client = i2c_client; |
134 | 135 | ||
135 | /* | 136 | /* |
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 689381a24887..5f2273aac37d 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c | |||
@@ -50,8 +50,12 @@ struct mpc8xxx_wdt_type { | |||
50 | bool hw_enabled; | 50 | bool hw_enabled; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static struct mpc8xxx_wdt __iomem *wd_base; | 53 | struct mpc8xxx_wdt_ddata { |
54 | static int mpc8xxx_wdt_init_late(void); | 54 | struct mpc8xxx_wdt __iomem *base; |
55 | struct watchdog_device wdd; | ||
56 | struct timer_list timer; | ||
57 | spinlock_t lock; | ||
58 | }; | ||
55 | 59 | ||
56 | static u16 timeout = 0xffff; | 60 | static u16 timeout = 0xffff; |
57 | module_param(timeout, ushort, 0); | 61 | module_param(timeout, ushort, 0); |
@@ -68,65 +72,59 @@ module_param(nowayout, bool, 0); | |||
68 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | 72 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " |
69 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 73 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
70 | 74 | ||
71 | /* | 75 | static void mpc8xxx_wdt_keepalive(struct mpc8xxx_wdt_ddata *ddata) |
72 | * We always prescale, but if someone really doesn't want to they can set this | ||
73 | * to 0 | ||
74 | */ | ||
75 | static int prescale = 1; | ||
76 | |||
77 | static DEFINE_SPINLOCK(wdt_spinlock); | ||
78 | |||
79 | static void mpc8xxx_wdt_keepalive(void) | ||
80 | { | 76 | { |
81 | /* Ping the WDT */ | 77 | /* Ping the WDT */ |
82 | spin_lock(&wdt_spinlock); | 78 | spin_lock(&ddata->lock); |
83 | out_be16(&wd_base->swsrr, 0x556c); | 79 | out_be16(&ddata->base->swsrr, 0x556c); |
84 | out_be16(&wd_base->swsrr, 0xaa39); | 80 | out_be16(&ddata->base->swsrr, 0xaa39); |
85 | spin_unlock(&wdt_spinlock); | 81 | spin_unlock(&ddata->lock); |
86 | } | 82 | } |
87 | 83 | ||
88 | static struct watchdog_device mpc8xxx_wdt_dev; | ||
89 | static void mpc8xxx_wdt_timer_ping(unsigned long arg); | ||
90 | static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, | ||
91 | (unsigned long)&mpc8xxx_wdt_dev); | ||
92 | |||
93 | static void mpc8xxx_wdt_timer_ping(unsigned long arg) | 84 | static void mpc8xxx_wdt_timer_ping(unsigned long arg) |
94 | { | 85 | { |
95 | struct watchdog_device *w = (struct watchdog_device *)arg; | 86 | struct mpc8xxx_wdt_ddata *ddata = (void *)arg; |
96 | 87 | ||
97 | mpc8xxx_wdt_keepalive(); | 88 | mpc8xxx_wdt_keepalive(ddata); |
98 | /* We're pinging it twice faster than needed, just to be sure. */ | 89 | /* We're pinging it twice faster than needed, just to be sure. */ |
99 | mod_timer(&wdt_timer, jiffies + HZ * w->timeout / 2); | 90 | mod_timer(&ddata->timer, jiffies + HZ * ddata->wdd.timeout / 2); |
100 | } | 91 | } |
101 | 92 | ||
102 | static int mpc8xxx_wdt_start(struct watchdog_device *w) | 93 | static int mpc8xxx_wdt_start(struct watchdog_device *w) |
103 | { | 94 | { |
104 | u32 tmp = SWCRR_SWEN; | 95 | struct mpc8xxx_wdt_ddata *ddata = |
96 | container_of(w, struct mpc8xxx_wdt_ddata, wdd); | ||
97 | |||
98 | u32 tmp = SWCRR_SWEN | SWCRR_SWPR; | ||
105 | 99 | ||
106 | /* Good, fire up the show */ | 100 | /* Good, fire up the show */ |
107 | if (prescale) | ||
108 | tmp |= SWCRR_SWPR; | ||
109 | if (reset) | 101 | if (reset) |
110 | tmp |= SWCRR_SWRI; | 102 | tmp |= SWCRR_SWRI; |
111 | 103 | ||
112 | tmp |= timeout << 16; | 104 | tmp |= timeout << 16; |
113 | 105 | ||
114 | out_be32(&wd_base->swcrr, tmp); | 106 | out_be32(&ddata->base->swcrr, tmp); |
115 | 107 | ||
116 | del_timer_sync(&wdt_timer); | 108 | del_timer_sync(&ddata->timer); |
117 | 109 | ||
118 | return 0; | 110 | return 0; |
119 | } | 111 | } |
120 | 112 | ||
121 | static int mpc8xxx_wdt_ping(struct watchdog_device *w) | 113 | static int mpc8xxx_wdt_ping(struct watchdog_device *w) |
122 | { | 114 | { |
123 | mpc8xxx_wdt_keepalive(); | 115 | struct mpc8xxx_wdt_ddata *ddata = |
116 | container_of(w, struct mpc8xxx_wdt_ddata, wdd); | ||
117 | |||
118 | mpc8xxx_wdt_keepalive(ddata); | ||
124 | return 0; | 119 | return 0; |
125 | } | 120 | } |
126 | 121 | ||
127 | static int mpc8xxx_wdt_stop(struct watchdog_device *w) | 122 | static int mpc8xxx_wdt_stop(struct watchdog_device *w) |
128 | { | 123 | { |
129 | mod_timer(&wdt_timer, jiffies); | 124 | struct mpc8xxx_wdt_ddata *ddata = |
125 | container_of(w, struct mpc8xxx_wdt_ddata, wdd); | ||
126 | |||
127 | mod_timer(&ddata->timer, jiffies); | ||
130 | return 0; | 128 | return 0; |
131 | } | 129 | } |
132 | 130 | ||
@@ -143,53 +141,57 @@ static struct watchdog_ops mpc8xxx_wdt_ops = { | |||
143 | .stop = mpc8xxx_wdt_stop, | 141 | .stop = mpc8xxx_wdt_stop, |
144 | }; | 142 | }; |
145 | 143 | ||
146 | static struct watchdog_device mpc8xxx_wdt_dev = { | ||
147 | .info = &mpc8xxx_wdt_info, | ||
148 | .ops = &mpc8xxx_wdt_ops, | ||
149 | }; | ||
150 | |||
151 | static const struct of_device_id mpc8xxx_wdt_match[]; | ||
152 | static int mpc8xxx_wdt_probe(struct platform_device *ofdev) | 144 | static int mpc8xxx_wdt_probe(struct platform_device *ofdev) |
153 | { | 145 | { |
154 | int ret; | 146 | int ret; |
155 | const struct of_device_id *match; | 147 | struct resource *res; |
156 | struct device_node *np = ofdev->dev.of_node; | ||
157 | const struct mpc8xxx_wdt_type *wdt_type; | 148 | const struct mpc8xxx_wdt_type *wdt_type; |
149 | struct mpc8xxx_wdt_ddata *ddata; | ||
158 | u32 freq = fsl_get_sys_freq(); | 150 | u32 freq = fsl_get_sys_freq(); |
159 | bool enabled; | 151 | bool enabled; |
160 | unsigned int timeout_sec; | 152 | unsigned int timeout_sec; |
161 | 153 | ||
162 | match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev); | 154 | wdt_type = of_device_get_match_data(&ofdev->dev); |
163 | if (!match) | 155 | if (!wdt_type) |
164 | return -EINVAL; | 156 | return -EINVAL; |
165 | wdt_type = match->data; | ||
166 | 157 | ||
167 | if (!freq || freq == -1) | 158 | if (!freq || freq == -1) |
168 | return -EINVAL; | 159 | return -EINVAL; |
169 | 160 | ||
170 | wd_base = of_iomap(np, 0); | 161 | ddata = devm_kzalloc(&ofdev->dev, sizeof(*ddata), GFP_KERNEL); |
171 | if (!wd_base) | 162 | if (!ddata) |
172 | return -ENOMEM; | 163 | return -ENOMEM; |
173 | 164 | ||
174 | enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN; | 165 | res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); |
166 | ddata->base = devm_ioremap_resource(&ofdev->dev, res); | ||
167 | if (IS_ERR(ddata->base)) | ||
168 | return PTR_ERR(ddata->base); | ||
169 | |||
170 | enabled = in_be32(&ddata->base->swcrr) & SWCRR_SWEN; | ||
175 | if (!enabled && wdt_type->hw_enabled) { | 171 | if (!enabled && wdt_type->hw_enabled) { |
176 | pr_info("could not be enabled in software\n"); | 172 | pr_info("could not be enabled in software\n"); |
177 | ret = -ENOSYS; | 173 | return -ENODEV; |
178 | goto err_unmap; | ||
179 | } | 174 | } |
180 | 175 | ||
176 | spin_lock_init(&ddata->lock); | ||
177 | setup_timer(&ddata->timer, mpc8xxx_wdt_timer_ping, | ||
178 | (unsigned long)ddata); | ||
179 | |||
180 | ddata->wdd.info = &mpc8xxx_wdt_info, | ||
181 | ddata->wdd.ops = &mpc8xxx_wdt_ops, | ||
182 | |||
181 | /* Calculate the timeout in seconds */ | 183 | /* Calculate the timeout in seconds */ |
182 | if (prescale) | 184 | timeout_sec = (timeout * wdt_type->prescaler) / freq; |
183 | timeout_sec = (timeout * wdt_type->prescaler) / freq; | 185 | |
184 | else | 186 | ddata->wdd.timeout = timeout_sec; |
185 | timeout_sec = timeout / freq; | 187 | |
186 | 188 | watchdog_set_nowayout(&ddata->wdd, nowayout); | |
187 | mpc8xxx_wdt_dev.timeout = timeout_sec; | 189 | |
188 | #ifdef MODULE | 190 | ret = watchdog_register_device(&ddata->wdd); |
189 | ret = mpc8xxx_wdt_init_late(); | 191 | if (ret) { |
190 | if (ret) | 192 | pr_err("cannot register watchdog device (err=%d)\n", ret); |
191 | goto err_unmap; | 193 | return ret; |
192 | #endif | 194 | } |
193 | 195 | ||
194 | pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d (%d seconds)\n", | 196 | pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d (%d seconds)\n", |
195 | reset ? "reset" : "interrupt", timeout, timeout_sec); | 197 | reset ? "reset" : "interrupt", timeout, timeout_sec); |
@@ -200,21 +202,20 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev) | |||
200 | * userspace handles it. | 202 | * userspace handles it. |
201 | */ | 203 | */ |
202 | if (enabled) | 204 | if (enabled) |
203 | mod_timer(&wdt_timer, jiffies); | 205 | mod_timer(&ddata->timer, jiffies); |
206 | |||
207 | platform_set_drvdata(ofdev, ddata); | ||
204 | return 0; | 208 | return 0; |
205 | err_unmap: | ||
206 | iounmap(wd_base); | ||
207 | wd_base = NULL; | ||
208 | return ret; | ||
209 | } | 209 | } |
210 | 210 | ||
211 | static int mpc8xxx_wdt_remove(struct platform_device *ofdev) | 211 | static int mpc8xxx_wdt_remove(struct platform_device *ofdev) |
212 | { | 212 | { |
213 | struct mpc8xxx_wdt_ddata *ddata = platform_get_drvdata(ofdev); | ||
214 | |||
213 | pr_crit("Watchdog removed, expect the %s soon!\n", | 215 | pr_crit("Watchdog removed, expect the %s soon!\n", |
214 | reset ? "reset" : "machine check exception"); | 216 | reset ? "reset" : "machine check exception"); |
215 | del_timer_sync(&wdt_timer); | 217 | del_timer_sync(&ddata->timer); |
216 | watchdog_unregister_device(&mpc8xxx_wdt_dev); | 218 | watchdog_unregister_device(&ddata->wdd); |
217 | iounmap(wd_base); | ||
218 | 219 | ||
219 | return 0; | 220 | return 0; |
220 | } | 221 | } |
@@ -253,31 +254,6 @@ static struct platform_driver mpc8xxx_wdt_driver = { | |||
253 | }, | 254 | }, |
254 | }; | 255 | }; |
255 | 256 | ||
256 | /* | ||
257 | * We do wdt initialization in two steps: arch_initcall probes the wdt | ||
258 | * very early to start pinging the watchdog (misc devices are not yet | ||
259 | * available), and later module_init() just registers the misc device. | ||
260 | */ | ||
261 | static int mpc8xxx_wdt_init_late(void) | ||
262 | { | ||
263 | int ret; | ||
264 | |||
265 | if (!wd_base) | ||
266 | return -ENODEV; | ||
267 | |||
268 | watchdog_set_nowayout(&mpc8xxx_wdt_dev, nowayout); | ||
269 | |||
270 | ret = watchdog_register_device(&mpc8xxx_wdt_dev); | ||
271 | if (ret) { | ||
272 | pr_err("cannot register watchdog device (err=%d)\n", ret); | ||
273 | return ret; | ||
274 | } | ||
275 | return 0; | ||
276 | } | ||
277 | #ifndef MODULE | ||
278 | module_init(mpc8xxx_wdt_init_late); | ||
279 | #endif | ||
280 | |||
281 | static int __init mpc8xxx_wdt_init(void) | 257 | static int __init mpc8xxx_wdt_init(void) |
282 | { | 258 | { |
283 | return platform_driver_register(&mpc8xxx_wdt_driver); | 259 | return platform_driver_register(&mpc8xxx_wdt_driver); |
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 938b987de551..6ad9df948711 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c | |||
@@ -210,6 +210,14 @@ static int mtk_wdt_probe(struct platform_device *pdev) | |||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | 212 | ||
213 | static void mtk_wdt_shutdown(struct platform_device *pdev) | ||
214 | { | ||
215 | struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); | ||
216 | |||
217 | if (watchdog_active(&mtk_wdt->wdt_dev)) | ||
218 | mtk_wdt_stop(&mtk_wdt->wdt_dev); | ||
219 | } | ||
220 | |||
213 | static int mtk_wdt_remove(struct platform_device *pdev) | 221 | static int mtk_wdt_remove(struct platform_device *pdev) |
214 | { | 222 | { |
215 | struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); | 223 | struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); |
@@ -221,17 +229,48 @@ static int mtk_wdt_remove(struct platform_device *pdev) | |||
221 | return 0; | 229 | return 0; |
222 | } | 230 | } |
223 | 231 | ||
232 | #ifdef CONFIG_PM_SLEEP | ||
233 | static int mtk_wdt_suspend(struct device *dev) | ||
234 | { | ||
235 | struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev); | ||
236 | |||
237 | if (watchdog_active(&mtk_wdt->wdt_dev)) | ||
238 | mtk_wdt_stop(&mtk_wdt->wdt_dev); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int mtk_wdt_resume(struct device *dev) | ||
244 | { | ||
245 | struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev); | ||
246 | |||
247 | if (watchdog_active(&mtk_wdt->wdt_dev)) { | ||
248 | mtk_wdt_start(&mtk_wdt->wdt_dev); | ||
249 | mtk_wdt_ping(&mtk_wdt->wdt_dev); | ||
250 | } | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | #endif | ||
255 | |||
224 | static const struct of_device_id mtk_wdt_dt_ids[] = { | 256 | static const struct of_device_id mtk_wdt_dt_ids[] = { |
225 | { .compatible = "mediatek,mt6589-wdt" }, | 257 | { .compatible = "mediatek,mt6589-wdt" }, |
226 | { /* sentinel */ } | 258 | { /* sentinel */ } |
227 | }; | 259 | }; |
228 | MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids); | 260 | MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids); |
229 | 261 | ||
262 | static const struct dev_pm_ops mtk_wdt_pm_ops = { | ||
263 | SET_SYSTEM_SLEEP_PM_OPS(mtk_wdt_suspend, | ||
264 | mtk_wdt_resume) | ||
265 | }; | ||
266 | |||
230 | static struct platform_driver mtk_wdt_driver = { | 267 | static struct platform_driver mtk_wdt_driver = { |
231 | .probe = mtk_wdt_probe, | 268 | .probe = mtk_wdt_probe, |
232 | .remove = mtk_wdt_remove, | 269 | .remove = mtk_wdt_remove, |
270 | .shutdown = mtk_wdt_shutdown, | ||
233 | .driver = { | 271 | .driver = { |
234 | .name = DRV_NAME, | 272 | .name = DRV_NAME, |
273 | .pm = &mtk_wdt_pm_ops, | ||
235 | .of_match_table = mtk_wdt_dt_ids, | 274 | .of_match_table = mtk_wdt_dt_ids, |
236 | }, | 275 | }, |
237 | }; | 276 | }; |
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index c028454be66c..bd917bb757b8 100644 --- a/drivers/watchdog/nv_tco.c +++ b/drivers/watchdog/nv_tco.c | |||
@@ -294,6 +294,8 @@ static const struct pci_device_id tco_pci_tbl[] = { | |||
294 | PCI_ANY_ID, PCI_ANY_ID, }, | 294 | PCI_ANY_ID, PCI_ANY_ID, }, |
295 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, | 295 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, |
296 | PCI_ANY_ID, PCI_ANY_ID, }, | 296 | PCI_ANY_ID, PCI_ANY_ID, }, |
297 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS, | ||
298 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
297 | { 0, }, /* End of list */ | 299 | { 0, }, /* End of list */ |
298 | }; | 300 | }; |
299 | MODULE_DEVICE_TABLE(pci, tco_pci_tbl); | 301 | MODULE_DEVICE_TABLE(pci, tco_pci_tbl); |
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index de911c7e477c..d96bee017fd3 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -253,6 +253,7 @@ static int omap_wdt_probe(struct platform_device *pdev) | |||
253 | wdev->wdog.ops = &omap_wdt_ops; | 253 | wdev->wdog.ops = &omap_wdt_ops; |
254 | wdev->wdog.min_timeout = TIMER_MARGIN_MIN; | 254 | wdev->wdog.min_timeout = TIMER_MARGIN_MIN; |
255 | wdev->wdog.max_timeout = TIMER_MARGIN_MAX; | 255 | wdev->wdog.max_timeout = TIMER_MARGIN_MAX; |
256 | wdev->wdog.parent = &pdev->dev; | ||
256 | 257 | ||
257 | if (watchdog_init_timeout(&wdev->wdog, timer_margin, &pdev->dev) < 0) | 258 | if (watchdog_init_timeout(&wdev->wdog, timer_margin, &pdev->dev) < 0) |
258 | wdev->wdog.timeout = TIMER_MARGIN_DEFAULT; | 259 | wdev->wdog.timeout = TIMER_MARGIN_DEFAULT; |
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index ef0c628d5037..c6b8f4a43bde 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
@@ -567,6 +567,7 @@ static int orion_wdt_probe(struct platform_device *pdev) | |||
567 | 567 | ||
568 | dev->wdt.timeout = wdt_max_duration; | 568 | dev->wdt.timeout = wdt_max_duration; |
569 | dev->wdt.max_timeout = wdt_max_duration; | 569 | dev->wdt.max_timeout = wdt_max_duration; |
570 | dev->wdt.parent = &pdev->dev; | ||
570 | watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); | 571 | watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); |
571 | 572 | ||
572 | platform_set_drvdata(pdev, &dev->wdt); | 573 | platform_set_drvdata(pdev, &dev->wdt); |
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index b9c6049c3e78..4224b3ec83a5 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c | |||
@@ -167,6 +167,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) | |||
167 | 167 | ||
168 | pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? | 168 | pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? |
169 | WDIOF_CARDRESET : 0; | 169 | WDIOF_CARDRESET : 0; |
170 | pnx4008_wdd.parent = &pdev->dev; | ||
170 | watchdog_set_nowayout(&pnx4008_wdd, nowayout); | 171 | watchdog_set_nowayout(&pnx4008_wdd, nowayout); |
171 | 172 | ||
172 | pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */ | 173 | pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */ |
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index aa03ca8f2d9b..773dcfaee7b2 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c | |||
@@ -171,6 +171,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) | |||
171 | wdt->wdd.ops = &qcom_wdt_ops; | 171 | wdt->wdd.ops = &qcom_wdt_ops; |
172 | wdt->wdd.min_timeout = 1; | 172 | wdt->wdd.min_timeout = 1; |
173 | wdt->wdd.max_timeout = 0x10000000U / wdt->rate; | 173 | wdt->wdd.max_timeout = 0x10000000U / wdt->rate; |
174 | wdt->wdd.parent = &pdev->dev; | ||
174 | 175 | ||
175 | /* | 176 | /* |
176 | * If 'timeout-sec' unspecified in devicetree, assume a 30 second | 177 | * If 'timeout-sec' unspecified in devicetree, assume a 30 second |
diff --git a/drivers/watchdog/retu_wdt.c b/drivers/watchdog/retu_wdt.c index b7c68e275aeb..39cd51df2ffc 100644 --- a/drivers/watchdog/retu_wdt.c +++ b/drivers/watchdog/retu_wdt.c | |||
@@ -127,6 +127,7 @@ static int retu_wdt_probe(struct platform_device *pdev) | |||
127 | retu_wdt->timeout = RETU_WDT_MAX_TIMER; | 127 | retu_wdt->timeout = RETU_WDT_MAX_TIMER; |
128 | retu_wdt->min_timeout = 0; | 128 | retu_wdt->min_timeout = 0; |
129 | retu_wdt->max_timeout = RETU_WDT_MAX_TIMER; | 129 | retu_wdt->max_timeout = RETU_WDT_MAX_TIMER; |
130 | retu_wdt->parent = &pdev->dev; | ||
130 | 131 | ||
131 | watchdog_set_drvdata(retu_wdt, wdev); | 132 | watchdog_set_drvdata(retu_wdt, wdev); |
132 | watchdog_set_nowayout(retu_wdt, nowayout); | 133 | watchdog_set_nowayout(retu_wdt, nowayout); |
diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c index a6f7e2e29beb..1967919ae743 100644 --- a/drivers/watchdog/rt2880_wdt.c +++ b/drivers/watchdog/rt2880_wdt.c | |||
@@ -161,6 +161,7 @@ static int rt288x_wdt_probe(struct platform_device *pdev) | |||
161 | rt288x_wdt_dev.dev = &pdev->dev; | 161 | rt288x_wdt_dev.dev = &pdev->dev; |
162 | rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause(); | 162 | rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause(); |
163 | rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq); | 163 | rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq); |
164 | rt288x_wdt_dev.parent = &pdev->dev; | ||
164 | 165 | ||
165 | watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout, | 166 | watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout, |
166 | &pdev->dev); | 167 | &pdev->dev); |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index e89ae027c91d..d781000c7825 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -607,6 +607,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) | |||
607 | watchdog_set_nowayout(&wdt->wdt_device, nowayout); | 607 | watchdog_set_nowayout(&wdt->wdt_device, nowayout); |
608 | 608 | ||
609 | wdt->wdt_device.bootstatus = s3c2410wdt_get_bootstatus(wdt); | 609 | wdt->wdt_device.bootstatus = s3c2410wdt_get_bootstatus(wdt); |
610 | wdt->wdt_device.parent = &pdev->dev; | ||
610 | 611 | ||
611 | ret = watchdog_register_device(&wdt->wdt_device); | 612 | ret = watchdog_register_device(&wdt->wdt_device); |
612 | if (ret) { | 613 | if (ret) { |
diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c new file mode 100644 index 000000000000..a49634cdc1cc --- /dev/null +++ b/drivers/watchdog/sama5d4_wdt.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * Driver for Atmel SAMA5D4 Watchdog Timer | ||
3 | * | ||
4 | * Copyright (C) 2015 Atmel Corporation | ||
5 | * | ||
6 | * Licensed under GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_irq.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/reboot.h> | ||
17 | #include <linux/watchdog.h> | ||
18 | |||
19 | #include "at91sam9_wdt.h" | ||
20 | |||
21 | /* minimum and maximum watchdog timeout, in seconds */ | ||
22 | #define MIN_WDT_TIMEOUT 1 | ||
23 | #define MAX_WDT_TIMEOUT 16 | ||
24 | #define WDT_DEFAULT_TIMEOUT MAX_WDT_TIMEOUT | ||
25 | |||
26 | #define WDT_SEC2TICKS(s) ((s) ? (((s) << 8) - 1) : 0) | ||
27 | |||
28 | struct sama5d4_wdt { | ||
29 | struct watchdog_device wdd; | ||
30 | void __iomem *reg_base; | ||
31 | u32 config; | ||
32 | }; | ||
33 | |||
34 | static int wdt_timeout = WDT_DEFAULT_TIMEOUT; | ||
35 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
36 | |||
37 | module_param(wdt_timeout, int, 0); | ||
38 | MODULE_PARM_DESC(wdt_timeout, | ||
39 | "Watchdog timeout in seconds. (default = " | ||
40 | __MODULE_STRING(WDT_DEFAULT_TIMEOUT) ")"); | ||
41 | |||
42 | module_param(nowayout, bool, 0); | ||
43 | MODULE_PARM_DESC(nowayout, | ||
44 | "Watchdog cannot be stopped once started (default=" | ||
45 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
46 | |||
47 | #define wdt_read(wdt, field) \ | ||
48 | readl_relaxed((wdt)->reg_base + (field)) | ||
49 | |||
50 | #define wdt_write(wtd, field, val) \ | ||
51 | writel_relaxed((val), (wdt)->reg_base + (field)) | ||
52 | |||
53 | static int sama5d4_wdt_start(struct watchdog_device *wdd) | ||
54 | { | ||
55 | struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); | ||
56 | u32 reg; | ||
57 | |||
58 | reg = wdt_read(wdt, AT91_WDT_MR); | ||
59 | reg &= ~AT91_WDT_WDDIS; | ||
60 | wdt_write(wdt, AT91_WDT_MR, reg); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int sama5d4_wdt_stop(struct watchdog_device *wdd) | ||
66 | { | ||
67 | struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); | ||
68 | u32 reg; | ||
69 | |||
70 | reg = wdt_read(wdt, AT91_WDT_MR); | ||
71 | reg |= AT91_WDT_WDDIS; | ||
72 | wdt_write(wdt, AT91_WDT_MR, reg); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int sama5d4_wdt_ping(struct watchdog_device *wdd) | ||
78 | { | ||
79 | struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); | ||
80 | |||
81 | wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd, | ||
87 | unsigned int timeout) | ||
88 | { | ||
89 | struct sama5d4_wdt *wdt = watchdog_get_drvdata(wdd); | ||
90 | u32 value = WDT_SEC2TICKS(timeout); | ||
91 | u32 reg; | ||
92 | |||
93 | reg = wdt_read(wdt, AT91_WDT_MR); | ||
94 | reg &= ~AT91_WDT_WDV; | ||
95 | reg &= ~AT91_WDT_WDD; | ||
96 | reg |= AT91_WDT_SET_WDV(value); | ||
97 | reg |= AT91_WDT_SET_WDD(value); | ||
98 | wdt_write(wdt, AT91_WDT_MR, reg); | ||
99 | |||
100 | wdd->timeout = timeout; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static const struct watchdog_info sama5d4_wdt_info = { | ||
106 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
107 | .identity = "Atmel SAMA5D4 Watchdog", | ||
108 | }; | ||
109 | |||
110 | static struct watchdog_ops sama5d4_wdt_ops = { | ||
111 | .owner = THIS_MODULE, | ||
112 | .start = sama5d4_wdt_start, | ||
113 | .stop = sama5d4_wdt_stop, | ||
114 | .ping = sama5d4_wdt_ping, | ||
115 | .set_timeout = sama5d4_wdt_set_timeout, | ||
116 | }; | ||
117 | |||
118 | static irqreturn_t sama5d4_wdt_irq_handler(int irq, void *dev_id) | ||
119 | { | ||
120 | struct sama5d4_wdt *wdt = platform_get_drvdata(dev_id); | ||
121 | |||
122 | if (wdt_read(wdt, AT91_WDT_SR)) { | ||
123 | pr_crit("Atmel Watchdog Software Reset\n"); | ||
124 | emergency_restart(); | ||
125 | pr_crit("Reboot didn't succeed\n"); | ||
126 | } | ||
127 | |||
128 | return IRQ_HANDLED; | ||
129 | } | ||
130 | |||
131 | static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt) | ||
132 | { | ||
133 | const char *tmp; | ||
134 | |||
135 | wdt->config = AT91_WDT_WDDIS; | ||
136 | |||
137 | if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) && | ||
138 | !strcmp(tmp, "software")) | ||
139 | wdt->config |= AT91_WDT_WDFIEN; | ||
140 | else | ||
141 | wdt->config |= AT91_WDT_WDRSTEN; | ||
142 | |||
143 | if (of_property_read_bool(np, "atmel,idle-halt")) | ||
144 | wdt->config |= AT91_WDT_WDIDLEHLT; | ||
145 | |||
146 | if (of_property_read_bool(np, "atmel,dbg-halt")) | ||
147 | wdt->config |= AT91_WDT_WDDBGHLT; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int sama5d4_wdt_init(struct sama5d4_wdt *wdt) | ||
153 | { | ||
154 | struct watchdog_device *wdd = &wdt->wdd; | ||
155 | u32 value = WDT_SEC2TICKS(wdd->timeout); | ||
156 | u32 reg; | ||
157 | |||
158 | /* | ||
159 | * Because the fields WDV and WDD must not be modified when the WDDIS | ||
160 | * bit is set, so clear the WDDIS bit before writing the WDT_MR. | ||
161 | */ | ||
162 | reg = wdt_read(wdt, AT91_WDT_MR); | ||
163 | reg &= ~AT91_WDT_WDDIS; | ||
164 | wdt_write(wdt, AT91_WDT_MR, reg); | ||
165 | |||
166 | reg = wdt->config; | ||
167 | reg |= AT91_WDT_SET_WDD(value); | ||
168 | reg |= AT91_WDT_SET_WDV(value); | ||
169 | |||
170 | wdt_write(wdt, AT91_WDT_MR, reg); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int sama5d4_wdt_probe(struct platform_device *pdev) | ||
176 | { | ||
177 | struct watchdog_device *wdd; | ||
178 | struct sama5d4_wdt *wdt; | ||
179 | struct resource *res; | ||
180 | void __iomem *regs; | ||
181 | u32 irq = 0; | ||
182 | int ret; | ||
183 | |||
184 | wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); | ||
185 | if (!wdt) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | wdd = &wdt->wdd; | ||
189 | wdd->timeout = wdt_timeout; | ||
190 | wdd->info = &sama5d4_wdt_info; | ||
191 | wdd->ops = &sama5d4_wdt_ops; | ||
192 | wdd->min_timeout = MIN_WDT_TIMEOUT; | ||
193 | wdd->max_timeout = MAX_WDT_TIMEOUT; | ||
194 | |||
195 | watchdog_set_drvdata(wdd, wdt); | ||
196 | |||
197 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
198 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
199 | if (IS_ERR(regs)) | ||
200 | return PTR_ERR(regs); | ||
201 | |||
202 | wdt->reg_base = regs; | ||
203 | |||
204 | if (pdev->dev.of_node) { | ||
205 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); | ||
206 | if (!irq) | ||
207 | dev_warn(&pdev->dev, "failed to get IRQ from DT\n"); | ||
208 | |||
209 | ret = of_sama5d4_wdt_init(pdev->dev.of_node, wdt); | ||
210 | if (ret) | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | if ((wdt->config & AT91_WDT_WDFIEN) && irq) { | ||
215 | ret = devm_request_irq(&pdev->dev, irq, sama5d4_wdt_irq_handler, | ||
216 | IRQF_SHARED | IRQF_IRQPOLL | | ||
217 | IRQF_NO_SUSPEND, pdev->name, pdev); | ||
218 | if (ret) { | ||
219 | dev_err(&pdev->dev, | ||
220 | "cannot register interrupt handler\n"); | ||
221 | return ret; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | ret = watchdog_init_timeout(wdd, wdt_timeout, &pdev->dev); | ||
226 | if (ret) { | ||
227 | dev_err(&pdev->dev, "unable to set timeout value\n"); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | ret = sama5d4_wdt_init(wdt); | ||
232 | if (ret) | ||
233 | return ret; | ||
234 | |||
235 | watchdog_set_nowayout(wdd, nowayout); | ||
236 | |||
237 | ret = watchdog_register_device(wdd); | ||
238 | if (ret) { | ||
239 | dev_err(&pdev->dev, "failed to register watchdog device\n"); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | platform_set_drvdata(pdev, wdt); | ||
244 | |||
245 | dev_info(&pdev->dev, "initialized (timeout = %d sec, nowayout = %d)\n", | ||
246 | wdt_timeout, nowayout); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int sama5d4_wdt_remove(struct platform_device *pdev) | ||
252 | { | ||
253 | struct sama5d4_wdt *wdt = platform_get_drvdata(pdev); | ||
254 | |||
255 | sama5d4_wdt_stop(&wdt->wdd); | ||
256 | |||
257 | watchdog_unregister_device(&wdt->wdd); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct of_device_id sama5d4_wdt_of_match[] = { | ||
263 | { .compatible = "atmel,sama5d4-wdt", }, | ||
264 | { } | ||
265 | }; | ||
266 | MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match); | ||
267 | |||
268 | static struct platform_driver sama5d4_wdt_driver = { | ||
269 | .probe = sama5d4_wdt_probe, | ||
270 | .remove = sama5d4_wdt_remove, | ||
271 | .driver = { | ||
272 | .name = "sama5d4_wdt", | ||
273 | .of_match_table = sama5d4_wdt_of_match, | ||
274 | } | ||
275 | }; | ||
276 | module_platform_driver(sama5d4_wdt_driver); | ||
277 | |||
278 | MODULE_AUTHOR("Atmel Corporation"); | ||
279 | MODULE_DESCRIPTION("Atmel SAMA5D4 Watchdog Timer driver"); | ||
280 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 567458b137a6..f90812170657 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c | |||
@@ -252,6 +252,7 @@ static int sh_wdt_probe(struct platform_device *pdev) | |||
252 | 252 | ||
253 | watchdog_set_nowayout(&sh_wdt_dev, nowayout); | 253 | watchdog_set_nowayout(&sh_wdt_dev, nowayout); |
254 | watchdog_set_drvdata(&sh_wdt_dev, wdt); | 254 | watchdog_set_drvdata(&sh_wdt_dev, wdt); |
255 | sh_wdt_dev.parent = &pdev->dev; | ||
255 | 256 | ||
256 | spin_lock_init(&wdt->lock); | 257 | spin_lock_init(&wdt->lock); |
257 | 258 | ||
diff --git a/drivers/watchdog/sirfsoc_wdt.c b/drivers/watchdog/sirfsoc_wdt.c index 42fa5c0c518a..d0578ab2e636 100644 --- a/drivers/watchdog/sirfsoc_wdt.c +++ b/drivers/watchdog/sirfsoc_wdt.c | |||
@@ -154,6 +154,7 @@ static int sirfsoc_wdt_probe(struct platform_device *pdev) | |||
154 | 154 | ||
155 | watchdog_init_timeout(&sirfsoc_wdd, timeout, &pdev->dev); | 155 | watchdog_init_timeout(&sirfsoc_wdd, timeout, &pdev->dev); |
156 | watchdog_set_nowayout(&sirfsoc_wdd, nowayout); | 156 | watchdog_set_nowayout(&sirfsoc_wdd, nowayout); |
157 | sirfsoc_wdd.parent = &pdev->dev; | ||
157 | 158 | ||
158 | ret = watchdog_register_device(&sirfsoc_wdd); | 159 | ret = watchdog_register_device(&sirfsoc_wdd); |
159 | if (ret) | 160 | if (ret) |
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 4e7fec36f5c3..01d816251302 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c | |||
@@ -226,6 +226,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) | |||
226 | wdt->adev = adev; | 226 | wdt->adev = adev; |
227 | wdt->wdd.info = &wdt_info; | 227 | wdt->wdd.info = &wdt_info; |
228 | wdt->wdd.ops = &wdt_ops; | 228 | wdt->wdd.ops = &wdt_ops; |
229 | wdt->wdd.parent = &adev->dev; | ||
229 | 230 | ||
230 | spin_lock_init(&wdt->lock); | 231 | spin_lock_init(&wdt->lock); |
231 | watchdog_set_nowayout(&wdt->wdd, nowayout); | 232 | watchdog_set_nowayout(&wdt->wdd, nowayout); |
diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c index 6785afdc0fca..14e9badf2bfa 100644 --- a/drivers/watchdog/st_lpc_wdt.c +++ b/drivers/watchdog/st_lpc_wdt.c | |||
@@ -241,6 +241,7 @@ static int st_wdog_probe(struct platform_device *pdev) | |||
241 | return -EINVAL; | 241 | return -EINVAL; |
242 | } | 242 | } |
243 | st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate; | 243 | st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate; |
244 | st_wdog_dev.parent = &pdev->dev; | ||
244 | 245 | ||
245 | ret = clk_prepare_enable(clk); | 246 | ret = clk_prepare_enable(clk); |
246 | if (ret) { | 247 | if (ret) { |
diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index e7f0d5b60d3d..3ee6128a540e 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c | |||
@@ -76,6 +76,7 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev) | |||
76 | watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); | 76 | watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); |
77 | 77 | ||
78 | stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); | 78 | stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); |
79 | stmp3xxx_wdd.parent = &pdev->dev; | ||
79 | 80 | ||
80 | ret = watchdog_register_device(&stmp3xxx_wdd); | 81 | ret = watchdog_register_device(&stmp3xxx_wdd); |
81 | if (ret < 0) { | 82 | if (ret < 0) { |
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index a29afb37c48c..47bd8a14d01f 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c | |||
@@ -184,7 +184,7 @@ static int sunxi_wdt_start(struct watchdog_device *wdt_dev) | |||
184 | /* Set system reset function */ | 184 | /* Set system reset function */ |
185 | reg = readl(wdt_base + regs->wdt_cfg); | 185 | reg = readl(wdt_base + regs->wdt_cfg); |
186 | reg &= ~(regs->wdt_reset_mask); | 186 | reg &= ~(regs->wdt_reset_mask); |
187 | reg |= ~(regs->wdt_reset_val); | 187 | reg |= regs->wdt_reset_val; |
188 | writel(reg, wdt_base + regs->wdt_cfg); | 188 | writel(reg, wdt_base + regs->wdt_cfg); |
189 | 189 | ||
190 | /* Enable watchdog */ | 190 | /* Enable watchdog */ |
diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c index 30451ea46902..7f97cdd53f29 100644 --- a/drivers/watchdog/tegra_wdt.c +++ b/drivers/watchdog/tegra_wdt.c | |||
@@ -218,6 +218,7 @@ static int tegra_wdt_probe(struct platform_device *pdev) | |||
218 | wdd->ops = &tegra_wdt_ops; | 218 | wdd->ops = &tegra_wdt_ops; |
219 | wdd->min_timeout = MIN_WDT_TIMEOUT; | 219 | wdd->min_timeout = MIN_WDT_TIMEOUT; |
220 | wdd->max_timeout = MAX_WDT_TIMEOUT; | 220 | wdd->max_timeout = MAX_WDT_TIMEOUT; |
221 | wdd->parent = &pdev->dev; | ||
221 | 222 | ||
222 | watchdog_set_drvdata(wdd, wdt); | 223 | watchdog_set_drvdata(wdd, wdt); |
223 | 224 | ||
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c index 2c1db6fa9a27..9bf3cc0f3961 100644 --- a/drivers/watchdog/twl4030_wdt.c +++ b/drivers/watchdog/twl4030_wdt.c | |||
@@ -83,6 +83,7 @@ static int twl4030_wdt_probe(struct platform_device *pdev) | |||
83 | wdt->timeout = 30; | 83 | wdt->timeout = 30; |
84 | wdt->min_timeout = 1; | 84 | wdt->min_timeout = 1; |
85 | wdt->max_timeout = 30; | 85 | wdt->max_timeout = 30; |
86 | wdt->parent = &pdev->dev; | ||
86 | 87 | ||
87 | watchdog_set_nowayout(wdt, nowayout); | 88 | watchdog_set_nowayout(wdt, nowayout); |
88 | platform_set_drvdata(pdev, wdt); | 89 | platform_set_drvdata(pdev, wdt); |
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 7f615933d31a..c2da880292bc 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c | |||
@@ -131,6 +131,7 @@ static int __init txx9wdt_probe(struct platform_device *dev) | |||
131 | txx9wdt.timeout = timeout; | 131 | txx9wdt.timeout = timeout; |
132 | txx9wdt.min_timeout = 1; | 132 | txx9wdt.min_timeout = 1; |
133 | txx9wdt.max_timeout = WD_MAX_TIMEOUT; | 133 | txx9wdt.max_timeout = WD_MAX_TIMEOUT; |
134 | txx9wdt.parent = &dev->dev; | ||
134 | watchdog_set_nowayout(&txx9wdt, nowayout); | 135 | watchdog_set_nowayout(&txx9wdt, nowayout); |
135 | 136 | ||
136 | ret = watchdog_register_device(&txx9wdt); | 137 | ret = watchdog_register_device(&txx9wdt); |
diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index 9de09ab00838..37c084353cce 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c | |||
@@ -96,6 +96,7 @@ static int ux500_wdt_probe(struct platform_device *pdev) | |||
96 | ux500_wdt.max_timeout = WATCHDOG_MAX28; | 96 | ux500_wdt.max_timeout = WATCHDOG_MAX28; |
97 | } | 97 | } |
98 | 98 | ||
99 | ux500_wdt.parent = &pdev->dev; | ||
99 | watchdog_set_nowayout(&ux500_wdt, nowayout); | 100 | watchdog_set_nowayout(&ux500_wdt, nowayout); |
100 | 101 | ||
101 | /* disable auto off on sleep */ | 102 | /* disable auto off on sleep */ |
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 56369c4f1961..5f9cbc37520d 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c | |||
@@ -206,6 +206,7 @@ static int wdt_probe(struct pci_dev *pdev, | |||
206 | timeout = WDT_TIMEOUT; | 206 | timeout = WDT_TIMEOUT; |
207 | 207 | ||
208 | wdt_dev.timeout = timeout; | 208 | wdt_dev.timeout = timeout; |
209 | wdt_dev.parent = &pdev->dev; | ||
209 | watchdog_set_nowayout(&wdt_dev, nowayout); | 210 | watchdog_set_nowayout(&wdt_dev, nowayout); |
210 | if (readl(wdt_mem) & VIA_WDT_FIRED) | 211 | if (readl(wdt_mem) & VIA_WDT_FIRED) |
211 | wdt_dev.bootstatus |= WDIOF_CARDRESET; | 212 | wdt_dev.bootstatus |= WDIOF_CARDRESET; |
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 2fa17e746ff6..8d1184aee932 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c | |||
@@ -215,6 +215,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) | |||
215 | 215 | ||
216 | wm831x_wdt->info = &wm831x_wdt_info; | 216 | wm831x_wdt->info = &wm831x_wdt_info; |
217 | wm831x_wdt->ops = &wm831x_wdt_ops; | 217 | wm831x_wdt->ops = &wm831x_wdt_ops; |
218 | wm831x_wdt->parent = &pdev->dev; | ||
218 | watchdog_set_nowayout(wm831x_wdt, nowayout); | 219 | watchdog_set_nowayout(wm831x_wdt, nowayout); |
219 | watchdog_set_drvdata(wm831x_wdt, driver_data); | 220 | watchdog_set_drvdata(wm831x_wdt, driver_data); |
220 | 221 | ||
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index 34d272ada23d..4ab4b8347d45 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c | |||
@@ -151,6 +151,7 @@ static int wm8350_wdt_probe(struct platform_device *pdev) | |||
151 | 151 | ||
152 | watchdog_set_nowayout(&wm8350_wdt, nowayout); | 152 | watchdog_set_nowayout(&wm8350_wdt, nowayout); |
153 | watchdog_set_drvdata(&wm8350_wdt, wm8350); | 153 | watchdog_set_drvdata(&wm8350_wdt, wm8350); |
154 | wm8350_wdt.parent = &pdev->dev; | ||
154 | 155 | ||
155 | /* Default to 4s timeout */ | 156 | /* Default to 4s timeout */ |
156 | wm8350_wdt_set_timeout(&wm8350_wdt, 4); | 157 | wm8350_wdt_set_timeout(&wm8350_wdt, 4); |