Bladeren bron

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
  ...
Linus Torvalds 18 jaren geleden
bovenliggende
commit
2f63251ed0

+ 8 - 0
MAINTAINERS

@@ -756,6 +756,14 @@ L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
 W:	http://blackfin.uclinux.org
 S:	Supported
 
+BLACKFIN WATCHDOG DRIVER
+P:	Mike Frysinger
+M:	michael.frysinger@analog.com
+M:	vapier.adi@gmail.com
+L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:	http://blackfin.uclinux.org
+S:	Supported
+
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:	Thomas Sailer
 M:	t.sailer@alumni.ethz.ch

+ 6 - 0
arch/powerpc/boot/dts/prpmc2800.dts

@@ -207,6 +207,12 @@
 			interrupt-parent = <&/mv64x60/pic>;
 		};
 
+		wdt@b410 {			/* watchdog timer */
+			compatible = "marvell,mv64x60-wdt";
+			reg = <b410 8>;
+			timeout = <a>;		/* wdt timeout in seconds */
+		};
+
 		i2c@c000 {
 			device_type = "i2c";
 			compatible = "marvell,mv64x60-i2c";

+ 64 - 0
arch/powerpc/sysdev/mv64x60_dev.c

@@ -390,6 +390,61 @@ error:
 	return err;
 }
 
+/*
+ * Create mv64x60_wdt platform devices
+ */
+static int __init mv64x60_wdt_device_setup(struct device_node *np, int id)
+{
+	struct resource r;
+	struct platform_device *pdev;
+	struct mv64x60_wdt_pdata pdata;
+	const unsigned int *prop;
+	int err;
+
+	err = of_address_to_resource(np, 0, &r);
+	if (err)
+		return err;
+
+	memset(&pdata, 0, sizeof(pdata));
+
+	prop = of_get_property(np, "timeout", NULL);
+	if (!prop)
+		return -ENODEV;
+	pdata.timeout = *prop;
+
+	np = of_get_parent(np);
+	if (!np)
+		return -ENODEV;
+
+	prop = of_get_property(np, "clock-frequency", NULL);
+	of_node_put(np);
+	if (!prop)
+		return -ENODEV;
+	pdata.bus_clk = *prop / 1000000; /* wdt driver wants freq in MHz */
+
+	pdev = platform_device_alloc(MV64x60_WDT_NAME, id);
+	if (!pdev)
+		return -ENOMEM;
+
+	err = platform_device_add_resources(pdev, &r, 1);
+	if (err)
+		goto error;
+
+	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (err)
+		goto error;
+
+	err = platform_device_add(pdev);
+	if (err)
+		goto error;
+
+	return 0;
+
+error:
+	platform_device_put(pdev);
+	return err;
+}
+
 static int __init mv64x60_device_setup(void)
 {
 	struct device_node *np = NULL;
@@ -414,6 +469,15 @@ static int __init mv64x60_device_setup(void)
 		if ((err = mv64x60_i2c_device_setup(np, id)))
 			goto error;
 
+	/* support up to one watchdog timer */
+	np = of_find_compatible_node(np, NULL, "marvell,mv64x60-wdt");
+	if (np) {
+		if ((err = mv64x60_wdt_device_setup(np, id)))
+			goto error;
+		of_node_put(np);
+	}
+
+
 	return 0;
 
 error:

+ 29 - 0
arch/ppc/syslib/mv64x60.c

@@ -441,6 +441,32 @@ static struct platform_device i2c_device = {
 };
 #endif
 
+#ifdef CONFIG_WATCHDOG
+static struct mv64x60_wdt_pdata mv64x60_wdt_pdata = {
+	.timeout		= 10,  /* default watchdog expiry in seconds */
+	.bus_clk		= 133, /* default bus clock in MHz */
+};
+
+static struct resource mv64x60_wdt_resources[] = {
+	[0] = {
+		.name	= "mv64x60 wdt base",
+		.start	= MV64x60_WDT_WDC,
+		.end	= MV64x60_WDT_WDC + 8 - 1, /* two 32-bit registers */
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device wdt_device = {
+	.name		= MV64x60_WDT_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv64x60_wdt_resources),
+	.resource	= mv64x60_wdt_resources,
+	.dev = {
+		.platform_data = &mv64x60_wdt_pdata,
+	},
+};
+#endif
+
 #if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
 static struct mv64xxx_pdata mv64xxx_pdata = {
 	.hs_reg_valid	= 0,
@@ -476,6 +502,9 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = {
 #ifdef	CONFIG_I2C_MV64XXX
 	&i2c_device,
 #endif
+#ifdef	CONFIG_MV64X60_WDT
+	&wdt_device,
+#endif
 #if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
 	&mv64xxx_device,
 #endif

+ 1 - 0
drivers/Makefile

@@ -66,6 +66,7 @@ obj-y				+= i2c/
 obj-$(CONFIG_W1)		+= w1/
 obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
+obj-$(CONFIG_WATCHDOG)		+= char/watchdog/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/

+ 0 - 1
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/

+ 85 - 32
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
 #

+ 36 - 7
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

+ 490 - 0
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) ")");

+ 1 - 1
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 = {

+ 4 - 0
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;

+ 281 - 0
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)
+{
+	int ret = 0, size;
+	struct resource *res;
+
+	spin_lock_init(&io_lock);
+
+	if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
+		heartbeat = DEFAULT_HEARTBEAT;
+
+	printk(KERN_INFO MODULE_NAME
+		"DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		printk(KERN_INFO MODULE_NAME
+			"failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	size = res->end - res->start + 1;
+	wdt_mem = request_mem_region(res->start, size, pdev->name);
+
+	if (wdt_mem == NULL) {
+		printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
+		return -ENOENT;
+	}
+	wdt_base = (void __iomem *)(res->start);
+
+	ret = misc_register(&davinci_wdt_miscdev);
+	if (ret < 0) {
+		printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
+		release_resource(wdt_mem);
+		kfree(wdt_mem);
+	} else {
+		set_bit(WDT_DEVICE_INITED, &wdt_status);
+	}
+
+	return ret;
+}
+
+static int davinci_wdt_remove(struct platform_device *pdev)
+{
+	misc_deregister(&davinci_wdt_miscdev);
+	if (wdt_mem) {
+		release_resource(wdt_mem);
+		kfree(wdt_mem);
+		wdt_mem = NULL;
+	}
+	return 0;
+}
+
+static struct platform_driver platform_wdt_driver = {
+	.driver = {
+		.name = "watchdog",
+	},
+	.probe = davinci_wdt_probe,
+	.remove = davinci_wdt_remove,
+};
+
+static int __init davinci_wdt_init(void)
+{
+	return platform_driver_register(&platform_wdt_driver);
+}
+
+static void __exit davinci_wdt_exit(void)
+{
+	return platform_driver_unregister(&platform_wdt_driver);
+}
+
+module_init(davinci_wdt_init);
+module_exit(davinci_wdt_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("DaVinci Watchdog Driver");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat,
+		 "Watchdog heartbeat period in seconds from 1 to "
+		 __MODULE_STRING(MAX_HEARTBEAT) ", default "
+		 __MODULE_STRING(DEFAULT_HEARTBEAT));
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

+ 35 - 3
drivers/char/watchdog/iTCO_wdt.c

@@ -39,7 +39,12 @@
  *	82801HR  (ICH8R)     : document number 313056-002, 313057-004,
  *	82801HH  (ICH8DH)    : document number 313056-002, 313057-004,
  *	82801HO  (ICH8DO)    : document number 313056-002, 313057-004,
- *	6300ESB  (6300ESB)   : document number 300641-003
+ *	82801IB  (ICH9)      : document number 316972-001, 316973-001,
+ *	82801IR  (ICH9R)     : document number 316972-001, 316973-001,
+ *	82801IH  (ICH9DH)    : document number 316972-001, 316973-001,
+ *	6300ESB  (6300ESB)   : document number 300641-003, 300884-010,
+ *	631xESB  (631xESB)   : document number 313082-001, 313075-005,
+ *	632xESB  (632xESB)   : document number 313082-001, 313075-005
  */
 
 /*
@@ -48,8 +53,8 @@
 
 /* Module and version information */
 #define DRV_NAME        "iTCO_wdt"
-#define DRV_VERSION     "1.01"
-#define DRV_RELDATE     "21-Jan-2007"
+#define DRV_VERSION     "1.02"
+#define DRV_RELDATE     "26-Jul-2007"
 #define PFX		DRV_NAME ": "
 
 /* Includes */
@@ -92,6 +97,10 @@ enum iTCO_chipsets {
 	TCO_ICH8,	/* ICH8 & ICH8R */
 	TCO_ICH8DH,	/* ICH8DH */
 	TCO_ICH8DO,	/* ICH8DO */
+	TCO_ICH9,	/* ICH9 */
+	TCO_ICH9R,	/* ICH9R */
+	TCO_ICH9DH,	/* ICH9DH */
+	TCO_631XESB,	/* 631xESB/632xESB */
 };
 
 static struct {
@@ -118,6 +127,10 @@ static struct {
 	{"ICH8 or ICH8R", 2},
 	{"ICH8DH", 2},
 	{"ICH8DO", 2},
+	{"ICH9", 2},
+	{"ICH9R", 2},
+	{"ICH9DH", 2},
+	{"631xESB/632xESB", 2},
 	{NULL,0}
 };
 
@@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8    },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH  },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO  },
+	{ PCI_VENDOR_ID_INTEL, 0x2918,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9    },
+	{ PCI_VENDOR_ID_INTEL, 0x2916,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R    },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH    },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2671,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2672,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2673,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2674,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2675,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2676,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2677,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2678,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x2679,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267a,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267b,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267c,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267d,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267e,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
+	{ PCI_VENDOR_ID_INTEL, 0x267f,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB },
 	{ 0, },			/* End of list */
 };
 MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);

+ 1 - 0
drivers/char/watchdog/machzwd.c

@@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		break;
 
 	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
 		return put_user(0, p);
 
 	case WDIOC_KEEPALIVE:

+ 5 - 0
drivers/char/watchdog/mixcomwd.c

@@ -215,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
 				return -EFAULT;
 			}
 			break;
+		case WDIOC_GETBOOTSTATUS:
+			if (copy_to_user(p, &status, sizeof(int))) {
+				return -EFAULT;
+			}
+			break;
 		case WDIOC_GETSUPPORT:
 			if (copy_to_user(argp, &ident, sizeof(ident))) {
 				return -EFAULT;

+ 286 - 0
drivers/char/watchdog/mpc5200_wdt.c

@@ -0,0 +1,286 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <asm/of_platform.h>
+#include <asm/uaccess.h>
+#include <asm/mpc52xx.h>
+
+
+#define GPT_MODE_WDT		(1<<15)
+#define GPT_MODE_CE		(1<<12)
+#define GPT_MODE_MS_TIMER	(0x4)
+
+
+struct mpc5200_wdt {
+	unsigned count;	/* timer ticks before watchdog kicks in */
+	long ipb_freq;
+	struct miscdevice miscdev;
+	struct resource mem;
+	struct mpc52xx_gpt __iomem *regs;
+	spinlock_t io_lock;
+};
+
+/* is_active stores wether or not the /dev/watchdog device is opened */
+static unsigned long is_active;
+
+/* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from
+ * file operations, which sucks. But there can be max 1 watchdog anyway, so...
+ */
+static struct mpc5200_wdt *wdt_global;
+
+
+/* helper to calculate timeout in timer counts */
+static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout)
+{
+	/* use biggest prescaler of 64k */
+	wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout;
+
+	if (wdt->count > 0xffff)
+		wdt->count = 0xffff;
+}
+/* return timeout in seconds (calculated from timer count) */
+static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt)
+{
+	return wdt->count * 0x10000 / wdt->ipb_freq;
+}
+
+
+/* watchdog operations */
+static int mpc5200_wdt_start(struct mpc5200_wdt *wdt)
+{
+	spin_lock(&wdt->io_lock);
+	/* disable */
+	out_be32(&wdt->regs->mode, 0);
+	/* set timeout, with maximum prescaler */
+	out_be32(&wdt->regs->count, 0x0 | wdt->count);
+	/* enable watchdog */
+	out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER);
+	spin_unlock(&wdt->io_lock);
+
+	return 0;
+}
+static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt)
+{
+	spin_lock(&wdt->io_lock);
+	/* writing A5 to OCPW resets the watchdog */
+	out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode)));
+	spin_unlock(&wdt->io_lock);
+	return 0;
+}
+static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt)
+{
+	spin_lock(&wdt->io_lock);
+	/* disable */
+	out_be32(&wdt->regs->mode, 0);
+	spin_unlock(&wdt->io_lock);
+	return 0;
+}
+
+
+/* file operations */
+static ssize_t mpc5200_wdt_write(struct file *file, const char *data,
+		size_t len, loff_t *ppos)
+{
+	struct mpc5200_wdt *wdt = file->private_data;
+	mpc5200_wdt_ping(wdt);
+	return 0;
+}
+static struct watchdog_info mpc5200_wdt_info = {
+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+	.identity	= "mpc5200 watchdog on GPT0",
+};
+static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	struct mpc5200_wdt *wdt = file->private_data;
+	int __user *data = (int __user *)arg;
+	int timeout;
+	int ret = 0;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = copy_to_user(data, &mpc5200_wdt_info,
+			sizeof(mpc5200_wdt_info));
+		if (ret)
+			ret = -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(0, data);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		mpc5200_wdt_ping(wdt);
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		ret = get_user(timeout, data);
+		if (ret)
+			break;
+		mpc5200_wdt_set_timeout(wdt, timeout);
+		mpc5200_wdt_start(wdt);
+		/* fall through and return the timeout */
+
+	case WDIOC_GETTIMEOUT:
+		timeout = mpc5200_wdt_get_timeout(wdt);
+		ret = put_user(timeout, data);
+		break;
+
+	default:
+		ret = -ENOTTY;
+	}
+	return ret;
+}
+static int mpc5200_wdt_open(struct inode *inode, struct file *file)
+{
+	/* /dev/watchdog can only be opened once */
+	if (test_and_set_bit(0, &is_active))
+		return -EBUSY;
+
+	/* Set and activate the watchdog */
+	mpc5200_wdt_set_timeout(wdt_global, 30);
+	mpc5200_wdt_start(wdt_global);
+	file->private_data = wdt_global;
+	return nonseekable_open(inode, file);
+}
+static int mpc5200_wdt_release(struct inode *inode, struct file *file)
+{
+#if WATCHDOG_NOWAYOUT == 0
+	struct mpc5200_wdt *wdt = file->private_data;
+	mpc5200_wdt_stop(wdt);
+	wdt->count = 0;		/* == disabled */
+#endif
+	clear_bit(0, &is_active);
+	return 0;
+}
+
+static struct file_operations mpc5200_wdt_fops = {
+	.owner	= THIS_MODULE,
+	.write	= mpc5200_wdt_write,
+	.ioctl	= mpc5200_wdt_ioctl,
+	.open	= mpc5200_wdt_open,
+	.release = mpc5200_wdt_release,
+};
+
+/* module operations */
+static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct mpc5200_wdt *wdt;
+	int err;
+	const void *has_wdt;
+	int size;
+
+	has_wdt = of_get_property(op->node, "has-wdt", NULL);
+	if (!has_wdt)
+		return -ENODEV;
+
+	wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	wdt->ipb_freq = mpc52xx_find_ipb_freq(op->node);
+
+	err = of_address_to_resource(op->node, 0, &wdt->mem);
+	if (err)
+		goto out_free;
+	size = wdt->mem.end - wdt->mem.start + 1;
+	if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) {
+		err = -ENODEV;
+		goto out_free;
+	}
+	wdt->regs = ioremap(wdt->mem.start, size);
+	if (!wdt->regs) {
+		err = -ENODEV;
+		goto out_release;
+	}
+
+	dev_set_drvdata(&op->dev, wdt);
+	spin_lock_init(&wdt->io_lock);
+
+	wdt->miscdev = (struct miscdevice) {
+		.minor	= WATCHDOG_MINOR,
+		.name	= "watchdog",
+		.fops	= &mpc5200_wdt_fops,
+		.parent = &op->dev,
+	};
+	wdt_global = wdt;
+	err = misc_register(&wdt->miscdev);
+	if (!err)
+		return 0;
+
+	iounmap(wdt->regs);
+ out_release:
+	release_mem_region(wdt->mem.start, size);
+ out_free:
+	kfree(wdt);
+	return err;
+}
+
+static int mpc5200_wdt_remove(struct of_device *op)
+{
+	struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
+
+	mpc5200_wdt_stop(wdt);
+	misc_deregister(&wdt->miscdev);
+	iounmap(wdt->regs);
+	release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1);
+	kfree(wdt);
+
+	return 0;
+}
+static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state)
+{
+	struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
+	mpc5200_wdt_stop(wdt);
+	return 0;
+}
+static int mpc5200_wdt_resume(struct of_device *op)
+{
+	struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
+	if (wdt->count)
+		mpc5200_wdt_start(wdt);
+	return 0;
+}
+static int mpc5200_wdt_shutdown(struct of_device *op)
+{
+	struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev);
+	mpc5200_wdt_stop(wdt);
+	return 0;
+}
+
+static struct of_device_id mpc5200_wdt_match[] = {
+	{ .compatible = "mpc5200-gpt", },
+	{},
+};
+static struct of_platform_driver mpc5200_wdt_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "mpc5200-gpt-wdt",
+	.match_table	= mpc5200_wdt_match,
+	.probe		= mpc5200_wdt_probe,
+	.remove		= mpc5200_wdt_remove,
+	.suspend	= mpc5200_wdt_suspend,
+	.resume		= mpc5200_wdt_resume,
+	.shutdown	= mpc5200_wdt_shutdown,
+};
+
+
+static int __init mpc5200_wdt_init(void)
+{
+	return of_register_platform_driver(&mpc5200_wdt_driver);
+}
+
+static void __exit mpc5200_wdt_exit(void)
+{
+	of_unregister_platform_driver(&mpc5200_wdt_driver);
+}
+
+module_init(mpc5200_wdt_init);
+module_exit(mpc5200_wdt_exit);
+
+MODULE_AUTHOR("Domen Puncer <domen.puncer@telargo.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

+ 3 - 0
drivers/char/watchdog/mpc83xx_wdt.c

@@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, p);
 	case WDIOC_KEEPALIVE:
 		mpc83xx_wdt_keepalive();
 		return 0;

+ 1 - 1
drivers/char/watchdog/mpc8xx_wdt.c

@@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
 	m8xx_wdt_reset();
 	mpc8xx_wdt_handler_disable();
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int mpc8xx_wdt_release(struct inode *inode, struct file *file)

+ 1 - 0
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
 			mtx1_wdt_reset();
 			break;
 		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
 			if ( copy_to_user(argp, &value, sizeof(int)) )
 				return -EFAULT;
 			break;

+ 140 - 78
drivers/char/watchdog/mv64x60_wdt.c

@@ -23,61 +23,101 @@
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 
-#include <asm/mv64x60.h>
+#include <linux/mv643xx.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-/* MV64x60 WDC (config) register access definitions */
-#define MV64x60_WDC_CTL1_MASK	(3 << 24)
-#define MV64x60_WDC_CTL1(val)	((val & 3) << 24)
-#define MV64x60_WDC_CTL2_MASK	(3 << 26)
-#define MV64x60_WDC_CTL2(val)	((val & 3) << 26)
+#define MV64x60_WDT_WDC_OFFSET	0
+
+/*
+ * The watchdog configuration register contains a pair of 2-bit fields,
+ *   1.  a reload field, bits 27-26, which triggers a reload of
+ *       the countdown register, and
+ *   2.  an enable field, bits 25-24, which toggles between
+ *       enabling and disabling the watchdog timer.
+ * Bit 31 is a read-only field which indicates whether the
+ * watchdog timer is currently enabled.
+ *
+ * The low 24 bits contain the timer reload value.
+ */
+#define MV64x60_WDC_ENABLE_SHIFT	24
+#define MV64x60_WDC_SERVICE_SHIFT	26
+#define MV64x60_WDC_ENABLED_SHIFT	31
+
+#define MV64x60_WDC_ENABLED_TRUE	1
+#define MV64x60_WDC_ENABLED_FALSE	0
 
 /* Flags bits */
 #define MV64x60_WDOG_FLAG_OPENED	0
-#define MV64x60_WDOG_FLAG_ENABLED	1
 
 static unsigned long wdt_flags;
 static int wdt_status;
-static void __iomem *mv64x60_regs;
+static void __iomem *mv64x60_wdt_regs;
 static int mv64x60_wdt_timeout;
+static int mv64x60_wdt_count;
+static unsigned int bus_clk;
+static char expect_close;
+static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static void mv64x60_wdt_reg_write(u32 val)
+static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
 {
-	/* Allow write only to CTL1 / CTL2 fields, retaining values in
-	 * other fields.
-	 */
-	u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
-	data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
-	data |= val;
-	writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+	u32 data;
+	u32 enabled;
+	int ret = 0;
+
+	spin_lock(&mv64x60_wdt_spinlock);
+	data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
+	enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1;
+
+	/* only toggle the requested field if enabled state matches predicate */
+	if ((enabled ^ enabled_predicate) == 0) {
+		/* We write a 1, then a 2 -- to the appropriate field */
+		data = (1 << field_shift) | mv64x60_wdt_count;
+		writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
+
+		data = (2 << field_shift) | mv64x60_wdt_count;
+		writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET);
+		ret = 1;
+	}
+	spin_unlock(&mv64x60_wdt_spinlock);
+
+	return ret;
 }
 
 static void mv64x60_wdt_service(void)
 {
-	/* Write 01 followed by 10 to CTL2 */
-	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
-	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+	mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
+			       MV64x60_WDC_SERVICE_SHIFT);
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+	if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE,
+				   MV64x60_WDC_ENABLE_SHIFT)) {
+		mv64x60_wdt_service();
+		printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+	}
 }
 
 static void mv64x60_wdt_handler_disable(void)
 {
-	if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
-		/* Write 01 followed by 10 to CTL1 */
-		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
-		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+	if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
+				   MV64x60_WDC_ENABLE_SHIFT))
 		printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
-	}
 }
 
-static void mv64x60_wdt_handler_enable(void)
+static void mv64x60_wdt_set_timeout(unsigned int timeout)
 {
-	if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
-		/* Write 01 followed by 10 to CTL1 */
-		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
-		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
-		printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
-	}
+	/* maximum bus cycle count is 0xFFFFFFFF */
+	if (timeout > 0xFFFFFFFF / bus_clk)
+		timeout = 0xFFFFFFFF / bus_clk;
+
+	mv64x60_wdt_count = timeout * bus_clk >> 8;
+	mv64x60_wdt_timeout = timeout;
 }
 
 static 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)
 	if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
 		return -EBUSY;
 
-	mv64x60_wdt_service();
-	mv64x60_wdt_handler_enable();
+	if (nowayout)
+		__module_get(THIS_MODULE);
 
-	nonseekable_open(inode, file);
+	mv64x60_wdt_handler_enable();
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int mv64x60_wdt_release(struct inode *inode, struct file *file)
 {
-	mv64x60_wdt_service();
-
-#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
-	mv64x60_wdt_handler_disable();
-#endif
+	if (expect_close == 42)
+		mv64x60_wdt_handler_disable();
+	else {
+		printk(KERN_CRIT
+		       "mv64x60_wdt: unexpected close, not stopping timer!\n");
+		mv64x60_wdt_service();
+	}
+	expect_close = 0;
 
 	clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
 
@@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
 static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
 				 size_t len, loff_t * ppos)
 {
-	if (len)
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			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;
+			}
+		}
 		mv64x60_wdt_service();
+	}
 
 	return len;
 }
@@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
 			     unsigned int cmd, unsigned long arg)
 {
 	int timeout;
+	int options;
 	void __user *argp = (void __user *)arg;
 	static struct watchdog_info info = {
-		.options = WDIOF_KEEPALIVEPING,
+		.options =	WDIOF_SETTIMEOUT	|
+				WDIOF_MAGICCLOSE	|
+				WDIOF_KEEPALIVEPING,
 		.firmware_version = 0,
 		.identity = "MV64x60 watchdog",
 	};
@@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
 		return -EOPNOTSUPP;
 
 	case WDIOC_SETOPTIONS:
-		return -EOPNOTSUPP;
+		if (get_user(options, (int __user *)argp))
+			return -EFAULT;
+
+		if (options & WDIOS_DISABLECARD)
+			mv64x60_wdt_handler_disable();
+
+		if (options & WDIOS_ENABLECARD)
+			mv64x60_wdt_handler_enable();
+		break;
 
 	case WDIOC_KEEPALIVE:
 		mv64x60_wdt_service();
@@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
 		break;
 
 	case WDIOC_SETTIMEOUT:
-		return -EOPNOTSUPP;
+		if (get_user(timeout, (int __user *)argp))
+			return -EFAULT;
+		mv64x60_wdt_set_timeout(timeout);
+		/* Fall through */
 
 	case WDIOC_GETTIMEOUT:
-		timeout = mv64x60_wdt_timeout * HZ;
-		if (put_user(timeout, (int __user *)argp))
+		if (put_user(mv64x60_wdt_timeout, (int __user *)argp))
 			return -EFAULT;
 		break;
 
@@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = {
 static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
 {
 	struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
-	int bus_clk = 133;
+	struct resource *r;
+	int timeout = 10;
 
-	mv64x60_wdt_timeout = 10;
+	bus_clk = 133;			/* in MHz */
 	if (pdata) {
-		mv64x60_wdt_timeout = pdata->timeout;
+		timeout = pdata->timeout;
 		bus_clk = pdata->bus_clk;
 	}
 
-	mv64x60_regs = mv64x60_get_bridge_vbase();
+	/* Since bus_clk is truncated MHz, actual frequency could be
+	 * up to 1MHz higher.  Round up, since it's better to time out
+	 * too late than too soon.
+	 */
+	bus_clk++;
+	bus_clk *= 1000000;		/* convert to Hz */
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
 
-	writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
-	       mv64x60_regs + MV64x60_WDT_WDC);
+	mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1);
+	if (mv64x60_wdt_regs == NULL)
+		return -ENOMEM;
+
+	mv64x60_wdt_set_timeout(timeout);
+
+	mv64x60_wdt_handler_disable();	/* in case timer was already running */
 
 	return misc_register(&mv64x60_wdt_miscdev);
 }
@@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&mv64x60_wdt_miscdev);
 
-	mv64x60_wdt_service();
 	mv64x60_wdt_handler_disable();
 
+	iounmap(mv64x60_wdt_regs);
+
 	return 0;
 }
 
@@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = {
 	},
 };
 
-static struct platform_device *mv64x60_wdt_dev;
-
 static int __init mv64x60_wdt_init(void)
 {
-	int ret;
-
 	printk(KERN_INFO "MV64x60 watchdog driver\n");
 
-	mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1);
-	if (!mv64x60_wdt_dev) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = platform_device_add(mv64x60_wdt_dev);
-	if (ret) {
-		platform_device_put(mv64x60_wdt_dev);
-		goto out;
-	}
-
-	ret = platform_driver_register(&mv64x60_wdt_driver);
-	if (ret) {
-		platform_device_unregister(mv64x60_wdt_dev);
-		goto out;
-	}
-
- out:
-	return ret;
+	return platform_driver_register(&mv64x60_wdt_driver);
 }
 
 static void __exit mv64x60_wdt_exit(void)
 {
 	platform_driver_unregister(&mv64x60_wdt_driver);
-	platform_device_unregister(mv64x60_wdt_dev);
 }
 
 module_init(mv64x60_wdt_init);

+ 2 - 2
drivers/char/watchdog/omap_wdt.c

@@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
 
 	omap_wdt_set_timeout();
 	omap_wdt_enable();
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int omap_wdt_release(struct inode *inode, struct file *file)
@@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file,
 
 	switch (cmd) {
 	default:
-		return -ENOIOCTLCMD;
+		return -ENOTTY;
 	case WDIOC_GETSUPPORT:
 		return copy_to_user((struct watchdog_info __user *)arg, &ident,
 				sizeof(ident));

+ 3 - 3
drivers/char/watchdog/s3c2410_wdt.c

@@ -52,10 +52,10 @@
 
 #include <asm/arch/map.h>
 
-#undef S3C24XX_VA_WATCHDOG
-#define S3C24XX_VA_WATCHDOG (0)
+#undef S3C_VA_WATCHDOG
+#define S3C_VA_WATCHDOG (0)
 
-#include <asm/arch/regs-watchdog.h>
+#include <asm/plat-s3c/regs-watchdog.h>
 
 #define PFX "s3c2410-wdt: "
 

+ 1 - 2
drivers/char/watchdog/sa1100_wdt.c

@@ -45,7 +45,6 @@ static int boot_status;
  */
 static int sa1100dog_open(struct inode *inode, struct file *file)
 {
-	nonseekable_open(inode, file);
 	if (test_and_set_bit(1,&sa1100wdt_users))
 		return -EBUSY;
 
@@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
 	OSSR = OSSR_M3;
 	OWER = OWER_WME;
 	OIER |= OIER_E3;
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 /*

+ 1 - 3
drivers/char/watchdog/sbc60xxwdt.c

@@ -191,8 +191,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou
 
 static int fop_open(struct inode * inode, struct file * file)
 {
-	nonseekable_open(inode, file);
-
 	/* Just in case we're already talking to someone... */
 	if(test_and_set_bit(0, &wdt_is_open))
 		return -EBUSY;
@@ -202,7 +200,7 @@ static int fop_open(struct inode * inode, struct file * file)
 
 	/* Good, fire up the show */
 	wdt_startup();
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int fop_close(struct inode * inode, struct file * file)

+ 1 - 3
drivers/char/watchdog/sc1200wdt.c

@@ -150,8 +150,6 @@ static inline int sc1200wdt_status(void)
 
 static int sc1200wdt_open(struct inode *inode, struct file *file)
 {
-	nonseekable_open(inode, file);
-
 	/* allow one at a time */
 	if (down_trylock(&open_sem))
 		return -EBUSY;
@@ -162,7 +160,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file)
 	sc1200wdt_start();
 	printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 

+ 1 - 3
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
 
 static int fop_open(struct inode * inode, struct file * file)
 {
-	nonseekable_open(inode, file);
-
 	/* Just in case we're already talking to someone... */
 	if(test_and_set_bit(0, &wdt_is_open))
 		return -EBUSY;
@@ -258,7 +256,7 @@ static int fop_open(struct inode * inode, struct file * file)
 
 	/* Good, fire up the show */
 	wdt_startup();
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int fop_close(struct inode * inode, struct file * file)

+ 15 - 9
drivers/char/watchdog/w83627hf_wdt.c

@@ -4,7 +4,7 @@
  *	(c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
  *		added support for W83627THF.
  *
- *	(c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
+ *	(c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
  *
  *	Based on advantechwdt.c which is based on wdt.c.
  *	Original copyright messages:
@@ -42,7 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#define WATCHDOG_NAME "w83627hf/thf WDT"
+#define WATCHDOG_NAME "w83627hf/thf/hg WDT"
 #define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
 
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
 
 static int timeout = WATCHDOG_TIMEOUT;	/* in seconds */
 module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
@@ -78,9 +78,9 @@ w83627hf_select_wd_register(void)
 	outb_p(0x87, WDT_EFER); /* Enter extended function mode */
 	outb_p(0x87, WDT_EFER); /* Again according to manual */
 
-	outb(0x20, WDT_EFER); 	/* check chip version	*/
+	outb(0x20, WDT_EFER);	/* check chip version	*/
 	c = inb(WDT_EFDR);
-	if (c == 0x82) {	/* W83627THF 		*/
+	if (c == 0x82) {	/* W83627THF		*/
 		outb_p(0x2b, WDT_EFER); /* select GPIO3 */
 		c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
 		outb_p(0x2b, WDT_EFER);
@@ -114,11 +114,17 @@ w83627hf_init(void)
 		printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout);
 		outb_p(timeout, WDT_EFDR);    /* Write back to CRF6 */
 	}
+
 	outb_p(0xF5, WDT_EFER); /* Select CRF5 */
 	t=inb_p(WDT_EFDR);      /* read CRF5 */
 	t&=~0x0C;               /* set second mode & disable keyboard turning off watchdog */
 	outb_p(t, WDT_EFDR);    /* Write back to CRF5 */
 
+	outb_p(0xF7, WDT_EFER); /* Select CRF7 */
+	t=inb_p(WDT_EFDR);      /* read CRF7 */
+	t&=~0xC0;               /* disable keyboard & mouse turning off watchdog */
+	outb_p(t, WDT_EFDR);    /* Write back to CRF7 */
+
 	w83627hf_unselect_wd_register();
 }
 
@@ -126,7 +132,7 @@ static void
 wdt_ctrl(int timeout)
 {
 	spin_lock(&io_lock);
-	
+
 	w83627hf_select_wd_register();
 
 	outb_p(0xF6, WDT_EFER);    /* Select CRF6 */
@@ -154,7 +160,7 @@ wdt_disable(void)
 static int
 wdt_set_heartbeat(int t)
 {
-	if ((t < 1) || (t > 63))
+	if ((t < 1) || (t > 255))
 		return -EINVAL;
 
 	timeout = t;
@@ -324,11 +330,11 @@ wdt_init(void)
 
 	spin_lock_init(&io_lock);
 
-	printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n");
+	printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n");
 
 	if (wdt_set_heartbeat(timeout)) {
 		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-		printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n",
+		printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n",
 			WATCHDOG_TIMEOUT);
 	}
 

+ 0 - 8
include/asm-ppc/mv64x60.h

@@ -120,14 +120,6 @@ extern spinlock_t mv64x60_lock;
 
 #define	MV64x60_64BIT_WIN_COUNT			24
 
-/* Watchdog Platform Device, Driver Data */
-#define	MV64x60_WDT_NAME			"wdt"
-
-struct mv64x60_wdt_pdata {
-	int	timeout;	/* watchdog expiry in seconds, default 10 */
-	int	bus_clk;	/* bus clock in MHz, default 133 */
-};
-
 /*
  * Define a structure that's used to pass in config information to the
  * core routines.

+ 8 - 0
include/linux/mv643xx.h

@@ -1302,4 +1302,12 @@ struct mv643xx_eth_platform_data {
 	u8		mac_addr[6];	/* mac address if non-zero*/
 };
 
+/* Watchdog Platform Device, Driver Data */
+#define	MV64x60_WDT_NAME			"mv64x60_wdt"
+
+struct mv64x60_wdt_pdata {
+	int	timeout;	/* watchdog expiry in seconds, default 10 */
+	int	bus_clk;	/* bus clock in MHz, default 133 */
+};
+
 #endif /* __ASM_MV643XX_H */