aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/watchdog/Kconfig117
-rw-r--r--drivers/char/watchdog/Makefile43
-rw-r--r--drivers/char/watchdog/bfin_wdt.c490
-rw-r--r--drivers/char/watchdog/booke_wdt.c2
-rw-r--r--drivers/char/watchdog/cpu5wdt.c4
-rw-r--r--drivers/char/watchdog/davinci_wdt.c281
-rw-r--r--drivers/char/watchdog/iTCO_wdt.c38
-rw-r--r--drivers/char/watchdog/machzwd.c1
-rw-r--r--drivers/char/watchdog/mixcomwd.c5
-rw-r--r--drivers/char/watchdog/mpc5200_wdt.c286
-rw-r--r--drivers/char/watchdog/mpc83xx_wdt.c3
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c2
-rw-r--r--drivers/char/watchdog/mtx-1_wdt.c1
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c218
-rw-r--r--drivers/char/watchdog/omap_wdt.c4
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c6
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c3
-rw-r--r--drivers/char/watchdog/sbc60xxwdt.c4
-rw-r--r--drivers/char/watchdog/sc1200wdt.c4
-rw-r--r--drivers/char/watchdog/sc520_wdt.c4
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c24
23 files changed, 1394 insertions, 148 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index a9e4c5f922a0..f0878b2ec55e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -66,6 +66,7 @@ obj-y += i2c/
66obj-$(CONFIG_W1) += w1/ 66obj-$(CONFIG_W1) += w1/
67obj-$(CONFIG_POWER_SUPPLY) += power/ 67obj-$(CONFIG_POWER_SUPPLY) += power/
68obj-$(CONFIG_HWMON) += hwmon/ 68obj-$(CONFIG_HWMON) += hwmon/
69obj-$(CONFIG_WATCHDOG) += char/watchdog/
69obj-$(CONFIG_PHONE) += telephony/ 70obj-$(CONFIG_PHONE) += telephony/
70obj-$(CONFIG_MD) += md/ 71obj-$(CONFIG_MD) += md/
71obj-$(CONFIG_BT) += bluetooth/ 72obj-$(CONFIG_BT) += bluetooth/
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 23b26b87cc32..d68ddbe70f73 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -97,7 +97,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
97obj-$(CONFIG_GPIO_TB0219) += tb0219.o 97obj-$(CONFIG_GPIO_TB0219) += tb0219.o
98obj-$(CONFIG_TELCLOCK) += tlclk.o 98obj-$(CONFIG_TELCLOCK) += tlclk.o
99 99
100obj-$(CONFIG_WATCHDOG) += watchdog/
101obj-$(CONFIG_MWAVE) += mwave/ 100obj-$(CONFIG_MWAVE) += mwave/
102obj-$(CONFIG_AGP) += agp/ 101obj-$(CONFIG_AGP) += agp/
103obj-$(CONFIG_DRM) += drm/ 102obj-$(CONFIG_DRM) += drm/
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 16fb23125e96..37bddc1802de 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -55,6 +55,8 @@ config SOFT_WATCHDOG
55 To compile this driver as a module, choose M here: the 55 To compile this driver as a module, choose M here: the
56 module will be called softdog. 56 module will be called softdog.
57 57
58# ALPHA Architecture
59
58# ARM Architecture 60# ARM Architecture
59 61
60config AT91RM9200_WATCHDOG 62config AT91RM9200_WATCHDOG
@@ -189,7 +191,7 @@ config PNX4008_WATCHDOG
189 191
190config IOP_WATCHDOG 192config IOP_WATCHDOG
191 tristate "IOP Watchdog" 193 tristate "IOP Watchdog"
192 depends on WATCHDOG && PLAT_IOP 194 depends on PLAT_IOP
193 select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X) 195 select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
194 help 196 help
195 Say Y here if to include support for the watchdog timer 197 Say Y here if to include support for the watchdog timer
@@ -203,15 +205,48 @@ config IOP_WATCHDOG
203 operating as an Root Complex and/or Central Resource, the PCI-X 205 operating as an Root Complex and/or Central Resource, the PCI-X
204 and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER. 206 and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER.
205 207
208config DAVINCI_WATCHDOG
209 tristate "DaVinci watchdog"
210 depends on ARCH_DAVINCI
211 help
212 Say Y here if to include support for the watchdog timer
213 in the DaVinci DM644x/DM646x processors.
214 To compile this driver as a module, choose M here: the
215 module will be called davinci_wdt.
216
217 NOTE: once enabled, this timer cannot be disabled.
218 Say N if you are unsure.
219
220# ARM26 Architecture
221
206# AVR32 Architecture 222# AVR32 Architecture
207 223
208config AT32AP700X_WDT 224config AT32AP700X_WDT
209 tristate "AT32AP700x watchdog" 225 tristate "AT32AP700x watchdog"
210 depends on WATCHDOG && CPU_AT32AP7000 226 depends on CPU_AT32AP7000
211 help 227 help
212 Watchdog timer embedded into AT32AP700x devices. This will reboot 228 Watchdog timer embedded into AT32AP700x devices. This will reboot
213 your system when the timeout is reached. 229 your system when the timeout is reached.
214 230
231# BLACKFIN Architecture
232
233config BFIN_WDT
234 tristate "Blackfin On-Chip Watchdog Timer"
235 depends on BLACKFIN
236 ---help---
237 If you say yes here you will get support for the Blackfin On-Chip
238 Watchdog Timer. If you have one of these processors and wish to
239 have watchdog support enabled, say Y, otherwise say N.
240
241 To compile this driver as a module, choose M here: the
242 module will be called bfin_wdt.
243
244# CRIS Architecture
245
246# FRV Architecture
247
248# H8300 Architecture
249
215# X86 (i386 + ia64 + x86_64) Architecture 250# X86 (i386 + ia64 + x86_64) Architecture
216 251
217config ACQUIRE_WDT 252config ACQUIRE_WDT
@@ -540,37 +575,11 @@ config SBC_EPX_C3_WATCHDOG
540 To compile this driver as a module, choose M here: the 575 To compile this driver as a module, choose M here: the
541 module will be called sbc_epx_c3. 576 module will be called sbc_epx_c3.
542 577
543# PowerPC Architecture 578# M32R Architecture
544 579
545config 8xx_WDT 580# M68K Architecture
546 tristate "MPC8xx Watchdog Timer"
547 depends on 8xx
548 581
549config 83xx_WDT 582# M68KNOMMU Architecture
550 tristate "MPC83xx Watchdog Timer"
551 depends on PPC_83xx
552
553config MV64X60_WDT
554 tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
555 depends on MV64X60
556
557config BOOKE_WDT
558 bool "PowerPC Book-E Watchdog Timer"
559 depends on BOOKE || 4xx
560 ---help---
561 Please see Documentation/watchdog/watchdog-api.txt for
562 more information.
563
564# PPC64 Architecture
565
566config WATCHDOG_RTAS
567 tristate "RTAS watchdog"
568 depends on PPC_RTAS
569 help
570 This driver adds watchdog support for the RTAS watchdog.
571
572 To compile this driver as a module, choose M here. The module
573 will be called wdrtas.
574 583
575# MIPS Architecture 584# MIPS Architecture
576 585
@@ -600,6 +609,44 @@ config WDT_RM9K_GPI
600 To compile this driver as a module, choose M here: the 609 To compile this driver as a module, choose M here: the
601 module will be called rm9k_wdt. 610 module will be called rm9k_wdt.
602 611
612# PARISC Architecture
613
614# POWERPC Architecture
615
616config MPC5200_WDT
617 tristate "MPC5200 Watchdog Timer"
618 depends on PPC_MPC52xx
619
620config 8xx_WDT
621 tristate "MPC8xx Watchdog Timer"
622 depends on 8xx
623
624config 83xx_WDT
625 tristate "MPC83xx Watchdog Timer"
626 depends on PPC_83xx
627
628config MV64X60_WDT
629 tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
630 depends on MV64X60
631
632config BOOKE_WDT
633 bool "PowerPC Book-E Watchdog Timer"
634 depends on BOOKE || 4xx
635 ---help---
636 Please see Documentation/watchdog/watchdog-api.txt for
637 more information.
638
639# PPC64 Architecture
640
641config WATCHDOG_RTAS
642 tristate "RTAS watchdog"
643 depends on PPC_RTAS
644 help
645 This driver adds watchdog support for the RTAS watchdog.
646
647 To compile this driver as a module, choose M here. The module
648 will be called wdrtas.
649
603# S390 Architecture 650# S390 Architecture
604 651
605config ZVM_WATCHDOG 652config ZVM_WATCHDOG
@@ -614,7 +661,7 @@ config ZVM_WATCHDOG
614 To compile this driver as a module, choose M here. The module 661 To compile this driver as a module, choose M here. The module
615 will be called vmwatchdog. 662 will be called vmwatchdog.
616 663
617# SUPERH Architecture 664# SUPERH (sh + sh64) Architecture
618 665
619config SH_WDT 666config SH_WDT
620 tristate "SuperH Watchdog" 667 tristate "SuperH Watchdog"
@@ -641,6 +688,8 @@ config SH_WDT_MMAP
641 If you say Y here, user applications will be able to mmap the 688 If you say Y here, user applications will be able to mmap the
642 WDT/CPG registers. 689 WDT/CPG registers.
643 690
691# SPARC Architecture
692
644# SPARC64 Architecture 693# SPARC64 Architecture
645 694
646config WATCHDOG_CP1XXX 695config WATCHDOG_CP1XXX
@@ -665,6 +714,10 @@ config WATCHDOG_RIO
665 machines. The watchdog timeout period is normally one minute but 714 machines. The watchdog timeout period is normally one minute but
666 can be changed with a boot-time parameter. 715 can be changed with a boot-time parameter.
667 716
717# V850 Architecture
718
719# XTENSA Architecture
720
668# 721#
669# ISA-based Watchdog Cards 722# ISA-based Watchdog Cards
670# 723#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index bdb9d5e3bb41..389f8b14ccc4 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o
22# USB-based Watchdog Cards 22# USB-based Watchdog Cards
23obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o 23obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
24 24
25# ALPHA Architecture
26
25# ARM Architecture 27# ARM Architecture
26obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o 28obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
27obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o 29obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
@@ -36,10 +38,22 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
36obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o 38obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
37obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o 39obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
38obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o 40obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
41obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
42
43# ARM26 Architecture
39 44
40# AVR32 Architecture 45# AVR32 Architecture
41obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o 46obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
42 47
48# BLACKFIN Architecture
49obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o
50
51# CRIS Architecture
52
53# FRV Architecture
54
55# H8300 Architecture
56
43# X86 (i386 + ia64 + x86_64) Architecture 57# X86 (i386 + ia64 + x86_64) Architecture
44obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o 58obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
45obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o 59obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
@@ -66,8 +80,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
66obj-$(CONFIG_MACHZ_WDT) += machzwd.o 80obj-$(CONFIG_MACHZ_WDT) += machzwd.o
67obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o 81obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
68 82
69# PowerPC Architecture 83# M32R Architecture
84
85# M68K Architecture
86
87# M68KNOMMU Architecture
88
89# MIPS Architecture
90obj-$(CONFIG_INDYDOG) += indydog.o
91obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
92obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
93
94# PARISC Architecture
95
96# POWERPC Architecture
70obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 97obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
98obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
71obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o 99obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
72obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o 100obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
73obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o 101obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
@@ -75,17 +103,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
75# PPC64 Architecture 103# PPC64 Architecture
76obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o 104obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
77 105
78# MIPS Architecture
79obj-$(CONFIG_INDYDOG) += indydog.o
80obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
81obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
82
83# S390 Architecture 106# S390 Architecture
84 107
85# SUPERH Architecture 108# SUPERH (sh + sh64) Architecture
86obj-$(CONFIG_SH_WDT) += shwdt.o 109obj-$(CONFIG_SH_WDT) += shwdt.o
87 110
111# SPARC Architecture
112
88# SPARC64 Architecture 113# SPARC64 Architecture
89 114
115# V850 Architecture
116
117# XTENSA Architecture
118
90# Architecture Independant 119# Architecture Independant
91obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o 120obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/char/watchdog/bfin_wdt.c b/drivers/char/watchdog/bfin_wdt.c
new file mode 100644
index 000000000000..309d27913fc1
--- /dev/null
+++ b/drivers/char/watchdog/bfin_wdt.c
@@ -0,0 +1,490 @@
1/*
2 * Blackfin On-Chip Watchdog Driver
3 * Supports BF53[123]/BF53[467]/BF54[2489]/BF561
4 *
5 * Originally based on softdog.c
6 * Copyright 2006-2007 Analog Devices Inc.
7 * Copyright 2006-2007 Michele d'Amico
8 * Copyright 1996 Alan Cox <alan@redhat.com>
9 *
10 * Enter bugs at http://blackfin.uclinux.org/
11 *
12 * Licensed under the GPL-2 or later.
13 */
14
15#include <linux/platform_device.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/types.h>
19#include <linux/timer.h>
20#include <linux/miscdevice.h>
21#include <linux/watchdog.h>
22#include <linux/fs.h>
23#include <linux/notifier.h>
24#include <linux/reboot.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <asm/blackfin.h>
28#include <asm/uaccess.h>
29
30#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
31#define stampit() stamp("here i am")
32
33#define WATCHDOG_NAME "bfin-wdt"
34#define PFX WATCHDOG_NAME ": "
35
36/* The BF561 has two watchdogs (one per core), but since Linux
37 * only runs on core A, we'll just work with that one.
38 */
39#ifdef BF561_FAMILY
40# define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL()
41# define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT()
42# define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT()
43# define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x)
44# define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x)
45# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x)
46#endif
47
48/* Bit in SWRST that indicates boot caused by watchdog */
49#define SWRST_RESET_WDOG 0x4000
50
51/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */
52#define WDOG_EXPIRED 0x8000
53
54/* Masks for WDEV field in WDOG_CTL register */
55#define ICTL_RESET 0x0
56#define ICTL_NMI 0x2
57#define ICTL_GPI 0x4
58#define ICTL_NONE 0x6
59#define ICTL_MASK 0x6
60
61/* Masks for WDEN field in WDOG_CTL register */
62#define WDEN_MASK 0x0FF0
63#define WDEN_ENABLE 0x0000
64#define WDEN_DISABLE 0x0AD0
65
66/* some defaults */
67#define WATCHDOG_TIMEOUT 20
68
69static unsigned int timeout = WATCHDOG_TIMEOUT;
70static int nowayout = WATCHDOG_NOWAYOUT;
71static struct watchdog_info bfin_wdt_info;
72static unsigned long open_check;
73static char expect_close;
74static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED;
75
76/**
77 * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
78 *
79 * The Userspace watchdog got a KeepAlive: schedule the next timeout.
80 */
81static int bfin_wdt_keepalive(void)
82{
83 stampit();
84 bfin_write_WDOG_STAT(0);
85 return 0;
86}
87
88/**
89 * bfin_wdt_stop - Stop the Watchdog
90 *
91 * Stops the on-chip watchdog.
92 */
93static int bfin_wdt_stop(void)
94{
95 stampit();
96 bfin_write_WDOG_CTL(WDEN_DISABLE);
97 return 0;
98}
99
100/**
101 * bfin_wdt_start - Start the Watchdog
102 *
103 * Starts the on-chip watchdog. Automatically loads WDOG_CNT
104 * into WDOG_STAT for us.
105 */
106static int bfin_wdt_start(void)
107{
108 stampit();
109 bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET);
110 return 0;
111}
112
113/**
114 * bfin_wdt_running - Check Watchdog status
115 *
116 * See if the watchdog is running.
117 */
118static int bfin_wdt_running(void)
119{
120 stampit();
121 return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE);
122}
123
124/**
125 * bfin_wdt_set_timeout - Set the Userspace Watchdog timeout
126 * @t: new timeout value (in seconds)
127 *
128 * Translate the specified timeout in seconds into System Clock
129 * terms which is what the on-chip Watchdog requires.
130 */
131static int bfin_wdt_set_timeout(unsigned long t)
132{
133 u32 cnt;
134 unsigned long flags;
135
136 stampit();
137
138 cnt = t * get_sclk();
139 if (cnt < get_sclk()) {
140 printk(KERN_WARNING PFX "timeout value is too large\n");
141 return -EINVAL;
142 }
143
144 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
145 {
146 int run = bfin_wdt_running();
147 bfin_wdt_stop();
148 bfin_write_WDOG_CNT(cnt);
149 if (run) bfin_wdt_start();
150 }
151 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
152
153 timeout = t;
154
155 return 0;
156}
157
158/**
159 * bfin_wdt_open - Open the Device
160 * @inode: inode of device
161 * @file: file handle of device
162 *
163 * Watchdog device is opened and started.
164 */
165static int bfin_wdt_open(struct inode *inode, struct file *file)
166{
167 stampit();
168
169 if (test_and_set_bit(0, &open_check))
170 return -EBUSY;
171
172 if (nowayout)
173 __module_get(THIS_MODULE);
174
175 bfin_wdt_keepalive();
176 bfin_wdt_start();
177
178 return nonseekable_open(inode, file);
179}
180
181/**
182 * bfin_wdt_close - Close the Device
183 * @inode: inode of device
184 * @file: file handle of device
185 *
186 * Watchdog device is closed and stopped.
187 */
188static int bfin_wdt_release(struct inode *inode, struct file *file)
189{
190 stampit();
191
192 if (expect_close == 42) {
193 bfin_wdt_stop();
194 } else {
195 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
196 bfin_wdt_keepalive();
197 }
198
199 expect_close = 0;
200 clear_bit(0, &open_check);
201
202 return 0;
203}
204
205/**
206 * bfin_wdt_write - Write to Device
207 * @file: file handle of device
208 * @buf: buffer to write
209 * @count: length of buffer
210 * @ppos: offset
211 *
212 * Pings the watchdog on write.
213 */
214static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
215 size_t len, loff_t *ppos)
216{
217 stampit();
218
219 if (len) {
220 if (!nowayout) {
221 size_t i;
222
223 /* In case it was set long ago */
224 expect_close = 0;
225
226 for (i = 0; i != len; i++) {
227 char c;
228 if (get_user(c, data + i))
229 return -EFAULT;
230 if (c == 'V')
231 expect_close = 42;
232 }
233 }
234 bfin_wdt_keepalive();
235 }
236
237 return len;
238}
239
240/**
241 * bfin_wdt_ioctl - Query Device
242 * @inode: inode of device
243 * @file: file handle of device
244 * @cmd: watchdog command
245 * @arg: argument
246 *
247 * Query basic information from the device or ping it, as outlined by the
248 * watchdog API.
249 */
250static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
251 unsigned int cmd, unsigned long arg)
252{
253 void __user *argp = (void __user *)arg;
254 int __user *p = argp;
255
256 stampit();
257
258 switch (cmd) {
259 default:
260 return -ENOTTY;
261
262 case WDIOC_GETSUPPORT:
263 if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
264 return -EFAULT;
265 else
266 return 0;
267
268 case WDIOC_GETSTATUS:
269 case WDIOC_GETBOOTSTATUS:
270 return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
271
272 case WDIOC_KEEPALIVE:
273 bfin_wdt_keepalive();
274 return 0;
275
276 case WDIOC_SETTIMEOUT: {
277 int new_timeout;
278
279 if (get_user(new_timeout, p))
280 return -EFAULT;
281
282 if (bfin_wdt_set_timeout(new_timeout))
283 return -EINVAL;
284 }
285 /* Fall */
286 case WDIOC_GETTIMEOUT:
287 return put_user(timeout, p);
288
289 case WDIOC_SETOPTIONS: {
290 unsigned long flags;
291 int options, ret = -EINVAL;
292
293 if (get_user(options, p))
294 return -EFAULT;
295
296 spin_lock_irqsave(&bfin_wdt_spinlock, flags);
297
298 if (options & WDIOS_DISABLECARD) {
299 bfin_wdt_stop();
300 ret = 0;
301 }
302
303 if (options & WDIOS_ENABLECARD) {
304 bfin_wdt_start();
305 ret = 0;
306 }
307
308 spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
309
310 return ret;
311 }
312 }
313}
314
315/**
316 * bfin_wdt_notify_sys - Notifier Handler
317 * @this: notifier block
318 * @code: notifier event
319 * @unused: unused
320 *
321 * Handles specific events, such as turning off the watchdog during a
322 * shutdown event.
323 */
324static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code,
325 void *unused)
326{
327 stampit();
328
329 if (code == SYS_DOWN || code == SYS_HALT)
330 bfin_wdt_stop();
331
332 return NOTIFY_DONE;
333}
334
335#ifdef CONFIG_PM
336static int state_before_suspend;
337
338/**
339 * bfin_wdt_suspend - suspend the watchdog
340 * @pdev: device being suspended
341 * @state: requested suspend state
342 *
343 * Remember if the watchdog was running and stop it.
344 * TODO: is this even right? Doesn't seem to be any
345 * standard in the watchdog world ...
346 */
347static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state)
348{
349 stampit();
350
351 state_before_suspend = bfin_wdt_running();
352 bfin_wdt_stop();
353
354 return 0;
355}
356
357/**
358 * bfin_wdt_resume - resume the watchdog
359 * @pdev: device being resumed
360 *
361 * If the watchdog was running, turn it back on.
362 */
363static int bfin_wdt_resume(struct platform_device *pdev)
364{
365 stampit();
366
367 if (state_before_suspend) {
368 bfin_wdt_set_timeout(timeout);
369 bfin_wdt_start();
370 }
371
372 return 0;
373}
374#else
375# define bfin_wdt_suspend NULL
376# define bfin_wdt_resume NULL
377#endif
378
379static struct platform_device bfin_wdt_device = {
380 .name = WATCHDOG_NAME,
381 .id = -1,
382};
383
384static struct platform_driver bfin_wdt_driver = {
385 .driver = {
386 .name = WATCHDOG_NAME,
387 .owner = THIS_MODULE,
388 },
389 .suspend = bfin_wdt_suspend,
390 .resume = bfin_wdt_resume,
391};
392
393static struct file_operations bfin_wdt_fops = {
394 .owner = THIS_MODULE,
395 .llseek = no_llseek,
396 .write = bfin_wdt_write,
397 .ioctl = bfin_wdt_ioctl,
398 .open = bfin_wdt_open,
399 .release = bfin_wdt_release,
400};
401
402static struct miscdevice bfin_wdt_miscdev = {
403 .minor = WATCHDOG_MINOR,
404 .name = "watchdog",
405 .fops = &bfin_wdt_fops,
406};
407
408static struct watchdog_info bfin_wdt_info = {
409 .identity = "Blackfin Watchdog",
410 .options = WDIOF_SETTIMEOUT |
411 WDIOF_KEEPALIVEPING |
412 WDIOF_MAGICCLOSE,
413};
414
415static struct notifier_block bfin_wdt_notifier = {
416 .notifier_call = bfin_wdt_notify_sys,
417};
418
419/**
420 * bfin_wdt_init - Initialize module
421 *
422 * Registers the device and notifier handler. Actual device
423 * initialization is handled by bfin_wdt_open().
424 */
425static int __init bfin_wdt_init(void)
426{
427 int ret;
428
429 stampit();
430
431 /* Check that the timeout value is within range */
432 if (bfin_wdt_set_timeout(timeout))
433 return -EINVAL;
434
435 /* Since this is an on-chip device and needs no board-specific
436 * resources, we'll handle all the platform device stuff here.
437 */
438 ret = platform_device_register(&bfin_wdt_device);
439 if (ret)
440 return ret;
441
442 ret = platform_driver_probe(&bfin_wdt_driver, NULL);
443 if (ret)
444 return ret;
445
446 ret = register_reboot_notifier(&bfin_wdt_notifier);
447 if (ret) {
448 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
449 return ret;
450 }
451
452 ret = misc_register(&bfin_wdt_miscdev);
453 if (ret) {
454 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
455 WATCHDOG_MINOR, ret);
456 unregister_reboot_notifier(&bfin_wdt_notifier);
457 return ret;
458 }
459
460 printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
461 timeout, nowayout);
462
463 return 0;
464}
465
466/**
467 * bfin_wdt_exit - Deinitialize module
468 *
469 * Unregisters the device and notifier handler. Actual device
470 * deinitialization is handled by bfin_wdt_close().
471 */
472static void __exit bfin_wdt_exit(void)
473{
474 misc_deregister(&bfin_wdt_miscdev);
475 unregister_reboot_notifier(&bfin_wdt_notifier);
476}
477
478module_init(bfin_wdt_init);
479module_exit(bfin_wdt_exit);
480
481MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>");
482MODULE_DESCRIPTION("Blackfin Watchdog Device Driver");
483MODULE_LICENSE("GPL");
484MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
485
486module_param(timeout, uint, 0);
487MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
488
489module_param(nowayout, int, 0);
490MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
index 0f5c77ddd39d..d362f5bf658a 100644
--- a/drivers/char/watchdog/booke_wdt.c
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -144,7 +144,7 @@ static int booke_wdt_open (struct inode *inode, struct file *file)
144 booke_wdt_period); 144 booke_wdt_period);
145 } 145 }
146 146
147 return 0; 147 return nonseekable_open(inode, file);
148} 148}
149 149
150static const struct file_operations booke_wdt_fops = { 150static const struct file_operations booke_wdt_fops = {
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index d0d45a8b09f0..5941ca601a3a 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -162,6 +162,10 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm
162 if ( copy_to_user(argp, &value, sizeof(int)) ) 162 if ( copy_to_user(argp, &value, sizeof(int)) )
163 return -EFAULT; 163 return -EFAULT;
164 break; 164 break;
165 case WDIOC_GETBOOTSTATUS:
166 if ( copy_to_user(argp, &value, sizeof(int)) )
167 return -EFAULT;
168 break;
165 case WDIOC_GETSUPPORT: 169 case WDIOC_GETSUPPORT:
166 if ( copy_to_user(argp, &ident, sizeof(ident)) ) 170 if ( copy_to_user(argp, &ident, sizeof(ident)) )
167 return -EFAULT; 171 return -EFAULT;
diff --git a/drivers/char/watchdog/davinci_wdt.c b/drivers/char/watchdog/davinci_wdt.c
new file mode 100644
index 000000000000..19db5302ba6e
--- /dev/null
+++ b/drivers/char/watchdog/davinci_wdt.c
@@ -0,0 +1,281 @@
1/*
2 * drivers/char/watchdog/davinci_wdt.c
3 *
4 * Watchdog driver for DaVinci DM644x/DM646x processors
5 *
6 * Copyright (C) 2006 Texas Instruments.
7 *
8 * 2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/fs.h>
19#include <linux/miscdevice.h>
20#include <linux/watchdog.h>
21#include <linux/init.h>
22#include <linux/bitops.h>
23#include <linux/platform_device.h>
24#include <linux/spinlock.h>
25
26#include <asm/hardware.h>
27#include <asm/uaccess.h>
28#include <asm/io.h>
29
30#define MODULE_NAME "DAVINCI-WDT: "
31
32#define DEFAULT_HEARTBEAT 60
33#define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/
34
35/* Timer register set definition */
36#define PID12 (0x0)
37#define EMUMGT (0x4)
38#define TIM12 (0x10)
39#define TIM34 (0x14)
40#define PRD12 (0x18)
41#define PRD34 (0x1C)
42#define TCR (0x20)
43#define TGCR (0x24)
44#define WDTCR (0x28)
45
46/* TCR bit definitions */
47#define ENAMODE12_DISABLED (0 << 6)
48#define ENAMODE12_ONESHOT (1 << 6)
49#define ENAMODE12_PERIODIC (2 << 6)
50
51/* TGCR bit definitions */
52#define TIM12RS_UNRESET (1 << 0)
53#define TIM34RS_UNRESET (1 << 1)
54#define TIMMODE_64BIT_WDOG (2 << 2)
55
56/* WDTCR bit definitions */
57#define WDEN (1 << 14)
58#define WDFLAG (1 << 15)
59#define WDKEY_SEQ0 (0xa5c6 << 16)
60#define WDKEY_SEQ1 (0xda7e << 16)
61
62static int heartbeat = DEFAULT_HEARTBEAT;
63
64static spinlock_t io_lock;
65static unsigned long wdt_status;
66#define WDT_IN_USE 0
67#define WDT_OK_TO_CLOSE 1
68#define WDT_REGION_INITED 2
69#define WDT_DEVICE_INITED 3
70
71static struct resource *wdt_mem;
72static void __iomem *wdt_base;
73
74static void wdt_service(void)
75{
76 spin_lock(&io_lock);
77
78 /* put watchdog in service state */
79 davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR);
80 /* put watchdog in active state */
81 davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR);
82
83 spin_unlock(&io_lock);
84}
85
86static void wdt_enable(void)
87{
88 u32 tgcr;
89 u32 timer_margin;
90
91 spin_lock(&io_lock);
92
93 /* disable, internal clock source */
94 davinci_writel(0, wdt_base + TCR);
95 /* reset timer, set mode to 64-bit watchdog, and unreset */
96 davinci_writel(0, wdt_base + TGCR);
97 tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET;
98 davinci_writel(tgcr, wdt_base + TGCR);
99 /* clear counter regs */
100 davinci_writel(0, wdt_base + TIM12);
101 davinci_writel(0, wdt_base + TIM34);
102 /* set timeout period */
103 timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff);
104 davinci_writel(timer_margin, wdt_base + PRD12);
105 timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32);
106 davinci_writel(timer_margin, wdt_base + PRD34);
107 /* enable run continuously */
108 davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR);
109 /* Once the WDT is in pre-active state write to
110 * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are
111 * write protected (except for the WDKEY field)
112 */
113 /* put watchdog in pre-active state */
114 davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR);
115 /* put watchdog in active state */
116 davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR);
117
118 spin_unlock(&io_lock);
119}
120
121static int davinci_wdt_open(struct inode *inode, struct file *file)
122{
123 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
124 return -EBUSY;
125
126 wdt_enable();
127
128 return nonseekable_open(inode, file);
129}
130
131static ssize_t
132davinci_wdt_write(struct file *file, const char *data, size_t len,
133 loff_t *ppos)
134{
135 if (len)
136 wdt_service();
137
138 return len;
139}
140
141static struct watchdog_info ident = {
142 .options = WDIOF_KEEPALIVEPING,
143 .identity = "DaVinci Watchdog",
144};
145
146static int
147davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
148 unsigned long arg)
149{
150 int ret = -ENOTTY;
151
152 switch (cmd) {
153 case WDIOC_GETSUPPORT:
154 ret = copy_to_user((struct watchdog_info *)arg, &ident,
155 sizeof(ident)) ? -EFAULT : 0;
156 break;
157
158 case WDIOC_GETSTATUS:
159 case WDIOC_GETBOOTSTATUS:
160 ret = put_user(0, (int *)arg);
161 break;
162
163 case WDIOC_GETTIMEOUT:
164 ret = put_user(heartbeat, (int *)arg);
165 break;
166
167 case WDIOC_KEEPALIVE:
168 wdt_service();
169 ret = 0;
170 break;
171 }
172 return ret;
173}
174
175static int davinci_wdt_release(struct inode *inode, struct file *file)
176{
177 wdt_service();
178 clear_bit(WDT_IN_USE, &wdt_status);
179
180 return 0;
181}
182
183static const struct file_operations davinci_wdt_fops = {
184 .owner = THIS_MODULE,
185 .llseek = no_llseek,
186 .write = davinci_wdt_write,
187 .ioctl = davinci_wdt_ioctl,
188 .open = davinci_wdt_open,
189 .release = davinci_wdt_release,
190};
191
192static struct miscdevice davinci_wdt_miscdev = {
193 .minor = WATCHDOG_MINOR,
194 .name = "watchdog",
195 .fops = &davinci_wdt_fops,
196};
197
198static int davinci_wdt_probe(struct platform_device *pdev)
199{
200 int ret = 0, size;
201 struct resource *res;
202
203 spin_lock_init(&io_lock);
204
205 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
206 heartbeat = DEFAULT_HEARTBEAT;
207
208 printk(KERN_INFO MODULE_NAME
209 "DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat);
210
211 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
212 if (res == NULL) {
213 printk(KERN_INFO MODULE_NAME
214 "failed to get memory region resource\n");
215 return -ENOENT;
216 }
217
218 size = res->end - res->start + 1;
219 wdt_mem = request_mem_region(res->start, size, pdev->name);
220
221 if (wdt_mem == NULL) {
222 printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
223 return -ENOENT;
224 }
225 wdt_base = (void __iomem *)(res->start);
226
227 ret = misc_register(&davinci_wdt_miscdev);
228 if (ret < 0) {
229 printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
230 release_resource(wdt_mem);
231 kfree(wdt_mem);
232 } else {
233 set_bit(WDT_DEVICE_INITED, &wdt_status);
234 }
235
236 return ret;
237}
238
239static int davinci_wdt_remove(struct platform_device *pdev)
240{
241 misc_deregister(&davinci_wdt_miscdev);
242 if (wdt_mem) {
243 release_resource(wdt_mem);
244 kfree(wdt_mem);
245 wdt_mem = NULL;
246 }
247 return 0;
248}
249
250static struct platform_driver platform_wdt_driver = {
251 .driver = {
252 .name = "watchdog",
253 },
254 .probe = davinci_wdt_probe,
255 .remove = davinci_wdt_remove,
256};
257
258static int __init davinci_wdt_init(void)
259{
260 return platform_driver_register(&platform_wdt_driver);
261}
262
263static void __exit davinci_wdt_exit(void)
264{
265 return platform_driver_unregister(&platform_wdt_driver);
266}
267
268module_init(davinci_wdt_init);
269module_exit(davinci_wdt_exit);
270
271MODULE_AUTHOR("Texas Instruments");
272MODULE_DESCRIPTION("DaVinci Watchdog Driver");
273
274module_param(heartbeat, int, 0);
275MODULE_PARM_DESC(heartbeat,
276 "Watchdog heartbeat period in seconds from 1 to "
277 __MODULE_STRING(MAX_HEARTBEAT) ", default "
278 __MODULE_STRING(DEFAULT_HEARTBEAT));
279
280MODULE_LICENSE("GPL");
281MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index eac4f9b9f007..cd5a565bc3a0 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -39,7 +39,12 @@
39 * 82801HR (ICH8R) : document number 313056-002, 313057-004, 39 * 82801HR (ICH8R) : document number 313056-002, 313057-004,
40 * 82801HH (ICH8DH) : document number 313056-002, 313057-004, 40 * 82801HH (ICH8DH) : document number 313056-002, 313057-004,
41 * 82801HO (ICH8DO) : document number 313056-002, 313057-004, 41 * 82801HO (ICH8DO) : document number 313056-002, 313057-004,
42 * 6300ESB (6300ESB) : document number 300641-003 42 * 82801IB (ICH9) : document number 316972-001, 316973-001,
43 * 82801IR (ICH9R) : document number 316972-001, 316973-001,
44 * 82801IH (ICH9DH) : document number 316972-001, 316973-001,
45 * 6300ESB (6300ESB) : document number 300641-003, 300884-010,
46 * 631xESB (631xESB) : document number 313082-001, 313075-005,
47 * 632xESB (632xESB) : document number 313082-001, 313075-005
43 */ 48 */
44 49
45/* 50/*
@@ -48,8 +53,8 @@
48 53
49/* Module and version information */ 54/* Module and version information */
50#define DRV_NAME "iTCO_wdt" 55#define DRV_NAME "iTCO_wdt"
51#define DRV_VERSION "1.01" 56#define DRV_VERSION "1.02"
52#define DRV_RELDATE "21-Jan-2007" 57#define DRV_RELDATE "26-Jul-2007"
53#define PFX DRV_NAME ": " 58#define PFX DRV_NAME ": "
54 59
55/* Includes */ 60/* Includes */
@@ -92,6 +97,10 @@ enum iTCO_chipsets {
92 TCO_ICH8, /* ICH8 & ICH8R */ 97 TCO_ICH8, /* ICH8 & ICH8R */
93 TCO_ICH8DH, /* ICH8DH */ 98 TCO_ICH8DH, /* ICH8DH */
94 TCO_ICH8DO, /* ICH8DO */ 99 TCO_ICH8DO, /* ICH8DO */
100 TCO_ICH9, /* ICH9 */
101 TCO_ICH9R, /* ICH9R */
102 TCO_ICH9DH, /* ICH9DH */
103 TCO_631XESB, /* 631xESB/632xESB */
95}; 104};
96 105
97static struct { 106static struct {
@@ -118,6 +127,10 @@ static struct {
118 {"ICH8 or ICH8R", 2}, 127 {"ICH8 or ICH8R", 2},
119 {"ICH8DH", 2}, 128 {"ICH8DH", 2},
120 {"ICH8DO", 2}, 129 {"ICH8DO", 2},
130 {"ICH9", 2},
131 {"ICH9R", 2},
132 {"ICH9DH", 2},
133 {"631xESB/632xESB", 2},
121 {NULL,0} 134 {NULL,0}
122}; 135};
123 136
@@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
148 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, 161 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 },
149 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, 162 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH },
150 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, 163 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO },
164 { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 },
165 { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R },
166 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH },
167 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
168 { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
169 { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
170 { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
171 { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
172 { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
173 { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
174 { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
175 { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
176 { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
177 { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
178 { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
179 { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
180 { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
181 { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
182 { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
151 { 0, }, /* End of list */ 183 { 0, }, /* End of list */
152}; 184};
153MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); 185MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index a0d27160c80e..6d35bb112a5f 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
321 break; 321 break;
322 322
323 case WDIOC_GETSTATUS: 323 case WDIOC_GETSTATUS:
324 case WDIOC_GETBOOTSTATUS:
324 return put_user(0, p); 325 return put_user(0, p);
325 326
326 case WDIOC_KEEPALIVE: 327 case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index db2ccb864412..1adf1d56027d 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -215,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
215 return -EFAULT; 215 return -EFAULT;
216 } 216 }
217 break; 217 break;
218 case WDIOC_GETBOOTSTATUS:
219 if (copy_to_user(p, &status, sizeof(int))) {
220 return -EFAULT;
221 }
222 break;
218 case WDIOC_GETSUPPORT: 223 case WDIOC_GETSUPPORT:
219 if (copy_to_user(argp, &ident, sizeof(ident))) { 224 if (copy_to_user(argp, &ident, sizeof(ident))) {
220 return -EFAULT; 225 return -EFAULT;
diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/char/watchdog/mpc5200_wdt.c
new file mode 100644
index 000000000000..564143d40610
--- /dev/null
+++ b/drivers/char/watchdog/mpc5200_wdt.c
@@ -0,0 +1,286 @@
1#include <linux/init.h>
2#include <linux/module.h>
3#include <linux/miscdevice.h>
4#include <linux/watchdog.h>
5#include <linux/io.h>
6#include <linux/spinlock.h>
7#include <asm/of_platform.h>
8#include <asm/uaccess.h>
9#include <asm/mpc52xx.h>
10
11
12#define GPT_MODE_WDT (1<<15)
13#define GPT_MODE_CE (1<<12)
14#define GPT_MODE_MS_TIMER (0x4)
15
16
17struct mpc5200_wdt {
18 unsigned count; /* timer ticks before watchdog kicks in */
19 long ipb_freq;
20 struct miscdevice miscdev;
21 struct resource mem;
22 struct mpc52xx_gpt __iomem *regs;
23 spinlock_t io_lock;
24};
25
26/* is_active stores wether or not the /dev/watchdog device is opened */
27static unsigned long is_active;
28
29/* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from
30 * file operations, which sucks. But there can be max 1 watchdog anyway, so...
31 */
32static struct mpc5200_wdt *wdt_global;
33
34
35/* helper to calculate timeout in timer counts */
36static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout)
37{
38 /* use biggest prescaler of 64k */
39 wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout;
40
41 if (wdt->count > 0xffff)
42 wdt->count = 0xffff;
43}
44/* return timeout in seconds (calculated from timer count) */
45static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt)
46{
47 return wdt->count * 0x10000 / wdt->ipb_freq;
48}
49
50
51/* watchdog operations */
52static int mpc5200_wdt_start(struct mpc5200_wdt *wdt)
53{
54 spin_lock(&wdt->io_lock);
55 /* disable */
56 out_be32(&wdt->regs->mode, 0);
57 /* set timeout, with maximum prescaler */
58 out_be32(&wdt->regs->count, 0x0 | wdt->count);
59 /* enable watchdog */
60 out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER);
61 spin_unlock(&wdt->io_lock);
62
63 return 0;
64}
65static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt)
66{
67 spin_lock(&wdt->io_lock);
68 /* writing A5 to OCPW resets the watchdog */
69 out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode)));
70 spin_unlock(&wdt->io_lock);
71 return 0;
72}
73static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt)
74{
75 spin_lock(&wdt->io_lock);
76 /* disable */
77 out_be32(&wdt->regs->mode, 0);
78 spin_unlock(&wdt->io_lock);
79 return 0;
80}
81
82
83/* file operations */
84static ssize_t mpc5200_wdt_write(struct file *file, const char *data,
85 size_t len, loff_t *ppos)
86{
87 struct mpc5200_wdt *wdt = file->private_data;
88 mpc5200_wdt_ping(wdt);
89 return 0;
90}
91static struct watchdog_info mpc5200_wdt_info = {
92 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
93 .identity = "mpc5200 watchdog on GPT0",
94};
95static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file,
96 unsigned int cmd, unsigned long arg)
97{
98 struct mpc5200_wdt *wdt = file->private_data;
99 int __user *data = (int __user *)arg;
100 int timeout;
101 int ret = 0;
102
103 switch (cmd) {
104 case WDIOC_GETSUPPORT:
105 ret = copy_to_user(data, &mpc5200_wdt_info,
106 sizeof(mpc5200_wdt_info));
107 if (ret)
108 ret = -EFAULT;
109 break;
110
111 case WDIOC_GETSTATUS:
112 case WDIOC_GETBOOTSTATUS:
113 ret = put_user(0, data);
114 break;
115
116 case WDIOC_KEEPALIVE:
117 mpc5200_wdt_ping(wdt);
118 break;
119
120 case WDIOC_SETTIMEOUT:
121 ret = get_user(timeout, data);
122 if (ret)
123 break;
124 mpc5200_wdt_set_timeout(wdt, timeout);
125 mpc5200_wdt_start(wdt);
126 /* fall through and return the timeout */
127
128 case WDIOC_GETTIMEOUT:
129 timeout = mpc5200_wdt_get_timeout(wdt);
130 ret = put_user(timeout, data);
131 break;
132
133 default:
134 ret = -ENOTTY;
135 }
136 return ret;
137}
138static int mpc5200_wdt_open(struct inode *inode, struct file *file)
139{
140 /* /dev/watchdog can only be opened once */
141 if (test_and_set_bit(0, &is_active))
142 return -EBUSY;
143
144 /* Set and activate the watchdog */
145 mpc5200_wdt_set_timeout(wdt_global, 30);
146 mpc5200_wdt_start(wdt_global);
147 file->private_data = wdt_global;
148 return nonseekable_open(inode, file);
149}
150static int mpc5200_wdt_release(struct inode *inode, struct file *file)
151{
152#if WATCHDOG_NOWAYOUT == 0
153 struct mpc5200_wdt *wdt = file->private_data;
154 mpc5200_wdt_stop(wdt);
155 wdt->count = 0; /* == disabled */
156#endif
157 clear_bit(0, &is_active);
158 return 0;
159}
160
161static struct file_operations mpc5200_wdt_fops = {
162 .owner = THIS_MODULE,
163 .write = mpc5200_wdt_write,
164 .ioctl = mpc5200_wdt_ioctl,
165 .open = mpc5200_wdt_open,
166 .release = mpc5200_wdt_release,
167};
168
169/* module operations */
170static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match)
171{
172 struct mpc5200_wdt *wdt;
173 int err;
174 const void *has_wdt;
175 int size;
176
177 has_wdt = of_get_property(op->node, "has-wdt", NULL);
178 if (!has_wdt)
179 return -ENODEV;
180
181 wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
182 if (!wdt)
183 return -ENOMEM;
184
185 wdt->ipb_freq = mpc52xx_find_ipb_freq(op->node);
186
187 err = of_address_to_resource(op->node, 0, &wdt->mem);
188 if (err)
189 goto out_free;
190 size = wdt->mem.end - wdt->mem.start + 1;
191 if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) {
192 err = -ENODEV;
193 goto out_free;
194 }
195 wdt->regs = ioremap(wdt->mem.start, size);
196 if (!wdt->regs) {
197 err = -ENODEV;
198 goto out_release;
199 }
200
201 dev_set_drvdata(&op->dev, wdt);
202 spin_lock_init(&wdt->io_lock);
203
204 wdt->miscdev = (struct miscdevice) {
205 .minor = WATCHDOG_MINOR,
206 .name = "watchdog",
207 .fops = &mpc5200_wdt_fops,
208 .parent = &op->dev,
209 };
210 wdt_global = wdt;
211 err = misc_register(&wdt->miscdev);
212 if (!err)
213 return 0;
214
215 iounmap(wdt->regs);
216 out_release:
217 release_mem_region(wdt->mem.start, size);
218 out_free:
219 kfree(wdt);
220 return err;
221}
222
223static int mpc5200_wdt_remove(struct of_device *op)
224{
225 struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
226
227 mpc5200_wdt_stop(wdt);
228 misc_deregister(&wdt->miscdev);
229 iounmap(wdt->regs);
230 release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1);
231 kfree(wdt);
232
233 return 0;
234}
235static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state)
236{
237 struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
238 mpc5200_wdt_stop(wdt);
239 return 0;
240}
241static int mpc5200_wdt_resume(struct of_device *op)
242{
243 struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
244 if (wdt->count)
245 mpc5200_wdt_start(wdt);
246 return 0;
247}
248static int mpc5200_wdt_shutdown(struct of_device *op)
249{
250 struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
251 mpc5200_wdt_stop(wdt);
252 return 0;
253}
254
255static struct of_device_id mpc5200_wdt_match[] = {
256 { .compatible = "mpc5200-gpt", },
257 {},
258};
259static struct of_platform_driver mpc5200_wdt_driver = {
260 .owner = THIS_MODULE,
261 .name = "mpc5200-gpt-wdt",
262 .match_table = mpc5200_wdt_match,
263 .probe = mpc5200_wdt_probe,
264 .remove = mpc5200_wdt_remove,
265 .suspend = mpc5200_wdt_suspend,
266 .resume = mpc5200_wdt_resume,
267 .shutdown = mpc5200_wdt_shutdown,
268};
269
270
271static int __init mpc5200_wdt_init(void)
272{
273 return of_register_platform_driver(&mpc5200_wdt_driver);
274}
275
276static void __exit mpc5200_wdt_exit(void)
277{
278 of_unregister_platform_driver(&mpc5200_wdt_driver);
279}
280
281module_init(mpc5200_wdt_init);
282module_exit(mpc5200_wdt_exit);
283
284MODULE_AUTHOR("Domen Puncer <domen.puncer@telargo.com>");
285MODULE_LICENSE("Dual BSD/GPL");
286MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
index 18ca752e2f90..a0bf95fb9763 100644
--- a/drivers/char/watchdog/mpc83xx_wdt.c
+++ b/drivers/char/watchdog/mpc83xx_wdt.c
@@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
119 switch (cmd) { 119 switch (cmd) {
120 case WDIOC_GETSUPPORT: 120 case WDIOC_GETSUPPORT:
121 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 121 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
122 case WDIOC_GETSTATUS:
123 case WDIOC_GETBOOTSTATUS:
124 return put_user(0, p);
122 case WDIOC_KEEPALIVE: 125 case WDIOC_KEEPALIVE:
123 mpc83xx_wdt_keepalive(); 126 mpc83xx_wdt_keepalive();
124 return 0; 127 return 0;
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 8aaed10dd499..85b5734403a5 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/char/watchdog/mpc8xx_wdt.c
@@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
57 m8xx_wdt_reset(); 57 m8xx_wdt_reset();
58 mpc8xx_wdt_handler_disable(); 58 mpc8xx_wdt_handler_disable();
59 59
60 return 0; 60 return nonseekable_open(inode, file);
61} 61}
62 62
63static int mpc8xx_wdt_release(struct inode *inode, struct file *file) 63static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c
index 419ab445c944..dcfd401a7ad7 100644
--- a/drivers/char/watchdog/mtx-1_wdt.c
+++ b/drivers/char/watchdog/mtx-1_wdt.c
@@ -143,6 +143,7 @@ static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int c
143 mtx1_wdt_reset(); 143 mtx1_wdt_reset();
144 break; 144 break;
145 case WDIOC_GETSTATUS: 145 case WDIOC_GETSTATUS:
146 case WDIOC_GETBOOTSTATUS:
146 if ( copy_to_user(argp, &value, sizeof(int)) ) 147 if ( copy_to_user(argp, &value, sizeof(int)) )
147 return -EFAULT; 148 return -EFAULT;
148 break; 149 break;
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
index b887cdb01334..0365c317f7e1 100644
--- a/drivers/char/watchdog/mv64x60_wdt.c
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -23,61 +23,101 @@
23#include <linux/watchdog.h> 23#include <linux/watchdog.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25 25
26#include <asm/mv64x60.h> 26#include <linux/mv643xx.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <asm/io.h> 28#include <asm/io.h>
29 29
30/* MV64x60 WDC (config) register access definitions */ 30#define MV64x60_WDT_WDC_OFFSET 0
31#define MV64x60_WDC_CTL1_MASK (3 << 24) 31
32#define MV64x60_WDC_CTL1(val) ((val & 3) << 24) 32/*
33#define MV64x60_WDC_CTL2_MASK (3 << 26) 33 * The watchdog configuration register contains a pair of 2-bit fields,
34#define MV64x60_WDC_CTL2(val) ((val & 3) << 26) 34 * 1. a reload field, bits 27-26, which triggers a reload of
35 * the countdown register, and
36 * 2. an enable field, bits 25-24, which toggles between
37 * enabling and disabling the watchdog timer.
38 * Bit 31 is a read-only field which indicates whether the
39 * watchdog timer is currently enabled.
40 *
41 * The low 24 bits contain the timer reload value.
42 */
43#define MV64x60_WDC_ENABLE_SHIFT 24
44#define MV64x60_WDC_SERVICE_SHIFT 26
45#define MV64x60_WDC_ENABLED_SHIFT 31
46
47#define MV64x60_WDC_ENABLED_TRUE 1
48#define MV64x60_WDC_ENABLED_FALSE 0
35 49
36/* Flags bits */ 50/* Flags bits */
37#define MV64x60_WDOG_FLAG_OPENED 0 51#define MV64x60_WDOG_FLAG_OPENED 0
38#define MV64x60_WDOG_FLAG_ENABLED 1
39 52
40static unsigned long wdt_flags; 53static unsigned long wdt_flags;
41static int wdt_status; 54static int wdt_status;
42static void __iomem *mv64x60_regs; 55static void __iomem *mv64x60_wdt_regs;
43static int mv64x60_wdt_timeout; 56static int mv64x60_wdt_timeout;
57static int mv64x60_wdt_count;
58static unsigned int bus_clk;
59static char expect_close;
60static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
61
62static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
44 65
45static void mv64x60_wdt_reg_write(u32 val) 66static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
46{ 67{
47 /* Allow write only to CTL1 / CTL2 fields, retaining values in 68 u32 data;
48 * other fields. 69 u32 enabled;
49 */ 70 int ret = 0;
50 u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); 71
51 data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); 72 spin_lock(&mv64x60_wdt_spinlock);
52 data |= val; 73 data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
53 writel(data, mv64x60_regs + MV64x60_WDT_WDC); 74 enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1;
75
76 /* only toggle the requested field if enabled state matches predicate */
77 if ((enabled ^ enabled_predicate) == 0) {
78 /* We write a 1, then a 2 -- to the appropriate field */
79 data = (1 << field_shift) | mv64x60_wdt_count;
80 writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
81
82 data = (2 << field_shift) | mv64x60_wdt_count;
83 writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
84 ret = 1;
85 }
86 spin_unlock(&mv64x60_wdt_spinlock);
87
88 return ret;
54} 89}
55 90
56static void mv64x60_wdt_service(void) 91static void mv64x60_wdt_service(void)
57{ 92{
58 /* Write 01 followed by 10 to CTL2 */ 93 mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
59 mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); 94 MV64x60_WDC_SERVICE_SHIFT);
60 mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); 95}
96
97static void mv64x60_wdt_handler_enable(void)
98{
99 if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE,
100 MV64x60_WDC_ENABLE_SHIFT)) {
101 mv64x60_wdt_service();
102 printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
103 }
61} 104}
62 105
63static void mv64x60_wdt_handler_disable(void) 106static void mv64x60_wdt_handler_disable(void)
64{ 107{
65 if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { 108 if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
66 /* Write 01 followed by 10 to CTL1 */ 109 MV64x60_WDC_ENABLE_SHIFT))
67 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
68 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
69 printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); 110 printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
70 }
71} 111}
72 112
73static void mv64x60_wdt_handler_enable(void) 113static void mv64x60_wdt_set_timeout(unsigned int timeout)
74{ 114{
75 if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { 115 /* maximum bus cycle count is 0xFFFFFFFF */
76 /* Write 01 followed by 10 to CTL1 */ 116 if (timeout > 0xFFFFFFFF / bus_clk)
77 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); 117 timeout = 0xFFFFFFFF / bus_clk;
78 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); 118
79 printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); 119 mv64x60_wdt_count = timeout * bus_clk >> 8;
80 } 120 mv64x60_wdt_timeout = timeout;
81} 121}
82 122
83static int mv64x60_wdt_open(struct inode *inode, struct file *file) 123static int mv64x60_wdt_open(struct inode *inode, struct file *file)
@@ -85,21 +125,24 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file)
85 if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) 125 if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
86 return -EBUSY; 126 return -EBUSY;
87 127
88 mv64x60_wdt_service(); 128 if (nowayout)
89 mv64x60_wdt_handler_enable(); 129 __module_get(THIS_MODULE);
90 130
91 nonseekable_open(inode, file); 131 mv64x60_wdt_handler_enable();
92 132
93 return 0; 133 return nonseekable_open(inode, file);
94} 134}
95 135
96static int mv64x60_wdt_release(struct inode *inode, struct file *file) 136static int mv64x60_wdt_release(struct inode *inode, struct file *file)
97{ 137{
98 mv64x60_wdt_service(); 138 if (expect_close == 42)
99 139 mv64x60_wdt_handler_disable();
100#if !defined(CONFIG_WATCHDOG_NOWAYOUT) 140 else {
101 mv64x60_wdt_handler_disable(); 141 printk(KERN_CRIT
102#endif 142 "mv64x60_wdt: unexpected close, not stopping timer!\n");
143 mv64x60_wdt_service();
144 }
145 expect_close = 0;
103 146
104 clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); 147 clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
105 148
@@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
109static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, 152static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
110 size_t len, loff_t * ppos) 153 size_t len, loff_t * ppos)
111{ 154{
112 if (len) 155 if (len) {
156 if (!nowayout) {
157 size_t i;
158
159 expect_close = 0;
160
161 for (i = 0; i != len; i++) {
162 char c;
163 if(get_user(c, data + i))
164 return -EFAULT;
165 if (c == 'V')
166 expect_close = 42;
167 }
168 }
113 mv64x60_wdt_service(); 169 mv64x60_wdt_service();
170 }
114 171
115 return len; 172 return len;
116} 173}
@@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
119 unsigned int cmd, unsigned long arg) 176 unsigned int cmd, unsigned long arg)
120{ 177{
121 int timeout; 178 int timeout;
179 int options;
122 void __user *argp = (void __user *)arg; 180 void __user *argp = (void __user *)arg;
123 static struct watchdog_info info = { 181 static struct watchdog_info info = {
124 .options = WDIOF_KEEPALIVEPING, 182 .options = WDIOF_SETTIMEOUT |
183 WDIOF_MAGICCLOSE |
184 WDIOF_KEEPALIVEPING,
125 .firmware_version = 0, 185 .firmware_version = 0,
126 .identity = "MV64x60 watchdog", 186 .identity = "MV64x60 watchdog",
127 }; 187 };
@@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
143 return -EOPNOTSUPP; 203 return -EOPNOTSUPP;
144 204
145 case WDIOC_SETOPTIONS: 205 case WDIOC_SETOPTIONS:
146 return -EOPNOTSUPP; 206 if (get_user(options, (int __user *)argp))
207 return -EFAULT;
208
209 if (options & WDIOS_DISABLECARD)
210 mv64x60_wdt_handler_disable();
211
212 if (options & WDIOS_ENABLECARD)
213 mv64x60_wdt_handler_enable();
214 break;
147 215
148 case WDIOC_KEEPALIVE: 216 case WDIOC_KEEPALIVE:
149 mv64x60_wdt_service(); 217 mv64x60_wdt_service();
@@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
151 break; 219 break;
152 220
153 case WDIOC_SETTIMEOUT: 221 case WDIOC_SETTIMEOUT:
154 return -EOPNOTSUPP; 222 if (get_user(timeout, (int __user *)argp))
223 return -EFAULT;
224 mv64x60_wdt_set_timeout(timeout);
225 /* Fall through */
155 226
156 case WDIOC_GETTIMEOUT: 227 case WDIOC_GETTIMEOUT:
157 timeout = mv64x60_wdt_timeout * HZ; 228 if (put_user(mv64x60_wdt_timeout, (int __user *)argp))
158 if (put_user(timeout, (int __user *)argp))
159 return -EFAULT; 229 return -EFAULT;
160 break; 230 break;
161 231
@@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = {
184static int __devinit mv64x60_wdt_probe(struct platform_device *dev) 254static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
185{ 255{
186 struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data; 256 struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
187 int bus_clk = 133; 257 struct resource *r;
258 int timeout = 10;
188 259
189 mv64x60_wdt_timeout = 10; 260 bus_clk = 133; /* in MHz */
190 if (pdata) { 261 if (pdata) {
191 mv64x60_wdt_timeout = pdata->timeout; 262 timeout = pdata->timeout;
192 bus_clk = pdata->bus_clk; 263 bus_clk = pdata->bus_clk;
193 } 264 }
194 265
195 mv64x60_regs = mv64x60_get_bridge_vbase(); 266 /* Since bus_clk is truncated MHz, actual frequency could be
267 * up to 1MHz higher. Round up, since it's better to time out
268 * too late than too soon.
269 */
270 bus_clk++;
271 bus_clk *= 1000000; /* convert to Hz */
272
273 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
274 if (!r)
275 return -ENODEV;
196 276
197 writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, 277 mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1);
198 mv64x60_regs + MV64x60_WDT_WDC); 278 if (mv64x60_wdt_regs == NULL)
279 return -ENOMEM;
280
281 mv64x60_wdt_set_timeout(timeout);
282
283 mv64x60_wdt_handler_disable(); /* in case timer was already running */
199 284
200 return misc_register(&mv64x60_wdt_miscdev); 285 return misc_register(&mv64x60_wdt_miscdev);
201} 286}
@@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
204{ 289{
205 misc_deregister(&mv64x60_wdt_miscdev); 290 misc_deregister(&mv64x60_wdt_miscdev);
206 291
207 mv64x60_wdt_service();
208 mv64x60_wdt_handler_disable(); 292 mv64x60_wdt_handler_disable();
209 293
294 iounmap(mv64x60_wdt_regs);
295
210 return 0; 296 return 0;
211} 297}
212 298
@@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = {
219 }, 305 },
220}; 306};
221 307
222static struct platform_device *mv64x60_wdt_dev;
223
224static int __init mv64x60_wdt_init(void) 308static int __init mv64x60_wdt_init(void)
225{ 309{
226 int ret;
227
228 printk(KERN_INFO "MV64x60 watchdog driver\n"); 310 printk(KERN_INFO "MV64x60 watchdog driver\n");
229 311
230 mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1); 312 return platform_driver_register(&mv64x60_wdt_driver);
231 if (!mv64x60_wdt_dev) {
232 ret = -ENOMEM;
233 goto out;
234 }
235
236 ret = platform_device_add(mv64x60_wdt_dev);
237 if (ret) {
238 platform_device_put(mv64x60_wdt_dev);
239 goto out;
240 }
241
242 ret = platform_driver_register(&mv64x60_wdt_driver);
243 if (ret) {
244 platform_device_unregister(mv64x60_wdt_dev);
245 goto out;
246 }
247
248 out:
249 return ret;
250} 313}
251 314
252static void __exit mv64x60_wdt_exit(void) 315static void __exit mv64x60_wdt_exit(void)
253{ 316{
254 platform_driver_unregister(&mv64x60_wdt_driver); 317 platform_driver_unregister(&mv64x60_wdt_driver);
255 platform_device_unregister(mv64x60_wdt_dev);
256} 318}
257 319
258module_init(mv64x60_wdt_init); 320module_init(mv64x60_wdt_init);
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
index b36fa8de2131..719b066f73c4 100644
--- a/drivers/char/watchdog/omap_wdt.c
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
142 142
143 omap_wdt_set_timeout(); 143 omap_wdt_set_timeout();
144 omap_wdt_enable(); 144 omap_wdt_enable();
145 return 0; 145 return nonseekable_open(inode, file);
146} 146}
147 147
148static int omap_wdt_release(struct inode *inode, struct file *file) 148static int omap_wdt_release(struct inode *inode, struct file *file)
@@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file,
197 197
198 switch (cmd) { 198 switch (cmd) {
199 default: 199 default:
200 return -ENOIOCTLCMD; 200 return -ENOTTY;
201 case WDIOC_GETSUPPORT: 201 case WDIOC_GETSUPPORT:
202 return copy_to_user((struct watchdog_info __user *)arg, &ident, 202 return copy_to_user((struct watchdog_info __user *)arg, &ident,
203 sizeof(ident)); 203 sizeof(ident));
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 50430bced2f2..5d1c15f83d23 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -52,10 +52,10 @@
52 52
53#include <asm/arch/map.h> 53#include <asm/arch/map.h>
54 54
55#undef S3C24XX_VA_WATCHDOG 55#undef S3C_VA_WATCHDOG
56#define S3C24XX_VA_WATCHDOG (0) 56#define S3C_VA_WATCHDOG (0)
57 57
58#include <asm/arch/regs-watchdog.h> 58#include <asm/plat-s3c/regs-watchdog.h>
59 59
60#define PFX "s3c2410-wdt: " 60#define PFX "s3c2410-wdt: "
61 61
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 33c1137f17d6..3475f47aaa45 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -45,7 +45,6 @@ static int boot_status;
45 */ 45 */
46static int sa1100dog_open(struct inode *inode, struct file *file) 46static int sa1100dog_open(struct inode *inode, struct file *file)
47{ 47{
48 nonseekable_open(inode, file);
49 if (test_and_set_bit(1,&sa1100wdt_users)) 48 if (test_and_set_bit(1,&sa1100wdt_users))
50 return -EBUSY; 49 return -EBUSY;
51 50
@@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
54 OSSR = OSSR_M3; 53 OSSR = OSSR_M3;
55 OWER = OWER_WME; 54 OWER = OWER_WME;
56 OIER |= OIER_E3; 55 OIER |= OIER_E3;
57 return 0; 56 return nonseekable_open(inode, file);
58} 57}
59 58
60/* 59/*
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
index b6282039198c..e4f3cb6090bc 100644
--- a/drivers/char/watchdog/sbc60xxwdt.c
+++ b/drivers/char/watchdog/sbc60xxwdt.c
@@ -191,8 +191,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
191 191
192static int fop_open(struct inode * inode, struct file * file) 192static int fop_open(struct inode * inode, struct file * file)
193{ 193{
194 nonseekable_open(inode, file);
195
196 /* Just in case we're already talking to someone... */ 194 /* Just in case we're already talking to someone... */
197 if(test_and_set_bit(0, &wdt_is_open)) 195 if(test_and_set_bit(0, &wdt_is_open))
198 return -EBUSY; 196 return -EBUSY;
@@ -202,7 +200,7 @@ static int fop_open(struct inode * inode, struct file * file)
202 200
203 /* Good, fire up the show */ 201 /* Good, fire up the show */
204 wdt_startup(); 202 wdt_startup();
205 return 0; 203 return nonseekable_open(inode, file);
206} 204}
207 205
208static int fop_close(struct inode * inode, struct file * file) 206static int fop_close(struct inode * inode, struct file * file)
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 2f7ba7a514fe..9670d47190d0 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -150,8 +150,6 @@ static inline int sc1200wdt_status(void)
150 150
151static int sc1200wdt_open(struct inode *inode, struct file *file) 151static int sc1200wdt_open(struct inode *inode, struct file *file)
152{ 152{
153 nonseekable_open(inode, file);
154
155 /* allow one at a time */ 153 /* allow one at a time */
156 if (down_trylock(&open_sem)) 154 if (down_trylock(&open_sem))
157 return -EBUSY; 155 return -EBUSY;
@@ -162,7 +160,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file)
162 sc1200wdt_start(); 160 sc1200wdt_start();
163 printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout); 161 printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
164 162
165 return 0; 163 return nonseekable_open(inode, file);
166} 164}
167 165
168 166
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index 2676a43895a7..e8594c64d1e6 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -248,8 +248,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
248 248
249static int fop_open(struct inode * inode, struct file * file) 249static int fop_open(struct inode * inode, struct file * file)
250{ 250{
251 nonseekable_open(inode, file);
252
253 /* Just in case we're already talking to someone... */ 251 /* Just in case we're already talking to someone... */
254 if(test_and_set_bit(0, &wdt_is_open)) 252 if(test_and_set_bit(0, &wdt_is_open))
255 return -EBUSY; 253 return -EBUSY;
@@ -258,7 +256,7 @@ static int fop_open(struct inode * inode, struct file * file)
258 256
259 /* Good, fire up the show */ 257 /* Good, fire up the show */
260 wdt_startup(); 258 wdt_startup();
261 return 0; 259 return nonseekable_open(inode, file);
262} 260}
263 261
264static int fop_close(struct inode * inode, struct file * file) 262static int fop_close(struct inode * inode, struct file * file)
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index b46e7f47d705..df33b3b5a53c 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -4,7 +4,7 @@
4 * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> 4 * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
5 * added support for W83627THF. 5 * added support for W83627THF.
6 * 6 *
7 * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> 7 * (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
8 * 8 *
9 * Based on advantechwdt.c which is based on wdt.c. 9 * Based on advantechwdt.c which is based on wdt.c.
10 * Original copyright messages: 10 * Original copyright messages:
@@ -42,7 +42,7 @@
42#include <asm/uaccess.h> 42#include <asm/uaccess.h>
43#include <asm/system.h> 43#include <asm/system.h>
44 44
45#define WATCHDOG_NAME "w83627hf/thf WDT" 45#define WATCHDOG_NAME "w83627hf/thf/hg WDT"
46#define PFX WATCHDOG_NAME ": " 46#define PFX WATCHDOG_NAME ": "
47#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ 47#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
48 48
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
57 57
58static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ 58static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
59module_param(timeout, int, 0); 59module_param(timeout, int, 0);
60MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 60MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
61 61
62static int nowayout = WATCHDOG_NOWAYOUT; 62static int nowayout = WATCHDOG_NOWAYOUT;
63module_param(nowayout, int, 0); 63module_param(nowayout, int, 0);
@@ -78,9 +78,9 @@ w83627hf_select_wd_register(void)
78 outb_p(0x87, WDT_EFER); /* Enter extended function mode */ 78 outb_p(0x87, WDT_EFER); /* Enter extended function mode */
79 outb_p(0x87, WDT_EFER); /* Again according to manual */ 79 outb_p(0x87, WDT_EFER); /* Again according to manual */
80 80
81 outb(0x20, WDT_EFER); /* check chip version */ 81 outb(0x20, WDT_EFER); /* check chip version */
82 c = inb(WDT_EFDR); 82 c = inb(WDT_EFDR);
83 if (c == 0x82) { /* W83627THF */ 83 if (c == 0x82) { /* W83627THF */
84 outb_p(0x2b, WDT_EFER); /* select GPIO3 */ 84 outb_p(0x2b, WDT_EFER); /* select GPIO3 */
85 c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ 85 c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
86 outb_p(0x2b, WDT_EFER); 86 outb_p(0x2b, WDT_EFER);
@@ -114,11 +114,17 @@ w83627hf_init(void)
114 printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); 114 printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout);
115 outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ 115 outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */
116 } 116 }
117
117 outb_p(0xF5, WDT_EFER); /* Select CRF5 */ 118 outb_p(0xF5, WDT_EFER); /* Select CRF5 */
118 t=inb_p(WDT_EFDR); /* read CRF5 */ 119 t=inb_p(WDT_EFDR); /* read CRF5 */
119 t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ 120 t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */
120 outb_p(t, WDT_EFDR); /* Write back to CRF5 */ 121 outb_p(t, WDT_EFDR); /* Write back to CRF5 */
121 122
123 outb_p(0xF7, WDT_EFER); /* Select CRF7 */
124 t=inb_p(WDT_EFDR); /* read CRF7 */
125 t&=~0xC0; /* disable keyboard & mouse turning off watchdog */
126 outb_p(t, WDT_EFDR); /* Write back to CRF7 */
127
122 w83627hf_unselect_wd_register(); 128 w83627hf_unselect_wd_register();
123} 129}
124 130
@@ -126,7 +132,7 @@ static void
126wdt_ctrl(int timeout) 132wdt_ctrl(int timeout)
127{ 133{
128 spin_lock(&io_lock); 134 spin_lock(&io_lock);
129 135
130 w83627hf_select_wd_register(); 136 w83627hf_select_wd_register();
131 137
132 outb_p(0xF6, WDT_EFER); /* Select CRF6 */ 138 outb_p(0xF6, WDT_EFER); /* Select CRF6 */
@@ -154,7 +160,7 @@ wdt_disable(void)
154static int 160static int
155wdt_set_heartbeat(int t) 161wdt_set_heartbeat(int t)
156{ 162{
157 if ((t < 1) || (t > 63)) 163 if ((t < 1) || (t > 255))
158 return -EINVAL; 164 return -EINVAL;
159 165
160 timeout = t; 166 timeout = t;
@@ -324,11 +330,11 @@ wdt_init(void)
324 330
325 spin_lock_init(&io_lock); 331 spin_lock_init(&io_lock);
326 332
327 printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n"); 333 printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n");
328 334
329 if (wdt_set_heartbeat(timeout)) { 335 if (wdt_set_heartbeat(timeout)) {
330 wdt_set_heartbeat(WATCHDOG_TIMEOUT); 336 wdt_set_heartbeat(WATCHDOG_TIMEOUT);
331 printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", 337 printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n",
332 WATCHDOG_TIMEOUT); 338 WATCHDOG_TIMEOUT);
333 } 339 }
334 340