diff options
Diffstat (limited to 'drivers/char/watchdog')
-rw-r--r-- | drivers/char/watchdog/Kconfig | 7 | ||||
-rw-r--r-- | drivers/char/watchdog/Makefile | 72 | ||||
-rw-r--r-- | drivers/char/watchdog/booke_wdt.c | 192 | ||||
-rw-r--r-- | drivers/char/watchdog/ixp2000_wdt.c | 2 | ||||
-rw-r--r-- | drivers/char/watchdog/ixp4xx_wdt.c | 2 | ||||
-rw-r--r-- | drivers/char/watchdog/s3c2410_wdt.c | 87 | ||||
-rw-r--r-- | drivers/char/watchdog/scx200_wdt.c | 2 | ||||
-rw-r--r-- | drivers/char/watchdog/softdog.c | 13 | ||||
-rw-r--r-- | drivers/char/watchdog/w83627hf_wdt.c | 6 |
9 files changed, 321 insertions, 62 deletions
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index b53e2e2b5aee..c3898afce3ae 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -346,6 +346,13 @@ config 8xx_WDT | |||
346 | tristate "MPC8xx Watchdog Timer" | 346 | tristate "MPC8xx Watchdog Timer" |
347 | depends on WATCHDOG && 8xx | 347 | depends on WATCHDOG && 8xx |
348 | 348 | ||
349 | config BOOKE_WDT | ||
350 | tristate "PowerPC Book-E Watchdog Timer" | ||
351 | depends on WATCHDOG && (BOOKE || 4xx) | ||
352 | ---help--- | ||
353 | Please see Documentation/watchdog/watchdog-api.txt for | ||
354 | more information. | ||
355 | |||
349 | # MIPS Architecture | 356 | # MIPS Architecture |
350 | 357 | ||
351 | config INDYDOG | 358 | config INDYDOG |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index c1838834ea7f..cfeac6f10137 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -2,42 +2,68 @@ | |||
2 | # Makefile for the WatchDog device drivers. | 2 | # Makefile for the WatchDog device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | # Only one watchdog can succeed. We probe the ISA/PCI/USB based | ||
6 | # watchdog-cards first, then the architecture specific watchdog | ||
7 | # drivers and then the architecture independant "softdog" driver. | ||
8 | # This means that if your ISA/PCI/USB card isn't detected that | ||
9 | # you can fall back to an architecture specific driver and if | ||
10 | # that also fails then you can fall back to the software watchdog | ||
11 | # to give you some cover. | ||
12 | |||
13 | # ISA-based Watchdog Cards | ||
5 | obj-$(CONFIG_PCWATCHDOG) += pcwd.o | 14 | obj-$(CONFIG_PCWATCHDOG) += pcwd.o |
6 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o | ||
7 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o | ||
8 | obj-$(CONFIG_IB700_WDT) += ib700wdt.o | ||
9 | obj-$(CONFIG_MIXCOMWD) += mixcomwd.o | 15 | obj-$(CONFIG_MIXCOMWD) += mixcomwd.o |
10 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | ||
11 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o | ||
12 | obj-$(CONFIG_WDT) += wdt.o | 16 | obj-$(CONFIG_WDT) += wdt.o |
17 | |||
18 | # PCI-based Watchdog Cards | ||
19 | obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o | ||
13 | obj-$(CONFIG_WDTPCI) += wdt_pci.o | 20 | obj-$(CONFIG_WDTPCI) += wdt_pci.o |
21 | |||
22 | # USB-based Watchdog Cards | ||
23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | ||
24 | |||
25 | # ARM Architecture | ||
14 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 26 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
15 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 27 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
16 | obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o | 28 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
17 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 29 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o |
18 | obj-$(CONFIG_SH_WDT) += shwdt.o | ||
19 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o | 30 | obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o |
20 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | 31 | obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o |
21 | obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o | 32 | |
22 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o | 33 | # X86 (i386 + ia64 + x86_64) Architecture |
23 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o | 34 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o |
24 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o | 35 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o |
25 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o | ||
26 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o | 36 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o |
27 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o | 37 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o |
38 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o | ||
39 | obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o | ||
40 | obj-$(CONFIG_IB700_WDT) += ib700wdt.o | ||
28 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o | 41 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o |
42 | obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o | ||
43 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o | ||
44 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | ||
45 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o | ||
29 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o | 46 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o |
30 | obj-$(CONFIG_INDYDOG) += indydog.o | 47 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o |
31 | obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o | 48 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o |
32 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | 49 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
33 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | 50 | |
34 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 51 | # PowerPC Architecture |
35 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 52 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
53 | |||
54 | # PPC64 Architecture | ||
36 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o | 55 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o |
56 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | ||
57 | |||
58 | # MIPS Architecture | ||
59 | obj-$(CONFIG_INDYDOG) += indydog.o | ||
60 | |||
61 | # S390 Architecture | ||
62 | |||
63 | # SUPERH Architecture | ||
64 | obj-$(CONFIG_SH_WDT) += shwdt.o | ||
37 | 65 | ||
38 | # Only one watchdog can succeed. We probe the hardware watchdog | 66 | # SPARC64 Architecture |
39 | # drivers first, then the softdog driver. This means if your hardware | ||
40 | # watchdog dies or is 'borrowed' for some reason the software watchdog | ||
41 | # still gives you some cover. | ||
42 | 67 | ||
68 | # Architecture Independant | ||
43 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o | 69 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o |
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c new file mode 100644 index 000000000000..abc30cca6645 --- /dev/null +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/booke_wdt.c | ||
3 | * | ||
4 | * Watchdog timer for PowerPC Book-E systems | ||
5 | * | ||
6 | * Author: Matthew McClintock | ||
7 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
8 | * | ||
9 | * Copyright 2005 Freescale Semiconductor Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/config.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/notifier.h> | ||
22 | #include <linux/watchdog.h> | ||
23 | |||
24 | #include <asm/reg_booke.h> | ||
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/system.h> | ||
27 | |||
28 | /* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot. | ||
29 | * Also, the wdt_period sets the watchdog timer period timeout. | ||
30 | * For E500 cpus the wdt_period sets which bit changing from 0->1 will | ||
31 | * trigger a watchog timeout. This watchdog timeout will occur 3 times, the | ||
32 | * first time nothing will happen, the second time a watchdog exception will | ||
33 | * occur, and the final time the board will reset. | ||
34 | */ | ||
35 | |||
36 | #ifdef CONFIG_FSL_BOOKE | ||
37 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ | ||
38 | #else | ||
39 | #define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ | ||
40 | #endif /* for timing information */ | ||
41 | |||
42 | u32 booke_wdt_enabled = 0; | ||
43 | u32 booke_wdt_period = WDT_PERIOD_DEFAULT; | ||
44 | |||
45 | #ifdef CONFIG_FSL_BOOKE | ||
46 | #define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15)) | ||
47 | #else | ||
48 | #define WDTP(x) (TCR_WP(x)) | ||
49 | #endif | ||
50 | |||
51 | /* | ||
52 | * booke_wdt_enable: | ||
53 | */ | ||
54 | static __inline__ void booke_wdt_enable(void) | ||
55 | { | ||
56 | u32 val; | ||
57 | |||
58 | val = mfspr(SPRN_TCR); | ||
59 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); | ||
60 | |||
61 | mtspr(SPRN_TCR, val); | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | * booke_wdt_ping: | ||
66 | */ | ||
67 | static __inline__ void booke_wdt_ping(void) | ||
68 | { | ||
69 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * booke_wdt_write: | ||
74 | */ | ||
75 | static ssize_t booke_wdt_write (struct file *file, const char *buf, | ||
76 | size_t count, loff_t *ppos) | ||
77 | { | ||
78 | booke_wdt_ping(); | ||
79 | return count; | ||
80 | } | ||
81 | |||
82 | static struct watchdog_info ident = { | ||
83 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
84 | .firmware_version = 0, | ||
85 | .identity = "PowerPC Book-E Watchdog", | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * booke_wdt_ioctl: | ||
90 | */ | ||
91 | static int booke_wdt_ioctl (struct inode *inode, struct file *file, | ||
92 | unsigned int cmd, unsigned long arg) | ||
93 | { | ||
94 | u32 tmp = 0; | ||
95 | |||
96 | switch (cmd) { | ||
97 | case WDIOC_GETSUPPORT: | ||
98 | if (copy_to_user ((struct watchdog_info *) arg, &ident, | ||
99 | sizeof(struct watchdog_info))) | ||
100 | return -EFAULT; | ||
101 | case WDIOC_GETSTATUS: | ||
102 | return put_user(ident.options, (u32 *) arg); | ||
103 | case WDIOC_GETBOOTSTATUS: | ||
104 | /* XXX: something is clearing TSR */ | ||
105 | tmp = mfspr(SPRN_TSR) & TSR_WRS(3); | ||
106 | /* returns 1 if last reset was caused by the WDT */ | ||
107 | return (tmp ? 1 : 0); | ||
108 | case WDIOC_KEEPALIVE: | ||
109 | booke_wdt_ping(); | ||
110 | return 0; | ||
111 | case WDIOC_SETTIMEOUT: | ||
112 | if (get_user(booke_wdt_period, (u32 *) arg)) | ||
113 | return -EFAULT; | ||
114 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period)); | ||
115 | return 0; | ||
116 | case WDIOC_GETTIMEOUT: | ||
117 | return put_user(booke_wdt_period, (u32 *) arg); | ||
118 | case WDIOC_SETOPTIONS: | ||
119 | if (get_user(tmp, (u32 *) arg)) | ||
120 | return -EINVAL; | ||
121 | if (tmp == WDIOS_ENABLECARD) { | ||
122 | booke_wdt_ping(); | ||
123 | break; | ||
124 | } else | ||
125 | return -EINVAL; | ||
126 | return 0; | ||
127 | default: | ||
128 | return -ENOIOCTLCMD; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | /* | ||
134 | * booke_wdt_open: | ||
135 | */ | ||
136 | static int booke_wdt_open (struct inode *inode, struct file *file) | ||
137 | { | ||
138 | if (booke_wdt_enabled == 0) { | ||
139 | booke_wdt_enabled = 1; | ||
140 | booke_wdt_enable(); | ||
141 | printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", | ||
142 | booke_wdt_period); | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static struct file_operations booke_wdt_fops = { | ||
149 | .owner = THIS_MODULE, | ||
150 | .llseek = no_llseek, | ||
151 | .write = booke_wdt_write, | ||
152 | .ioctl = booke_wdt_ioctl, | ||
153 | .open = booke_wdt_open, | ||
154 | }; | ||
155 | |||
156 | static struct miscdevice booke_wdt_miscdev = { | ||
157 | .minor = WATCHDOG_MINOR, | ||
158 | .name = "watchdog", | ||
159 | .fops = &booke_wdt_fops, | ||
160 | }; | ||
161 | |||
162 | static void __exit booke_wdt_exit(void) | ||
163 | { | ||
164 | misc_deregister(&booke_wdt_miscdev); | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * booke_wdt_init: | ||
169 | */ | ||
170 | static int __init booke_wdt_init(void) | ||
171 | { | ||
172 | int ret = 0; | ||
173 | |||
174 | printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); | ||
175 | ident.firmware_version = cpu_specs[0].pvr_value; | ||
176 | |||
177 | ret = misc_register(&booke_wdt_miscdev); | ||
178 | if (ret) { | ||
179 | printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n", | ||
180 | WATCHDOG_MINOR, ret); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | if (booke_wdt_enabled == 1) { | ||
185 | printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", | ||
186 | booke_wdt_period); | ||
187 | booke_wdt_enable(); | ||
188 | } | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | device_initcall(booke_wdt_init); | ||
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index e7640bc4904b..0cfb9b9c4a4b 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c | |||
@@ -182,7 +182,7 @@ static struct file_operations ixp2000_wdt_fops = | |||
182 | static struct miscdevice ixp2000_wdt_miscdev = | 182 | static struct miscdevice ixp2000_wdt_miscdev = |
183 | { | 183 | { |
184 | .minor = WATCHDOG_MINOR, | 184 | .minor = WATCHDOG_MINOR, |
185 | .name = "IXP2000 Watchdog", | 185 | .name = "watchdog", |
186 | .fops = &ixp2000_wdt_fops, | 186 | .fops = &ixp2000_wdt_fops, |
187 | }; | 187 | }; |
188 | 188 | ||
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c index 8d916afbf4fa..b5be8b11104a 100644 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ b/drivers/char/watchdog/ixp4xx_wdt.c | |||
@@ -176,7 +176,7 @@ static struct file_operations ixp4xx_wdt_fops = | |||
176 | static struct miscdevice ixp4xx_wdt_miscdev = | 176 | static struct miscdevice ixp4xx_wdt_miscdev = |
177 | { | 177 | { |
178 | .minor = WATCHDOG_MINOR, | 178 | .minor = WATCHDOG_MINOR, |
179 | .name = "IXP4xx Watchdog", | 179 | .name = "watchdog", |
180 | .fops = &ixp4xx_wdt_fops, | 180 | .fops = &ixp4xx_wdt_fops, |
181 | }; | 181 | }; |
182 | 182 | ||
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index f85ac898a49a..8b292bf343c4 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -27,7 +27,10 @@ | |||
27 | * Fixed tmr_count / wdt_count confusion | 27 | * Fixed tmr_count / wdt_count confusion |
28 | * Added configurable debug | 28 | * Added configurable debug |
29 | * | 29 | * |
30 | * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code | 30 | * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code |
31 | * | ||
32 | * 25-Jan-2005 DA Added suspend/resume support | ||
33 | * Replaced reboot notifier with .shutdown method | ||
31 | * | 34 | * |
32 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 35 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
33 | */ | 36 | */ |
@@ -40,8 +43,6 @@ | |||
40 | #include <linux/miscdevice.h> | 43 | #include <linux/miscdevice.h> |
41 | #include <linux/watchdog.h> | 44 | #include <linux/watchdog.h> |
42 | #include <linux/fs.h> | 45 | #include <linux/fs.h> |
43 | #include <linux/notifier.h> | ||
44 | #include <linux/reboot.h> | ||
45 | #include <linux/init.h> | 46 | #include <linux/init.h> |
46 | #include <linux/device.h> | 47 | #include <linux/device.h> |
47 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
@@ -317,20 +318,6 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, | |||
317 | } | 318 | } |
318 | } | 319 | } |
319 | 320 | ||
320 | /* | ||
321 | * Notifier for system down | ||
322 | */ | ||
323 | |||
324 | static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
325 | void *unused) | ||
326 | { | ||
327 | if(code==SYS_DOWN || code==SYS_HALT) { | ||
328 | /* Turn the WDT off */ | ||
329 | s3c2410wdt_stop(); | ||
330 | } | ||
331 | return NOTIFY_DONE; | ||
332 | } | ||
333 | |||
334 | /* kernel interface */ | 321 | /* kernel interface */ |
335 | 322 | ||
336 | static struct file_operations s3c2410wdt_fops = { | 323 | static struct file_operations s3c2410wdt_fops = { |
@@ -348,10 +335,6 @@ static struct miscdevice s3c2410wdt_miscdev = { | |||
348 | .fops = &s3c2410wdt_fops, | 335 | .fops = &s3c2410wdt_fops, |
349 | }; | 336 | }; |
350 | 337 | ||
351 | static struct notifier_block s3c2410wdt_notifier = { | ||
352 | .notifier_call = s3c2410wdt_notify_sys, | ||
353 | }; | ||
354 | |||
355 | /* interrupt handler code */ | 338 | /* interrupt handler code */ |
356 | 339 | ||
357 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param, | 340 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param, |
@@ -432,18 +415,10 @@ static int s3c2410wdt_probe(struct device *dev) | |||
432 | } | 415 | } |
433 | } | 416 | } |
434 | 417 | ||
435 | ret = register_reboot_notifier(&s3c2410wdt_notifier); | ||
436 | if (ret) { | ||
437 | printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n", | ||
438 | ret); | ||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | ret = misc_register(&s3c2410wdt_miscdev); | 418 | ret = misc_register(&s3c2410wdt_miscdev); |
443 | if (ret) { | 419 | if (ret) { |
444 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", | 420 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", |
445 | WATCHDOG_MINOR, ret); | 421 | WATCHDOG_MINOR, ret); |
446 | unregister_reboot_notifier(&s3c2410wdt_notifier); | ||
447 | return ret; | 422 | return ret; |
448 | } | 423 | } |
449 | 424 | ||
@@ -479,15 +454,63 @@ static int s3c2410wdt_remove(struct device *dev) | |||
479 | return 0; | 454 | return 0; |
480 | } | 455 | } |
481 | 456 | ||
457 | static void s3c2410wdt_shutdown(struct device *dev) | ||
458 | { | ||
459 | s3c2410wdt_stop(); | ||
460 | } | ||
461 | |||
462 | #ifdef CONFIG_PM | ||
463 | |||
464 | static unsigned long wtcon_save; | ||
465 | static unsigned long wtdat_save; | ||
466 | |||
467 | static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level) | ||
468 | { | ||
469 | if (level == SUSPEND_POWER_DOWN) { | ||
470 | /* Save watchdog state, and turn it off. */ | ||
471 | wtcon_save = readl(wdt_base + S3C2410_WTCON); | ||
472 | wtdat_save = readl(wdt_base + S3C2410_WTDAT); | ||
473 | |||
474 | /* Note that WTCNT doesn't need to be saved. */ | ||
475 | s3c2410wdt_stop(); | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int s3c2410wdt_resume(struct device *dev, u32 level) | ||
482 | { | ||
483 | if (level == RESUME_POWER_ON) { | ||
484 | /* Restore watchdog state. */ | ||
485 | |||
486 | writel(wtdat_save, wdt_base + S3C2410_WTDAT); | ||
487 | writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ | ||
488 | writel(wtcon_save, wdt_base + S3C2410_WTCON); | ||
489 | |||
490 | printk(KERN_INFO PFX "watchdog %sabled\n", | ||
491 | (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); | ||
492 | } | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | #else | ||
498 | #define s3c2410wdt_suspend NULL | ||
499 | #define s3c2410wdt_resume NULL | ||
500 | #endif /* CONFIG_PM */ | ||
501 | |||
502 | |||
482 | static struct device_driver s3c2410wdt_driver = { | 503 | static struct device_driver s3c2410wdt_driver = { |
483 | .name = "s3c2410-wdt", | 504 | .name = "s3c2410-wdt", |
484 | .bus = &platform_bus_type, | 505 | .bus = &platform_bus_type, |
485 | .probe = s3c2410wdt_probe, | 506 | .probe = s3c2410wdt_probe, |
486 | .remove = s3c2410wdt_remove, | 507 | .remove = s3c2410wdt_remove, |
508 | .shutdown = s3c2410wdt_shutdown, | ||
509 | .suspend = s3c2410wdt_suspend, | ||
510 | .resume = s3c2410wdt_resume, | ||
487 | }; | 511 | }; |
488 | 512 | ||
489 | 513 | ||
490 | |||
491 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | 514 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; |
492 | 515 | ||
493 | static int __init watchdog_init(void) | 516 | static int __init watchdog_init(void) |
@@ -499,13 +522,13 @@ static int __init watchdog_init(void) | |||
499 | static void __exit watchdog_exit(void) | 522 | static void __exit watchdog_exit(void) |
500 | { | 523 | { |
501 | driver_unregister(&s3c2410wdt_driver); | 524 | driver_unregister(&s3c2410wdt_driver); |
502 | unregister_reboot_notifier(&s3c2410wdt_notifier); | ||
503 | } | 525 | } |
504 | 526 | ||
505 | module_init(watchdog_init); | 527 | module_init(watchdog_init); |
506 | module_exit(watchdog_exit); | 528 | module_exit(watchdog_exit); |
507 | 529 | ||
508 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 530 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, " |
531 | "Dimitry Andric <dimitry.andric@tomtom.com>"); | ||
509 | MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver"); | 532 | MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver"); |
510 | MODULE_LICENSE("GPL"); | 533 | MODULE_LICENSE("GPL"); |
511 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 534 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index c4568569f3a8..b4a102a2d7e3 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c | |||
@@ -206,7 +206,7 @@ static struct file_operations scx200_wdt_fops = { | |||
206 | 206 | ||
207 | static struct miscdevice scx200_wdt_miscdev = { | 207 | static struct miscdevice scx200_wdt_miscdev = { |
208 | .minor = WATCHDOG_MINOR, | 208 | .minor = WATCHDOG_MINOR, |
209 | .name = NAME, | 209 | .name = "watchdog", |
210 | .fops = &scx200_wdt_fops, | 210 | .fops = &scx200_wdt_fops, |
211 | }; | 211 | }; |
212 | 212 | ||
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c index 4d7ed931f5c6..20e5eb8667f2 100644 --- a/drivers/char/watchdog/softdog.c +++ b/drivers/char/watchdog/softdog.c | |||
@@ -77,7 +77,7 @@ static void watchdog_fire(unsigned long); | |||
77 | 77 | ||
78 | static struct timer_list watchdog_ticktock = | 78 | static struct timer_list watchdog_ticktock = |
79 | TIMER_INITIALIZER(watchdog_fire, 0, 0); | 79 | TIMER_INITIALIZER(watchdog_fire, 0, 0); |
80 | static unsigned long timer_alive; | 80 | static unsigned long driver_open, orphan_timer; |
81 | static char expect_close; | 81 | static char expect_close; |
82 | 82 | ||
83 | 83 | ||
@@ -87,6 +87,9 @@ static char expect_close; | |||
87 | 87 | ||
88 | static void watchdog_fire(unsigned long data) | 88 | static void watchdog_fire(unsigned long data) |
89 | { | 89 | { |
90 | if (test_and_clear_bit(0, &orphan_timer)) | ||
91 | module_put(THIS_MODULE); | ||
92 | |||
90 | if (soft_noboot) | 93 | if (soft_noboot) |
91 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); | 94 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); |
92 | else | 95 | else |
@@ -128,9 +131,9 @@ static int softdog_set_heartbeat(int t) | |||
128 | 131 | ||
129 | static int softdog_open(struct inode *inode, struct file *file) | 132 | static int softdog_open(struct inode *inode, struct file *file) |
130 | { | 133 | { |
131 | if(test_and_set_bit(0, &timer_alive)) | 134 | if (test_and_set_bit(0, &driver_open)) |
132 | return -EBUSY; | 135 | return -EBUSY; |
133 | if (nowayout) | 136 | if (!test_and_clear_bit(0, &orphan_timer)) |
134 | __module_get(THIS_MODULE); | 137 | __module_get(THIS_MODULE); |
135 | /* | 138 | /* |
136 | * Activate timer | 139 | * Activate timer |
@@ -147,11 +150,13 @@ static int softdog_release(struct inode *inode, struct file *file) | |||
147 | */ | 150 | */ |
148 | if (expect_close == 42) { | 151 | if (expect_close == 42) { |
149 | softdog_stop(); | 152 | softdog_stop(); |
153 | module_put(THIS_MODULE); | ||
150 | } else { | 154 | } else { |
151 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 155 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); |
156 | set_bit(0, &orphan_timer); | ||
152 | softdog_keepalive(); | 157 | softdog_keepalive(); |
153 | } | 158 | } |
154 | clear_bit(0, &timer_alive); | 159 | clear_bit(0, &driver_open); |
155 | expect_close = 0; | 160 | expect_close = 0; |
156 | return 0; | 161 | return 0; |
157 | } | 162 | } |
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index 465e0fd0423d..b5d821015421 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c | |||
@@ -93,6 +93,12 @@ w83627hf_init(void) | |||
93 | 93 | ||
94 | w83627hf_select_wd_register(); | 94 | w83627hf_select_wd_register(); |
95 | 95 | ||
96 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ | ||
97 | t=inb_p(WDT_EFDR); /* read CRF6 */ | ||
98 | if (t != 0) { | ||
99 | printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); | ||
100 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ | ||
101 | } | ||
96 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ | 102 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ |
97 | t=inb_p(WDT_EFDR); /* read CRF5 */ | 103 | t=inb_p(WDT_EFDR); /* read CRF5 */ |
98 | t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ | 104 | t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ |