diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 38 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 2 | ||||
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 33 | ||||
-rw-r--r-- | drivers/watchdog/hpwdt.c | 59 | ||||
-rw-r--r-- | drivers/watchdog/i6300esb.c | 14 | ||||
-rw-r--r-- | drivers/watchdog/ie6xx_wdt.c | 348 | ||||
-rw-r--r-- | drivers/watchdog/it87_wdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/ixp2000_wdt.c | 215 | ||||
-rw-r--r-- | drivers/watchdog/pcwd_pci.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 10 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 7 | ||||
-rw-r--r-- | drivers/watchdog/sch311x_wdt.c | 39 | ||||
-rw-r--r-- | drivers/watchdog/shwdt.c | 306 | ||||
-rw-r--r-- | drivers/watchdog/sp5100_tco.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/via_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/wdt_pci.c | 34 | ||||
-rw-r--r-- | drivers/watchdog/wm831x_wdt.c | 13 |
17 files changed, 535 insertions, 628 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37096246c937..a18bf6358eb8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -129,17 +129,6 @@ config 977_WATCHDOG | |||
129 | 129 | ||
130 | Not sure? It's safe to say N. | 130 | Not sure? It's safe to say N. |
131 | 131 | ||
132 | config IXP2000_WATCHDOG | ||
133 | tristate "IXP2000 Watchdog" | ||
134 | depends on ARCH_IXP2000 | ||
135 | help | ||
136 | Say Y here if to include support for the watchdog timer | ||
137 | in the Intel IXP2000(2400, 2800, 2850) network processors. | ||
138 | This driver can be built as a module by choosing M. The module | ||
139 | will be called ixp2000_wdt. | ||
140 | |||
141 | Say N if you are unsure. | ||
142 | |||
143 | config IXP4XX_WATCHDOG | 132 | config IXP4XX_WATCHDOG |
144 | tristate "IXP4xx Watchdog" | 133 | tristate "IXP4xx Watchdog" |
145 | depends on ARCH_IXP4XX | 134 | depends on ARCH_IXP4XX |
@@ -543,7 +532,7 @@ config WAFER_WDT | |||
543 | 532 | ||
544 | config I6300ESB_WDT | 533 | config I6300ESB_WDT |
545 | tristate "Intel 6300ESB Timer/Watchdog" | 534 | tristate "Intel 6300ESB Timer/Watchdog" |
546 | depends on X86 && PCI | 535 | depends on PCI |
547 | ---help--- | 536 | ---help--- |
548 | Hardware driver for the watchdog timer built into the Intel | 537 | Hardware driver for the watchdog timer built into the Intel |
549 | 6300ESB controller hub. | 538 | 6300ESB controller hub. |
@@ -551,6 +540,19 @@ config I6300ESB_WDT | |||
551 | To compile this driver as a module, choose M here: the | 540 | To compile this driver as a module, choose M here: the |
552 | module will be called i6300esb. | 541 | module will be called i6300esb. |
553 | 542 | ||
543 | config IE6XX_WDT | ||
544 | tristate "Intel Atom E6xx Watchdog" | ||
545 | depends on X86 && PCI | ||
546 | select WATCHDOG_CORE | ||
547 | select MFD_CORE | ||
548 | select LPC_SCH | ||
549 | ---help--- | ||
550 | Hardware driver for the watchdog timer built into the Intel | ||
551 | Atom E6XX (TunnelCreek) processor. | ||
552 | |||
553 | To compile this driver as a module, choose M here: the | ||
554 | module will be called ie6xx_wdt. | ||
555 | |||
554 | config INTEL_SCU_WATCHDOG | 556 | config INTEL_SCU_WATCHDOG |
555 | bool "Intel SCU Watchdog for Mobile Platforms" | 557 | bool "Intel SCU Watchdog for Mobile Platforms" |
556 | depends on X86_MRST | 558 | depends on X86_MRST |
@@ -607,7 +609,12 @@ config IT87_WDT | |||
607 | depends on X86 && EXPERIMENTAL | 609 | depends on X86 && EXPERIMENTAL |
608 | ---help--- | 610 | ---help--- |
609 | This is the driver for the hardware watchdog on the ITE IT8702, | 611 | This is the driver for the hardware watchdog on the ITE IT8702, |
610 | IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips. | 612 | IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728 |
613 | Super I/O chips. | ||
614 | |||
615 | If the driver does not work, then make sure that the game port in | ||
616 | the BIOS is enabled. | ||
617 | |||
611 | This watchdog simply watches your kernel to make sure it doesn't | 618 | This watchdog simply watches your kernel to make sure it doesn't |
612 | freeze, and if it does, it reboots your computer after a certain | 619 | freeze, and if it does, it reboots your computer after a certain |
613 | amount of time. | 620 | amount of time. |
@@ -780,7 +787,7 @@ config SMSC37B787_WDT | |||
780 | 787 | ||
781 | config VIA_WDT | 788 | config VIA_WDT |
782 | tristate "VIA Watchdog Timer" | 789 | tristate "VIA Watchdog Timer" |
783 | depends on X86 | 790 | depends on X86 && PCI |
784 | select WATCHDOG_CORE | 791 | select WATCHDOG_CORE |
785 | ---help--- | 792 | ---help--- |
786 | This is the driver for the hardware watchdog timer on VIA | 793 | This is the driver for the hardware watchdog timer on VIA |
@@ -937,7 +944,7 @@ config BCM47XX_WDT | |||
937 | tristate "Broadcom BCM47xx Watchdog Timer" | 944 | tristate "Broadcom BCM47xx Watchdog Timer" |
938 | depends on BCM47XX | 945 | depends on BCM47XX |
939 | help | 946 | help |
940 | Hardware driver for the Broadcom BCM47xx Watchog Timer. | 947 | Hardware driver for the Broadcom BCM47xx Watchdog Timer. |
941 | 948 | ||
942 | config RC32434_WDT | 949 | config RC32434_WDT |
943 | tristate "IDT RC32434 SoC Watchdog Timer" | 950 | tristate "IDT RC32434 SoC Watchdog Timer" |
@@ -1138,6 +1145,7 @@ config ZVM_WATCHDOG | |||
1138 | config SH_WDT | 1145 | config SH_WDT |
1139 | tristate "SuperH Watchdog" | 1146 | tristate "SuperH Watchdog" |
1140 | depends on SUPERH && (CPU_SH3 || CPU_SH4) | 1147 | depends on SUPERH && (CPU_SH3 || CPU_SH4) |
1148 | select WATCHDOG_CORE | ||
1141 | help | 1149 | help |
1142 | This driver adds watchdog support for the integrated watchdog in the | 1150 | This driver adds watchdog support for the integrated watchdog in the |
1143 | SuperH processors. If you have one of these processors and wish | 1151 | SuperH processors. If you have one of these processors and wish |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e8f479a16402..442bfbe0882a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -36,7 +36,6 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o | |||
36 | obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o | 36 | obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o |
37 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 37 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
38 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 38 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
39 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | ||
40 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | 39 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o |
41 | obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o | 40 | obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o |
42 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o | 41 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o |
@@ -81,6 +80,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o | |||
81 | obj-$(CONFIG_IBMASR) += ibmasr.o | 80 | obj-$(CONFIG_IBMASR) += ibmasr.o |
82 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o | 81 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o |
83 | obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o | 82 | obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o |
83 | obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o | ||
84 | obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o | 84 | obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o |
85 | ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) | 85 | ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) |
86 | obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o | 86 | obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o |
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 639ae9a23fbc..dc30dbd21cf1 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
@@ -282,29 +282,19 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev) | |||
282 | platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | 282 | platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); |
283 | if (!ar7_regs_wdt) { | 283 | if (!ar7_regs_wdt) { |
284 | pr_err("could not get registers resource\n"); | 284 | pr_err("could not get registers resource\n"); |
285 | rc = -ENODEV; | 285 | return -ENODEV; |
286 | goto out; | ||
287 | } | ||
288 | |||
289 | if (!request_mem_region(ar7_regs_wdt->start, | ||
290 | resource_size(ar7_regs_wdt), LONGNAME)) { | ||
291 | pr_warn("watchdog I/O region busy\n"); | ||
292 | rc = -EBUSY; | ||
293 | goto out; | ||
294 | } | 286 | } |
295 | 287 | ||
296 | ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); | 288 | ar7_wdt = devm_request_and_ioremap(&pdev->dev, ar7_regs_wdt); |
297 | if (!ar7_wdt) { | 289 | if (!ar7_wdt) { |
298 | pr_err("could not ioremap registers\n"); | 290 | pr_err("could not ioremap registers\n"); |
299 | rc = -ENXIO; | 291 | return -ENXIO; |
300 | goto out_mem_region; | ||
301 | } | 292 | } |
302 | 293 | ||
303 | vbus_clk = clk_get(NULL, "vbus"); | 294 | vbus_clk = clk_get(NULL, "vbus"); |
304 | if (IS_ERR(vbus_clk)) { | 295 | if (IS_ERR(vbus_clk)) { |
305 | pr_err("could not get vbus clock\n"); | 296 | pr_err("could not get vbus clock\n"); |
306 | rc = PTR_ERR(vbus_clk); | 297 | return PTR_ERR(vbus_clk); |
307 | goto out_mem_region; | ||
308 | } | 298 | } |
309 | 299 | ||
310 | ar7_wdt_disable_wdt(); | 300 | ar7_wdt_disable_wdt(); |
@@ -314,24 +304,21 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev) | |||
314 | rc = misc_register(&ar7_wdt_miscdev); | 304 | rc = misc_register(&ar7_wdt_miscdev); |
315 | if (rc) { | 305 | if (rc) { |
316 | pr_err("unable to register misc device\n"); | 306 | pr_err("unable to register misc device\n"); |
317 | goto out_alloc; | 307 | goto out; |
318 | } | 308 | } |
319 | goto out; | 309 | return 0; |
320 | 310 | ||
321 | out_alloc: | ||
322 | iounmap(ar7_wdt); | ||
323 | out_mem_region: | ||
324 | release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); | ||
325 | out: | 311 | out: |
312 | clk_put(vbus_clk); | ||
313 | vbus_clk = NULL; | ||
326 | return rc; | 314 | return rc; |
327 | } | 315 | } |
328 | 316 | ||
329 | static int __devexit ar7_wdt_remove(struct platform_device *pdev) | 317 | static int __devexit ar7_wdt_remove(struct platform_device *pdev) |
330 | { | 318 | { |
331 | misc_deregister(&ar7_wdt_miscdev); | 319 | misc_deregister(&ar7_wdt_miscdev); |
332 | iounmap(ar7_wdt); | 320 | clk_put(vbus_clk); |
333 | release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt)); | 321 | vbus_clk = NULL; |
334 | |||
335 | return 0; | 322 | return 0; |
336 | } | 323 | } |
337 | 324 | ||
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 9f13b897fd64..2b763815aeec 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -147,7 +147,6 @@ struct cmn_registers { | |||
147 | 147 | ||
148 | static unsigned int hpwdt_nmi_decoding; | 148 | static unsigned int hpwdt_nmi_decoding; |
149 | static unsigned int allow_kdump; | 149 | static unsigned int allow_kdump; |
150 | static unsigned int priority; /* hpwdt at end of die_notify list */ | ||
151 | static unsigned int is_icru; | 150 | static unsigned int is_icru; |
152 | static DEFINE_SPINLOCK(rom_lock); | 151 | static DEFINE_SPINLOCK(rom_lock); |
153 | static void *cru_rom_addr; | 152 | static void *cru_rom_addr; |
@@ -723,28 +722,35 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) | |||
723 | } | 722 | } |
724 | 723 | ||
725 | /* | 724 | /* |
726 | * If the priority is set to 1, then we will be put first on the | 725 | * Only one function can register for NMI_UNKNOWN |
727 | * die notify list to handle a critical NMI. The default is to | ||
728 | * be last so other users of the NMI signal can function. | ||
729 | */ | 726 | */ |
730 | retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, | 727 | retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, 0, "hpwdt"); |
731 | (priority) ? NMI_FLAG_FIRST : 0, | 728 | if (retval) |
732 | "hpwdt"); | 729 | goto error; |
733 | if (retval != 0) { | 730 | retval = register_nmi_handler(NMI_SERR, hpwdt_pretimeout, 0, "hpwdt"); |
734 | dev_warn(&dev->dev, | 731 | if (retval) |
735 | "Unable to register a die notifier (err=%d).\n", | 732 | goto error1; |
736 | retval); | 733 | retval = register_nmi_handler(NMI_IO_CHECK, hpwdt_pretimeout, 0, "hpwdt"); |
737 | if (cru_rom_addr) | 734 | if (retval) |
738 | iounmap(cru_rom_addr); | 735 | goto error2; |
739 | } | ||
740 | 736 | ||
741 | dev_info(&dev->dev, | 737 | dev_info(&dev->dev, |
742 | "HP Watchdog Timer Driver: NMI decoding initialized" | 738 | "HP Watchdog Timer Driver: NMI decoding initialized" |
743 | ", allow kernel dump: %s (default = 0/OFF)" | 739 | ", allow kernel dump: %s (default = 0/OFF)\n", |
744 | ", priority: %s (default = 0/LAST).\n", | 740 | (allow_kdump == 0) ? "OFF" : "ON"); |
745 | (allow_kdump == 0) ? "OFF" : "ON", | ||
746 | (priority == 0) ? "LAST" : "FIRST"); | ||
747 | return 0; | 741 | return 0; |
742 | |||
743 | error2: | ||
744 | unregister_nmi_handler(NMI_SERR, "hpwdt"); | ||
745 | error1: | ||
746 | unregister_nmi_handler(NMI_UNKNOWN, "hpwdt"); | ||
747 | error: | ||
748 | dev_warn(&dev->dev, | ||
749 | "Unable to register a die notifier (err=%d).\n", | ||
750 | retval); | ||
751 | if (cru_rom_addr) | ||
752 | iounmap(cru_rom_addr); | ||
753 | return retval; | ||
748 | } | 754 | } |
749 | 755 | ||
750 | static void hpwdt_exit_nmi_decoding(void) | 756 | static void hpwdt_exit_nmi_decoding(void) |
@@ -855,16 +861,6 @@ static struct pci_driver hpwdt_driver = { | |||
855 | .remove = __devexit_p(hpwdt_exit), | 861 | .remove = __devexit_p(hpwdt_exit), |
856 | }; | 862 | }; |
857 | 863 | ||
858 | static void __exit hpwdt_cleanup(void) | ||
859 | { | ||
860 | pci_unregister_driver(&hpwdt_driver); | ||
861 | } | ||
862 | |||
863 | static int __init hpwdt_init(void) | ||
864 | { | ||
865 | return pci_register_driver(&hpwdt_driver); | ||
866 | } | ||
867 | |||
868 | MODULE_AUTHOR("Tom Mingarelli"); | 864 | MODULE_AUTHOR("Tom Mingarelli"); |
869 | MODULE_DESCRIPTION("hp watchdog driver"); | 865 | MODULE_DESCRIPTION("hp watchdog driver"); |
870 | MODULE_LICENSE("GPL"); | 866 | MODULE_LICENSE("GPL"); |
@@ -881,11 +877,6 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | |||
881 | #ifdef CONFIG_HPWDT_NMI_DECODING | 877 | #ifdef CONFIG_HPWDT_NMI_DECODING |
882 | module_param(allow_kdump, int, 0); | 878 | module_param(allow_kdump, int, 0); |
883 | MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); | 879 | MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); |
884 | |||
885 | module_param(priority, int, 0); | ||
886 | MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" | ||
887 | " (default = 0/Last)\n"); | ||
888 | #endif /* !CONFIG_HPWDT_NMI_DECODING */ | 880 | #endif /* !CONFIG_HPWDT_NMI_DECODING */ |
889 | 881 | ||
890 | module_init(hpwdt_init); | 882 | module_pci_driver(hpwdt_driver); |
891 | module_exit(hpwdt_cleanup); | ||
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 738032a36bcf..276877d5b6a3 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c | |||
@@ -492,19 +492,7 @@ static struct pci_driver esb_driver = { | |||
492 | .shutdown = esb_shutdown, | 492 | .shutdown = esb_shutdown, |
493 | }; | 493 | }; |
494 | 494 | ||
495 | static int __init watchdog_init(void) | 495 | module_pci_driver(esb_driver); |
496 | { | ||
497 | return pci_register_driver(&esb_driver); | ||
498 | } | ||
499 | |||
500 | static void __exit watchdog_cleanup(void) | ||
501 | { | ||
502 | pci_unregister_driver(&esb_driver); | ||
503 | pr_info("Watchdog Module Unloaded\n"); | ||
504 | } | ||
505 | |||
506 | module_init(watchdog_init); | ||
507 | module_exit(watchdog_cleanup); | ||
508 | 496 | ||
509 | MODULE_AUTHOR("Ross Biro and David Härdeman"); | 497 | MODULE_AUTHOR("Ross Biro and David Härdeman"); |
510 | MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); | 498 | MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); |
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c new file mode 100644 index 000000000000..5f0d776f902c --- /dev/null +++ b/drivers/watchdog/ie6xx_wdt.c | |||
@@ -0,0 +1,348 @@ | |||
1 | /* | ||
2 | * Intel Atom E6xx Watchdog driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Alexander Stein | ||
5 | * <alexander.stein@systec-electronic.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of version 2 of the GNU General | ||
9 | * Public License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be | ||
12 | * useful, but WITHOUT ANY WARRANTY; without even the implied | ||
13 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
14 | * PURPOSE. See the GNU General Public License for more details. | ||
15 | * You should have received a copy of the GNU General Public | ||
16 | * License along with this program; if not, write to the Free | ||
17 | * Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | * Boston, MA 02111-1307, USA. | ||
19 | * The full GNU General Public License is included in this | ||
20 | * distribution in the file called COPYING. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/watchdog.h> | ||
31 | #include <linux/miscdevice.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | |||
37 | #define DRIVER_NAME "ie6xx_wdt" | ||
38 | |||
39 | #define PV1 0x00 | ||
40 | #define PV2 0x04 | ||
41 | |||
42 | #define RR0 0x0c | ||
43 | #define RR1 0x0d | ||
44 | #define WDT_RELOAD 0x01 | ||
45 | #define WDT_TOUT 0x02 | ||
46 | |||
47 | #define WDTCR 0x10 | ||
48 | #define WDT_PRE_SEL 0x04 | ||
49 | #define WDT_RESET_SEL 0x08 | ||
50 | #define WDT_RESET_EN 0x10 | ||
51 | #define WDT_TOUT_EN 0x20 | ||
52 | |||
53 | #define DCR 0x14 | ||
54 | |||
55 | #define WDTLR 0x18 | ||
56 | #define WDT_LOCK 0x01 | ||
57 | #define WDT_ENABLE 0x02 | ||
58 | #define WDT_TOUT_CNF 0x03 | ||
59 | |||
60 | #define MIN_TIME 1 | ||
61 | #define MAX_TIME (10 * 60) /* 10 minutes */ | ||
62 | #define DEFAULT_TIME 60 | ||
63 | |||
64 | static unsigned int timeout = DEFAULT_TIME; | ||
65 | module_param(timeout, uint, 0); | ||
66 | MODULE_PARM_DESC(timeout, | ||
67 | "Default Watchdog timer setting (" | ||
68 | __MODULE_STRING(DEFAULT_TIME) "s)." | ||
69 | "The range is from 1 to 600"); | ||
70 | |||
71 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
72 | module_param(nowayout, bool, 0); | ||
73 | MODULE_PARM_DESC(nowayout, | ||
74 | "Watchdog cannot be stopped once started (default=" | ||
75 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
76 | |||
77 | static u8 resetmode = 0x10; | ||
78 | module_param(resetmode, byte, 0); | ||
79 | MODULE_PARM_DESC(resetmode, | ||
80 | "Resetmode bits: 0x08 warm reset (cold reset otherwise), " | ||
81 | "0x10 reset enable, 0x20 disable toggle GPIO[4] (default=0x10)"); | ||
82 | |||
83 | static struct { | ||
84 | unsigned short sch_wdtba; | ||
85 | struct spinlock unlock_sequence; | ||
86 | #ifdef CONFIG_DEBUG_FS | ||
87 | struct dentry *debugfs; | ||
88 | #endif | ||
89 | } ie6xx_wdt_data; | ||
90 | |||
91 | /* | ||
92 | * This is needed to write to preload and reload registers | ||
93 | * struct ie6xx_wdt_data.unlock_sequence must be used | ||
94 | * to prevent sequence interrupts | ||
95 | */ | ||
96 | static void ie6xx_wdt_unlock_registers(void) | ||
97 | { | ||
98 | outb(0x80, ie6xx_wdt_data.sch_wdtba + RR0); | ||
99 | outb(0x86, ie6xx_wdt_data.sch_wdtba + RR0); | ||
100 | } | ||
101 | |||
102 | static int ie6xx_wdt_ping(struct watchdog_device *wdd) | ||
103 | { | ||
104 | spin_lock(&ie6xx_wdt_data.unlock_sequence); | ||
105 | ie6xx_wdt_unlock_registers(); | ||
106 | outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1); | ||
107 | spin_unlock(&ie6xx_wdt_data.unlock_sequence); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) | ||
112 | { | ||
113 | u32 preload; | ||
114 | u64 clock; | ||
115 | u8 wdtcr; | ||
116 | |||
117 | /* Watchdog clock is PCI Clock (33MHz) */ | ||
118 | clock = 33000000; | ||
119 | /* and the preload value is loaded into [34:15] of the down counter */ | ||
120 | preload = (t * clock) >> 15; | ||
121 | /* | ||
122 | * Manual states preload must be one less. | ||
123 | * Does not wrap as t is at least 1 | ||
124 | */ | ||
125 | preload -= 1; | ||
126 | |||
127 | spin_lock(&ie6xx_wdt_data.unlock_sequence); | ||
128 | |||
129 | /* Set ResetMode & Enable prescaler for range 10ms to 10 min */ | ||
130 | wdtcr = resetmode & 0x38; | ||
131 | outb(wdtcr, ie6xx_wdt_data.sch_wdtba + WDTCR); | ||
132 | |||
133 | ie6xx_wdt_unlock_registers(); | ||
134 | outl(0, ie6xx_wdt_data.sch_wdtba + PV1); | ||
135 | |||
136 | ie6xx_wdt_unlock_registers(); | ||
137 | outl(preload, ie6xx_wdt_data.sch_wdtba + PV2); | ||
138 | |||
139 | ie6xx_wdt_unlock_registers(); | ||
140 | outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1); | ||
141 | |||
142 | spin_unlock(&ie6xx_wdt_data.unlock_sequence); | ||
143 | |||
144 | wdd->timeout = t; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int ie6xx_wdt_start(struct watchdog_device *wdd) | ||
149 | { | ||
150 | ie6xx_wdt_set_timeout(wdd, wdd->timeout); | ||
151 | |||
152 | /* Enable the watchdog timer */ | ||
153 | spin_lock(&ie6xx_wdt_data.unlock_sequence); | ||
154 | outb(WDT_ENABLE, ie6xx_wdt_data.sch_wdtba + WDTLR); | ||
155 | spin_unlock(&ie6xx_wdt_data.unlock_sequence); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int ie6xx_wdt_stop(struct watchdog_device *wdd) | ||
161 | { | ||
162 | if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK) | ||
163 | return -1; | ||
164 | |||
165 | /* Disable the watchdog timer */ | ||
166 | spin_lock(&ie6xx_wdt_data.unlock_sequence); | ||
167 | outb(0, ie6xx_wdt_data.sch_wdtba + WDTLR); | ||
168 | spin_unlock(&ie6xx_wdt_data.unlock_sequence); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static const struct watchdog_info ie6xx_wdt_info = { | ||
174 | .identity = "Intel Atom E6xx Watchdog", | ||
175 | .options = WDIOF_SETTIMEOUT | | ||
176 | WDIOF_MAGICCLOSE | | ||
177 | WDIOF_KEEPALIVEPING, | ||
178 | }; | ||
179 | |||
180 | static const struct watchdog_ops ie6xx_wdt_ops = { | ||
181 | .owner = THIS_MODULE, | ||
182 | .start = ie6xx_wdt_start, | ||
183 | .stop = ie6xx_wdt_stop, | ||
184 | .ping = ie6xx_wdt_ping, | ||
185 | .set_timeout = ie6xx_wdt_set_timeout, | ||
186 | }; | ||
187 | |||
188 | static struct watchdog_device ie6xx_wdt_dev = { | ||
189 | .info = &ie6xx_wdt_info, | ||
190 | .ops = &ie6xx_wdt_ops, | ||
191 | .min_timeout = MIN_TIME, | ||
192 | .max_timeout = MAX_TIME, | ||
193 | }; | ||
194 | |||
195 | #ifdef CONFIG_DEBUG_FS | ||
196 | |||
197 | static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused) | ||
198 | { | ||
199 | seq_printf(s, "PV1 = 0x%08x\n", | ||
200 | inl(ie6xx_wdt_data.sch_wdtba + PV1)); | ||
201 | seq_printf(s, "PV2 = 0x%08x\n", | ||
202 | inl(ie6xx_wdt_data.sch_wdtba + PV2)); | ||
203 | seq_printf(s, "RR = 0x%08x\n", | ||
204 | inw(ie6xx_wdt_data.sch_wdtba + RR0)); | ||
205 | seq_printf(s, "WDTCR = 0x%08x\n", | ||
206 | inw(ie6xx_wdt_data.sch_wdtba + WDTCR)); | ||
207 | seq_printf(s, "DCR = 0x%08x\n", | ||
208 | inl(ie6xx_wdt_data.sch_wdtba + DCR)); | ||
209 | seq_printf(s, "WDTLR = 0x%08x\n", | ||
210 | inw(ie6xx_wdt_data.sch_wdtba + WDTLR)); | ||
211 | |||
212 | seq_printf(s, "\n"); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int ie6xx_wdt_dbg_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return single_open(file, ie6xx_wdt_dbg_show, NULL); | ||
219 | } | ||
220 | |||
221 | static const struct file_operations ie6xx_wdt_dbg_operations = { | ||
222 | .open = ie6xx_wdt_dbg_open, | ||
223 | .read = seq_read, | ||
224 | .llseek = seq_lseek, | ||
225 | .release = single_release, | ||
226 | }; | ||
227 | |||
228 | static void __devinit ie6xx_wdt_debugfs_init(void) | ||
229 | { | ||
230 | /* /sys/kernel/debug/ie6xx_wdt */ | ||
231 | ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt", | ||
232 | S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); | ||
233 | } | ||
234 | |||
235 | static void __devexit ie6xx_wdt_debugfs_exit(void) | ||
236 | { | ||
237 | debugfs_remove(ie6xx_wdt_data.debugfs); | ||
238 | } | ||
239 | |||
240 | #else | ||
241 | static void __devinit ie6xx_wdt_debugfs_init(void) | ||
242 | { | ||
243 | } | ||
244 | |||
245 | static void __devexit ie6xx_wdt_debugfs_exit(void) | ||
246 | { | ||
247 | } | ||
248 | #endif | ||
249 | |||
250 | static int __devinit ie6xx_wdt_probe(struct platform_device *pdev) | ||
251 | { | ||
252 | struct resource *res; | ||
253 | u8 wdtlr; | ||
254 | int ret; | ||
255 | |||
256 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
257 | if (!res) | ||
258 | return -ENODEV; | ||
259 | |||
260 | if (!request_region(res->start, resource_size(res), pdev->name)) { | ||
261 | dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n", | ||
262 | (u64)res->start); | ||
263 | return -EBUSY; | ||
264 | } | ||
265 | |||
266 | ie6xx_wdt_data.sch_wdtba = res->start; | ||
267 | dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba); | ||
268 | |||
269 | ie6xx_wdt_dev.timeout = timeout; | ||
270 | watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); | ||
271 | |||
272 | spin_lock_init(&ie6xx_wdt_data.unlock_sequence); | ||
273 | |||
274 | wdtlr = inb(ie6xx_wdt_data.sch_wdtba + WDTLR); | ||
275 | if (wdtlr & WDT_LOCK) | ||
276 | dev_warn(&pdev->dev, | ||
277 | "Watchdog Timer is Locked (Reg=0x%x)\n", wdtlr); | ||
278 | |||
279 | ie6xx_wdt_debugfs_init(); | ||
280 | |||
281 | ret = watchdog_register_device(&ie6xx_wdt_dev); | ||
282 | if (ret) { | ||
283 | dev_err(&pdev->dev, | ||
284 | "Watchdog timer: cannot register device (err =%d)\n", | ||
285 | ret); | ||
286 | goto misc_register_error; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | misc_register_error: | ||
292 | ie6xx_wdt_debugfs_exit(); | ||
293 | release_region(res->start, resource_size(res)); | ||
294 | ie6xx_wdt_data.sch_wdtba = 0; | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static int __devexit ie6xx_wdt_remove(struct platform_device *pdev) | ||
299 | { | ||
300 | struct resource *res; | ||
301 | |||
302 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
303 | ie6xx_wdt_stop(NULL); | ||
304 | watchdog_unregister_device(&ie6xx_wdt_dev); | ||
305 | ie6xx_wdt_debugfs_exit(); | ||
306 | release_region(res->start, resource_size(res)); | ||
307 | ie6xx_wdt_data.sch_wdtba = 0; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static struct platform_driver ie6xx_wdt_driver = { | ||
313 | .probe = ie6xx_wdt_probe, | ||
314 | .remove = __devexit_p(ie6xx_wdt_remove), | ||
315 | .driver = { | ||
316 | .name = DRIVER_NAME, | ||
317 | .owner = THIS_MODULE, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static int __init ie6xx_wdt_init(void) | ||
322 | { | ||
323 | /* Check boot parameters to verify that their initial values */ | ||
324 | /* are in range. */ | ||
325 | if ((timeout < MIN_TIME) || | ||
326 | (timeout > MAX_TIME)) { | ||
327 | pr_err("Watchdog timer: value of timeout %d (dec) " | ||
328 | "is out of range from %d to %d (dec)\n", | ||
329 | timeout, MIN_TIME, MAX_TIME); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | return platform_driver_register(&ie6xx_wdt_driver); | ||
334 | } | ||
335 | |||
336 | static void __exit ie6xx_wdt_exit(void) | ||
337 | { | ||
338 | platform_driver_unregister(&ie6xx_wdt_driver); | ||
339 | } | ||
340 | |||
341 | late_initcall(ie6xx_wdt_init); | ||
342 | module_exit(ie6xx_wdt_exit); | ||
343 | |||
344 | MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); | ||
345 | MODULE_DESCRIPTION("Intel Atom E6xx Watchdog Device Driver"); | ||
346 | MODULE_LICENSE("GPL"); | ||
347 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
348 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 8a741bcb5124..d3dcc6988b5f 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c | |||
@@ -12,7 +12,8 @@ | |||
12 | * http://www.ite.com.tw/ | 12 | * http://www.ite.com.tw/ |
13 | * | 13 | * |
14 | * Support of the watchdog timers, which are available on | 14 | * Support of the watchdog timers, which are available on |
15 | * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726. | 15 | * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 |
16 | * and IT8728. | ||
16 | * | 17 | * |
17 | * This program is free software; you can redistribute it and/or | 18 | * This program is free software; you can redistribute it and/or |
18 | * modify it under the terms of the GNU General Public License | 19 | * modify it under the terms of the GNU General Public License |
@@ -84,6 +85,7 @@ | |||
84 | #define IT8720_ID 0x8720 | 85 | #define IT8720_ID 0x8720 |
85 | #define IT8721_ID 0x8721 | 86 | #define IT8721_ID 0x8721 |
86 | #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ | 87 | #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ |
88 | #define IT8728_ID 0x8728 | ||
87 | 89 | ||
88 | /* GPIO Configuration Registers LDN=0x07 */ | 90 | /* GPIO Configuration Registers LDN=0x07 */ |
89 | #define WDTCTRL 0x71 | 91 | #define WDTCTRL 0x71 |
@@ -95,7 +97,7 @@ | |||
95 | #define WDT_CIRINT 0x80 | 97 | #define WDT_CIRINT 0x80 |
96 | #define WDT_MOUSEINT 0x40 | 98 | #define WDT_MOUSEINT 0x40 |
97 | #define WDT_KYBINT 0x20 | 99 | #define WDT_KYBINT 0x20 |
98 | #define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */ | 100 | #define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721, it8728 */ |
99 | #define WDT_FORCE 0x02 | 101 | #define WDT_FORCE 0x02 |
100 | #define WDT_ZERO 0x01 | 102 | #define WDT_ZERO 0x01 |
101 | 103 | ||
@@ -616,6 +618,7 @@ static int __init it87_wdt_init(void) | |||
616 | case IT8718_ID: | 618 | case IT8718_ID: |
617 | case IT8720_ID: | 619 | case IT8720_ID: |
618 | case IT8721_ID: | 620 | case IT8721_ID: |
621 | case IT8728_ID: | ||
619 | max_units = 65535; | 622 | max_units = 65535; |
620 | try_gameport = 0; | 623 | try_gameport = 0; |
621 | break; | 624 | break; |
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c deleted file mode 100644 index 3f047a58d3ae..000000000000 --- a/drivers/watchdog/ixp2000_wdt.c +++ /dev/null | |||
@@ -1,215 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/ixp2000_wdt.c | ||
3 | * | ||
4 | * Watchdog driver for Intel IXP2000 network processors | ||
5 | * | ||
6 | * Adapted from the IXP4xx watchdog driver by Lennert Buytenhek. | ||
7 | * The original version carries these notices: | ||
8 | * | ||
9 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
10 | * | ||
11 | * Copyright 2004 (c) MontaVista, Software, Inc. | ||
12 | * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu> | ||
13 | * | ||
14 | * This file is licensed under the terms of the GNU General Public | ||
15 | * License version 2. This program is licensed "as is" without any | ||
16 | * warranty of any kind, whether express or implied. | ||
17 | */ | ||
18 | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/timer.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/fs.h> | ||
27 | #include <linux/miscdevice.h> | ||
28 | #include <linux/watchdog.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/bitops.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <mach/hardware.h> | ||
33 | |||
34 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
35 | static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ | ||
36 | static unsigned long wdt_status; | ||
37 | static DEFINE_SPINLOCK(wdt_lock); | ||
38 | |||
39 | #define WDT_IN_USE 0 | ||
40 | #define WDT_OK_TO_CLOSE 1 | ||
41 | |||
42 | static unsigned long wdt_tick_rate; | ||
43 | |||
44 | static void wdt_enable(void) | ||
45 | { | ||
46 | spin_lock(&wdt_lock); | ||
47 | ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); | ||
48 | ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); | ||
49 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); | ||
50 | ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); | ||
51 | spin_unlock(&wdt_lock); | ||
52 | } | ||
53 | |||
54 | static void wdt_disable(void) | ||
55 | { | ||
56 | spin_lock(&wdt_lock); | ||
57 | ixp2000_reg_write(IXP2000_T4_CTL, 0); | ||
58 | spin_unlock(&wdt_lock); | ||
59 | } | ||
60 | |||
61 | static void wdt_keepalive(void) | ||
62 | { | ||
63 | spin_lock(&wdt_lock); | ||
64 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); | ||
65 | spin_unlock(&wdt_lock); | ||
66 | } | ||
67 | |||
68 | static int ixp2000_wdt_open(struct inode *inode, struct file *file) | ||
69 | { | ||
70 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
71 | return -EBUSY; | ||
72 | |||
73 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
74 | |||
75 | wdt_enable(); | ||
76 | |||
77 | return nonseekable_open(inode, file); | ||
78 | } | ||
79 | |||
80 | static ssize_t ixp2000_wdt_write(struct file *file, const char *data, | ||
81 | size_t len, loff_t *ppos) | ||
82 | { | ||
83 | if (len) { | ||
84 | if (!nowayout) { | ||
85 | size_t i; | ||
86 | |||
87 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
88 | |||
89 | for (i = 0; i != len; i++) { | ||
90 | char c; | ||
91 | |||
92 | if (get_user(c, data + i)) | ||
93 | return -EFAULT; | ||
94 | if (c == 'V') | ||
95 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
96 | } | ||
97 | } | ||
98 | wdt_keepalive(); | ||
99 | } | ||
100 | |||
101 | return len; | ||
102 | } | ||
103 | |||
104 | |||
105 | static const struct watchdog_info ident = { | ||
106 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | ||
107 | WDIOF_KEEPALIVEPING, | ||
108 | .identity = "IXP2000 Watchdog", | ||
109 | }; | ||
110 | |||
111 | static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd, | ||
112 | unsigned long arg) | ||
113 | { | ||
114 | int ret = -ENOTTY; | ||
115 | int time; | ||
116 | |||
117 | switch (cmd) { | ||
118 | case WDIOC_GETSUPPORT: | ||
119 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
120 | sizeof(ident)) ? -EFAULT : 0; | ||
121 | break; | ||
122 | |||
123 | case WDIOC_GETSTATUS: | ||
124 | ret = put_user(0, (int *)arg); | ||
125 | break; | ||
126 | |||
127 | case WDIOC_GETBOOTSTATUS: | ||
128 | ret = put_user(0, (int *)arg); | ||
129 | break; | ||
130 | |||
131 | case WDIOC_KEEPALIVE: | ||
132 | wdt_enable(); | ||
133 | ret = 0; | ||
134 | break; | ||
135 | |||
136 | case WDIOC_SETTIMEOUT: | ||
137 | ret = get_user(time, (int *)arg); | ||
138 | if (ret) | ||
139 | break; | ||
140 | |||
141 | if (time <= 0 || time > 60) { | ||
142 | ret = -EINVAL; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | heartbeat = time; | ||
147 | wdt_keepalive(); | ||
148 | /* Fall through */ | ||
149 | |||
150 | case WDIOC_GETTIMEOUT: | ||
151 | ret = put_user(heartbeat, (int *)arg); | ||
152 | break; | ||
153 | } | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static int ixp2000_wdt_release(struct inode *inode, struct file *file) | ||
159 | { | ||
160 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
161 | wdt_disable(); | ||
162 | else | ||
163 | pr_crit("Device closed unexpectedly - timer will not stop\n"); | ||
164 | clear_bit(WDT_IN_USE, &wdt_status); | ||
165 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | |||
171 | static const struct file_operations ixp2000_wdt_fops = { | ||
172 | .owner = THIS_MODULE, | ||
173 | .llseek = no_llseek, | ||
174 | .write = ixp2000_wdt_write, | ||
175 | .unlocked_ioctl = ixp2000_wdt_ioctl, | ||
176 | .open = ixp2000_wdt_open, | ||
177 | .release = ixp2000_wdt_release, | ||
178 | }; | ||
179 | |||
180 | static struct miscdevice ixp2000_wdt_miscdev = { | ||
181 | .minor = WATCHDOG_MINOR, | ||
182 | .name = "watchdog", | ||
183 | .fops = &ixp2000_wdt_fops, | ||
184 | }; | ||
185 | |||
186 | static int __init ixp2000_wdt_init(void) | ||
187 | { | ||
188 | if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { | ||
189 | pr_info("Unable to use IXP2000 watchdog due to IXP2800 erratum #25\n"); | ||
190 | return -EIO; | ||
191 | } | ||
192 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; | ||
193 | return misc_register(&ixp2000_wdt_miscdev); | ||
194 | } | ||
195 | |||
196 | static void __exit ixp2000_wdt_exit(void) | ||
197 | { | ||
198 | misc_deregister(&ixp2000_wdt_miscdev); | ||
199 | } | ||
200 | |||
201 | module_init(ixp2000_wdt_init); | ||
202 | module_exit(ixp2000_wdt_exit); | ||
203 | |||
204 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); | ||
205 | MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog"); | ||
206 | |||
207 | module_param(heartbeat, int, 0); | ||
208 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)"); | ||
209 | |||
210 | module_param(nowayout, bool, 0); | ||
211 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
212 | |||
213 | MODULE_LICENSE("GPL"); | ||
214 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
215 | |||
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index c891399bed6a..ee6900da8678 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c | |||
@@ -707,6 +707,7 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev, | |||
707 | goto err_out_disable_device; | 707 | goto err_out_disable_device; |
708 | } | 708 | } |
709 | 709 | ||
710 | spin_lock_init(&pcipcwd_private.io_lock); | ||
710 | pcipcwd_private.pdev = pdev; | 711 | pcipcwd_private.pdev = pdev; |
711 | pcipcwd_private.io_addr = pci_resource_start(pdev, 0); | 712 | pcipcwd_private.io_addr = pci_resource_start(pdev, 0); |
712 | 713 | ||
@@ -814,22 +815,7 @@ static struct pci_driver pcipcwd_driver = { | |||
814 | .remove = __devexit_p(pcipcwd_card_exit), | 815 | .remove = __devexit_p(pcipcwd_card_exit), |
815 | }; | 816 | }; |
816 | 817 | ||
817 | static int __init pcipcwd_init_module(void) | 818 | module_pci_driver(pcipcwd_driver); |
818 | { | ||
819 | spin_lock_init(&pcipcwd_private.io_lock); | ||
820 | |||
821 | return pci_register_driver(&pcipcwd_driver); | ||
822 | } | ||
823 | |||
824 | static void __exit pcipcwd_cleanup_module(void) | ||
825 | { | ||
826 | pci_unregister_driver(&pcipcwd_driver); | ||
827 | |||
828 | pr_info("Watchdog Module Unloaded\n"); | ||
829 | } | ||
830 | |||
831 | module_init(pcipcwd_init_module); | ||
832 | module_exit(pcipcwd_cleanup_module); | ||
833 | 819 | ||
834 | MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); | 820 | MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); |
835 | MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); | 821 | MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); |
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 6b8432f61d05..87722e126058 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | #include <linux/of.h> | ||
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | 37 | ||
37 | /* WatchDog Timer - Chapter 23 Page 207 */ | 38 | /* WatchDog Timer - Chapter 23 Page 207 */ |
@@ -201,10 +202,19 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev) | |||
201 | return 0; | 202 | return 0; |
202 | } | 203 | } |
203 | 204 | ||
205 | #ifdef CONFIG_OF | ||
206 | static const struct of_device_id pnx4008_wdt_match[] = { | ||
207 | { .compatible = "nxp,pnx4008-wdt" }, | ||
208 | { } | ||
209 | }; | ||
210 | MODULE_DEVICE_TABLE(of, pnx4008_wdt_match); | ||
211 | #endif | ||
212 | |||
204 | static struct platform_driver platform_wdt_driver = { | 213 | static struct platform_driver platform_wdt_driver = { |
205 | .driver = { | 214 | .driver = { |
206 | .name = "pnx4008-watchdog", | 215 | .name = "pnx4008-watchdog", |
207 | .owner = THIS_MODULE, | 216 | .owner = THIS_MODULE, |
217 | .of_match_table = of_match_ptr(pnx4008_wdt_match), | ||
208 | }, | 218 | }, |
209 | .probe = pnx4008_wdt_probe, | 219 | .probe = pnx4008_wdt_probe, |
210 | .remove = __devexit_p(pnx4008_wdt_remove), | 220 | .remove = __devexit_p(pnx4008_wdt_remove), |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 04e5a6de47d7..200ece5e2a22 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/cpufreq.h> | 40 | #include <linux/cpufreq.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/err.h> | 42 | #include <linux/err.h> |
43 | #include <linux/of.h> | ||
43 | 44 | ||
44 | #include <mach/map.h> | 45 | #include <mach/map.h> |
45 | 46 | ||
@@ -201,7 +202,7 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou | |||
201 | writel(count, wdt_base + S3C2410_WTDAT); | 202 | writel(count, wdt_base + S3C2410_WTDAT); |
202 | writel(wtcon, wdt_base + S3C2410_WTCON); | 203 | writel(wtcon, wdt_base + S3C2410_WTCON); |
203 | 204 | ||
204 | wdd->timeout = timeout; | 205 | wdd->timeout = (count * divisor) / freq; |
205 | 206 | ||
206 | return 0; | 207 | return 0; |
207 | } | 208 | } |
@@ -503,8 +504,6 @@ static const struct of_device_id s3c2410_wdt_match[] = { | |||
503 | {}, | 504 | {}, |
504 | }; | 505 | }; |
505 | MODULE_DEVICE_TABLE(of, s3c2410_wdt_match); | 506 | MODULE_DEVICE_TABLE(of, s3c2410_wdt_match); |
506 | #else | ||
507 | #define s3c2410_wdt_match NULL | ||
508 | #endif | 507 | #endif |
509 | 508 | ||
510 | static struct platform_driver s3c2410wdt_driver = { | 509 | static struct platform_driver s3c2410wdt_driver = { |
@@ -516,7 +515,7 @@ static struct platform_driver s3c2410wdt_driver = { | |||
516 | .driver = { | 515 | .driver = { |
517 | .owner = THIS_MODULE, | 516 | .owner = THIS_MODULE, |
518 | .name = "s3c2410-wdt", | 517 | .name = "s3c2410-wdt", |
519 | .of_match_table = s3c2410_wdt_match, | 518 | .of_match_table = of_match_ptr(s3c2410_wdt_match), |
520 | }, | 519 | }, |
521 | }; | 520 | }; |
522 | 521 | ||
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index bd86f32d63ab..f8477002b728 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #define DRV_NAME "sch311x_wdt" | 41 | #define DRV_NAME "sch311x_wdt" |
42 | 42 | ||
43 | /* Runtime registers */ | 43 | /* Runtime registers */ |
44 | #define RESGEN 0x1d | ||
45 | #define GP60 0x47 | 44 | #define GP60 0x47 |
46 | #define WDT_TIME_OUT 0x65 | 45 | #define WDT_TIME_OUT 0x65 |
47 | #define WDT_VAL 0x66 | 46 | #define WDT_VAL 0x66 |
@@ -69,10 +68,6 @@ static unsigned short force_id; | |||
69 | module_param(force_id, ushort, 0); | 68 | module_param(force_id, ushort, 0); |
70 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 69 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
71 | 70 | ||
72 | static unsigned short therm_trip; | ||
73 | module_param(therm_trip, ushort, 0); | ||
74 | MODULE_PARM_DESC(therm_trip, "Should a ThermTrip trigger the reset generator"); | ||
75 | |||
76 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | 71 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ |
77 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 72 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
78 | module_param(timeout, int, 0); | 73 | module_param(timeout, int, 0); |
@@ -358,26 +353,16 @@ static struct miscdevice sch311x_wdt_miscdev = { | |||
358 | static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | 353 | static int __devinit sch311x_wdt_probe(struct platform_device *pdev) |
359 | { | 354 | { |
360 | struct device *dev = &pdev->dev; | 355 | struct device *dev = &pdev->dev; |
361 | unsigned char val; | ||
362 | int err; | 356 | int err; |
363 | 357 | ||
364 | spin_lock_init(&sch311x_wdt_data.io_lock); | 358 | spin_lock_init(&sch311x_wdt_data.io_lock); |
365 | 359 | ||
366 | if (!request_region(sch311x_wdt_data.runtime_reg + RESGEN, 1, | ||
367 | DRV_NAME)) { | ||
368 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", | ||
369 | sch311x_wdt_data.runtime_reg + RESGEN, | ||
370 | sch311x_wdt_data.runtime_reg + RESGEN); | ||
371 | err = -EBUSY; | ||
372 | goto exit; | ||
373 | } | ||
374 | |||
375 | if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) { | 360 | if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) { |
376 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", | 361 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", |
377 | sch311x_wdt_data.runtime_reg + GP60, | 362 | sch311x_wdt_data.runtime_reg + GP60, |
378 | sch311x_wdt_data.runtime_reg + GP60); | 363 | sch311x_wdt_data.runtime_reg + GP60); |
379 | err = -EBUSY; | 364 | err = -EBUSY; |
380 | goto exit_release_region; | 365 | goto exit; |
381 | } | 366 | } |
382 | 367 | ||
383 | if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4, | 368 | if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4, |
@@ -386,7 +371,7 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | |||
386 | sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, | 371 | sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, |
387 | sch311x_wdt_data.runtime_reg + WDT_CTRL); | 372 | sch311x_wdt_data.runtime_reg + WDT_CTRL); |
388 | err = -EBUSY; | 373 | err = -EBUSY; |
389 | goto exit_release_region2; | 374 | goto exit_release_region; |
390 | } | 375 | } |
391 | 376 | ||
392 | /* Make sure that the watchdog is not running */ | 377 | /* Make sure that the watchdog is not running */ |
@@ -414,24 +399,13 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | |||
414 | /* Get status at boot */ | 399 | /* Get status at boot */ |
415 | sch311x_wdt_get_status(&sch311x_wdt_data.boot_status); | 400 | sch311x_wdt_get_status(&sch311x_wdt_data.boot_status); |
416 | 401 | ||
417 | /* enable watchdog */ | ||
418 | /* -- Reset Generator -- | ||
419 | * Bit 0 Enable Watchdog Timer Generation: 0* = Enabled, 1 = Disabled | ||
420 | * Bit 1 Thermtrip Source Select: O* = No Source, 1 = Source | ||
421 | * Bit 2 WDT2_CTL: WDT input bit | ||
422 | * Bit 3-7 Reserved | ||
423 | */ | ||
424 | outb(0, sch311x_wdt_data.runtime_reg + RESGEN); | ||
425 | val = therm_trip ? 0x06 : 0x04; | ||
426 | outb(val, sch311x_wdt_data.runtime_reg + RESGEN); | ||
427 | |||
428 | sch311x_wdt_miscdev.parent = dev; | 402 | sch311x_wdt_miscdev.parent = dev; |
429 | 403 | ||
430 | err = misc_register(&sch311x_wdt_miscdev); | 404 | err = misc_register(&sch311x_wdt_miscdev); |
431 | if (err != 0) { | 405 | if (err != 0) { |
432 | dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", | 406 | dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", |
433 | WATCHDOG_MINOR, err); | 407 | WATCHDOG_MINOR, err); |
434 | goto exit_release_region3; | 408 | goto exit_release_region2; |
435 | } | 409 | } |
436 | 410 | ||
437 | dev_info(dev, | 411 | dev_info(dev, |
@@ -440,12 +414,10 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | |||
440 | 414 | ||
441 | return 0; | 415 | return 0; |
442 | 416 | ||
443 | exit_release_region3: | ||
444 | release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); | ||
445 | exit_release_region2: | 417 | exit_release_region2: |
446 | release_region(sch311x_wdt_data.runtime_reg + GP60, 1); | 418 | release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); |
447 | exit_release_region: | 419 | exit_release_region: |
448 | release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1); | 420 | release_region(sch311x_wdt_data.runtime_reg + GP60, 1); |
449 | sch311x_wdt_data.runtime_reg = 0; | 421 | sch311x_wdt_data.runtime_reg = 0; |
450 | exit: | 422 | exit: |
451 | return err; | 423 | return err; |
@@ -461,7 +433,6 @@ static int __devexit sch311x_wdt_remove(struct platform_device *pdev) | |||
461 | misc_deregister(&sch311x_wdt_miscdev); | 433 | misc_deregister(&sch311x_wdt_miscdev); |
462 | release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); | 434 | release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4); |
463 | release_region(sch311x_wdt_data.runtime_reg + GP60, 1); | 435 | release_region(sch311x_wdt_data.runtime_reg + GP60, 1); |
464 | release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1); | ||
465 | sch311x_wdt_data.runtime_reg = 0; | 436 | sch311x_wdt_data.runtime_reg = 0; |
466 | return 0; | 437 | return 0; |
467 | } | 438 | } |
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 93958a7763e6..e5b59bebcdb1 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Watchdog driver for integrated watchdog in the SuperH processors. | 4 | * Watchdog driver for integrated watchdog in the SuperH processors. |
5 | * | 5 | * |
6 | * Copyright (C) 2001 - 2010 Paul Mundt <lethal@linux-sh.org> | 6 | * Copyright (C) 2001 - 2012 Paul Mundt <lethal@linux-sh.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
@@ -25,16 +25,15 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/spinlock.h> | ||
28 | #include <linux/miscdevice.h> | 29 | #include <linux/miscdevice.h> |
29 | #include <linux/watchdog.h> | 30 | #include <linux/watchdog.h> |
30 | #include <linux/reboot.h> | 31 | #include <linux/pm_runtime.h> |
31 | #include <linux/notifier.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
34 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
35 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
36 | #include <linux/io.h> | 35 | #include <linux/io.h> |
37 | #include <linux/uaccess.h> | 36 | #include <linux/clk.h> |
38 | #include <asm/watchdog.h> | 37 | #include <asm/watchdog.h> |
39 | 38 | ||
40 | #define DRV_NAME "sh-wdt" | 39 | #define DRV_NAME "sh-wdt" |
@@ -69,10 +68,6 @@ | |||
69 | static int clock_division_ratio = WTCSR_CKS_4096; | 68 | static int clock_division_ratio = WTCSR_CKS_4096; |
70 | #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) | 69 | #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) |
71 | 70 | ||
72 | static const struct watchdog_info sh_wdt_info; | ||
73 | static struct platform_device *sh_wdt_dev; | ||
74 | static DEFINE_SPINLOCK(shwdt_lock); | ||
75 | |||
76 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 71 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
77 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 72 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
78 | static bool nowayout = WATCHDOG_NOWAYOUT; | 73 | static bool nowayout = WATCHDOG_NOWAYOUT; |
@@ -81,19 +76,22 @@ static unsigned long next_heartbeat; | |||
81 | struct sh_wdt { | 76 | struct sh_wdt { |
82 | void __iomem *base; | 77 | void __iomem *base; |
83 | struct device *dev; | 78 | struct device *dev; |
79 | struct clk *clk; | ||
80 | spinlock_t lock; | ||
84 | 81 | ||
85 | struct timer_list timer; | 82 | struct timer_list timer; |
86 | |||
87 | unsigned long enabled; | ||
88 | char expect_close; | ||
89 | }; | 83 | }; |
90 | 84 | ||
91 | static void sh_wdt_start(struct sh_wdt *wdt) | 85 | static int sh_wdt_start(struct watchdog_device *wdt_dev) |
92 | { | 86 | { |
87 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
93 | unsigned long flags; | 88 | unsigned long flags; |
94 | u8 csr; | 89 | u8 csr; |
95 | 90 | ||
96 | spin_lock_irqsave(&shwdt_lock, flags); | 91 | pm_runtime_get_sync(wdt->dev); |
92 | clk_enable(wdt->clk); | ||
93 | |||
94 | spin_lock_irqsave(&wdt->lock, flags); | ||
97 | 95 | ||
98 | next_heartbeat = jiffies + (heartbeat * HZ); | 96 | next_heartbeat = jiffies + (heartbeat * HZ); |
99 | mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); | 97 | mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); |
@@ -122,15 +120,18 @@ static void sh_wdt_start(struct sh_wdt *wdt) | |||
122 | csr &= ~RSTCSR_RSTS; | 120 | csr &= ~RSTCSR_RSTS; |
123 | sh_wdt_write_rstcsr(csr); | 121 | sh_wdt_write_rstcsr(csr); |
124 | #endif | 122 | #endif |
125 | spin_unlock_irqrestore(&shwdt_lock, flags); | 123 | spin_unlock_irqrestore(&wdt->lock, flags); |
124 | |||
125 | return 0; | ||
126 | } | 126 | } |
127 | 127 | ||
128 | static void sh_wdt_stop(struct sh_wdt *wdt) | 128 | static int sh_wdt_stop(struct watchdog_device *wdt_dev) |
129 | { | 129 | { |
130 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
130 | unsigned long flags; | 131 | unsigned long flags; |
131 | u8 csr; | 132 | u8 csr; |
132 | 133 | ||
133 | spin_lock_irqsave(&shwdt_lock, flags); | 134 | spin_lock_irqsave(&wdt->lock, flags); |
134 | 135 | ||
135 | del_timer(&wdt->timer); | 136 | del_timer(&wdt->timer); |
136 | 137 | ||
@@ -138,28 +139,39 @@ static void sh_wdt_stop(struct sh_wdt *wdt) | |||
138 | csr &= ~WTCSR_TME; | 139 | csr &= ~WTCSR_TME; |
139 | sh_wdt_write_csr(csr); | 140 | sh_wdt_write_csr(csr); |
140 | 141 | ||
141 | spin_unlock_irqrestore(&shwdt_lock, flags); | 142 | spin_unlock_irqrestore(&wdt->lock, flags); |
143 | |||
144 | clk_disable(wdt->clk); | ||
145 | pm_runtime_put_sync(wdt->dev); | ||
146 | |||
147 | return 0; | ||
142 | } | 148 | } |
143 | 149 | ||
144 | static inline void sh_wdt_keepalive(struct sh_wdt *wdt) | 150 | static int sh_wdt_keepalive(struct watchdog_device *wdt_dev) |
145 | { | 151 | { |
152 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
146 | unsigned long flags; | 153 | unsigned long flags; |
147 | 154 | ||
148 | spin_lock_irqsave(&shwdt_lock, flags); | 155 | spin_lock_irqsave(&wdt->lock, flags); |
149 | next_heartbeat = jiffies + (heartbeat * HZ); | 156 | next_heartbeat = jiffies + (heartbeat * HZ); |
150 | spin_unlock_irqrestore(&shwdt_lock, flags); | 157 | spin_unlock_irqrestore(&wdt->lock, flags); |
158 | |||
159 | return 0; | ||
151 | } | 160 | } |
152 | 161 | ||
153 | static int sh_wdt_set_heartbeat(int t) | 162 | static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t) |
154 | { | 163 | { |
164 | struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev); | ||
155 | unsigned long flags; | 165 | unsigned long flags; |
156 | 166 | ||
157 | if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ | 167 | if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ |
158 | return -EINVAL; | 168 | return -EINVAL; |
159 | 169 | ||
160 | spin_lock_irqsave(&shwdt_lock, flags); | 170 | spin_lock_irqsave(&wdt->lock, flags); |
161 | heartbeat = t; | 171 | heartbeat = t; |
162 | spin_unlock_irqrestore(&shwdt_lock, flags); | 172 | wdt_dev->timeout = t; |
173 | spin_unlock_irqrestore(&wdt->lock, flags); | ||
174 | |||
163 | return 0; | 175 | return 0; |
164 | } | 176 | } |
165 | 177 | ||
@@ -168,7 +180,7 @@ static void sh_wdt_ping(unsigned long data) | |||
168 | struct sh_wdt *wdt = (struct sh_wdt *)data; | 180 | struct sh_wdt *wdt = (struct sh_wdt *)data; |
169 | unsigned long flags; | 181 | unsigned long flags; |
170 | 182 | ||
171 | spin_lock_irqsave(&shwdt_lock, flags); | 183 | spin_lock_irqsave(&wdt->lock, flags); |
172 | if (time_before(jiffies, next_heartbeat)) { | 184 | if (time_before(jiffies, next_heartbeat)) { |
173 | u8 csr; | 185 | u8 csr; |
174 | 186 | ||
@@ -182,137 +194,9 @@ static void sh_wdt_ping(unsigned long data) | |||
182 | } else | 194 | } else |
183 | dev_warn(wdt->dev, "Heartbeat lost! Will not ping " | 195 | dev_warn(wdt->dev, "Heartbeat lost! Will not ping " |
184 | "the watchdog\n"); | 196 | "the watchdog\n"); |
185 | spin_unlock_irqrestore(&shwdt_lock, flags); | 197 | spin_unlock_irqrestore(&wdt->lock, flags); |
186 | } | ||
187 | |||
188 | static int sh_wdt_open(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); | ||
191 | |||
192 | if (test_and_set_bit(0, &wdt->enabled)) | ||
193 | return -EBUSY; | ||
194 | if (nowayout) | ||
195 | __module_get(THIS_MODULE); | ||
196 | |||
197 | file->private_data = wdt; | ||
198 | |||
199 | sh_wdt_start(wdt); | ||
200 | |||
201 | return nonseekable_open(inode, file); | ||
202 | } | ||
203 | |||
204 | static int sh_wdt_close(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | struct sh_wdt *wdt = file->private_data; | ||
207 | |||
208 | if (wdt->expect_close == 42) { | ||
209 | sh_wdt_stop(wdt); | ||
210 | } else { | ||
211 | dev_crit(wdt->dev, "Unexpected close, not " | ||
212 | "stopping watchdog!\n"); | ||
213 | sh_wdt_keepalive(wdt); | ||
214 | } | ||
215 | |||
216 | clear_bit(0, &wdt->enabled); | ||
217 | wdt->expect_close = 0; | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static ssize_t sh_wdt_write(struct file *file, const char *buf, | ||
223 | size_t count, loff_t *ppos) | ||
224 | { | ||
225 | struct sh_wdt *wdt = file->private_data; | ||
226 | |||
227 | if (count) { | ||
228 | if (!nowayout) { | ||
229 | size_t i; | ||
230 | |||
231 | wdt->expect_close = 0; | ||
232 | |||
233 | for (i = 0; i != count; i++) { | ||
234 | char c; | ||
235 | if (get_user(c, buf + i)) | ||
236 | return -EFAULT; | ||
237 | if (c == 'V') | ||
238 | wdt->expect_close = 42; | ||
239 | } | ||
240 | } | ||
241 | sh_wdt_keepalive(wdt); | ||
242 | } | ||
243 | |||
244 | return count; | ||
245 | } | 198 | } |
246 | 199 | ||
247 | static long sh_wdt_ioctl(struct file *file, unsigned int cmd, | ||
248 | unsigned long arg) | ||
249 | { | ||
250 | struct sh_wdt *wdt = file->private_data; | ||
251 | int new_heartbeat; | ||
252 | int options, retval = -EINVAL; | ||
253 | |||
254 | switch (cmd) { | ||
255 | case WDIOC_GETSUPPORT: | ||
256 | return copy_to_user((struct watchdog_info *)arg, | ||
257 | &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0; | ||
258 | case WDIOC_GETSTATUS: | ||
259 | case WDIOC_GETBOOTSTATUS: | ||
260 | return put_user(0, (int *)arg); | ||
261 | case WDIOC_SETOPTIONS: | ||
262 | if (get_user(options, (int *)arg)) | ||
263 | return -EFAULT; | ||
264 | |||
265 | if (options & WDIOS_DISABLECARD) { | ||
266 | sh_wdt_stop(wdt); | ||
267 | retval = 0; | ||
268 | } | ||
269 | |||
270 | if (options & WDIOS_ENABLECARD) { | ||
271 | sh_wdt_start(wdt); | ||
272 | retval = 0; | ||
273 | } | ||
274 | |||
275 | return retval; | ||
276 | case WDIOC_KEEPALIVE: | ||
277 | sh_wdt_keepalive(wdt); | ||
278 | return 0; | ||
279 | case WDIOC_SETTIMEOUT: | ||
280 | if (get_user(new_heartbeat, (int *)arg)) | ||
281 | return -EFAULT; | ||
282 | |||
283 | if (sh_wdt_set_heartbeat(new_heartbeat)) | ||
284 | return -EINVAL; | ||
285 | |||
286 | sh_wdt_keepalive(wdt); | ||
287 | /* Fall */ | ||
288 | case WDIOC_GETTIMEOUT: | ||
289 | return put_user(heartbeat, (int *)arg); | ||
290 | default: | ||
291 | return -ENOTTY; | ||
292 | } | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int sh_wdt_notify_sys(struct notifier_block *this, | ||
297 | unsigned long code, void *unused) | ||
298 | { | ||
299 | struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); | ||
300 | |||
301 | if (code == SYS_DOWN || code == SYS_HALT) | ||
302 | sh_wdt_stop(wdt); | ||
303 | |||
304 | return NOTIFY_DONE; | ||
305 | } | ||
306 | |||
307 | static const struct file_operations sh_wdt_fops = { | ||
308 | .owner = THIS_MODULE, | ||
309 | .llseek = no_llseek, | ||
310 | .write = sh_wdt_write, | ||
311 | .unlocked_ioctl = sh_wdt_ioctl, | ||
312 | .open = sh_wdt_open, | ||
313 | .release = sh_wdt_close, | ||
314 | }; | ||
315 | |||
316 | static const struct watchdog_info sh_wdt_info = { | 200 | static const struct watchdog_info sh_wdt_info = { |
317 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | 201 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
318 | WDIOF_MAGICCLOSE, | 202 | WDIOF_MAGICCLOSE, |
@@ -320,14 +204,17 @@ static const struct watchdog_info sh_wdt_info = { | |||
320 | .identity = "SH WDT", | 204 | .identity = "SH WDT", |
321 | }; | 205 | }; |
322 | 206 | ||
323 | static struct notifier_block sh_wdt_notifier = { | 207 | static const struct watchdog_ops sh_wdt_ops = { |
324 | .notifier_call = sh_wdt_notify_sys, | 208 | .owner = THIS_MODULE, |
209 | .start = sh_wdt_start, | ||
210 | .stop = sh_wdt_stop, | ||
211 | .ping = sh_wdt_keepalive, | ||
212 | .set_timeout = sh_wdt_set_heartbeat, | ||
325 | }; | 213 | }; |
326 | 214 | ||
327 | static struct miscdevice sh_wdt_miscdev = { | 215 | static struct watchdog_device sh_wdt_dev = { |
328 | .minor = WATCHDOG_MINOR, | 216 | .info = &sh_wdt_info, |
329 | .name = "watchdog", | 217 | .ops = &sh_wdt_ops, |
330 | .fops = &sh_wdt_fops, | ||
331 | }; | 218 | }; |
332 | 219 | ||
333 | static int __devinit sh_wdt_probe(struct platform_device *pdev) | 220 | static int __devinit sh_wdt_probe(struct platform_device *pdev) |
@@ -347,39 +234,49 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev) | |||
347 | if (unlikely(!res)) | 234 | if (unlikely(!res)) |
348 | return -EINVAL; | 235 | return -EINVAL; |
349 | 236 | ||
350 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
351 | resource_size(res), DRV_NAME)) | ||
352 | return -EBUSY; | ||
353 | |||
354 | wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); | 237 | wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); |
355 | if (unlikely(!wdt)) { | 238 | if (unlikely(!wdt)) |
356 | rc = -ENOMEM; | 239 | return -ENOMEM; |
357 | goto out_release; | ||
358 | } | ||
359 | 240 | ||
360 | wdt->dev = &pdev->dev; | 241 | wdt->dev = &pdev->dev; |
361 | 242 | ||
362 | wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | 243 | wdt->clk = clk_get(&pdev->dev, NULL); |
244 | if (IS_ERR(wdt->clk)) { | ||
245 | /* | ||
246 | * Clock framework support is optional, continue on | ||
247 | * anyways if we don't find a matching clock. | ||
248 | */ | ||
249 | wdt->clk = NULL; | ||
250 | } | ||
251 | |||
252 | wdt->base = devm_request_and_ioremap(wdt->dev, res); | ||
363 | if (unlikely(!wdt->base)) { | 253 | if (unlikely(!wdt->base)) { |
364 | rc = -ENXIO; | 254 | rc = -EADDRNOTAVAIL; |
365 | goto out_err; | 255 | goto err; |
366 | } | 256 | } |
367 | 257 | ||
368 | rc = register_reboot_notifier(&sh_wdt_notifier); | 258 | watchdog_set_nowayout(&sh_wdt_dev, nowayout); |
259 | watchdog_set_drvdata(&sh_wdt_dev, wdt); | ||
260 | |||
261 | spin_lock_init(&wdt->lock); | ||
262 | |||
263 | rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat); | ||
369 | if (unlikely(rc)) { | 264 | if (unlikely(rc)) { |
370 | dev_err(&pdev->dev, | 265 | /* Default timeout if invalid */ |
371 | "Can't register reboot notifier (err=%d)\n", rc); | 266 | sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT); |
372 | goto out_unmap; | 267 | |
268 | dev_warn(&pdev->dev, | ||
269 | "heartbeat value must be 1<=x<=3600, using %d\n", | ||
270 | sh_wdt_dev.timeout); | ||
373 | } | 271 | } |
374 | 272 | ||
375 | sh_wdt_miscdev.parent = wdt->dev; | 273 | dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n", |
274 | sh_wdt_dev.timeout, nowayout); | ||
376 | 275 | ||
377 | rc = misc_register(&sh_wdt_miscdev); | 276 | rc = watchdog_register_device(&sh_wdt_dev); |
378 | if (unlikely(rc)) { | 277 | if (unlikely(rc)) { |
379 | dev_err(&pdev->dev, | 278 | dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); |
380 | "Can't register miscdev on minor=%d (err=%d)\n", | 279 | goto err; |
381 | sh_wdt_miscdev.minor, rc); | ||
382 | goto out_unreg; | ||
383 | } | 280 | } |
384 | 281 | ||
385 | init_timer(&wdt->timer); | 282 | init_timer(&wdt->timer); |
@@ -388,20 +285,15 @@ static int __devinit sh_wdt_probe(struct platform_device *pdev) | |||
388 | wdt->timer.expires = next_ping_period(clock_division_ratio); | 285 | wdt->timer.expires = next_ping_period(clock_division_ratio); |
389 | 286 | ||
390 | platform_set_drvdata(pdev, wdt); | 287 | platform_set_drvdata(pdev, wdt); |
391 | sh_wdt_dev = pdev; | ||
392 | 288 | ||
393 | dev_info(&pdev->dev, "initialized.\n"); | 289 | dev_info(&pdev->dev, "initialized.\n"); |
394 | 290 | ||
291 | pm_runtime_enable(&pdev->dev); | ||
292 | |||
395 | return 0; | 293 | return 0; |
396 | 294 | ||
397 | out_unreg: | 295 | err: |
398 | unregister_reboot_notifier(&sh_wdt_notifier); | 296 | clk_put(wdt->clk); |
399 | out_unmap: | ||
400 | devm_iounmap(&pdev->dev, wdt->base); | ||
401 | out_err: | ||
402 | devm_kfree(&pdev->dev, wdt); | ||
403 | out_release: | ||
404 | devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); | ||
405 | 297 | ||
406 | return rc; | 298 | return rc; |
407 | } | 299 | } |
@@ -409,36 +301,35 @@ out_release: | |||
409 | static int __devexit sh_wdt_remove(struct platform_device *pdev) | 301 | static int __devexit sh_wdt_remove(struct platform_device *pdev) |
410 | { | 302 | { |
411 | struct sh_wdt *wdt = platform_get_drvdata(pdev); | 303 | struct sh_wdt *wdt = platform_get_drvdata(pdev); |
412 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
413 | 304 | ||
414 | platform_set_drvdata(pdev, NULL); | 305 | platform_set_drvdata(pdev, NULL); |
415 | 306 | ||
416 | misc_deregister(&sh_wdt_miscdev); | 307 | watchdog_unregister_device(&sh_wdt_dev); |
417 | 308 | ||
418 | sh_wdt_dev = NULL; | 309 | pm_runtime_disable(&pdev->dev); |
419 | 310 | clk_put(wdt->clk); | |
420 | unregister_reboot_notifier(&sh_wdt_notifier); | ||
421 | devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); | ||
422 | devm_iounmap(&pdev->dev, wdt->base); | ||
423 | devm_kfree(&pdev->dev, wdt); | ||
424 | 311 | ||
425 | return 0; | 312 | return 0; |
426 | } | 313 | } |
427 | 314 | ||
315 | static void sh_wdt_shutdown(struct platform_device *pdev) | ||
316 | { | ||
317 | sh_wdt_stop(&sh_wdt_dev); | ||
318 | } | ||
319 | |||
428 | static struct platform_driver sh_wdt_driver = { | 320 | static struct platform_driver sh_wdt_driver = { |
429 | .driver = { | 321 | .driver = { |
430 | .name = DRV_NAME, | 322 | .name = DRV_NAME, |
431 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
432 | }, | 324 | }, |
433 | 325 | ||
434 | .probe = sh_wdt_probe, | 326 | .probe = sh_wdt_probe, |
435 | .remove = __devexit_p(sh_wdt_remove), | 327 | .remove = __devexit_p(sh_wdt_remove), |
328 | .shutdown = sh_wdt_shutdown, | ||
436 | }; | 329 | }; |
437 | 330 | ||
438 | static int __init sh_wdt_init(void) | 331 | static int __init sh_wdt_init(void) |
439 | { | 332 | { |
440 | int rc; | ||
441 | |||
442 | if (unlikely(clock_division_ratio < 0x5 || | 333 | if (unlikely(clock_division_ratio < 0x5 || |
443 | clock_division_ratio > 0x7)) { | 334 | clock_division_ratio > 0x7)) { |
444 | clock_division_ratio = WTCSR_CKS_4096; | 335 | clock_division_ratio = WTCSR_CKS_4096; |
@@ -447,17 +338,6 @@ static int __init sh_wdt_init(void) | |||
447 | clock_division_ratio); | 338 | clock_division_ratio); |
448 | } | 339 | } |
449 | 340 | ||
450 | rc = sh_wdt_set_heartbeat(heartbeat); | ||
451 | if (unlikely(rc)) { | ||
452 | heartbeat = WATCHDOG_HEARTBEAT; | ||
453 | |||
454 | pr_info("heartbeat value must be 1<=x<=3600, using %d\n", | ||
455 | heartbeat); | ||
456 | } | ||
457 | |||
458 | pr_info("configured with heartbeat=%d sec (nowayout=%d)\n", | ||
459 | heartbeat, nowayout); | ||
460 | |||
461 | return platform_driver_register(&sh_wdt_driver); | 341 | return platform_driver_register(&sh_wdt_driver); |
462 | } | 342 | } |
463 | 343 | ||
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index 59108e48ada3..ae5e82cb83fa 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c | |||
@@ -313,7 +313,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) | |||
313 | tcobase_phys = val; | 313 | tcobase_phys = val; |
314 | 314 | ||
315 | tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); | 315 | tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); |
316 | if (tcobase == 0) { | 316 | if (!tcobase) { |
317 | pr_err("failed to get tcobase address\n"); | 317 | pr_err("failed to get tcobase address\n"); |
318 | goto unreg_mem_region; | 318 | goto unreg_mem_region; |
319 | } | 319 | } |
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 465e08273c97..5603e31afdab 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c | |||
@@ -202,6 +202,9 @@ static int __devinit wdt_probe(struct pci_dev *pdev, | |||
202 | goto err_out_release; | 202 | goto err_out_release; |
203 | } | 203 | } |
204 | 204 | ||
205 | if (timeout < 1 || timeout > WDT_TIMEOUT_MAX) | ||
206 | timeout = WDT_TIMEOUT; | ||
207 | |||
205 | wdt_dev.timeout = timeout; | 208 | wdt_dev.timeout = timeout; |
206 | watchdog_set_nowayout(&wdt_dev, nowayout); | 209 | watchdog_set_nowayout(&wdt_dev, nowayout); |
207 | if (readl(wdt_mem) & VIA_WDT_FIRED) | 210 | if (readl(wdt_mem) & VIA_WDT_FIRED) |
@@ -250,20 +253,7 @@ static struct pci_driver wdt_driver = { | |||
250 | .remove = __devexit_p(wdt_remove), | 253 | .remove = __devexit_p(wdt_remove), |
251 | }; | 254 | }; |
252 | 255 | ||
253 | static int __init wdt_init(void) | 256 | module_pci_driver(wdt_driver); |
254 | { | ||
255 | if (timeout < 1 || timeout > WDT_TIMEOUT_MAX) | ||
256 | timeout = WDT_TIMEOUT; | ||
257 | return pci_register_driver(&wdt_driver); | ||
258 | } | ||
259 | |||
260 | static void __exit wdt_exit(void) | ||
261 | { | ||
262 | pci_unregister_driver(&wdt_driver); | ||
263 | } | ||
264 | |||
265 | module_init(wdt_init); | ||
266 | module_exit(wdt_exit); | ||
267 | 257 | ||
268 | MODULE_AUTHOR("Marc Vertes"); | 258 | MODULE_AUTHOR("Marc Vertes"); |
269 | MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset"); | 259 | MODULE_DESCRIPTION("Driver for watchdog timer on VIA chipset"); |
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 1c888c7d4cce..e32654efdbb6 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c | |||
@@ -739,39 +739,7 @@ static struct pci_driver wdtpci_driver = { | |||
739 | .remove = __devexit_p(wdtpci_remove_one), | 739 | .remove = __devexit_p(wdtpci_remove_one), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | 742 | module_pci_driver(wdtpci_driver); | |
743 | /** | ||
744 | * wdtpci_cleanup: | ||
745 | * | ||
746 | * Unload the watchdog. You cannot do this with any file handles open. | ||
747 | * If your watchdog is set to continue ticking on close and you unload | ||
748 | * it, well it keeps ticking. We won't get the interrupt but the board | ||
749 | * will not touch PC memory so all is fine. You just have to load a new | ||
750 | * module in xx seconds or reboot. | ||
751 | */ | ||
752 | |||
753 | static void __exit wdtpci_cleanup(void) | ||
754 | { | ||
755 | pci_unregister_driver(&wdtpci_driver); | ||
756 | } | ||
757 | |||
758 | |||
759 | /** | ||
760 | * wdtpci_init: | ||
761 | * | ||
762 | * Set up the WDT watchdog board. All we have to do is grab the | ||
763 | * resources we require and bitch if anyone beat us to them. | ||
764 | * The open() function will actually kick the board off. | ||
765 | */ | ||
766 | |||
767 | static int __init wdtpci_init(void) | ||
768 | { | ||
769 | return pci_register_driver(&wdtpci_driver); | ||
770 | } | ||
771 | |||
772 | |||
773 | module_init(wdtpci_init); | ||
774 | module_exit(wdtpci_cleanup); | ||
775 | 743 | ||
776 | MODULE_AUTHOR("JP Nollmann, Alan Cox"); | 744 | MODULE_AUTHOR("JP Nollmann, Alan Cox"); |
777 | MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards"); | 745 | MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards"); |
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index b1815c5ed7a7..87d66d236c3e 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c | |||
@@ -247,8 +247,9 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) | |||
247 | reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT; | 247 | reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT; |
248 | 248 | ||
249 | if (pdata->update_gpio) { | 249 | if (pdata->update_gpio) { |
250 | ret = gpio_request(pdata->update_gpio, | 250 | ret = gpio_request_one(pdata->update_gpio, |
251 | "Watchdog update"); | 251 | GPIOF_DIR_OUT | GPIOF_INIT_LOW, |
252 | "Watchdog update"); | ||
252 | if (ret < 0) { | 253 | if (ret < 0) { |
253 | dev_err(wm831x->dev, | 254 | dev_err(wm831x->dev, |
254 | "Failed to request update GPIO: %d\n", | 255 | "Failed to request update GPIO: %d\n", |
@@ -256,14 +257,6 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev) | |||
256 | goto err; | 257 | goto err; |
257 | } | 258 | } |
258 | 259 | ||
259 | ret = gpio_direction_output(pdata->update_gpio, 0); | ||
260 | if (ret != 0) { | ||
261 | dev_err(wm831x->dev, | ||
262 | "gpio_direction_output returned: %d\n", | ||
263 | ret); | ||
264 | goto err_gpio; | ||
265 | } | ||
266 | |||
267 | driver_data->update_gpio = pdata->update_gpio; | 260 | driver_data->update_gpio = pdata->update_gpio; |
268 | 261 | ||
269 | /* Make sure the watchdog takes hardware updates */ | 262 | /* Make sure the watchdog takes hardware updates */ |