summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 20:43:52 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 20:43:52 -0700
commit2f63251ed0a803ddbe7bf2577b69d467aa872f68 (patch)
tree960ba4e27bb2cffdda0841ee701515c4bd75143a /drivers/char
parentd6dd9e93c7531fa31370e27d053a3940d8d662fb (diff)
parent647e50f38345525d8261c295a0d0629dcea23a9b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: (28 commits) [WATCHDOG] Fix pcwd_init_module crash [WATCHDOG] ICH9 support for iTCO_wdt [WATCHDOG] 631xESB/632xESB support for iTCO_wdt - add all LPC bridges [WATCHDOG] 631xESB/632xESB support for iTCO_wdt [WATCHDOG] omap_wdt.c - default error for IOCTL is -ENOTTY [WATCHDOG] Return value of nonseekable_open [WATCHDOG] mv64x60_wdt: Rework the timeout register manipulation [WATCHDOG] mv64x60_wdt: disable watchdog timer when driver is probed [WATCHDOG] mv64x60_wdt: Support the WDIOF_MAGICCLOSE feature [WATCHDOG] mv64x60_wdt: Add a module parameter to change nowayout setting [WATCHDOG] mv64x60_wdt: Add WDIOC_SETOPTIONS ioctl support [WATCHDOG] mv64x60_wdt: Support for WDIOC_SETTIMEOUT ioctl [WATCHDOG] mv64x60_wdt: Fix WDIOC_GETTIMEOUT return value [WATCHDOG] mv64x60_wdt: Check return value of nonseekable_open [WATCHDOG] mv64x60_wdt: Add arch/powerpc platform support [WATCHDOG] mv64x60_wdt: Get register address from platform data [WATCHDOG] mv64x60_wdt: set up platform_device in platform code [WATCHDOG] ensure mouse and keyboard ignored in w83627hf_wdt [WATCHDOG] s3c2410_wdt: fixup after arch include moves [WATCHDOG] git-watchdog-typo ...
Diffstat (limited to 'drivers/char')
-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
22 files changed, 1393 insertions, 148 deletions
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
obj-$(CONFIG_GPIO_TB0219) += tb0219.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
-obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_MWAVE) += mwave/
obj-$(CONFIG_AGP) += agp/
obj-$(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
To compile this driver as a module, choose M here: the
module will be called softdog.
+# ALPHA Architecture
+
# ARM Architecture
config AT91RM9200_WATCHDOG
@@ -189,7 +191,7 @@ config PNX4008_WATCHDOG
config IOP_WATCHDOG
tristate "IOP Watchdog"
- depends on WATCHDOG && PLAT_IOP
+ depends on PLAT_IOP
select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
help
Say Y here if to include support for the watchdog timer
@@ -203,15 +205,48 @@ config IOP_WATCHDOG
operating as an Root Complex and/or Central Resource, the PCI-X
and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER.
+config DAVINCI_WATCHDOG
+ tristate "DaVinci watchdog"
+ depends on ARCH_DAVINCI
+ help
+ Say Y here if to include support for the watchdog timer
+ in the DaVinci DM644x/DM646x processors.
+ To compile this driver as a module, choose M here: the
+ module will be called davinci_wdt.
+
+ NOTE: once enabled, this timer cannot be disabled.
+ Say N if you are unsure.
+
+# ARM26 Architecture
+
# AVR32 Architecture
config AT32AP700X_WDT
tristate "AT32AP700x watchdog"
- depends on WATCHDOG && CPU_AT32AP7000
+ depends on CPU_AT32AP7000
help
Watchdog timer embedded into AT32AP700x devices. This will reboot
your system when the timeout is reached.
+# BLACKFIN Architecture
+
+config BFIN_WDT
+ tristate "Blackfin On-Chip Watchdog Timer"
+ depends on BLACKFIN
+ ---help---
+ If you say yes here you will get support for the Blackfin On-Chip
+ Watchdog Timer. If you have one of these processors and wish to
+ have watchdog support enabled, say Y, otherwise say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bfin_wdt.
+
+# CRIS Architecture
+
+# FRV Architecture
+
+# H8300 Architecture
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
@@ -540,37 +575,11 @@ config SBC_EPX_C3_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called sbc_epx_c3.
-# PowerPC Architecture
+# M32R Architecture
-config 8xx_WDT
- tristate "MPC8xx Watchdog Timer"
- depends on 8xx
+# M68K Architecture
-config 83xx_WDT
- tristate "MPC83xx Watchdog Timer"
- depends on PPC_83xx
-
-config MV64X60_WDT
- tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
- depends on MV64X60
-
-config BOOKE_WDT
- bool "PowerPC Book-E Watchdog Timer"
- depends on BOOKE || 4xx
- ---help---
- Please see Documentation/watchdog/watchdog-api.txt for
- more information.
-
-# PPC64 Architecture
-
-config WATCHDOG_RTAS
- tristate "RTAS watchdog"
- depends on PPC_RTAS
- help
- This driver adds watchdog support for the RTAS watchdog.
-
- To compile this driver as a module, choose M here. The module
- will be called wdrtas.
+# M68KNOMMU Architecture
# MIPS Architecture
@@ -600,6 +609,44 @@ config WDT_RM9K_GPI
To compile this driver as a module, choose M here: the
module will be called rm9k_wdt.
+# PARISC Architecture
+
+# POWERPC Architecture
+
+config MPC5200_WDT
+ tristate "MPC5200 Watchdog Timer"
+ depends on PPC_MPC52xx
+
+config 8xx_WDT
+ tristate "MPC8xx Watchdog Timer"
+ depends on 8xx
+
+config 83xx_WDT
+ tristate "MPC83xx Watchdog Timer"
+ depends on PPC_83xx
+
+config MV64X60_WDT
+ tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+ depends on MV64X60
+
+config BOOKE_WDT
+ bool "PowerPC Book-E Watchdog Timer"
+ depends on BOOKE || 4xx
+ ---help---
+ Please see Documentation/watchdog/watchdog-api.txt for
+ more information.
+
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
# S390 Architecture
config ZVM_WATCHDOG
@@ -614,7 +661,7 @@ config ZVM_WATCHDOG
To compile this driver as a module, choose M here. The module
will be called vmwatchdog.
-# SUPERH Architecture
+# SUPERH (sh + sh64) Architecture
config SH_WDT
tristate "SuperH Watchdog"
@@ -641,6 +688,8 @@ config SH_WDT_MMAP
If you say Y here, user applications will be able to mmap the
WDT/CPG registers.
+# SPARC Architecture
+
# SPARC64 Architecture
config WATCHDOG_CP1XXX
@@ -665,6 +714,10 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
+# V850 Architecture
+
+# XTENSA Architecture
+
#
# ISA-based Watchdog Cards
#
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
# USB-based Watchdog Cards
obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
+# ALPHA Architecture
+
# ARM Architecture
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
@@ -36,10 +38,22 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
+obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
+
+# ARM26 Architecture
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
+# BLACKFIN Architecture
+obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o
+
+# CRIS Architecture
+
+# FRV Architecture
+
+# H8300 Architecture
+
# X86 (i386 + ia64 + x86_64) Architecture
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
@@ -66,8 +80,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
-# PowerPC Architecture
+# M32R Architecture
+
+# M68K Architecture
+
+# M68KNOMMU Architecture
+
+# MIPS Architecture
+obj-$(CONFIG_INDYDOG) += indydog.o
+obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
+obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+
+# PARISC Architecture
+
+# POWERPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
@@ -75,17 +103,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# PPC64 Architecture
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-# MIPS Architecture
-obj-$(CONFIG_INDYDOG) += indydog.o
-obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
-obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
-
# S390 Architecture
-# SUPERH Architecture
+# SUPERH (sh + sh64) Architecture
obj-$(CONFIG_SH_WDT) += shwdt.o
+# SPARC Architecture
+
# SPARC64 Architecture
+# V850 Architecture
+
+# XTENSA Architecture
+
# Architecture Independant
obj-$(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 @@
+/*
+ * Blackfin On-Chip Watchdog Driver
+ * Supports BF53[123]/BF53[467]/BF54[2489]/BF561
+ *
+ * Originally based on softdog.c
+ * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2007 Michele d'Amico
+ * Copyright 1996 Alan Cox <alan@redhat.com>
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+
+#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
+#define stampit() stamp("here i am")
+
+#define WATCHDOG_NAME "bfin-wdt"
+#define PFX WATCHDOG_NAME ": "
+
+/* The BF561 has two watchdogs (one per core), but since Linux
+ * only runs on core A, we'll just work with that one.
+ */
+#ifdef BF561_FAMILY
+# define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL()
+# define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT()
+# define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT()
+# define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x)
+# define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x)
+# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x)
+#endif
+
+/* Bit in SWRST that indicates boot caused by watchdog */
+#define SWRST_RESET_WDOG 0x4000
+
+/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */
+#define WDOG_EXPIRED 0x8000
+
+/* Masks for WDEV field in WDOG_CTL register */
+#define ICTL_RESET 0x0
+#define ICTL_NMI 0x2
+#define ICTL_GPI 0x4
+#define ICTL_NONE 0x6
+#define ICTL_MASK 0x6
+
+/* Masks for WDEN field in WDOG_CTL register */
+#define WDEN_MASK 0x0FF0
+#define WDEN_ENABLE 0x0000
+#define WDEN_DISABLE 0x0AD0
+
+/* some defaults */
+#define WATCHDOG_TIMEOUT 20
+
+static unsigned int timeout = WATCHDOG_TIMEOUT;
+static int nowayout = WATCHDOG_NOWAYOUT;
+static struct watchdog_info bfin_wdt_info;
+static unsigned long open_check;
+static char expect_close;
+static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED;
+
+/**
+ * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
+ *
+ * The Userspace watchdog got a KeepAlive: schedule the next timeout.
+ */
+static int bfin_wdt_keepalive(void)
+{
+ stampit();
+ bfin_write_WDOG_STAT(0);
+ return 0;
+}
+
+/**
+ * bfin_wdt_stop - Stop the Watchdog
+ *
+ * Stops the on-chip watchdog.
+ */
+static int bfin_wdt_stop(void)
+{
+ stampit();
+ bfin_write_WDOG_CTL(WDEN_DISABLE);
+ return 0;
+}
+
+/**
+ * bfin_wdt_start - Start the Watchdog
+ *
+ * Starts the on-chip watchdog. Automatically loads WDOG_CNT
+ * into WDOG_STAT for us.
+ */
+static int bfin_wdt_start(void)
+{
+ stampit();
+ bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET);
+ return 0;
+}
+
+/**
+ * bfin_wdt_running - Check Watchdog status
+ *
+ * See if the watchdog is running.
+ */
+static int bfin_wdt_running(void)
+{
+ stampit();
+ return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE);
+}
+
+/**
+ * bfin_wdt_set_timeout - Set the Userspace Watchdog timeout
+ * @t: new timeout value (in seconds)
+ *
+ * Translate the specified timeout in seconds into System Clock
+ * terms which is what the on-chip Watchdog requires.
+ */
+static int bfin_wdt_set_timeout(unsigned long t)
+{
+ u32 cnt;
+ unsigned long flags;
+
+ stampit();
+
+ cnt = t * get_sclk();
+ if (cnt < get_sclk()) {
+ printk(KERN_WARNING PFX "timeout value is too large\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&bfin_wdt_spinlock, flags);
+ {
+ int run = bfin_wdt_running();
+ bfin_wdt_stop();
+ bfin_write_WDOG_CNT(cnt);
+ if (run) bfin_wdt_start();
+ }
+ spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
+
+ timeout = t;
+
+ return 0;
+}
+
+/**
+ * bfin_wdt_open - Open the Device
+ * @inode: inode of device
+ * @file: file handle of device
+ *
+ * Watchdog device is opened and started.
+ */
+static int bfin_wdt_open(struct inode *inode, struct file *file)
+{
+ stampit();
+
+ if (test_and_set_bit(0, &open_check))
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ bfin_wdt_keepalive();
+ bfin_wdt_start();
+
+ return nonseekable_open(inode, file);
+}
+
+/**
+ * bfin_wdt_close - Close the Device
+ * @inode: inode of device
+ * @file: file handle of device
+ *
+ * Watchdog device is closed and stopped.
+ */
+static int bfin_wdt_release(struct inode *inode, struct file *file)
+{
+ stampit();
+
+ if (expect_close == 42) {
+ bfin_wdt_stop();
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ bfin_wdt_keepalive();
+ }
+
+ expect_close = 0;
+ clear_bit(0, &open_check);
+
+ return 0;
+}
+
+/**
+ * bfin_wdt_write - Write to Device
+ * @file: file handle of device
+ * @buf: buffer to write
+ * @count: length of buffer
+ * @ppos: offset
+ *
+ * Pings the watchdog on write.
+ */
+static ssize_t bfin_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ stampit();
+
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ expect_close = 0;
+
+ for (i = 0; i != len; i++) {
+ char c;
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ bfin_wdt_keepalive();
+ }
+
+ return len;
+}
+
+/**
+ * bfin_wdt_ioctl - Query Device
+ * @inode: inode of device
+ * @file: file handle of device
+ * @cmd: watchdog command
+ * @arg: argument
+ *
+ * Query basic information from the device or ping it, as outlined by the
+ * watchdog API.
+ */
+static int bfin_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+
+ stampit();
+
+ switch (cmd) {
+ default:
+ return -ENOTTY;
+
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info)))
+ return -EFAULT;
+ else
+ return 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p);
+
+ case WDIOC_KEEPALIVE:
+ bfin_wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT: {
+ int new_timeout;
+
+ if (get_user(new_timeout, p))
+ return -EFAULT;
+
+ if (bfin_wdt_set_timeout(new_timeout))
+ return -EINVAL;
+ }
+ /* Fall */
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, p);
+
+ case WDIOC_SETOPTIONS: {
+ unsigned long flags;
+ int options, ret = -EINVAL;
+
+ if (get_user(options, p))
+ return -EFAULT;
+
+ spin_lock_irqsave(&bfin_wdt_spinlock, flags);
+
+ if (options & WDIOS_DISABLECARD) {
+ bfin_wdt_stop();
+ ret = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ bfin_wdt_start();
+ ret = 0;
+ }
+
+ spin_unlock_irqrestore(&bfin_wdt_spinlock, flags);
+
+ return ret;
+ }
+ }
+}
+
+/**
+ * bfin_wdt_notify_sys - Notifier Handler
+ * @this: notifier block
+ * @code: notifier event
+ * @unused: unused
+ *
+ * Handles specific events, such as turning off the watchdog during a
+ * shutdown event.
+ */
+static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ stampit();
+
+ if (code == SYS_DOWN || code == SYS_HALT)
+ bfin_wdt_stop();
+
+ return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_PM
+static int state_before_suspend;
+
+/**
+ * bfin_wdt_suspend - suspend the watchdog
+ * @pdev: device being suspended
+ * @state: requested suspend state
+ *
+ * Remember if the watchdog was running and stop it.
+ * TODO: is this even right? Doesn't seem to be any
+ * standard in the watchdog world ...
+ */
+static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ stampit();
+
+ state_before_suspend = bfin_wdt_running();
+ bfin_wdt_stop();
+
+ return 0;
+}
+
+/**
+ * bfin_wdt_resume - resume the watchdog
+ * @pdev: device being resumed
+ *
+ * If the watchdog was running, turn it back on.
+ */
+static int bfin_wdt_resume(struct platform_device *pdev)
+{
+ stampit();
+
+ if (state_before_suspend) {
+ bfin_wdt_set_timeout(timeout);
+ bfin_wdt_start();
+ }
+
+ return 0;
+}
+#else
+# define bfin_wdt_suspend NULL
+# define bfin_wdt_resume NULL
+#endif
+
+static struct platform_device bfin_wdt_device = {
+ .name = WATCHDOG_NAME,
+ .id = -1,
+};
+
+static struct platform_driver bfin_wdt_driver = {
+ .driver = {
+ .name = WATCHDOG_NAME,
+ .owner = THIS_MODULE,
+ },
+ .suspend = bfin_wdt_suspend,
+ .resume = bfin_wdt_resume,
+};
+
+static struct file_operations bfin_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = bfin_wdt_write,
+ .ioctl = bfin_wdt_ioctl,
+ .open = bfin_wdt_open,
+ .release = bfin_wdt_release,
+};
+
+static struct miscdevice bfin_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &bfin_wdt_fops,
+};
+
+static struct watchdog_info bfin_wdt_info = {
+ .identity = "Blackfin Watchdog",
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+};
+
+static struct notifier_block bfin_wdt_notifier = {
+ .notifier_call = bfin_wdt_notify_sys,
+};
+
+/**
+ * bfin_wdt_init - Initialize module
+ *
+ * Registers the device and notifier handler. Actual device
+ * initialization is handled by bfin_wdt_open().
+ */
+static int __init bfin_wdt_init(void)
+{
+ int ret;
+
+ stampit();
+
+ /* Check that the timeout value is within range */
+ if (bfin_wdt_set_timeout(timeout))
+ return -EINVAL;
+
+ /* Since this is an on-chip device and needs no board-specific
+ * resources, we'll handle all the platform device stuff here.
+ */
+ ret = platform_device_register(&bfin_wdt_device);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_probe(&bfin_wdt_driver, NULL);
+ if (ret)
+ return ret;
+
+ ret = register_reboot_notifier(&bfin_wdt_notifier);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
+ return ret;
+ }
+
+ ret = misc_register(&bfin_wdt_miscdev);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ unregister_reboot_notifier(&bfin_wdt_notifier);
+ return ret;
+ }
+
+ printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
+ timeout, nowayout);
+
+ return 0;
+}
+
+/**
+ * bfin_wdt_exit - Deinitialize module
+ *
+ * Unregisters the device and notifier handler. Actual device
+ * deinitialization is handled by bfin_wdt_close().
+ */
+static void __exit bfin_wdt_exit(void)
+{
+ misc_deregister(&bfin_wdt_miscdev);
+ unregister_reboot_notifier(&bfin_wdt_notifier);
+}
+
+module_init(bfin_wdt_init);
+module_exit(bfin_wdt_exit);
+
+MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("Blackfin Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+module_param(nowayout, int, 0);
+MODULE_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)
booke_wdt_period);
}
- return 0;
+ return nonseekable_open(inode, file);
}
static 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
if ( copy_to_user(argp, &value, sizeof(int)) )
return -EFAULT;
break;
+ case WDIOC_GETBOOTSTATUS:
+ if ( copy_to_user(argp, &value, sizeof(int)) )
+ return -EFAULT;
+ break;
case WDIOC_GETSUPPORT:
if ( copy_to_user(argp, &ident, sizeof(ident)) )
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 @@
+/*
+ * drivers/char/watchdog/davinci_wdt.c
+ *
+ * Watchdog driver for DaVinci DM644x/DM646x processors
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define MODULE_NAME "DAVINCI-WDT: "
+
+#define DEFAULT_HEARTBEAT 60
+#define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/
+
+/* Timer register set definition */
+#define PID12 (0x0)
+#define EMUMGT (0x4)
+#define TIM12 (0x10)
+#define TIM34 (0x14)
+#define PRD12 (0x18)
+#define PRD34 (0x1C)
+#define TCR (0x20)
+#define TGCR (0x24)
+#define WDTCR (0x28)
+
+/* TCR bit definitions */
+#define ENAMODE12_DISABLED (0 << 6)
+#define ENAMODE12_ONESHOT (1 << 6)
+#define ENAMODE12_PERIODIC (2 << 6)
+
+/* TGCR bit definitions */
+#define TIM12RS_UNRESET (1 << 0)
+#define TIM34RS_UNRESET (1 << 1)
+#define TIMMODE_64BIT_WDOG (2 << 2)
+
+/* WDTCR bit definitions */
+#define WDEN (1 << 14)
+#define WDFLAG (1 << 15)
+#define WDKEY_SEQ0 (0xa5c6 << 16)
+#define WDKEY_SEQ1 (0xda7e << 16)
+
+static int heartbeat = DEFAULT_HEARTBEAT;
+
+static spinlock_t io_lock;
+static unsigned long wdt_status;
+#define WDT_IN_USE 0
+#define WDT_OK_TO_CLOSE 1
+#define WDT_REGION_INITED 2
+#define WDT_DEVICE_INITED 3
+
+static struct resource *wdt_mem;
+static void __iomem *wdt_base;
+
+static void wdt_service(void)
+{
+ spin_lock(&io_lock);
+
+ /* put watchdog in service state */
+ davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR);
+ /* put watchdog in active state */
+ davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR);
+
+ spin_unlock(&io_lock);
+}
+
+static void wdt_enable(void)
+{
+ u32 tgcr;
+ u32 timer_margin;
+
+ spin_lock(&io_lock);
+
+ /* disable, internal clock source */
+ davinci_writel(0, wdt_base + TCR);
+ /* reset timer, set mode to 64-bit watchdog, and unreset */
+ davinci_writel(0, wdt_base + TGCR);
+ tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET;
+ davinci_writel(tgcr, wdt_base + TGCR);
+ /* clear counter regs */
+ davinci_writel(0, wdt_base + TIM12);
+ davinci_writel(0, wdt_base + TIM34);
+ /* set timeout period */
+ timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff);
+ davinci_writel(timer_margin, wdt_base + PRD12);
+ timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32);
+ davinci_writel(timer_margin, wdt_base + PRD34);
+ /* enable run continuously */
+ davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR);
+ /* Once the WDT is in pre-active state write to
+ * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are
+ * write protected (except for the WDKEY field)
+ */
+ /* put watchdog in pre-active state */
+ davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR);
+ /* put watchdog in active state */
+ davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR);
+
+ spin_unlock(&io_lock);
+}
+
+static int davinci_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+
+ wdt_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t
+davinci_wdt_write(struct file *file, const char *data, size_t len,
+ loff_t *ppos)
+{
+ if (len)
+ wdt_service();
+
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING,
+ .identity = "DaVinci Watchdog",
+};
+
+static int
+davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOTTY;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, (int *)arg);
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(heartbeat, (int *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_service();
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int davinci_wdt_release(struct inode *inode, struct file *file)
+{
+ wdt_service();
+ clear_bit(WDT_IN_USE, &wdt_status);
+
+ return 0;
+}
+
+static const struct file_operations davinci_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = davinci_wdt_write,
+ .ioctl = davinci_wdt_ioctl,
+ .open = davinci_wdt_open,
+ .release = davinci_wdt_release,
+};
+
+static struct miscdevice davinci_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &davinci_wdt_fops,
+};
+
+static int davinci_wdt_probe(struct platform_device *pdev)