mv watchdog tree under drivers
authorWim Van Sebroeck <wim@iguana.be>
Fri, 17 Aug 2007 08:38:02 +0000 (08:38 +0000)
committerWim Van Sebroeck <wim@iguana.be>
Thu, 18 Oct 2007 10:39:03 +0000 (10:39 +0000)
move watchdog tree from drivers/char/watchdog to drivers/watchdog.

Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
127 files changed:
drivers/Kconfig
drivers/Makefile
drivers/char/Kconfig
drivers/char/watchdog/Kconfig [deleted file]
drivers/char/watchdog/Makefile [deleted file]
drivers/char/watchdog/acquirewdt.c [deleted file]
drivers/char/watchdog/advantechwdt.c [deleted file]
drivers/char/watchdog/alim1535_wdt.c [deleted file]
drivers/char/watchdog/alim7101_wdt.c [deleted file]
drivers/char/watchdog/at32ap700x_wdt.c [deleted file]
drivers/char/watchdog/at91rm9200_wdt.c [deleted file]
drivers/char/watchdog/bfin_wdt.c [deleted file]
drivers/char/watchdog/booke_wdt.c [deleted file]
drivers/char/watchdog/cpu5wdt.c [deleted file]
drivers/char/watchdog/davinci_wdt.c [deleted file]
drivers/char/watchdog/ep93xx_wdt.c [deleted file]
drivers/char/watchdog/eurotechwdt.c [deleted file]
drivers/char/watchdog/i6300esb.c [deleted file]
drivers/char/watchdog/iTCO_vendor_support.c [deleted file]
drivers/char/watchdog/iTCO_wdt.c [deleted file]
drivers/char/watchdog/ib700wdt.c [deleted file]
drivers/char/watchdog/ibmasr.c [deleted file]
drivers/char/watchdog/indydog.c [deleted file]
drivers/char/watchdog/iop_wdt.c [deleted file]
drivers/char/watchdog/ixp2000_wdt.c [deleted file]
drivers/char/watchdog/ixp4xx_wdt.c [deleted file]
drivers/char/watchdog/ks8695_wdt.c [deleted file]
drivers/char/watchdog/machzwd.c [deleted file]
drivers/char/watchdog/mixcomwd.c [deleted file]
drivers/char/watchdog/mpc5200_wdt.c [deleted file]
drivers/char/watchdog/mpc83xx_wdt.c [deleted file]
drivers/char/watchdog/mpc8xx_wdt.c [deleted file]
drivers/char/watchdog/mpcore_wdt.c [deleted file]
drivers/char/watchdog/mtx-1_wdt.c [deleted file]
drivers/char/watchdog/mv64x60_wdt.c [deleted file]
drivers/char/watchdog/omap_wdt.c [deleted file]
drivers/char/watchdog/omap_wdt.h [deleted file]
drivers/char/watchdog/pc87413_wdt.c [deleted file]
drivers/char/watchdog/pcwd.c [deleted file]
drivers/char/watchdog/pcwd_pci.c [deleted file]
drivers/char/watchdog/pcwd_usb.c [deleted file]
drivers/char/watchdog/pnx4008_wdt.c [deleted file]
drivers/char/watchdog/rm9k_wdt.c [deleted file]
drivers/char/watchdog/s3c2410_wdt.c [deleted file]
drivers/char/watchdog/sa1100_wdt.c [deleted file]
drivers/char/watchdog/sbc60xxwdt.c [deleted file]
drivers/char/watchdog/sbc8360.c [deleted file]
drivers/char/watchdog/sbc_epx_c3.c [deleted file]
drivers/char/watchdog/sc1200wdt.c [deleted file]
drivers/char/watchdog/sc520_wdt.c [deleted file]
drivers/char/watchdog/scx200_wdt.c [deleted file]
drivers/char/watchdog/shwdt.c [deleted file]
drivers/char/watchdog/smsc37b787_wdt.c [deleted file]
drivers/char/watchdog/softdog.c [deleted file]
drivers/char/watchdog/w83627hf_wdt.c [deleted file]
drivers/char/watchdog/w83697hf_wdt.c [deleted file]
drivers/char/watchdog/w83877f_wdt.c [deleted file]
drivers/char/watchdog/w83977f_wdt.c [deleted file]
drivers/char/watchdog/wafer5823wdt.c [deleted file]
drivers/char/watchdog/wd501p.h [deleted file]
drivers/char/watchdog/wdrtas.c [deleted file]
drivers/char/watchdog/wdt.c [deleted file]
drivers/char/watchdog/wdt285.c [deleted file]
drivers/char/watchdog/wdt977.c [deleted file]
drivers/char/watchdog/wdt_pci.c [deleted file]
drivers/watchdog/Kconfig [new file with mode: 0644]
drivers/watchdog/Makefile [new file with mode: 0644]
drivers/watchdog/acquirewdt.c [new file with mode: 0644]
drivers/watchdog/advantechwdt.c [new file with mode: 0644]
drivers/watchdog/alim1535_wdt.c [new file with mode: 0644]
drivers/watchdog/alim7101_wdt.c [new file with mode: 0644]
drivers/watchdog/at32ap700x_wdt.c [new file with mode: 0644]
drivers/watchdog/at91rm9200_wdt.c [new file with mode: 0644]
drivers/watchdog/bfin_wdt.c [new file with mode: 0644]
drivers/watchdog/booke_wdt.c [new file with mode: 0644]
drivers/watchdog/cpu5wdt.c [new file with mode: 0644]
drivers/watchdog/davinci_wdt.c [new file with mode: 0644]
drivers/watchdog/ep93xx_wdt.c [new file with mode: 0644]
drivers/watchdog/eurotechwdt.c [new file with mode: 0644]
drivers/watchdog/i6300esb.c [new file with mode: 0644]
drivers/watchdog/iTCO_vendor_support.c [new file with mode: 0644]
drivers/watchdog/iTCO_wdt.c [new file with mode: 0644]
drivers/watchdog/ib700wdt.c [new file with mode: 0644]
drivers/watchdog/ibmasr.c [new file with mode: 0644]
drivers/watchdog/indydog.c [new file with mode: 0644]
drivers/watchdog/iop_wdt.c [new file with mode: 0644]
drivers/watchdog/ixp2000_wdt.c [new file with mode: 0644]
drivers/watchdog/ixp4xx_wdt.c [new file with mode: 0644]
drivers/watchdog/ks8695_wdt.c [new file with mode: 0644]
drivers/watchdog/machzwd.c [new file with mode: 0644]
drivers/watchdog/mixcomwd.c [new file with mode: 0644]
drivers/watchdog/mpc5200_wdt.c [new file with mode: 0644]
drivers/watchdog/mpc83xx_wdt.c [new file with mode: 0644]
drivers/watchdog/mpc8xx_wdt.c [new file with mode: 0644]
drivers/watchdog/mpcore_wdt.c [new file with mode: 0644]
drivers/watchdog/mtx-1_wdt.c [new file with mode: 0644]
drivers/watchdog/mv64x60_wdt.c [new file with mode: 0644]
drivers/watchdog/omap_wdt.c [new file with mode: 0644]
drivers/watchdog/omap_wdt.h [new file with mode: 0644]
drivers/watchdog/pc87413_wdt.c [new file with mode: 0644]
drivers/watchdog/pcwd.c [new file with mode: 0644]
drivers/watchdog/pcwd_pci.c [new file with mode: 0644]
drivers/watchdog/pcwd_usb.c [new file with mode: 0644]
drivers/watchdog/pnx4008_wdt.c [new file with mode: 0644]
drivers/watchdog/rm9k_wdt.c [new file with mode: 0644]
drivers/watchdog/s3c2410_wdt.c [new file with mode: 0644]
drivers/watchdog/sa1100_wdt.c [new file with mode: 0644]
drivers/watchdog/sbc60xxwdt.c [new file with mode: 0644]
drivers/watchdog/sbc8360.c [new file with mode: 0644]
drivers/watchdog/sbc_epx_c3.c [new file with mode: 0644]
drivers/watchdog/sc1200wdt.c [new file with mode: 0644]
drivers/watchdog/sc520_wdt.c [new file with mode: 0644]
drivers/watchdog/scx200_wdt.c [new file with mode: 0644]
drivers/watchdog/shwdt.c [new file with mode: 0644]
drivers/watchdog/smsc37b787_wdt.c [new file with mode: 0644]
drivers/watchdog/softdog.c [new file with mode: 0644]
drivers/watchdog/w83627hf_wdt.c [new file with mode: 0644]
drivers/watchdog/w83697hf_wdt.c [new file with mode: 0644]
drivers/watchdog/w83877f_wdt.c [new file with mode: 0644]
drivers/watchdog/w83977f_wdt.c [new file with mode: 0644]
drivers/watchdog/wafer5823wdt.c [new file with mode: 0644]
drivers/watchdog/wd501p.h [new file with mode: 0644]
drivers/watchdog/wdrtas.c [new file with mode: 0644]
drivers/watchdog/wdt.c [new file with mode: 0644]
drivers/watchdog/wdt285.c [new file with mode: 0644]
drivers/watchdog/wdt977.c [new file with mode: 0644]
drivers/watchdog/wdt_pci.c [new file with mode: 0644]

index 4fb134d50da731e96ce25aef47c3f3b8c21f45f1..34f40ea0ba60a3a4d886e7aad341d59789d4d11a 100644 (file)
@@ -58,6 +58,8 @@ source "drivers/power/Kconfig"
 
 source "drivers/hwmon/Kconfig"
 
+source "drivers/watchdog/Kconfig"
+
 source "drivers/ssb/Kconfig"
 
 source "drivers/mfd/Kconfig"
index 174c27eb443032f06ad3b8a61c7410bd6f0d4566..d2dc01cc73e7cd98c511003e66274c2299650e76 100644 (file)
@@ -66,7 +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_WATCHDOG)         += watchdog/
 obj-$(CONFIG_PHONE)            += telephony/
 obj-$(CONFIG_MD)               += md/
 obj-$(CONFIG_BT)               += bluetooth/
index 204d53e506de40af3d37d42e2a1030dbdda323d0..69f85185478272b62e25f68cb1c5a0563e9f56e4 100644 (file)
@@ -649,8 +649,6 @@ config HVCS
 
 source "drivers/char/ipmi/Kconfig"
 
-source "drivers/char/watchdog/Kconfig"
-
 config DS1620
        tristate "NetWinder thermometer support"
        depends on ARCH_NETWINDER
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
deleted file mode 100644 (file)
index 37bddc1..0000000
+++ /dev/null
@@ -1,853 +0,0 @@
-#
-# Watchdog device configuration
-#
-
-menuconfig WATCHDOG
-       bool "Watchdog Timer Support"
-       ---help---
-         If you say Y here (and to one of the following options) and create a
-         character special file /dev/watchdog with major number 10 and minor
-         number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
-         subsequently opening the file and then failing to write to it for
-         longer than 1 minute will result in rebooting the machine. This
-         could be useful for a networked machine that needs to come back
-         on-line as fast as possible after a lock-up. There's both a watchdog
-         implementation entirely in software (which can sometimes fail to
-         reboot the machine) and a driver for hardware watchdog boards, which
-         are more robust and can also keep track of the temperature inside
-         your computer. For details, read <file:Documentation/watchdog/watchdog.txt>
-         in the kernel source.
-
-         The watchdog is usually used together with the watchdog daemon
-         which is available from
-         <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
-         also monitor NFS connections and can reboot the machine when the process
-         table is full.
-
-         If unsure, say N.
-
-if WATCHDOG
-
-config WATCHDOG_NOWAYOUT
-       bool "Disable watchdog shutdown on close"
-       help
-         The default watchdog behaviour (which you get if you say N here) is
-         to stop the timer if the process managing it closes the file
-         /dev/watchdog. It's always remotely possible that this process might
-         get killed. If you say Y here, the watchdog cannot be stopped once
-         it has been started.
-
-#
-# General Watchdog drivers
-#
-
-comment "Watchdog Device Drivers"
-
-# Architecture Independent
-
-config SOFT_WATCHDOG
-       tristate "Software watchdog"
-       help
-         A software monitoring watchdog. This will fail to reboot your system
-         from some situations that the hardware watchdog will recover
-         from. Equally it's a lot cheaper to install.
-
-         To compile this driver as a module, choose M here: the
-         module will be called softdog.
-
-# ALPHA Architecture
-
-# ARM Architecture
-
-config AT91RM9200_WATCHDOG
-       tristate "AT91RM9200 watchdog"
-       depends on ARCH_AT91RM9200
-       help
-         Watchdog timer embedded into AT91RM9200 chips. This will reboot your
-         system when the timeout is reached.
-
-config 21285_WATCHDOG
-       tristate "DC21285 watchdog"
-       depends on FOOTBRIDGE
-       help
-         The Intel Footbridge chip contains a built-in watchdog circuit. Say Y
-         here if you wish to use this. Alternatively say M to compile the
-         driver as a module, which will be called wdt285.
-
-         This driver does not work on all machines. In particular, early CATS
-         boards have hardware problems that will cause the machine to simply
-         lock up if the watchdog fires.
-
-         "If in doubt, leave it out" - say N.
-
-config 977_WATCHDOG
-       tristate "NetWinder WB83C977 watchdog"
-       depends on FOOTBRIDGE && ARCH_NETWINDER
-       help
-         Say Y here to include support for the WB977 watchdog included in
-         NetWinder machines. Alternatively say M to compile the driver as
-         a module, which will be called wdt977.
-
-         Not sure? It's safe to say N.
-
-config IXP2000_WATCHDOG
-       tristate "IXP2000 Watchdog"
-       depends on ARCH_IXP2000
-       help
-         Say Y here if to include support for the watchdog timer
-         in the Intel IXP2000(2400, 2800, 2850) network processors.
-         This driver can be built as a module by choosing M. The module
-         will be called ixp2000_wdt.
-
-         Say N if you are unsure.
-
-config IXP4XX_WATCHDOG
-       tristate "IXP4xx Watchdog"
-       depends on ARCH_IXP4XX
-       help
-         Say Y here if to include support for the watchdog timer
-         in the Intel IXP4xx network processors. This driver can
-         be built as a module by choosing M. The module will
-         be called ixp4xx_wdt.
-
-         Note: The internal IXP4xx watchdog does a soft CPU reset
-         which doesn't reset any peripherals. There are circumstances
-         where the watchdog will fail to reset the board correctly
-         (e.g., if the boot ROM is in an unreadable state).
-
-         Say N if you are unsure.
-
-config KS8695_WATCHDOG
-       tristate "KS8695 watchdog"
-       depends on ARCH_KS8695
-       help
-         Watchdog timer embedded into KS8695 processor. This will reboot your
-         system when the timeout is reached.
-
-config S3C2410_WATCHDOG
-       tristate "S3C2410 Watchdog"
-       depends on ARCH_S3C2410
-       help
-         Watchdog timer block in the Samsung S3C2410 chips. This will
-         reboot the system when the timer expires with the watchdog
-         enabled.
-
-         The driver is limited by the speed of the system's PCLK
-         signal, so with reasonably fast systems (PCLK around 50-66MHz)
-         then watchdog intervals of over approximately 20seconds are
-         unavailable.
-
-         The driver can be built as a module by choosing M, and will
-         be called s3c2410_wdt
-
-config SA1100_WATCHDOG
-       tristate "SA1100/PXA2xx watchdog"
-       depends on ARCH_SA1100 || ARCH_PXA
-       help
-         Watchdog timer embedded into SA11x0 and PXA2xx chips. This will
-         reboot your system when timeout is reached.
-
-         NOTE: once enabled, this timer cannot be disabled.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sa1100_wdt.
-
-config MPCORE_WATCHDOG
-       tristate "MPcore watchdog"
-       depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS
-       help
-         Watchdog timer embedded into the MPcore system.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mpcore_wdt.
-
-config EP93XX_WATCHDOG
-       tristate "EP93xx Watchdog"
-       depends on ARCH_EP93XX
-       help
-         Say Y here if to include support for the watchdog timer
-         embedded in the Cirrus Logic EP93xx family of devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ep93xx_wdt.
-
-config OMAP_WATCHDOG
-       tristate "OMAP Watchdog"
-       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
-       help
-         Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
-         enable the OMAP1610/OMAP1710 watchdog timer.
-
-config PNX4008_WATCHDOG
-       tristate "PNX4008 Watchdog"
-       depends on ARCH_PNX4008
-       help
-         Say Y here if to include support for the watchdog timer
-         in the PNX4008 processor.
-         This driver can be built as a module by choosing M. The module
-         will be called pnx4008_wdt.
-
-         Say N if you are unsure.
-
-config IOP_WATCHDOG
-       tristate "IOP Watchdog"
-       depends on PLAT_IOP
-       select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
-       help
-         Say Y here if to include support for the watchdog timer
-         in the Intel IOP3XX & IOP13XX I/O Processors.  This driver can
-         be built as a module by choosing M. The module will
-         be called iop_wdt.
-
-         Note: The IOP13XX watchdog does an Internal Bus Reset which will
-         affect both cores and the peripherals of the IOP.  The ATU-X
-         and/or ATUe configuration registers will remain intact, but if
-         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 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
-       tristate "Acquire SBC Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on Single Board
-         Computers produced by Acquire Inc (and others). This watchdog
-         simply watches your kernel to make sure it doesn't freeze, and if
-         it does, it reboots your computer after a certain amount of time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called acquirewdt.
-
-         Most people will say N.
-
-config ADVANTECH_WDT
-       tristate "Advantech SBC Watchdog Timer"
-       depends on X86
-       help
-         If you are configuring a Linux kernel for the Advantech single-board
-         computer, say `Y' here to support its built-in watchdog timer
-         feature. More information can be found at
-         <http://www.advantech.com.tw/products/>
-
-config ALIM1535_WDT
-       tristate "ALi M1535 PMU Watchdog Timer"
-       depends on X86 && PCI
-       ---help---
-         This is the driver for the hardware watchdog on the ALi M1535 PMU.
-
-         To compile this driver as a module, choose M here: the
-         module will be called alim1535_wdt.
-
-         Most people will say N.
-
-config ALIM7101_WDT
-       tristate "ALi M7101 PMU Computer Watchdog"
-       depends on X86 && PCI
-       help
-         This is the driver for the hardware watchdog on the ALi M7101 PMU
-         as used in the x86 Cobalt servers.
-
-         To compile this driver as a module, choose M here: the
-         module will be called alim7101_wdt.
-
-         Most people will say N.
-
-config SC520_WDT
-       tristate "AMD Elan SC520 processor Watchdog"
-       depends on X86
-       help
-         This is the driver for the hardware watchdog built in to the
-         AMD "Elan" SC520 microcomputer commonly used in embedded systems.
-         This watchdog simply watches your kernel to make sure it doesn't
-         freeze, and if it does, it reboots your computer after a certain
-         amount of time.
-
-         You can compile this driver directly into the kernel, or use
-         it as a module.  The module will be called sc520_wdt.
-
-config EUROTECH_WDT
-       tristate "Eurotech CPU-1220/1410 Watchdog Timer"
-       depends on X86
-       help
-         Enable support for the watchdog timer on the Eurotech CPU-1220 and
-         CPU-1410 cards.  These are PC/104 SBCs. Spec sheets and product
-         information are at <http://www.eurotech.it/>.
-
-config IB700_WDT
-       tristate "IB700 SBC Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the IB700 Single
-         Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
-         simply watches your kernel to make sure it doesn't freeze, and if
-         it does, it reboots your computer after a certain amount of time.
-
-         This driver is like the WDT501 driver but for slightly different hardware.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ib700wdt.
-
-         Most people will say N.
-
-config IBMASR
-       tristate "IBM Automatic Server Restart"
-       depends on X86
-       help
-         This is the driver for the IBM Automatic Server Restart watchdog
-         timer built-in into some eServer xSeries machines.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ibmasr.
-
-config WAFER_WDT
-       tristate "ICP Wafer 5823 Single Board Computer Watchdog"
-       depends on X86
-       help
-         This is a driver for the hardware watchdog on the ICP Wafer 5823
-         Single Board Computer (and probably other similar models).
-
-         To compile this driver as a module, choose M here: the
-         module will be called wafer5823wdt.
-
-config I6300ESB_WDT
-       tristate "Intel 6300ESB Timer/Watchdog"
-       depends on X86 && PCI
-       ---help---
-         Hardware driver for the watchdog timer built into the Intel
-         6300ESB controller hub.
-
-         To compile this driver as a module, choose M here: the
-         module will be called i6300esb.
-
-config ITCO_WDT
-       tristate "Intel TCO Timer/Watchdog"
-       depends on (X86 || IA64) && PCI
-       ---help---
-         Hardware driver for the intel TCO timer based watchdog devices.
-         These drivers are included in the Intel 82801 I/O Controller
-         Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB
-         controller hub.
-
-         The TCO (Total Cost of Ownership) timer is a watchdog timer
-         that will reboot the machine after its second expiration. The
-         expiration time can be configured with the "heartbeat" parameter.
-
-         On some motherboards the driver may fail to reset the chipset's
-         NO_REBOOT flag which prevents the watchdog from rebooting the
-         machine. If this is the case you will get a kernel message like
-         "failed to reset NO_REBOOT flag, reboot disabled by hardware".
-
-         To compile this driver as a module, choose M here: the
-         module will be called iTCO_wdt.
-
-config ITCO_VENDOR_SUPPORT
-       bool "Intel TCO Timer/Watchdog Specific Vendor Support"
-       depends on ITCO_WDT
-       ---help---
-         Add vendor specific support to the intel TCO timer based watchdog
-         devices. At this moment we only have additional support for some
-         SuperMicro Inc. motherboards.
-
-config SC1200_WDT
-       tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
-       depends on X86
-       help
-         This is a driver for National Semiconductor PC87307/PC97307 hardware
-         watchdog cards as found on the SC1200. This watchdog is mainly used
-         for power management purposes and can be used to power down the device
-         during inactivity periods (includes interrupt activity monitoring).
-
-         To compile this driver as a module, choose M here: the
-         module will be called sc1200wdt.
-
-         Most people will say N.
-
-config SCx200_WDT
-       tristate "National Semiconductor SCx200 Watchdog"
-       depends on SCx200 && PCI
-       help
-         Enable the built-in watchdog timer support on the National
-         Semiconductor SCx200 processors.
-
-         If compiled as a module, it will be called scx200_wdt.
-
-config PC87413_WDT
-       tristate "NS PC87413 watchdog"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the PC87413 chipset
-         This watchdog simply watches your kernel to make sure it doesn't
-         freeze, and if it does, it reboots your computer after a certain
-         amount of time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pc87413_wdt.
-
-         Most people will say N.
-config 60XX_WDT
-       tristate "SBC-60XX Watchdog Timer"
-       depends on X86
-       help
-         This driver can be used with the watchdog timer found on some
-         single board computers, namely the 6010 PII based computer.
-         It may well work with other cards.  It reads port 0x443 to enable
-         and re-set the watchdog timer, and reads port 0x45 to disable
-         the watchdog.  If you have a card that behave in similar ways,
-         you can probably make this driver work with your card as well.
-
-         You can compile this driver directly into the kernel, or use
-         it as a module.  The module will be called sbc60xxwdt.
-
-config SBC8360_WDT
-       tristate "SBC8360 Watchdog Timer"
-       depends on X86
-       ---help---
-
-         This is the driver for the hardware watchdog on the SBC8360 Single
-         Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
-
-         To compile this driver as a module, choose M here: the
-         module will be called sbc8360.ko.
-
-         Most people will say N.
-
-config CPU5_WDT
-       tristate "SMA CPU5 Watchdog"
-       depends on X86
-       ---help---
-         TBD.
-         To compile this driver as a module, choose M here: the
-         module will be called cpu5wdt.
-
-config SMSC37B787_WDT
-       tristate "Winbond SMsC37B787 Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog component on the
-         Winbond SMsC37B787 chipset as used on the NetRunner Mainboard
-         from Vision Systems and maybe others.
-
-         This watchdog simply watches your kernel to make sure it doesn't
-         freeze, and if it does, it reboots your computer after a certain
-         amount of time.
-
-         Usually a userspace daemon will notify the kernel WDT driver that
-         userspace is still alive, at regular intervals.
-
-         To compile this driver as a module, choose M here: the
-         module will be called smsc37b787_wdt.
-
-         Most people will say N.
-
-config W83627HF_WDT
-       tristate "W83627HF Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the W83627HF chipset
-         as used in Advantech PC-9578 and Tyan S2721-533 motherboards
-         (and likely others).  This watchdog simply watches your kernel to
-         make sure it doesn't freeze, and if it does, it reboots your computer
-         after a certain amount of time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w83627hf_wdt.
-
-         Most people will say N.
-
-config W83697HF_WDT
-       tristate "W83697HF/W83697HG Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the W83697HF/HG
-         chipset as used in Dedibox/VIA motherboards (and likely others).
-         This watchdog simply watches your kernel to make sure it doesn't
-         freeze, and if it does, it reboots your computer after a certain
-         amount of time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w83697hf_wdt.
-
-         Most people will say N.
-
-config W83877F_WDT
-       tristate "W83877F (EMACS) Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the W83877F chipset
-         as used in EMACS PC-104 motherboards (and likely others).  This
-         watchdog simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w83877f_wdt.
-
-         Most people will say N.
-
-config W83977F_WDT
-       tristate "W83977F (PCM-5335) Watchdog Timer"
-       depends on X86
-       ---help---
-         This is the driver for the hardware watchdog on the W83977F I/O chip
-         as used in AAEON's PCM-5335 SBC (and likely others).  This
-         watchdog simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w83977f_wdt.
-
-config MACHZ_WDT
-       tristate "ZF MachZ Watchdog"
-       depends on X86
-       ---help---
-         If you are using a ZF Micro MachZ processor, say Y here, otherwise
-         N.  This is the driver for the watchdog timer built-in on that
-         processor using ZF-Logic interface.  This watchdog simply watches
-         your kernel to make sure it doesn't freeze, and if it does, it
-         reboots your computer after a certain amount of time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called machzwd.
-
-config SBC_EPX_C3_WATCHDOG
-       tristate "Winsystems SBC EPX-C3 watchdog"
-       depends on X86
-       ---help---
-         This is the driver for the built-in watchdog timer on the EPX-C3
-         Single-board computer made by Winsystems, Inc.
-
-         *Note*: This hardware watchdog is not probeable and thus there
-         is no way to know if writing to its IO address will corrupt
-         your system or have any real effect.  The only way to be sure
-         that this driver does what you want is to make sure you
-         are running it on an EPX-C3 from Winsystems with the watchdog
-         timer at IO address 0x1ee and 0x1ef.  It will write to both those
-         IO ports.  Basically, the assumption is made that if you compile
-         this driver into your kernel and/or load it as a module, that you
-         know what you are doing and that you are in fact running on an
-         EPX-C3 board!
-
-         To compile this driver as a module, choose M here: the
-         module will be called sbc_epx_c3.
-
-# M32R Architecture
-
-# M68K Architecture
-
-# M68KNOMMU Architecture
-
-# MIPS Architecture
-
-config INDYDOG
-       tristate "Indy/I2 Hardware Watchdog"
-       depends on SGI_IP22
-       help
-         Hardware driver for the Indy's/I2's watchdog. This is a
-         watchdog timer that will reboot the machine after a 60 second
-         timer expired and no process has written to /dev/watchdog during
-         that time.
-
-config WDT_MTX1
-       tristate "MTX-1 Hardware Watchdog"
-       depends on MIPS_MTX1
-       help
-         Hardware driver for the MTX-1 boards. This is a watchdog timer that
-         will reboot the machine after a 100 seconds timer expired.
-
-config WDT_RM9K_GPI
-       tristate "RM9000/GPI hardware watchdog"
-       depends on CPU_RM9000
-       help
-         Watchdog implementation using the GPI hardware found on
-         PMC-Sierra RM9xxx CPUs.
-
-         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
-       tristate "z/VM Watchdog Timer"
-       depends on S390
-       help
-         IBM s/390 and zSeries machines running under z/VM 5.1 or later
-         provide a virtual watchdog timer to their guest that cause a
-         user define Control Program command to be executed after a
-         timeout.
-
-         To compile this driver as a module, choose M here. The module
-         will be called vmwatchdog.
-
-# SUPERH (sh + sh64) Architecture
-
-config SH_WDT
-       tristate "SuperH Watchdog"
-       depends on SUPERH && (CPU_SH3 || CPU_SH4)
-       help
-         This driver adds watchdog support for the integrated watchdog in the
-         SuperH processors. If you have one of these processors and wish
-         to have watchdog support enabled, say Y, otherwise say N.
-
-         As a side note, saying Y here will automatically boost HZ to 1000
-         so that the timer has a chance to clear the overflow counter. On
-         slower systems (such as the SH-2 and SH-3) this will likely yield
-         some performance issues. As such, the WDT should be avoided here
-         unless it is absolutely necessary.
-
-         To compile this driver as a module, choose M here: the
-         module will be called shwdt.
-
-config SH_WDT_MMAP
-       bool "Allow mmap of SH WDT"
-       default n
-       depends on SH_WDT
-       help
-         If you say Y here, user applications will be able to mmap the
-         WDT/CPG registers.
-
-# SPARC Architecture
-
-# SPARC64 Architecture
-
-config WATCHDOG_CP1XXX
-       tristate "CP1XXX Hardware Watchdog support"
-       depends on SPARC64 && PCI
-       ---help---
-         This is the driver for the hardware watchdog timers present on
-         Sun Microsystems CompactPCI models CP1400 and CP1500.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cpwatchdog.
-
-         If you do not have a CompactPCI model CP1400 or CP1500, or
-         another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
-         you should say N to this option.
-
-config WATCHDOG_RIO
-       tristate "RIO Hardware Watchdog support"
-       depends on SPARC64 && PCI
-       help
-         Say Y here to support the hardware watchdog capability on Sun 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
-#
-
-comment "ISA-based Watchdog Cards"
-       depends on ISA
-
-config PCWATCHDOG
-       tristate "Berkshire Products ISA-PC Watchdog"
-       depends on ISA
-       ---help---
-         This is the driver for the Berkshire Products ISA-PC Watchdog card.
-         This card simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time. This driver is like the WDT501 driver but for different
-         hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.txt>. The PC
-         watchdog cards can be ordered from <http://www.berkprod.com/>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pcwd.
-
-         Most people will say N.
-
-config MIXCOMWD
-       tristate "Mixcom Watchdog"
-       depends on ISA
-       ---help---
-         This is a driver for the Mixcom hardware watchdog cards.  This
-         watchdog simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mixcomwd.
-
-         Most people will say N.
-
-config WDT
-       tristate "WDT Watchdog timer"
-       depends on ISA
-       ---help---
-         If you have a WDT500P or WDT501P watchdog board, say Y here,
-         otherwise N. It is not possible to probe for this board, which means
-         that you have to inform the kernel about the IO port and IRQ that
-         is needed (you can do this via the io and irq parameters)
-
-         To compile this driver as a module, choose M here: the
-         module will be called wdt.
-
-config WDT_501
-       bool "WDT501 features"
-       depends on WDT
-       help
-         Saying Y here and creating a character special file /dev/temperature
-         with major number 10 and minor number 131 ("man mknod") will give
-         you a thermometer inside your computer: reading from
-         /dev/temperature yields one byte, the temperature in degrees
-         Fahrenheit. This works only if you have a WDT501P watchdog board
-         installed.
-
-         If you want to enable the Fan Tachometer on the WDT501P, then you
-         can do this via the tachometer parameter. Only do this if you have a
-         fan tachometer actually set up.
-
-#
-# PCI-based Watchdog Cards
-#
-
-comment "PCI-based Watchdog Cards"
-       depends on PCI
-
-config PCIPCWATCHDOG
-       tristate "Berkshire Products PCI-PC Watchdog"
-       depends on PCI
-       ---help---
-         This is the driver for the Berkshire Products PCI-PC Watchdog card.
-         This card simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time. The card can also monitor the internal temperature of the PC.
-         More info is available at <http://www.berkprod.com/pci_pc_watchdog.htm>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pcwd_pci.
-
-         Most people will say N.
-
-config WDTPCI
-       tristate "PCI-WDT500/501 Watchdog timer"
-       depends on PCI
-       ---help---
-         If you have a PCI-WDT500/501 watchdog board, say Y here, otherwise N.
-
-         To compile this driver as a module, choose M here: the
-         module will be called wdt_pci.
-
-config WDT_501_PCI
-       bool "PCI-WDT501 features"
-       depends on WDTPCI
-       help
-         Saying Y here and creating a character special file /dev/temperature
-         with major number 10 and minor number 131 ("man mknod") will give
-         you a thermometer inside your computer: reading from
-         /dev/temperature yields one byte, the temperature in degrees
-         Fahrenheit. This works only if you have a PCI-WDT501 watchdog board
-         installed.
-
-         If you want to enable the Fan Tachometer on the PCI-WDT501, then you
-         can do this via the tachometer parameter. Only do this if you have a
-         fan tachometer actually set up.
-
-#
-# USB-based Watchdog Cards
-#
-
-comment "USB-based Watchdog Cards"
-       depends on USB
-
-config USBPCWATCHDOG
-       tristate "Berkshire Products USB-PC Watchdog"
-       depends on USB
-       ---help---
-         This is the driver for the Berkshire Products USB-PC Watchdog card.
-         This card simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time. The card can also monitor the internal temperature of the PC.
-         More info is available at <http://www.berkprod.com/usb_pc_watchdog.htm>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pcwd_usb.
-
-         Most people will say N.
-
-endif # WATCHDOG
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
deleted file mode 100644 (file)
index 389f8b1..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#
-# Makefile for the WatchDog device drivers.
-#
-
-# Only one watchdog can succeed. We probe the ISA/PCI/USB based
-# watchdog-cards first, then the architecture specific watchdog
-# drivers and then the architecture independant "softdog" driver.
-# This means that if your ISA/PCI/USB card isn't detected that
-# you can fall back to an architecture specific driver and if
-# that also fails then you can fall back to the software watchdog
-# to give you some cover.
-
-# ISA-based Watchdog Cards
-obj-$(CONFIG_PCWATCHDOG) += pcwd.o
-obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
-obj-$(CONFIG_WDT) += wdt.o
-
-# PCI-based Watchdog Cards
-obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
-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
-obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
-obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
-obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
-obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
-obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
-obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
-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
-obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
-obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
-obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
-obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
-obj-$(CONFIG_IB700_WDT) += ib700wdt.o
-obj-$(CONFIG_IBMASR) += ibmasr.o
-obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
-obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
-obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
-obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
-obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
-obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
-obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
-obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
-obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
-obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
-obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
-obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
-obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
-obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
-obj-$(CONFIG_MACHZ_WDT) += machzwd.o
-obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
-
-# 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
-
-# PPC64 Architecture
-obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-
-# S390 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/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
deleted file mode 100644 (file)
index 85269c3..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- *     Acquire Single Board Computer Watchdog Timer driver
- *
- *      Based on wdt.c. Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
- *
- *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *          Can't add timeout - driver doesn't allow changing value
- */
-
-/*
- *     Theory of Operation:
- *             The Watch-Dog Timer is provided to ensure that standalone
- *             Systems can always recover from catastrophic conditions that
- *             caused the CPU to crash. This condition may have occured by
- *             external EMI or a software bug. When the CPU stops working
- *             correctly, hardware on the board will either perform a hardware
- *             reset (cold boot) or a non-maskable interrupt (NMI) to bring the
- *             system back to a known state.
- *
- *             The Watch-Dog Timer is controlled by two I/O Ports.
- *               443 hex       - Read  - Enable or refresh the Watch-Dog Timer
- *               043 hex       - Read  - Disable the Watch-Dog Timer
- *
- *             To enable the Watch-Dog Timer, a read from I/O port 443h must
- *             be performed. This will enable and activate the countdown timer
- *             which will eventually time out and either reset the CPU or cause
- *             an NMI depending on the setting of a jumper. To ensure that this
- *             reset condition does not occur, the Watch-Dog Timer must be
- *             periodically refreshed by reading the same I/O port 443h.
- *             The Watch-Dog Timer is disabled by reading I/O port 043h.
- *
- *             The Watch-Dog Timer Time-Out Period is set via jumpers.
- *             It can be 1, 2, 10, 20, 110 or 220 seconds.
- */
-
-/*
- *     Includes, defines, variables, module parameters, ...
- */
-
-/* Includes */
-#include <linux/module.h>              /* For module specific items */
-#include <linux/moduleparam.h>         /* For new moduleparam's */
-#include <linux/types.h>               /* For standard types (like size_t) */
-#include <linux/errno.h>               /* For the -ENODEV/... values */
-#include <linux/kernel.h>              /* For printk/panic/... */
-#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
-#include <linux/watchdog.h>            /* For the watchdog specific items */
-#include <linux/fs.h>                  /* For file operations */
-#include <linux/ioport.h>              /* For io-port access */
-#include <linux/platform_device.h>     /* For platform_driver framework */
-#include <linux/init.h>                        /* For __init/__exit/... */
-
-#include <asm/uaccess.h>               /* For copy_to_user/put_user/... */
-#include <asm/io.h>                    /* For inb/outb/... */
-
-/* Module information */
-#define DRV_NAME "acquirewdt"
-#define PFX DRV_NAME ": "
-#define WATCHDOG_NAME "Acquire WDT"
-#define WATCHDOG_HEARTBEAT 0   /* There is no way to see what the correct time-out period is */
-
-/* internal variables */
-static struct platform_device *acq_platform_device;    /* the watchdog platform device */
-static unsigned long acq_is_open;
-static char expect_close;
-
-/* module parameters */
-static int wdt_stop = 0x43;    /* You must set this - there is no sane way to probe for this board. */
-module_param(wdt_stop, int, 0);
-MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
-
-static int wdt_start = 0x443;  /* You must set this - there is no sane way to probe for this board. */
-module_param(wdt_start, int, 0);
-MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
-
-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) ")");
-
-/*
- *     Watchdog Operations
- */
-
-static void acq_keepalive(void)
-{
-       /* Write a watchdog value */
-       inb_p(wdt_start);
-}
-
-static void acq_stop(void)
-{
-       /* Turn the card off */
-       inb_p(wdt_stop);
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-
-               /* Well, anyhow someone wrote to us, we should return that favour */
-               acq_keepalive();
-       }
-       return count;
-}
-
-static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       int options, retval = -EINVAL;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident =
-       {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = WATCHDOG_NAME,
-       };
-
-       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:
-         acq_keepalive();
-         return 0;
-
-       case WDIOC_GETTIMEOUT:
-         return put_user(WATCHDOG_HEARTBEAT, p);
-
-       case WDIOC_SETOPTIONS:
-       {
-           if (get_user(options, p))
-             return -EFAULT;
-
-           if (options & WDIOS_DISABLECARD)
-           {
-             acq_stop();
-             retval = 0;
-           }
-
-           if (options & WDIOS_ENABLECARD)
-           {
-             acq_keepalive();
-             retval = 0;
-           }
-
-           return retval;
-       }
-
-       default:
-         return -ENOTTY;
-       }
-}
-
-static int acq_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &acq_is_open))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate */
-       acq_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int acq_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               acq_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               acq_keepalive();
-       }
-       clear_bit(0, &acq_is_open);
-       expect_close = 0;
-       return 0;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations acq_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = acq_write,
-       .ioctl          = acq_ioctl,
-       .open           = acq_open,
-       .release        = acq_close,
-};
-
-static struct miscdevice acq_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &acq_fops,
-};
-
-/*
- *     Init & exit routines
- */
-
-static int __devinit acq_probe(struct platform_device *dev)
-{
-       int ret;
-
-       if (wdt_stop != wdt_start) {
-               if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                               wdt_stop);
-                       ret = -EIO;
-                       goto out;
-               }
-       }
-
-       if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
-               ret = -EIO;
-               goto unreg_stop;
-       }
-
-       ret = misc_register(&acq_miscdev);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto unreg_regions;
-       }
-
-       printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
-               nowayout);
-
-       return 0;
-
-unreg_regions:
-       release_region(wdt_start, 1);
-unreg_stop:
-       if (wdt_stop != wdt_start)
-               release_region(wdt_stop, 1);
-out:
-       return ret;
-}
-
-static int __devexit acq_remove(struct platform_device *dev)
-{
-       misc_deregister(&acq_miscdev);
-       release_region(wdt_start,1);
-       if(wdt_stop != wdt_start)
-               release_region(wdt_stop,1);
-
-       return 0;
-}
-
-static void acq_shutdown(struct platform_device *dev)
-{
-       /* Turn the WDT off if we have a soft shutdown */
-       acq_stop();
-}
-
-static struct platform_driver acquirewdt_driver = {
-       .probe          = acq_probe,
-       .remove         = __devexit_p(acq_remove),
-       .shutdown       = acq_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = DRV_NAME,
-       },
-};
-
-static int __init acq_init(void)
-{
-       int err;
-
-       printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
-
-       err = platform_driver_register(&acquirewdt_driver);
-       if (err)
-               return err;
-
-       acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
-       if (IS_ERR(acq_platform_device)) {
-               err = PTR_ERR(acq_platform_device);
-               goto unreg_platform_driver;
-       }
-
-       return 0;
-
-unreg_platform_driver:
-       platform_driver_unregister(&acquirewdt_driver);
-       return err;
-}
-
-static void __exit acq_exit(void)
-{
-       platform_device_unregister(acq_platform_device);
-       platform_driver_unregister(&acquirewdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(acq_init);
-module_exit(acq_exit);
-
-MODULE_AUTHOR("David Woodhouse");
-MODULE_DESCRIPTION("Acquire Inc. Single Board Computer Watchdog Timer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
deleted file mode 100644 (file)
index 8121cc2..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- *     Advantech Single Board Computer WDT driver
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     Based on acquirewdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
- *
- *     14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *         Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *
- *     16-Oct-2002 Rob Radez <rob@osinvestor.com>
- *         Clean up ioctls, clean up init + exit, add expect close support,
- *         add wdt_start and wdt_stop as parameters.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define DRV_NAME "advantechwdt"
-#define PFX DRV_NAME ": "
-#define WATCHDOG_NAME "Advantech WDT"
-#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
-
-static struct platform_device *advwdt_platform_device; /* the watchdog platform device */
-static unsigned long advwdt_is_open;
-static char adv_expect_close;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- *
- *     To enable or restart, write the timeout value in seconds (1 to 63)
- *     to I/O port wdt_start.  To disable, read I/O port wdt_stop.
- *     Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
- *     check your manual (at least the PCA-6159 seems to be different -
- *     the manual says wdt_stop is 0x43, not 0x443).
- *     (0x43 is also a write-only control register for the 8254 timer!)
- */
-
-static int wdt_stop = 0x443;
-module_param(wdt_stop, int, 0);
-MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)");
-
-static int wdt_start = 0x443;
-module_param(wdt_start, int, 0);
-MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
-
-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) ".");
-
-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) ")");
-
-/*
- *     Watchdog Operations
- */
-
-static void
-advwdt_ping(void)
-{
-       /* Write a watchdog value */
-       outb_p(timeout, wdt_start);
-}
-
-static void
-advwdt_disable(void)
-{
-       inb_p(wdt_stop);
-}
-
-static int
-advwdt_set_heartbeat(int t)
-{
-       if ((t < 1) || (t > 63))
-               return -EINVAL;
-
-       timeout = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t
-advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       adv_expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       adv_expect_close = 42;
-                       }
-               }
-               advwdt_ping();
-       }
-       return count;
-}
-
-static int
-advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       int new_timeout;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = WATCHDOG_NAME,
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user(argp, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-         return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-         advwdt_ping();
-         break;
-
-       case WDIOC_SETTIMEOUT:
-         if (get_user(new_timeout, p))
-                 return -EFAULT;
-         if (advwdt_set_heartbeat(new_timeout))
-                 return -EINVAL;
-         advwdt_ping();
-         /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-         return put_user(timeout, p);
-
-       case WDIOC_SETOPTIONS:
-       {
-         int options, retval = -EINVAL;
-
-         if (get_user(options, p))
-           return -EFAULT;
-
-         if (options & WDIOS_DISABLECARD) {
-           advwdt_disable();
-           retval = 0;
-         }
-
-         if (options & WDIOS_ENABLECARD) {
-           advwdt_ping();
-           retval = 0;
-         }
-
-         return retval;
-       }
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-advwdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &advwdt_is_open))
-               return -EBUSY;
-       /*
-        *      Activate
-        */
-
-       advwdt_ping();
-       return nonseekable_open(inode, file);
-}
-
-static int
-advwdt_close(struct inode *inode, struct file *file)
-{
-       if (adv_expect_close == 42) {
-               advwdt_disable();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               advwdt_ping();
-       }
-       clear_bit(0, &advwdt_is_open);
-       adv_expect_close = 0;
-       return 0;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations advwdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = advwdt_write,
-       .ioctl          = advwdt_ioctl,
-       .open           = advwdt_open,
-       .release        = advwdt_close,
-};
-
-static struct miscdevice advwdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &advwdt_fops,
-};
-
-/*
- *     Init & exit routines
- */
-
-static int __devinit
-advwdt_probe(struct platform_device *dev)
-{
-       int ret;
-
-       if (wdt_stop != wdt_start) {
-               if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                               wdt_stop);
-                       ret = -EIO;
-                       goto out;
-               }
-       }
-
-       if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
-               ret = -EIO;
-               goto unreg_stop;
-       }
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (advwdt_set_heartbeat(timeout)) {
-               advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
-                       timeout);
-       }
-
-       ret = misc_register(&advwdt_miscdev);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto unreg_regions;
-       }
-
-       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-out:
-       return ret;
-unreg_regions:
-       release_region(wdt_start, 1);
-unreg_stop:
-       if (wdt_stop != wdt_start)
-               release_region(wdt_stop, 1);
-       goto out;
-}
-
-static int __devexit
-advwdt_remove(struct platform_device *dev)
-{
-       misc_deregister(&advwdt_miscdev);
-       release_region(wdt_start,1);
-       if(wdt_stop != wdt_start)
-               release_region(wdt_stop,1);
-
-       return 0;
-}
-
-static void
-advwdt_shutdown(struct platform_device *dev)
-{
-       /* Turn the WDT off if we have a soft shutdown */
-       advwdt_disable();
-}
-
-static struct platform_driver advwdt_driver = {
-       .probe          = advwdt_probe,
-       .remove         = __devexit_p(advwdt_remove),
-       .shutdown       = advwdt_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = DRV_NAME,
-       },
-};
-
-static int __init
-advwdt_init(void)
-{
-       int err;
-
-       printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
-
-       err = platform_driver_register(&advwdt_driver);
-       if (err)
-               return err;
-
-       advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
-       if (IS_ERR(advwdt_platform_device)) {
-               err = PTR_ERR(advwdt_platform_device);
-               goto unreg_platform_driver;
-       }
-
-       return 0;
-
-unreg_platform_driver:
-       platform_driver_unregister(&advwdt_driver);
-       return err;
-}
-
-static void __exit
-advwdt_exit(void)
-{
-       platform_device_unregister(advwdt_platform_device);
-       platform_driver_unregister(&advwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(advwdt_init);
-module_exit(advwdt_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marek Michalkiewicz <marekm@linux.org.pl>");
-MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c
deleted file mode 100644 (file)
index c404fc6..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- *     Watchdog for the 7101 PMU version found in the ALi M1535 chipsets
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define WATCHDOG_NAME "ALi_M1535"
-#define PFX WATCHDOG_NAME ": "
-#define WATCHDOG_TIMEOUT 60    /* 60 sec default timeout */
-
-/* internal variables */
-static unsigned long ali_is_open;
-static char ali_expect_release;
-static struct pci_dev *ali_pci;
-static u32 ali_timeout_bits;   /* stores the computed timeout */
-static spinlock_t ali_lock;    /* Guards the hardware */
-
-/* module parameters */
-static int timeout = WATCHDOG_TIMEOUT;
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-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) ")");
-
-/*
- *     ali_start       -       start watchdog countdown
- *
- *     Starts the timer running providing the timer has a counter
- *     configuration set.
- */
-
-static void ali_start(void)
-{
-       u32 val;
-
-       spin_lock(&ali_lock);
-
-       pci_read_config_dword(ali_pci, 0xCC, &val);
-       val &= ~0x3F;   /* Mask count */
-       val |= (1<<25) | ali_timeout_bits;
-       pci_write_config_dword(ali_pci, 0xCC, val);
-
-       spin_unlock(&ali_lock);
-}
-
-/*
- *     ali_stop        -       stop the timer countdown
- *
- *     Stop the ALi watchdog countdown
- */
-
-static void ali_stop(void)
-{
-       u32 val;
-
-       spin_lock(&ali_lock);
-
-       pci_read_config_dword(ali_pci, 0xCC, &val);
-       val &= ~0x3F;   /* Mask count to zero (disabled) */
-       val &= ~(1<<25);/* and for safety mask the reset enable */
-       pci_write_config_dword(ali_pci, 0xCC, val);
-
-       spin_unlock(&ali_lock);
-}
-
-/*
- *     ali_keepalive   -       send a keepalive to the watchdog
- *
- *      Send a keepalive to the timer (actually we restart the timer).
- */
-
-static void ali_keepalive(void)
-{
-       ali_start();
-}
-
-/*
- *     ali_settimer    -       compute the timer reload value
- *     @t: time in seconds
- *
- *     Computes the timeout values needed
- */
-
-static int ali_settimer(int t)
-{
-       if(t < 0)
-               return -EINVAL;
-       else if(t < 60)
-               ali_timeout_bits = t|(1<<6);
-       else if(t < 3600)
-               ali_timeout_bits = (t/60)|(1<<7);
-       else if(t < 18000)
-               ali_timeout_bits = (t/300)|(1<<6)|(1<<7);
-       else return -EINVAL;
-
-       timeout = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-/*
- *     ali_write       -       writes to ALi watchdog
- *     @file: file from VFS
- *     @data: user address of data
- *     @len: length of data
- *     @ppos: pointer to the file offset
- *
- *     Handle a write to the ALi watchdog. Writing to the file pings
- *     the watchdog and resets it. Writing the magic 'V' sequence allows
- *     the next close to turn off the watchdog.
- */
-
-static ssize_t ali_write(struct file *file, const char __user *data,
-                             size_t len, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       ali_expect_release = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if(get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       ali_expect_release = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               ali_start();
-       }
-       return len;
-}
-
-/*
- *     ali_ioctl       -       handle watchdog ioctls
- *     @inode: VFS inode
- *     @file: VFS file pointer
- *     @cmd: ioctl number
- *     @arg: arguments to the ioctl
- *
- *     Handle the watchdog ioctls supported by the ALi driver. Really
- *     we want an extension to enable irq ack monitoring and the like
- */
-
-static int ali_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_KEEPALIVEPING |
-                                       WDIOF_SETTIMEOUT |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "ALi M1535 WatchDog Timer",
-       };
-
-       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:
-                       ali_keepalive();
-                       return 0;
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if (get_user (new_options, p))
-                               return -EFAULT;
-
-                       if (new_options & WDIOS_DISABLECARD) {
-                               ali_stop();
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_ENABLECARD) {
-                               ali_start();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_timeout;
-
-                       if (get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       if (ali_settimer(new_timeout))
-                           return -EINVAL;
-
-                       ali_keepalive();
-                       /* Fall */
-               }
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout, p);
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-/*
- *     ali_open        -       handle open of ali watchdog
- *     @inode: inode from VFS
- *     @file: file from VFS
- *
- *     Open the ALi watchdog device. Ensure only one person opens it
- *     at a time. Also start the watchdog running.
- */
-
-static int ali_open(struct inode *inode, struct file *file)
-{
-       /* /dev/watchdog can only be opened once */
-       if (test_and_set_bit(0, &ali_is_open))
-               return -EBUSY;
-
-       /* Activate */
-       ali_start();
-       return nonseekable_open(inode, file);
-}
-
-/*
- *     ali_release     -       close an ALi watchdog
- *     @inode: inode from VFS
- *     @file: file from VFS
- *
- *     Close the ALi watchdog device. Actual shutdown of the timer
- *     only occurs if the magic sequence has been set.
- */
-
-static int ali_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        */
-       if (ali_expect_release == 42) {
-               ali_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               ali_keepalive();
-       }
-       clear_bit(0, &ali_is_open);
-       ali_expect_release = 0;
-       return 0;
-}
-
-/*
- *     ali_notify_sys  -       System down notifier
- *
- *     Notifier for system down
- */
-
-
-static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the WDT off */
-               ali_stop();
-       }
-
-       return NOTIFY_DONE;
-}
-
-/*
- *     Data for PCI driver interface
- *
- *     This data only exists for exporting the supported
- *     PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- *     register a pci_driver, because someone else might one day
- *     want to register another driver on the same PCI id.
- */
-
-static struct pci_device_id ali_pci_tbl[] = {
-       { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
-       { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
-       { 0, },
-};
-MODULE_DEVICE_TABLE(pci, ali_pci_tbl);
-
-/*
- *     ali_find_watchdog       -       find a 1535 and 7101
- *
- *     Scans the PCI hardware for a 1535 series bridge and matching 7101
- *     watchdog device. This may be overtight but it is better to be safe
- */
-
-static int __init ali_find_watchdog(void)
-{
-       struct pci_dev *pdev;
-       u32 wdog;
-
-       /* Check for a 1533/1535 series bridge */
-       pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
-       if (pdev == NULL)
-               pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL);
-       if (pdev == NULL)
-               return -ENODEV;
-       pci_dev_put(pdev);
-
-       /* Check for the a 7101 PMU */
-       pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
-       if(pdev == NULL)
-               return -ENODEV;
-
-       if(pci_enable_device(pdev)) {
-               pci_dev_put(pdev);
-               return -EIO;
-       }
-
-       ali_pci = pdev;
-
-       /*
-        *      Initialize the timer bits
-        */
-       pci_read_config_dword(pdev, 0xCC, &wdog);
-
-       wdog &= ~0x3F;          /* Timer bits */
-       wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24));     /* Issued events */
-       wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9));      /* No monitor bits */
-
-       pci_write_config_dword(pdev, 0xCC, wdog);
-
-       return 0;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations ali_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .write =        ali_write,
-       .ioctl =        ali_ioctl,
-       .open =         ali_open,
-       .release =      ali_release,
-};
-
-static struct miscdevice ali_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &ali_fops,
-};
-
-static struct notifier_block ali_notifier = {
-       .notifier_call =        ali_notify_sys,
-};
-
-/*
- *     watchdog_init   -       module initialiser
- *
- *     Scan for a suitable watchdog and if so initialize it. Return an error
- *     if we cannot, the error causes the module to unload
- */
-
-static int __init watchdog_init(void)
-{
-       int ret;
-
-       spin_lock_init(&ali_lock);
-
-       /* Check whether or not the hardware watchdog is there */
-       if (ali_find_watchdog() != 0) {
-               return -ENODEV;
-       }
-
-       /* Check that the timeout value is within it's range ; if not reset to the default */
-       if (timeout < 1 || timeout >= 18000) {
-               timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n",
-                       timeout);
-       }
-
-       /* Calculate the watchdog's timeout */
-       ali_settimer(timeout);
-
-       ret = misc_register(&ali_miscdev);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto out;
-       }
-
-       ret = register_reboot_notifier(&ali_notifier);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto unreg_miscdev;
-       }
-
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-out:
-       return ret;
-unreg_miscdev:
-       misc_deregister(&ali_miscdev);
-       goto out;
-}
-
-/*
- *     watchdog_exit   -       module de-initialiser
- *
- *     Called while unloading a successfully installed watchdog module.
- */
-
-static void __exit watchdog_exit(void)
-{
-       /* Stop the timer before we leave */
-       ali_stop();
-
-       /* Deregister */
-       unregister_reboot_notifier(&ali_notifier);
-       misc_deregister(&ali_miscdev);
-       pci_dev_put(ali_pci);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("ALi M1535 PMU Watchdog Timer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
deleted file mode 100644 (file)
index 67aed9f..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- *     ALi M7101 PMU Computer Watchdog Timer driver
- *
- *     Based on w83877f_wdt.c by Scott Jennings <linuxdrivers@oro.net>
- *     and the Cobalt kernel WDT timer driver by Tim Hockin
- *                                           <thockin@cobaltnet.com>
- *
- *     (c)2002 Steve Hill <steve@navaho.co.uk>
- *
- *  This WDT driver is different from most other Linux WDT
- *  drivers in that the driver will ping the watchdog by itself,
- *  because this particular WDT has a very short timeout (1.6
- *  seconds) and it would be insane to count on any userspace
- *  daemon always getting scheduled within that time frame.
- *
- *  Additions:
- *   Aug 23, 2004 - Added use_gpio module parameter for use on revision a1d PMUs
- *                  found on very old cobalt hardware.
- *                  -- Mike Waychison <michael.waychison@sun.com>
- */
-
-#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/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define OUR_NAME "alim7101_wdt"
-#define PFX OUR_NAME ": "
-
-#define WDT_ENABLE 0x9C
-#define WDT_DISABLE 0x8C
-
-#define ALI_7101_WDT    0x92
-#define ALI_7101_GPIO   0x7D
-#define ALI_7101_GPIO_O 0x7E
-#define ALI_WDT_ARM     0x01
-
-/*
- * We're going to use a 1 second timeout.
- * If we reset the watchdog every ~250ms we should be safe.  */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 30 seconds.
- */
-
-#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-static int use_gpio = 0; /* Use the pic (for a1d revision alim7101) */
-module_param(use_gpio, int, 0);
-MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog.  (required by old cobalt boards)");
-
-static void wdt_timer_ping(unsigned long);
-static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
-static unsigned long next_heartbeat;
-static unsigned long wdt_is_open;
-static char wdt_expect_close;
-static struct pci_dev *alim7101_pmu;
-
-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) ")");
-
-/*
- *     Whack the dog
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT
-        */
-       char    tmp;
-
-       if(time_before(jiffies, next_heartbeat))
-       {
-               /* Ping the WDT (this is actually a disarm/arm sequence) */
-               pci_read_config_byte(alim7101_pmu, 0x92, &tmp);
-               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
-               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM));
-               if (use_gpio) {
-                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
-                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp
-                                       | 0x20);
-                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp
-                                       & ~0x20);
-               }
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
-       /* Re-set the timer interval */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-}
-
-/*
- * Utility routines
- */
-
-static void wdt_change(int writeval)
-{
-       char    tmp;
-
-       pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp);
-       if (writeval == WDT_ENABLE) {
-               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM));
-               if (use_gpio) {
-                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
-                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp & ~0x20);
-               }
-
-       } else {
-               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
-               if (use_gpio) {
-                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
-                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 0x20);
-               }
-       }
-}
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + (timeout * HZ);
-
-       /* We must enable before we kick off the timer in case the timer
-          occurs as we ping it */
-
-       wdt_change(WDT_ENABLE);
-
-       /* Start the timer */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
-}
-
-static void wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer_sync(&timer);
-       wdt_change(WDT_DISABLE);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
-}
-
-static void wdt_keepalive(void)
-{
-       /* user land ping */
-       next_heartbeat = jiffies + (timeout * HZ);
-}
-
-/*
- * /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count) {
-               if (!nowayout) {
-                       size_t ofs;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       wdt_expect_close = 0;
-
-                       /* now scan */
-                       for (ofs = 0; ofs != count; ofs++) {
-                               char c;
-                               if (get_user(c, buf+ofs))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       wdt_expect_close = 42;
-                       }
-               }
-               /* someone wrote to us, we should restart timer */
-               wdt_keepalive();
-       }
-       return count;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       /* Just in case we're already talking to someone... */
-       if(test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-       /* Good, fire up the show */
-       wdt_startup();
-       return nonseekable_open(inode, file);
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(wdt_expect_close == 42)
-               wdt_turnoff();
-       else {
-               /* wim: shouldn't there be a: del_timer(&timer); */
-               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
-       }
-       clear_bit(0, &wdt_is_open);
-       wdt_expect_close = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident =
-       {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "ALiM7101",
-       };
-
-       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:
-                       wdt_keepalive();
-                       return 0;
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if(get_user(new_options, p))
-                               return -EFAULT;
-
-                       if(new_options & WDIOS_DISABLECARD) {
-                               wdt_turnoff();
-                               retval = 0;
-                       }
-
-                       if(new_options & WDIOS_ENABLECARD) {
-                               wdt_startup();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_timeout;
-
-                       if(get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       wdt_keepalive();
-                       /* Fall through */
-               }
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout, p);
-               default:
-                       return -ENOTTY;
-       }
-}
-
-static const struct file_operations wdt_fops = {
-       .owner=         THIS_MODULE,
-       .llseek=        no_llseek,
-       .write=         fop_write,
-       .open=          fop_open,
-       .release=       fop_close,
-       .ioctl=         fop_ioctl,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor=WATCHDOG_MINOR,
-       .name="watchdog",
-       .fops=&wdt_fops,
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT)
-               wdt_turnoff();
-
-       if (code==SYS_RESTART) {
-               /*
-                * Cobalt devices have no way of rebooting themselves other than
-                * getting the watchdog to pull reset, so we restart the watchdog on
-                * reboot with no heartbeat
-                */
-               wdt_change(WDT_ENABLE);
-               printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n");
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier=
-{
-       .notifier_call = wdt_notify_sys,
-};
-
-static void __exit alim7101_wdt_unload(void)
-{
-       wdt_turnoff();
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-       unregister_reboot_notifier(&wdt_notifier);
-       pci_dev_put(alim7101_pmu);
-}
-
-static int __init alim7101_wdt_init(void)
-{
-       int rc = -EBUSY;
-       struct pci_dev *ali1543_south;
-       char tmp;
-
-       printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n");
-       alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-               NULL);
-       if (!alim7101_pmu) {
-               printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n");
-               return -EBUSY;
-       }
-
-       /* Set the WDT in the PMU to 1 second */
-       pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02);
-
-       ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-               NULL);
-       if (!ali1543_south) {
-               printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n");
-               goto err_out;
-       }
-       pci_read_config_byte(ali1543_south, 0x5e, &tmp);
-       pci_dev_put(ali1543_south);
-       if ((tmp & 0x1e) == 0x00) {
-               if (!use_gpio) {
-                       printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'.  If this is a cobalt board, set the 'use_gpio' module parameter.\n");
-                       goto err_out;
-               } 
-               nowayout = 1;
-       } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
-               printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
-               goto err_out;
-       }
-
-       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
-       {
-               timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
-                       timeout);
-       }
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
-               goto err_out;
-       }
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_miscdev;
-       }
-
-       if (nowayout) {
-               __module_get(THIS_MODULE);
-       }
-
-       printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out:
-       pci_dev_put(alim7101_pmu);
-       return rc;
-}
-
-module_init(alim7101_wdt_init);
-module_exit(alim7101_wdt_unload);
-
-static struct pci_device_id alim7101_pci_tbl[] __devinitdata = {
-       { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
-       { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl);
-
-MODULE_AUTHOR("Steve Hill");
-MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/at32ap700x_wdt.c b/drivers/char/watchdog/at32ap700x_wdt.c
deleted file mode 100644 (file)
index 54a5161..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Watchdog driver for Atmel AT32AP700X devices
- *
- * Copyright (C) 2005-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/watchdog.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
-#define TIMEOUT_MIN            1
-#define TIMEOUT_MAX            2
-#define TIMEOUT_DEFAULT                TIMEOUT_MAX
-
-/* module parameters */
-static int timeout =  TIMEOUT_DEFAULT;
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,
-               "Timeout value. Limited to be 1 or 2 seconds. (default="
-               __MODULE_STRING(TIMEOUT_DEFAULT) ")");
-
-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) ")");
-
-/* Watchdog registers and write/read macro */
-#define WDT_CTRL               0x00
-#define WDT_CTRL_EN               0
-#define WDT_CTRL_PSEL             8
-#define WDT_CTRL_KEY             24
-
-#define WDT_CLR                        0x04
-
-#define WDT_BIT(name)          (1 << WDT_##name)
-#define WDT_BF(name, value)    ((value) << WDT_##name)
-
-#define wdt_readl(dev, reg)                            \
-       __raw_readl((dev)->regs + WDT_##reg)
-#define wdt_writel(dev, reg, value)                    \
-       __raw_writel((value), (dev)->regs + WDT_##reg)
-
-struct wdt_at32ap700x {
-       void __iomem            *regs;
-       spinlock_t              io_lock;
-       int                     timeout;
-       unsigned long           users;
-       struct miscdevice       miscdev;
-};
-
-static struct wdt_at32ap700x *wdt;
-static char expect_release;
-
-/*
- * Disable the watchdog.
- */
-static inline void at32_wdt_stop(void)
-{
-       unsigned long psel;
-
-       spin_lock(&wdt->io_lock);
-       psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f);
-       wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55));
-       wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa));
-       spin_unlock(&wdt->io_lock);
-}
-
-/*
- * Enable and reset the watchdog.
- */
-static inline void at32_wdt_start(void)
-{
-       /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */
-       unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe;
-
-       spin_lock(&wdt->io_lock);
-       wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
-                       | WDT_BF(CTRL_PSEL, psel)
-                       | WDT_BF(CTRL_KEY, 0x55));
-       wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
-                       | WDT_BF(CTRL_PSEL, psel)
-                       | WDT_BF(CTRL_KEY, 0xaa));
-       spin_unlock(&wdt->io_lock);
-}
-
-/*
- * Pat the watchdog timer.
- */
-static inline void at32_wdt_pat(void)
-{
-       spin_lock(&wdt->io_lock);
-       wdt_writel(wdt, CLR, 0x42);
-       spin_unlock(&wdt->io_lock);
-}
-
-/*
- * Watchdog device is opened, and watchdog starts running.
- */
-static int at32_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(1, &wdt->users))
-               return -EBUSY;
-
-       at32_wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-/*
- * Close the watchdog device.
- */
-static int at32_wdt_close(struct inode *inode, struct file *file)
-{
-       if (expect_release == 42) {
-               at32_wdt_stop();
-       } else {
-               dev_dbg(wdt->miscdev.parent,
-                       "Unexpected close, not stopping watchdog!\n");
-               at32_wdt_pat();
-       }
-       clear_bit(1, &wdt->users);
-       expect_release = 0;
-       return 0;
-}
-
-/*
- * Change the watchdog time interval.
- */
-static int at32_wdt_settimeout(int time)
-{
-       /*
-        * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
-        * 2 ^ 16 allowing up to 2 seconds timeout.
-        */
-       if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
-               return -EINVAL;
-
-       /*
-        * Set new watchdog time. It will be used when at32_wdt_start() is
-        * called.
-        */
-       wdt->timeout = time;
-       return 0;
-}
-
-static struct watchdog_info at32_wdt_info = {
-       .identity       = "at32ap700x watchdog",
-       .options        = WDIOF_SETTIMEOUT |
-                         WDIOF_KEEPALIVEPING |
-                         WDIOF_MAGICCLOSE,
-};
-
-/*
- * Handle commands from user-space.
- */
-static int at32_wdt_ioctl(struct inode *inode, struct file *file,
-               unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       switch (cmd) {
-       case WDIOC_KEEPALIVE:
-               at32_wdt_pat();
-               ret = 0;
-               break;
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(argp, &at32_wdt_info,
-                               sizeof(at32_wdt_info)) ? -EFAULT : 0;
-               break;
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-               ret = at32_wdt_settimeout(time);
-               if (ret)
-                       break;
-               /* Enable new time value */
-               at32_wdt_start();
-               /* fall through */
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(wdt->timeout, p);
-               break;
-       case WDIOC_GETSTATUS: /* fall through */
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, p);
-               break;
-       case WDIOC_SETOPTIONS:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-               if (time & WDIOS_DISABLECARD)
-                       at32_wdt_stop();
-               if (time & WDIOS_ENABLECARD)
-                       at32_wdt_start();
-               ret = 0;
-               break;
-       }
-
-       return ret;
-}
-
-static ssize_t at32_wdt_write(struct file *file, const char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /*
-                        * note: just in case someone wrote the magic
-                        * character five months ago...
-                        */
-                       expect_release = 0;
-
-                       /*
-                        * scan to see whether or not we got the magic
-                        * character
-                        */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_release = 42;
-                       }
-               }
-               /* someone wrote to us, we should pat the watchdog */
-               at32_wdt_pat();
-       }
-       return len;
-}
-
-static const struct file_operations at32_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .ioctl          = at32_wdt_ioctl,
-       .open           = at32_wdt_open,
-       .release        = at32_wdt_close,
-       .write          = at32_wdt_write,
-};
-
-static int __init at32_wdt_probe(struct platform_device *pdev)
-{
-       struct resource *regs;
-       int ret;
-
-       if (wdt) {
-               dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n");
-               return -EBUSY;
-       }
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_dbg(&pdev->dev, "missing mmio resource\n");
-               return -ENXIO;
-       }
-
-       wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL);
-       if (!wdt) {
-               dev_dbg(&pdev->dev, "no memory for wdt structure\n");
-               return -ENOMEM;
-       }
-
-       wdt->regs = ioremap(regs->start, regs->end - regs->start + 1);
-       if (!wdt->regs) {
-               ret = -ENOMEM;
-               dev_dbg(&pdev->dev, "could not map I/O memory\n");
-               goto err_free;
-       }
-       spin_lock_init(&wdt->io_lock);
-       wdt->users = 0;
-       wdt->miscdev.minor = WATCHDOG_MINOR;
-       wdt->miscdev.name = "watchdog";
-       wdt->miscdev.fops = &at32_wdt_fops;
-
-       if (at32_wdt_settimeout(timeout)) {
-               at32_wdt_settimeout(TIMEOUT_DEFAULT);
-               dev_dbg(&pdev->dev,
-                       "default timeout invalid, set to %d sec.\n",
-                       TIMEOUT_DEFAULT);
-       }
-
-       ret = misc_register(&wdt->miscdev);
-       if (ret) {
-               dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
-               goto err_iounmap;
-       }
-
-       platform_set_drvdata(pdev, wdt);
-       wdt->miscdev.parent = &pdev->dev;
-       dev_info(&pdev->dev,
-               "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
-               wdt->regs, wdt->timeout, nowayout);
-
-       return 0;
-
-err_iounmap:
-       iounmap(wdt->regs);
-err_free:
-       kfree(wdt);
-       wdt = NULL;
-       return ret;
-}
-
-static int __exit at32_wdt_remove(struct platform_device *pdev)
-{
-       if (wdt && platform_get_drvdata(pdev) == wdt) {
-               /* Stop the timer before we leave */
-               if (!nowayout)
-                       at32_wdt_stop();
-
-               misc_deregister(&wdt->miscdev);
-               iounmap(wdt->regs);
-               kfree(wdt);
-               wdt = NULL;
-               platform_set_drvdata(pdev, NULL);
-       }
-
-       return 0;
-}
-
-static void at32_wdt_shutdown(struct platform_device *pdev)
-{
-       at32_wdt_stop();
-}
-
-#ifdef CONFIG_PM
-static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message)
-{
-       at32_wdt_stop();
-       return 0;
-}
-
-static int at32_wdt_resume(struct platform_device *pdev)
-{
-       if (wdt->users)
-               at32_wdt_start();
-       return 0;
-}
-#else
-#define at32_wdt_suspend NULL
-#define at32_wdt_resume NULL
-#endif
-
-static struct platform_driver at32_wdt_driver = {
-       .remove         = __exit_p(at32_wdt_remove),
-       .suspend        = at32_wdt_suspend,
-       .resume         = at32_wdt_resume,
-       .driver         = {
-               .name   = "at32_wdt",
-               .owner  = THIS_MODULE,
-       },
-       .shutdown       = at32_wdt_shutdown,
-};
-
-static int __init at32_wdt_init(void)
-{
-       return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe);
-}
-module_init(at32_wdt_init);
-
-static void __exit at32_wdt_exit(void)
-{
-       platform_driver_unregister(&at32_wdt_driver);
-}
-module_exit(at32_wdt_exit);
-
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
-MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c
deleted file mode 100644 (file)
index 38bd373..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Watchdog driver for Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) 2003 SAN People (Pty) Ltd
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/watchdog.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/arch/at91_st.h>
-
-
-#define WDT_DEFAULT_TIME       5       /* seconds */
-#define WDT_MAX_TIME           256     /* seconds */
-
-static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-module_param(wdt_time, int, 0);
-MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-#endif
-
-
-static unsigned long at91wdt_busy;
-
-/* ......................................................................... */
-
-/*
- * Disable the watchdog.
- */
-static void inline at91_wdt_stop(void)
-{
-       at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
-}
-
-/*
- * Enable and reset the watchdog.
- */
-static void inline at91_wdt_start(void)
-{
-       at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
-       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-/*
- * Reload the watchdog timer.  (ie, pat the watchdog)
- */
-static void inline at91_wdt_reload(void)
-{
-       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-/* ......................................................................... */
-
-/*
- * Watchdog device is opened, and watchdog starts running.
- */
-static int at91_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &at91wdt_busy))
-               return -EBUSY;
-
-       at91_wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-/*
- * Close the watchdog device.
- * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
- *  disabled.
- */
-static int at91_wdt_close(struct inode *inode, struct file *file)
-{
-       if (!nowayout)
-               at91_wdt_stop();        /* Disable the watchdog when file is closed */
-
-       clear_bit(0, &at91wdt_busy);
-       return 0;
-}
-
-/*
- * Change the watchdog time interval.
- */
-static int at91_wdt_settimeout(int new_time)
-{
-       /*
-        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
-        *
-        * Since WDV is a 16-bit counter, the maximum period is
-        * 65536 / 0.256 = 256 seconds.
-        */
-       if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
-               return -EINVAL;
-
-       /* Set new watchdog time. It will be used when at91_wdt_start() is called. */
-       wdt_time = new_time;
-       return 0;
-}
-
-static struct watchdog_info at91_wdt_info = {
-       .identity       = "at91 watchdog",
-       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-};
-
-/*
- * Handle commands from user-space.
- */
-static int at91_wdt_ioctl(struct inode *inode, struct file *file,
-               unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_value;
-
-       switch(cmd) {
-               case WDIOC_KEEPALIVE:
-                       at91_wdt_reload();      /* pat the watchdog */
-                       return 0;
-
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_value, p))
-                               return -EFAULT;
-
-                       if (at91_wdt_settimeout(new_value))
-                               return -EINVAL;
-
-                       /* Enable new time value */
-                       at91_wdt_start();
-
-                       /* Return current value */
-                       return put_user(wdt_time, p);
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(wdt_time, p);
-
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-
-               case WDIOC_SETOPTIONS:
-                       if (get_user(new_value, p))
-                               return -EFAULT;
-
-                       if (new_value & WDIOS_DISABLECARD)
-                               at91_wdt_stop();
-                       if (new_value & WDIOS_ENABLECARD)
-                               at91_wdt_start();
-                       return 0;
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-/*
- * Pat the watchdog whenever device is written to.
- */
-static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       at91_wdt_reload();              /* pat the watchdog */
-       return len;
-}
-
-/* ......................................................................... */
-
-static const struct file_operations at91wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .ioctl          = at91_wdt_ioctl,
-       .open           = at91_wdt_open,
-       .release        = at91_wdt_close,
-       .write          = at91_wdt_write,
-};
-
-static struct miscdevice at91wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &at91wdt_fops,
-};
-
-static int __init at91wdt_probe(struct platform_device *pdev)
-{
-       int res;
-
-       if (at91wdt_miscdev.parent)
-               return -EBUSY;
-       at91wdt_miscdev.parent = &pdev->dev;
-
-       res = misc_register(&at91wdt_miscdev);
-       if (res)
-               return res;
-
-       printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : "");
-       return 0;
-}
-
-static int __exit at91wdt_remove(struct platform_device *pdev)
-{
-       int res;
-
-       res = misc_deregister(&at91wdt_miscdev);
-       if (!res)
-               at91wdt_miscdev.parent = NULL;
-
-       return res;
-}
-
-static void at91wdt_shutdown(struct platform_device *pdev)
-{
-       at91_wdt_stop();
-}
-
-#ifdef CONFIG_PM
-
-static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
-{
-       at91_wdt_stop();
-       return 0;
-}
-
-static int at91wdt_resume(struct platform_device *pdev)
-{
-       if (at91wdt_busy)
-               at91_wdt_start();
-               return 0;
-}
-
-#else
-#define at91wdt_suspend NULL
-#define at91wdt_resume NULL
-#endif
-
-static struct platform_driver at91wdt_driver = {
-       .probe          = at91wdt_probe,
-       .remove         = __exit_p(at91wdt_remove),
-       .shutdown       = at91wdt_shutdown,
-       .suspend        = at91wdt_suspend,
-       .resume         = at91wdt_resume,
-       .driver         = {
-               .name   = "at91_wdt",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init at91_wdt_init(void)
-{
-       /* Check that the heartbeat value is within range; if not reset to the default */
-       if (at91_wdt_settimeout(wdt_time)) {
-               at91_wdt_settimeout(WDT_DEFAULT_TIME);
-               pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
-       }
-
-       return platform_driver_register(&at91wdt_driver);
-}
-
-static void __exit at91_wdt_exit(void)
-{
-       platform_driver_unregister(&at91wdt_driver);
-}
-
-module_init(at91_wdt_init);
-module_exit(at91_wdt_exit);
-
-MODULE_AUTHOR("Andrew Victor");
-MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/bfin_wdt.c b/drivers/char/watchdog/bfin_wdt.c
deleted file mode 100644 (file)
index 309d279..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index d362f5b..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * drivers/char/watchdog/booke_wdt.c
- *
- * Watchdog timer for PowerPC Book-E systems
- *
- * Author: Matthew McClintock
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * Copyright 2005 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/notifier.h>
-#include <linux/watchdog.h>
-
-#include <asm/reg_booke.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
- * Also, the wdt_period sets the watchdog timer period timeout.
- * For E500 cpus the wdt_period sets which bit changing from 0->1 will
- * trigger a watchog timeout. This watchdog timeout will occur 3 times, the
- * first time nothing will happen, the second time a watchdog exception will
- * occur, and the final time the board will reset.
- */
-
-#ifdef CONFIG_FSL_BOOKE
-#define WDT_PERIOD_DEFAULT 63  /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */
-#else
-#define WDT_PERIOD_DEFAULT 3   /* Refer to the PPC40x and PPC4xx manuals */
-#endif                         /* for timing information */
-
-u32 booke_wdt_enabled = 0;
-u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
-
-#ifdef CONFIG_FSL_BOOKE
-#define WDTP(x)                ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
-#else
-#define WDTP(x)                (TCR_WP(x))
-#endif
-
-/*
- * booke_wdt_ping:
- */
-static __inline__ void booke_wdt_ping(void)
-{
-       mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
-}
-
-/*
- * booke_wdt_enable:
- */
-static __inline__ void booke_wdt_enable(void)
-{
-       u32 val;
-
-       /* clear status before enabling watchdog */
-       booke_wdt_ping();
-       val = mfspr(SPRN_TCR);
-       val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
-
-       mtspr(SPRN_TCR, val);
-}
-
-/*
- * booke_wdt_write:
- */
-static ssize_t booke_wdt_write (struct file *file, const char __user *buf,
-                               size_t count, loff_t *ppos)
-{
-       booke_wdt_ping();
-       return count;
-}
-
-static struct watchdog_info ident = {
-  .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-  .firmware_version = 0,
-  .identity = "PowerPC Book-E Watchdog",
-};
-
-/*
- * booke_wdt_ioctl:
- */
-static int booke_wdt_ioctl (struct inode *inode, struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       u32 tmp = 0;
-       u32 __user *p = (u32 __user *)arg;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user ((struct watchdog_info __user *) arg, &ident,
-                               sizeof(struct watchdog_info)))
-                       return -EFAULT;
-       case WDIOC_GETSTATUS:
-               return put_user(ident.options, p);
-       case WDIOC_GETBOOTSTATUS:
-               /* XXX: something is clearing TSR */
-               tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
-               /* returns 1 if last reset was caused by the WDT */
-               return (tmp ? 1 : 0);
-       case WDIOC_KEEPALIVE:
-               booke_wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(booke_wdt_period, p))
-                       return -EFAULT;
-               mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
-               return 0;
-       case WDIOC_GETTIMEOUT:
-               return put_user(booke_wdt_period, p);
-       case WDIOC_SETOPTIONS:
-               if (get_user(tmp, p))
-                       return -EINVAL;
-               if (tmp == WDIOS_ENABLECARD) {
-                       booke_wdt_ping();
-                       break;
-               } else
-                       return -EINVAL;
-               return 0;
-       default:
-               return -ENOTTY;
-       }
-
-       return 0;
-}
-/*
- * booke_wdt_open:
- */
-static int booke_wdt_open (struct inode *inode, struct file *file)
-{
-       if (booke_wdt_enabled == 0) {
-               booke_wdt_enabled = 1;
-               booke_wdt_enable();
-               printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
-                               booke_wdt_period);
-       }
-
-       return nonseekable_open(inode, file);
-}
-
-static const struct file_operations booke_wdt_fops = {
-  .owner = THIS_MODULE,
-  .llseek = no_llseek,
-  .write = booke_wdt_write,
-  .ioctl = booke_wdt_ioctl,
-  .open = booke_wdt_open,
-};
-
-static struct miscdevice booke_wdt_miscdev = {
-  .minor = WATCHDOG_MINOR,
-  .name = "watchdog",
-  .fops = &booke_wdt_fops,
-};
-
-static void __exit booke_wdt_exit(void)
-{
-       misc_deregister(&booke_wdt_miscdev);
-}
-
-/*
- * booke_wdt_init:
- */
-static int __init booke_wdt_init(void)
-{
-       int ret = 0;
-
-       printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
-       ident.firmware_version = cur_cpu_spec->pvr_value;
-
-       ret = misc_register(&booke_wdt_miscdev);
-       if (ret) {
-               printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
-                               WATCHDOG_MINOR, ret);
-               return ret;
-       }
-
-       if (booke_wdt_enabled == 1) {
-               printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
-                               booke_wdt_period);
-               booke_wdt_enable();
-       }
-
-       return ret;
-}
-device_initcall(booke_wdt_init);
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
deleted file mode 100644 (file)
index 5941ca6..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * sma cpu5 watchdog driver
- *
- * Copyright (C) 2003 Heiko Ronsdorf <hero@ihg.uni-duisburg.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/watchdog.h>
-
-/* adjustable parameters */
-
-static int verbose = 0;
-static int port = 0x91;
-static int ticks = 10000;
-
-#define PFX                    "cpu5wdt: "
-
-#define CPU5WDT_EXTENT          0x0A
-
-#define CPU5WDT_STATUS_REG      0x00
-#define CPU5WDT_TIME_A_REG      0x02
-#define CPU5WDT_TIME_B_REG      0x03
-#define CPU5WDT_MODE_REG        0x04
-#define CPU5WDT_TRIGGER_REG     0x07
-#define CPU5WDT_ENABLE_REG      0x08
-#define CPU5WDT_RESET_REG       0x09
-
-#define CPU5WDT_INTERVAL       (HZ/10+1)
-
-/* some device data */
-
-static struct {
-       struct completion stop;
-       volatile int running;
-       struct timer_list timer;
-       volatile int queue;
-       int default_ticks;
-       unsigned long inuse;
-} cpu5wdt_device;
-
-/* generic helper functions */
-
-static void cpu5wdt_trigger(unsigned long unused)
-{
-       if ( verbose > 2 )
-               printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
-
-       if( cpu5wdt_device.running )
-               ticks--;
-
-       /* keep watchdog alive */
-       outb(1, port + CPU5WDT_TRIGGER_REG);
-
-       /* requeue?? */
-       if (cpu5wdt_device.queue && ticks)
-               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
-       else {
-               /* ticks doesn't matter anyway */
-               complete(&cpu5wdt_device.stop);
-       }
-
-}
-
-static void cpu5wdt_reset(void)
-{
-       ticks = cpu5wdt_device.default_ticks;
-
-       if ( verbose )
-               printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
-
-}
-
-static void cpu5wdt_start(void)
-{
-       if ( !cpu5wdt_device.queue ) {
-               cpu5wdt_device.queue = 1;
-               outb(0, port + CPU5WDT_TIME_A_REG);
-               outb(0, port + CPU5WDT_TIME_B_REG);
-               outb(1, port + CPU5WDT_MODE_REG);
-               outb(0, port + CPU5WDT_RESET_REG);
-               outb(0, port + CPU5WDT_ENABLE_REG);
-               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
-       }
-       /* if process dies, counter is not decremented */
-       cpu5wdt_device.running++;
-}
-
-static int cpu5wdt_stop(void)
-{
-       if ( cpu5wdt_device.running )
-               cpu5wdt_device.running = 0;
-
-       ticks = cpu5wdt_device.default_ticks;
-
-       if ( verbose )
-               printk(KERN_CRIT PFX "stop not possible\n");
-
-       return -EIO;
-}
-
-/* filesystem operations */
-
-static int cpu5wdt_open(struct inode *inode, struct file *file)
-{
-       if ( test_and_set_bit(0, &cpu5wdt_device.inuse) )
-               return -EBUSY;
-
-       return nonseekable_open(inode, file);
-}
-
-static int cpu5wdt_release(struct inode *inode, struct file *file)
-{
-       clear_bit(0, &cpu5wdt_device.inuse);
-       return 0;
-}
-
-static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       unsigned int value;
-       static struct watchdog_info ident =
-       {
-               .options = WDIOF_CARDRESET,
-               .identity = "CPU5 WDT",
-       };
-
-       switch(cmd) {
-               case WDIOC_KEEPALIVE:
-                       cpu5wdt_reset();
-                       break;
-               case WDIOC_GETSTATUS:
-                       value = inb(port + CPU5WDT_STATUS_REG);
-                       value = (value >> 2) & 1;
-                       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;
-                       break;
-               case WDIOC_SETOPTIONS:
-                       if ( copy_from_user(&value, argp, sizeof(int)) )
-                               return -EFAULT;
-                       switch(value) {
-                               case WDIOS_ENABLECARD:
-                                       cpu5wdt_start();
-                                       break;
-                               case WDIOS_DISABLECARD:
-                                       return cpu5wdt_stop();
-                               default:
-                                       return -EINVAL;
-                       }
-                       break;
-               default:
-                       return -ENOTTY;
-       }
-       return 0;
-}
-
-static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if ( !count )
-               return -EIO;
-
-       cpu5wdt_reset();
-
-       return count;
-}
-
-static const struct file_operations cpu5wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .ioctl          = cpu5wdt_ioctl,
-       .open           = cpu5wdt_open,
-       .write          = cpu5wdt_write,
-       .release        = cpu5wdt_release,
-};
-
-static struct miscdevice cpu5wdt_misc = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &cpu5wdt_fops,
-};
-
-/* init/exit function */
-
-static int __devinit cpu5wdt_init(void)
-{
-       unsigned int val;
-       int err;
-
-       if ( verbose )
-               printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose);
-
-       if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) {
-               printk(KERN_ERR PFX "request_region failed\n");
-               err = -EBUSY;
-               goto no_port;
-       }
-
-       if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
-               printk(KERN_ERR PFX "misc_register failed\n");
-               goto no_misc;
-       }
-
-       /* watchdog reboot? */
-       val = inb(port + CPU5WDT_STATUS_REG);
-       val = (val >> 2) & 1;
-       if ( !val )
-               printk(KERN_INFO PFX "sorry, was my fault\n");
-
-       init_completion(&cpu5wdt_device.stop);
-       cpu5wdt_device.queue = 0;
-
-       clear_bit(0, &cpu5wdt_device.inuse);
-
-       setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
-
-       cpu5wdt_device.default_ticks = ticks;
-
-       printk(KERN_INFO PFX "init success\n");
-
-       return 0;
-
-no_misc:
-       release_region(port, CPU5WDT_EXTENT);
-no_port:
-       return err;
-}
-
-static int __devinit cpu5wdt_init_module(void)
-{
-       return cpu5wdt_init();
-}
-
-static void __devexit cpu5wdt_exit(void)
-{
-       if ( cpu5wdt_device.queue ) {
-               cpu5wdt_device.queue = 0;
-               wait_for_completion(&cpu5wdt_device.stop);
-       }
-
-       misc_deregister(&cpu5wdt_misc);
-
-       release_region(port, CPU5WDT_EXTENT);
-
-}
-
-static void __devexit cpu5wdt_exit_module(void)
-{
-       cpu5wdt_exit();
-}
-
-/* module entry points */
-
-module_init(cpu5wdt_init_module);
-module_exit(cpu5wdt_exit_module);
-
-MODULE_AUTHOR("Heiko Ronsdorf <hero@ihg.uni-duisburg.de>");
-MODULE_DESCRIPTION("sma cpu5 watchdog driver");
-MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-module_param(port, int, 0);
-MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
-
-module_param(verbose, int, 0);
-MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
-
-module_param(ticks, int, 0);
-MODULE_PARM_DESC(ticks, "count down ticks, default is 10000");
diff --git a/drivers/char/watchdog/davinci_wdt.c b/drivers/char/watchdog/davinci_wdt.c
deleted file mode 100644 (file)
index 19db530..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * 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);
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
deleted file mode 100644 (file)
index 0e4787a..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Watchdog driver for Cirrus Logic EP93xx family of devices.
- *
- * Copyright (c) 2004 Ray Lehtiniemi
- * Copyright (c) 2006 Tower Technologies
- * Based on ep93xx driver, bits from alim7101_wdt.c
- *
- * Authors: Ray Lehtiniemi <rayl@mail.com>,
- *     Alessandro Zummo <a.zummo@towertech.it>
- *
- * 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.
- *
- * This watchdog fires after 250msec, which is a too short interval
- * for us to rely on the user space daemon alone. So we ping the
- * wdt each ~200msec and eventually stop doing it if the user space
- * daemon dies.
- *
- * TODO:
- *
- *     - Test last reset from watchdog status
- *     - Add a few missing ioctls
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/timer.h>
-
-#include <asm/hardware.h>
-#include <asm/uaccess.h>
-
-#define WDT_VERSION    "0.3"
-#define PFX            "ep93xx_wdt: "
-
-/* default timeout (secs) */
-#define WDT_TIMEOUT 30
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int timeout = WDT_TIMEOUT;
-
-static struct timer_list timer;
-static unsigned long next_heartbeat;
-static unsigned long wdt_status;
-static unsigned long boot_status;
-
-#define WDT_IN_USE             0
-#define WDT_OK_TO_CLOSE                1
-
-#define EP93XX_WDT_REG(x)      (EP93XX_WATCHDOG_BASE + (x))
-#define EP93XX_WDT_WATCHDOG    EP93XX_WDT_REG(0x00)
-#define EP93XX_WDT_WDSTATUS    EP93XX_WDT_REG(0x04)
-
-/* reset the wdt every ~200ms */
-#define WDT_INTERVAL (HZ/5)
-
-static void wdt_enable(void)
-{
-       __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG);
-}
-
-static void wdt_disable(void)
-{
-       __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG);
-}
-
-static inline void wdt_ping(void)
-{
-       __raw_writew(0x5555, EP93XX_WDT_WATCHDOG);
-}
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + (timeout * HZ);
-
-       wdt_enable();
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-}
-
-static void wdt_shutdown(void)
-{
-       del_timer_sync(&timer);
-       wdt_disable();
-}
-
-static void wdt_keepalive(void)
-{
-       /* user land ping */
-       next_heartbeat = jiffies + (timeout * HZ);
-}
-
-static int ep93xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_startup();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
-                loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                               else
-                                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_keepalive();
-       }
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
-       .identity = "EP93xx Watchdog",
-};
-
-static int
-ep93xx_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 __user *)arg, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int __user *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int __user *)arg);
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               /* actually, it is 0.250 seconds.... */
-               ret = put_user(1, (int __user *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_keepalive();
-               ret = 0;
-               break;
-       }
-       return ret;
-}
-
-static int ep93xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               wdt_shutdown();
-       else
-               printk(KERN_CRIT PFX "Device closed unexpectedly - "
-                       "timer will not stop\n");
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations ep93xx_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .write          = ep93xx_wdt_write,
-       .ioctl          = ep93xx_wdt_ioctl,
-       .open           = ep93xx_wdt_open,
-       .release        = ep93xx_wdt_release,
-};
-
-static struct miscdevice ep93xx_wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ep93xx_wdt_fops,
-};
-
-static void ep93xx_timer_ping(unsigned long data)
-{
-       if (time_before(jiffies, next_heartbeat))
-               wdt_ping();
-
-       /* Re-set the timer interval */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-}
-
-static int __init ep93xx_wdt_init(void)
-{
-       int err;
-
-       err = misc_register(&ep93xx_wdt_miscdev);
-
-       boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0;
-
-       printk(KERN_INFO PFX "EP93XX watchdog, driver version "
-               WDT_VERSION "%s\n",
-               (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08)
-               ? " (nCS1 disable detected)" : "");
-
-       if (timeout < 1 || timeout > 3600) {
-               timeout = WDT_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1<=x<=3600, using %d\n",
-                       timeout);
-       }
-
-       setup_timer(&timer, ep93xx_timer_ping, 1);
-       return err;
-}
-
-static void __exit ep93xx_wdt_exit(void)
-{
-       wdt_shutdown();
-       misc_deregister(&ep93xx_wdt_miscdev);
-}
-
-module_init(ep93xx_wdt_init);
-module_exit(ep93xx_wdt_exit);
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
-               "Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("EP93xx Watchdog");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(WDT_VERSION);
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
deleted file mode 100644 (file)
index b14e9d1..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- *     Eurotech CPU-1220/1410/1420 on board WDT driver
- *
- *     (c) Copyright 2001 Ascensit <support@ascensit.com>
- *     (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
- *     (c) Copyright 2002 Rob Radez <rob@osinvestor.com>
- *
- *     Based on wdt.c.
- *     Original copyright messages:
- *
- *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                              http://www.redhat.com
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *      warranty for any of this software. This material is provided
- *      "AS-IS" and at no charge.
- *
- *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>*
- */
-
-/* Changelog:
- *
- * 2001 - Rodolfo Giometti
- *     Initial release
- *
- * 2002/04/25 - Rob Radez
- *     clean up #includes
- *     clean up locking
- *     make __setup param unique
- *     proper options in watchdog_info
- *     add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls
- *     add expect_close support
- *
- * 2002.05.30 - Joel Becker <joel.becker@oracle.com>
- *     Added Matt Domsch's nowayout module option.
- */
-
-/*
- *     The eurotech CPU-1220/1410/1420's watchdog is a part
- *     of the on-board SUPER I/O device SMSC FDC 37B782.
- */
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static unsigned long eurwdt_is_open;
-static int eurwdt_timeout;
-static char eur_expect_close;
-
-/*
- * You must set these - there is no sane way to probe for this board.
- * You can use eurwdt=x,y to set these now.
- */
-
-static int io = 0x3f0;
-static int irq = 10;
-static char *ev = "int";
-
-#define WDT_TIMEOUT            60                /* 1 minute */
-
-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) ")");
-
-/*
- * Some symbolic names
- */
-
-#define WDT_CTRL_REG           0x30
-#define WDT_OUTPIN_CFG         0xe2
-#define WDT_EVENT_INT          0x00
-#define WDT_EVENT_REBOOT       0x08
-#define WDT_UNIT_SEL           0xf1
-#define WDT_UNIT_SECS          0x80
-#define WDT_TIMEOUT_VAL                0xf2
-#define WDT_TIMER_CFG          0xf3
-
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
-module_param(ev, charp, 0);
-MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `int')");
-
-
-/*
- * Programming support
- */
-
-static inline void eurwdt_write_reg(u8 index, u8 data)
-{
-       outb(index, io);
-       outb(data, io+1);
-}
-
-static inline void eurwdt_lock_chip(void)
-{
-       outb(0xaa, io);
-}
-
-static inline void eurwdt_unlock_chip(void)
-{
-       outb(0x55, io);
-       eurwdt_write_reg(0x07, 0x08);   /* set the logical device */
-}
-
-static inline void eurwdt_set_timeout(int timeout)
-{
-       eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout);
-}
-
-static inline void eurwdt_disable_timer(void)
-{
-       eurwdt_set_timeout(0);
-}
-
-static void eurwdt_activate_timer(void)
-{
-       eurwdt_disable_timer();
-       eurwdt_write_reg(WDT_CTRL_REG, 0x01);   /* activate the WDT */
-       eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT);
-
-       /* Setting interrupt line */
-       if (irq == 2 || irq > 15 || irq < 0) {
-               printk(KERN_ERR ": invalid irq number\n");
-               irq = 0;        /* if invalid we disable interrupt */
-       }
-       if (irq == 0)
-               printk(KERN_INFO ": interrupt disabled\n");
-
-       eurwdt_write_reg(WDT_TIMER_CFG, irq<<4);
-
-       eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS);  /* we use seconds */
-       eurwdt_set_timeout(0);  /* the default timeout */
-}
-
-
-/*
- * Kernel methods.
- */
-
-static irqreturn_t eurwdt_interrupt(int irq, void *dev_id)
-{
-       printk(KERN_CRIT "timeout WDT timeout\n");
-
-#ifdef ONLY_TESTING
-       printk(KERN_CRIT "Would Reboot.\n");
-#else
-       printk(KERN_CRIT "Initiating system reboot.\n");
-       emergency_restart();
-#endif
-       return IRQ_HANDLED;
-}
-
-
-/**
- * eurwdt_ping:
- *
- * Reload counter one with the watchdog timeout.
- */
-
-static void eurwdt_ping(void)
-{
-       /* Write the watchdog default value */
-       eurwdt_set_timeout(eurwdt_timeout);
-}
-
-/**
- * eurwdt_write:
- * @file: file handle to the watchdog
- * @buf: buffer to write (unused as data does not matter here
- * @count: count of bytes
- * @ppos: pointer to the position to write. No seeks allowed
- *
- * A write to a watchdog device is defined as a keepalive signal. Any
- * write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t eurwdt_write(struct file *file, const char __user *buf,
-size_t count, loff_t *ppos)
-{
-       if (count)      {
-               if (!nowayout) {
-                       size_t i;
-
-                       eur_expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if(get_user(c, buf+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       eur_expect_close = 42;
-                       }
-               }
-               eurwdt_ping();  /* the default timeout */
-       }
-
-       return count;
-}
-
-/**
- * eurwdt_ioctl:
- * @inode: inode of the device
- * @file: file handle to the device
- * @cmd: watchdog command
- * @arg: argument pointer
- *
- * The watchdog API defines a common set of functions for all watchdogs
- * according to their available features.
- */
-
-static int eurwdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options          = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity         = "WDT Eurotech CPU-1220/1410",
-       };
-
-       int time;
-       int options, retval = -EINVAL;
-
-       switch(cmd) {
-       default:
-               return -ENOTTY;
-
-       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:
-               eurwdt_ping();
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (copy_from_user(&time, p, sizeof(int)))
-                       return -EFAULT;
-
-               /* Sanity check */
-               if (time < 0 || time > 255)
-                       return -EINVAL;
-
-               eurwdt_timeout = time;
-               eurwdt_set_timeout(time);
-               /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(eurwdt_timeout, p);
-
-       case WDIOC_SETOPTIONS:
-               if (get_user(options, p))
-                       return -EFAULT;
-               if (options & WDIOS_DISABLECARD) {
-                       eurwdt_disable_timer();
-                       retval = 0;
-               }
-               if (options & WDIOS_ENABLECARD) {
-                       eurwdt_activate_timer();
-                       eurwdt_ping();
-                       retval = 0;
-               }
-               return retval;
-       }
-}
-
-/**
- * eurwdt_open:
- * @inode: inode of device
- * @file: file handle to device
- *
- * The misc device has been opened. The watchdog device is single
- * open and on opening we load the counter.
- */
-
-static int eurwdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &eurwdt_is_open))
-               return -EBUSY;
-       eurwdt_timeout = WDT_TIMEOUT;   /* initial timeout */
-       /* Activate the WDT */
-       eurwdt_activate_timer();
-       return nonseekable_open(inode, file);
-}
-
-/**
- * eurwdt_release:
- * @inode: inode to board
- * @file: file handle to board
- *
- * The watchdog has a configurable API. There is a religious dispute
- * between people who want their watchdog to be able to shut down and
- * those who want to be sure if the watchdog manager dies the machine
- * reboots. In the former case we disable the counters, in the latter
- * case you have to open it again very soon.
- */
-
-static int eurwdt_release(struct inode *inode, struct file *file)
-{
-       if (eur_expect_close == 42) {
-               eurwdt_disable_timer();
-       } else {
-               printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
-               eurwdt_ping();
-       }
-       clear_bit(0, &eurwdt_is_open);
-       eur_expect_close = 0;
-       return 0;
-}
-
-/**
- * eurwdt_notify_sys:
- * @this: our notifier block
- * @code: the event being reported
- * @unused: unused
- *
- * Our notifier is called on system shutdowns. We want to turn the card
- * off at reboot otherwise the machine will reboot again during memory
- * test or worse yet during the following fsck. This would suck, in fact
- * trust me - if it happens it does suck.
- */
-
-static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the card off */
-               eurwdt_disable_timer();
-       }
-
-       return NOTIFY_DONE;
-}
-
-/*
- * Kernel Interfaces
- */
-
-
-static const struct file_operations eurwdt_fops = {
-       .owner  = THIS_MODULE,
-       .llseek = no_llseek,
-       .write  = eurwdt_write,
-       .ioctl  = eurwdt_ioctl,
-       .open   = eurwdt_open,
-       .release        = eurwdt_release,
-};
-
-static struct miscdevice eurwdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &eurwdt_fops,
-};
-
-/*
- * The WDT card needs to learn about soft shutdowns in order to
- * turn the timebomb registers off.
- */
-
-static struct notifier_block eurwdt_notifier = {
-       .notifier_call = eurwdt_notify_sys,
-};
-
-/**
- * cleanup_module:
- *
- * Unload the watchdog. You cannot do this with any file handles open.
- * If your watchdog is set to continue ticking on close and you unload
- * it, well it keeps ticking. We won't get the interrupt but the board
- * will not touch PC memory so all is fine. You just have to load a new
- * module in 60 seconds or reboot.
- */
-
-static void __exit eurwdt_exit(void)
-{
-       eurwdt_lock_chip();
-
-       misc_deregister(&eurwdt_miscdev);
-
-       unregister_reboot_notifier(&eurwdt_notifier);
-       release_region(io, 2);
-       free_irq(irq, NULL);
-}
-
-/**
- * eurwdt_init:
- *
- * Set up the WDT watchdog board. After grabbing the resources
- * we require we need also to unlock the device.
- * The open() function will actually kick the board off.
- */
-
-static int __init eurwdt_init(void)
-{
-       int ret;
-
-       ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
-       if(ret) {
-               printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
-               goto out;
-       }
-
-       if (!request_region(io, 2, "eurwdt")) {
-               printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
-               ret = -EBUSY;
-               goto outirq;
-       }
-
-       ret = register_reboot_notifier(&eurwdt_notifier);
-       if (ret) {
-               printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret);
-               goto outreg;
-       }
-
-       ret = misc_register(&eurwdt_miscdev);
-       if (ret) {
-               printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
-               WATCHDOG_MINOR);
-               goto outreboot;
-       }
-
-       eurwdt_unlock_chip();
-
-       ret = 0;
-       printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
-               " - timeout event: %s\n",
-               io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
-
-out:
-       return ret;
-
-outreboot:
-       unregister_reboot_notifier(&eurwdt_notifier);
-
-outreg:
-       release_region(io, 2);
-
-outirq:
-       free_irq(irq, NULL);
-       goto out;
-}
-
-module_init(eurwdt_init);
-module_exit(eurwdt_exit);
-
-MODULE_AUTHOR("Rodolfo Giometti");
-MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
deleted file mode 100644 (file)
index c598250..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- *     i6300esb:       Watchdog timer driver for Intel 6300ESB chipset
- *
- *     (c) Copyright 2004 Google Inc.
- *     (c) Copyright 2005 David Härdeman <david@2gen.com>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *      based on i810-tco.c which is in turn based on softdog.c
- *
- *     The timer is implemented in the following I/O controller hubs:
- *     (See the intel documentation on http://developer.intel.com.)
- *     6300ESB chip : document number 300641-003
- *
- *  2004YYZZ Ross Biro
- *     Initial version 0.01
- *  2004YYZZ Ross Biro
- *     Version 0.02
- *  20050210 David Härdeman <david@2gen.com>
- *      Ported driver to kernel 2.6
- */
-
-/*
- *      Includes, defines, variables, module parameters, ...
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-/* Module and version information */
-#define ESB_VERSION "0.03"
-#define ESB_MODULE_NAME "i6300ESB timer"
-#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
-#define PFX ESB_MODULE_NAME ": "
-
-/* PCI configuration registers */
-#define ESB_CONFIG_REG  0x60            /* Config register                   */
-#define ESB_LOCK_REG    0x68            /* WDT lock register                 */
-
-/* Memory mapped registers */
-#define ESB_TIMER1_REG  BASEADDR + 0x00 /* Timer1 value after each reset     */
-#define ESB_TIMER2_REG  BASEADDR + 0x04 /* Timer2 value after each reset     */
-#define ESB_GINTSR_REG  BASEADDR + 0x08 /* General Interrupt Status Register */
-#define ESB_RELOAD_REG  BASEADDR + 0x0c /* Reload register                   */
-
-/* Lock register bits */
-#define ESB_WDT_FUNC    ( 0x01 << 2 )   /* Watchdog functionality            */
-#define ESB_WDT_ENABLE  ( 0x01 << 1 )   /* Enable WDT                        */
-#define ESB_WDT_LOCK    ( 0x01 << 0 )   /* Lock (nowayout)                   */
-
-/* Config register bits */
-#define ESB_WDT_REBOOT  ( 0x01 << 5 )   /* Enable reboot on timeout          */
-#define ESB_WDT_FREQ    ( 0x01 << 2 )   /* Decrement frequency               */
-#define ESB_WDT_INTTYPE ( 0x11 << 0 )   /* Interrupt type on timer1 timeout  */
-
-/* Reload register bits */
-#define ESB_WDT_RELOAD ( 0x01 << 8 )    /* prevent timeout                   */
-
-/* Magic constants */
-#define ESB_UNLOCK1     0x80            /* Step 1 to unlock reset registers  */
-#define ESB_UNLOCK2     0x86            /* Step 2 to unlock reset registers  */
-
-/* internal variables */
-static void __iomem *BASEADDR;
-static spinlock_t esb_lock; /* Guards the hardware */
-static unsigned long timer_alive;
-static struct pci_dev *esb_pci;
-static unsigned short triggered; /* The status of the watchdog upon boot */
-static char esb_expect_close;
-
-/* module parameters */
-#define WATCHDOG_HEARTBEAT 30   /* 30 sec default heartbeat (1<heartbeat<2*1023) */
-static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-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) ")");
-
-/*
- * Some i6300ESB specific functions
- */
-
-/*
- * Prepare for reloading the timer by unlocking the proper registers.
- * This is performed by first writing 0x80 followed by 0x86 to the
- * reload register. After this the appropriate registers can be written
- * to once before they need to be unlocked again.
- */
-static inline void esb_unlock_registers(void) {
-        writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
-        writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
-}
-
-static void esb_timer_start(void)
-{
-       u8 val;
-
-       /* Enable or Enable + Lock? */
-       val = 0x02 | (nowayout ? 0x01 : 0x00);
-
-        pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
-}
-
-static int esb_timer_stop(void)
-{
-       u8 val;
-
-       spin_lock(&esb_lock);
-       /* First, reset timers as suggested by the docs */
-       esb_unlock_registers();
-       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
-       /* Then disable the WDT */
-       pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
-       pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
-       spin_unlock(&esb_lock);
-
-       /* Returns 0 if the timer was disabled, non-zero otherwise */
-       return (val & 0x01);
-}
-
-static void esb_timer_keepalive(void)
-{
-       spin_lock(&esb_lock);
-       esb_unlock_registers();
-       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
-        /* FIXME: Do we need to flush anything here? */
-       spin_unlock(&esb_lock);
-}
-
-static int esb_timer_set_heartbeat(int time)
-{
-       u32 val;
-
-       if (time < 0x1 || time > (2 * 0x03ff))
-               return -EINVAL;
-
-       spin_lock(&esb_lock);
-
-       /* We shift by 9, so if we are passed a value of 1 sec,
-        * val will be 1 << 9 = 512, then write that to two
-        * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
-        */
-       val = time << 9;
-
-       /* Write timer 1 */
-       esb_unlock_registers();
-       writel(val, ESB_TIMER1_REG);
-
-       /* Write timer 2 */
-       esb_unlock_registers();
-        writel(val, ESB_TIMER2_REG);
-
-        /* Reload */
-       esb_unlock_registers();
-       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
-
-       /* FIXME: Do we need to flush everything out? */
-
-       /* Done */
-       heartbeat = time;
-       spin_unlock(&esb_lock);
-       return 0;
-}
-
-static int esb_timer_read (void)
-{
-               u32 count;
-
-       /* This isn't documented, and doesn't take into
-         * acount which stage is running, but it looks
-         * like a 20 bit count down, so we might as well report it.
-         */
-        pci_read_config_dword(esb_pci, 0x64, &count);
-        return (int)count;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int esb_open (struct inode *inode, struct file *file)
-{
-        /* /dev/watchdog can only be opened once */
-        if (test_and_set_bit(0, &timer_alive))
-                return -EBUSY;
-
-        /* Reload and activate timer */
-        esb_timer_keepalive ();
-        esb_timer_start ();
-
-       return nonseekable_open(inode, file);
-}
-
-static int esb_release (struct inode *inode, struct file *file)
-{
-        /* Shut off the timer. */
-        if (esb_expect_close == 42) {
-                esb_timer_stop ();
-        } else {
-                printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-                esb_timer_keepalive ();
-        }
-        clear_bit(0, &timer_alive);
-        esb_expect_close = 0;
-        return 0;
-}
-
-static ssize_t esb_write (struct file *file, const char __user *data,
-                         size_t len, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-        if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       esb_expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if(get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       esb_expect_close = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               esb_timer_keepalive ();
-       }
-       return len;
-}
-
-static int esb_ioctl (struct inode *inode, struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-       int new_options, retval = -EINVAL;
-       int new_heartbeat;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             ESB_MODULE_NAME,
-       };
-
-       switch (cmd) {
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &ident,
-                                           sizeof (ident)) ? -EFAULT : 0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user (esb_timer_read(), p);
-
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user (triggered, p);
-
-                case WDIOC_KEEPALIVE:
-                        esb_timer_keepalive ();
-                        return 0;
-
-                case WDIOC_SETOPTIONS:
-                {
-                        if (get_user (new_options, p))
-                                return -EFAULT;
-
-                        if (new_options & WDIOS_DISABLECARD) {
-                                esb_timer_stop ();
-                                retval = 0;
-                        }
-
-                        if (new_options & WDIOS_ENABLECARD) {
-                                esb_timer_keepalive ();
-                                esb_timer_start ();
-                                retval = 0;
-                        }
-
-                        return retval;
-                }
-
-                case WDIOC_SETTIMEOUT:
-                {
-                        if (get_user(new_heartbeat, p))
-                                return -EFAULT;
-
-                        if (esb_timer_set_heartbeat(new_heartbeat))
-                            return -EINVAL;
-
-                        esb_timer_keepalive ();
-                        /* Fall */
-                }
-
-                case WDIOC_GETTIMEOUT:
-                        return put_user(heartbeat, p);
-
-                default:
-                        return -ENOTTY;
-        }
-}
-
-/*
- *      Notify system
- */
-
-static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
-{
-        if (code==SYS_DOWN || code==SYS_HALT) {
-                /* Turn the WDT off */
-                esb_timer_stop ();
-        }
-
-        return NOTIFY_DONE;
-}
-
-/*
- *      Kernel Interfaces
- */
-
-static const struct file_operations esb_fops = {
-        .owner =        THIS_MODULE,
-        .llseek =       no_llseek,
-        .write =        esb_write,
-        .ioctl =        esb_ioctl,
-        .open =         esb_open,
-        .release =      esb_release,
-};
-
-static struct miscdevice esb_miscdev = {
-        .minor =        WATCHDOG_MINOR,
-        .name =         "watchdog",
-        .fops =         &esb_fops,
-};
-
-static struct notifier_block esb_notifier = {
-        .notifier_call =        esb_notify_sys,
-};
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id esb_pci_tbl[] = {
-        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
-        { 0, },                 /* End of list */
-};
-MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
-
-/*
- *      Init & exit routines
- */
-
-static unsigned char __init esb_getdevice (void)
-{
-       u8 val1;
-       unsigned short val2;
-
-        struct pci_dev *dev = NULL;
-        /*
-         *      Find the PCI device
-         */
-
-        for_each_pci_dev(dev) {
-                if (pci_match_id(esb_pci_tbl, dev)) {
-                        esb_pci = dev;
-                        break;
-                }
-       }
-
-        if (esb_pci) {
-               if (pci_enable_device(esb_pci)) {
-                       printk (KERN_ERR PFX "failed to enable device\n");
-                       goto err_devput;
-               }
-
-               if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
-                       printk (KERN_ERR PFX "failed to request region\n");
-                       goto err_disable;
-               }
-
-               BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
-                                  pci_resource_len(esb_pci, 0));
-               if (BASEADDR == NULL) {
-                       /* Something's wrong here, BASEADDR has to be set */
-                       printk (KERN_ERR PFX "failed to get BASEADDR\n");
-                        goto err_release;
-                }
-
-               /*
-                * The watchdog has two timers, it can be setup so that the
-                * expiry of timer1 results in an interrupt and the expiry of
-                * timer2 results in a reboot. We set it to not generate
-                * any interrupts as there is not much we can do with it
-                * right now.
-                *
-                * We also enable reboots and set the timer frequency to
-                * the PCI clock divided by 2^15 (approx 1KHz).
-                */
-               pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
-
-               /* Check that the WDT isn't already locked */
-               pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
-               if (val1 & ESB_WDT_LOCK)
-                       printk (KERN_WARNING PFX "nowayout already set\n");
-
-               /* Set the timer to watchdog mode and disable it for now */
-               pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
-
-               /* Check if the watchdog was previously triggered */
-               esb_unlock_registers();
-               val2 = readw(ESB_RELOAD_REG);
-               triggered = (val2 & (0x01 << 9) >> 9);
-
-               /* Reset trigger flag and timers */
-               esb_unlock_registers();
-               writew((0x11 << 8), ESB_RELOAD_REG);
-
-               /* Done */
-               return 1;
-
-err_release:
-               pci_release_region(esb_pci, 0);
-err_disable:
-               pci_disable_device(esb_pci);
-err_devput:
-               pci_dev_put(esb_pci);
-       }
-       return 0;
-}
-
-static int __init watchdog_init (void)
-{
-        int ret;
-
-        spin_lock_init(&esb_lock);
-
-        /* Check whether or not the hardware watchdog is there */
-        if (!esb_getdevice () || esb_pci == NULL)
-                return -ENODEV;
-
-        /* Check that the heartbeat value is within it's range ; if not reset to the default */
-        if (esb_timer_set_heartbeat (heartbeat)) {
-                esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
-                printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
-                      heartbeat);
-        }
-
-        ret = register_reboot_notifier(&esb_notifier);
-        if (ret != 0) {
-                printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                        ret);
-                goto err_unmap;
-        }
-
-        ret = misc_register(&esb_miscdev);
-        if (ret != 0) {
-                printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                        WATCHDOG_MINOR, ret);
-                goto err_notifier;
-        }
-
-        esb_timer_stop ();
-
-        printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
-                BASEADDR, heartbeat, nowayout);
-
-        return 0;
-
-err_notifier:
-        unregister_reboot_notifier(&esb_notifier);
-err_unmap:
-       iounmap(BASEADDR);
-/* err_release: */
-       pci_release_region(esb_pci, 0);
-/* err_disable: */
-       pci_disable_device(esb_pci);
-/* err_devput: */
-       pci_dev_put(esb_pci);
-        return ret;
-}
-
-static void __exit watchdog_cleanup (void)
-{
-       /* Stop the timer before we leave */
-       if (!nowayout)
-               esb_timer_stop ();
-
-       /* Deregister */
-       misc_deregister(&esb_miscdev);
-        unregister_reboot_notifier(&esb_notifier);
-       iounmap(BASEADDR);
-       pci_release_region(esb_pci, 0);
-       pci_disable_device(esb_pci);
-       pci_dev_put(esb_pci);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_cleanup);
-
-MODULE_AUTHOR("Ross Biro and David Härdeman");
-MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/iTCO_vendor_support.c b/drivers/char/watchdog/iTCO_vendor_support.c
deleted file mode 100644 (file)
index 4150839..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- *     intel TCO vendor specific watchdog driver support
- *
- *     (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
- *     provide warranty for any of this software. This material is
- *     provided "AS-IS" and at no charge.
- */
-
-/*
- *     Includes, defines, variables, module parameters, ...
- */
-
-/* Module and version information */
-#define DRV_NAME        "iTCO_vendor_support"
-#define DRV_VERSION     "1.01"
-#define DRV_RELDATE     "11-Nov-2006"
-#define PFX            DRV_NAME ": "
-
-/* Includes */
-#include <linux/module.h>              /* For module specific items */
-#include <linux/moduleparam.h>         /* For new moduleparam's */
-#include <linux/types.h>               /* For standard types (like size_t) */
-#include <linux/errno.h>               /* For the -ENODEV/... values */
-#include <linux/kernel.h>              /* For printk/panic/... */
-#include <linux/init.h>                        /* For __init/__exit/... */
-#include <linux/ioport.h>              /* For io-port access */
-
-#include <asm/io.h>                    /* For inb/outb/... */
-
-/* iTCO defines */
-#define        SMI_EN          acpibase + 0x30 /* SMI Control and Enable Register */
-#define        TCOBASE         acpibase + 0x60 /* TCO base address             */
-#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
-
-/* List of vendor support modes */
-#define SUPERMICRO_OLD_BOARD   1       /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
-#define SUPERMICRO_NEW_BOARD   2       /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */
-
-static int vendorsupport = 0;
-module_param(vendorsupport, int, 0);
-MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+");
-
-/*
- *     Vendor Specific Support
- */
-
-/*
- *     Vendor Support: 1
- *     Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE
- *     iTCO chipset: ICH2
- *
- *     Code contributed by: R. Seretny <lkpatches@paypc.com>
- *     Documentation obtained by R. Seretny from SuperMicro Technical Support
- *
- *     To enable Watchdog function:
- *         BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes
- *         This setting enables SMI to clear the watchdog expired flag.
- *         If BIOS or CPU fail which may cause SMI hang, then system will
- *         reboot. When application starts to use watchdog function,
- *         application has to take over the control from SMI.
- *
- *         For P3TSSE, J36 jumper needs to be removed to enable the Watchdog
- *         function.
- *
- *         Note: The system will reboot when Expire Flag is set TWICE.
- *         So, if the watchdog timer is 20 seconds, then the maximum hang
- *         time is about 40 seconds, and the minimum hang time is about
- *         20.6 seconds.
- */
-
-static void supermicro_old_pre_start(unsigned long acpibase)
-{
-       unsigned long val32;
-
-       val32 = inl(SMI_EN);
-       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
-       outl(val32, SMI_EN);    /* Needed to activate watchdog */
-}
-
-static void supermicro_old_pre_stop(unsigned long acpibase)
-{
-       unsigned long val32;
-
-       val32 = inl(SMI_EN);
-       val32 &= 0x00002000;    /* Turn on SMI clearing watchdog */
-       outl(val32, SMI_EN);    /* Needed to deactivate watchdog */
-}
-
-static void supermicro_old_pre_keepalive(unsigned long acpibase)
-{
-       /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
-       /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */
-       outb(0x08, TCO1_STS);
-}
-
-/*
- *     Vendor Support: 2
- *     Board: Super Micro Computer Inc. P4SBx, P4DPx
- *     iTCO chipset: ICH4
- *
- *     Code contributed by: R. Seretny <lkpatches@paypc.com>
- *     Documentation obtained by R. Seretny from SuperMicro Technical Support
- *
- *     To enable Watchdog function:
- *      1. BIOS
- *       For P4SBx:
- *       BIOS setup -> Advanced -> Integrated Peripherals -> Watch Dog Feature
- *       For P4DPx:
- *       BIOS setup -> Advanced -> I/O Device Configuration -> Watch Dog
- *      This setting enables or disables Watchdog function. When enabled, the
- *      default watchdog timer is set to be 5 minutes (about 4’35”). It is
- *      enough to load and run the OS. The application (service or driver) has
- *      to take over the control once OS is running up and before watchdog
- *      expires.
- *
- *      2. JUMPER
- *       For P4SBx: JP39
- *       For P4DPx: JP37
- *       This jumper is used for safety.  Closed is enabled. This jumper
- *       prevents user enables watchdog in BIOS by accident.
- *
- *      To enable Watch Dog function, both BIOS and JUMPER must be enabled.
- *
- *     The documentation lists motherboards P4SBx and P4DPx series as of
- *     20-March-2002. However, this code works flawlessly with much newer
- *     motherboards, such as my X6DHR-8G2 (SuperServer 6014H-82).
- *
- *     The original iTCO driver as written does not actually reset the
- *     watchdog timer on these machines, as a result they reboot after five
- *     minutes.
- *
- *     NOTE: You may leave the Watchdog function disabled in the SuperMicro
- *     BIOS to avoid a "boot-race"... This driver will enable watchdog
- *     functionality even if it's disabled in the BIOS once the /dev/watchdog
- *     file is opened.
- */
-
-/* I/O Port's */
-#define SM_REGINDEX    0x2e            /* SuperMicro ICH4+ Register Index */
-#define SM_DATAIO      0x2f            /* SuperMicro ICH4+ Register Data I/O */
-
-/* Control Register's */
-#define SM_CTLPAGESW   0x07            /* SuperMicro ICH4+ Control Page Switch */
-#define SM_CTLPAGE             0x08    /* SuperMicro ICH4+ Control Page Num */
-
-#define SM_WATCHENABLE 0x30            /* Watchdog enable: Bit 0: 0=off, 1=on */
-
-#define SM_WATCHPAGE   0x87            /* Watchdog unlock control page */
-
-#define SM_ENDWATCH    0xAA            /* Watchdog lock control page */
-
-#define SM_COUNTMODE   0xf5            /* Watchdog count mode select */
-                                       /* (Bit 3: 0 = seconds, 1 = minutes */
-
-#define SM_WATCHTIMER  0xf6            /* 8-bits, Watchdog timer counter (RW) */
-
-#define SM_RESETCONTROL        0xf7            /* Watchdog reset control */
-                                       /* Bit 6: timer is reset by kbd interrupt */
-                                       /* Bit 7: timer is reset by mouse interrupt */
-
-static void supermicro_new_unlock_watchdog(void)
-{
-       outb(SM_WATCHPAGE, SM_REGINDEX);        /* Write 0x87 to port 0x2e twice */
-       outb(SM_WATCHPAGE, SM_REGINDEX);
-
-       outb(SM_CTLPAGESW, SM_REGINDEX);        /* Switch to watchdog control page */
-       outb(SM_CTLPAGE, SM_DATAIO);
-}
-
-static void supermicro_new_lock_watchdog(void)
-{
-       outb(SM_ENDWATCH, SM_REGINDEX);
-}
-
-static void supermicro_new_pre_start(unsigned int heartbeat)
-{
-       unsigned int val;
-
-       supermicro_new_unlock_watchdog();
-
-       /* Watchdog timer setting needs to be in seconds*/
-       outb(SM_COUNTMODE, SM_REGINDEX);
-       val = inb(SM_DATAIO);
-       val &= 0xF7;
-       outb(val, SM_DATAIO);
-
-       /* Write heartbeat interval to WDOG */
-       outb (SM_WATCHTIMER, SM_REGINDEX);
-       outb((heartbeat & 255), SM_DATAIO);
-
-       /* Make sure keyboard/mouse interrupts don't interfere */
-       outb(SM_RESETCONTROL, SM_REGINDEX);
-       val = inb(SM_DATAIO);
-       val &= 0x3f;
-       outb(val, SM_DATAIO);
-
-       /* enable watchdog by setting bit 0 of Watchdog Enable to 1 */
-       outb(SM_WATCHENABLE, SM_REGINDEX);
-       val = inb(SM_DATAIO);
-       val |= 0x01;
-       outb(val, SM_DATAIO);
-
-       supermicro_new_lock_watchdog();
-}
-
-static void supermicro_new_pre_stop(void)
-{
-       unsigned int val;
-
-       supermicro_new_unlock_watchdog();
-
-       /* disable watchdog by setting bit 0 of Watchdog Enable to 0 */
-       outb(SM_WATCHENABLE, SM_REGINDEX);
-       val = inb(SM_DATAIO);
-       val &= 0xFE;
-       outb(val, SM_DATAIO);
-
-       supermicro_new_lock_watchdog();
-}
-
-static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
-{
-       supermicro_new_unlock_watchdog();
-
-       /* reset watchdog timeout to heartveat value */
-       outb(SM_WATCHTIMER, SM_REGINDEX);
-       outb((heartbeat & 255), SM_DATAIO);
-
-       supermicro_new_lock_watchdog();
-}
-
-/*
- *     Generic Support Functions
- */
-
-void iTCO_vendor_pre_start(unsigned long acpibase,
-                          unsigned int heartbeat)
-{
-       if (vendorsupport == SUPERMICRO_OLD_BOARD)
-               supermicro_old_pre_start(acpibase);
-       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
-               supermicro_new_pre_start(heartbeat);
-}
-EXPORT_SYMBOL(iTCO_vendor_pre_start);
-
-void iTCO_vendor_pre_stop(unsigned long acpibase)
-{
-       if (vendorsupport == SUPERMICRO_OLD_BOARD)
-               supermicro_old_pre_stop(acpibase);
-       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
-               supermicro_new_pre_stop();
-}
-EXPORT_SYMBOL(iTCO_vendor_pre_stop);
-
-void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
-{
-       if (vendorsupport == SUPERMICRO_OLD_BOARD)
-               supermicro_old_pre_keepalive(acpibase);
-       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
-               supermicro_new_pre_set_heartbeat(heartbeat);
-}
-EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
-
-void iTCO_vendor_pre_set_heartbeat(unsigned int heartbeat)
-{
-       if (vendorsupport == SUPERMICRO_NEW_BOARD)
-               supermicro_new_pre_set_heartbeat(heartbeat);
-}
-EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat);
-
-int iTCO_vendor_check_noreboot_on(void)
-{
-       switch(vendorsupport) {
-       case SUPERMICRO_OLD_BOARD:
-               return 0;
-       default:
-               return 1;
-       }
-}
-EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
-
-static int __init iTCO_vendor_init_module(void)
-{
-       printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
-       return 0;
-}
-
-static void __exit iTCO_vendor_exit_module(void)
-{
-       printk (KERN_INFO PFX "Module Unloaded\n");
-}
-
-module_init(iTCO_vendor_init_module);
-module_exit(iTCO_vendor_exit_module);
-
-MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, R. Seretny <lkpatches@paypc.com>");
-MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support");
-MODULE_VERSION(DRV_VERSION);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
deleted file mode 100644 (file)
index cd5a565..0000000
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- *     intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
- *
- *     (c) Copyright 2006-2007 Wim Van Sebroeck <wim@iguana.be>.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
- *     provide warranty for any of this software. This material is
- *     provided "AS-IS" and at no charge.
- *
- *     The TCO watchdog is implemented in the following I/O controller hubs:
- *     (See the intel documentation on http://developer.intel.com.)
- *     82801AA  (ICH)       : document number 290655-003, 290677-014,
- *     82801AB  (ICHO)      : document number 290655-003, 290677-014,
- *     82801BA  (ICH2)      : document number 290687-002, 298242-027,
- *     82801BAM (ICH2-M)    : document number 290687-002, 298242-027,
- *     82801CA  (ICH3-S)    : document number 290733-003, 290739-013,
- *     82801CAM (ICH3-M)    : document number 290716-001, 290718-007,
- *     82801DB  (ICH4)      : document number 290744-001, 290745-020,
- *     82801DBM (ICH4-M)    : document number 252337-001, 252663-005,
- *     82801E   (C-ICH)     : document number 273599-001, 273645-002,
- *     82801EB  (ICH5)      : document number 252516-001, 252517-003,
- *     82801ER  (ICH5R)     : document number 252516-001, 252517-003,
- *     82801FB  (ICH6)      : document number 301473-002, 301474-007,
- *     82801FR  (ICH6R)     : document number 301473-002, 301474-007,
- *     82801FBM (ICH6-M)    : document number 301473-002, 301474-007,
- *     82801FW  (ICH6W)     : document number 301473-001, 301474-007,
- *     82801FRW (ICH6RW)    : document number 301473-001, 301474-007,
- *     82801GB  (ICH7)      : document number 307013-002, 307014-009,
- *     82801GR  (ICH7R)     : document number 307013-002, 307014-009,
- *     82801GDH (ICH7DH)    : document number 307013-002, 307014-009,
- *     82801GBM (ICH7-M)    : document number 307013-002, 307014-009,
- *     82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
- *     82801HB  (ICH8)      : document number 313056-002, 313057-004,
- *     82801HR  (ICH8R)     : document number 313056-002, 313057-004,
- *     82801HH  (ICH8DH)    : document number 313056-002, 313057-004,
- *     82801HO  (ICH8DO)    : document number 313056-002, 313057-004,
- *     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
- */
-
-/*
- *     Includes, defines, variables, module parameters, ...
- */
-
-/* Module and version information */
-#define DRV_NAME        "iTCO_wdt"
-#define DRV_VERSION     "1.02"
-#define DRV_RELDATE     "26-Jul-2007"
-#define PFX            DRV_NAME ": "
-
-/* Includes */
-#include <linux/module.h>              /* For module specific items */
-#include <linux/moduleparam.h>         /* For new moduleparam's */
-#include <linux/types.h>               /* For standard types (like size_t) */
-#include <linux/errno.h>               /* For the -ENODEV/... values */
-#include <linux/kernel.h>              /* For printk/panic/... */
-#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
-#include <linux/watchdog.h>            /* For the watchdog specific items */
-#include <linux/init.h>                        /* For __init/__exit/... */
-#include <linux/fs.h>                  /* For file operations */
-#include <linux/platform_device.h>     /* For platform_driver framework */
-#include <linux/pci.h>                 /* For pci functions */
-#include <linux/ioport.h>              /* For io-port access */
-#include <linux/spinlock.h>            /* For spin_lock/spin_unlock/... */
-
-#include <asm/uaccess.h>               /* For copy_to_user/put_user/... */
-#include <asm/io.h>                    /* For inb/outb/... */
-
-/* TCO related info */
-enum iTCO_chipsets {
-       TCO_ICH = 0,    /* ICH */
-       TCO_ICH0,       /* ICH0 */
-       TCO_ICH2,       /* ICH2 */
-       TCO_ICH2M,      /* ICH2-M */
-       TCO_ICH3,       /* ICH3-S */
-       TCO_ICH3M,      /* ICH3-M */
-       TCO_ICH4,       /* ICH4 */
-       TCO_ICH4M,      /* ICH4-M */
-       TCO_CICH,       /* C-ICH */
-       TCO_ICH5,       /* ICH5 & ICH5R */
-       TCO_6300ESB,    /* 6300ESB */
-       TCO_ICH6,       /* ICH6 & ICH6R */
-       TCO_ICH6M,      /* ICH6-M */
-       TCO_ICH6W,      /* ICH6W & ICH6RW */
-       TCO_ICH7,       /* ICH7 & ICH7R */
-       TCO_ICH7M,      /* ICH7-M */
-       TCO_ICH7MDH,    /* ICH7-M DH */
-       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 {
-       char *name;
-       unsigned int iTCO_version;
-} iTCO_chipset_info[] __devinitdata = {
-       {"ICH", 1},
-       {"ICH0", 1},
-       {"ICH2", 1},
-       {"ICH2-M", 1},
-       {"ICH3-S", 1},
-       {"ICH3-M", 1},
-       {"ICH4", 1},
-       {"ICH4-M", 1},
-       {"C-ICH", 1},
-       {"ICH5 or ICH5R", 1},
-       {"6300ESB", 1},
-       {"ICH6 or ICH6R", 2},
-       {"ICH6-M", 2},
-       {"ICH6W or ICH6RW", 2},
-       {"ICH7 or ICH7R", 2},
-       {"ICH7-M", 2},
-       {"ICH7-M DH", 2},
-       {"ICH8 or ICH8R", 2},
-       {"ICH8DH", 2},
-       {"ICH8DO", 2},
-       {"ICH9", 2},
-       {"ICH9R", 2},
-       {"ICH9DH", 2},
-       {"631xESB/632xESB", 2},
-       {NULL,0}
-};
-
-/*
- * This data only exists for exporting the supported PCI ids
- * via MODULE_DEVICE_TABLE.  We do not actually register a
- * pci_driver, because the I/O Controller Hub has also other
- * functions that probably will be registered by other drivers.
- */
-static struct pci_device_id iTCO_wdt_pci_tbl[] = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH     },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,       PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7    },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M   },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
-       { 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);
-
-/* Address definitions for the TCO */
-#define        TCOBASE         iTCO_wdt_private.ACPIBASE + 0x60        /* TCO base address                */
-#define        SMI_EN          iTCO_wdt_private.ACPIBASE + 0x30        /* SMI Control and Enable Register */
-
-#define TCO_RLD                TCOBASE + 0x00  /* TCO Timer Reload and Current Value */
-#define TCOv1_TMR      TCOBASE + 0x01  /* TCOv1 Timer Initial Value    */
-#define        TCO_DAT_IN      TCOBASE + 0x02  /* TCO Data In Register         */
-#define        TCO_DAT_OUT     TCOBASE + 0x03  /* TCO Data Out Register        */
-#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
-#define        TCO2_STS        TCOBASE + 0x06  /* TCO2 Status Register         */
-#define TCO1_CNT       TCOBASE + 0x08  /* TCO1 Control Register        */
-#define TCO2_CNT       TCOBASE + 0x0a  /* TCO2 Control Register        */
-#define TCOv2_TMR      TCOBASE + 0x12  /* TCOv2 Timer Initial Value    */
-
-/* internal variables */
-static unsigned long is_active;
-static char expect_release;
-static struct {                                /* this is private data for the iTCO_wdt device */
-       unsigned int iTCO_version;      /* TCO version/generation */
-       unsigned long ACPIBASE;         /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
-       unsigned long __iomem *gcs;     /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */
-       spinlock_t io_lock;             /* the lock for io operations */
-       struct pci_dev *pdev;           /* the PCI-device */
-} iTCO_wdt_private;
-
-static struct platform_device *iTCO_wdt_platform_device;       /* the watchdog platform device */
-
-/* module parameters */
-#define WATCHDOG_HEARTBEAT 30  /* 30 sec default heartbeat */
-static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-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) ")");
-
-/* iTCO Vendor Specific Support hooks */
-#ifdef CONFIG_ITCO_VENDOR_SUPPORT
-extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
-extern void iTCO_vendor_pre_stop(unsigned long);
-extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
-extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
-extern int iTCO_vendor_check_noreboot_on(void);
-#else
-#define iTCO_vendor_pre_start(acpibase, heartbeat)     {}
-#define iTCO_vendor_pre_stop(acpibase)                 {}
-#define iTCO_vendor_pre_keepalive(acpibase,heartbeat)  {}
-#define iTCO_vendor_pre_set_heartbeat(heartbeat)       {}
-#define iTCO_vendor_check_noreboot_on()                        1       /* 1=check noreboot; 0=don't check */
-#endif
-
-/*
- * Some TCO specific functions
- */
-
-static inline unsigned int seconds_to_ticks(int seconds)
-{
-       /* the internal timer is stored as ticks which decrement
-        * every 0.6 seconds */
-       return (seconds * 10) / 6;
-}
-
-static void iTCO_wdt_set_NO_REBOOT_bit(void)
-{
-       u32 val32;
-
-       /* Set the NO_REBOOT bit: this disables reboots */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               val32 = readl(iTCO_wdt_private.gcs);
-               val32 |= 0x00000020;
-               writel(val32, iTCO_wdt_private.gcs);
-       } else if (iTCO_wdt_private.iTCO_version == 1) {
-               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
-               val32 |= 0x00000002;
-               pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
-       }
-}
-
-static int iTCO_wdt_unset_NO_REBOOT_bit(void)
-{
-       int ret = 0;
-       u32 val32;
-
-       /* Unset the NO_REBOOT bit: this enables reboots */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               val32 = readl(iTCO_wdt_private.gcs);
-               val32 &= 0xffffffdf;
-               writel(val32, iTCO_wdt_private.gcs);
-
-               val32 = readl(iTCO_wdt_private.gcs);
-               if (val32 & 0x00000020)
-                       ret = -EIO;
-       } else if (iTCO_wdt_private.iTCO_version == 1) {
-               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
-               val32 &= 0xfffffffd;
-               pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
-
-               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
-               if (val32 & 0x00000002)
-                       ret = -EIO;
-       }
-
-       return ret; /* returns: 0 = OK, -EIO = Error */
-}
-
-static int iTCO_wdt_start(void)
-{
-       unsigned int val;
-
-       spin_lock(&iTCO_wdt_private.io_lock);
-
-       iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
-
-       /* disable chipset's NO_REBOOT bit */
-       if (iTCO_wdt_unset_NO_REBOOT_bit()) {
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
-               return -EIO;
-       }
-
-       /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
-       val = inw(TCO1_CNT);
-       val &= 0xf7ff;
-       outw(val, TCO1_CNT);
-       val = inw(TCO1_CNT);
-       spin_unlock(&iTCO_wdt_private.io_lock);
-
-       if (val & 0x0800)
-               return -1;
-       return 0;
-}
-
-static int iTCO_wdt_stop(void)
-{
-       unsigned int val;
-
-       spin_lock(&iTCO_wdt_private.io_lock);
-
-       iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
-
-       /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
-       val = inw(TCO1_CNT);
-       val |= 0x0800;
-       outw(val, TCO1_CNT);
-       val = inw(TCO1_CNT);
-
-       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-       iTCO_wdt_set_NO_REBOOT_bit();
-
-       spin_unlock(&iTCO_wdt_private.io_lock);
-
-       if ((val & 0x0800) == 0)
-               return -1;
-       return 0;
-}
-
-static int iTCO_wdt_keepalive(void)
-{
-       spin_lock(&iTCO_wdt_private.io_lock);
-
-       iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
-
-       /* Reload the timer by writing to the TCO Timer Counter register */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               outw(0x01, TCO_RLD);
-       } else if (iTCO_wdt_private.iTCO_version == 1) {
-               outb(0x01, TCO_RLD);
-       }
-
-       spin_unlock(&iTCO_wdt_private.io_lock);
-       return 0;
-}
-
-static int iTCO_wdt_set_heartbeat(int t)
-{
-       unsigned int val16;
-       unsigned char val8;
-       unsigned int tmrval;
-
-       tmrval = seconds_to_ticks(t);
-       /* from the specs: */
-       /* "Values of 0h-3h are ignored and should not be attempted" */
-       if (tmrval < 0x04)
-               return -EINVAL;
-       if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
-           ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
-               return -EINVAL;
-
-       iTCO_vendor_pre_set_heartbeat(tmrval);
-
-       /* Write new heartbeat to watchdog */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               spin_lock(&iTCO_wdt_private.io_lock);
-               val16 = inw(TCOv2_TMR);
-               val16 &= 0xfc00;
-               val16 |= tmrval;
-               outw(val16, TCOv2_TMR);
-               val16 = inw(TCOv2_TMR);
-               spin_unlock(&iTCO_wdt_private.io_lock);
-
-               if ((val16 & 0x3ff) != tmrval)
-                       return -EINVAL;
-       } else if (iTCO_wdt_private.iTCO_version == 1) {
-               spin_lock(&iTCO_wdt_private.io_lock);
-               val8 = inb(TCOv1_TMR);
-               val8 &= 0xc0;
-               val8 |= (tmrval & 0xff);
-               outb(val8, TCOv1_TMR);
-               val8 = inb(TCOv1_TMR);
-               spin_unlock(&iTCO_wdt_private.io_lock);
-
-               if ((val8 & 0x3f) != tmrval)
-                       return -EINVAL;
-       }
-
-       heartbeat = t;
-       return 0;
-}
-
-static int iTCO_wdt_get_timeleft (int *time_left)
-{
-       unsigned int val16;
-       unsigned char val8;
-
-       /* read the TCO Timer */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               spin_lock(&iTCO_wdt_private.io_lock);
-               val16 = inw(TCO_RLD);
-               val16 &= 0x3ff;
-               spin_unlock(&iTCO_wdt_private.io_lock);
-
-               *time_left = (val16 * 6) / 10;
-       } else if (iTCO_wdt_private.iTCO_version == 1) {
-               spin_lock(&iTCO_wdt_private.io_lock);
-               val8 = inb(TCO_RLD);
-               val8 &= 0x3f;
-               spin_unlock(&iTCO_wdt_private.io_lock);
-
-               *time_left = (val8 * 6) / 10;
-       } else
-               return -EINVAL;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int iTCO_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;
-
-       /*
-        *      Reload and activate timer
-        */
-       iTCO_wdt_keepalive();
-       iTCO_wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int iTCO_wdt_release (struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        */
-       if (expect_release == 42) {
-               iTCO_wdt_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               iTCO_wdt_keepalive();
-       }
-       clear_bit(0, &is_active);
-       expect_release = 0;
-       return 0;
-}
-
-static ssize_t iTCO_wdt_write (struct file *file, const char __user *data,
-                             size_t len, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       expect_release = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_release = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               iTCO_wdt_keepalive();
-       }
-       return len;
-}
-
-static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       int new_options, retval = -EINVAL;
-       int new_heartbeat;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             DRV_NAME,
-       };
-
-       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:
-                       iTCO_wdt_keepalive();
-                       return 0;
-
-               case WDIOC_SETOPTIONS:
-               {
-                       if (get_user(new_options, p))
-                               return -EFAULT;
-
-                       if (new_options & WDIOS_DISABLECARD) {
-                               iTCO_wdt_stop();
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_ENABLECARD) {
-                               iTCO_wdt_keepalive();
-                               iTCO_wdt_start();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-
-               case WDIOC_SETTIMEOUT:
-               {
-                       if (get_user(new_heartbeat, p))
-                               return -EFAULT;
-
-                       if (iTCO_wdt_set_heartbeat(new_heartbeat))
-                               return -EINVAL;
-
-                       iTCO_wdt_keepalive();
-                       /* Fall */
-               }
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, p);
-
-               case WDIOC_GETTIMELEFT:
-               {
-                       int time_left;
-
-                       if (iTCO_wdt_get_timeleft(&time_left))
-                               return -EINVAL;
-
-                       return put_user(time_left, p);
-               }
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations iTCO_wdt_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .write =        iTCO_wdt_write,
-       .ioctl =        iTCO_wdt_ioctl,
-       .open =         iTCO_wdt_open,
-       .release =      iTCO_wdt_release,
-};
-
-static struct miscdevice iTCO_wdt_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &iTCO_wdt_fops,
-};
-
-/*
- *     Init & exit routines
- */
-
-static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
-{
-       int ret;
-       u32 base_address;
-       unsigned long RCBA;
-       unsigned long val32;
-
-       /*
-        *      Find the ACPI/PM base I/O address which is the base
-        *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
-        *      ACPIBASE is bits [15:7] from 0x40-0x43
-        */
-       pci_read_config_dword(pdev, 0x40, &base_address);
-       base_address &= 0x0000ff80;
-       if (base_address == 0x00000000) {
-               /* Something's wrong here, ACPIBASE has to be set */
-               printk(KERN_ERR PFX "failed to get TCOBASE address\n");
-               pci_dev_put(pdev);
-               return -ENODEV;
-       }
-       iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version;
-       iTCO_wdt_private.ACPIBASE = base_address;
-       iTCO_wdt_private.pdev = pdev;
-
-       /* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */
-       /* To get access to it you have to read RCBA from PCI Config space 0xf0
-          and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */
-       if (iTCO_wdt_private.iTCO_version == 2) {
-               pci_read_config_dword(pdev, 0xf0, &base_address);
-               RCBA = base_address & 0xffffc000;
-               iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4);
-       }
-
-       /* Check chipset's NO_REBOOT bit */
-       if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
-               ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
-               goto out;
-       }
-
-       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-       iTCO_wdt_set_NO_REBOOT_bit();
-
-       /* Set the TCO_EN bit in SMI_EN register */
-       if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
-               printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
-                       SMI_EN );
-               ret = -EIO;
-               goto out;
-       }
-       val32 = inl(SMI_EN);
-       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
-       outl(val32, SMI_EN);
-       release_region(SMI_EN, 4);
-
-       /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */
-       if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) {
-               printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n",
-                       TCOBASE);
-               ret = -EIO;
-               goto out;
-       }
-
-       printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
-               iTCO_chipset_info[ent->driver_data].name,
-               iTCO_chipset_info[ent->driver_data].iTCO_version,
-               TCOBASE);
-
-       /* Clear out the (probably old) status */
-       outb(0, TCO1_STS);
-       outb(3, TCO2_STS);
-
-       /* Make sure the watchdog is not running */
-       iTCO_wdt_stop();
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (iTCO_wdt_set_heartbeat(heartbeat)) {
-               iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n",
-                       heartbeat);
-       }
-
-       ret = misc_register(&iTCO_wdt_miscdev);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto unreg_region;
-       }
-
-       printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-
-       return 0;
-
-unreg_region:
-       release_region (TCOBASE, 0x20);
-out:
-       if (iTCO_wdt_private.iTCO_version == 2)
-               iounmap(iTCO_wdt_private.gcs);
-       pci_dev_put(iTCO_wdt_private.pdev);
-       iTCO_wdt_private.ACPIBASE = 0;
-       return ret;
-}
-
-static void iTCO_wdt_cleanup(void)
-{
-       /* Stop the timer before we leave */
-       if (!nowayout)
-               iTCO_wdt_stop();
-
-       /* Deregister */
-       misc_deregister(&iTCO_wdt_miscdev);
-       release_region(TCOBASE, 0x20);
-       if (iTCO_wdt_private.iTCO_version == 2)
-               iounmap(iTCO_wdt_private.gcs);
-       pci_dev_put(iTCO_wdt_private.pdev);
-       iTCO_wdt_private.ACPIBASE = 0;
-}
-
-static int iTCO_wdt_probe(struct platform_device *dev)
-{
-       int found = 0;
-       struct pci_dev *pdev = NULL;
-       const struct pci_device_id *ent;
-
-       spin_lock_init(&iTCO_wdt_private.io_lock);
-
-       for_each_pci_dev(pdev) {
-               ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
-               if (ent) {
-                       if (!(iTCO_wdt_init(pdev, ent, dev))) {
-                               found++;
-                               break;
-                       }
-               }
-       }
-
-       if (!found) {
-               printk(KERN_INFO PFX "No card detected\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static int iTCO_wdt_remove(struct platform_device *dev)
-{
-       if (iTCO_wdt_private.ACPIBASE)
-               iTCO_wdt_cleanup();
-
-       return 0;
-}
-
-static void iTCO_wdt_shutdown(struct platform_device *dev)
-{
-       iTCO_wdt_stop();
-}
-
-#define iTCO_wdt_suspend NULL
-#define iTCO_wdt_resume  NULL
-
-static struct platform_driver iTCO_wdt_driver = {
-       .probe          = iTCO_wdt_probe,
-       .remove         = iTCO_wdt_remove,
-       .shutdown       = iTCO_wdt_shutdown,
-       .suspend        = iTCO_wdt_suspend,
-       .resume         = iTCO_wdt_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = DRV_NAME,
-       },
-};
-
-static int __init iTCO_wdt_init_module(void)
-{
-       int err;
-
-       printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n",
-               DRV_VERSION, DRV_RELDATE);
-
-       err = platform_driver_register(&iTCO_wdt_driver);
-       if (err)
-               return err;
-
-       iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
-       if (IS_ERR(iTCO_wdt_platform_device)) {
-               err = PTR_ERR(iTCO_wdt_platform_device);
-               goto unreg_platform_driver;
-       }
-
-       return 0;
-
-unreg_platform_driver:
-       platform_driver_unregister(&iTCO_wdt_driver);
-       return err;
-}
-
-static void __exit iTCO_wdt_cleanup_module(void)
-{
-       platform_device_unregister(iTCO_wdt_platform_device);
-       platform_driver_unregister(&iTCO_wdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(iTCO_wdt_init_module);
-module_exit(iTCO_wdt_cleanup_module);
-
-MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
-MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
-MODULE_VERSION(DRV_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
deleted file mode 100644 (file)
index c3a60f5..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- *     IB700 Single Board Computer WDT driver
- *
- *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
- *
- *     Based on advantechwdt.c which is based on acquirewdt.c which
- *     is based on wdt.c.
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     Based on acquirewdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
- *
- *     14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *          Added timeout module option to override default
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static struct platform_device *ibwdt_platform_device;
-static unsigned long ibwdt_is_open;
-static spinlock_t ibwdt_lock;
-static char expect_close;
-
-/* Module information */
-#define DRV_NAME "ib700wdt"
-#define PFX DRV_NAME ": "
-
-/*
- *
- * Watchdog Timer Configuration
- *
- * The function of the watchdog timer is to reset the system
- * automatically and is defined at I/O port 0443H.  To enable the
- * watchdog timer and allow the system to reset, write I/O port 0443H.
- * To disable the timer, write I/O port 0441H for the system to stop the
- * watchdog function.  The timer has a tolerance of 20% for its
- * intervals.
- *
- * The following describes how the timer should be programmed.
- *
- * Enabling Watchdog:
- * MOV AX,000FH (Choose the values from 0 to F)
- * MOV DX,0443H
- * OUT DX,AX
- *
- * Disabling Watchdog:
- * MOV AX,000FH (Any value is fine.)
- * MOV DX,0441H
- * OUT DX,AX
- *
- * Watchdog timer control table:
- * Level   Value  Time/sec | Level Value Time/sec
- *   1       F       0     |   9     7      16
- *   2       E       2     |   10    6      18
- *   3       D       4     |   11    5      20
- *   4       C       6     |   12    4      22
- *   5       B       8     |   13    3      24
- *   6       A       10    |   14    2      26
- *   7       9       12    |   15    1      28
- *   8       8       14    |   16    0      30
- *
- */
-
-static int wd_times[] = {
-       30,     /* 0x0 */
-       28,     /* 0x1 */
-       26,     /* 0x2 */
-       24,     /* 0x3 */
-       22,     /* 0x4 */
-       20,     /* 0x5 */
-       18,     /* 0x6 */
-       16,     /* 0x7 */
-       14,     /* 0x8 */
-       12,     /* 0x9 */
-       10,     /* 0xA */
-       8,      /* 0xB */
-       6,      /* 0xC */
-       4,      /* 0xD */
-       2,      /* 0xE */
-       0,      /* 0xF */
-};
-
-#define WDT_STOP 0x441
-#define WDT_START 0x443
-
-/* Default timeout */
-#define WD_TIMO 0              /* 30 seconds +/- 20%, from table */
-
-static int wd_margin = WD_TIMO;
-
-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) ")");
-
-
-/*
- *     Watchdog Operations
- */
-
-static void
-ibwdt_ping(void)
-{
-       spin_lock(&ibwdt_lock);
-
-       /* Write a watchdog value */
-       outb_p(wd_margin, WDT_START);
-
-       spin_unlock(&ibwdt_lock);
-}
-
-static void
-ibwdt_disable(void)
-{
-       spin_lock(&ibwdt_lock);
-       outb_p(0, WDT_STOP);
-       spin_unlock(&ibwdt_lock);
-}
-
-static int
-ibwdt_set_heartbeat(int t)
-{
-       int i;
-
-       if ((t < 0) || (t > 30))
-               return -EINVAL;
-
-       for (i = 0x0F; i > -1; i--)
-               if (wd_times[i] > t)
-                       break;
-       wd_margin = i;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t
-ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               ibwdt_ping();
-       }
-       return count;
-}
-
-static int
-ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       int new_margin;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "IB700 WDT",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user(argp, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-         return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-         ibwdt_ping();
-         break;
-
-       case WDIOC_SETTIMEOUT:
-         if (get_user(new_margin, p))
-                 return -EFAULT;
-         if (ibwdt_set_heartbeat(new_margin))
-                 return -EINVAL;
-         ibwdt_ping();
-         /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-         return put_user(wd_times[wd_margin], p);
-
-       case WDIOC_SETOPTIONS:
-       {
-         int options, retval = -EINVAL;
-
-         if (get_user(options, p))
-           return -EFAULT;
-
-         if (options & WDIOS_DISABLECARD) {
-           ibwdt_disable();
-           retval = 0;
-         }
-
-         if (options & WDIOS_ENABLECARD) {
-           ibwdt_ping();
-           retval = 0;
-         }
-
-         return retval;
-       }
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-ibwdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &ibwdt_is_open)) {
-               return -EBUSY;
-       }
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate */
-       ibwdt_ping();
-       return nonseekable_open(inode, file);
-}
-
-static int
-ibwdt_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               ibwdt_disable();
-       } else {
-               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-               ibwdt_ping();
-       }
-       clear_bit(0, &ibwdt_is_open);
-       expect_close = 0;
-       return 0;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations ibwdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = ibwdt_write,
-       .ioctl          = ibwdt_ioctl,
-       .open           = ibwdt_open,
-       .release        = ibwdt_close,
-};
-
-static struct miscdevice ibwdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &ibwdt_fops,
-};
-
-/*
- *     Init & exit routines
- */
-
-static int __devinit ibwdt_probe(struct platform_device *dev)
-{
-       int res;
-
-       spin_lock_init(&ibwdt_lock);
-
-#if WDT_START != WDT_STOP
-       if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
-               printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP);
-               res = -EIO;
-               goto out_nostopreg;
-       }
-#endif
-
-       if (!request_region(WDT_START, 1, "IB700 WDT")) {
-               printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START);
-               res = -EIO;
-               goto out_nostartreg;
-       }
-
-       res = misc_register(&ibwdt_miscdev);
-       if (res) {
-               printk (KERN_ERR PFX "failed to register misc device\n");
-               goto out_nomisc;
-       }
-       return 0;
-
-out_nomisc:
-       release_region(WDT_START, 1);
-out_nostartreg:
-#if WDT_START != WDT_STOP
-       release_region(WDT_STOP, 1);
-#endif
-out_nostopreg:
-       return res;
-}
-
-static int __devexit ibwdt_remove(struct platform_device *dev)
-{
-       misc_deregister(&ibwdt_miscdev);
-       release_region(WDT_START,1);
-#if WDT_START != WDT_STOP
-       release_region(WDT_STOP,1);
-#endif
-       return 0;
-}
-
-static void ibwdt_shutdown(struct platform_device *dev)
-{
-       /* Turn the WDT off if we have a soft shutdown */
-       ibwdt_disable();
-}
-
-static struct platform_driver ibwdt_driver = {
-       .probe          = ibwdt_probe,
-       .remove         = __devexit_p(ibwdt_remove),
-       .shutdown       = ibwdt_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = DRV_NAME,
-       },
-};
-
-static int __init ibwdt_init(void)
-{
-       int err;
-
-       printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
-
-       err = platform_driver_register(&ibwdt_driver);
-       if (err)
-               return err;
-
-       ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
-       if (IS_ERR(ibwdt_platform_device)) {
-               err = PTR_ERR(ibwdt_platform_device);
-               goto unreg_platform_driver;
-       }
-
-       return 0;
-
-unreg_platform_driver:
-       platform_driver_unregister(&ibwdt_driver);
-       return err;
-}
-
-static void __exit ibwdt_exit(void)
-{
-       platform_device_unregister(ibwdt_platform_device);
-       platform_driver_unregister(&ibwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(ibwdt_init);
-module_exit(ibwdt_exit);
-
-MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
-MODULE_DESCRIPTION("IB700 SBC watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-/* end of ib700wdt.c */
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
deleted file mode 100644 (file)
index 94155f6..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * IBM Automatic Server Restart driver.
- *
- * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
- *
- * Based on driver written by Pete Reynolds.
- * Copyright (c) IBM Corporation, 1998-2004.
- *
- * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
- */
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/timer.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/dmi.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-
-enum {
-       ASMTYPE_UNKNOWN,
-       ASMTYPE_TOPAZ,
-       ASMTYPE_JASPER,
-       ASMTYPE_PEARL,
-       ASMTYPE_JUNIPER,
-       ASMTYPE_SPRUCE,
-};
-
-#define PFX "ibmasr: "
-
-#define TOPAZ_ASR_REG_OFFSET   4
-#define TOPAZ_ASR_TOGGLE       0x40
-#define TOPAZ_ASR_DISABLE      0x80
-
-/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
-#define PEARL_BASE     0xe04
-#define PEARL_WRITE    0xe06
-#define PEARL_READ     0xe07
-
-#define PEARL_ASR_DISABLE_MASK 0x80    /* bit 7: disable = 1, enable = 0 */
-#define PEARL_ASR_TOGGLE_MASK  0x40    /* bit 6: 0, then 1, then 0 */
-
-/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
-#define JASPER_ASR_REG_OFFSET  0x38
-
-#define JASPER_ASR_DISABLE_MASK        0x01    /* bit 0: disable = 1, enable = 0 */
-#define JASPER_ASR_TOGGLE_MASK 0x02    /* bit 1: 0, then 1, then 0 */
-
-#define JUNIPER_BASE_ADDRESS   0x54b   /* Base address of Juniper ASR */
-#define JUNIPER_ASR_DISABLE_MASK 0x01  /* bit 0: disable = 1 enable = 0 */
-#define JUNIPER_ASR_TOGGLE_MASK        0x02    /* bit 1: 0, then 1, then 0 */
-
-#define SPRUCE_BASE_ADDRESS    0x118e  /* Base address of Spruce ASR */
-#define SPRUCE_ASR_DISABLE_MASK        0x01    /* bit 1: disable = 1 enable = 0 */
-#define SPRUCE_ASR_TOGGLE_MASK 0x02    /* bit 0: 0, then 1, then 0 */
-
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-static unsigned long asr_is_open;
-static char asr_expect_close;
-
-static unsigned int asr_type, asr_base, asr_length;
-static unsigned int asr_read_addr, asr_write_addr;
-static unsigned char asr_toggle_mask, asr_disable_mask;
-
-static void asr_toggle(void)
-{
-       unsigned char reg = inb(asr_read_addr);
-
-       outb(reg & ~asr_toggle_mask, asr_write_addr);
-       reg = inb(asr_read_addr);
-
-       outb(reg | asr_toggle_mask, asr_write_addr);
-       reg = inb(asr_read_addr);
-
-       outb(reg & ~asr_toggle_mask, asr_write_addr);
-       reg = inb(asr_read_addr);
-}
-
-static void asr_enable(void)
-{
-       unsigned char reg;
-
-       if (asr_type == ASMTYPE_TOPAZ) {
-               /* asr_write_addr == asr_read_addr */
-               reg = inb(asr_read_addr);
-               outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
-                    asr_read_addr);
-       } else {
-               /*
-                * First make sure the hardware timer is reset by toggling
-                * ASR hardware timer line.
-                */
-               asr_toggle();
-
-               reg = inb(asr_read_addr);
-               outb(reg & ~asr_disable_mask, asr_write_addr);
-       }
-       reg = inb(asr_read_addr);
-}
-
-static void asr_disable(void)
-{
-       unsigned char reg = inb(asr_read_addr);
-
-       if (asr_type == ASMTYPE_TOPAZ)
-               /* asr_write_addr == asr_read_addr */
-               outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
-                    asr_read_addr);
-       else {
-               outb(reg | asr_toggle_mask, asr_write_addr);
-               reg = inb(asr_read_addr);
-
-               outb(reg | asr_disable_mask, asr_write_addr);
-       }
-       reg = inb(asr_read_addr);
-}
-
-static int __init asr_get_base_address(void)
-{
-       unsigned char low, high;
-       const char *type = "";
-
-       asr_length = 1;
-
-       switch (asr_type) {
-       case ASMTYPE_TOPAZ:
-               /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
-               outb(0x07, 0x2e);
-               outb(0x07, 0x2f);
-
-               /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
-               outb(0x60, 0x2e);
-               high = inb(0x2f);
-
-               /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
-               outb(0x61, 0x2e);
-               low = inb(0x2f);
-
-               asr_base = (high << 16) | low;
-               asr_read_addr = asr_write_addr =
-                       asr_base + TOPAZ_ASR_REG_OFFSET;
-               asr_length = 5;
-
-               break;
-
-       case ASMTYPE_JASPER:
-               type = "Jaspers ";
-
-               /* FIXME: need to use pci_config_lock here, but it's not exported */
-
-/*             spin_lock_irqsave(&pci_config_lock, flags);*/
-
-               /* Select the SuperIO chip in the PCI I/O port register */
-               outl(0x8000f858, 0xcf8);
-
-               /*
-                * Read the base address for the SuperIO chip.
-                * Only the lower 16 bits are valid, but the address is word
-                * aligned so the last bit must be masked off.
-                */
-               asr_base = inl(0xcfc) & 0xfffe;
-
-/*             spin_unlock_irqrestore(&pci_config_lock, flags);*/
-
-               asr_read_addr = asr_write_addr =
-                       asr_base + JASPER_ASR_REG_OFFSET;
-               asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
-               asr_disable_mask = JASPER_ASR_DISABLE_MASK;
-               asr_length = JASPER_ASR_REG_OFFSET + 1;
-
-               break;
-
-       case ASMTYPE_PEARL:
-               type = "Pearls ";
-               asr_base = PEARL_BASE;
-               asr_read_addr = PEARL_READ;
-               asr_write_addr = PEARL_WRITE;
-               asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
-               asr_disable_mask = PEARL_ASR_DISABLE_MASK;
-               asr_length = 4;
-               break;
-
-       case ASMTYPE_JUNIPER:
-               type = "Junipers ";
-               asr_base = JUNIPER_BASE_ADDRESS;
-               asr_read_addr = asr_write_addr = asr_base;
-               asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
-               asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
-               break;
-
-       case ASMTYPE_SPRUCE:
-               type = "Spruce's ";
-               asr_base = SPRUCE_BASE_ADDRESS;
-               asr_read_addr = asr_write_addr = asr_base;
-               asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
-               asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
-               break;
-       }
-
-       if (!request_region(asr_base, asr_length, "ibmasr")) {
-               printk(KERN_ERR PFX "address %#x already in use\n",
-                       asr_base);
-               return -EBUSY;
-       }
-
-       printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
-
-       return 0;
-}
-
-
-static ssize_t asr_write(struct file *file, const char __user *buf,
-                        size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       asr_expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       asr_expect_close = 42;
-                       }
-               }
-               asr_toggle();
-       }
-       return count;
-}
-
-static int asr_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
-{
-       static const struct watchdog_info ident = {
-               .options =      WDIOF_KEEPALIVEPING | 
-                               WDIOF_MAGICCLOSE,
-               .identity =     "IBM ASR"
-       };
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int heartbeat;
-
-       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:
-                       asr_toggle();
-                       return 0;
-
-               /*
-                * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
-                * and WDIOC_GETTIMEOUT always returns 256.
-                */
-               case WDIOC_GETTIMEOUT:
-                       heartbeat = 256;
-                       return put_user(heartbeat, p);
-
-               case WDIOC_SETOPTIONS: {
-                       int new_options, retval = -EINVAL;
-
-                       if (get_user(new_options, p))
-                               return -EFAULT;
-
-                       if (new_options & WDIOS_DISABLECARD) {
-                               asr_disable();
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_ENABLECARD) {
-                               asr_enable();
-                               asr_toggle();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-       }
-
-       return -ENOTTY;
-}
-
-static int asr_open(struct inode *inode, struct file *file)
-{
-       if(test_and_set_bit(0, &asr_is_open))
-               return -EBUSY;
-
-       asr_toggle();
-       asr_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static int asr_release(struct inode *inode, struct file *file)
-{
-       if (asr_expect_close == 42)
-               asr_disable();
-       else {
-               printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
-               asr_toggle();
-       }
-       clear_bit(0, &asr_is_open);
-       asr_expect_close = 0;
-       return 0;
-}
-
-static const struct file_operations asr_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .write =        asr_write,
-       .ioctl =        asr_ioctl,
-       .open =         asr_open,
-       .release =      asr_release,
-};
-
-static struct miscdevice asr_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &asr_fops,
-};
-
-
-struct ibmasr_id {
-       const char *desc;
-       int type;
-};
-
-static struct ibmasr_id __initdata ibmasr_id_table[] = {
-       { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
-       { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
-       { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
-       { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
-       { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
-       { NULL }
-};
-
-static int __init ibmasr_init(void)
-{
-       struct ibmasr_id *id;
-       int rc;
-
-       for (id = ibmasr_id_table; id->desc; id++) {
-               if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
-                       asr_type = id->type;
-                       break;
-               }
-       }
-
-       if (!asr_type)
-               return -ENODEV;
-
-       rc = asr_get_base_address();
-       if (rc)
-               return rc;
-
-       rc = misc_register(&asr_miscdev);
-       if (rc < 0) {
-               release_region(asr_base, asr_length);
-               printk(KERN_ERR PFX "failed to register misc device\n");
-               return rc;
-       }
-
-       return 0;
-}
-
-static void __exit ibmasr_exit(void)
-{
-       if (!nowayout)
-               asr_disable();
-
-       misc_deregister(&asr_miscdev);
-
-       release_region(asr_base, asr_length);
-}
-
-module_init(ibmasr_init);
-module_exit(ibmasr_exit);
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
-MODULE_AUTHOR("Andrey Panin");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
deleted file mode 100644 (file)
index 788245b..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- *     IndyDog 0.3     A Hardware Watchdog Device for SGI IP22
- *
- *     (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     based on softdog.c by Alan Cox <alan@redhat.com>
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/sgi/mc.h>
-
-#define PFX "indydog: "
-static int indydog_alive;
-
-#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
-
-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 indydog_start(void)
-{
-       u32 mc_ctrl0 = sgimc->cpuctrl0;
-
-       mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
-       sgimc->cpuctrl0 = mc_ctrl0;
-}
-
-static void indydog_stop(void)
-{
-       u32 mc_ctrl0 = sgimc->cpuctrl0;
-
-       mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
-       sgimc->cpuctrl0 = mc_ctrl0;
-
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
-}
-
-static void indydog_ping(void)
-{
-       sgimc->watchdogt = 0;
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int indydog_open(struct inode *inode, struct file *file)
-{
-       if (indydog_alive)
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate timer */
-       indydog_start();
-       indydog_ping();
-
-       indydog_alive = 1;
-       printk(KERN_INFO "Started watchdog timer.\n");
-
-       return nonseekable_open(inode, file);
-}
-
-static int indydog_release(struct inode *inode, struct file *file)
-{
-       /* Shut off the timer.
-        * Lock it in if it's a module and we defined ...NOWAYOUT */
-       if (!nowayout)
-               indydog_stop();         /* Turn the WDT off */
-
-       indydog_alive = 0;
-
-       return 0;
-}
-
-static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       /* Refresh the timer. */
-       if (len) {
-               indydog_ping();
-       }
-       return len;
-}
-
-static int indydog_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int options, retval = -EINVAL;
-       static struct watchdog_info ident = {
-               .options                = WDIOF_KEEPALIVEPING |
-                                         WDIOF_MAGICCLOSE,
-               .firmware_version       = 0,
-               .identity               = "Hardware Watchdog for SGI IP22",
-       };
-
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user((struct watchdog_info *)arg,
-                                        &ident, sizeof(ident)))
-                               return -EFAULT;
-                       return 0;
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0,(int *)arg);
-               case WDIOC_KEEPALIVE:
-                       indydog_ping();
-                       return 0;
-               case WDIOC_GETTIMEOUT:
-                       return put_user(WATCHDOG_TIMEOUT,(int *)arg);
-               case WDIOC_SETOPTIONS:
-               {
-                       if (get_user(options, (int *)arg))
-                               return -EFAULT;
-
-                       if (options & WDIOS_DISABLECARD) {
-                               indydog_stop();
-                               retval = 0;
-                       }
-
-                       if (options & WDIOS_ENABLECARD) {
-                               indydog_start();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-       }
-}
-
-static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               indydog_stop();         /* Turn the WDT off */
-
-       return NOTIFY_DONE;
-}
-
-static const struct file_operations indydog_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = indydog_write,
-       .ioctl          = indydog_ioctl,
-       .open           = indydog_open,
-       .release        = indydog_release,
-};
-
-static struct miscdevice indydog_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &indydog_fops,
-};
-
-static struct notifier_block indydog_notifier = {
-       .notifier_call = indydog_notify_sys,
-};
-
-static char banner[] __initdata =
-       KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
-
-static int __init watchdog_init(void)
-{
-       int ret;
-
-       ret = register_reboot_notifier(&indydog_notifier);
-       if (ret) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               return ret;
-       }
-
-       ret = misc_register(&indydog_miscdev);
-       if (ret) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               unregister_reboot_notifier(&indydog_notifier);
-               return ret;
-       }
-
-       printk(banner);
-
-       return 0;
-}
-
-static void __exit watchdog_exit(void)
-{
-       misc_deregister(&indydog_miscdev);
-       unregister_reboot_notifier(&indydog_notifier);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
-
-MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
-MODULE_DESCRIPTION("Hardware Watchdog Device for SGI IP22");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/iop_wdt.c b/drivers/char/watchdog/iop_wdt.c
deleted file mode 100644 (file)
index bbbd91a..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * drivers/char/watchdog/iop_wdt.c
- *
- * WDT driver for Intel I/O Processors
- * Copyright (C) 2005, Intel Corporation.
- *
- * Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- *     Curt E Bruns <curt.e.bruns@intel.com>
- *     Peter Milne <peter.milne@d-tacq.com>
- *     Dan Williams <dan.j.williams@intel.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/uaccess.h>
-#include <asm/hardware.h>
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-static unsigned long wdt_status;
-static unsigned long boot_status;
-
-#define WDT_IN_USE             0
-#define WDT_OK_TO_CLOSE                1
-#define WDT_ENABLED            2
-
-static unsigned long iop_watchdog_timeout(void)
-{
-       return (0xffffffffUL / get_iop_tick_rate());
-}
-
-/**
- * wdt_supports_disable - determine if we are accessing a iop13xx watchdog
- * or iop3xx by whether it has a disable command
- */
-static int wdt_supports_disable(void)
-{
-       int can_disable;
-
-       if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM)
-               can_disable = 1;
-       else
-               can_disable = 0;
-
-       return can_disable;
-}
-
-static void wdt_enable(void)
-{
-       /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
-        * Takes approx. 10.7s to timeout
-        */
-       write_wdtcr(IOP_WDTCR_EN_ARM);
-       write_wdtcr(IOP_WDTCR_EN);
-}
-
-/* returns 0 if the timer was successfully disabled */
-static int wdt_disable(void)
-{
-       /* Stop Counting */
-       if (wdt_supports_disable()) {
-               write_wdtcr(IOP_WDTCR_DIS_ARM);
-               write_wdtcr(IOP_WDTCR_DIS);
-               clear_bit(WDT_ENABLED, &wdt_status);
-               printk(KERN_INFO "WATCHDOG: Disabled\n");
-               return 0;
-       } else
-               return 1;
-}
-
-static int iop_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_enable();
-
-       set_bit(WDT_ENABLED, &wdt_status);
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-iop_wdt_write(struct file *file, const char *data, size_t len,
-                 loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_enable();
-       }
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
-       .identity = "iop watchdog",
-};
-
-static int
-iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                 unsigned long arg)
-{
-       int options;
-       int ret = -ENOTTY;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user
-                   ((struct watchdog_info *)arg, &ident, sizeof ident))
-                       ret = -EFAULT;
-               else
-                       ret = 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int *)arg);
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(iop_watchdog_timeout(), (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-
-       case WDIOC_SETOPTIONS:
-               if (get_user(options, (int *)arg))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       if (!nowayout) {
-                               if (wdt_disable() == 0) {
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                                       ret = 0;
-                               } else
-                                       ret = -ENXIO;
-                       } else
-                               ret = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       wdt_enable();
-                       ret = 0;
-               }
-               break;
-       }
-
-       return ret;
-}
-
-static int iop_wdt_release(struct inode *inode, struct file *file)
-{
-       int state = 1;
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               if (test_bit(WDT_ENABLED, &wdt_status))
-                       state = wdt_disable();
-
-       /* if the timer is not disbaled reload and notify that we are still
-        * going down
-        */
-       if (state != 0) {
-               wdt_enable();
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                      "reset in %lu seconds\n", iop_watchdog_timeout());
-       }
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations iop_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = iop_wdt_write,
-       .ioctl = iop_wdt_ioctl,
-       .open = iop_wdt_open,
-       .release = iop_wdt_release,
-};
-
-static struct miscdevice iop_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &iop_wdt_fops,
-};
-
-static int __init iop_wdt_init(void)
-{
-       int ret;
-
-       ret = misc_register(&iop_wdt_miscdev);
-       if (ret == 0)
-               printk("iop watchdog timer: timeout %lu sec\n",
-                      iop_watchdog_timeout());
-
-       /* check if the reset was caused by the watchdog timer */
-       boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
-
-       /* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset
-        * NOTE: An IB Reset will Reset both cores in the IOP342
-        */
-       write_wdtsr(IOP13XX_WDTCR_IB_RESET);
-
-       return ret;
-}
-
-static void __exit iop_wdt_exit(void)
-{
-       misc_deregister(&iop_wdt_miscdev);
-}
-
-module_init(iop_wdt_init);
-module_exit(iop_wdt_exit);
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
-MODULE_DESCRIPTION("iop watchdog timer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
deleted file mode 100644 (file)
index dc7548d..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * drivers/char/watchdog/ixp2000_wdt.c
- *
- * Watchdog driver for Intel IXP2000 network processors
- *
- * Adapted from the IXP4xx watchdog driver by Lennert Buytenhek.
- * The original version carries these notices:
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (c) MontaVista, Software, Inc.
- * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
- *
- * 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 <asm/hardware.h>
-#include <asm/uaccess.h>
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-static unsigned int heartbeat = 60;    /* (secs) Default is 1 minute */
-static unsigned long wdt_status;
-
-#define        WDT_IN_USE              0
-#define        WDT_OK_TO_CLOSE         1
-
-static unsigned long wdt_tick_rate;
-
-static void
-wdt_enable(void)
-{
-       ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
-       ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
-       ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
-       ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
-}
-
-static void
-wdt_disable(void)
-{
-       ixp2000_reg_write(IXP2000_T4_CTL, 0);
-}
-
-static void
-wdt_keepalive(void)
-{
-       ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
-}
-
-static int
-ixp2000_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_keepalive();
-       }
-
-       return len;
-}
-
-
-static struct watchdog_info ident = {
-       .options        = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
-                               WDIOF_KEEPALIVEPING,
-       .identity       = "IXP2000 Watchdog",
-};
-
-static int
-ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                       unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, (int *)arg);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > 60) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               heartbeat = time;
-               wdt_keepalive();
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-       }
-
-       return ret;
-}
-
-static int
-ixp2000_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
-               wdt_disable();
-       } else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
-       }
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-
-static const struct file_operations ixp2000_wdt_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = ixp2000_wdt_write,
-       .ioctl          = ixp2000_wdt_ioctl,
-       .open           = ixp2000_wdt_open,
-       .release        = ixp2000_wdt_release,
-};
-
-static struct miscdevice ixp2000_wdt_miscdev =
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ixp2000_wdt_fops,
-};
-
-static int __init ixp2000_wdt_init(void)
-{
-       if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
-               printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
-               return -EIO;
-       }
-
-       wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
-
-       return misc_register(&ixp2000_wdt_miscdev);
-}
-
-static void __exit ixp2000_wdt_exit(void)
-{
-       misc_deregister(&ixp2000_wdt_miscdev);
-}
-
-module_init(ixp2000_wdt_init);
-module_exit(ixp2000_wdt_exit);
-
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
deleted file mode 100644 (file)
index 5864bb8..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * drivers/char/watchdog/ixp4xx_wdt.c
- *
- * Watchdog driver for Intel IXP4xx network processors
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright 2004 (c) MontaVista, Software, Inc.
- * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
- *
- * 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 <asm/hardware.h>
-#include <asm/uaccess.h>
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int heartbeat = 60;     /* (secs) Default is 1 minute */
-static unsigned long wdt_status;
-static unsigned long boot_status;
-
-#define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL)
-
-#define        WDT_IN_USE              0
-#define        WDT_OK_TO_CLOSE         1
-
-static void
-wdt_enable(void)
-{
-       *IXP4XX_OSWK = IXP4XX_WDT_KEY;
-       *IXP4XX_OSWE = 0;
-       *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat;
-       *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE;
-       *IXP4XX_OSWK = 0;
-}
-
-static void
-wdt_disable(void)
-{
-       *IXP4XX_OSWK = IXP4XX_WDT_KEY;
-       *IXP4XX_OSWE = 0;
-       *IXP4XX_OSWK = 0;
-}
-
-static int
-ixp4xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_enable();
-       }
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options        = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
-                         WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-       .identity       = "IXP4xx Watchdog",
-};
-
-
-static int
-ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                       unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int *)arg);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, (int *)arg);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > 60) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               heartbeat = time;
-               wdt_enable();
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-       }
-       return ret;
-}
-
-static int
-ixp4xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
-               wdt_disable();
-       } else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
-       }
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-
-static const struct file_operations ixp4xx_wdt_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = ixp4xx_wdt_write,
-       .ioctl          = ixp4xx_wdt_ioctl,
-       .open           = ixp4xx_wdt_open,
-       .release        = ixp4xx_wdt_release,
-};
-
-static struct miscdevice ixp4xx_wdt_miscdev =
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ixp4xx_wdt_fops,
-};
-
-static int __init ixp4xx_wdt_init(void)
-{
-       int ret;
-       unsigned long processor_id;
-
-       asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
-       if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
-               printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - "
-                       "watchdog disabled\n");
-
-               return -ENODEV;
-       }
-
-       ret = misc_register(&ixp4xx_wdt_miscdev);
-       if (ret == 0)
-               printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat);
-
-       boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ?
-                       WDIOF_CARDRESET : 0;
-
-       return ret;
-}
-
-static void __exit ixp4xx_wdt_exit(void)
-{
-       misc_deregister(&ixp4xx_wdt_miscdev);
-}
-
-
-module_init(ixp4xx_wdt_init);
-module_exit(ixp4xx_wdt_exit);
-
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
diff --git a/drivers/char/watchdog/ks8695_wdt.c b/drivers/char/watchdog/ks8695_wdt.c
deleted file mode 100644 (file)
index 7150fb9..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Watchdog driver for Kendin/Micrel KS8695.
- *
- * (C) 2007 Andrew Victor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/watchdog.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/arch/regs-timer.h>
-
-
-#define WDT_DEFAULT_TIME       5       /* seconds */
-#define WDT_MAX_TIME           171     /* seconds */
-
-static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-module_param(wdt_time, int, 0);
-MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-#endif
-
-
-static unsigned long ks8695wdt_busy;
-
-/* ......................................................................... */
-
-/*
- * Disable the watchdog.
- */
-static void inline ks8695_wdt_stop(void)
-{
-       unsigned long tmcon;
-
-       /* disable timer0 */
-       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-}
-
-/*
- * Enable and reset the watchdog.
- */
-static void inline ks8695_wdt_start(void)
-{
-       unsigned long tmcon;
-       unsigned long tval = wdt_time * CLOCK_TICK_RATE;
-
-       /* disable timer0 */
-       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-
-       /* program timer0 */
-       __raw_writel(tval | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
-
-       /* re-enable timer0 */
-       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-       __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-}
-
-/*
- * Reload the watchdog timer.  (ie, pat the watchdog)
- */
-static void inline ks8695_wdt_reload(void)
-{
-       unsigned long tmcon;
-
-       /* disable, then re-enable timer0 */
-       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-       __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
-}
-
-/*
- * Change the watchdog time interval.
- */
-static int ks8695_wdt_settimeout(int new_time)
-{
-       /*
-        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
-        *
-        * Since WDV is a 16-bit counter, the maximum period is
-        * 65536 / 0.256 = 256 seconds.
-        */
-       if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
-               return -EINVAL;
-
-       /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */
-       wdt_time = new_time;
-       return 0;
-}
-
-/* ......................................................................... */
-
-/*
- * Watchdog device is opened, and watchdog starts running.
- */
-static int ks8695_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &ks8695wdt_busy))
-               return -EBUSY;
-
-       ks8695_wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-/*
- * Close the watchdog device.
- * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
- *  disabled.
- */
-static int ks8695_wdt_close(struct inode *inode, struct file *file)
-{
-       if (!nowayout)
-               ks8695_wdt_stop();      /* Disable the watchdog when file is closed */
-
-       clear_bit(0, &ks8695wdt_busy);
-       return 0;
-}
-
-static struct watchdog_info ks8695_wdt_info = {
-       .identity       = "ks8695 watchdog",
-       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-};
-
-/*
- * Handle commands from user-space.
- */
-static int ks8695_wdt_ioctl(struct inode *inode, struct file *file,
-               unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_value;
-
-       switch(cmd) {
-               case WDIOC_KEEPALIVE:
-                       ks8695_wdt_reload();    /* pat the watchdog */
-                       return 0;
-
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_value, p))
-                               return -EFAULT;
-
-                       if (ks8695_wdt_settimeout(new_value))
-                               return -EINVAL;
-
-                       /* Enable new time value */
-                       ks8695_wdt_start();
-
-                       /* Return current value */
-                       return put_user(wdt_time, p);
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(wdt_time, p);
-
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-
-               case WDIOC_SETOPTIONS:
-                       if (get_user(new_value, p))
-                               return -EFAULT;
-
-                       if (new_value & WDIOS_DISABLECARD)
-                               ks8695_wdt_stop();
-                       if (new_value & WDIOS_ENABLECARD)
-                               ks8695_wdt_start();
-                       return 0;
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-/*
- * Pat the watchdog whenever device is written to.
- */
-static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       ks8695_wdt_reload();            /* pat the watchdog */
-       return len;
-}
-
-/* ......................................................................... */
-
-static const struct file_operations ks8695wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .ioctl          = ks8695_wdt_ioctl,
-       .open           = ks8695_wdt_open,
-       .release        = ks8695_wdt_close,
-       .write          = ks8695_wdt_write,
-};
-
-static struct miscdevice ks8695wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ks8695wdt_fops,
-};
-
-static int __init ks8695wdt_probe(struct platform_device *pdev)
-{
-       int res;
-
-       if (ks8695wdt_miscdev.parent)
-               return -EBUSY;
-       ks8695wdt_miscdev.parent = &pdev->dev;
-
-       res = misc_register(&ks8695wdt_miscdev);
-       if (res)
-               return res;
-
-       printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : "");
-       return 0;
-}
-
-static int __exit ks8695wdt_remove(struct platform_device *pdev)
-{
-       int res;
-
-       res = misc_deregister(&ks8695wdt_miscdev);
-       if (!res)
-               ks8695wdt_miscdev.parent = NULL;
-
-       return res;
-}
-
-static void ks8695wdt_shutdown(struct platform_device *pdev)
-{
-       ks8695_wdt_stop();
-}
-
-#ifdef CONFIG_PM
-
-static int ks8695wdt_suspend(struct platform_device *pdev, pm_message_t message)
-{
-       ks8695_wdt_stop();
-       return 0;
-}
-
-static int ks8695wdt_resume(struct platform_device *pdev)
-{
-       if (ks8695wdt_busy)
-               ks8695_wdt_start();
-       return 0;
-}
-
-#else
-#define ks8695wdt_suspend NULL
-#define ks8695wdt_resume       NULL
-#endif
-
-static struct platform_driver ks8695wdt_driver = {
-       .probe          = ks8695wdt_probe,
-       .remove         = __exit_p(ks8695wdt_remove),
-       .shutdown       = ks8695wdt_shutdown,
-       .suspend        = ks8695wdt_suspend,
-       .resume         = ks8695wdt_resume,
-       .driver         = {
-               .name   = "ks8695_wdt",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init ks8695_wdt_init(void)
-{
-       /* Check that the heartbeat value is within range; if not reset to the default */
-       if (ks8695_wdt_settimeout(wdt_time)) {
-               ks8695_wdt_settimeout(WDT_DEFAULT_TIME);
-               pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", wdt_time, WDT_MAX_TIME);
-       }
-
-       return platform_driver_register(&ks8695wdt_driver);
-}
-
-static void __exit ks8695_wdt_exit(void)
-{
-       platform_driver_unregister(&ks8695wdt_driver);
-}
-
-module_init(ks8695_wdt_init);
-module_exit(ks8695_wdt_exit);
-
-MODULE_AUTHOR("Andrew Victor");
-MODULE_DESCRIPTION("Watchdog driver for KS8695");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
deleted file mode 100644 (file)
index 6d35bb1..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- *  MachZ ZF-Logic Watchdog Timer driver for Linux
- *
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- *  The author does NOT admit liability nor provide warranty for
- *  any of this software. This material is provided "AS-IS" in
- *  the hope that it may be useful for others.
- *
- *  Author: Fernando Fuganti <fuganti@conectiva.com.br>
- *
- *  Based on sbc60xxwdt.c by Jakob Oestergaard
- *
- *
- *  We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the
- *  following periods:
- *      wd#1 - 2 seconds;
- *      wd#2 - 7.2 ms;
- *  After the expiration of wd#1, it can generate a NMI, SCI, SMI, or
- *  a system RESET and it starts wd#2 that unconditionaly will RESET
- *  the system when the counter reaches zero.
- *
- *  14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* ports */
-#define ZF_IOBASE      0x218
-#define INDEX          0x218
-#define DATA_B         0x219
-#define DATA_W         0x21A
-#define DATA_D         0x21A
-
-/* indexes */                  /* size */
-#define ZFL_VERSION    0x02    /* 16   */
-#define CONTROL        0x10    /* 16   */
-#define STATUS         0x12    /* 8    */
-#define COUNTER_1      0x0C    /* 16   */
-#define COUNTER_2      0x0E    /* 8    */
-#define PULSE_LEN      0x0F    /* 8    */
-
-/* controls */
-#define ENABLE_WD1     0x0001
-#define ENABLE_WD2     0x0002
-#define RESET_WD1      0x0010
-#define RESET_WD2      0x0020
-#define GEN_SCI                0x0100
-#define GEN_NMI                0x0200
-#define GEN_SMI                0x0400
-#define GEN_RESET      0x0800
-
-
-/* utilities */
-
-#define WD1    0
-#define WD2    1
-
-#define zf_writew(port, data)  { outb(port, INDEX); outw(data, DATA_W); }
-#define zf_writeb(port, data)  { outb(port, INDEX); outb(data, DATA_B); }
-#define zf_get_ZFL_version()   zf_readw(ZFL_VERSION)
-
-
-static unsigned short zf_readw(unsigned char port)
-{
-       outb(port, INDEX);
-       return inw(DATA_W);
-}
-
-
-MODULE_AUTHOR("Fernando Fuganti <fuganti@conectiva.com.br>");
-MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-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) ")");
-
-#define PFX "machzwd"
-
-static struct watchdog_info zf_info = {
-       .options                = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
-       .firmware_version       = 1,
-       .identity               = "ZF-Logic watchdog",
-};
-
-
-/*
- * action refers to action taken when watchdog resets
- * 0 = GEN_RESET
- * 1 = GEN_SMI
- * 2 = GEN_NMI
- * 3 = GEN_SCI
- * defaults to GEN_RESET (0)
- */
-static int action = 0;
-module_param(action, int, 0);
-MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
-
-static void zf_ping(unsigned long data);
-
-static int zf_action = GEN_RESET;
-static unsigned long zf_is_open;
-static char zf_expect_close;
-static spinlock_t zf_lock;
-static spinlock_t zf_port_lock;
-static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
-static unsigned long next_heartbeat = 0;
-
-
-/* timeout for user land heart beat (10 seconds) */
-#define ZF_USER_TIMEO (HZ*10)
-
-/* timeout for hardware watchdog (~500ms) */
-#define ZF_HW_TIMEO (HZ/2)
-
-/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */
-#define ZF_CTIMEOUT 0xffff
-
-#ifndef ZF_DEBUG
-#      define dprintk(format, args...)
-#else
-#      define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args)
-#endif
-
-
-static inline void zf_set_status(unsigned char new)
-{
-       zf_writeb(STATUS, new);
-}
-
-
-/* CONTROL register functions */
-
-static inline unsigned short zf_get_control(void)
-{
-       return zf_readw(CONTROL);
-}
-
-static inline void zf_set_control(unsigned short new)
-{
-       zf_writew(CONTROL, new);
-}
-
-
-/* WD#? counter functions */
-/*
- *     Just set counter value
- */
-
-static inline void zf_set_timer(unsigned short new, unsigned char n)
-{
-       switch(n){
-               case WD1:
-                       zf_writew(COUNTER_1, new);
-               case WD2:
-                       zf_writeb(COUNTER_2, new > 0xff ? 0xff : new);
-               default:
-                       return;
-       }
-}
-
-/*
- * stop hardware timer
- */
-static void zf_timer_off(void)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-
-       /* stop internal ping */
-       del_timer_sync(&zf_timer);
-
-       spin_lock_irqsave(&zf_port_lock, flags);
-       /* stop watchdog timer */
-       ctrl_reg = zf_get_control();
-       ctrl_reg |= (ENABLE_WD1|ENABLE_WD2);    /* disable wd1 and wd2 */
-       ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2);
-       zf_set_control(ctrl_reg);
-       spin_unlock_irqrestore(&zf_port_lock, flags);
-
-       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
-}
-
-
-/*
- * start hardware timer
- */
-static void zf_timer_on(void)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&zf_port_lock, flags);
-
-       zf_writeb(PULSE_LEN, 0xff);
-
-       zf_set_timer(ZF_CTIMEOUT, WD1);
-
-       /* user land ping */
-       next_heartbeat = jiffies + ZF_USER_TIMEO;
-
-       /* start the timer for internal ping */
-       mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
-
-       /* start watchdog timer */
-       ctrl_reg = zf_get_control();
-       ctrl_reg |= (ENABLE_WD1|zf_action);
-       zf_set_control(ctrl_reg);
-       spin_unlock_irqrestore(&zf_port_lock, flags);
-
-       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
-}
-
-
-static void zf_ping(unsigned long data)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-
-       zf_writeb(COUNTER_2, 0xff);
-
-       if(time_before(jiffies, next_heartbeat)){
-
-               dprintk("time_before: %ld\n", next_heartbeat - jiffies);
-
-               /*
-                * reset event is activated by transition from 0 to 1 on
-                * RESET_WD1 bit and we assume that it is already zero...
-                */
-
-               spin_lock_irqsave(&zf_port_lock, flags);
-               ctrl_reg = zf_get_control();
-               ctrl_reg |= RESET_WD1;
-               zf_set_control(ctrl_reg);
-
-               /* ...and nothing changes until here */
-               ctrl_reg &= ~(RESET_WD1);
-               zf_set_control(ctrl_reg);
-               spin_unlock_irqrestore(&zf_port_lock, flags);
-
-               mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
-       }else{
-               printk(KERN_CRIT PFX ": I will reset your machine\n");
-       }
-}
-
-static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
-                                                               loff_t *ppos)
-{
-       /* See if we got the magic character */
-       if(count){
-
-               /*
-                * no need to check for close confirmation
-                * no way to disable watchdog ;)
-                */
-               if (!nowayout) {
-                       size_t ofs;
-
-                       /*
-                        * note: just in case someone wrote the magic character
-                        * five months ago...
-                        */
-                       zf_expect_close = 0;
-
-                       /* now scan */
-                       for (ofs = 0; ofs != count; ofs++){
-                               char c;
-                               if (get_user(c, buf + ofs))
-                                       return -EFAULT;
-                               if (c == 'V'){
-                                       zf_expect_close = 42;
-                                       dprintk("zf_expect_close = 42\n");
-                               }
-                       }
-               }
-
-               /*
-                * Well, anyhow someone wrote to us,
-                * we should return that favour
-                */
-               next_heartbeat = jiffies + ZF_USER_TIMEO;
-               dprintk("user ping at %ld\n", jiffies);
-
-       }
-
-       return count;
-}
-
-static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
-                       return -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               zf_ping(0);
-               break;
-
-       default:
-               return -ENOTTY;
-       }
-
-       return 0;
-}
-
-static int zf_open(struct inode *inode, struct file *file)
-{
-       spin_lock(&zf_lock);
-       if(test_and_set_bit(0, &zf_is_open)) {
-               spin_unlock(&zf_lock);
-               return -EBUSY;
-       }
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       spin_unlock(&zf_lock);
-
-       zf_timer_on();
-
-       return nonseekable_open(inode, file);
-}
-
-static int zf_close(struct inode *inode, struct file *file)
-{
-       if(zf_expect_close == 42){
-               zf_timer_off();
-       } else {
-               del_timer(&zf_timer);
-               printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
-       }
-
-       spin_lock(&zf_lock);
-       clear_bit(0, &zf_is_open);
-       spin_unlock(&zf_lock);
-
-       zf_expect_close = 0;
-
-       return 0;
-}
-
-/*
- * Notifier for system down
- */
-
-static int zf_notify_sys(struct notifier_block *this, unsigned long code,
-                                                               void *unused)
-{
-       if(code == SYS_DOWN || code == SYS_HALT){
-               zf_timer_off();
-       }
-
-       return NOTIFY_DONE;
-}
-
-
-
-
-static const struct file_operations zf_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = zf_write,
-       .ioctl          = zf_ioctl,
-       .open           = zf_open,
-       .release        = zf_close,
-};
-
-static struct miscdevice zf_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &zf_fops,
-};
-
-/*
- * The device needs to learn about soft shutdowns in order to
- * turn the timebomb registers off.
- */
-static struct notifier_block zf_notifier = {
-       .notifier_call = zf_notify_sys,
-};
-
-static void __init zf_show_action(int act)
-{
-       char *str[] = { "RESET", "SMI", "NMI", "SCI" };
-
-       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
-}
-
-static int __init zf_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n");
-
-       ret = zf_get_ZFL_version();
-       if ((!ret) || (ret == 0xffff)) {
-               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
-               return -ENODEV;
-       }
-
-       if((action <= 3) && (action >= 0)){
-               zf_action = zf_action>>action;
-       } else
-               action = 0;
-
-       zf_show_action(action);
-
-       spin_lock_init(&zf_lock);
-       spin_lock_init(&zf_port_lock);
-
-       if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
-               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
-                                                       ZF_IOBASE);
-               ret = -EBUSY;
-               goto no_region;
-       }
-
-       ret = register_reboot_notifier(&zf_notifier);
-       if(ret){
-               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
-                                                                       ret);
-               goto no_reboot;
-       }
-
-       ret = misc_register(&zf_miscdev);
-       if (ret){
-               printk(KERN_ERR "can't misc_register on minor=%d\n",
-                                                       WATCHDOG_MINOR);
-               goto no_misc;
-       }
-
-       zf_set_status(0);
-       zf_set_control(0);
-
-       return 0;
-
-no_misc:
-       unregister_reboot_notifier(&zf_notifier);
-no_reboot:
-       release_region(ZF_IOBASE, 3);
-no_region:
-       return ret;
-}
-
-
-static void __exit zf_exit(void)
-{
-       zf_timer_off();
-
-       misc_deregister(&zf_miscdev);
-       unregister_reboot_notifier(&zf_notifier);
-       release_region(ZF_IOBASE, 3);
-}
-
-module_init(zf_init);
-module_exit(zf_exit);
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
deleted file mode 100644 (file)
index 1adf1d5..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * MixCom Watchdog: A Simple Hardware Watchdog Device
- * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
- *
- * Author: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Version 0.1 (99/04/15):
- *             - first version
- *
- * Version 0.2 (99/06/16):
- *             - added kernel timer watchdog ping after close
- *               since the hardware does not support watchdog shutdown
- *
- * Version 0.3 (99/06/21):
- *             - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls
- *
- * Version 0.3.1 (99/06/22):
- *             - allow module removal while internal timer is active,
- *               print warning about probable reset
- *
- * Version 0.4 (99/11/15):
- *             - support for one more type board
- *
- * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
- *             - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *
- * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
- *             - make mixcomwd_opened unsigned,
- *               removed lock_kernel/unlock_kernel from mixcomwd_release,
- *               modified ioctl a bit to conform to API
- *
- */
-
-#define VERSION "0.6"
-#define WATCHDOG_NAME "mixcomwd"
-#define PFX WATCHDOG_NAME ": "
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-/*
- * We have two types of cards that can be probed:
- * 1) The Mixcom cards: these cards can be found at addresses
- *    0x180, 0x280, 0x380 with an additional offset of 0xc10.
- *    (Or 0xd90, 0xe90, 0xf90).
- * 2) The FlashCOM cards: these cards can be set up at
- *    0x300 -> 0x378, in 0x8 jumps with an offset of 0x04.
- *    (Or 0x304 -> 0x37c in 0x8 jumps).
- *    Each card has it's own ID.
- */
-#define MIXCOM_ID 0x11
-#define FLASHCOM_ID 0x18
-static struct {
-       int ioport;
-       int id;
-} mixcomwd_io_info[] __devinitdata = {
-       /* The Mixcom cards */
-       {0x0d90, MIXCOM_ID},
-       {0x0e90, MIXCOM_ID},
-       {0x0f90, MIXCOM_ID},
-       /* The FlashCOM cards */
-       {0x0304, FLASHCOM_ID},
-       {0x030c, FLASHCOM_ID},
-       {0x0314, FLASHCOM_ID},
-       {0x031c, FLASHCOM_ID},
-       {0x0324, FLASHCOM_ID},
-       {0x032c, FLASHCOM_ID},
-       {0x0334, FLASHCOM_ID},
-       {0x033c, FLASHCOM_ID},
-       {0x0344, FLASHCOM_ID},
-       {0x034c, FLASHCOM_ID},
-       {0x0354, FLASHCOM_ID},
-       {0x035c, FLASHCOM_ID},
-       {0x0364, FLASHCOM_ID},
-       {0x036c, FLASHCOM_ID},
-       {0x0374, FLASHCOM_ID},
-       {0x037c, FLASHCOM_ID},
-       /* The end of the list */
-       {0x0000, 0},
-};
-
-static void mixcomwd_timerfun(unsigned long d);
-
-static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
-
-static int watchdog_port;
-static int mixcomwd_timer_alive;
-static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
-static char expect_close;
-
-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 mixcomwd_ping(void)
-{
-       outb_p(55,watchdog_port);
-       return;
-}
-
-static void mixcomwd_timerfun(unsigned long d)
-{
-       mixcomwd_ping();
-
-       mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
-}
-
-/*
- *     Allow only one person to hold it open
- */
-
-static int mixcomwd_open(struct inode *inode, struct file *file)
-{
-       if(test_and_set_bit(0,&mixcomwd_opened)) {
-               return -EBUSY;
-       }
-       mixcomwd_ping();
-
-       if (nowayout) {
-               /*
-                * fops_get() code via open() has already done
-                * a try_module_get() so it is safe to do the
-                * __module_get().
-                */
-               __module_get(THIS_MODULE);
-       } else {
-               if(mixcomwd_timer_alive) {
-                       del_timer(&mixcomwd_timer);
-                       mixcomwd_timer_alive=0;
-               }
-       }
-       return nonseekable_open(inode, file);
-}
-
-static int mixcomwd_release(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               if(mixcomwd_timer_alive) {
-                       printk(KERN_ERR PFX "release called while internal timer alive");
-                       return -EBUSY;
-               }
-               mixcomwd_timer_alive=1;
-               mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
-       } else {
-               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-       }
-
-       clear_bit(0,&mixcomwd_opened);
-       expect_close=0;
-       return 0;
-}
-
-
-static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
-{
-       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;
-                       }
-               }
-               mixcomwd_ping();
-       }
-       return len;
-}
-
-static int mixcomwd_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int status;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "MixCOM watchdog",
-       };
-
-       switch(cmd)
-       {
-               case WDIOC_GETSTATUS:
-                       status=mixcomwd_opened;
-                       if (!nowayout) {
-                               status|=mixcomwd_timer_alive;
-                       }
-                       if (copy_to_user(p, &status, sizeof(int))) {
-                               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;
-                       }
-                       break;
-               case WDIOC_KEEPALIVE:
-                       mixcomwd_ping();
-                       break;
-               default:
-                       return -ENOTTY;
-       }
-       return 0;
-}
-
-static const struct file_operations mixcomwd_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = mixcomwd_write,
-       .ioctl          = mixcomwd_ioctl,
-       .open           = mixcomwd_open,
-       .release        = mixcomwd_release,
-};
-
-static struct miscdevice mixcomwd_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &mixcomwd_fops,
-};
-
-static int __init checkcard(int port, int card_id)
-{
-       int id;
-
-       if (!request_region(port, 1, "MixCOM watchdog")) {
-               return 0;
-       }
-
-       id=inb_p(port);
-       if (card_id==MIXCOM_ID)
-               id &= 0x3f;
-
-       if (id!=card_id) {
-               release_region(port, 1);
-               return 0;
-       }
-       return 1;
-}
-
-static int __init mixcomwd_init(void)
-{
-       int i;
-       int ret;
-       int found=0;
-
-       for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
-               if (checkcard(mixcomwd_io_info[i].ioport,
-                             mixcomwd_io_info[i].id)) {
-                       found = 1;
-                       watchdog_port = mixcomwd_io_info[i].ioport;
-               }
-       }
-
-       if (!found) {
-               printk(KERN_ERR PFX "No card detected, or port not available.\n");
-               return -ENODEV;
-       }
-
-       ret = misc_register(&mixcomwd_miscdev);
-       if (ret)
-       {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto error_misc_register_watchdog;
-       }
-
-       printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
-               VERSION, watchdog_port);
-
-       return 0;
-
-error_misc_register_watchdog:
-       release_region(watchdog_port, 1);
-       watchdog_port = 0x0000;
-       return ret;
-}
-
-static void __exit mixcomwd_exit(void)
-{
-       if (!nowayout) {
-               if(mixcomwd_timer_alive) {
-                       printk(KERN_WARNING PFX "I quit now, hardware will"
-                              " probably reboot!\n");
-                       del_timer_sync(&mixcomwd_timer);
-                       mixcomwd_timer_alive=0;
-               }
-       }
-       misc_deregister(&mixcomwd_miscdev);
-       release_region(watchdog_port,1);
-}
-
-module_init(mixcomwd_init);
-module_exit(mixcomwd_exit);
-
-MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
-MODULE_DESCRIPTION("MixCom Watchdog driver");
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/char/watchdog/mpc5200_wdt.c
deleted file mode 100644 (file)
index 9cfb975..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-#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 __user *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);
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
deleted file mode 100644 (file)
index a0bf95f..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
- *
- * Authors: Dave Updegraff <dave@cray.org>
- *         Kumar Gala <galak@kernel.crashing.org>
- *             Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
- *                             ..and from sc520_wdt
- *
- * Note: it appears that you can only actually ENABLE or DISABLE the thing
- * once after POR. Once enabled, you cannot disable, and vice versa.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/watchdog.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-struct mpc83xx_wdt {
-       __be32 res0;
-       __be32 swcrr; /* System watchdog control register */
-#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
-#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
-#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
-#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
-       __be32 swcnr; /* System watchdog count register */
-       u8 res1[2];
-       __be16 swsrr; /* System watchdog service register */
-       u8 res2[0xF0];
-};
-
-static struct mpc83xx_wdt __iomem *wd_base;
-
-static u16 timeout = 0xffff;
-module_param(timeout, ushort, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
-
-static int reset = 1;
-module_param(reset, bool, 0);
-MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
-
-/*
- * We always prescale, but if someone really doesn't want to they can set this
- * to 0
- */
-static int prescale = 1;
-static unsigned int timeout_sec;
-
-static unsigned long wdt_is_open;
-static spinlock_t wdt_spinlock;
-
-static void mpc83xx_wdt_keepalive(void)
-{
-       /* Ping the WDT */
-       spin_lock(&wdt_spinlock);
-       out_be16(&wd_base->swsrr, 0x556c);
-       out_be16(&wd_base->swsrr, 0xaa39);
-       spin_unlock(&wdt_spinlock);
-}
-
-static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
-                                size_t count, loff_t *ppos)
-{
-       if (count)
-               mpc83xx_wdt_keepalive();
-       return count;
-}
-
-static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
-{
-       u32 tmp = SWCRR_SWEN;
-       if (test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-
-       /* Once we start the watchdog we can't stop it */
-       __module_get(THIS_MODULE);
-
-       /* Good, fire up the show */
-       if (prescale)
-               tmp |= SWCRR_SWPR;
-       if (reset)
-               tmp |= SWCRR_SWRI;
-
-       tmp |= timeout << 16;
-
-       out_be32(&wd_base->swcrr, tmp);
-
-       return nonseekable_open(inode, file);
-}
-
-static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
-{
-       printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
-       mpc83xx_wdt_keepalive();
-       clear_bit(0, &wdt_is_open);
-       return 0;
-}
-
-static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
-                               unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING,
-               .firmware_version = 1,
-               .identity = "MPC83xx",
-       };
-
-       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;
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout_sec, p);
-       default:
-               return -ENOTTY;
-       }
-}
-
-static const struct file_operations mpc83xx_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = mpc83xx_wdt_write,
-       .ioctl          = mpc83xx_wdt_ioctl,
-       .open           = mpc83xx_wdt_open,
-       .release        = mpc83xx_wdt_release,
-};
-
-static struct miscdevice mpc83xx_wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &mpc83xx_wdt_fops,
-};
-
-static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
-{
-       struct resource *r;
-       int ret;
-       unsigned int *freq = dev->dev.platform_data;
-
-       /* get a pointer to the register memory */
-       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-
-       if (!r) {
-               ret = -ENODEV;
-               goto err_out;
-       }
-
-       wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
-
-       if (wd_base == NULL) {
-               ret = -ENOMEM;
-               goto err_out;
-       }
-
-       ret = misc_register(&mpc83xx_wdt_miscdev);
-       if (ret) {
-               printk(KERN_ERR "cannot register miscdev on minor=%d "
-                               "(err=%d)\n",
-                               WATCHDOG_MINOR, ret);
-               goto err_unmap;
-       }
-
-       /* Calculate the timeout in seconds */
-       if (prescale)
-               timeout_sec = (timeout * 0x10000) / (*freq);
-       else
-               timeout_sec = timeout / (*freq);
-
-       printk(KERN_INFO "WDT driver for MPC83xx initialized. "
-               "mode:%s timeout=%d (%d seconds)\n",
-               reset ? "reset":"interrupt", timeout, timeout_sec);
-
-       spin_lock_init(&wdt_spinlock);
-
-       return 0;
-
-err_unmap:
-       iounmap(wd_base);
-err_out:
-       return ret;
-}
-
-static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
-{
-       misc_deregister(&mpc83xx_wdt_miscdev);
-       iounmap(wd_base);
-
-       return 0;
-}
-
-static struct platform_driver mpc83xx_wdt_driver = {
-       .probe          = mpc83xx_wdt_probe,
-       .remove         = __devexit_p(mpc83xx_wdt_remove),
-       .driver         = {
-               .name   = "mpc83xx_wdt",
-       },
-};
-
-static int __init mpc83xx_wdt_init(void)
-{
-       return platform_driver_register(&mpc83xx_wdt_driver);
-}
-
-static void __exit mpc83xx_wdt_exit(void)
-{
-       platform_driver_unregister(&mpc83xx_wdt_driver);
-}
-
-module_init(mpc83xx_wdt_init);
-module_exit(mpc83xx_wdt_exit);
-
-MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
-MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
deleted file mode 100644 (file)
index 85b5734..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
- *
- * Author: Florian Schirmer <jolt@tuxbox.org>
- *
- * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/watchdog.h>
-#include <asm/8xx_immap.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <syslib/m8xx_wdt.h>
-
-static unsigned long wdt_opened;
-static int wdt_status;
-
-static void mpc8xx_wdt_handler_disable(void)
-{
-       volatile uint __iomem *piscr;
-       piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
-
-       if (!m8xx_has_internal_rtc)
-               m8xx_wdt_stop_timer();
-       else
-               out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
-
-       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
-}
-
-static void mpc8xx_wdt_handler_enable(void)
-{
-       volatile uint __iomem *piscr;
-       piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
-
-       if (!m8xx_has_internal_rtc)
-               m8xx_wdt_install_timer();
-       else
-               out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
-
-       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
-}
-
-static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &wdt_opened))
-               return -EBUSY;
-
-       m8xx_wdt_reset();
-       mpc8xx_wdt_handler_disable();
-
-       return nonseekable_open(inode, file);
-}
-
-static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
-{
-       m8xx_wdt_reset();
-
-#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
-       mpc8xx_wdt_handler_enable();
-#endif
-
-       clear_bit(0, &wdt_opened);
-
-       return 0;
-}
-
-static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
-                               loff_t * ppos)
-{
-       if (len)
-               m8xx_wdt_reset();
-
-       return len;
-}
-
-static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       int timeout;
-       static struct watchdog_info info = {
-               .options = WDIOF_KEEPALIVEPING,
-               .firmware_version = 0,
-               .identity = "MPC8xx watchdog",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user((void *)arg, &info, sizeof(info)))
-                       return -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               if (put_user(wdt_status, (int *)arg))
-                       return -EFAULT;
-               wdt_status &= ~WDIOF_KEEPALIVEPING;
-               break;
-
-       case WDIOC_GETTEMP:
-               return -EOPNOTSUPP;
-
-       case WDIOC_SETOPTIONS:
-               return -EOPNOTSUPP;
-
-       case WDIOC_KEEPALIVE:
-               m8xx_wdt_reset();
-               wdt_status |= WDIOF_KEEPALIVEPING;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               return -EOPNOTSUPP;
-
-       case WDIOC_GETTIMEOUT:
-               timeout = m8xx_wdt_get_timeout();
-               if (put_user(timeout, (int *)arg))
-                       return -EFAULT;
-               break;
-
-       default:
-               return -ENOTTY;
-       }
-
-       return 0;
-}
-
-static const struct file_operations mpc8xx_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = mpc8xx_wdt_write,
-       .ioctl = mpc8xx_wdt_ioctl,
-       .open = mpc8xx_wdt_open,
-       .release = mpc8xx_wdt_release,
-};
-
-static struct miscdevice mpc8xx_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &mpc8xx_wdt_fops,
-};
-
-static int __init mpc8xx_wdt_init(void)
-{
-       return misc_register(&mpc8xx_wdt_miscdev);
-}
-
-static void __exit mpc8xx_wdt_exit(void)
-{
-       misc_deregister(&mpc8xx_wdt_miscdev);
-
-       m8xx_wdt_reset();
-       mpc8xx_wdt_handler_enable();
-}
-
-module_init(mpc8xx_wdt_init);
-module_exit(mpc8xx_wdt_exit);
-
-MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
-MODULE_DESCRIPTION("MPC8xx watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
deleted file mode 100644 (file)
index 0d2b277..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- *     Watchdog driver for the mpcore watchdog timer
- *
- *     (c) Copyright 2004 ARM Limited
- *
- *     Based on the SoftDog driver:
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <asm/hardware/arm_twd.h>
-#include <asm/uaccess.h>
-
-struct mpcore_wdt {
-       unsigned long   timer_alive;
-       struct device   *dev;
-       void __iomem    *base;
-       int             irq;
-       unsigned int    perturb;
-       char            expect_close;
-};
-
-static struct platform_device *mpcore_wdt_dev;
-
-extern unsigned int mpcore_timer_rate;
-
-#define TIMER_MARGIN   60
-static int mpcore_margin = TIMER_MARGIN;
-module_param(mpcore_margin, int, 0);
-MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
-
-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) ")");
-
-#define ONLY_TESTING   0
-static int mpcore_noboot = ONLY_TESTING;
-module_param(mpcore_noboot, int, 0);
-MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
-
-/*
- *     This is the interrupt handler.  Note that we only use this
- *     in testing mode, so don't actually do a reboot here.
- */
-static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
-{
-       struct mpcore_wdt *wdt = arg;
-
-       /* Check it really was our interrupt */
-       if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
-               dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
-
-               /* Clear the interrupt on the watchdog */
-               writel(1, wdt->base + TWD_WDOG_INTSTAT);
-
-               return IRQ_HANDLED;
-       }
-
-       return IRQ_NONE;
-}
-
-/*
- *     mpcore_wdt_keepalive - reload the timer
- *
- *     Note that the spec says a DIFFERENT value must be written to the reload
- *     register each time.  The "perturb" variable deals with this by adding 1
- *     to the count every other time the function is called.
- */
-static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
-{
-       unsigned int count;
-
-       /* Assume prescale is set to 256 */
-       count = (mpcore_timer_rate / 256) * mpcore_margin;
-
-       /* Reload the counter */
-       writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
-
-       wdt->perturb = wdt->perturb ? 0 : 1;
-}
-
-static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
-{
-       writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
-       writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
-       writel(0x0, wdt->base + TWD_WDOG_CONTROL);
-}
-
-static void mpcore_wdt_start(struct mpcore_wdt *wdt)
-{
-       dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
-
-       /* This loads the count register but does NOT start the count yet */
-       mpcore_wdt_keepalive(wdt);
-
-       if (mpcore_noboot) {
-               /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
-               writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
-       } else {
-               /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
-               writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
-       }
-}
-
-static int mpcore_wdt_set_heartbeat(int t)
-{
-       if (t < 0x0001 || t > 0xFFFF)
-               return -EINVAL;
-
-       mpcore_margin = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-static int mpcore_wdt_open(struct inode *inode, struct file *file)
-{
-       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev);
-
-       if (test_and_set_bit(0, &wdt->timer_alive))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       file->private_data = wdt;
-
-       /*
-        *      Activate timer
-        */
-       mpcore_wdt_start(wdt);
-
-       return nonseekable_open(inode, file);
-}
-
-static int mpcore_wdt_release(struct inode *inode, struct file *file)
-{
-       struct mpcore_wdt *wdt = file->private_data;
-
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (wdt->expect_close == 42) {
-               mpcore_wdt_stop(wdt);
-       } else {
-               dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
-               mpcore_wdt_keepalive(wdt);
-       }
-       clear_bit(0, &wdt->timer_alive);
-       wdt->expect_close = 0;
-       return 0;
-}
-
-static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       struct mpcore_wdt *wdt = file->private_data;
-
-       /*
-        *      Refresh the timer.
-        */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       wdt->expect_close = 0;
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       wdt->expect_close = 42;
-                       }
-               }
-               mpcore_wdt_keepalive(wdt);
-       }
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options                = WDIOF_SETTIMEOUT |
-                                 WDIOF_KEEPALIVEPING |
-                                 WDIOF_MAGICCLOSE,
-       .identity               = "MPcore Watchdog",
-};
-
-static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
-                            unsigned int cmd, unsigned long arg)
-{
-       struct mpcore_wdt *wdt = file->private_data;
-       int ret;
-       union {
-               struct watchdog_info ident;
-               int i;
-       } uarg;
-
-       if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
-               return -ENOTTY;
-
-       if (_IOC_DIR(cmd) & _IOC_WRITE) {
-               ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
-               if (ret)
-                       return -EFAULT;
-       }
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               uarg.ident = ident;
-               ret = 0;
-               break;
-
-       case WDIOC_SETOPTIONS:
-               ret = -EINVAL;
-               if (uarg.i & WDIOS_DISABLECARD) {
-                       mpcore_wdt_stop(wdt);
-                       ret = 0;
-               }
-               if (uarg.i & WDIOS_ENABLECARD) {
-                       mpcore_wdt_start(wdt);
-                       ret = 0;
-               }
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               uarg.i = 0;
-               ret = 0;
-               break;
-
-       case WDIOC_KEEPALIVE:
-               mpcore_wdt_keepalive(wdt);
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = mpcore_wdt_set_heartbeat(uarg.i);
-               if (ret)
-                       break;
-
-               mpcore_wdt_keepalive(wdt);
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               uarg.i = mpcore_margin;
-               ret = 0;
-               break;
-
-       default:
-               return -ENOTTY;
-       }
-
-       if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
-               ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
-               if (ret)
-                       ret = -EFAULT;
-       }
-       return ret;
-}
-
-/*
- *     System shutdown handler.  Turn off the watchdog if we're
- *     restarting or halting the system.
- */
-static void mpcore_wdt_shutdown(struct platform_device *dev)
-{
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
-
-       if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
-               mpcore_wdt_stop(wdt);
-}
-
-/*
- *     Kernel Interfaces
- */
-static const struct file_operations mpcore_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = mpcore_wdt_write,
-       .ioctl          = mpcore_wdt_ioctl,
-       .open           = mpcore_wdt_open,
-       .release        = mpcore_wdt_release,
-};
-
-static struct miscdevice mpcore_wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &mpcore_wdt_fops,
-};
-
-static int __devinit mpcore_wdt_probe(struct platform_device *dev)
-{
-       struct mpcore_wdt *wdt;
-       struct resource *res;
-       int ret;
-
-       /* We only accept one device, and it must have an id of -1 */
-       if (dev->id != -1)
-               return -ENODEV;
-
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto err_out;
-       }
-
-       wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
-       if (!wdt) {
-               ret = -ENOMEM;
-               goto err_out;
-       }
-
-       wdt->dev = &dev->dev;
-       wdt->irq = platform_get_irq(dev, 0);
-       if (wdt->irq < 0) {
-               ret = -ENXIO;
-               goto err_free;
-       }
-       wdt->base = ioremap(res->start, res->end - res->start + 1);
-       if (!wdt->base) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
-
-       mpcore_wdt_miscdev.parent = &dev->dev;
-       ret = misc_register(&mpcore_wdt_miscdev);
-       if (ret) {
-               dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
-                          WATCHDOG_MINOR, ret);
-               goto err_misc;
-       }
-
-       ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt);
-       if (ret) {
-               dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
-               goto err_irq;
-       }
-
-       mpcore_wdt_stop(wdt);
-       platform_set_drvdata(&dev->dev, wdt);
-       mpcore_wdt_dev = dev;
-
-       return 0;
-
- err_irq:
-       misc_deregister(&mpcore_wdt_miscdev);
- err_misc:
-       iounmap(wdt->base);
- err_free:
-       kfree(wdt);
- err_out:
-       return ret;
-}
-
-static int __devexit mpcore_wdt_remove(struct platform_device *dev)
-{
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
-
-       misc_deregister(&mpcore_wdt_miscdev);
-
-       mpcore_wdt_dev = NULL;
-
-       free_irq(wdt->irq, wdt);
-       iounmap(wdt->base);
-       kfree(wdt);
-       return 0;
-}
-
-static struct platform_driver mpcore_wdt_driver = {
-       .probe          = mpcore_wdt_probe,
-       .remove         = __devexit_p(mpcore_wdt_remove),
-       .shutdown       = mpcore_wdt_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "mpcore_wdt",
-       },
-};
-
-static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
-
-static int __init mpcore_wdt_init(void)
-{
-       /*
-        * Check that the margin value is within it's range;
-        * if not reset to the default
-        */
-       if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
-               mpcore_wdt_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
-                       TIMER_MARGIN);
-       }
-
-       printk(banner, mpcore_noboot, mpcore_margin, nowayout);
-
-       return platform_driver_register(&mpcore_wdt_driver);
-}
-
-static void __exit mpcore_wdt_exit(void)
-{
-       platform_driver_unregister(&mpcore_wdt_driver);
-}
-
-module_init(mpcore_wdt_init);
-module_exit(mpcore_wdt_exit);
-
-MODULE_AUTHOR("ARM Limited");
-MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c
deleted file mode 100644 (file)
index dcfd401..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- *      Driver for the MTX-1 Watchdog.
- *
- *      (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
- *                              http://www.4g-systems.biz
- *
- *     (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org>
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- *      Neither Michael Stickel nor 4G Systems admit liability nor provide
- *      warranty for any of this software. This material is provided
- *      "AS-IS" and at no charge.
- *
- *      (c) Copyright 2005    4G Systems <info@4g-systems.biz>
- *
- *      Release 0.01.
- *      Author: Michael Stickel  michael.stickel@4g-systems.biz
- *
- *      Release 0.02.
- *     Author: Florian Fainelli florian@openwrt.org
- *             use the Linux watchdog/timer APIs
- *
- *      The Watchdog is configured to reset the MTX-1
- *      if it is not triggered for 100 seconds.
- *      It should not be triggered more often than 1.6 seconds.
- *
- *      A timer triggers the watchdog every 5 seconds, until
- *      it is opened for the first time. After the first open
- *      it MUST be triggered every 2..95 seconds.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
-#include <linux/jiffies.h>
-#include <linux/watchdog.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-#define MTX1_WDT_INTERVAL      (5 * HZ)
-
-static int ticks = 100 * HZ;
-
-static struct {
-       struct completion stop;
-       volatile int running;
-       struct timer_list timer;
-       volatile int queue;
-       int default_ticks;
-       unsigned long inuse;
-} mtx1_wdt_device;
-
-static void mtx1_wdt_trigger(unsigned long unused)
-{
-       u32 tmp;
-
-       if (mtx1_wdt_device.running)
-               ticks--;
-       /*
-        * toggle GPIO2_15
-        */
-       tmp = au_readl(GPIO2_DIR);
-       tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15));
-       au_writel (tmp, GPIO2_DIR);
-
-       if (mtx1_wdt_device.queue && ticks)
-               mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
-       else {
-               complete(&mtx1_wdt_device.stop);
-       }
-}
-
-static void mtx1_wdt_reset(void)
-{
-       ticks = mtx1_wdt_device.default_ticks;
-}
-
-
-static void mtx1_wdt_start(void)
-{
-       if (!mtx1_wdt_device.queue) {
-               mtx1_wdt_device.queue = 1;
-               au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR);
-               mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
-       }
-       mtx1_wdt_device.running++;
-}
-
-static int mtx1_wdt_stop(void)
-{
-       if (mtx1_wdt_device.queue) {
-               mtx1_wdt_device.queue = 0;
-               au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR);
-       }
-
-       ticks = mtx1_wdt_device.default_ticks;
-
-       return 0;
-}
-
-/* Filesystem functions */
-
-static int mtx1_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &mtx1_wdt_device.inuse))
-               return -EBUSY;
-
-       return nonseekable_open(inode, file);
-}
-
-
-static int mtx1_wdt_release(struct inode *inode, struct file *file)
-{
-       clear_bit(0, &mtx1_wdt_device.inuse);
-       return 0;
-}
-
-static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       unsigned int value;
-       static struct watchdog_info ident =
-       {
-               .options = WDIOF_CARDRESET,
-               .identity = "MTX-1 WDT",
-       };
-
-       switch(cmd) {
-               case WDIOC_KEEPALIVE:
-                       mtx1_wdt_reset();
-                       break;
-               case WDIOC_GETSTATUS:
-               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;
-                       break;
-               case WDIOC_SETOPTIONS:
-                       if ( copy_from_user(&value, argp, sizeof(int)) )
-                               return -EFAULT;
-                       switch(value) {
-                               case WDIOS_ENABLECARD:
-                                       mtx1_wdt_start();
-                                       break;
-                               case WDIOS_DISABLECARD:
-                                       return mtx1_wdt_stop();
-                               default:
-                                       return -EINVAL;
-                       }
-                       break;
-               default:
-                       return -ENOTTY;
-       }
-       return 0;
-}
-
-
-static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-       if (!count)
-               return -EIO;
-
-       mtx1_wdt_reset();
-       return count;
-}
-
-static struct file_operations mtx1_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .ioctl          = mtx1_wdt_ioctl,
-       .open           = mtx1_wdt_open,
-       .write          = mtx1_wdt_write,
-       .release        = mtx1_wdt_release
-};
-
-
-static struct miscdevice mtx1_wdt_misc = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &mtx1_wdt_fops
-};
-
-
-static int __init mtx1_wdt_init(void)
-{
-       int ret;
-
-       if ((ret = misc_register(&mtx1_wdt_misc)) < 0) {
-               printk(KERN_ERR " mtx-1_wdt : failed to register\n");
-               return ret;
-       }
-
-       init_completion(&mtx1_wdt_device.stop);
-       mtx1_wdt_device.queue = 0;
-
-       clear_bit(0, &mtx1_wdt_device.inuse);
-
-       setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
-
-       mtx1_wdt_device.default_ticks = ticks;
-
-       mtx1_wdt_start();
-
-       printk(KERN_INFO "MTX-1 Watchdog driver\n");
-
-       return 0;
-}
-
-static void __exit mtx1_wdt_exit(void)
-{
-       if (mtx1_wdt_device.queue) {
-               mtx1_wdt_device.queue = 0;
-               wait_for_completion(&mtx1_wdt_device.stop);
-       }
-       misc_deregister(&mtx1_wdt_misc);
-}
-
-module_init(mtx1_wdt_init);
-module_exit(mtx1_wdt_exit);
-
-MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
-MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
deleted file mode 100644 (file)
index 0365c31..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
- *
- * Author: James Chapman <jchapman@katalix.com>
- *
- * Platform-specific setup code should configure the dog to generate
- * interrupt or reset as required.  This code only enables/disables
- * and services the watchdog.
- *
- * Derived from mpc8xx_wdt.c, with the following copyright.
- * 
- * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/watchdog.h>
-#include <linux/platform_device.h>
-
-#include <linux/mv643xx.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#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
-
-static unsigned long wdt_flags;
-static int wdt_status;
-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 int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
-{
-       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)
-{
-       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 (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
-                                  MV64x60_WDC_ENABLE_SHIFT))
-               printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
-}
-
-static void mv64x60_wdt_set_timeout(unsigned int timeout)
-{
-       /* 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)
-{
-       if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       mv64x60_wdt_handler_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static int mv64x60_wdt_release(struct inode *inode, struct file *file)
-{
-       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);
-
-       return 0;
-}
-
-static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
-                                size_t len, loff_t * ppos)
-{
-       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;
-}
-
-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_SETTIMEOUT        |
-                               WDIOF_MAGICCLOSE        |
-                               WDIOF_KEEPALIVEPING,
-               .firmware_version = 0,
-               .identity = "MV64x60 watchdog",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &info, sizeof(info)))
-                       return -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               if (put_user(wdt_status, (int __user *)argp))
-                       return -EFAULT;
-               wdt_status &= ~WDIOF_KEEPALIVEPING;
-               break;
-
-       case WDIOC_GETTEMP:
-               return -EOPNOTSUPP;
-
-       case WDIOC_SETOPTIONS:
-               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();
-               wdt_status |= WDIOF_KEEPALIVEPING;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(timeout, (int __user *)argp))
-                       return -EFAULT;
-               mv64x60_wdt_set_timeout(timeout);
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               if (put_user(mv64x60_wdt_timeout, (int __user *)argp))
-                       return -EFAULT;
-               break;
-
-       default:
-               return -ENOTTY;
-       }
-
-       return 0;
-}
-
-static const struct file_operations mv64x60_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = mv64x60_wdt_write,
-       .ioctl = mv64x60_wdt_ioctl,
-       .open = mv64x60_wdt_open,
-       .release = mv64x60_wdt_release,
-};
-
-static struct miscdevice mv64x60_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &mv64x60_wdt_fops,
-};
-
-static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
-{
-       struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
-       struct resource *r;
-       int timeout = 10;
-
-       bus_clk = 133;                  /* in MHz */
-       if (pdata) {
-               timeout = pdata->timeout;
-               bus_clk = pdata->bus_clk;
-       }
-
-       /* 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;
-
-       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);
-}
-
-static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
-{
-       misc_deregister(&mv64x60_wdt_miscdev);
-
-       mv64x60_wdt_handler_disable();
-
-       iounmap(mv64x60_wdt_regs);
-
-       return 0;
-}
-
-static struct platform_driver mv64x60_wdt_driver = {
-       .probe = mv64x60_wdt_probe,
-       .remove = __devexit_p(mv64x60_wdt_remove),
-       .driver = {
-               .owner = THIS_MODULE,
-               .name = MV64x60_WDT_NAME,
-       },
-};
-
-static int __init mv64x60_wdt_init(void)
-{
-       printk(KERN_INFO "MV64x60 watchdog driver\n");
-
-       return platform_driver_register(&mv64x60_wdt_driver);
-}
-
-static void __exit mv64x60_wdt_exit(void)
-{
-       platform_driver_unregister(&mv64x60_wdt_driver);
-}
-
-module_init(mv64x60_wdt_init);
-module_exit(mv64x60_wdt_exit);
-
-MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
-MODULE_DESCRIPTION("MV64x60 watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
deleted file mode 100644 (file)
index 719b066..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * linux/drivers/char/watchdog/omap_wdt.c
- *
- * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
- *
- * Author: MontaVista Software, Inc.
- *      <gdavis@mvista.com> or <source@mvista.com>
- *
- * 2003 (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.
- *
- * History:
- *
- * 20030527: George G. Davis <gdavis@mvista.com>
- *     Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
- *     (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
- *     Based on SoftDog driver by Alan Cox <alan@redhat.com>
- *
- * Copyright (c) 2004 Texas Instruments.
- *     1. Modified to support OMAP1610 32-KHz watchdog timer
- *     2. Ported to 2.6 kernel
- *
- * Copyright (c) 2005 David Brownell
- *     Use the driver model and standard identifiers; handle bigger timeouts.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/moduleparam.h>
-#include <linux/clk.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/hardware.h>
-#include <asm/bitops.h>
-
-#include <asm/arch/prcm.h>
-
-#include "omap_wdt.h"
-
-static unsigned timer_margin;
-module_param(timer_margin, uint, 0);
-MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
-
-static int omap_wdt_users;
-static struct clk *armwdt_ck = NULL;
-static struct clk *mpu_wdt_ick = NULL;
-static struct clk *mpu_wdt_fck = NULL;
-
-static unsigned int wdt_trgr_pattern = 0x1234;
-
-static void omap_wdt_ping(void)
-{
-       /* wait for posted write to complete */
-       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
-               cpu_relax();
-       wdt_trgr_pattern = ~wdt_trgr_pattern;
-       omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
-       /* wait for posted write to complete */
-       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
-               cpu_relax();
-       /* reloaded WCRR from WLDR */
-}
-
-static void omap_wdt_enable(void)
-{
-       /* Sequence to enable the watchdog */
-       omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
-       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
-               cpu_relax();
-       omap_writel(0x4444, OMAP_WATCHDOG_SPR);
-       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
-               cpu_relax();
-}
-
-static void omap_wdt_disable(void)
-{
-       /* sequence required to disable watchdog */
-       omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
-               cpu_relax();
-       omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
-               cpu_relax();
-}
-
-static void omap_wdt_adjust_timeout(unsigned new_timeout)
-{
-       if (new_timeout < TIMER_MARGIN_MIN)
-               new_timeout = TIMER_MARGIN_DEFAULT;
-       if (new_timeout > TIMER_MARGIN_MAX)
-               new_timeout = TIMER_MARGIN_MAX;
-       timer_margin = new_timeout;
-}
-
-static void omap_wdt_set_timeout(void)
-{
-       u32 pre_margin = GET_WLDR_VAL(timer_margin);
-
-       /* just count up at 32 KHz */
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
-               cpu_relax();
-       omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
-               cpu_relax();
-}
-
-/*
- *     Allow only one task to hold it open
- */
-
-static int omap_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
-               return -EBUSY;
-
-       if (cpu_is_omap16xx())
-               clk_enable(armwdt_ck);  /* Enable the clock */
-
-       if (cpu_is_omap24xx()) {
-               clk_enable(mpu_wdt_ick);    /* Enable the interface clock */
-               clk_enable(mpu_wdt_fck);    /* Enable the functional clock */
-       }
-
-       /* initialize prescaler */
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
-               cpu_relax();
-       omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
-       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
-               cpu_relax();
-
-       omap_wdt_set_timeout();
-       omap_wdt_enable();
-       return nonseekable_open(inode, file);
-}
-
-static int omap_wdt_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer unless NOWAYOUT is defined.
-        */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-       omap_wdt_disable();
-
-       if (cpu_is_omap16xx()) {
-               clk_disable(armwdt_ck); /* Disable the clock */
-               clk_put(armwdt_ck);
-               armwdt_ck = NULL;
-       }
-
-       if (cpu_is_omap24xx()) {
-               clk_disable(mpu_wdt_ick);       /* Disable the clock */
-               clk_disable(mpu_wdt_fck);       /* Disable the clock */
-               clk_put(mpu_wdt_ick);
-               clk_put(mpu_wdt_fck);
-               mpu_wdt_ick = NULL;
-               mpu_wdt_fck = NULL;
-       }
-#else
-       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
-#endif
-       omap_wdt_users = 0;
-       return 0;
-}
-
-static ssize_t
-omap_wdt_write(struct file *file, const char __user *data,
-               size_t len, loff_t *ppos)
-{
-       /* Refresh LOAD_TIME. */
-       if (len)
-               omap_wdt_ping();
-       return len;
-}
-
-static int
-omap_wdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int new_margin;
-       static struct watchdog_info ident = {
-               .identity = "OMAP Watchdog",
-               .options = WDIOF_SETTIMEOUT,
-               .firmware_version = 0,
-       };
-
-       switch (cmd) {
-       default:
-               return -ENOTTY;
-       case WDIOC_GETSUPPORT:
-               return copy_to_user((struct watchdog_info __user *)arg, &ident,
-                               sizeof(ident));
-       case WDIOC_GETSTATUS:
-               return put_user(0, (int __user *)arg);
-       case WDIOC_GETBOOTSTATUS:
-               if (cpu_is_omap16xx())
-                       return put_user(omap_readw(ARM_SYSST),
-                                       (int __user *)arg);
-               if (cpu_is_omap24xx())
-                       return put_user(omap_prcm_get_reset_sources(),
-                                       (int __user *)arg);
-       case WDIOC_KEEPALIVE:
-               omap_wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, (int __user *)arg))
-                       return -EFAULT;
-               omap_wdt_adjust_timeout(new_margin);
-
-               omap_wdt_disable();
-               omap_wdt_set_timeout();
-               omap_wdt_enable();
-
-               omap_wdt_ping();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(timer_margin, (int __user *)arg);
-       }
-}
-
-static const struct file_operations omap_wdt_fops = {
-       .owner = THIS_MODULE,
-       .write = omap_wdt_write,
-       .ioctl = omap_wdt_ioctl,
-       .open = omap_wdt_open,
-       .release = omap_wdt_release,
-};
-
-static struct miscdevice omap_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &omap_wdt_fops
-};
-
-static int __init omap_wdt_probe(struct platform_device *pdev)
-{
-       struct resource *res, *mem;
-       int ret;
-
-       /* reserve static register mappings */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENOENT;
-
-       mem = request_mem_region(res->start, res->end - res->start + 1,
-                                pdev->name);
-       if (mem == NULL)
-               return -EBUSY;
-
-       platform_set_drvdata(pdev, mem);
-
-       omap_wdt_users = 0;
-
-       if (cpu_is_omap16xx()) {
-               armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
-               if (IS_ERR(armwdt_ck)) {
-                       ret = PTR_ERR(armwdt_ck);
-                       armwdt_ck = NULL;
-                       goto fail;
-               }
-       }
-
-       if (cpu_is_omap24xx()) {
-               mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
-               if (IS_ERR(mpu_wdt_ick)) {
-                       ret = PTR_ERR(mpu_wdt_ick);
-                       mpu_wdt_ick = NULL;
-                       goto fail;
-               }
-               mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
-               if (IS_ERR(mpu_wdt_fck)) {
-                       ret = PTR_ERR(mpu_wdt_fck);
-                       mpu_wdt_fck = NULL;
-                       goto fail;
-               }
-       }
-
-       omap_wdt_disable();
-       omap_wdt_adjust_timeout(timer_margin);
-
-       omap_wdt_miscdev.parent = &pdev->dev;
-       ret = misc_register(&omap_wdt_miscdev);
-       if (ret)
-               goto fail;
-
-       pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
-
-       /* autogate OCP interface clock */
-       omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
-       return 0;
-
-fail:
-       if (armwdt_ck)
-               clk_put(armwdt_ck);
-       if (mpu_wdt_ick)
-               clk_put(mpu_wdt_ick);
-       if (mpu_wdt_fck)
-               clk_put(mpu_wdt_fck);
-       release_resource(mem);
-       return ret;
-}
-
-static void omap_wdt_shutdown(struct platform_device *pdev)
-{
-       omap_wdt_disable();
-}
-
-static int omap_wdt_remove(struct platform_device *pdev)
-{
-       struct resource *mem = platform_get_drvdata(pdev);
-       misc_deregister(&omap_wdt_miscdev);
-       release_resource(mem);
-       if (armwdt_ck)
-               clk_put(armwdt_ck);
-       if (mpu_wdt_ick)
-               clk_put(mpu_wdt_ick);
-       if (mpu_wdt_fck)
-               clk_put(mpu_wdt_fck);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-/* REVISIT ... not clear this is the best way to handle system suspend; and
- * it's very inappropriate for selective device suspend (e.g. suspending this
- * through sysfs rather than by stopping the watchdog daemon).  Also, this
- * may not play well enough with NOWAYOUT...
- */
-
-static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       if (omap_wdt_users)
-               omap_wdt_disable();
-       return 0;
-}
-
-static int omap_wdt_resume(struct platform_device *pdev)
-{
-       if (omap_wdt_users) {
-               omap_wdt_enable();
-               omap_wdt_ping();
-       }
-       return 0;
-}
-
-#else
-#define        omap_wdt_suspend        NULL
-#define        omap_wdt_resume         NULL
-#endif
-
-static struct platform_driver omap_wdt_driver = {
-       .probe          = omap_wdt_probe,
-       .remove         = omap_wdt_remove,
-       .shutdown       = omap_wdt_shutdown,
-       .suspend        = omap_wdt_suspend,
-       .resume         = omap_wdt_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "omap_wdt",
-       },
-};
-
-static int __init omap_wdt_init(void)
-{
-       return platform_driver_register(&omap_wdt_driver);
-}
-
-static void __exit omap_wdt_exit(void)
-{
-       platform_driver_unregister(&omap_wdt_driver);
-}
-
-module_init(omap_wdt_init);
-module_exit(omap_wdt_exit);
-
-MODULE_AUTHOR("George G. Davis");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
deleted file mode 100644 (file)
index 52a532a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  linux/drivers/char/watchdog/omap_wdt.h
- *
- *  BRIEF MODULE DESCRIPTION
- *      OMAP Watchdog timer register definitions
- *
- *  Copyright (C) 2004 Texas Instruments.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _OMAP_WATCHDOG_H
-#define _OMAP_WATCHDOG_H
-
-#define OMAP1610_WATCHDOG_BASE         0xfffeb000
-#define OMAP2420_WATCHDOG_BASE         0x48022000      /*WDT Timer 2 */
-
-#ifdef CONFIG_ARCH_OMAP24XX
-#define OMAP_WATCHDOG_BASE             OMAP2420_WATCHDOG_BASE
-#else
-#define OMAP_WATCHDOG_BASE             OMAP1610_WATCHDOG_BASE
-#define RM_RSTST_WKUP                  0
-#endif
-
-#define OMAP_WATCHDOG_REV              (OMAP_WATCHDOG_BASE + 0x00)
-#define OMAP_WATCHDOG_SYS_CONFIG       (OMAP_WATCHDOG_BASE + 0x10)
-#define OMAP_WATCHDOG_STATUS           (OMAP_WATCHDOG_BASE + 0x14)
-#define OMAP_WATCHDOG_CNTRL            (OMAP_WATCHDOG_BASE + 0x24)
-#define OMAP_WATCHDOG_CRR              (OMAP_WATCHDOG_BASE + 0x28)
-#define OMAP_WATCHDOG_LDR              (OMAP_WATCHDOG_BASE + 0x2c)
-#define OMAP_WATCHDOG_TGR              (OMAP_WATCHDOG_BASE + 0x30)
-#define OMAP_WATCHDOG_WPS              (OMAP_WATCHDOG_BASE + 0x34)
-#define OMAP_WATCHDOG_SPR              (OMAP_WATCHDOG_BASE + 0x48)
-
-/* Using the prescaler, the OMAP watchdog could go for many
- * months before firing.  These limits work without scaling,
- * with the 60 second default assumed by most tools and docs.
- */
-#define TIMER_MARGIN_MAX       (24 * 60 * 60)  /* 1 day */
-#define TIMER_MARGIN_DEFAULT   60      /* 60 secs */
-#define TIMER_MARGIN_MIN       1
-
-#define PTV                    0       /* prescale */
-#define GET_WLDR_VAL(secs)     (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
-
-#endif                         /* _OMAP_WATCHDOG_H */
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c
deleted file mode 100644 (file)
index 3d3deae..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- *      NS pc87413-wdt Watchdog Timer driver for Linux 2.6.x.x
- *
- *      This code is based on wdt.c with original copyright.
- *
- *      (C) Copyright 2006 Sven Anders, <anders@anduras.de>
- *                     and Marcus Junker, <junker@anduras.de>
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- *      Neither Sven Anders, Marcus Junker nor ANDURAS AG
- *      admit liability nor provide warranty for any of this software.
- *      This material is provided "AS-IS" and at no charge.
- *
- *      Release 1.1
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/notifier.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-#include <linux/version.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* #define DEBUG 1 */
-
-#define DEFAULT_TIMEOUT     1            /* 1 minute */
-#define MAX_TIMEOUT         255
-
-#define VERSION             "1.1"
-#define MODNAME             "pc87413 WDT"
-#define PFX                 MODNAME ": "
-#define DPFX                MODNAME " - DEBUG: "
-
-#define WDT_INDEX_IO_PORT   (io+0)       /* I/O port base (index register) */
-#define WDT_DATA_IO_PORT    (WDT_INDEX_IO_PORT+1)
-#define SWC_LDN             0x04
-#define SIOCFG2             0x22         /* Serial IO register */
-#define WDCTL               0x10         /* Watchdog-Timer-Controll-Register */
-#define WDTO                0x11         /* Watchdog timeout register */
-#define WDCFG               0x12         /* Watchdog config register */
-
-static int io = 0x2E;                   /* Address used on Portwell Boards */
-
-static int timeout = DEFAULT_TIMEOUT;    /* timeout value */
-static unsigned long timer_enabled = 0;  /* is the timer enabled? */
-
-static char expect_close;                /* is the close expected? */
-
-static spinlock_t io_lock;               /* to guard the watchdog from io races */
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-/* -- Low level function ----------------------------------------*/
-
-/* Select pins for Watchdog output */
-
-static inline void pc87413_select_wdt_out (void)
-{
-       unsigned int cr_data = 0;
-
-       /* Step 1: Select multiple pin,pin55,as WDT output */
-
-       outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
-
-       cr_data = inb (WDT_DATA_IO_PORT);
-
-       cr_data |= 0x80; /* Set Bit7 to 1*/
-       outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
-
-       outb_p(cr_data, WDT_DATA_IO_PORT);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:"
-                             " Bit7 to 1: %d\n", cr_data);
-#endif
-}
-
-/* Enable SWC functions */
-
-static inline void pc87413_enable_swc(void)
-{
-       unsigned int cr_data=0;
-
-       /* Step 2: Enable SWC functions */
-
-       outb_p(0x07, WDT_INDEX_IO_PORT);        /* Point SWC_LDN (LDN=4) */
-       outb_p(SWC_LDN, WDT_DATA_IO_PORT);
-
-       outb_p(0x30, WDT_INDEX_IO_PORT);        /* Read Index 0x30 First */
-       cr_data = inb(WDT_DATA_IO_PORT);
-       cr_data |= 0x01;                        /* Set Bit0 to 1 */
-       outb_p(0x30, WDT_INDEX_IO_PORT);
-       outb_p(cr_data, WDT_DATA_IO_PORT);      /* Index0x30_bit0P1 */
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
-#endif
-}
-
-/* Read SWC I/O base address */
-
-static inline unsigned int pc87413_get_swc_base(void)
-{
-       unsigned int  swc_base_addr = 0;
-       unsigned char addr_l, addr_h = 0;
-
-       /* Step 3: Read SWC I/O Base Address */
-
-       outb_p(0x60, WDT_INDEX_IO_PORT);        /* Read Index 0x60 */
-       addr_h = inb(WDT_DATA_IO_PORT);
-
-       outb_p(0x61, WDT_INDEX_IO_PORT);        /* Read Index 0x61 */
-
-       addr_l = inb(WDT_DATA_IO_PORT);
-
-       swc_base_addr = (addr_h << 8) + addr_l;
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d,"
-                             " res %d\n", addr_l, addr_h, swc_base_addr);
-#endif
-
-       return swc_base_addr;
-}
-
-/* Select Bank 3 of SWC */
-
-static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
-{
-       /* Step 4: Select Bank3 of SWC */
-
-       outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
-#endif
-}
-
-/* Set watchdog timeout to x minutes */
-
-static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
-                                        char pc87413_time)
-{
-       /* Step 5: Programm WDTO, Twd. */
-
-       outb_p(pc87413_time, swc_base_addr + WDTO);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
-#endif
-}
-
-/* Enable WDEN */
-
-static inline void pc87413_enable_wden(unsigned int swc_base_addr)
-{
-       /* Step 6: Enable WDEN */
-
-       outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable WDEN\n");
-#endif
-}
-
-/* Enable SW_WD_TREN */
-static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
-{
-       /* Enable SW_WD_TREN */
-
-       outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
-#endif
-}
-
-/* Disable SW_WD_TREN */
-
-static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
-{
-       /* Disable SW_WD_TREN */
-
-       outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
-#endif
-}
-
-/* Enable SW_WD_TRG */
-
-static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
-{
-       /* Enable SW_WD_TRG */
-
-       outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
-#endif
-}
-
-/* Disable SW_WD_TRG */
-
-static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
-{
-       /* Disable SW_WD_TRG */
-
-       outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
-
-#ifdef DEBUG
-       printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
-#endif
-}
-
-/* -- Higher level functions ------------------------------------*/
-
-/* Enable the watchdog */
-
-static void pc87413_enable(void)
-{
-       unsigned int swc_base_addr;
-
-       spin_lock(&io_lock);
-
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, timeout);
-       pc87413_enable_wden(swc_base_addr);
-       pc87413_enable_sw_wd_tren(swc_base_addr);
-       pc87413_enable_sw_wd_trg(swc_base_addr);
-
-       spin_unlock(&io_lock);
-}
-
-/* Disable the watchdog */
-
-static void pc87413_disable(void)
-{
-       unsigned int swc_base_addr;
-
-       spin_lock(&io_lock);
-
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_disable_sw_wd_tren(swc_base_addr);
-       pc87413_disable_sw_wd_trg(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, 0);
-
-       spin_unlock(&io_lock);
-}
-
-/* Refresh the watchdog */
-
-static void pc87413_refresh(void)
-{
-       unsigned int swc_base_addr;
-
-       spin_lock(&io_lock);
-
-       pc87413_select_wdt_out();
-       pc87413_enable_swc();
-       swc_base_addr = pc87413_get_swc_base();
-       pc87413_swc_bank3(swc_base_addr);
-       pc87413_disable_sw_wd_tren(swc_base_addr);
-       pc87413_disable_sw_wd_trg(swc_base_addr);
-       pc87413_programm_wdto(swc_base_addr, timeout);
-       pc87413_enable_wden(swc_base_addr);
-       pc87413_enable_sw_wd_tren(swc_base_addr);
-       pc87413_enable_sw_wd_trg(swc_base_addr);
-
-       spin_unlock(&io_lock);
-}
-
-/* -- File operations -------------------------------------------*/
-
-/**
- *     pc87413_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- */
-
-static int pc87413_open(struct inode *inode, struct file *file)
-{
-       /* /dev/watchdog can only be opened once */
-
-       if (test_and_set_bit(0, &timer_enabled))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Reload and activate timer */
-       pc87413_refresh();
-
-       printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to"
-                                " %d minute(s).\n", timeout);
-
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     pc87413_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute
- *     between people who want their watchdog to be able to shut down and
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-
-static int pc87413_release(struct inode *inode, struct file *file)
-{
-       /* Shut off the timer. */
-
-       if (expect_close == 42) {
-               pc87413_disable();
-               printk(KERN_INFO MODNAME "Watchdog disabled,"
-                                        " sleeping again...\n");
-       } else {
-               printk(KERN_CRIT MODNAME "Unexpected close, not stopping"
-                                        " watchdog!\n");
-               pc87413_refresh();
-       }
-
-       clear_bit(0, &timer_enabled);
-       expect_close = 0;
-
-       return 0;
-}
-
-/**
- *     pc87413_status:
- *
- *      return, if the watchdog is enabled (timeout is set...)
- */
-
-
-static int pc87413_status(void)
-{
-         return 0; /* currently not supported */
-}
-
-/**
- *     pc87413_write:
- *     @file: file handle to the watchdog
- *     @data: data buffer to write
- *     @len: length in bytes
- *     @ppos: pointer to the position to write. No seeks allowed
- *
- *     A write to a watchdog device is defined as a keepalive signal. Any
- *     write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t pc87413_write(struct file *file, const char __user *data,
-                            size_t len, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* reset expect flag */
-                       expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               pc87413_refresh();
-       }
-       return len;
-}
-
-/**
- *     pc87413_ioctl:
- *     @inode: inode of the device
- *     @file: file handle to the device
- *     @cmd: watchdog command
- *     @arg: argument pointer
- *
- *     The watchdog API defines a common set of functions for all watchdogs
- *     according to their available features. We only actually usefully support
- *     querying capabilities and current status.
- */
-
-static int pc87413_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, unsigned long arg)
-{
-       int new_timeout;
-
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-
-       static struct watchdog_info ident = {
-               .options          = WDIOF_KEEPALIVEPING |
-                                   WDIOF_SETTIMEOUT |
-                                   WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity         = "PC87413(HF/F) watchdog"
-       };
-
-       uarg.i = (int __user *)arg;
-
-       switch(cmd) {
-               default:
-                       return -ENOTTY;
-
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(uarg.ident, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user(pc87413_status(), uarg.i);
-
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, uarg.i);
-
-               case WDIOC_KEEPALIVE:
-                       pc87413_refresh();
-#ifdef DEBUG
-                       printk(KERN_INFO DPFX "keepalive\n");
-#endif
-                       return 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_timeout, uarg.i))
-                               return -EFAULT;
-
-                       // the API states this is given in secs
-                       new_timeout /= 60;
-
-                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       pc87413_refresh();
-
-                       // fall through and return the new timeout...
-
-               case WDIOC_GETTIMEOUT:
-
-                       new_timeout = timeout * 60;
-
-                       return put_user(new_timeout, uarg.i);
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int options, retval = -EINVAL;
-
-                       if (get_user(options, uarg.i))
-                               return -EFAULT;
-
-                       if (options & WDIOS_DISABLECARD) {
-                               pc87413_disable();
-                               retval = 0;
-                       }
-
-                       if (options & WDIOS_ENABLECARD) {
-                               pc87413_enable();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-       }
-}
-
-/* -- Notifier funtions -----------------------------------------*/
-
-/**
- *     notify_sys:
- *     @this: our notifier block
- *     @code: the event being reported
- *     @unused: unused
- *
- *     Our notifier is called on system shutdowns. We want to turn the card
- *     off at reboot otherwise the machine will reboot again during memory
- *     test or worse yet during the following fsck. This would suck, in fact
- *     trust me - if it happens it does suck.
- */
-
-static int pc87413_notify_sys(struct notifier_block *this,
-                             unsigned long code,
-                             void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-       {
-               /* Turn the card off */
-               pc87413_disable();
-       }
-       return NOTIFY_DONE;
-}
-
-/* -- Module's structures ---------------------------------------*/
-
-static const struct file_operations pc87413_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = pc87413_write,
-       .ioctl          = pc87413_ioctl,
-       .open           = pc87413_open,
-       .release        = pc87413_release,
-};
-
-static struct notifier_block pc87413_notifier =
-{
-       .notifier_call  = pc87413_notify_sys,
-};
-
-static struct miscdevice pc87413_miscdev=
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &pc87413_fops
-};
-
-/* -- Module init functions -------------------------------------*/
-
-/**
- *     pc87413_init: module's "constructor"
- *
- *     Set up the WDT watchdog board. All we have to do is grab the
- *     resources we require and bitch if anyone beat us to them.
- *     The open() function will actually kick the board off.
- */
-
-static int __init pc87413_init(void)
-{
-       int ret;
-
-       spin_lock_init(&io_lock);
-
-       printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT);
-
-       /* request_region(io, 2, "pc87413"); */
-
-       ret = register_reboot_notifier(&pc87413_notifier);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-       }
-
-       ret = misc_register(&pc87413_miscdev);
-
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               unregister_reboot_notifier(&pc87413_notifier);
-               return ret;
-       }
-
-       printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
-
-       pc87413_enable();
-
-       return 0;
-}
-
-/**
- *     pc87413_exit: module's "destructor"
- *
- *     Unload the watchdog. You cannot do this with any file handles open.
- *     If your watchdog is set to continue ticking on close and you unload
- *     it, well it keeps ticking. We won't get the interrupt but the board
- *     will not touch PC memory so all is fine. You just have to load a new
- *     module in 60 seconds or reboot.
- */
-
-static void __exit pc87413_exit(void)
-{
-       /* Stop the timer before we leave */
-       if (!nowayout)
-       {
-               pc87413_disable();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
-       }
-
-       misc_deregister(&pc87413_miscdev);
-       unregister_reboot_notifier(&pc87413_notifier);
-       /* release_region(io,2); */
-
-       printk(MODNAME " watchdog component driver removed.\n");
-}
-
-module_init(pc87413_init);
-module_exit(pc87413_exit);
-
-MODULE_AUTHOR("Sven Anders <anders@anduras.de>, Marcus Junker <junker@anduras.de>,");
-MODULE_DESCRIPTION("PC87413 WDT driver");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ").");
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(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/pcwd.c b/drivers/char/watchdog/pcwd.c
deleted file mode 100644 (file)
index 7b41434..0000000
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * PC Watchdog Driver
- * by Ken Hollis (khollis@bitgate.com)
- *
- * Permission granted from Simon Machell (smachell@berkprod.com)
- * Written for the Linux Kernel, and GPLed by Ken Hollis
- *
- * 960107      Added request_region routines, modulized the whole thing.
- * 960108      Fixed end-of-file pointer (Thanks to Dan Hollis), added
- *             WD_TIMEOUT define.
- * 960216      Added eof marker on the file, and changed verbose messages.
- * 960716      Made functional and cosmetic changes to the source for
- *             inclusion in Linux 2.0.x kernels, thanks to Alan Cox.
- * 960717      Removed read/seek routines, replaced with ioctl.  Also, added
- *             check_region command due to Alan's suggestion.
- * 960821      Made changes to compile in newer 2.0.x kernels.  Added
- *             "cold reboot sense" entry.
- * 960825      Made a few changes to code, deleted some defines and made
- *             typedefs to replace them.  Made heartbeat reset only available
- *             via ioctl, and removed the write routine.
- * 960828      Added new items for PC Watchdog Rev.C card.
- * 960829      Changed around all of the IOCTLs, added new features,
- *             added watchdog disable/re-enable routines.  Added firmware
- *             version reporting.  Added read routine for temperature.
- *             Removed some extra defines, added an autodetect Revision
- *             routine.
- * 961006       Revised some documentation, fixed some cosmetic bugs.  Made
- *              drivers to panic the system if it's overheating at bootup.
- * 961118      Changed some verbiage on some of the output, tidied up
- *             code bits, and added compatibility to 2.1.x.
- * 970912       Enabled board on open and disable on close.
- * 971107      Took account of recent VFS changes (broke read).
- * 971210       Disable board on initialisation in case board already ticking.
- * 971222       Changed open/close for temperature handling
- *              Michael Meskes <meskes@debian.org>.
- * 980112       Used minor numbers from include/linux/miscdevice.h
- * 990403       Clear reset status after reading control status register in
- *              pcwd_showprevstate(). [Marc Boucher <marc@mbsi.ca>]
- * 990605      Made changes to code to support Firmware 1.22a, added
- *             fairly useless proc entry.
- * 990610      removed said useless proc code for the merge <alan>
- * 000403      Removed last traces of proc code. <davej>
- * 011214      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com>
- *              Added timeout module option to override default
- */
-
-/*
- *     A bells and whistles driver is available from http://www.pcwd.de/
- *     More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
- */
-
-#include <linux/module.h>      /* For module specific items */
-#include <linux/moduleparam.h> /* For new moduleparam's */
-#include <linux/types.h>       /* For standard types (like size_t) */
-#include <linux/errno.h>       /* For the -ENODEV/... values */
-#include <linux/kernel.h>      /* For printk/panic/... */
-#include <linux/delay.h>       /* For mdelay function */
-#include <linux/timer.h>       /* For timer related operations */
-#include <linux/jiffies.h>     /* For jiffies stuff */
-#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
-#include <linux/watchdog.h>    /* For the watchdog specific items */
-#include <linux/reboot.h>      /* For kernel_power_off() */
-#include <linux/init.h>                /* For __init/__exit/... */
-#include <linux/fs.h>          /* For file operations */
-#include <linux/isa.h>         /* For isa devices */
-#include <linux/ioport.h>      /* For io-port access */
-#include <linux/spinlock.h>    /* For spin_lock/spin_unlock/... */
-
-#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
-#include <asm/io.h>            /* For inb/outb/... */
-
-/* Module and version information */
-#define WATCHDOG_VERSION "1.20"
-#define WATCHDOG_DATE "18 Feb 2007"
-#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
-#define WATCHDOG_NAME "pcwd"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
-#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
-
-/*
- * It should be noted that PCWD_REVISION_B was removed because A and B
- * are essentially the same types of card, with the exception that B
- * has temperature reporting.  Since I didn't receive a Rev.B card,
- * the Rev.B card is not supported.  (It's a good thing too, as they
- * are no longer in production.)
- */
-#define        PCWD_REVISION_A         1
-#define        PCWD_REVISION_C         2
-
-/*
- * These are the auto-probe addresses available.
- *
- * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
- * Revision A has an address range of 2 addresses, while Revision C has 4.
- */
-#define PCWD_ISA_NR_CARDS      3
-static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
-
-/*
- * These are the defines that describe the control status bits for the
- * PCI-PC Watchdog card.
-*/
-/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
-#define WD_WDRST               0x01    /* Previously reset state */
-#define WD_T110                        0x02    /* Temperature overheat sense */
-#define WD_HRTBT               0x04    /* Heartbeat sense */
-#define WD_RLY2                        0x08    /* External relay triggered */
-#define WD_SRLY2               0x80    /* Software external relay triggered */
-/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
-#define WD_REVC_WTRP           0x01    /* Watchdog Trip status */
-#define WD_REVC_HRBT           0x02    /* Watchdog Heartbeat */
-#define WD_REVC_TTRP           0x04    /* Temperature Trip status */
-#define WD_REVC_RL2A           0x08    /* Relay 2 activated by on-board processor */
-#define WD_REVC_RL1A           0x10    /* Relay 1 active */
-#define WD_REVC_R2DS           0x40    /* Relay 2 disable */
-#define WD_REVC_RLY2           0x80    /* Relay 2 activated? */
-/* Port 2 : Control Status #2 */
-#define WD_WDIS                        0x10    /* Watchdog Disabled */
-#define WD_ENTP                        0x20    /* Watchdog Enable Temperature Trip */
-#define WD_SSEL                        0x40    /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
-#define WD_WCMD                        0x80    /* Watchdog Command Mode */
-
-/* max. time we give an ISA watchdog card to process a command */
-/* 500ms for each 4 bit response (according to spec.) */
-#define ISA_COMMAND_TIMEOUT     1000
-
-/* Watchdog's internal commands */
-#define CMD_ISA_IDLE                   0x00
-#define CMD_ISA_VERSION_INTEGER                0x01
-#define CMD_ISA_VERSION_TENTH          0x02
-#define CMD_ISA_VERSION_HUNDRETH       0x03
-#define CMD_ISA_VERSION_MINOR          0x04
-#define CMD_ISA_SWITCH_SETTINGS                0x05
-#define CMD_ISA_RESET_PC               0x06
-#define CMD_ISA_ARM_0                  0x07
-#define CMD_ISA_ARM_30                 0x08
-#define CMD_ISA_ARM_60                 0x09
-#define CMD_ISA_DELAY_TIME_2SECS       0x0A
-#define CMD_ISA_DELAY_TIME_4SECS       0x0B
-#define CMD_ISA_DELAY_TIME_8SECS       0x0C
-#define CMD_ISA_RESET_RELAYS           0x0D
-
-/* Watchdog's Dip Switch heartbeat values */
-static const int heartbeat_tbl [] = {
-       20,     /* OFF-OFF-OFF  = 20 Sec  */
-       40,     /* OFF-OFF-ON   = 40 Sec  */
-       60,     /* OFF-ON-OFF   =  1 Min  */
-       300,    /* OFF-ON-ON    =  5 Min  */
-       600,    /* ON-OFF-OFF   = 10 Min  */
-       1800,   /* ON-OFF-ON    = 30 Min  */
-       3600,   /* ON-ON-OFF    =  1 Hour */
-       7200,   /* ON-ON-ON     =  2 hour */
-};
-
-/*
- * We are using an kernel timer to do the pinging of the watchdog
- * every ~500ms. We try to set the internal heartbeat of the
- * watchdog to 2 ms.
- */
-
-#define WDT_INTERVAL (HZ/2+1)
-
-/* We can only use 1 card due to the /dev/watchdog restriction */
-static int cards_found;
-
-/* internal variables */
-static atomic_t open_allowed = ATOMIC_INIT(1);
-static char expect_close;
-static int temp_panic;
-static struct {                                /* this is private data for each ISA-PC watchdog card */
-       char fw_ver_str[6];             /* The cards firmware version */
-       int revision;                   /* The card's revision */
-       int supports_temp;              /* Wether or not the card has a temperature device */
-       int command_mode;               /* Wether or not the card is in command mode */
-       int boot_status;                /* The card's boot status */
-       int io_addr;                    /* The cards I/O address */
-       spinlock_t io_lock;             /* the lock for io operations */
-       struct timer_list timer;        /* The timer that pings the watchdog */
-       unsigned long next_heartbeat;   /* the next_heartbeat for the timer */
-} pcwd_private;
-
-/* module parameters */
-#define QUIET  0       /* Default */
-#define VERBOSE        1       /* Verbose */
-#define DEBUG  2       /* print fancy stuff too */
-static int debug = QUIET;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
-
-#define WATCHDOG_HEARTBEAT 0           /* default heartbeat = delay-time from dip-switches */
-static int heartbeat = WATCHDOG_HEARTBEAT;
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-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) ")");
-
-/*
- *     Internal functions
- */
-
-static int send_isa_command(int cmd)
-{
-       int i;
-       int control_status;
-       int port0, last_port0;  /* Double read for stabilising */
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
-                       cmd);
-
-       /* The WCMD bit must be 1 and the command is only 4 bits in size */
-       control_status = (cmd & 0x0F) | WD_WCMD;
-       outb_p(control_status, pcwd_private.io_addr + 2);
-       udelay(ISA_COMMAND_TIMEOUT);
-
-       port0 = inb_p(pcwd_private.io_addr);
-       for (i = 0; i < 25; ++i) {
-               last_port0 = port0;
-               port0 = inb_p(pcwd_private.io_addr);
-
-               if (port0 == last_port0)
-                       break;  /* Data is stable */
-
-               udelay (250);
-       }
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
-                       cmd, port0, last_port0);
-
-       return port0;
-}
-
-static int set_command_mode(void)
-{
-       int i, found=0, count=0;
-
-       /* Set the card into command mode */
-       spin_lock(&pcwd_private.io_lock);
-       while ((!found) && (count < 3)) {
-               i = send_isa_command(CMD_ISA_IDLE);
-
-               if (i == 0x00)
-                       found = 1;
-               else if (i == 0xF3) {
-                       /* Card does not like what we've done to it */
-                       outb_p(0x00, pcwd_private.io_addr + 2);
-                       udelay(1200);   /* Spec says wait 1ms */
-                       outb_p(0x00, pcwd_private.io_addr + 2);
-                       udelay(ISA_COMMAND_TIMEOUT);
-               }
-               count++;
-       }
-       spin_unlock(&pcwd_private.io_lock);
-       pcwd_private.command_mode = found;
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
-
-       return(found);
-}
-
-static void unset_command_mode(void)
-{
-       /* Set the card into normal mode */
-       spin_lock(&pcwd_private.io_lock);
-       outb_p(0x00, pcwd_private.io_addr + 2);
-       udelay(ISA_COMMAND_TIMEOUT);
-       spin_unlock(&pcwd_private.io_lock);
-
-       pcwd_private.command_mode = 0;
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
-}
-
-static inline void pcwd_check_temperature_support(void)
-{
-       if (inb(pcwd_private.io_addr) != 0xF0)
-               pcwd_private.supports_temp = 1;
-}
-
-static inline void pcwd_get_firmware(void)
-{
-       int one, ten, hund, minor;
-
-       strcpy(pcwd_private.fw_ver_str, "ERROR");
-
-       if (set_command_mode()) {
-               one = send_isa_command(CMD_ISA_VERSION_INTEGER);
-               ten = send_isa_command(CMD_ISA_VERSION_TENTH);
-               hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
-               minor = send_isa_command(CMD_ISA_VERSION_MINOR);
-               sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
-       }
-       unset_command_mode();
-
-       return;
-}
-
-static inline int pcwd_get_option_switches(void)
-{
-       int option_switches=0;
-
-       if (set_command_mode()) {
-               /* Get switch settings */
-               option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
-       }
-
-       unset_command_mode();
-       return(option_switches);
-}
-
-static void pcwd_show_card_info(void)
-{
-       int option_switches;
-
-       /* Get some extra info from the hardware (in command/debug/diag mode) */
-       if (pcwd_private.revision == PCWD_REVISION_A)
-               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
-       else if (pcwd_private.revision == PCWD_REVISION_C) {
-               pcwd_get_firmware();
-               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
-                       pcwd_private.io_addr, pcwd_private.fw_ver_str);
-               option_switches = pcwd_get_option_switches();
-               printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
-                       option_switches,
-                       ((option_switches & 0x10) ? "ON" : "OFF"),
-                       ((option_switches & 0x08) ? "ON" : "OFF"));
-
-               /* Reprogram internal heartbeat to 2 seconds */
-               if (set_command_mode()) {
-                       send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
-                       unset_command_mode();
-               }
-       }
-
-       if (pcwd_private.supports_temp)
-               printk(KERN_INFO PFX "Temperature Option Detected\n");
-
-       if (pcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
-
-       if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
-               printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
-               printk(KERN_EMERG PFX "CPU Overheat\n");
-       }
-
-       if (pcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
-}
-
-static void pcwd_timer_ping(unsigned long data)
-{
-       int wdrst_stat;
-
-       /* If we got a heartbeat pulse within the WDT_INTERVAL
-        * we agree to ping the WDT */
-       if(time_before(jiffies, pcwd_private.next_heartbeat)) {
-               /* Ping the watchdog */
-               spin_lock(&pcwd_private.io_lock);
-               if (pcwd_private.revision == PCWD_REVISION_A) {
-                       /*  Rev A cards are reset by setting the WD_WDRST bit in register 1 */
-                       wdrst_stat = inb_p(pcwd_private.io_addr);
-                       wdrst_stat &= 0x0F;
-                       wdrst_stat |= WD_WDRST;
-
-                       outb_p(wdrst_stat, pcwd_private.io_addr + 1);
-               } else {
-                       /* Re-trigger watchdog by writing to port 0 */
-                       outb_p(0x00, pcwd_private.io_addr);
-               }
-
-               /* Re-set the timer interval */
-               mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
-
-               spin_unlock(&pcwd_private.io_lock);
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-static int pcwd_start(void)
-{
-       int stat_reg;
-
-       pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
-
-       /* Start the timer */
-       mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
-
-       /* Enable the port */
-       if (pcwd_private.revision == PCWD_REVISION_C) {
-               spin_lock(&pcwd_private.io_lock);
-               outb_p(0x00, pcwd_private.io_addr + 3);
-               udelay(ISA_COMMAND_TIMEOUT);
-               stat_reg = inb_p(pcwd_private.io_addr + 2);
-               spin_unlock(&pcwd_private.io_lock);
-               if (stat_reg & WD_WDIS) {
-                       printk(KERN_INFO PFX "Could not start watchdog\n");
-                       return -EIO;
-               }
-       }
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
-
-       return 0;
-}
-
-static int pcwd_stop(void)
-{
-       int stat_reg;
-
-       /* Stop the timer */
-       del_timer(&pcwd_private.timer);
-
-       /*  Disable the board  */
-       if (pcwd_private.revision == PCWD_REVISION_C) {
-               spin_lock(&pcwd_private.io_lock);
-               outb_p(0xA5, pcwd_private.io_addr + 3);
-               udelay(ISA_COMMAND_TIMEOUT);
-               outb_p(0xA5, pcwd_private.io_addr + 3);
-               udelay(ISA_COMMAND_TIMEOUT);
-               stat_reg = inb_p(pcwd_private.io_addr + 2);
-               spin_unlock(&pcwd_private.io_lock);
-               if ((stat_reg & WD_WDIS) == 0) {
-                       printk(KERN_INFO PFX "Could not stop watchdog\n");
-                       return -EIO;
-               }
-       }
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
-
-       return 0;
-}
-
-static int pcwd_keepalive(void)
-{
-       /* user land ping */
-       pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
-
-       return 0;
-}
-
-static int pcwd_set_heartbeat(int t)
-{
-       if ((t < 2) || (t > 7200)) /* arbitrary upper limit */
-               return -EINVAL;
-
-       heartbeat = t;
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
-
-       return 0;
-}
-
-static int pcwd_get_status(int *status)
-{
-       int control_status;
-
-       *status=0;
-       spin_lock(&pcwd_private.io_lock);
-       if (pcwd_private.revision == PCWD_REVISION_A)
-               /* Rev A cards return status information from
-                * the base register, which is used for the
-                * temperature in other cards. */
-               control_status = inb(pcwd_private.io_addr);
-       else {
-               /* Rev C cards return card status in the base
-                * address + 1 register. And use different bits
-                * to indicate a card initiated reset, and an
-                * over-temperature condition. And the reboot
-                * status can be reset. */
-               control_status = inb(pcwd_private.io_addr + 1);
-       }
-       spin_unlock(&pcwd_private.io_lock);
-
-       if (pcwd_private.revision == PCWD_REVISION_A) {
-               if (control_status & WD_WDRST)
-                       *status |= WDIOF_CARDRESET;
-
-               if (control_status & WD_T110) {
-                       *status |= WDIOF_OVERHEAT;
-                       if (temp_panic) {
-                               printk(KERN_INFO PFX "Temperature overheat trip!\n");
-                               kernel_power_off();
-                               /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
-                       }
-               }
-       } else {
-               if (control_status & WD_REVC_WTRP)
-                       *status |= WDIOF_CARDRESET;
-
-               if (control_status & WD_REVC_TTRP) {
-                       *status |= WDIOF_OVERHEAT;
-                       if (temp_panic) {
-                               printk(KERN_INFO PFX "Temperature overheat trip!\n");
-                               kernel_power_off();
-                               /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int pcwd_clear_status(void)
-{
-       int control_status;
-
-       if (pcwd_private.revision == PCWD_REVISION_C) {
-               spin_lock(&pcwd_private.io_lock);
-
-               if (debug >= VERBOSE)
-                       printk(KERN_INFO PFX "clearing watchdog trip status\n");
-
-               control_status = inb_p(pcwd_private.io_addr + 1);
-
-               if (debug >= DEBUG) {
-                       printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
-                       printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                               (control_status & WD_REVC_R2DS));
-               }
-
-               /* clear reset status & Keep Relay 2 disable state as it is */
-               outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
-
-               spin_unlock(&pcwd_private.io_lock);
-       }
-       return 0;
-}
-
-static int pcwd_get_temperature(int *temperature)
-{
-       /* check that port 0 gives temperature info and no command results */
-       if (pcwd_private.command_mode)
-               return -1;
-
-       *temperature = 0;
-       if (!pcwd_private.supports_temp)
-               return -ENODEV;
-
-       /*
-        * Convert celsius to fahrenheit, since this was
-        * the decided 'standard' for this return value.
-        */
-       spin_lock(&pcwd_private.io_lock);
-       *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
-       spin_unlock(&pcwd_private.io_lock);
-
-       if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                       *temperature);
-       }
-
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int pcwd_ioctl(struct inode *inode, struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-       int rv;
-       int status;
-       int temperature;
-       int new_heartbeat;
-       int __user *argp = (int __user *)arg;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_OVERHEAT |
-                                       WDIOF_CARDRESET |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_SETTIMEOUT |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     1,
-               .identity =             "PCWD",
-       };
-
-       switch(cmd) {
-       default:
-               return -ENOTTY;
-
-       case WDIOC_GETSUPPORT:
-               if(copy_to_user(argp, &ident, sizeof(ident)))
-                       return -EFAULT;
-               return 0;
-
-       case WDIOC_GETSTATUS:
-               pcwd_get_status(&status);
-               return put_user(status, argp);
-
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(pcwd_private.boot_status, argp);
-
-       case WDIOC_GETTEMP:
-               if (pcwd_get_temperature(&temperature))
-                       return -EFAULT;
-
-               return put_user(temperature, argp);
-
-       case WDIOC_SETOPTIONS:
-               if (pcwd_private.revision == PCWD_REVISION_C)
-               {
-                       if(copy_from_user(&rv, argp, sizeof(int)))
-                               return -EFAULT;
-
-                       if (rv & WDIOS_DISABLECARD)
-                       {
-                               return pcwd_stop();
-                       }
-
-                       if (rv & WDIOS_ENABLECARD)
-                       {
-                               return pcwd_start();
-                       }
-
-                       if (rv & WDIOS_TEMPPANIC)
-                       {
-                               temp_panic = 1;
-                       }
-               }
-               return -EINVAL;
-
-       case WDIOC_KEEPALIVE:
-               pcwd_keepalive();
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_heartbeat, argp))
-                       return -EFAULT;
-
-               if (pcwd_set_heartbeat(new_heartbeat))
-                       return -EINVAL;
-
-               pcwd_keepalive();
-               /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(heartbeat, argp);
-       }
-
-       return 0;
-}
-
-static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
-                         loff_t *ppos)
-{
-       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, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               pcwd_keepalive();
-       }
-       return len;
-}
-
-static int pcwd_open(struct inode *inode, struct file *file)
-{
-       if (!atomic_dec_and_test(&open_allowed) ) {
-               if (debug >= VERBOSE)
-                       printk(KERN_ERR PFX "Attempt to open already opened device.\n");
-               atomic_inc( &open_allowed );
-               return -EBUSY;
-       }
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate */
-       pcwd_start();
-       pcwd_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int pcwd_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               pcwd_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               pcwd_keepalive();
-       }
-       expect_close = 0;
-       atomic_inc( &open_allowed );
-       return 0;
-}
-
-/*
- *     /dev/temperature handling
- */
-
-static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count,
-                        loff_t *ppos)
-{
-       int temperature;
-
-       if (pcwd_get_temperature(&temperature))
-               return -EFAULT;
-
-       if (copy_to_user(buf, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-static int pcwd_temp_open(struct inode *inode, struct file *file)
-{
-       if (!pcwd_private.supports_temp)
-               return -ENODEV;
-
-       return nonseekable_open(inode, file);
-}
-
-static int pcwd_temp_close(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations pcwd_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = pcwd_write,
-       .ioctl          = pcwd_ioctl,
-       .open           = pcwd_open,
-       .release        = pcwd_close,
-};
-
-static struct miscdevice pcwd_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &pcwd_fops,
-};
-
-static const struct file_operations pcwd_temp_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = pcwd_temp_read,
-       .open           = pcwd_temp_open,
-       .release        = pcwd_temp_close,
-};
-
-static struct miscdevice temp_miscdev = {
-       .minor =        TEMP_MINOR,
-       .name =         "temperature",
-       .fops =         &pcwd_temp_fops,
-};
-
-/*
- *     Init & exit routines
- */
-
-static inline int get_revision(void)
-{
-       int r = PCWD_REVISION_C;
-
-       spin_lock(&pcwd_private.io_lock);
-       /* REV A cards use only 2 io ports; test
-        * presumes a floating bus reads as 0xff. */
-       if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
-           (inb(pcwd_private.io_addr + 3) == 0xFF))
-               r=PCWD_REVISION_A;
-       spin_unlock(&pcwd_private.io_lock);
-
-       return r;
-}
-
-/*
- *  The ISA cards have a heartbeat bit in one of the registers, which
- *  register is card dependent.  The heartbeat bit is monitored, and if
- *  found, is considered proof that a Berkshire card has been found.
- *  The initial rate is once per second at board start up, then twice
- *  per second for normal operation.
- */
-static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
-{
-       int base_addr=pcwd_ioports[id];
-       int port0, last_port0;  /* Reg 0, in case it's REV A */
-       int port1, last_port1;  /* Register 1 for REV C cards */
-       int i;
-       int retval;
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
-                       id);
-
-       if (!request_region (base_addr, 4, "PCWD")) {
-               printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
-               return 0;
-       }
-
-       retval = 0;
-
-       port0 = inb_p(base_addr);       /* For REV A boards */
-       port1 = inb_p(base_addr + 1);   /* For REV C boards */
-       if (port0 != 0xff || port1 != 0xff) {
-               /* Not an 'ff' from a floating bus, so must be a card! */
-               for (i = 0; i < 4; ++i) {
-
-                       msleep(500);
-
-                       last_port0 = port0;
-                       last_port1 = port1;
-
-                       port0 = inb_p(base_addr);
-                       port1 = inb_p(base_addr + 1);
-
-                       /* Has either hearbeat bit changed?  */
-                       if ((port0 ^ last_port0) & WD_HRTBT ||
-                           (port1 ^ last_port1) & WD_REVC_HRBT) {
-                               retval = 1;
-                               break;
-                       }
-               }
-       }
-       release_region (base_addr, 4);
-
-       return retval;
-}
-
-static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
-{
-       int ret;
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
-                       id);
-
-       cards_found++;
-       if (cards_found == 1)
-               printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
-
-       if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
-               return -ENODEV;
-       }
-
-       if (pcwd_ioports[id] == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
-               return -ENODEV;
-       }
-       pcwd_private.io_addr = pcwd_ioports[id];
-
-       spin_lock_init(&pcwd_private.io_lock);
-
-       /* Check card's revision */
-       pcwd_private.revision = get_revision();
-
-       if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       pcwd_private.io_addr);
-               ret=-EIO;
-               goto error_request_region;
-       }
-
-       /* Initial variables */
-       pcwd_private.supports_temp = 0;
-       temp_panic = 0;
-       pcwd_private.boot_status = 0x0000;
-
-       /* get the boot_status */
-       pcwd_get_status(&pcwd_private.boot_status);
-
-       /* clear the "card caused reboot" flag */
-       pcwd_clear_status();
-
-       setup_timer(&pcwd_private.timer, pcwd_timer_ping, 0);
-
-       /*  Disable the board  */
-       pcwd_stop();
-
-       /*  Check whether or not the card supports the temperature device */
-       pcwd_check_temperature_support();
-
-       /* Show info about the card itself */
-       pcwd_show_card_info();
-
-       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
-       if (heartbeat == 0)
-               heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (pcwd_set_heartbeat(heartbeat)) {
-               pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
-                       WATCHDOG_HEARTBEAT);
-       }
-
-       if (pcwd_private.supports_temp) {
-               ret = misc_register(&temp_miscdev);
-               if (ret) {
-                       printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                               TEMP_MINOR, ret);
-                       goto error_misc_register_temp;
-               }
-       }
-
-       ret = misc_register(&pcwd_miscdev);
-       if (ret) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto error_misc_register_watchdog;
-       }
-
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-
-       return 0;
-
-error_misc_register_watchdog:
-       if (pcwd_private.supports_temp)
-               misc_deregister(&temp_miscdev);
-error_misc_register_temp:
-       release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
-error_request_region:
-       pcwd_private.io_addr = 0x0000;
-       cards_found--;
-       return ret;
-}
-
-static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
-{
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
-                       id);
-
-       if (!pcwd_private.io_addr)
-               return 1;
-
-       /*  Disable the board  */
-       if (!nowayout)
-               pcwd_stop();
-
-       /* Deregister */
-       misc_deregister(&pcwd_miscdev);
-       if (pcwd_private.supports_temp)
-               misc_deregister(&temp_miscdev);
-       release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
-       pcwd_private.io_addr = 0x0000;
-       cards_found--;
-
-       return 0;
-}
-
-static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
-{
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n",
-                       id);
-
-       pcwd_stop();
-}
-
-static struct isa_driver pcwd_isa_driver = {
-       .match          = pcwd_isa_match,
-       .probe          = pcwd_isa_probe,
-       .remove         = __devexit_p(pcwd_isa_remove),
-       .shutdown       = pcwd_isa_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = WATCHDOG_NAME,
-       },
-};
-
-static int __init pcwd_init_module(void)
-{
-       return isa_register_driver(&pcwd_isa_driver, PCWD_ISA_NR_CARDS);
-}
-
-static void __exit pcwd_cleanup_module(void)
-{
-       isa_unregister_driver(&pcwd_isa_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(pcwd_init_module);
-module_exit(pcwd_cleanup_module);
-
-MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>, Wim Van Sebroeck <wim@iguana.be>");
-MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver");
-MODULE_VERSION(WATCHDOG_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
deleted file mode 100644 (file)
index 61a89e9..0000000
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- *     Berkshire PCI-PC Watchdog Card Driver
- *
- *     (c) Copyright 2003-2007 Wim Van Sebroeck <wim@iguana.be>.
- *
- *     Based on source code of the following authors:
- *       Ken Hollis <kenji@bitgate.com>,
- *       Lindsay Harris <lindsay@bluegum.com>,
- *       Alan Cox <alan@redhat.com>,
- *       Matt Domsch <Matt_Domsch@dell.com>,
- *       Rob Radez <rob@osinvestor.com>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
- *     provide warranty for any of this software. This material is
- *     provided "AS-IS" and at no charge.
- */
-
-/*
- *     A bells and whistles driver is available from:
- *     http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/
- *
- *     More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
- */
-
-/*
- *     Includes, defines, variables, module parameters, ...
- */
-
-#include <linux/module.h>      /* For module specific items */
-#include <linux/moduleparam.h> /* For new moduleparam's */
-#include <linux/types.h>       /* For standard types (like size_t) */
-#include <linux/errno.h>       /* For the -ENODEV/... values */
-#include <linux/kernel.h>      /* For printk/panic/... */
-#include <linux/delay.h>       /* For mdelay function */
-#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
-#include <linux/watchdog.h>    /* For the watchdog specific items */
-#include <linux/notifier.h>    /* For notifier support */
-#include <linux/reboot.h>      /* For reboot_notifier stuff */
-#include <linux/init.h>                /* For __init/__exit/... */
-#include <linux/fs.h>          /* For file operations */
-#include <linux/pci.h>         /* For pci functions */
-#include <linux/ioport.h>      /* For io-port access */
-#include <linux/spinlock.h>    /* For spin_lock/spin_unlock/... */
-
-#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
-#include <asm/io.h>            /* For inb/outb/... */
-
-/* Module and version information */
-#define WATCHDOG_VERSION "1.03"
-#define WATCHDOG_DATE "21 Jan 2007"
-#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
-#define WATCHDOG_NAME "pcwd_pci"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
-
-/* Stuff for the PCI ID's  */
-#ifndef PCI_VENDOR_ID_QUICKLOGIC
-#define PCI_VENDOR_ID_QUICKLOGIC    0x11e3
-#endif
-
-#ifndef PCI_DEVICE_ID_WATCHDOG_PCIPCWD
-#define PCI_DEVICE_ID_WATCHDOG_PCIPCWD 0x5030
-#endif
-
-/*
- * These are the defines that describe the control status bits for the
- * PCI-PC Watchdog card.
- */
-/* Port 1 : Control Status #1 */
-#define WD_PCI_WTRP            0x01    /* Watchdog Trip status */
-#define WD_PCI_HRBT            0x02    /* Watchdog Heartbeat */
-#define WD_PCI_TTRP            0x04    /* Temperature Trip status */
-#define WD_PCI_RL2A            0x08    /* Relay 2 Active */
-#define WD_PCI_RL1A            0x10    /* Relay 1 Active */
-#define WD_PCI_R2DS            0x40    /* Relay 2 Disable Temperature-trip/reset */
-#define WD_PCI_RLY2            0x80    /* Activate Relay 2 on the board */
-/* Port 2 : Control Status #2 */
-#define WD_PCI_WDIS            0x10    /* Watchdog Disable */
-#define WD_PCI_ENTP            0x20    /* Enable Temperature Trip Reset */
-#define WD_PCI_WRSP            0x40    /* Watchdog wrote response */
-#define WD_PCI_PCMD            0x80    /* PC has sent command */
-
-/* according to documentation max. time to process a command for the pci
- * watchdog card is 100 ms, so we give it 150 ms to do it's job */
-#define PCI_COMMAND_TIMEOUT    150
-
-/* Watchdog's internal commands */
-#define CMD_GET_STATUS                         0x04
-#define CMD_GET_FIRMWARE_VERSION               0x08
-#define CMD_READ_WATCHDOG_TIMEOUT              0x18
-#define CMD_WRITE_WATCHDOG_TIMEOUT             0x19
-#define CMD_GET_CLEAR_RESET_COUNT              0x84
-
-/* Watchdog's Dip Switch heartbeat values */
-static const int heartbeat_tbl [] = {
-       5,      /* OFF-OFF-OFF  =  5 Sec  */
-       10,     /* OFF-OFF-ON   = 10 Sec  */
-       30,     /* OFF-ON-OFF   = 30 Sec  */
-       60,     /* OFF-ON-ON    =  1 Min  */
-       300,    /* ON-OFF-OFF   =  5 Min  */
-       600,    /* ON-OFF-ON    = 10 Min  */
-       1800,   /* ON-ON-OFF    = 30 Min  */
-       3600,   /* ON-ON-ON     =  1 hour */
-};
-
-/* We can only use 1 card due to the /dev/watchdog restriction */
-static int cards_found;
-
-/* internal variables */
-static int temp_panic;
-static unsigned long is_active;
-static char expect_release;
-static struct {                                /* this is private data for each PCI-PC watchdog card */
-       int supports_temp;              /* Wether or not the card has a temperature device */
-       int boot_status;                /* The card's boot status */
-       unsigned long io_addr;          /* The cards I/O address */
-       spinlock_t io_lock;             /* the lock for io operations */
-       struct pci_dev *pdev;           /* the PCI-device */
-} pcipcwd_private;
-
-/* module parameters */
-#define QUIET  0       /* Default */
-#define VERBOSE        1       /* Verbose */
-#define DEBUG  2       /* print fancy stuff too */
-static int debug = QUIET;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
-
-#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
-static int heartbeat = WATCHDOG_HEARTBEAT;
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-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) ")");
-
-/*
- *     Internal functions
- */
-
-static int send_command(int cmd, int *msb, int *lsb)
-{
-       int got_response, count;
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n",
-               cmd, *msb, *lsb);
-
-       spin_lock(&pcipcwd_private.io_lock);
-       /* If a command requires data it should be written first.
-        * Data for commands with 8 bits of data should be written to port 4.
-        * Commands with 16 bits of data, should be written as LSB to port 4
-        * and MSB to port 5.
-        * After the required data has been written then write the command to
-        * port 6. */
-       outb_p(*lsb, pcipcwd_private.io_addr + 4);
-       outb_p(*msb, pcipcwd_private.io_addr + 5);
-       outb_p(cmd, pcipcwd_private.io_addr + 6);
-
-       /* wait till the pci card processed the command, signaled by
-        * the WRSP bit in port 2 and give it a max. timeout of
-        * PCI_COMMAND_TIMEOUT to process */
-       got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
-       for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) {
-               mdelay(1);
-               got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
-       }
-
-       if (debug >= DEBUG) {
-               if (got_response) {
-                       printk(KERN_DEBUG PFX "time to process command was: %d ms\n",
-                               count);
-               } else {
-                       printk(KERN_DEBUG PFX "card did not respond on command!\n");
-               }
-       }
-
-       if (got_response) {
-               /* read back response */
-               *lsb = inb_p(pcipcwd_private.io_addr + 4);
-               *msb = inb_p(pcipcwd_private.io_addr + 5);
-
-               /* clear WRSP bit */
-               inb_p(pcipcwd_private.io_addr + 6);
-
-               if (debug >= DEBUG)
-                       printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
-                               cmd, *msb, *lsb);
-       }
-
-       spin_unlock(&pcipcwd_private.io_lock);
-
-       return got_response;
-}
-
-static inline void pcipcwd_check_temperature_support(void)
-{
-       if (inb_p(pcipcwd_private.io_addr) != 0xF0)
-               pcipcwd_private.supports_temp = 1;
-}
-
-static int pcipcwd_get_option_switches(void)
-{
-       int option_switches;
-
-       option_switches = inb_p(pcipcwd_private.io_addr + 3);
-       return option_switches;
-}
-
-static void pcipcwd_show_card_info(void)
-{
-       int got_fw_rev, fw_rev_major, fw_rev_minor;
-       char fw_ver_str[20];            /* The cards firmware version */
-       int option_switches;
-
-       got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
-       if (got_fw_rev) {
-               sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
-       } else {
-               sprintf(fw_ver_str, "<card no answer>");
-       }
-
-       /* Get switch settings */
-       option_switches = pcipcwd_get_option_switches();
-
-       printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n",
-               (int) pcipcwd_private.io_addr, fw_ver_str,
-               (pcipcwd_private.supports_temp ? "with" : "without"));
-
-       printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
-               option_switches,
-               ((option_switches & 0x10) ? "ON" : "OFF"),
-               ((option_switches & 0x08) ? "ON" : "OFF"));
-
-       if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n");
-
-       if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
-               printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
-
-       if (pcipcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
-}
-
-static int pcipcwd_start(void)
-{
-       int stat_reg;
-
-       spin_lock(&pcipcwd_private.io_lock);
-       outb_p(0x00, pcipcwd_private.io_addr + 3);
-       udelay(1000);
-
-       stat_reg = inb_p(pcipcwd_private.io_addr + 2);
-       spin_unlock(&pcipcwd_private.io_lock);
-
-       if (stat_reg & WD_PCI_WDIS) {
-               printk(KERN_ERR PFX "Card timer not enabled\n");
-               return -1;
-       }
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
-
-       return 0;
-}
-
-static int pcipcwd_stop(void)
-{
-       int stat_reg;
-
-       spin_lock(&pcipcwd_private.io_lock);
-       outb_p(0xA5, pcipcwd_private.io_addr + 3);
-       udelay(1000);
-
-       outb_p(0xA5, pcipcwd_private.io_addr + 3);
-       udelay(1000);
-
-       stat_reg = inb_p(pcipcwd_private.io_addr + 2);
-       spin_unlock(&pcipcwd_private.io_lock);
-
-       if (!(stat_reg & WD_PCI_WDIS)) {
-               printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
-               return -1;
-       }
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
-
-       return 0;
-}
-
-static int pcipcwd_keepalive(void)
-{
-       /* Re-trigger watchdog by writing to port 0 */
-       spin_lock(&pcipcwd_private.io_lock);
-       outb_p(0x42, pcipcwd_private.io_addr);  /* send out any data */
-       spin_unlock(&pcipcwd_private.io_lock);
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
-
-       return 0;
-}
-
-static int pcipcwd_set_heartbeat(int t)
-{
-       int t_msb = t / 256;
-       int t_lsb = t % 256;
-
-       if ((t < 0x0001) || (t > 0xFFFF))
-               return -EINVAL;
-
-       /* Write new heartbeat to watchdog */
-       send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb);
-
-       heartbeat = t;
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
-
-       return 0;
-}
-
-static int pcipcwd_get_status(int *status)
-{
-       int control_status;
-
-       *status=0;
-       control_status = inb_p(pcipcwd_private.io_addr + 1);
-       if (control_status & WD_PCI_WTRP)
-               *status |= WDIOF_CARDRESET;
-       if (control_status & WD_PCI_TTRP) {
-               *status |= WDIOF_OVERHEAT;
-               if (temp_panic)
-                       panic(PFX "Temperature overheat trip!\n");
-       }
-
-       if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n",
-                      control_status);
-
-       return 0;
-}
-
-static int pcipcwd_clear_status(void)
-{
-       int control_status;
-       int msb;
-       int reset_counter;
-
-       if (debug >= VERBOSE)
-               printk(KERN_INFO PFX "clearing watchdog trip status & LED\n");
-
-       control_status = inb_p(pcipcwd_private.io_addr + 1);
-
-       if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
-               printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                      (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
-       }
-
-       /* clear trip status & LED and keep mode of relay 2 */
-       outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1);
-
-       /* clear reset counter */
-       msb=0;
-       reset_counter=0xff;
-       send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
-
-       if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "reset count was: 0x%02x\n",
-                      reset_counter);
-       }
-
-       return 0;
-}
-
-static int pcipcwd_get_temperature(int *temperature)
-{
-       *temperature = 0;
-       if (!pcipcwd_private.supports_temp)
-               return -ENODEV;
-
-       spin_lock(&pcipcwd_private.io_lock);
-       *temperature = inb_p(pcipcwd_private.io_addr);
-       spin_unlock(&pcipcwd_private.io_lock);
-
-       /*
-        * Convert celsius to fahrenheit, since this was
-        * the decided 'standard' for this return value.
-        */
-       *temperature = (*temperature * 9 / 5) + 32;
-
-       if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                      *temperature);
-       }
-
-       return 0;
-}
-
-static int pcipcwd_get_timeleft(int *time_left)
-{
-       int msb;
-       int lsb;
-
-       /* Read the time that's left before rebooting */
-       /* Note: if the board is not yet armed then we will read 0xFFFF */
-       send_command(CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
-
-       *time_left = (msb << 8) + lsb;
-
-       if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Time left before next reboot: %d\n",
-                      *time_left);
-
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t pcipcwd_write(struct file *file, const char __user *data,
-                            size_t len, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       expect_release = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if(get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_release = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               pcipcwd_keepalive();
-       }
-       return len;
-}
-
-static int pcipcwd_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_OVERHEAT |
-                                       WDIOF_CARDRESET |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_SETTIMEOUT |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     1,
-               .identity =             WATCHDOG_DRIVER_NAME,
-       };
-
-       switch (cmd) {
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &ident,
-                               sizeof (ident)) ? -EFAULT : 0;
-
-               case WDIOC_GETSTATUS:
-               {
-                       int status;
-
-                       pcipcwd_get_status(&status);
-
-                       return put_user(status, p);
-               }
-
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(pcipcwd_private.boot_status, p);
-
-               case WDIOC_GETTEMP:
-               {
-                       int temperature;
-
-                       if (pcipcwd_get_temperature(&temperature))
-                               return -EFAULT;
-
-                       return put_user(temperature, p);
-               }
-
-               case WDIOC_KEEPALIVE:
-                       pcipcwd_keepalive();
-                       return 0;
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if (get_user (new_options, p))
-                               return -EFAULT;
-
-                       if (new_options & WDIOS_DISABLECARD) {
-                               if (pcipcwd_stop())
-                                       return -EIO;
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_ENABLECARD) {
-                               if (pcipcwd_start())
-                                       return -EIO;
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_TEMPPANIC) {
-                               temp_panic = 1;
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_heartbeat;
-
-                       if (get_user(new_heartbeat, p))
-                               return -EFAULT;
-
-                       if (pcipcwd_set_heartbeat(new_heartbeat))
-                           return -EINVAL;
-
-                       pcipcwd_keepalive();
-                       /* Fall */
-               }
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, p);
-
-               case WDIOC_GETTIMELEFT:
-               {
-                       int time_left;
-
-                       if (pcipcwd_get_timeleft(&time_left))
-                               return -EFAULT;
-
-                       return put_user(time_left, p);
-               }
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-static int pcipcwd_open(struct inode *inode, struct file *file)
-{
-       /* /dev/watchdog can only be opened once */
-       if (test_and_set_bit(0, &is_active)) {
-               if (debug >= VERBOSE)
-                       printk(KERN_ERR PFX "Attempt to open already opened device.\n");
-               return -EBUSY;
-       }
-
-       /* Activate */
-       pcipcwd_start();
-       pcipcwd_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int pcipcwd_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        */
-       if (expect_release == 42) {
-               pcipcwd_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               pcipcwd_keepalive();
-       }
-       expect_release = 0;
-       clear_bit(0, &is_active);
-       return 0;
-}
-
-/*
- *     /dev/temperature handling
- */
-
-static ssize_t pcipcwd_temp_read(struct file *file, char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       int temperature;
-
-       if (pcipcwd_get_temperature(&temperature))
-               return -EFAULT;
-
-       if (copy_to_user (data, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-static int pcipcwd_temp_open(struct inode *inode, struct file *file)
-{
-       if (!pcipcwd_private.supports_temp)
-               return -ENODEV;
-
-       return nonseekable_open(inode, file);
-}
-
-static int pcipcwd_temp_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-/*
- *     Notify system
- */
-
-static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the WDT off */
-               pcipcwd_stop();
-       }
-
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations pcipcwd_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .write =        pcipcwd_write,
-       .ioctl =        pcipcwd_ioctl,
-       .open =         pcipcwd_open,
-       .release =      pcipcwd_release,
-};
-
-static struct miscdevice pcipcwd_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &pcipcwd_fops,
-};
-
-static const struct file_operations pcipcwd_temp_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .read =         pcipcwd_temp_read,
-       .open =         pcipcwd_temp_open,
-       .release =      pcipcwd_temp_release,
-};
-
-static struct miscdevice pcipcwd_temp_miscdev = {
-       .minor =        TEMP_MINOR,
-       .name =         "temperature",
-       .fops =         &pcipcwd_temp_fops,
-};
-
-static struct notifier_block pcipcwd_notifier = {
-       .notifier_call =        pcipcwd_notify_sys,
-};
-
-/*
- *     Init & exit routines
- */
-
-static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
-{
-       int ret = -EIO;
-
-       cards_found++;
-       if (cards_found == 1)
-               printk(KERN_INFO PFX DRIVER_VERSION);
-
-       if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
-               return -ENODEV;
-       }
-
-       if (pci_enable_device(pdev)) {
-               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
-               return -ENODEV;
-       }
-
-       if (pci_resource_start(pdev, 0) == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
-               ret = -ENODEV;
-               goto err_out_disable_device;
-       }
-
-       pcipcwd_private.pdev = pdev;
-       pcipcwd_private.io_addr = pci_resource_start(pdev, 0);
-
-       if (pci_request_regions(pdev, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       (int) pcipcwd_private.io_addr);
-               ret = -EIO;
-               goto err_out_disable_device;
-       }
-
-       /* get the boot_status */
-       pcipcwd_get_status(&pcipcwd_private.boot_status);
-
-       /* clear the "card caused reboot" flag */
-       pcipcwd_clear_status();
-
-       /* disable card */
-       pcipcwd_stop();
-
-       /* Check whether or not the card supports the temperature device */
-       pcipcwd_check_temperature_support();
-
-       /* Show info about the card itself */
-       pcipcwd_show_card_info();
-
-       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
-       if (heartbeat == 0)
-               heartbeat = heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)];
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (pcipcwd_set_heartbeat(heartbeat)) {
-               pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
-                       WATCHDOG_HEARTBEAT);
-       }
-
-       ret = register_reboot_notifier(&pcipcwd_notifier);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto err_out_release_region;
-       }
-
-       if (pcipcwd_private.supports_temp) {
-               ret = misc_register(&pcipcwd_temp_miscdev);
-               if (ret != 0) {
-                       printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                               TEMP_MINOR, ret);
-                       goto err_out_unregister_reboot;
-               }
-       }
-
-       ret = misc_register(&pcipcwd_miscdev);
-       if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto err_out_misc_deregister;
-       }
-
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-
-       return 0;
-
-err_out_misc_deregister:
-       if (pcipcwd_private.supports_temp)
-               misc_deregister(&pcipcwd_temp_miscdev);
-err_out_unregister_reboot:
-       unregister_reboot_notifier(&pcipcwd_notifier);
-err_out_release_region:
-       pci_release_regions(pdev);
-err_out_disable_device:
-       pci_disable_device(pdev);
-       return ret;
-}
-
-static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
-{
-       /* Stop the timer before we leave */
-       if (!nowayout)
-               pcipcwd_stop();
-
-       /* Deregister */
-       misc_deregister(&pcipcwd_miscdev);
-       if (pcipcwd_private.supports_temp)
-               misc_deregister(&pcipcwd_temp_miscdev);
-       unregister_reboot_notifier(&pcipcwd_notifier);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       cards_found--;
-}
-
-static struct pci_device_id pcipcwd_pci_tbl[] = {
-       { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       { 0 },                  /* End of list */
-};
-MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
-
-static struct pci_driver pcipcwd_driver = {
-       .name           = WATCHDOG_NAME,
-       .id_table       = pcipcwd_pci_tbl,
-       .probe          = pcipcwd_card_init,
-       .remove         = __devexit_p(pcipcwd_card_exit),
-};
-
-static int __init pcipcwd_init_module(void)
-{
-       spin_lock_init(&pcipcwd_private.io_lock);
-
-       return pci_register_driver(&pcipcwd_driver);
-}
-
-static void __exit pcipcwd_cleanup_module(void)
-{
-       pci_unregister_driver(&pcipcwd_driver);
-
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
-}
-
-module_init(pcipcwd_init_module);
-module_exit(pcipcwd_cleanup_module);
-
-MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
-MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
deleted file mode 100644 (file)
index 0f3fd6c..0000000
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- *     Berkshire USB-PC Watchdog Card Driver
- *
- *     (c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
- *
- *     Based on source code of the following authors:
- *       Ken Hollis <kenji@bitgate.com>,
- *       Alan Cox <alan@redhat.com>,
- *       Matt Domsch <Matt_Domsch@dell.com>,
- *       Rob Radez <rob@osinvestor.com>,
- *       Greg Kroah-Hartman <greg@kroah.com>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
- *     provide warranty for any of this software. This material is
- *     provided "AS-IS" and at no charge.
- *
- *     Thanks also to Simon Machell at Berkshire Products Inc. for
- *     providing the test hardware. More info is available at
- *     http://www.berkprod.com/ or http://www.pcwatchdog.com/
- */
-
-#include <linux/module.h>      /* For module specific items */
-#include <linux/moduleparam.h> /* For new moduleparam's */
-#include <linux/types.h>       /* For standard types (like size_t) */
-#include <linux/errno.h>       /* For the -ENODEV/... values */
-#include <linux/kernel.h>      /* For printk/panic/... */
-#include <linux/delay.h>       /* For mdelay function */
-#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
-#include <linux/watchdog.h>    /* For the watchdog specific items */
-#include <linux/notifier.h>    /* For notifier support */
-#include <linux/reboot.h>      /* For reboot_notifier stuff */
-#include <linux/init.h>                /* For __init/__exit/... */
-#include <linux/fs.h>          /* For file operations */
-#include <linux/usb.h>         /* For USB functions */
-#include <linux/slab.h>                /* For kmalloc, ... */
-#include <linux/mutex.h>       /* For mutex locking */
-#include <linux/hid.h>         /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
-
-#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
-
-
-#ifdef CONFIG_USB_DEBUG
-       static int debug = 1;
-#else
-       static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0)
-
-
-/* Module and Version Information */
-#define DRIVER_VERSION "1.02"
-#define DRIVER_DATE "21 Jan 2007"
-#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
-#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
-#define DRIVER_LICENSE "GPL"
-#define DRIVER_NAME "pcwd_usb"
-#define PFX DRIVER_NAME ": "
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-
-/* Module Parameters */
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
-static int heartbeat = WATCHDOG_HEARTBEAT;
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-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) ")");
-
-/* The vendor and product id's for the USB-PC Watchdog card */
-#define USB_PCWD_VENDOR_ID     0x0c98
-#define USB_PCWD_PRODUCT_ID    0x1140
-
-/* table of devices that work with this driver */
-static struct usb_device_id usb_pcwd_table [] = {
-       { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
-       { }                                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
-
-/* according to documentation max. time to process a command for the USB
- * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
-#define USB_COMMAND_TIMEOUT    250
-
-/* Watchdog's internal commands */
-#define CMD_READ_TEMP                  0x02    /* Read Temperature; Re-trigger Watchdog */
-#define CMD_TRIGGER                    CMD_READ_TEMP
-#define CMD_GET_STATUS                 0x04    /* Get Status Information */
-#define CMD_GET_FIRMWARE_VERSION       0x08    /* Get Firmware Version */
-#define CMD_GET_DIP_SWITCH_SETTINGS    0x0c    /* Get Dip Switch Settings */
-#define CMD_READ_WATCHDOG_TIMEOUT      0x18    /* Read Current Watchdog Time */
-#define CMD_WRITE_WATCHDOG_TIMEOUT     0x19    /* Write Current Watchdog Time */
-#define CMD_ENABLE_WATCHDOG            0x30    /* Enable / Disable Watchdog */
-#define CMD_DISABLE_WATCHDOG           CMD_ENABLE_WATCHDOG
-
-/* Watchdog's Dip Switch heartbeat values */
-static const int heartbeat_tbl [] = {
-       5,      /* OFF-OFF-OFF  =  5 Sec  */
-       10,     /* OFF-OFF-ON   = 10 Sec  */
-       30,     /* OFF-ON-OFF   = 30 Sec  */
-       60,     /* OFF-ON-ON    =  1 Min  */
-       300,    /* ON-OFF-OFF   =  5 Min  */
-       600,    /* ON-OFF-ON    = 10 Min  */
-       1800,   /* ON-ON-OFF    = 30 Min  */
-       3600,   /* ON-ON-ON     =  1 hour */
-};
-
-/* We can only use 1 card due to the /dev/watchdog restriction */
-static int cards_found;
-
-/* some internal variables */
-static unsigned long is_active;
-static char expect_release;
-
-/* Structure to hold all of our device specific stuff */
-struct usb_pcwd_private {
-       struct usb_device *     udev;                   /* save off the usb device pointer */
-       struct usb_interface *  interface;              /* the interface for this device */
-
-       unsigned int            interface_number;       /* the interface number used for cmd's */
-
-       unsigned char *         intr_buffer;            /* the buffer to intr data */
-       dma_addr_t              intr_dma;               /* the dma address for the intr buffer */
-       size_t                  intr_size;              /* the size of the intr buffer */
-       struct urb *            intr_urb;               /* the urb used for the intr pipe */
-
-       unsigned char           cmd_command;            /* The command that is reported back */
-       unsigned char           cmd_data_msb;           /* The data MSB that is reported back */
-       unsigned char           cmd_data_lsb;           /* The data LSB that is reported back */
-       atomic_t                cmd_received;           /* true if we received a report after a command */
-
-       int                     exists;                 /* Wether or not the device exists */
-       struct mutex            mtx;                    /* locks this structure */
-};
-static struct usb_pcwd_private *usb_pcwd_device;
-
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
-/* local function prototypes */
-static int usb_pcwd_probe      (struct usb_interface *interface, const struct usb_device_id *id);
-static void usb_pcwd_disconnect        (struct usb_interface *interface);
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver usb_pcwd_driver = {
-       .name =         DRIVER_NAME,
-       .probe =        usb_pcwd_probe,
-       .disconnect =   usb_pcwd_disconnect,
-       .id_table =     usb_pcwd_table,
-};
-
-
-static void usb_pcwd_intr_done(struct urb *urb)
-{
-       struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context;
-       unsigned char *data = usb_pcwd->intr_buffer;
-       int retval;
-
-       switch (urb->status) {
-       case 0:                 /* success */
-               break;
-       case -ECONNRESET:       /* unlink */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       /* -EPIPE:  should clear the halt */
-       default:                /* error */
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto resubmit;
-       }
-
-       dbg("received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
-               data[0], data[1], data[2]);
-
-       usb_pcwd->cmd_command  = data[0];
-       usb_pcwd->cmd_data_msb = data[1];
-       usb_pcwd->cmd_data_lsb = data[2];
-
-       /* notify anyone waiting that the cmd has finished */
-       atomic_set (&usb_pcwd->cmd_received, 1);
-
-resubmit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n",
-                       retval);
-}
-
-static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd,
-       unsigned char *msb, unsigned char *lsb)
-{
-       int got_response, count;
-       unsigned char buf[6];
-
-       /* We will not send any commands if the USB PCWD device does not exist */
-       if ((!usb_pcwd) || (!usb_pcwd->exists))
-               return -1;
-
-       /* The USB PC Watchdog uses a 6 byte report format. The board currently uses
-        * only 3 of the six bytes of the report. */
-       buf[0] = cmd;                   /* Byte 0 = CMD */
-       buf[1] = *msb;                  /* Byte 1 = Data MSB */
-       buf[2] = *lsb;                  /* Byte 2 = Data LSB */
-       buf[3] = buf[4] = buf[5] = 0;   /* All other bytes not used */
-
-       dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
-               buf[0], buf[1], buf[2]);
-
-       atomic_set (&usb_pcwd->cmd_received, 0);
-
-       if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
-                       HID_REQ_SET_REPORT, HID_DT_REPORT,
-                       0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
-                       USB_COMMAND_TIMEOUT) != sizeof(buf)) {
-               dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
-       }
-       /* wait till the usb card processed the command,
-        * with a max. timeout of USB_COMMAND_TIMEOUT */
-       got_response = 0;
-       for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) {
-               mdelay(1);
-               if (atomic_read (&usb_pcwd->cmd_received))
-                       got_response = 1;
-       }
-
-       if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
-               /* read back response */
-               *msb = usb_pcwd->cmd_data_msb;
-               *lsb = usb_pcwd->cmd_data_lsb;
-       }
-
-       return got_response;
-}
-
-static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
-{
-       unsigned char msb = 0x00;
-       unsigned char lsb = 0x00;
-       int retval;
-
-       /* Enable Watchdog */
-       retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb);
-
-       if ((retval == 0) || (lsb == 0)) {
-               printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
-{
-       unsigned char msb = 0xA5;
-       unsigned char lsb = 0xC3;
-       int retval;
-
-       /* Disable Watchdog */
-       retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb);
-
-       if ((retval == 0) || (lsb != 0)) {
-               printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
-{
-       unsigned char dummy;
-
-       /* Re-trigger Watchdog */
-       usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
-
-       return 0;
-}
-
-static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
-{
-       unsigned char msb = t / 256;
-       unsigned char lsb = t % 256;
-
-       if ((t < 0x0001) || (t > 0xFFFF))
-               return -EINVAL;
-
-       /* Write new heartbeat to watchdog */
-       usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
-
-       heartbeat = t;
-       return 0;
-}
-
-static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature)
-{
-       unsigned char msb, lsb;
-
-       usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
-
-       /*
-        * Convert celsius to fahrenheit, since this was
-        * the decided 'standard' for this return value.
-        */
-       *temperature = (lsb * 9 / 5) + 32;
-
-       return 0;
-}
-
-static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left)
-{
-       unsigned char msb, lsb;
-
-       /* Read the time that's left before rebooting */
-       /* Note: if the board is not yet armed then we will read 0xFFFF */
-       usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
-
-       *time_left = (msb << 8) + lsb;
-
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
-                             size_t len, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       expect_release = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if(get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_release = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               usb_pcwd_keepalive(usb_pcwd_device);
-       }
-       return len;
-}
-
-static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_KEEPALIVEPING |
-                                       WDIOF_SETTIMEOUT |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     1,
-               .identity =             DRIVER_NAME,
-       };
-
-       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_GETTEMP:
-               {
-                       int temperature;
-
-                       if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
-                               return -EFAULT;
-
-                       return put_user(temperature, p);
-               }
-
-               case WDIOC_KEEPALIVE:
-                       usb_pcwd_keepalive(usb_pcwd_device);
-                       return 0;
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if (get_user (new_options, p))
-                               return -EFAULT;
-
-                       if (new_options & WDIOS_DISABLECARD) {
-                               usb_pcwd_stop(usb_pcwd_device);
-                               retval = 0;
-                       }
-
-                       if (new_options & WDIOS_ENABLECARD) {
-                               usb_pcwd_start(usb_pcwd_device);
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_heartbeat;
-
-                       if (get_user(new_heartbeat, p))
-                               return -EFAULT;
-
-                       if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
-                           return -EINVAL;
-
-                       usb_pcwd_keepalive(usb_pcwd_device);
-                       /* Fall */
-               }
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, p);
-
-               case WDIOC_GETTIMELEFT:
-               {
-                       int time_left;
-
-                       if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
-                               return -EFAULT;
-
-                       return put_user(time_left, p);
-               }
-
-               default:
-                       return -ENOTTY;
-       }
-}
-
-static int usb_pcwd_open(struct inode *inode, struct file *file)
-{
-       /* /dev/watchdog can only be opened once */
-       if (test_and_set_bit(0, &is_active))
-               return -EBUSY;
-
-       /* Activate */
-       usb_pcwd_start(usb_pcwd_device);
-       usb_pcwd_keepalive(usb_pcwd_device);
-       return nonseekable_open(inode, file);
-}
-
-static int usb_pcwd_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        */
-       if (expect_release == 42) {
-               usb_pcwd_stop(usb_pcwd_device);
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               usb_pcwd_keepalive(usb_pcwd_device);
-       }
-       expect_release = 0;
-       clear_bit(0, &is_active);
-       return 0;
-}
-
-/*
- *     /dev/temperature handling
- */
-
-static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       int temperature;
-
-       if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
-               return -EFAULT;
-
-       if (copy_to_user(data, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
-{
-       return nonseekable_open(inode, file);
-}
-
-static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-/*
- *     Notify system
- */
-
-static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the WDT off */
-               usb_pcwd_stop(usb_pcwd_device);
-       }
-
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations usb_pcwd_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .write =        usb_pcwd_write,
-       .ioctl =        usb_pcwd_ioctl,
-       .open =         usb_pcwd_open,
-       .release =      usb_pcwd_release,
-};
-
-static struct miscdevice usb_pcwd_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &usb_pcwd_fops,
-};
-
-static const struct file_operations usb_pcwd_temperature_fops = {
-       .owner =        THIS_MODULE,
-       .llseek =       no_llseek,
-       .read =         usb_pcwd_temperature_read,
-       .open =         usb_pcwd_temperature_open,
-       .release =      usb_pcwd_temperature_release,
-};
-
-static struct miscdevice usb_pcwd_temperature_miscdev = {
-       .minor =        TEMP_MINOR,
-       .name =         "temperature",
-       .fops =         &usb_pcwd_temperature_fops,
-};
-
-static struct notifier_block usb_pcwd_notifier = {
-       .notifier_call =        usb_pcwd_notify_sys,
-};
-
-/**
- *     usb_pcwd_delete
- */
-static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd)
-{
-       usb_free_urb(usb_pcwd->intr_urb);
-       if (usb_pcwd->intr_buffer != NULL)
-               usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
-                               usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
-       kfree (usb_pcwd);
-}
-
-/**
- *     usb_pcwd_probe
- *
- *     Called by the usb core when a new device is connected that it thinks
- *     this driver might be interested in.
- */
-static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(interface);
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_pcwd_private *usb_pcwd = NULL;
-       int pipe, maxp;
-       int retval = -ENOMEM;
-       int got_fw_rev;
-       unsigned char fw_rev_major, fw_rev_minor;
-       char fw_ver_str[20];
-       unsigned char option_switches, dummy;
-
-       cards_found++;
-       if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
-               return -ENODEV;
-       }
-
-       /* get the active interface descriptor */
-       iface_desc = interface->cur_altsetting;
-
-       /* check out that we have a HID device */
-       if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
-               printk(KERN_ERR PFX "The device isn't a Human Interface Device\n");
-               return -ENODEV;
-       }
-
-       /* check out the endpoint: it has to be Interrupt & IN */
-       endpoint = &iface_desc->endpoint[0].desc;
-
-       if (!((endpoint->bEndpointAddress & USB_DIR_IN) &&
-            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                               == USB_ENDPOINT_XFER_INT))) {
-               /* we didn't find a Interrupt endpoint with direction IN */
-               printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");
-               return -ENODEV;
-       }
-
-       /* get a handle to the interrupt data pipe */
-       pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
-       maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-
-       /* allocate memory for our device and initialize it */
-       usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);
-       if (usb_pcwd == NULL) {
-               printk(KERN_ERR PFX "Out of memory\n");
-               goto error;
-       }
-
-       usb_pcwd_device = usb_pcwd;
-
-       mutex_init(&usb_pcwd->mtx);
-       usb_pcwd->udev = udev;
-       usb_pcwd->interface = interface;
-       usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
-       usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
-
-       /* set up the memory buffer's */
-       if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) {
-               printk(KERN_ERR PFX "Out of memory\n");
-               goto error;
-       }
-
-       /* allocate the urb's */
-       usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!usb_pcwd->intr_urb) {
-               printk(KERN_ERR PFX "Out of memory\n");
-               goto error;
-       }
-
-       /* initialise the intr urb's */
-       usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
-                       usb_pcwd->intr_buffer, usb_pcwd->intr_size,
-                       usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
-       usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
-       usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       /* register our interrupt URB with the USB system */
-       if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
-               printk(KERN_ERR PFX "Problem registering interrupt URB\n");
-               retval = -EIO; /* failure */
-               goto error;
-       }
-
-       /* The device exists and can be communicated with */
-       usb_pcwd->exists = 1;
-
-       /* disable card */
-       usb_pcwd_stop(usb_pcwd);
-
-       /* Get the Firmware Version */
-       got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
-       if (got_fw_rev) {
-               sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
-       } else {
-               sprintf(fw_ver_str, "<card no answer>");
-       }
-
-       printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
-               fw_ver_str);
-
-       /* Get switch settings */
-       usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches);
-
-       printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
-               option_switches,
-               ((option_switches & 0x10) ? "ON" : "OFF"),
-               ((option_switches & 0x08) ? "ON" : "OFF"));
-
-       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
-       if (heartbeat == 0)
-               heartbeat = heartbeat_tbl[(option_switches & 0x07)];
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
-               usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
-                       WATCHDOG_HEARTBEAT);
-       }
-
-       retval = register_reboot_notifier(&usb_pcwd_notifier);
-       if (retval != 0) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       retval);
-               goto error;
-       }
-
-       retval = misc_register(&usb_pcwd_temperature_miscdev);
-       if (retval != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       TEMP_MINOR, retval);
-               goto err_out_unregister_reboot;
-       }
-
-       retval = misc_register(&usb_pcwd_miscdev);
-       if (retval != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, retval);
-               goto err_out_misc_deregister;
-       }
-
-       /* we can register the device now, as it is ready */
-       usb_set_intfdata (interface, usb_pcwd);
-
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-
-       return 0;
-
-err_out_misc_deregister:
-       misc_deregister(&usb_pcwd_temperature_miscdev);
-err_out_unregister_reboot:
-       unregister_reboot_notifier(&usb_pcwd_notifier);
-error:
-       if (usb_pcwd)
-               usb_pcwd_delete(usb_pcwd);
-       usb_pcwd_device = NULL;
-       return retval;
-}
-
-
-/**
- *     usb_pcwd_disconnect
- *
- *     Called by the usb core when the device is removed from the system.
- *
- *     This routine guarantees that the driver will not submit any more urbs
- *     by clearing dev->udev.
- */
-static void usb_pcwd_disconnect(struct usb_interface *interface)
-{
-       struct usb_pcwd_private *usb_pcwd;
-
-       /* prevent races with open() */
-       mutex_lock(&disconnect_mutex);
-
-       usb_pcwd = usb_get_intfdata (interface);
-       usb_set_intfdata (interface, NULL);
-
-       mutex_lock(&usb_pcwd->mtx);
-
-       /* Stop the timer before we leave */
-       if (!nowayout)
-               usb_pcwd_stop(usb_pcwd);
-
-       /* We should now stop communicating with the USB PCWD device */
-       usb_pcwd->exists = 0;
-
-       /* Deregister */
-       misc_deregister(&usb_pcwd_miscdev);
-       misc_deregister(&usb_pcwd_temperature_miscdev);
-       unregister_reboot_notifier(&usb_pcwd_notifier);
-
-       mutex_unlock(&usb_pcwd->mtx);
-
-       /* Delete the USB PCWD device */
-       usb_pcwd_delete(usb_pcwd);
-
-       cards_found--;
-
-       mutex_unlock(&disconnect_mutex);
-
-       printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
-}
-
-
-
-/**
- *     usb_pcwd_init
- */
-static int __init usb_pcwd_init(void)
-{
-       int result;
-
-       /* register this driver with the USB subsystem */
-       result = usb_register(&usb_pcwd_driver);
-       if (result) {
-               printk(KERN_ERR PFX "usb_register failed. Error number %d\n",
-                   result);
-               return result;
-       }
-
-       printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION " (" DRIVER_DATE ")\n");
-       return 0;
-}
-
-
-/**
- *     usb_pcwd_exit
- */
-static void __exit usb_pcwd_exit(void)
-{
-       /* deregister this driver with the USB subsystem */
-       usb_deregister(&usb_pcwd_driver);
-}
-
-
-module_init (usb_pcwd_init);
-module_exit (usb_pcwd_exit);
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c
deleted file mode 100644 (file)
index 22f8873..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * drivers/char/watchdog/pnx4008_wdt.c
- *
- * Watchdog driver for PNX4008 board
- *
- * Authors: Dmitry Chigirev <source@mvista.com>,
- *         Vitaly Wool <vitalywool@gmail.com>
- * Based on sa1100 driver,
- * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
- *
- * 2005-2006 (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/ioport.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-
-#include <asm/hardware.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define MODULE_NAME "PNX4008-WDT: "
-
-/* WatchDog Timer - Chapter 23 Page 207 */
-
-#define DEFAULT_HEARTBEAT 19
-#define MAX_HEARTBEAT     60
-
-/* Watchdog timer register set definition */
-#define WDTIM_INT(p)     ((p) + 0x0)
-#define WDTIM_CTRL(p)    ((p) + 0x4)
-#define WDTIM_COUNTER(p) ((p) + 0x8)
-#define WDTIM_MCTRL(p)   ((p) + 0xC)
-#define WDTIM_MATCH0(p)  ((p) + 0x10)
-#define WDTIM_EMR(p)     ((p) + 0x14)
-#define WDTIM_PULSE(p)   ((p) + 0x18)
-#define WDTIM_RES(p)     ((p) + 0x1C)
-
-/* WDTIM_INT bit definitions */
-#define MATCH_INT      1
-
-/* WDTIM_CTRL bit definitions */
-#define COUNT_ENAB     1
-#define RESET_COUNT    (1<<1)
-#define DEBUG_EN       (1<<2)
-
-/* WDTIM_MCTRL bit definitions */
-#define MR0_INT        1
-#undef  RESET_COUNT0
-#define RESET_COUNT0   (1<<2)
-#define STOP_COUNT0    (1<<2)
-#define M_RES1         (1<<3)
-#define M_RES2         (1<<4)
-#define RESFRC1        (1<<5)
-#define RESFRC2        (1<<6)
-
-/* WDTIM_EMR bit definitions */
-#define EXT_MATCH0      1
-#define MATCH_OUTPUT_HIGH (2<<4)       /*a MATCH_CTRL setting */
-
-/* WDTIM_RES bit definitions */
-#define WDOG_RESET      1      /* read only */
-
-#define WDOG_COUNTER_RATE 13000000     /*the counter clock is 13 MHz fixed */
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-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 unsigned long boot_status;
-
-static struct resource *wdt_mem;
-static void __iomem    *wdt_base;
-struct clk             *wdt_clk;
-
-static void wdt_enable(void)
-{
-       spin_lock(&io_lock);
-
-       if (wdt_clk)
-               clk_set_rate(wdt_clk, 1);
-
-       /* stop counter, initiate counter reset */
-       __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
-       /*wait for reset to complete. 100% guarantee event */
-       while (__raw_readl(WDTIM_COUNTER(wdt_base)))
-               cpu_relax();
-       /* internal and external reset, stop after that */
-       __raw_writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0,
-               WDTIM_MCTRL(wdt_base));
-       /* configure match output */
-       __raw_writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
-       /* clear interrupt, just in case */
-       __raw_writel(MATCH_INT, WDTIM_INT(wdt_base));
-       /* the longest pulse period 65541/(13*10^6) seconds ~ 5 ms. */
-       __raw_writel(0xFFFF, WDTIM_PULSE(wdt_base));
-       __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
-       /*enable counter, stop when debugger active */
-       __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
-
-       spin_unlock(&io_lock);
-}
-
-static void wdt_disable(void)
-{
-       spin_lock(&io_lock);
-
-       __raw_writel(0, WDTIM_CTRL(wdt_base));  /*stop counter */
-       if (wdt_clk)
-               clk_set_rate(wdt_clk, 0);
-
-       spin_unlock(&io_lock);
-}
-
-static int pnx4008_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-pnx4008_wdt_write(struct file *file, const char *data, size_t len,
-                 loff_t * ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_enable();
-       }
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
-           WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-       .identity = "PNX4008 Watchdog",
-};
-
-static int
-pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                 unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int *)arg);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, (int *)arg);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > MAX_HEARTBEAT) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               heartbeat = time;
-               wdt_enable();
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-       }
-       return ret;
-}
-
-static int pnx4008_wdt_release(struct inode *inode, struct file *file)
-{
-       if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
-
-       wdt_disable();
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations pnx4008_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = pnx4008_wdt_write,
-       .ioctl = pnx4008_wdt_ioctl,
-       .open = pnx4008_wdt_open,
-       .release = pnx4008_wdt_release,
-};
-
-static struct miscdevice pnx4008_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &pnx4008_wdt_fops,
-};
-
-static int pnx4008_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
-               "PNX4008 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 resouce\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 *)IO_ADDRESS(res->start);
-
-       wdt_clk = clk_get(&pdev->dev, "wdt_ck");
-       if (IS_ERR(wdt_clk)) {
-               ret = PTR_ERR(wdt_clk);
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
-               goto out;
-       } else
-               clk_set_rate(wdt_clk, 1);
-
-       ret = misc_register(&pnx4008_wdt_miscdev);
-       if (ret < 0) {
-               printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
-               release_resource(wdt_mem);
-               kfree(wdt_mem);
-               clk_set_rate(wdt_clk, 0);
-       } else {
-               boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
-                   WDIOF_CARDRESET : 0;
-               wdt_disable();          /*disable for now */
-               set_bit(WDT_DEVICE_INITED, &wdt_status);
-       }
-
-out:
-       return ret;
-}
-
-static int pnx4008_wdt_remove(struct platform_device *pdev)
-{
-       misc_deregister(&pnx4008_wdt_miscdev);
-       if (wdt_clk) {
-               clk_set_rate(wdt_clk, 0);
-               clk_put(wdt_clk);
-               wdt_clk = NULL;
-       }
-       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 = pnx4008_wdt_probe,
-       .remove = pnx4008_wdt_remove,
-};
-
-static int __init pnx4008_wdt_init(void)
-{
-       return platform_driver_register(&platform_wdt_driver);
-}
-
-static void __exit pnx4008_wdt_exit(void)
-{
-       return platform_driver_unregister(&platform_wdt_driver);
-}
-
-module_init(pnx4008_wdt_init);
-module_exit(pnx4008_wdt_exit);
-
-MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION("PNX4008 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_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout,
-                "Set to 1 to keep watchdog running after device release");
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c
deleted file mode 100644 (file)
index 5c921e4..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- *  Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx
- *  chips.
- *
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <asm/io.h>
-#include <asm/atomic.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <rm9k_wdt.h>
-
-
-#define CLOCK                  125000000
-#define MAX_TIMEOUT_SECONDS    32
-#define CPCCR                  0x0080
-#define CPGIG1SR               0x0044
-#define CPGIG1ER               0x0054
-
-
-/* Function prototypes */
-static irqreturn_t wdt_gpi_irqhdl(int, void *);
-static void wdt_gpi_start(void);
-static void wdt_gpi_stop(void);
-static void wdt_gpi_set_timeout(unsigned int);
-static int wdt_gpi_open(struct inode *, struct file *);
-static int wdt_gpi_release(struct inode *, struct file *);
-static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *);
-static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
-static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
-static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int);
-static int __init wdt_gpi_probe(struct device *);
-static int __exit wdt_gpi_remove(struct device *);
-
-
-static const char wdt_gpi_name[] = "wdt_gpi";
-static atomic_t opencnt;
-static int expect_close;
-static int locked;
-
-
-/* These are set from device resources */
-static void __iomem * wd_regs;
-static unsigned int wd_irq, wd_ctr;
-
-
-/* Module arguments */
-static int timeout = MAX_TIMEOUT_SECONDS;
-module_param(timeout, int, 0444);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
-
-static unsigned long resetaddr = 0xbffdc200;
-module_param(resetaddr, ulong, 0444);
-MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset");
-
-static unsigned long flagaddr = 0xbffdc104;
-module_param(flagaddr, ulong, 0444);
-MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to");
-
-static int powercycle;
-module_param(powercycle, bool, 0444);
-MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, bool, 0444);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
-
-
-/* Kernel interfaces */
-static const struct file_operations fops = {
-       .owner          = THIS_MODULE,
-       .open           = wdt_gpi_open,
-       .release        = wdt_gpi_release,
-       .write          = wdt_gpi_write,
-       .unlocked_ioctl = wdt_gpi_ioctl,
-};
-
-static struct miscdevice miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = wdt_gpi_name,
-       .fops           = &fops,
-};
-
-static struct notifier_block wdt_gpi_shutdown = {
-       .notifier_call  = wdt_gpi_notify,
-};
-
-
-/* Interrupt handler */
-static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt)
-{
-       if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
-               return IRQ_NONE;
-       __raw_writel(0x1, wd_regs + 0x0008);
-
-
-       printk(KERN_CRIT "%s: watchdog expired - resetting system\n",
-               wdt_gpi_name);
-
-       *(volatile char *) flagaddr |= 0x01;
-       *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2;
-       iob();
-       while (1)
-               cpu_relax();
-}
-
-
-/* Watchdog functions */
-static void wdt_gpi_start(void)
-{
-       u32 reg;
-
-       lock_titan_regs();
-       reg = titan_readl(CPGIG1ER);
-       titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER);
-       iob();
-       unlock_titan_regs();
-}
-
-static void wdt_gpi_stop(void)
-{
-       u32 reg;
-
-       lock_titan_regs();
-       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-       titan_writel(reg, CPCCR);
-       reg = titan_readl(CPGIG1ER);
-       titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER);
-       iob();
-       unlock_titan_regs();
-}
-
-static void wdt_gpi_set_timeout(unsigned int to)
-{
-       u32 reg;
-       const u32 wdval = (to * CLOCK) & ~0x0000000f;
-
-       lock_titan_regs();
-       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-       titan_writel(reg, CPCCR);
-       wmb();
-       __raw_writel(wdval, wd_regs + 0x0000);
-       wmb();
-       titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR);
-       wmb();
-       titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR);
-       iob();
-       unlock_titan_regs();
-}
-
-
-/* /dev/watchdog operations */
-static int wdt_gpi_open(struct inode *inode, struct file *file)
-{
-       int res;
-
-       if (unlikely(atomic_dec_if_positive(&opencnt) < 0))
-               return -EBUSY;
-
-       expect_close = 0;
-       if (locked) {
-               module_put(THIS_MODULE);
-               free_irq(wd_irq, &miscdev);
-               locked = 0;
-       }
-
-       res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
-                         wdt_gpi_name, &miscdev);
-       if (unlikely(res))
-               return res;
-
-       wdt_gpi_set_timeout(timeout);
-       wdt_gpi_start();
-
-       printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n",
-               wdt_gpi_name, timeout);
-       return nonseekable_open(inode, file);
-}
-
-static int wdt_gpi_release(struct inode *inode, struct file *file)
-{
-       if (nowayout) {
-               printk(KERN_INFO "%s: no way out - watchdog left running\n",
-                       wdt_gpi_name);
-               __module_get(THIS_MODULE);
-               locked = 1;
-       } else {
-               if (expect_close) {
-                       wdt_gpi_stop();
-                       free_irq(wd_irq, &miscdev);
-                       printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name);
-               } else {
-                       printk(KERN_CRIT "%s: unexpected close() -"
-                               " watchdog left running\n",
-                               wdt_gpi_name);
-                       wdt_gpi_set_timeout(timeout);
-                       __module_get(THIS_MODULE);
-                       locked = 1;
-               }
-       }
-
-       atomic_inc(&opencnt);
-       return 0;
-}
-
-static ssize_t
-wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o)
-{
-       char val;
-
-       wdt_gpi_set_timeout(timeout);
-       expect_close = (s > 0) && !get_user(val, d) && (val == 'V');
-       return s ? 1 : 0;
-}
-
-static long
-wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-       long res = -ENOTTY;
-       const long size = _IOC_SIZE(cmd);
-       int stat;
-       void __user *argp = (void __user *)arg;
-       static struct watchdog_info wdinfo = {
-               .identity               = "RM9xxx/GPI watchdog",
-               .firmware_version       = 0,
-               .options                = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
-       };
-
-       if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE))
-               return -ENOTTY;
-
-       if ((_IOC_DIR(cmd) & _IOC_READ)
-           && !access_ok(VERIFY_WRITE, arg, size))
-               return -EFAULT;
-
-       if ((_IOC_DIR(cmd) & _IOC_WRITE)
-           && !access_ok(VERIFY_READ, arg, size))
-               return -EFAULT;
-
-       expect_close = 0;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               wdinfo.options = nowayout ?
-                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
-                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE;
-               res = __copy_to_user(argp, &wdinfo, size) ?  -EFAULT : size;
-               break;
-
-       case WDIOC_GETSTATUS:
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               stat = (*(volatile char *) flagaddr & 0x01)
-                       ? WDIOF_CARDRESET : 0;
-               res = __copy_to_user(argp, &stat, size) ?
-                       -EFAULT : size;
-               break;
-
-       case WDIOC_SETOPTIONS:
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_gpi_set_timeout(timeout);
-               res = size;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               {
-                       int val;
-                       if (unlikely(__copy_from_user(&val, argp, size))) {
-                               res = -EFAULT;
-                               break;
-                       }
-
-                       if (val > MAX_TIMEOUT_SECONDS)
-                               val = MAX_TIMEOUT_SECONDS;
-                       timeout = val;
-                       wdt_gpi_set_timeout(val);
-                       res = size;
-                       printk(KERN_INFO "%s: timeout set to %u seconds\n",
-                               wdt_gpi_name, timeout);
-               }
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               res = __copy_to_user(argp, &timeout, size) ?
-                       -EFAULT : size;
-               break;
-       }
-
-       return res;
-}
-
-
-/* Shutdown notifier */
-static int
-wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               wdt_gpi_stop();
-
-       return NOTIFY_DONE;
-}
-
-
-/* Init & exit procedures */
-static const struct resource *
-wdt_gpi_get_resource(struct platform_device *pdv, const char *name,
-                     unsigned int type)
-{
-       char buf[80];
-       if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
-               return NULL;
-       return platform_get_resource_byname(pdv, type, buf);
-}
-
-/* No hotplugging on the platform bus - use __init */
-static int __init wdt_gpi_probe(struct device *dev)
-{
-       int res;
-       struct platform_device * const pdv = to_platform_device(dev);
-       const struct resource
-               * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
-                                                 IORESOURCE_MEM),
-               * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ,
-                                                 IORESOURCE_IRQ),
-               * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER,
-                                                 0);
-
-       if (unlikely(!rr || !ri || !rc))
-               return -ENXIO;
-
-       wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start);
-       if (unlikely(!wd_regs))
-               return -ENOMEM;
-       wd_irq = ri->start;
-       wd_ctr = rc->start;
-       res = misc_register(&miscdev);
-       if (res)
-               iounmap(wd_regs);
-       else
-               register_reboot_notifier(&wdt_gpi_shutdown);
-       return res;
-}
-
-static int __exit wdt_gpi_remove(struct device *dev)
-{
-       int res;
-
-       unregister_reboot_notifier(&wdt_gpi_shutdown);
-       res = misc_deregister(&miscdev);
-       iounmap(wd_regs);
-       wd_regs = NULL;
-       return res;
-}
-
-
-/* Device driver init & exit */
-static struct device_driver wdt_gpi_driver = {
-       .name           = (char *) wdt_gpi_name,
-       .bus            = &platform_bus_type,
-       .owner          = THIS_MODULE,
-       .probe          = wdt_gpi_probe,
-       .remove         = __exit_p(wdt_gpi_remove),
-       .shutdown       = NULL,
-       .suspend        = NULL,
-       .resume         = NULL,
-};
-
-static int __init wdt_gpi_init_module(void)
-{
-       atomic_set(&opencnt, 1);
-       if (timeout > MAX_TIMEOUT_SECONDS)
-               timeout = MAX_TIMEOUT_SECONDS;
-       return driver_register(&wdt_gpi_driver);
-}
-
-static void __exit wdt_gpi_cleanup_module(void)
-{
-       driver_unregister(&wdt_gpi_driver);
-}
-
-module_init(wdt_gpi_init_module);
-module_exit(wdt_gpi_cleanup_module);
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
deleted file mode 100644 (file)
index 5d1c15f..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-/* linux/drivers/char/watchdog/s3c2410_wdt.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 Watchdog Timer Support
- *
- * Based on, softdog.c by Alan Cox,
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog:
- *     05-Oct-2004     BJD     Added semaphore init to stop crashes on open
- *                             Fixed tmr_count / wdt_count confusion
- *                             Added configurable debug
- *
- *     11-Jan-2005     BJD     Fixed divide-by-2 in timeout code
- *
- *     25-Jan-2005     DA      Added suspend/resume support
- *                             Replaced reboot notifier with .shutdown method
- *
- *     10-Mar-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
-*/
-
-#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/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include <asm/arch/map.h>
-
-#undef S3C_VA_WATCHDOG
-#define S3C_VA_WATCHDOG (0)
-
-#include <asm/plat-s3c/regs-watchdog.h>
-
-#define PFX "s3c2410-wdt: "
-
-#define CONFIG_S3C2410_WATCHDOG_ATBOOT         (0)
-#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME   (15)
-
-static int nowayout    = WATCHDOG_NOWAYOUT;
-static int tmr_margin  = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
-static int tmr_atboot  = CONFIG_S3C2410_WATCHDOG_ATBOOT;
-static int soft_noboot = 0;
-static int debug       = 0;
-
-module_param(tmr_margin,  int, 0);
-module_param(tmr_atboot,  int, 0);
-module_param(nowayout,    int, 0);
-module_param(soft_noboot, int, 0);
-module_param(debug,      int, 0);
-
-MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")");
-
-MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
-
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
-
-MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)");
-
-
-typedef enum close_state {
-       CLOSE_STATE_NOT,
-       CLOSE_STATE_ALLOW=0x4021
-} close_state_t;
-
-static DECLARE_MUTEX(open_lock);
-
-static struct device    *wdt_dev;      /* platform device attached to */
-static struct resource *wdt_mem;
-static struct resource *wdt_irq;
-static struct clk      *wdt_clock;
-static void __iomem    *wdt_base;
-static unsigned int     wdt_count;
-static close_state_t    allow_close;
-
-/* watchdog control routines */
-
-#define DBG(msg...) do { \
-       if (debug) \
-               printk(KERN_INFO msg); \
-       } while(0)
-
-/* functions */
-
-static int s3c2410wdt_keepalive(void)
-{
-       writel(wdt_count, wdt_base + S3C2410_WTCNT);
-       return 0;
-}
-
-static int s3c2410wdt_stop(void)
-{
-       unsigned long wtcon;
-
-       wtcon = readl(wdt_base + S3C2410_WTCON);
-       wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);
-       writel(wtcon, wdt_base + S3C2410_WTCON);
-
-       return 0;
-}
-
-static int s3c2410wdt_start(void)
-{
-       unsigned long wtcon;
-
-       s3c2410wdt_stop();
-
-       wtcon = readl(wdt_base + S3C2410_WTCON);
-       wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;
-
-       if (soft_noboot) {
-               wtcon |= S3C2410_WTCON_INTEN;
-               wtcon &= ~S3C2410_WTCON_RSTEN;
-       } else {
-               wtcon &= ~S3C2410_WTCON_INTEN;
-               wtcon |= S3C2410_WTCON_RSTEN;
-       }
-
-       DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
-           __FUNCTION__, wdt_count, wtcon);
-
-       writel(wdt_count, wdt_base + S3C2410_WTDAT);
-       writel(wdt_count, wdt_base + S3C2410_WTCNT);
-       writel(wtcon, wdt_base + S3C2410_WTCON);
-
-       return 0;
-}
-
-static int s3c2410wdt_set_heartbeat(int timeout)
-{
-       unsigned int freq = clk_get_rate(wdt_clock);
-       unsigned int count;
-       unsigned int divisor = 1;
-       unsigned long wtcon;
-
-       if (timeout < 1)
-               return -EINVAL;
-
-       freq /= 128;
-       count = timeout * freq;
-
-       DBG("%s: count=%d, timeout=%d, freq=%d\n",
-           __FUNCTION__, count, timeout, freq);
-
-       /* if the count is bigger than the watchdog register,
-          then work out what we need to do (and if) we can
-          actually make this value
-       */
-
-       if (count >= 0x10000) {
-               for (divisor = 1; divisor <= 0x100; divisor++) {
-                       if ((count / divisor) < 0x10000)
-                               break;
-               }
-
-               if ((count / divisor) >= 0x10000) {
-                       dev_err(wdt_dev, "timeout %d too big\n", timeout);
-                       return -EINVAL;
-               }
-       }
-
-       tmr_margin = timeout;
-
-       DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
-           __FUNCTION__, timeout, divisor, count, count/divisor);
-
-       count /= divisor;
-       wdt_count = count;
-
-       /* update the pre-scaler */
-       wtcon = readl(wdt_base + S3C2410_WTCON);
-       wtcon &= ~S3C2410_WTCON_PRESCALE_MASK;
-       wtcon |= S3C2410_WTCON_PRESCALE(divisor-1);
-
-       writel(count, wdt_base + S3C2410_WTDAT);
-       writel(wtcon, wdt_base + S3C2410_WTCON);
-
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int s3c2410wdt_open(struct inode *inode, struct file *file)
-{
-       if(down_trylock(&open_lock))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       allow_close = CLOSE_STATE_NOT;
-
-       /* start the timer */
-       s3c2410wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int s3c2410wdt_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-
-       if (allow_close == CLOSE_STATE_ALLOW) {
-               s3c2410wdt_stop();
-       } else {
-               dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
-               s3c2410wdt_keepalive();
-       }
-
-       allow_close = CLOSE_STATE_NOT;
-       up(&open_lock);
-       return 0;
-}
-
-static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       /*
-        *      Refresh the timer.
-        */
-       if(len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       allow_close = CLOSE_STATE_NOT;
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       allow_close = CLOSE_STATE_ALLOW;
-                       }
-               }
-
-               s3c2410wdt_keepalive();
-       }
-       return len;
-}
-
-#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
-
-static struct watchdog_info s3c2410_wdt_ident = {
-       .options          =     OPTIONS,
-       .firmware_version =     0,
-       .identity         =     "S3C2410 Watchdog",
-};
-
-
-static int s3c2410wdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &s3c2410_wdt_ident,
-                               sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
-
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-
-               case WDIOC_KEEPALIVE:
-                       s3c2410wdt_keepalive();
-                       return 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_margin, p))
-                               return -EFAULT;
-
-                       if (s3c2410wdt_set_heartbeat(new_margin))
-                               return -EINVAL;
-
-                       s3c2410wdt_keepalive();
-                       return put_user(tmr_margin, p);
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(tmr_margin, p);
-       }
-}
-
-/* kernel interface */
-
-static const struct file_operations s3c2410wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = s3c2410wdt_write,
-       .ioctl          = s3c2410wdt_ioctl,
-       .open           = s3c2410wdt_open,
-       .release        = s3c2410wdt_release,
-};
-
-static struct miscdevice s3c2410wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &s3c2410wdt_fops,
-};
-
-/* interrupt handler code */
-
-static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
-{
-       dev_info(wdt_dev, "watchdog timer expired (irq)\n");
-
-       s3c2410wdt_keepalive();
-       return IRQ_HANDLED;
-}
-/* device interface */
-
-static int s3c2410wdt_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct device *dev;
-       unsigned int wtcon;
-       int started = 0;
-       int ret;
-       int size;
-
-       DBG("%s: probe=%p\n", __FUNCTION__, pdev);
-
-       dev = &pdev->dev;
-       wdt_dev = &pdev->dev;
-
-       /* get the memory region for the watchdog timer */
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(dev, "no memory resource specified\n");
-               return -ENOENT;
-       }
-
-       size = (res->end-res->start)+1;
-       wdt_mem = request_mem_region(res->start, size, pdev->name);
-       if (wdt_mem == NULL) {
-               dev_err(dev, "failed to get memory region\n");
-               ret = -ENOENT;
-               goto err_req;
-       }
-
-       wdt_base = ioremap(res->start, size);
-       if (wdt_base == 0) {
-               dev_err(dev, "failed to ioremap() region\n");
-               ret = -EINVAL;
-               goto err_req;
-       }
-
-       DBG("probe: mapped wdt_base=%p\n", wdt_base);
-
-       wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (wdt_irq == NULL) {
-               dev_err(dev, "no irq resource specified\n");
-               ret = -ENOENT;
-               goto err_map;
-       }
-
-       ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
-       if (ret != 0) {
-               dev_err(dev, "failed to install irq (%d)\n", ret);
-               goto err_map;
-       }
-
-       wdt_clock = clk_get(&pdev->dev, "watchdog");
-       if (IS_ERR(wdt_clock)) {
-               dev_err(dev, "failed to find watchdog clock source\n");
-               ret = PTR_ERR(wdt_clock);
-               goto err_irq;
-       }
-
-       clk_enable(wdt_clock);
-
-       /* see if we can actually set the requested timer margin, and if
-        * not, try the default value */
-
-       if (s3c2410wdt_set_heartbeat(tmr_margin)) {
-               started = s3c2410wdt_set_heartbeat(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
-
-               if (started == 0) {
-                       dev_info(dev,"tmr_margin value out of range, default %d used\n",
-                              CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
-               } else {
-                       dev_info(dev, "default timer value is out of range, cannot start\n");
-               }
-       }
-
-       ret = misc_register(&s3c2410wdt_miscdev);
-       if (ret) {
-               dev_err(dev, "cannot register miscdev on minor=%d (%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto err_clk;
-       }
-
-       if (tmr_atboot && started == 0) {
-               dev_info(dev, "starting watchdog timer\n");
-               s3c2410wdt_start();
-       } else if (!tmr_atboot) {
-               /* if we're not enabling the watchdog, then ensure it is
-                * disabled if it has been left running from the bootloader
-                * or other source */
-
-               s3c2410wdt_stop();
-       }
-
-       /* print out a statement of readiness */
-
-       wtcon = readl(wdt_base + S3C2410_WTCON);
-
-       dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
-                (wtcon & S3C2410_WTCON_ENABLE) ?  "" : "in",
-                (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
-                (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
-       
-       return 0;
-
- err_clk:
-       clk_disable(wdt_clock);
-       clk_put(wdt_clock);
-
- err_irq:
-       free_irq(wdt_irq->start, pdev);
-
- err_map:
-       iounmap(wdt_base);
-
- err_req:
-       release_resource(wdt_mem);
-       kfree(wdt_mem);
-
-       return ret;
-}
-
-static int s3c2410wdt_remove(struct platform_device *dev)
-{
-       release_resource(wdt_mem);
-       kfree(wdt_mem);
-       wdt_mem = NULL;
-
-       free_irq(wdt_irq->start, dev);
-       wdt_irq = NULL;
-
-       clk_disable(wdt_clock);
-       clk_put(wdt_clock);
-       wdt_clock = NULL;
-
-       iounmap(wdt_base);
-       misc_deregister(&s3c2410wdt_miscdev);
-       return 0;
-}
-
-static void s3c2410wdt_shutdown(struct platform_device *dev)
-{
-       s3c2410wdt_stop();      
-}
-
-#ifdef CONFIG_PM
-
-static unsigned long wtcon_save;
-static unsigned long wtdat_save;
-
-static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state)
-{
-       /* Save watchdog state, and turn it off. */
-       wtcon_save = readl(wdt_base + S3C2410_WTCON);
-       wtdat_save = readl(wdt_base + S3C2410_WTDAT);
-
-       /* Note that WTCNT doesn't need to be saved. */
-       s3c2410wdt_stop();
-
-       return 0;
-}
-
-static int s3c2410wdt_resume(struct platform_device *dev)
-{
-       /* Restore watchdog state. */
-
-       writel(wtdat_save, wdt_base + S3C2410_WTDAT);
-       writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
-       writel(wtcon_save, wdt_base + S3C2410_WTCON);
-
-       printk(KERN_INFO PFX "watchdog %sabled\n",
-              (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
-
-       return 0;
-}
-
-#else
-#define s3c2410wdt_suspend NULL
-#define s3c2410wdt_resume  NULL
-#endif /* CONFIG_PM */
-
-
-static struct platform_driver s3c2410wdt_driver = {
-       .probe          = s3c2410wdt_probe,
-       .remove         = s3c2410wdt_remove,
-       .shutdown       = s3c2410wdt_shutdown,
-       .suspend        = s3c2410wdt_suspend,
-       .resume         = s3c2410wdt_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "s3c2410-wdt",
-       },
-};
-
-
-static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
-
-static int __init watchdog_init(void)
-{
-       printk(banner);
-       return platform_driver_register(&s3c2410wdt_driver);
-}
-
-static void __exit watchdog_exit(void)
-{
-       platform_driver_unregister(&s3c2410wdt_driver);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
-
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, "
-             "Dimitry Andric <dimitry.andric@tomtom.com>");
-MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
deleted file mode 100644 (file)
index 3475f47..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *     Watchdog driver for the SA11x0/PXA2xx
- *
- *      (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
- *          Based on SoftDog driver by Alan Cox <alan@redhat.com>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 2000           Oleg Drokin <green@crimea.edu>
- *
- *      27/11/2000 Initial release
- */
-#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>
-
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
-
-#include <asm/hardware.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-
-#define OSCR_FREQ              CLOCK_TICK_RATE
-
-static unsigned long sa1100wdt_users;
-static int pre_margin;
-static int boot_status;
-
-/*
- *     Allow only one person to hold it open
- */
-static int sa1100dog_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(1,&sa1100wdt_users))
-               return -EBUSY;
-
-       /* Activate SA1100 Watchdog timer */
-       OSMR3 = OSCR + pre_margin;
-       OSSR = OSSR_M3;
-       OWER = OWER_WME;
-       OIER |= OIER_E3;
-       return nonseekable_open(inode, file);
-}
-
-/*
- * The watchdog cannot be disabled.
- *
- * Previous comments suggested that turning off the interrupt by
- * clearing OIER[E3] would prevent the watchdog timing out but this
- * does not appear to be true (at least on the PXA255).
- */
-static int sa1100dog_release(struct inode *inode, struct file *file)
-{
-       printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
-
-       clear_bit(1, &sa1100wdt_users);
-
-       return 0;
-}
-
-static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
-{
-       if (len)
-               /* Refresh OSMR3 timer. */
-               OSMR3 = OSCR + pre_margin;
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options        = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-       .identity       = "SA1100/PXA255 Watchdog",
-};
-
-static int sa1100dog_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(argp, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, p);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, p);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > 255) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               pre_margin = OSCR_FREQ * time;
-               OSMR3 = OSCR + pre_margin;
-               /*fall through*/
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(pre_margin / OSCR_FREQ, p);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               OSMR3 = OSCR + pre_margin;
-               ret = 0;
-               break;
-       }
-       return ret;
-}
-
-static const struct file_operations sa1100dog_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = sa1100dog_write,
-       .ioctl          = sa1100dog_ioctl,
-       .open           = sa1100dog_open,
-       .release        = sa1100dog_release,
-};
-
-static struct miscdevice sa1100dog_miscdev =
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &sa1100dog_fops,
-};
-
-static int margin __initdata = 60;             /* (secs) Default is 1 minute */
-
-static int __init sa1100dog_init(void)
-{
-       int ret;
-
-       /*
-        * Read the reset status, and save it for later.  If
-        * we suspend, RCSR will be cleared, and the watchdog
-        * reset reason will be lost.
-        */
-       boot_status = (RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0;
-       pre_margin = OSCR_FREQ * margin;
-
-       ret = misc_register(&sa1100dog_miscdev);
-       if (ret == 0)
-               printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
-                      margin);
-       return ret;
-}
-
-static void __exit sa1100dog_exit(void)
-{
-       misc_deregister(&sa1100dog_miscdev);
-}
-
-module_init(sa1100dog_init);
-module_exit(sa1100dog_exit);
-
-MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
-MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
-
-module_param(margin, int, 0);
-MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
deleted file mode 100644 (file)
index e4f3cb6..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- *     60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x
- *
- *      Based on acquirewdt.c by Alan Cox.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     The author does NOT admit liability nor provide warranty for
- *     any of this software. This material is provided "AS-IS" in
- *     the hope that it may be useful for others.
- *
- *     (c) Copyright 2000    Jakob Oestergaard <jakob@unthought.net>
- *
- *           12/4 - 2000      [Initial revision]
- *           25/4 - 2000      Added /dev/watchdog support
- *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
- *           12/4 - 2002      [rob@osinvestor.com] eliminate fop_read
- *                            fix possible wdt_is_open race
- *                            add CONFIG_WATCHDOG_NOWAYOUT support
- *                            remove lock_kernel/unlock_kernel pairs
- *                            added KERN_* to printk's
- *                            got rid of extraneous comments
- *                            changed watchdog_info to correctly reflect what the driver offers
- *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
- *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
- *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
- *                            use module_param
- *                            made timeout (the emulated heartbeat) a module_param
- *                            made the keepalive ping an internal subroutine
- *                            made wdt_stop and wdt_start module params
- *                            added extra printk's for startup problems
- *                            added MODULE_AUTHOR and MODULE_DESCRIPTION info
- *
- *
- *  This WDT driver is different from the other Linux WDT
- *  drivers in the following ways:
- *  *)  The driver will ping the watchdog by itself, because this
- *      particular WDT has a very short timeout (one second) and it
- *      would be insane to count on any userspace daemon always
- *      getting scheduled within that time frame.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define OUR_NAME "sbc60xxwdt"
-#define PFX OUR_NAME ": "
-
-/*
- * You must set these - The driver cannot probe for the settings
- */
-
-static int wdt_stop = 0x45;
-module_param(wdt_stop, int, 0);
-MODULE_PARM_DESC(wdt_stop, "SBC60xx WDT 'stop' io port (default 0x45)");
-
-static int wdt_start = 0x443;
-module_param(wdt_start, int, 0);
-MODULE_PARM_DESC(wdt_start, "SBC60xx WDT 'start' io port (default 0x443)");
-
-/*
- * The 60xx board can use watchdog timeout values from one second
- * to several minutes.  The default is one second, so if we reset
- * the watchdog every ~250ms we should be safe.
- */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 30 seconds.
- * If the daemon pulses us every 25 seconds, we can still afford
- * a 5 second scheduling delay on the (high priority) daemon. That
- * should be sufficient for a box under any load.
- */
-
-#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-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 wdt_timer_ping(unsigned long);
-static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
-static unsigned long next_heartbeat;
-static unsigned long wdt_is_open;
-static char wdt_expect_close;
-
-/*
- *     Whack the dog
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT
-        */
-       if(time_before(jiffies, next_heartbeat))
-       {
-               /* Ping the WDT by reading from wdt_start */
-               inb_p(wdt_start);
-               /* Re-set the timer interval */
-               mod_timer(&timer, jiffies + WDT_INTERVAL);
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-/*
- * Utility routines
- */
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + (timeout * HZ);
-
-       /* Start the timer */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
-}
-
-static void wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer(&timer);
-       inb_p(wdt_stop);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
-}
-
-static void wdt_keepalive(void)
-{
-       /* user land ping */
-       next_heartbeat = jiffies + (timeout * HZ);
-}
-
-/*
- * /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count)
-       {
-               if (!nowayout)
-               {
-                       size_t ofs;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       wdt_expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for(ofs = 0; ofs != count; ofs++)
-                       {
-                               char c;
-                               if(get_user(c, buf+ofs))
-                                       return -EFAULT;
-                               if(c == 'V')
-                                       wdt_expect_close = 42;
-                       }
-               }
-
-               /* Well, anyhow someone wrote to us, we should return that favour */
-               wdt_keepalive();
-       }
-       return count;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       /* Just in case we're already talking to someone... */
-       if(test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Good, fire up the show */
-       wdt_startup();
-       return nonseekable_open(inode, file);
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(wdt_expect_close == 42)
-               wdt_turnoff();
-       else {
-               del_timer(&timer);
-               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
-       }
-       clear_bit(0, &wdt_is_open);
-       wdt_expect_close = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident=
-       {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "SBC60xx",
-       };
-
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               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:
-                       wdt_keepalive();
-                       return 0;
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if(get_user(new_options, p))
-                               return -EFAULT;
-
-                       if(new_options & WDIOS_DISABLECARD) {
-                               wdt_turnoff();
-                               retval = 0;
-                       }
-
-                       if(new_options & WDIOS_ENABLECARD) {
-                               wdt_startup();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_timeout;
-
-                       if(get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       wdt_keepalive();
-                       /* Fall through */
-               }
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout, p);
-       }
-}
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = fop_write,
-       .open           = fop_open,
-       .release        = fop_close,
-       .ioctl          = fop_ioctl,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wdt_fops,
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-               wdt_turnoff();
-       return NOTIFY_DONE;
-}
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier=
-{
-       .notifier_call = wdt_notify_sys,
-};
-
-static void __exit sbc60xxwdt_unload(void)
-{
-       wdt_turnoff();
-
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-
-       unregister_reboot_notifier(&wdt_notifier);
-       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
-               release_region(wdt_stop,1);
-       release_region(wdt_start,1);
-}
-
-static int __init sbc60xxwdt_init(void)
-{
-       int rc = -EBUSY;
-
-       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
-       {
-               timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
-                       timeout);
-       }
-
-       if (!request_region(wdt_start, 1, "SBC 60XX WDT"))
-       {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
-               rc = -EIO;
-               goto err_out;
-       }
-
-       /* We cannot reserve 0x45 - the kernel already has! */
-       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
-       {
-               if (!request_region(wdt_stop, 1, "SBC 60XX WDT"))
-               {
-                       printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                               wdt_stop);
-                       rc = -EIO;
-                       goto err_out_region1;
-               }
-       }
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
-               goto err_out_region2;
-       }
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_miscdev;
-       }
-
-       printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out_region2:
-       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
-               release_region(wdt_stop,1);
-err_out_region1:
-       release_region(wdt_start,1);
-err_out:
-       return rc;
-}
-
-module_init(sbc60xxwdt_init);
-module_exit(sbc60xxwdt_unload);
-
-MODULE_AUTHOR("Jakob Oestergaard <jakob@unthought.net>");
-MODULE_DESCRIPTION("60xx Single Board Computer Watchdog Timer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
deleted file mode 100644 (file)
index 285d852..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- *     SBC8360 Watchdog driver
- *
- *     (c) Copyright 2005 Webcon, Inc.
- *
- *     Based on ib700wdt.c, which is based on advantechwdt.c which is based
- *      on acquirewdt.c which is based on wdt.c.
- *
- *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
- *
- *      Based on advantechwdt.c which is based on acquirewdt.c which
- *       is based on wdt.c.
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     Based on acquirewdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
- *
- *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *           Added timeout module option to override default
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/notifier.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static unsigned long sbc8360_is_open;
-static spinlock_t sbc8360_lock;
-static char expect_close;
-
-#define PFX "sbc8360: "
-
-/*
- *
- * Watchdog Timer Configuration
- *
- * The function of the watchdog timer is to reset the system automatically
- * and is defined at I/O port 0120H and 0121H.  To enable the watchdog timer
- * and allow the system to reset, write appropriate values from the table
- * below to I/O port 0120H and 0121H.  To disable the timer, write a zero
- * value to I/O port 0121H for the system to stop the watchdog function.
- *
- * The following describes how the timer should be programmed (according to
- * the vendor documentation)
- *
- * Enabling Watchdog:
- * MOV AX,000AH (enable, phase I)
- * MOV DX,0120H
- * OUT DX,AX
- * MOV AX,000BH (enable, phase II)
- * MOV DX,0120H
- * OUT DX,AX
- * MOV AX,000nH (set multiplier n, from 1-4)
- * MOV DX,0120H
- * OUT DX,AX
- * MOV AX,000mH (set base timer m, from 0-F)
- * MOV DX,0121H
- * OUT DX,AX
- *
- * Reset timer:
- * MOV AX,000mH (same as set base timer, above)
- * MOV DX,0121H
- * OUT DX,AX
- *
- * Disabling Watchdog:
- * MOV AX,0000H (a zero value)
- * MOV DX,0120H
- * OUT DX,AX
- *
- * Watchdog timeout configuration values:
- *             N
- *     M |     1       2       3       4
- *     --|----------------------------------
- *     0 |     0.5s    5s      50s     100s
- *     1 |     1s      10s     100s    200s
- *     2 |     1.5s    15s     150s    300s
- *     3 |     2s      20s     200s    400s
- *     4 |     2.5s    25s     250s    500s
- *     5 |     3s      30s     300s    600s
- *     6 |     3.5s    35s     350s    700s
- *     7 |     4s      40s     400s    800s
- *     8 |     4.5s    45s     450s    900s
- *     9 |     5s      50s     500s    1000s
- *     A |     5.5s    55s     550s    1100s
- *     B |     6s      60s     600s    1200s
- *     C |     6.5s    65s     650s    1300s
- *     D |     7s      70s     700s    1400s
- *     E |     7.5s    75s     750s    1500s
- *     F |     8s      80s     800s    1600s
- *
- * Another way to say the same things is:
- *  For N=1, Timeout = (M+1) * 0.5s
- *  For N=2, Timeout = (M+1) * 5s
- *  For N=3, Timeout = (M+1) * 50s
- *  For N=4, Timeout = (M+1) * 100s
- *
- */
-
-static int wd_times[64][2] = {
-       {0, 1},                 /* 0  = 0.5s */
-       {1, 1},                 /* 1  = 1s   */
-       {2, 1},                 /* 2  = 1.5s */
-       {3, 1},                 /* 3  = 2s   */
-       {4, 1},                 /* 4  = 2.5s */
-       {5, 1},                 /* 5  = 3s   */
-       {6, 1},                 /* 6  = 3.5s */
-       {7, 1},                 /* 7  = 4s   */
-       {8, 1},                 /* 8  = 4.5s */
-       {9, 1},                 /* 9  = 5s   */
-       {0xA, 1},               /* 10 = 5.5s */
-       {0xB, 1},               /* 11 = 6s   */
-       {0xC, 1},               /* 12 = 6.5s */
-       {0xD, 1},               /* 13 = 7s   */
-       {0xE, 1},               /* 14 = 7.5s */
-       {0xF, 1},               /* 15 = 8s   */
-       {0, 2},                 /* 16 = 5s  */
-       {1, 2},                 /* 17 = 10s */
-       {2, 2},                 /* 18 = 15s */
-       {3, 2},                 /* 19 = 20s */
-       {4, 2},                 /* 20 = 25s */
-       {5, 2},                 /* 21 = 30s */
-       {6, 2},                 /* 22 = 35s */
-       {7, 2},                 /* 23 = 40s */
-       {8, 2},                 /* 24 = 45s */
-       {9, 2},                 /* 25 = 50s */
-       {0xA, 2},               /* 26 = 55s */
-       {0xB, 2},               /* 27 = 60s */
-       {0xC, 2},               /* 28 = 65s */
-       {0xD, 2},               /* 29 = 70s */
-       {0xE, 2},               /* 30 = 75s */
-       {0xF, 2},               /* 31 = 80s */
-       {0, 3},                 /* 32 = 50s  */
-       {1, 3},                 /* 33 = 100s */
-       {2, 3},                 /* 34 = 150s */
-       {3, 3},                 /* 35 = 200s */
-       {4, 3},                 /* 36 = 250s */
-       {5, 3},                 /* 37 = 300s */
-       {6, 3},                 /* 38 = 350s */
-       {7, 3},                 /* 39 = 400s */
-       {8, 3},                 /* 40 = 450s */
-       {9, 3},                 /* 41 = 500s */
-       {0xA, 3},               /* 42 = 550s */
-       {0xB, 3},               /* 43 = 600s */
-       {0xC, 3},               /* 44 = 650s */
-       {0xD, 3},               /* 45 = 700s */
-       {0xE, 3},               /* 46 = 750s */
-       {0xF, 3},               /* 47 = 800s */
-       {0, 4},                 /* 48 = 100s */
-       {1, 4},                 /* 49 = 200s */
-       {2, 4},                 /* 50 = 300s */
-       {3, 4},                 /* 51 = 400s */
-       {4, 4},                 /* 52 = 500s */
-       {5, 4},                 /* 53 = 600s */
-       {6, 4},                 /* 54 = 700s */
-       {7, 4},                 /* 55 = 800s */
-       {8, 4},                 /* 56 = 900s */
-       {9, 4},                 /* 57 = 1000s */
-       {0xA, 4},               /* 58 = 1100s */
-       {0xB, 4},               /* 59 = 1200s */
-       {0xC, 4},               /* 60 = 1300s */
-       {0xD, 4},               /* 61 = 1400s */
-       {0xE, 4},               /* 62 = 1500s */
-       {0xF, 4}                /* 63 = 1600s */
-};
-
-#define SBC8360_ENABLE 0x120
-#define SBC8360_BASETIME 0x121
-
-static int timeout = 27;
-static int wd_margin = 0xB;
-static int wd_multiplier = 2;
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout,
-                "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-/*
- *     Kernel methods.
- */
-
-/* Activate and pre-configure watchdog */
-static void sbc8360_activate(void)
-{
-       /* Enable the watchdog */
-       outb(0x0A, SBC8360_ENABLE);
-       msleep_interruptible(100);
-       outb(0x0B, SBC8360_ENABLE);
-       msleep_interruptible(100);
-       /* Set timeout multiplier */
-       outb(wd_multiplier, SBC8360_ENABLE);
-       msleep_interruptible(100);
-       /* Nothing happens until first sbc8360_ping() */
-}
-
-/* Kernel pings watchdog */
-static void sbc8360_ping(void)
-{
-       /* Write the base timer register */
-       outb(wd_margin, SBC8360_BASETIME);
-}
-
-/* Userspace pings kernel driver, or requests clean close */
-static ssize_t sbc8360_write(struct file *file, const char __user * buf,
-                            size_t count, loff_t * ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               sbc8360_ping();
-       }
-       return count;
-}
-
-static int sbc8360_open(struct inode *inode, struct file *file)
-{
-       spin_lock(&sbc8360_lock);
-       if (test_and_set_bit(0, &sbc8360_is_open)) {
-               spin_unlock(&sbc8360_lock);
-               return -EBUSY;
-       }
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate and ping once to start the countdown */
-       spin_unlock(&sbc8360_lock);
-       sbc8360_activate();
-       sbc8360_ping();
-       return nonseekable_open(inode, file);
-}
-
-static int sbc8360_close(struct inode *inode, struct file *file)
-{
-       spin_lock(&sbc8360_lock);
-       if (expect_close == 42)
-               outb(0, SBC8360_ENABLE);
-       else
-               printk(KERN_CRIT PFX
-                      "SBC8360 device closed unexpectedly.  SBC8360 will not stop!\n");
-
-       clear_bit(0, &sbc8360_is_open);
-       expect_close = 0;
-       spin_unlock(&sbc8360_lock);
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
-                             void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Disable the SBC8360 Watchdog */
-               outb(0, SBC8360_ENABLE);
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations sbc8360_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = sbc8360_write,
-       .open = sbc8360_open,
-       .release = sbc8360_close,
-};
-
-static struct miscdevice sbc8360_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &sbc8360_fops,
-};
-
-/*
- *     The SBC8360 needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block sbc8360_notifier = {
-       .notifier_call = sbc8360_notify_sys,
-};
-
-static int __init sbc8360_init(void)
-{
-       int res;
-       unsigned long int mseconds = 60000;
-
-       if (timeout < 0 || timeout > 63) {
-               printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
-               res = -EINVAL;
-               goto out;
-       }
-
-       if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
-               printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
-                      SBC8360_ENABLE);
-               res = -EIO;
-               goto out;
-       }
-       if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
-               printk(KERN_ERR PFX
-                      "BASETIME method I/O %X is not available.\n",
-                      SBC8360_BASETIME);
-               res = -EIO;
-               goto out_nobasetimereg;
-       }
-
-       res = register_reboot_notifier(&sbc8360_notifier);
-       if (res) {
-               printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
-               goto out_noreboot;
-       }
-
-       spin_lock_init(&sbc8360_lock);
-       res = misc_register(&sbc8360_miscdev);
-       if (res) {
-               printk(KERN_ERR PFX "failed to register misc device\n");
-               goto out_nomisc;
-       }
-
-       wd_margin = wd_times[timeout][0];
-       wd_multiplier = wd_times[timeout][1];
-
-       if (wd_multiplier == 1)
-               mseconds = (wd_margin + 1) * 500;
-       else if (wd_multiplier == 2)
-               mseconds = (wd_margin + 1) * 5000;
-       else if (wd_multiplier == 3)
-               mseconds = (wd_margin + 1) * 50000;
-       else if (wd_multiplier == 4)
-               mseconds = (wd_margin + 1) * 100000;
-
-       /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
-       printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
-
-       return 0;
-
-      out_nomisc:
-       unregister_reboot_notifier(&sbc8360_notifier);
-      out_noreboot:
-       release_region(SBC8360_BASETIME, 1);
-      out_nobasetimereg:
-       release_region(SBC8360_ENABLE, 1);
-      out:
-       return res;
-}
-
-static void __exit sbc8360_exit(void)
-{
-       misc_deregister(&sbc8360_miscdev);
-       unregister_reboot_notifier(&sbc8360_notifier);
-       release_region(SBC8360_ENABLE, 1);
-       release_region(SBC8360_BASETIME, 1);
-}
-
-module_init(sbc8360_init);
-module_exit(sbc8360_exit);
-
-MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
-MODULE_DESCRIPTION("SBC8360 watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.01");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-/* end of sbc8360.c */
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
deleted file mode 100644 (file)
index 82cbd88..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *     SBC EPX C3 0.1  A Hardware Watchdog Device for the Winsystems EPX-C3
- *     single board computer
- *
- *     (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights
- *     Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     based on softdog.c by Alan Cox <alan@redhat.com>
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define PFX "epx_c3: "
-static int epx_c3_alive;
-
-#define WATCHDOG_TIMEOUT 1             /* 1 sec default timeout */
-
-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) ")");
-
-#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
-#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
-
-static void epx_c3_start(void)
-{
-       outb(1, EPXC3_WATCHDOG_CTL_REG);
-}
-
-static void epx_c3_stop(void)
-{
-
-       outb(0, EPXC3_WATCHDOG_CTL_REG);
-
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
-}
-
-static void epx_c3_pet(void)
-{
-       outb(1, EPXC3_WATCHDOG_PET_REG);
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int epx_c3_open(struct inode *inode, struct file *file)
-{
-       if (epx_c3_alive)
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Activate timer */
-       epx_c3_start();
-       epx_c3_pet();
-
-       epx_c3_alive = 1;
-       printk(KERN_INFO "Started watchdog timer.\n");
-
-       return nonseekable_open(inode, file);
-}
-
-static int epx_c3_release(struct inode *inode, struct file *file)
-{
-       /* Shut off the timer.
-        * Lock it in if it's a module and we defined ...NOWAYOUT */
-       if (!nowayout)
-               epx_c3_stop();          /* Turn the WDT off */
-
-       epx_c3_alive = 0;
-
-       return 0;
-}
-
-static ssize_t epx_c3_write(struct file *file, const char __user *data,
-                       size_t len, loff_t *ppos)
-{
-       /* Refresh the timer. */
-       if (len)
-               epx_c3_pet();
-       return len;
-}
-
-static int epx_c3_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
-{
-       int options, retval = -EINVAL;
-       int __user *argp = (void __user *)arg;
-       static struct watchdog_info ident = {
-               .options                = WDIOF_KEEPALIVEPING |
-                                         WDIOF_MAGICCLOSE,
-               .firmware_version       = 0,
-               .identity               = "Winsystems EPX-C3 H/W Watchdog",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &ident, sizeof(ident)))
-                       return -EFAULT;
-               return 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, argp);
-       case WDIOC_KEEPALIVE:
-               epx_c3_pet();
-               return 0;
-       case WDIOC_GETTIMEOUT:
-               return put_user(WATCHDOG_TIMEOUT, argp);
-       case WDIOC_SETOPTIONS:
-               if (get_user(options, argp))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       epx_c3_stop();
-                       retval = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       epx_c3_start();
-                       retval = 0;
-               }
-
-               return retval;
-       default:
-               return -ENOTTY;
-       }
-}
-
-static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
-                               void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               epx_c3_stop();          /* Turn the WDT off */
-
-       return NOTIFY_DONE;
-}
-
-static const struct file_operations epx_c3_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = epx_c3_write,
-       .ioctl          = epx_c3_ioctl,
-       .open           = epx_c3_open,
-       .release        = epx_c3_release,
-};
-
-static struct miscdevice epx_c3_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &epx_c3_fops,
-};
-
-static struct notifier_block epx_c3_notifier = {
-       .notifier_call = epx_c3_notify_sys,
-};
-
-static const char banner[] __initdata =
-    KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
-
-static int __init watchdog_init(void)
-{
-       int ret;
-
-       if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
-               return -EBUSY;
-
-       ret = register_reboot_notifier(&epx_c3_notifier);
-       if (ret) {
-               printk(KERN_ERR PFX "cannot register reboot notifier "
-                       "(err=%d)\n", ret);
-               goto out;
-       }
-
-       ret = misc_register(&epx_c3_miscdev);
-       if (ret) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
-                       "(err=%d)\n", WATCHDOG_MINOR, ret);
-               unregister_reboot_notifier(&epx_c3_notifier);
-               goto out;
-       }
-
-       printk(banner);
-
-       return 0;
-
-out:
-       release_region(EPXC3_WATCHDOG_CTL_REG, 2);
-       return ret;
-}
-
-static void __exit watchdog_exit(void)
-{
-       misc_deregister(&epx_c3_miscdev);
-       unregister_reboot_notifier(&epx_c3_notifier);
-       release_region(EPXC3_WATCHDOG_CTL_REG, 2);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
-
-MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
-MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC.  Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems!  It writes to IO ports 0x1ee and 0x1ef!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
deleted file mode 100644 (file)
index 9670d47..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- *     National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
- *     (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>,
- *                     All Rights Reserved.
- *     Based on wdt.c and wdt977.c by Alan Cox and Woody Suwalski respectively.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     The author(s) of this software shall not be held liable for damages
- *     of any nature resulting due to the use of this software. This
- *     software is provided AS-IS with no warranties.
- *
- *     Changelog:
- *     20020220 Zwane Mwaikambo        Code based on datasheet, no hardware.
- *     20020221 Zwane Mwaikambo        Cleanups as suggested by Jeff Garzik and Alan Cox.
- *     20020222 Zwane Mwaikambo        Added probing.
- *     20020225 Zwane Mwaikambo        Added ISAPNP support.
- *     20020412 Rob Radez              Broke out start/stop functions
- *              <rob@osinvestor.com>   Return proper status instead of temperature warning
- *                                     Add WDIOC_GETBOOTSTATUS and WDIOC_SETOPTIONS ioctls
- *                                     Fix CONFIG_WATCHDOG_NOWAYOUT
- *     20020530 Joel Becker            Add Matt Domsch's nowayout module option
- *     20030116 Adam Belay             Updated to the latest pnp code
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pnp.h>
-#include <linux/fs.h>
-
-#include <asm/semaphore.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define SC1200_MODULE_VER      "build 20020303"
-#define SC1200_MODULE_NAME     "sc1200wdt"
-#define PFX                    SC1200_MODULE_NAME ": "
-
-#define        MAX_TIMEOUT     255     /* 255 minutes */
-#define PMIR           (io)    /* Power Management Index Register */
-#define PMDR           (io+1)  /* Power Management Data Register */
-
-/* Data Register indexes */
-#define FER1           0x00    /* Function enable register 1 */
-#define FER2           0x01    /* Function enable register 2 */
-#define PMC1           0x02    /* Power Management Ctrl 1 */
-#define PMC2           0x03    /* Power Management Ctrl 2 */
-#define PMC3           0x04    /* Power Management Ctrl 3 */
-#define WDTO           0x05    /* Watchdog timeout register */
-#define        WDCF            0x06    /* Watchdog config register */
-#define WDST           0x07    /* Watchdog status register */
-
-/* WDCF bitfields - which devices assert WDO */
-#define KBC_IRQ                0x01    /* Keyboard Controller */
-#define MSE_IRQ                0x02    /* Mouse */
-#define UART1_IRQ      0x03    /* Serial0 */
-#define UART2_IRQ      0x04    /* Serial1 */
-/* 5 -7 are reserved */
-
-static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER;
-static int timeout = 1;
-static int io = -1;
-static int io_len = 2;         /* for non plug and play */
-static struct semaphore open_sem;
-static char expect_close;
-static spinlock_t sc1200wdt_lock;      /* io port access serialisation */
-
-#if defined CONFIG_PNP
-static int isapnp = 1;
-static struct pnp_dev *wdt_dev;
-
-module_param(isapnp, int, 0);
-MODULE_PARM_DESC(isapnp, "When set to 0 driver ISA PnP support will be disabled");
-#endif
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "io port");
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
-
-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) ")");
-
-
-
-/* Read from Data Register */
-static inline void sc1200wdt_read_data(unsigned char index, unsigned char *data)
-{
-       spin_lock(&sc1200wdt_lock);
-       outb_p(index, PMIR);
-       *data = inb(PMDR);
-       spin_unlock(&sc1200wdt_lock);
-}
-
-
-/* Write to Data Register */
-static inline void sc1200wdt_write_data(unsigned char index, unsigned char data)
-{
-       spin_lock(&sc1200wdt_lock);
-       outb_p(index, PMIR);
-       outb(data, PMDR);
-       spin_unlock(&sc1200wdt_lock);
-}
-
-
-static void sc1200wdt_start(void)
-{
-       unsigned char reg;
-
-       sc1200wdt_read_data(WDCF, &reg);
-       /* assert WDO when any of the following interrupts are triggered too */
-       reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ);
-       sc1200wdt_write_data(WDCF, reg);
-       /* set the timeout and get the ball rolling */
-       sc1200wdt_write_data(WDTO, timeout);
-}
-
-
-static void sc1200wdt_stop(void)
-{
-       sc1200wdt_write_data(WDTO, 0);
-}
-
-
-/* This returns the status of the WDO signal, inactive high. */
-static inline int sc1200wdt_status(void)
-{
-       unsigned char ret;
-
-       sc1200wdt_read_data(WDST, &ret);
-       /* If the bit is inactive, the watchdog is enabled, so return
-        * KEEPALIVEPING which is a bit of a kludge because there's nothing
-        * else for enabled/disabled status
-        */
-       return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING;  /* bits 1 - 7 are undefined */
-}
-
-
-static int sc1200wdt_open(struct inode *inode, struct file *file)
-{
-       /* allow one at a time */
-       if (down_trylock(&open_sem))
-               return -EBUSY;
-
-       if (timeout > MAX_TIMEOUT)
-               timeout = MAX_TIMEOUT;
-
-       sc1200wdt_start();
-       printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
-
-       return nonseekable_open(inode, file);
-}
-
-
-static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       int new_timeout;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 0,
-               .identity = "PC87307/PC97307",
-       };
-
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user(argp, &ident, sizeof ident))
-                               return -EFAULT;
-                       return 0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user(sc1200wdt_status(), p);
-
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-
-               case WDIOC_KEEPALIVE:
-                       sc1200wdt_write_data(WDTO, timeout);
-                       return 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       /* the API states this is given in secs */
-                       new_timeout /= 60;
-                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       sc1200wdt_write_data(WDTO, timeout);
-                       /* fall through and return the new timeout */
-
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout * 60, p);
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int options, retval = -EINVAL;
-
-                       if (get_user(options, p))
-                               return -EFAULT;
-
-                       if (options & WDIOS_DISABLECARD) {
-                               sc1200wdt_stop();
-                               retval = 0;
-                       }
-
-                       if (options & WDIOS_ENABLECARD) {
-                               sc1200wdt_start();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-       }
-}
-
-
-static int sc1200wdt_release(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               sc1200wdt_stop();
-               printk(KERN_INFO PFX "Watchdog disabled\n");
-       } else {
-               sc1200wdt_write_data(WDTO, timeout);
-               printk(KERN_CRIT PFX "Unexpected close!, timeout = %d min(s)\n", timeout);
-       }
-       up(&open_sem);
-       expect_close = 0;
-
-       return 0;
-}
-
-
-static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
-{
-       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;
-                       }
-               }
-
-               sc1200wdt_write_data(WDTO, timeout);
-               return len;
-       }
-
-       return 0;
-}
-
-
-static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               sc1200wdt_stop();
-
-       return NOTIFY_DONE;
-}
-
-
-static struct notifier_block sc1200wdt_notifier =
-{
-       .notifier_call =        sc1200wdt_notify_sys,
-};
-
-static const struct file_operations sc1200wdt_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = sc1200wdt_write,
-       .ioctl          = sc1200wdt_ioctl,
-       .open           = sc1200wdt_open,
-       .release        = sc1200wdt_release,
-};
-
-static struct miscdevice sc1200wdt_miscdev =
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &sc1200wdt_fops,
-};
-
-
-static int __init sc1200wdt_probe(void)
-{
-       /* The probe works by reading the PMC3 register's default value of 0x0e
-        * there is one caveat, if the device disables the parallel port or any
-        * of the UARTs we won't be able to detect it.
-        * Nb. This could be done with accuracy by reading the SID registers, but
-        * we don't have access to those io regions.
-        */
-
-       unsigned char reg;
-
-       sc1200wdt_read_data(PMC3, &reg);
-       reg &= 0x0f;                            /* we don't want the UART busy bits */
-       return (reg == 0x0e) ? 0 : -ENODEV;
-}
-
-
-#if defined CONFIG_PNP
-
-static struct pnp_device_id scl200wdt_pnp_devices[] = {
-       /* National Semiconductor PC87307/PC97307 watchdog component */
-       {.id = "NSC0800", .driver_data = 0},
-       {.id = ""},
-};
-
-static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
-{
-       /* this driver only supports one card at a time */
-       if (wdt_dev || !isapnp)
-               return -EBUSY;
-
-       wdt_dev = dev;
-       io = pnp_port_start(wdt_dev, 0);
-       io_len = pnp_port_len(wdt_dev, 0);
-
-       if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
-               return -EBUSY;
-       }
-
-       printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n", io, io_len);
-       return 0;
-}
-
-static void scl200wdt_pnp_remove(struct pnp_dev * dev)
-{
-       if (wdt_dev){
-               release_region(io, io_len);
-               wdt_dev = NULL;
-       }
-}
-
-static struct pnp_driver scl200wdt_pnp_driver = {
-       .name           = "scl200wdt",
-       .id_table       = scl200wdt_pnp_devices,
-       .probe          = scl200wdt_pnp_probe,
-       .remove         = scl200wdt_pnp_remove,
-};
-
-#endif /* CONFIG_PNP */
-
-
-static int __init sc1200wdt_init(void)
-{
-       int ret;
-
-       printk("%s\n", banner);
-
-       spin_lock_init(&sc1200wdt_lock);
-       sema_init(&open_sem, 1);
-
-#if defined CONFIG_PNP
-       if (isapnp) {
-               ret = pnp_register_driver(&scl200wdt_pnp_driver);
-               if (ret)
-                       goto out_clean;
-       }
-#endif
-
-       if (io == -1) {
-               printk(KERN_ERR PFX "io parameter must be specified\n");
-               ret = -EINVAL;
-               goto out_pnp;
-       }
-
-#if defined CONFIG_PNP
-       /* now that the user has specified an IO port and we haven't detected
-        * any devices, disable pnp support */
-       isapnp = 0;
-       pnp_unregister_driver(&scl200wdt_pnp_driver);
-#endif
-
-       if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
-               ret = -EBUSY;
-               goto out_pnp;
-       }
-
-       ret = sc1200wdt_probe();
-       if (ret)
-               goto out_io;
-
-       ret = register_reboot_notifier(&sc1200wdt_notifier);
-       if (ret) {
-               printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret);
-               goto out_io;
-       }
-
-       ret = misc_register(&sc1200wdt_miscdev);
-       if (ret) {
-               printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
-               goto out_rbt;
-       }
-
-       /* ret = 0 */
-
-out_clean:
-       return ret;
-
-out_rbt:
-       unregister_reboot_notifier(&sc1200wdt_notifier);
-
-out_io:
-       release_region(io, io_len);
-
-out_pnp:
-#if defined CONFIG_PNP
-       if (isapnp)
-               pnp_unregister_driver(&scl200wdt_pnp_driver);
-#endif
-       goto out_clean;
-}
-
-
-static void __exit sc1200wdt_exit(void)
-{
-       misc_deregister(&sc1200wdt_miscdev);
-       unregister_reboot_notifier(&sc1200wdt_notifier);
-
-#if defined CONFIG_PNP
-       if(isapnp)
-               pnp_unregister_driver(&scl200wdt_pnp_driver);
-       else
-#endif
-       release_region(io, io_len);
-}
-
-module_init(sc1200wdt_init);
-module_exit(sc1200wdt_exit);
-
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
-MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
deleted file mode 100644 (file)
index e8594c6..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- *     AMD Elan SC520 processor Watchdog Timer driver
- *
- *      Based on acquirewdt.c by Alan Cox,
- *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@unthought.net>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     The authors do NOT admit liability nor provide warranty for
- *     any of this software. This material is provided "AS-IS" in
- *      the hope that it may be useful for others.
- *
- *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
- *           9/27 - 2001      [Initial release]
- *
- *     Additional fixes Alan Cox
- *     -       Fixed formatting
- *     -       Removed debug printks
- *     -       Fixed SMP built kernel deadlock
- *     -       Switched to private locks not lock_kernel
- *     -       Used ioremap/writew/readw
- *     -       Added NOWAYOUT support
- *     4/12 - 2002 Changes by Rob Radez <rob@osinvestor.com>
- *     -       Change comments
- *     -       Eliminate fop_llseek
- *     -       Change CONFIG_WATCHDOG_NOWAYOUT semantics
- *     -       Add KERN_* tags to printks
- *     -       fix possible wdt_is_open race
- *     -       Report proper capabilities in watchdog_info
- *     -       Add WDIOC_{GETSTATUS, GETBOOTSTATUS, SETTIMEOUT,
- *             GETTIMEOUT, SETOPTIONS} ioctls
- *     09/8 - 2003 Changes by Wim Van Sebroeck <wim@iguana.be>
- *     -       cleanup of trailing spaces
- *     -       added extra printk's for startup problems
- *     -       use module_param
- *     -       made timeout (the emulated heartbeat) a module_param
- *     -       made the keepalive ping an internal subroutine
- *     3/27 - 2004 Changes by Sean Young <sean@mess.org>
- *     -       set MMCR_BASE to 0xfffef000
- *     -       CBAR does not need to be read
- *     -       removed debugging printks
- *
- *  This WDT driver is different from most other Linux WDT
- *  drivers in that the driver will ping the watchdog by itself,
- *  because this particular WDT has a very short timeout (1.6
- *  seconds) and it would be insane to count on any userspace
- *  daemon always getting scheduled within that time frame.
- *
- *  This driver uses memory mapped IO, and spinlock.
- */
-
-#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/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define OUR_NAME "sc520_wdt"
-#define PFX OUR_NAME ": "
-
-/*
- * The AMD Elan SC520 timeout value is 492us times a power of 2 (0-7)
- *
- *   0: 492us    2: 1.01s    4: 4.03s   6: 16.22s
- *   1: 503ms    3: 2.01s    5: 8.05s   7: 32.21s
- *
- * We will program the SC520 watchdog for a timeout of 2.01s.
- * If we reset the watchdog every ~250ms we should be safe.
- */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 30 seconds.
- */
-
-#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-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) ")");
-
-/*
- * AMD Elan SC520 - Watchdog Timer Registers
- */
-#define MMCR_BASE      0xfffef000      /* The default base address */
-#define OFFS_WDTMRCTL  0xCB0   /* Watchdog Timer Control Register */
-
-/* WDT Control Register bit definitions */
-#define WDT_EXP_SEL_01 0x0001  /* [01] Time-out = 496 us (with 33 Mhz clk). */
-#define WDT_EXP_SEL_02 0x0002  /* [02] Time-out = 508 ms (with 33 Mhz clk). */
-#define WDT_EXP_SEL_03 0x0004  /* [03] Time-out = 1.02 s (with 33 Mhz clk). */
-#define WDT_EXP_SEL_04 0x0008  /* [04] Time-out = 2.03 s (with 33 Mhz clk). */
-#define WDT_EXP_SEL_05 0x0010  /* [05] Time-out = 4.07 s (with 33 Mhz clk). */
-#define WDT_EXP_SEL_06 0x0020  /* [06] Time-out = 8.13 s (with 33 Mhz clk). */
-#define WDT_EXP_SEL_07 0x0040  /* [07] Time-out = 16.27s (with 33 Mhz clk). */
-#define WDT_EXP_SEL_08 0x0080  /* [08] Time-out = 32.54s (with 33 Mhz clk). */
-#define WDT_IRQ_FLG    0x1000  /* [12] Interrupt Request Flag */
-#define WDT_WRST_ENB   0x4000  /* [14] Watchdog Timer Reset Enable */
-#define WDT_ENB                0x8000  /* [15] Watchdog Timer Enable */
-
-static __u16 __iomem *wdtmrctl;
-
-static void wdt_timer_ping(unsigned long);
-static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
-static unsigned long next_heartbeat;
-static unsigned long wdt_is_open;
-static char wdt_expect_close;
-static spinlock_t wdt_spinlock;
-
-/*
- *     Whack the dog
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT
-        */
-       if(time_before(jiffies, next_heartbeat))
-       {
-               /* Ping the WDT */
-               spin_lock(&wdt_spinlock);
-               writew(0xAAAA, wdtmrctl);
-               writew(0x5555, wdtmrctl);
-               spin_unlock(&wdt_spinlock);
-
-               /* Re-set the timer interval */
-               mod_timer(&timer, jiffies + WDT_INTERVAL);
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-/*
- *     Utility routines
- */
-
-static void wdt_config(int writeval)
-{
-       __u16 dummy;
-       unsigned long flags;
-
-       /* buy some time (ping) */
-       spin_lock_irqsave(&wdt_spinlock, flags);
-       dummy=readw(wdtmrctl);  /* ensure write synchronization */
-       writew(0xAAAA, wdtmrctl);
-       writew(0x5555, wdtmrctl);
-       /* unlock WDT = make WDT configuration register writable one time */
-       writew(0x3333, wdtmrctl);
-       writew(0xCCCC, wdtmrctl);
-       /* write WDT configuration register */
-       writew(writeval, wdtmrctl);
-       spin_unlock_irqrestore(&wdt_spinlock, flags);
-}
-
-static int wdt_startup(void)
-{
-       next_heartbeat = jiffies + (timeout * HZ);
-
-       /* Start the timer */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-
-       /* Start the watchdog */
-       wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
-
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
-       return 0;
-}
-
-static int wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer(&timer);
-
-       /* Stop the watchdog */
-       wdt_config(0);
-
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
-       return 0;
-}
-
-static int wdt_keepalive(void)
-{
-       /* user land ping */
-       next_heartbeat = jiffies + (timeout * HZ);
-       return 0;
-}
-
-static int wdt_set_heartbeat(int t)
-{
-       if ((t < 1) || (t > 3600))      /* arbitrary upper limit */
-               return -EINVAL;
-
-       timeout = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count) {
-               if (!nowayout) {
-                       size_t ofs;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       wdt_expect_close = 0;
-
-                       /* now scan */
-                       for(ofs = 0; ofs != count; ofs++) {
-                               char c;
-                               if (get_user(c, buf + ofs))
-                                       return -EFAULT;
-                               if(c == 'V')
-                                       wdt_expect_close = 42;
-                       }
-               }
-
-               /* Well, anyhow someone wrote to us, we should return that favour */
-               wdt_keepalive();
-       }
-       return count;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       /* Just in case we're already talking to someone... */
-       if(test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Good, fire up the show */
-       wdt_startup();
-       return nonseekable_open(inode, file);
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(wdt_expect_close == 42) {
-               wdt_turnoff();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               wdt_keepalive();
-       }
-       clear_bit(0, &wdt_is_open);
-       wdt_expect_close = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "SC520",
-       };
-
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               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:
-                       wdt_keepalive();
-                       return 0;
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if(get_user(new_options, p))
-                               return -EFAULT;
-
-                       if(new_options & WDIOS_DISABLECARD) {
-                               wdt_turnoff();
-                               retval = 0;
-                       }
-
-                       if(new_options & WDIOS_ENABLECARD) {
-                               wdt_startup();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_timeout;
-
-                       if(get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       if(wdt_set_heartbeat(new_timeout))
-                               return -EINVAL;
-
-                       wdt_keepalive();
-                       /* Fall through */
-               }
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout, p);
-       }
-}
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = fop_write,
-       .open           = fop_open,
-       .release        = fop_close,
-       .ioctl          = fop_ioctl,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wdt_fops,
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-               wdt_turnoff();
-       return NOTIFY_DONE;
-}
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
-       .notifier_call = wdt_notify_sys,
-};
-
-static void __exit sc520_wdt_unload(void)
-{
-       if (!nowayout)
-               wdt_turnoff();
-
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-       unregister_reboot_notifier(&wdt_notifier);
-       iounmap(wdtmrctl);
-}
-
-static int __init sc520_wdt_init(void)
-{
-       int rc = -EBUSY;
-
-       spin_lock_init(&wdt_spinlock);
-
-       /* Check that the timeout value is within it's range ; if not reset to the default */
-       if (wdt_set_heartbeat(timeout)) {
-               wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n",
-                       WATCHDOG_TIMEOUT);
-       }
-
-       wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
-       if (!wdtmrctl) {
-               printk(KERN_ERR PFX "Unable to remap memory\n");
-               rc = -ENOMEM;
-               goto err_out_region2;
-       }
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc) {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_ioremap;
-       }
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, rc);
-               goto err_out_notifier;
-       }
-
-       printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
-               timeout,nowayout);
-
-       return 0;
-
-err_out_notifier:
-       unregister_reboot_notifier(&wdt_notifier);
-err_out_ioremap:
-       iounmap(wdtmrctl);
-err_out_region2:
-       return rc;
-}
-
-module_init(sc520_wdt_init);
-module_exit(sc520_wdt_unload);
-
-MODULE_AUTHOR("Scott and Bill Jennings");
-MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
deleted file mode 100644 (file)
index d4fd0fa..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/* drivers/char/watchdog/scx200_wdt.c
-
-   National Semiconductor SCx200 Watchdog support
-
-   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
-
-   Some code taken from:
-   National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
-   (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The author(s) of this software shall not be held liable for damages
-   of any nature resulting due to the use of this software. This
-   software is provided AS-IS with no warranties. */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/scx200.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define NAME "scx200_wdt"
-
-MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
-MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-static int margin = 60;                /* in seconds */
-module_param(margin, int, 0);
-MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
-
-static u16 wdto_restart;
-static struct semaphore open_semaphore;
-static char expect_close;
-
-/* Bits of the WDCNFG register */
-#define W_ENABLE 0x00fa                /* Enable watchdog */
-#define W_DISABLE 0x0000       /* Disable watchdog */
-
-/* The scaling factor for the timer, this depends on the value of W_ENABLE */
-#define W_SCALE (32768/1024)
-
-static void scx200_wdt_ping(void)
-{
-       outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
-}
-
-static void scx200_wdt_update_margin(void)
-{
-       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
-       wdto_restart = margin * W_SCALE;
-}
-
-static void scx200_wdt_enable(void)
-{
-       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
-              wdto_restart);
-
-       outw(0, scx200_cb_base + SCx200_WDT_WDTO);
-       outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
-       outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
-
-       scx200_wdt_ping();
-}
-
-static void scx200_wdt_disable(void)
-{
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
-
-       outw(0, scx200_cb_base + SCx200_WDT_WDTO);
-       outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
-       outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
-}
-
-static int scx200_wdt_open(struct inode *inode, struct file *file)
-{
-       /* only allow one at a time */
-       if (down_trylock(&open_semaphore))
-               return -EBUSY;
-       scx200_wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static int scx200_wdt_release(struct inode *inode, struct file *file)
-{
-       if (expect_close != 42) {
-               printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
-       } else if (!nowayout) {
-               scx200_wdt_disable();
-       }
-       expect_close = 0;
-       up(&open_semaphore);
-
-       return 0;
-}
-
-static int scx200_wdt_notify_sys(struct notifier_block *this,
-                                     unsigned long code, void *unused)
-{
-       if (code == SYS_HALT || code == SYS_POWER_OFF)
-               if (!nowayout)
-                       scx200_wdt_disable();
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block scx200_wdt_notifier =
-{
-       .notifier_call = scx200_wdt_notify_sys,
-};
-
-static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
-                                    size_t len, loff_t *ppos)
-{
-       /* check for a magic close character */
-       if (len)
-       {
-               size_t i;
-
-               scx200_wdt_ping();
-
-               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;
-               }
-
-               return len;
-       }
-
-       return 0;
-}
-
-static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .identity = "NatSemi SCx200 Watchdog",
-               .firmware_version = 1,
-               .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
-       };
-       int new_margin;
-
-       switch (cmd) {
-       default:
-               return -ENOTTY;
-       case WDIOC_GETSUPPORT:
-               if(copy_to_user(argp, &ident, sizeof(ident)))
-                       return -EFAULT;
-               return 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               if (put_user(0, p))
-                       return -EFAULT;
-               return 0;
-       case WDIOC_KEEPALIVE:
-               scx200_wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, p))
-                       return -EFAULT;
-               if (new_margin < 1)
-                       return -EINVAL;
-               margin = new_margin;
-               scx200_wdt_update_margin();
-               scx200_wdt_ping();
-       case WDIOC_GETTIMEOUT:
-               if (put_user(margin, p))
-                       return -EFAULT;
-               return 0;
-       }
-}
-
-static const struct file_operations scx200_wdt_fops = {
-       .owner   = THIS_MODULE,
-       .llseek  = no_llseek,
-       .write   = scx200_wdt_write,
-       .ioctl   = scx200_wdt_ioctl,
-       .open    = scx200_wdt_open,
-       .release = scx200_wdt_release,
-};
-
-static struct miscdevice scx200_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name  = "watchdog",
-       .fops  = &scx200_wdt_fops,
-};
-
-static int __init scx200_wdt_init(void)
-{
-       int r;
-
-       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
-
-       /* check that we have found the configuration block */
-       if (!scx200_cb_present())
-               return -ENODEV;
-
-       if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
-                           SCx200_WDT_SIZE,
-                           "NatSemi SCx200 Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
-               return -EBUSY;
-       }
-
-       scx200_wdt_update_margin();
-       scx200_wdt_disable();
-
-       sema_init(&open_semaphore, 1);
-
-       r = misc_register(&scx200_wdt_miscdev);
-       if (r) {
-               release_region(scx200_cb_base + SCx200_WDT_OFFSET,
-                               SCx200_WDT_SIZE);
-               return r;
-       }
-
-       r = register_reboot_notifier(&scx200_wdt_notifier);
-       if (r) {
-               printk(KERN_ERR NAME ": unable to register reboot notifier");
-               misc_deregister(&scx200_wdt_miscdev);
-               release_region(scx200_cb_base + SCx200_WDT_OFFSET,
-                               SCx200_WDT_SIZE);
-               return r;
-       }
-
-       return 0;
-}
-
-static void __exit scx200_wdt_cleanup(void)
-{
-       unregister_reboot_notifier(&scx200_wdt_notifier);
-       misc_deregister(&scx200_wdt_miscdev);
-       release_region(scx200_cb_base + SCx200_WDT_OFFSET,
-                      SCx200_WDT_SIZE);
-}
-
-module_init(scx200_wdt_init);
-module_exit(scx200_wdt_cleanup);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
deleted file mode 100644 (file)
index cecbedd..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * drivers/char/watchdog/shwdt.c
- *
- * Watchdog driver for integrated watchdog in the SuperH processors.
- *
- * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *
- * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
- *     Added expect close support, made emulated timeout runtime changeable
- *     general cleanups, add some ioctls
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/ioport.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/watchdog.h>
-
-#define PFX "shwdt: "
-
-/*
- * Default clock division ratio is 5.25 msecs. For an additional table of
- * values, consult the asm-sh/watchdog.h. Overload this at module load
- * time.
- *
- * In order for this to work reliably we need to have HZ set to 1000 or
- * something quite higher than 100 (or we need a proper high-res timer
- * implementation that will deal with this properly), otherwise the 10ms
- * resolution of a jiffy is enough to trigger the overflow. For things like
- * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
- * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
- * necssary.
- *
- * As a result of this timing problem, the only modes that are particularly
- * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms
- * overflow periods respectively.
- *
- * Also, since we can't really expect userspace to be responsive enough
- * before the overflow happens, we maintain two seperate timers .. One in
- * the kernel for clearing out WOVF every 2ms or so (again, this depends on
- * HZ == 1000), and another for monitoring userspace writes to the WDT device.
- *
- * As such, we currently use a configurable heartbeat interval which defaults
- * to 30s. In this case, the userspace daemon is only responsible for periodic
- * writes to the device before the next heartbeat is scheduled. If the daemon
- * misses its deadline, the kernel timer will allow the WDT to overflow.
- */
-static int clock_division_ratio = WTCSR_CKS_4096;
-
-#define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
-
-static void sh_wdt_ping(unsigned long data);
-
-static unsigned long shwdt_is_open;
-static struct watchdog_info sh_wdt_info;
-static char shwdt_expect_close;
-static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
-static unsigned long next_heartbeat;
-
-#define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
-static int heartbeat = WATCHDOG_HEARTBEAT;     /* in seconds */
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-/**
- *     sh_wdt_start - Start the Watchdog
- *
- *     Starts the watchdog.
- */
-static void sh_wdt_start(void)
-{
-       __u8 csr;
-
-       next_heartbeat = jiffies + (heartbeat * HZ);
-       mod_timer(&timer, next_ping_period(clock_division_ratio));
-
-       csr = sh_wdt_read_csr();
-       csr |= WTCSR_WT | clock_division_ratio;
-       sh_wdt_write_csr(csr);
-
-       sh_wdt_write_cnt(0);
-
-       /*
-        * These processors have a bit of an inconsistent initialization
-        * process.. starting with SH-3, RSTS was moved to WTCSR, and the
-        * RSTCSR register was removed.
-        *
-        * On the SH-2 however, in addition with bits being in different
-        * locations, we must deal with RSTCSR outright..
-        */
-       csr = sh_wdt_read_csr();
-       csr |= WTCSR_TME;
-       csr &= ~WTCSR_RSTS;
-       sh_wdt_write_csr(csr);
-
-#ifdef CONFIG_CPU_SH2
-       /*
-        * Whoever came up with the RSTCSR semantics must've been smoking
-        * some of the good stuff, since in addition to the WTCSR/WTCNT write
-        * brain-damage, it's managed to fuck things up one step further..
-        *
-        * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
-        * but if we want to touch RSTE or RSTS, the upper byte has to be
-        * 0x5a..
-        */
-       csr = sh_wdt_read_rstcsr();
-       csr &= ~RSTCSR_RSTS;
-       sh_wdt_write_rstcsr(csr);
-#endif
-}
-
-/**
- *     sh_wdt_stop - Stop the Watchdog
- *     Stops the watchdog.
- */
-static void sh_wdt_stop(void)
-{
-       __u8 csr;
-
-       del_timer(&timer);
-
-       csr = sh_wdt_read_csr();
-       csr &= ~WTCSR_TME;
-       sh_wdt_write_csr(csr);
-}
-
-/**
- *     sh_wdt_keepalive - Keep the Userspace Watchdog Alive
- *     The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
- */
-static inline void sh_wdt_keepalive(void)
-{
-       next_heartbeat = jiffies + (heartbeat * HZ);
-}
-
-/**
- *     sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
- *     Set the Userspace Watchdog heartbeat
- */
-static int sh_wdt_set_heartbeat(int t)
-{
-       if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
-               return -EINVAL;
-
-       heartbeat = t;
-       return 0;
-}
-
-/**
- *     sh_wdt_ping - Ping the Watchdog
- *     @data: Unused
- *
- *     Clears overflow bit, resets timer counter.
- */
-static void sh_wdt_ping(unsigned long data)
-{
-       if (time_before(jiffies, next_heartbeat)) {
-               __u8 csr;
-
-               csr = sh_wdt_read_csr();
-               csr &= ~WTCSR_IOVF;
-               sh_wdt_write_csr(csr);
-
-               sh_wdt_write_cnt(0);
-
-               mod_timer(&timer, next_ping_period(clock_division_ratio));
-       } else
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
-                      "the watchdog\n");
-}
-
-/**
- *     sh_wdt_open - Open the Device
- *     @inode: inode of device
- *     @file: file handle of device
- *
- *     Watchdog device is opened and started.
- */
-static int sh_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &shwdt_is_open))
-               return -EBUSY;
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       sh_wdt_start();
-
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     sh_wdt_close - Close the Device
- *     @inode: inode of device
- *     @file: file handle of device
- *
- *     Watchdog device is closed and stopped.
- */
-static int sh_wdt_close(struct inode *inode, struct file *file)
-{
-       if (shwdt_expect_close == 42) {
-               sh_wdt_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not "
-                      "stopping watchdog!\n");
-               sh_wdt_keepalive();
-       }
-
-       clear_bit(0, &shwdt_is_open);
-       shwdt_expect_close = 0;
-
-       return 0;
-}
-
-/**
- *     sh_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 sh_wdt_write(struct file *file, const char *buf,
-                           size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       shwdt_expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       shwdt_expect_close = 42;
-                       }
-               }
-               sh_wdt_keepalive();
-       }
-
-       return count;
-}
-
-/**
- *     sh_wdt_mmap - map WDT/CPG registers into userspace
- *     @file: file structure for the device
- *     @vma: VMA to map the registers into
- *
- *     A simple mmap() implementation for the corner cases where the counter
- *     needs to be mapped in userspace directly. Due to the relatively small
- *     size of the area, neighbouring registers not necessarily tied to the
- *     CPG will also be accessible through the register page, so this remains
- *     configurable for users that really know what they're doing.
- *
- *     Additionaly, the register page maps in the CPG register base relative
- *     to the nearest page-aligned boundary, which requires that userspace do
- *     the appropriate CPU subtype math for calculating the page offset for
- *     the counter value.
- */
-static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       int ret = -ENOSYS;
-
-#ifdef CONFIG_SH_WDT_MMAP
-       unsigned long addr;
-
-       /* Only support the simple cases where we map in a register page. */
-       if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
-               return -EINVAL;
-
-       /*
-        * Pick WTCNT as the start, it's usually the first register after the
-        * FRQCR, and neither one are generally page-aligned out of the box.
-        */
-       addr = WTCNT & ~(PAGE_SIZE - 1);
-
-       vma->vm_flags |= VM_IO;
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
-                              PAGE_SIZE, vma->vm_page_prot)) {
-               printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
-                      __FUNCTION__);
-               return -EAGAIN;
-       }
-
-       ret = 0;
-#endif
-
-       return ret;
-}
-
-/**
- *     sh_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 sh_wdt_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
-{
-       int new_heartbeat;
-       int options, retval = -EINVAL;
-
-       switch (cmd) {
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg,
-                                         &sh_wdt_info,
-                                         sizeof(sh_wdt_info)) ? -EFAULT : 0;
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, (int *)arg);
-               case WDIOC_KEEPALIVE:
-                       sh_wdt_keepalive();
-                       return 0;
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_heartbeat, (int *)arg))
-                               return -EFAULT;
-
-                       if (sh_wdt_set_heartbeat(new_heartbeat))
-                               return -EINVAL;
-
-                       sh_wdt_keepalive();
-                       /* Fall */
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, (int *)arg);
-               case WDIOC_SETOPTIONS:
-                       if (get_user(options, (int *)arg))
-                               return -EFAULT;
-
-                       if (options & WDIOS_DISABLECARD) {
-                               sh_wdt_stop();
-                               retval = 0;
-                       }
-
-                       if (options & WDIOS_ENABLECARD) {
-                               sh_wdt_start();
-                               retval = 0;
-                       }
-
-                       return retval;
-               default:
-                       return -ENOTTY;
-       }
-
-       return 0;
-}
-
-/**
- *     sh_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 sh_wdt_notify_sys(struct notifier_block *this,
-                            unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-               sh_wdt_stop();
-
-       return NOTIFY_DONE;
-}
-
-static const struct file_operations sh_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = sh_wdt_write,
-       .ioctl          = sh_wdt_ioctl,
-       .open           = sh_wdt_open,
-       .release        = sh_wdt_close,
-       .mmap           = sh_wdt_mmap,
-};
-
-static struct watchdog_info sh_wdt_info = {
-       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
-                                 WDIOF_MAGICCLOSE,
-       .firmware_version       = 1,
-       .identity               = "SH WDT",
-};
-
-static struct notifier_block sh_wdt_notifier = {
-       .notifier_call          = sh_wdt_notify_sys,
-};
-
-static struct miscdevice sh_wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &sh_wdt_fops,
-};
-
-/**
- *     sh_wdt_init - Initialize module
- *     Registers the device and notifier handler. Actual device
- *     initialization is handled by sh_wdt_open().
- */
-static int __init sh_wdt_init(void)
-{
-       int rc;
-
-       if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
-               clock_division_ratio = WTCSR_CKS_4096;
-               printk(KERN_INFO PFX "clock_division_ratio value must "
-                      "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
-       }
-
-       rc = sh_wdt_set_heartbeat(heartbeat);
-       if (unlikely(rc)) {
-               heartbeat = WATCHDOG_HEARTBEAT;
-               printk(KERN_INFO PFX "heartbeat value must "
-                      "be 1<=x<=3600, using %d\n", heartbeat);
-       }
-
-       rc = register_reboot_notifier(&sh_wdt_notifier);
-       if (unlikely(rc)) {
-               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
-                      rc);
-               return rc;
-       }
-
-       rc = misc_register(&sh_wdt_miscdev);
-       if (unlikely(rc)) {
-               printk(KERN_ERR PFX "Can't register miscdev on "
-                      "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
-               unregister_reboot_notifier(&sh_wdt_notifier);
-               return rc;
-       }
-
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-
-       return 0;
-}
-
-/**
- *     sh_wdt_exit - Deinitialize module
- *     Unregisters the device and notifier handler. Actual device
- *     deinitialization is handled by sh_wdt_close().
- */
-static void __exit sh_wdt_exit(void)
-{
-       misc_deregister(&sh_wdt_miscdev);
-       unregister_reboot_notifier(&sh_wdt_notifier);
-}
-
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
-MODULE_DESCRIPTION("SuperH watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-module_param(clock_division_ratio, int, 0);
-MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-module_init(sh_wdt_init);
-module_exit(sh_wdt_exit);
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c
deleted file mode 100644 (file)
index d3cb0a7..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- *     SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x
- *
- *      Based on acquirewdt.c by Alan Cox <alan@redhat.com>
- *       and some other existing drivers
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     The authors do NOT admit liability nor provide warranty for
- *     any of this software. This material is provided "AS-IS" in
- *      the hope that it may be useful for others.
- *
- *     (C) Copyright 2003-2006  Sven Anders <anders@anduras.de>
- *
- *  History:
- *     2003 - Created version 1.0 for Linux 2.4.x.
- *     2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE
- *             features. Released version 1.1
- *
- *  Theory of operation:
- *
- *      A Watchdog Timer (WDT) is a hardware circuit that can
- *      reset the computer system in case of a software fault.
- *      You probably knew that already.
- *
- *      Usually a userspace daemon will notify the kernel WDT driver
- *      via the /dev/watchdog special device file that userspace is
- *      still alive, at regular intervals.  When such a notification
- *      occurs, the driver will usually tell the hardware watchdog
- *      that everything is in order, and that the watchdog should wait
- *      for yet another little while to reset the system.
- *      If userspace fails (RAM error, kernel bug, whatever), the
- *      notifications cease to occur, and the hardware watchdog will
- *      reset the system (causing a reboot) after the timeout occurs.
- *
- * Create device with:
- *  mknod /dev/watchdog c 10 130
- *
- * For an example userspace keep-alive daemon, see:
- *   Documentation/watchdog/watchdog.txt
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* enable support for minutes as units? */
-/* (does not always work correctly, so disabled by default!) */
-#define SMSC_SUPPORT_MINUTES
-#undef SMSC_SUPPORT_MINUTES
-
-#define MAX_TIMEOUT     255
-
-#define UNIT_SECOND     0
-#define UNIT_MINUTE     1
-
-#define MODNAME                "smsc37b787_wdt: "
-#define VERSION         "1.1"
-
-#define IOPORT          0x3F0
-#define IOPORT_SIZE     2
-#define IODEV_NO        8
-
-static int unit = UNIT_SECOND;  /* timer's unit */
-static int timeout = 60;        /* timeout value: default is 60 "units" */
-static unsigned long timer_enabled = 0;   /* is the timer enabled? */
-
-static char expect_close;       /* is the close expected? */
-
-static spinlock_t io_lock;     /* to guard the watchdog from io races */
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-
-/* -- Low level function ----------------------------------------*/
-
-/* unlock the IO chip */
-
-static inline void open_io_config(void)
-{
-        outb(0x55, IOPORT);
-       mdelay(1);
-        outb(0x55, IOPORT);
-}
-
-/* lock the IO chip */
-static inline void close_io_config(void)
-{
-        outb(0xAA, IOPORT);
-}
-
-/* select the IO device */
-static inline void select_io_device(unsigned char devno)
-{
-        outb(0x07, IOPORT);
-        outb(devno, IOPORT+1);
-}
-
-/* write to the control register */
-static inline void write_io_cr(unsigned char reg, unsigned char data)
-{
-        outb(reg, IOPORT);
-        outb(data, IOPORT+1);
-}
-
-/* read from the control register */
-static inline char read_io_cr(unsigned char reg)
-{
-        outb(reg, IOPORT);
-        return inb(IOPORT+1);
-}
-
-/* -- Medium level functions ------------------------------------*/
-
-static inline void gpio_bit12(unsigned char reg)
-{
-       // -- General Purpose I/O Bit 1.2 --
-       // Bit 0,   In/Out: 0 = Output, 1 = Input
-       // Bit 1,   Polarity: 0 = No Invert, 1 = Invert
-       // Bit 2,   Group Enable Intr.: 0 = Disable, 1 = Enable
-       // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17,
-       //                           11 = Either Edge Triggered Intr. 2
-        // Bit 5/6  (Reserved)
-       // Bit 7,   Output Type: 0 = Push Pull Bit, 1 = Open Drain
-        write_io_cr(0xE2, reg);
-}
-
-static inline void gpio_bit13(unsigned char reg)
-{
-       // -- General Purpose I/O Bit 1.3 --
-       // Bit 0,  In/Out: 0 = Output, 1 = Input
-       // Bit 1,  Polarity: 0 = No Invert, 1 = Invert
-       // Bit 2,  Group Enable Intr.: 0 = Disable, 1 = Enable
-       // Bit 3,  Function select: 0 = GPI/O, 1 = LED
-        // Bit 4-6 (Reserved)
-       // Bit 7,  Output Type: 0 = Push Pull Bit, 1 = Open Drain
-        write_io_cr(0xE3, reg);
-}
-
-static inline void wdt_timer_units(unsigned char new_units)
-{
-       // -- Watchdog timer units --
-       // Bit 0-6 (Reserved)
-       // Bit 7,  WDT Time-out Value Units Select
-       //         (0 = Minutes, 1 = Seconds)
-        write_io_cr(0xF1, new_units);
-}
-
-static inline void wdt_timeout_value(unsigned char new_timeout)
-{
-       // -- Watchdog Timer Time-out Value --
-       // Bit 0-7 Binary coded units (0=Disabled, 1..255)
-        write_io_cr(0xF2, new_timeout);
-}
-
-static inline void wdt_timer_conf(unsigned char conf)
-{
-       // -- Watchdog timer configuration --
-       // Bit 0   Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O
-       // Bit 1   Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
-       // Bit 2   Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr.
-        // Bit 3   Reset the timer
-        //         (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled)
-       // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
-       //            0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
-        write_io_cr(0xF3, conf);
-}
-
-static inline void wdt_timer_ctrl(unsigned char reg)
-{
-       // -- Watchdog timer control --
-       // Bit 0   Status Bit: 0 = Timer counting, 1 = Timeout occured
-       // Bit 1   Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz
-       // Bit 2   Force Timeout: 1 = Forces WD timeout event (self-cleaning)
-       // Bit 3   P20 Force Timeout enabled:
-       //          0 = P20 activity does not generate the WD timeout event
-       //          1 = P20 Allows rising edge of P20, from the keyboard
-       //              controller, to force the WD timeout event.
-       // Bit 4   (Reserved)
-       // -- Soft power management --
-       // Bit 5   Stop Counter: 1 = Stop software power down counter
-       //            set via register 0xB8, (self-cleaning)
-       //            (Upon read: 0 = Counter running, 1 = Counter stopped)
-       // Bit 6   Restart Counter: 1 = Restart software power down counter
-       //            set via register 0xB8, (self-cleaning)
-       // Bit 7   SPOFF: 1 = Force software power down (self-cleaning)
-
-        write_io_cr(0xF4, reg);
-}
-
-/* -- Higher level functions ------------------------------------*/
-
-/* initialize watchdog */
-
-static void wb_smsc_wdt_initialize(void)
-{
-        unsigned char old;
-
-       spin_lock(&io_lock);
-        open_io_config();
-        select_io_device(IODEV_NO);
-
-       // enable the watchdog
-       gpio_bit13(0x08);  // Select pin 80 = LED not GPIO
-       gpio_bit12(0x0A);  // Set pin 79 = WDT not GPIO/Output/Polarity=Invert
-
-       // disable the timeout
-        wdt_timeout_value(0);
-
-       // reset control register
-        wdt_timer_ctrl(0x00);
-
-       // reset configuration register
-       wdt_timer_conf(0x00);
-
-       // read old (timer units) register
-        old = read_io_cr(0xF1) & 0x7F;
-        if (unit == UNIT_SECOND) old |= 0x80; // set to seconds
-
-       // set the watchdog timer units
-        wdt_timer_units(old);
-
-        close_io_config();
-       spin_unlock(&io_lock);
-}
-
-/* shutdown the watchdog */
-
-static void wb_smsc_wdt_shutdown(void)
-{
-       spin_lock(&io_lock);
-        open_io_config();
-        select_io_device(IODEV_NO);
-
-       // disable the watchdog
-        gpio_bit13(0x09);
-        gpio_bit12(0x09);
-
-       // reset watchdog config register
-       wdt_timer_conf(0x00);
-
-       // reset watchdog control register
-        wdt_timer_ctrl(0x00);
-
-       // disable timeout
-        wdt_timeout_value(0x00);
-
-        close_io_config();
-       spin_unlock(&io_lock);
-}
-
-/* set timeout => enable watchdog */
-
-static void wb_smsc_wdt_set_timeout(unsigned char new_timeout)
-{
-       spin_lock(&io_lock);
-        open_io_config();
-        select_io_device(IODEV_NO);
-
-       // set Power LED to blink, if we enable the timeout
-        wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02);
-
-       // set timeout value
-        wdt_timeout_value(new_timeout);
-
-        close_io_config();
-       spin_unlock(&io_lock);
-}
-
-/* get timeout */
-
-static unsigned char wb_smsc_wdt_get_timeout(void)
-{
-        unsigned char set_timeout;
-
-       spin_lock(&io_lock);
-        open_io_config();
-        select_io_device(IODEV_NO);
-        set_timeout = read_io_cr(0xF2);
-        close_io_config();
-       spin_unlock(&io_lock);
-
-        return set_timeout;
-}
-
-/* disable watchdog */
-
-static void wb_smsc_wdt_disable(void)
-{
-        // set the timeout to 0 to disable the watchdog
-        wb_smsc_wdt_set_timeout(0);
-}
-
-/* enable watchdog by setting the current timeout */
-
-static void wb_smsc_wdt_enable(void)
-{
-        // set the current timeout...
-        wb_smsc_wdt_set_timeout(timeout);
-}
-
-/* reset the timer */
-
-static void wb_smsc_wdt_reset_timer(void)
-{
-       spin_lock(&io_lock);
-        open_io_config();
-        select_io_device(IODEV_NO);
-
-       // reset the timer
-       wdt_timeout_value(timeout);
-       wdt_timer_conf(0x08);
-
-        close_io_config();
-       spin_unlock(&io_lock);
-}
-
-/* return, if the watchdog is enabled (timeout is set...) */
-
-static int wb_smsc_wdt_status(void)
-{
-       return (wb_smsc_wdt_get_timeout() == 0) ? 0 : WDIOF_KEEPALIVEPING;
-}
-
-
-/* -- File operations -------------------------------------------*/
-
-/* open => enable watchdog and set initial timeout */
-
-static int wb_smsc_wdt_open(struct inode *inode, struct file *file)
-{
-       /* /dev/watchdog can only be opened once */
-
-       if (test_and_set_bit(0, &timer_enabled))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       /* Reload and activate timer */
-       wb_smsc_wdt_enable();
-
-       printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
-
-       return nonseekable_open(inode, file);
-}
-
-/* close => shut off the timer */
-
-static int wb_smsc_wdt_release(struct inode *inode, struct file *file)
-{
-       /* Shut off the timer. */
-
-       if (expect_close == 42) {
-               wb_smsc_wdt_disable();
-               printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n");
-       } else {
-               printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n");
-               wb_smsc_wdt_reset_timer();
-       }
-
-       clear_bit(0, &timer_enabled);
-       expect_close = 0;
-       return 0;
-}
-
-/* write => update the timer to keep the machine alive */
-
-static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data,
-                                size_t len, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* reset expect flag */
-                       expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               wb_smsc_wdt_reset_timer();
-       }
-       return len;
-}
-
-/* ioctl => control interface */
-
-static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file,
-                            unsigned int cmd, unsigned long arg)
-{
-       int new_timeout;
-
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-
-       static struct watchdog_info ident = {
-               .options =              WDIOF_KEEPALIVEPING |
-                                       WDIOF_SETTIMEOUT |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "SMsC 37B787 Watchdog"
-       };
-
-       uarg.i = (int __user *)arg;
-
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(uarg.ident, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user(wb_smsc_wdt_status(), uarg.i);
-
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, uarg.i);
-
-               case WDIOC_KEEPALIVE:
-                       wb_smsc_wdt_reset_timer();
-                       return 0;
-
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_timeout, uarg.i))
-                               return -EFAULT;
-
-                       // the API states this is given in secs
-                       if (unit == UNIT_MINUTE)
-                         new_timeout /= 60;
-
-                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       wb_smsc_wdt_set_timeout(timeout);
-
-                       // fall through and return the new timeout...
-
-               case WDIOC_GETTIMEOUT:
-
-                       new_timeout = timeout;
-
-                       if (unit == UNIT_MINUTE)
-                         new_timeout *= 60;
-
-                       return put_user(new_timeout, uarg.i);
-
-               case WDIOC_SETOPTIONS:
-               {
-                       int options, retval = -EINVAL;
-
-                       if (get_user(options, uarg.i))
-                               return -EFAULT;
-
-                       if (options & WDIOS_DISABLECARD) {
-                               wb_smsc_wdt_disable();
-                               retval = 0;
-                       }
-
-                       if (options & WDIOS_ENABLECARD) {
-                               wb_smsc_wdt_enable();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-       }
-}
-
-/* -- Notifier funtions -----------------------------------------*/
-
-static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT)
-       {
-                // set timeout to 0, to avoid possible race-condition
-               timeout = 0;
-               wb_smsc_wdt_disable();
-       }
-       return NOTIFY_DONE;
-}
-
-/* -- Module's structures ---------------------------------------*/
-
-static const struct file_operations wb_smsc_wdt_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wb_smsc_wdt_write,
-       .ioctl          = wb_smsc_wdt_ioctl,
-       .open           = wb_smsc_wdt_open,
-       .release        = wb_smsc_wdt_release,
-};
-
-static struct notifier_block wb_smsc_wdt_notifier =
-{
-       .notifier_call  = wb_smsc_wdt_notify_sys,
-};
-
-static struct miscdevice wb_smsc_wdt_miscdev =
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &wb_smsc_wdt_fops,
-};
-
-/* -- Module init functions -------------------------------------*/
-
-/* module's "constructor" */
-
-static int __init wb_smsc_wdt_init(void)
-{
-       int ret;
-
-       spin_lock_init(&io_lock);
-
-       printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n");
-
-       if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
-               printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT);
-               ret = -EBUSY;
-               goto out_pnp;
-       }
-
-        // set new maximum, if it's too big
-        if (timeout > MAX_TIMEOUT)
-               timeout = MAX_TIMEOUT;
-
-        // init the watchdog timer
-        wb_smsc_wdt_initialize();
-
-       ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
-       if (ret) {
-               printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret);
-               goto out_io;
-       }
-
-       ret = misc_register(&wb_smsc_wdt_miscdev);
-       if (ret) {
-               printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
-               goto out_rbt;
-       }
-
-       // output info
-       printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
-       printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout);
-
-       // ret = 0
-
-out_clean:
-       return ret;
-
-out_rbt:
-       unregister_reboot_notifier(&wb_smsc_wdt_notifier);
-
-out_io:
-       release_region(IOPORT, IOPORT_SIZE);
-
-out_pnp:
-       goto out_clean;
-}
-
-/* module's "destructor" */
-
-static void __exit wb_smsc_wdt_exit(void)
-{
-       /* Stop the timer before we leave */
-       if (!nowayout)
-       {
-               wb_smsc_wdt_shutdown();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
-       }
-
-       misc_deregister(&wb_smsc_wdt_miscdev);
-       unregister_reboot_notifier(&wb_smsc_wdt_notifier);
-       release_region(IOPORT, IOPORT_SIZE);
-
-       printk("SMsC 37B787 watchdog component driver removed.\n");
-}
-
-module_init(wb_smsc_wdt_init);
-module_exit(wb_smsc_wdt_exit);
-
-MODULE_AUTHOR("Sven Anders <anders@anduras.de>");
-MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-#ifdef SMSC_SUPPORT_MINUTES
-module_param(unit, int, 0);
-MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0");
-#endif
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
-
-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/softdog.c b/drivers/char/watchdog/softdog.c
deleted file mode 100644 (file)
index 9c36949..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- *     SoftDog 0.07:   A Software Watchdog Device
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Software only watchdog driver. Unlike its big brother the WDT501P
- *     driver this won't always recover a failed machine.
- *
- *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
- *     Modularised.
- *     Added soft_margin; use upon insmod to change the timer delay.
- *     NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
- *         minors.
- *
- *  19980911 Alan Cox
- *     Made SMP safe for 2.3.x
- *
- *  20011127 Joel Becker (jlbec@evilplan.org>
- *     Added soft_noboot; Allows testing the softdog trigger without
- *     requiring a recompile.
- *     Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
- *
- *  20020530 Joel Becker <joel.becker@oracle.com>
- *     Added Matt Domsch's nowayout module option.
- */
-
-#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/jiffies.h>
-
-#include <asm/uaccess.h>
-
-#define PFX "SoftDog: "
-
-#define TIMER_MARGIN   60              /* Default is 60 seconds */
-static int soft_margin = TIMER_MARGIN; /* in seconds */
-module_param(soft_margin, int, 0);
-MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
-
-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) ")");
-
-#ifdef ONLY_TESTING
-static int soft_noboot = 1;
-#else
-static int soft_noboot = 0;
-#endif  /* ONLY_TESTING */
-
-module_param(soft_noboot, int, 0);
-MODULE_PARM_DESC(soft_noboot, "Softdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
-
-/*
- *     Our timer
- */
-
-static void watchdog_fire(unsigned long);
-
-static struct timer_list watchdog_ticktock =
-               TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long driver_open, orphan_timer;
-static char expect_close;
-
-
-/*
- *     If the timer expires..
- */
-
-static void watchdog_fire(unsigned long data)
-{
-       if (test_and_clear_bit(0, &orphan_timer))
-               module_put(THIS_MODULE);
-
-       if (soft_noboot)
-               printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
-       else
-       {
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
-               emergency_restart();
-               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
-       }
-}
-
-/*
- *     Softdog operations
- */
-
-static int softdog_keepalive(void)
-{
-       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
-       return 0;
-}
-
-static int softdog_stop(void)
-{
-       del_timer(&watchdog_ticktock);
-       return 0;
-}
-
-static int softdog_set_heartbeat(int t)
-{
-       if ((t < 0x0001) || (t > 0xFFFF))
-               return -EINVAL;
-
-       soft_margin = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int softdog_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &driver_open))
-               return -EBUSY;
-       if (!test_and_clear_bit(0, &orphan_timer))
-               __module_get(THIS_MODULE);
-       /*
-        *      Activate timer
-        */
-       softdog_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int softdog_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (expect_close == 42) {
-               softdog_stop();
-               module_put(THIS_MODULE);
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               set_bit(0, &orphan_timer);
-               softdog_keepalive();
-       }
-       clear_bit(0, &driver_open);
-       expect_close = 0;
-       return 0;
-}
-
-static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
-{
-       /*
-        *      Refresh the timer.
-        */
-       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;
-                       }
-               }
-               softdog_keepalive();
-       }
-       return len;
-}
-
-static int softdog_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "Software Watchdog",
-       };
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-               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:
-                       softdog_keepalive();
-                       return 0;
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_margin, p))
-                               return -EFAULT;
-                       if (softdog_set_heartbeat(new_margin))
-                               return -EINVAL;
-                       softdog_keepalive();
-                       /* Fall */
-               case WDIOC_GETTIMEOUT:
-                       return put_user(soft_margin, p);
-       }
-}
-
-/*
- *     Notifier for system down
- */
-
-static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the WDT off */
-               softdog_stop();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations softdog_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = softdog_write,
-       .ioctl          = softdog_ioctl,
-       .open           = softdog_open,
-       .release        = softdog_release,
-};
-
-static struct miscdevice softdog_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &softdog_fops,
-};
-
-static struct notifier_block softdog_notifier = {
-       .notifier_call  = softdog_notify_sys,
-};
-
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";
-
-static int __init watchdog_init(void)
-{
-       int ret;
-
-       /* Check that the soft_margin value is within it's range ; if not reset to the default */
-       if (softdog_set_heartbeat(soft_margin)) {
-               softdog_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n",
-                       TIMER_MARGIN);
-       }
-
-       ret = register_reboot_notifier(&softdog_notifier);
-       if (ret) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               return ret;
-       }
-
-       ret = misc_register(&softdog_miscdev);
-       if (ret) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               unregister_reboot_notifier(&softdog_notifier);
-               return ret;
-       }
-
-       printk(banner, soft_noboot, soft_margin, nowayout);
-
-       return 0;
-}
-
-static void __exit watchdog_exit(void)
-{
-       misc_deregister(&softdog_miscdev);
-       unregister_reboot_notifier(&softdog_notifier);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("Software Watchdog Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
deleted file mode 100644 (file)
index df33b3b..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- *     w83627hf/thf WDT driver
- *
- *     (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
- *             added support for W83627THF.
- *
- *     (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
- *
- *     Based on advantechwdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define WATCHDOG_NAME "w83627hf/thf/hg WDT"
-#define PFX WATCHDOG_NAME ": "
-#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
-
-static unsigned long wdt_is_open;
-static char expect_close;
-static spinlock_t io_lock;
-
-/* You must set this - there is no sane way to probe for this board. */
-static int wdt_io = 0x2E;
-module_param(wdt_io, int, 0);
-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 <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
-
-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) ")");
-
-/*
- *     Kernel methods.
- */
-
-#define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
-#define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register (same as EFER) */
-#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
-
-static void
-w83627hf_select_wd_register(void)
-{
-       unsigned char c;
-       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   */
-       c = inb(WDT_EFDR);
-       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);
-               outb_p(c, WDT_EFDR);    /* set GPIO3 to WDT0 */
-       }
-
-       outb_p(0x07, WDT_EFER); /* point to logical device number reg */
-       outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
-       outb_p(0x30, WDT_EFER); /* select CR30 */
-       outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
-}
-
-static void
-w83627hf_unselect_wd_register(void)
-{
-       outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
-}
-
-/* tyan motherboards seem to set F5 to 0x4C ?
- * So explicitly init to appropriate value. */
-static void
-w83627hf_init(void)
-{
-       unsigned char t;
-
-       w83627hf_select_wd_register();
-
-       outb_p(0xF6, WDT_EFER); /* Select CRF6 */
-       t=inb_p(WDT_EFDR);      /* read CRF6 */
-       if (t != 0) {
-               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();
-}
-
-static void
-wdt_ctrl(int timeout)
-{
-       spin_lock(&io_lock);
-
-       w83627hf_select_wd_register();
-
-       outb_p(0xF6, WDT_EFER);    /* Select CRF6 */
-       outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */
-
-       w83627hf_unselect_wd_register();
-
-       spin_unlock(&io_lock);
-}
-
-static int
-wdt_ping(void)
-{
-       wdt_ctrl(timeout);
-       return 0;
-}
-
-static int
-wdt_disable(void)
-{
-       wdt_ctrl(0);
-       return 0;
-}
-
-static int
-wdt_set_heartbeat(int t)
-{
-       if ((t < 1) || (t > 255))
-               return -EINVAL;
-
-       timeout = t;
-       return 0;
-}
-
-static ssize_t
-wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               wdt_ping();
-       }
-       return count;
-}
-
-static int
-wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_timeout;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "W83627HF WDT",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user(argp, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-         return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-         wdt_ping();
-         break;
-
-       case WDIOC_SETTIMEOUT:
-         if (get_user(new_timeout, p))
-                 return -EFAULT;
-         if (wdt_set_heartbeat(new_timeout))
-                 return -EINVAL;
-         wdt_ping();
-         /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-         return put_user(timeout, p);
-
-       case WDIOC_SETOPTIONS:
-       {
-         int options, retval = -EINVAL;
-
-         if (get_user(options, p))
-           return -EFAULT;
-
-         if (options & WDIOS_DISABLECARD) {
-           wdt_disable();
-           retval = 0;
-         }
-
-         if (options & WDIOS_ENABLECARD) {
-           wdt_ping();
-           retval = 0;
-         }
-
-         return retval;
-       }
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-       /*
-        *      Activate
-        */
-
-       wdt_ping();
-       return nonseekable_open(inode, file);
-}
-
-static int
-wdt_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               wdt_disable();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               wdt_ping();
-       }
-       expect_close = 0;
-       clear_bit(0, &wdt_is_open);
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int
-wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               wdt_disable();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdt_write,
-       .ioctl          = wdt_ioctl,
-       .open           = wdt_open,
-       .release        = wdt_close,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wdt_fops,
-};
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
-       .notifier_call = wdt_notify_sys,
-};
-
-static int __init
-wdt_init(void)
-{
-       int ret;
-
-       spin_lock_init(&io_lock);
-
-       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<=255, using %d\n",
-                       WATCHDOG_TIMEOUT);
-       }
-
-       if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
-               ret = -EIO;
-               goto out;
-       }
-
-       w83627hf_init();
-
-       ret = register_reboot_notifier(&wdt_notifier);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto unreg_regions;
-       }
-
-       ret = misc_register(&wdt_miscdev);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto unreg_reboot;
-       }
-
-       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-out:
-       return ret;
-unreg_reboot:
-       unregister_reboot_notifier(&wdt_notifier);
-unreg_regions:
-       release_region(wdt_io, 1);
-       goto out;
-}
-
-static void __exit
-wdt_exit(void)
-{
-       misc_deregister(&wdt_miscdev);
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(wdt_io,1);
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
-MODULE_DESCRIPTION("w83627hf/thf WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c
deleted file mode 100644 (file)
index d9e821d..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- *     w83697hf/hg WDT driver
- *
- *     (c) Copyright 2006 Samuel Tardieu <sam@rfc1149.net>
- *     (c) Copyright 2006 Marcus Junker <junker@anduras.de>
- *
- *     Based on w83627hf_wdt.c which is based on advantechwdt.c
- *     which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Marcus Junker nor ANDURAS AG admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define WATCHDOG_NAME "w83697hf/hg WDT"
-#define PFX WATCHDOG_NAME ": "
-#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
-
-static unsigned long wdt_is_open;
-static char expect_close;
-static spinlock_t io_lock;
-
-/* You must set this - there is no sane way to probe for this board. */
-static int wdt_io = 0x2e;
-module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)");
-
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
-module_param(timeout, int, 0);
-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);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-/*
- *     Kernel methods.
- */
-
-#define W83697HF_EFER (wdt_io+0)       /* Extended Function Enable Register */
-#define W83697HF_EFIR (wdt_io+0)       /* Extended Function Index Register (same as EFER) */
-#define W83697HF_EFDR (wdt_io+1)       /* Extended Function Data Register */
-
-static inline void
-w83697hf_unlock(void)
-{
-       outb_p(0x87, W83697HF_EFER);    /* Enter extended function mode */
-       outb_p(0x87, W83697HF_EFER);    /* Again according to manual */
-}
-
-static inline void
-w83697hf_lock(void)
-{
-       outb_p(0xAA, W83697HF_EFER);    /* Leave extended function mode */
-}
-
-/*
- *     The three functions w83697hf_get_reg(), w83697hf_set_reg() and
- *     w83697hf_write_timeout() must be called with the device unlocked.
- */
-
-static unsigned char
-w83697hf_get_reg(unsigned char reg)
-{
-       outb_p(reg, W83697HF_EFIR);
-       return inb_p(W83697HF_EFDR);
-}
-
-static void
-w83697hf_set_reg(unsigned char reg, unsigned char data)
-{
-       outb_p(reg, W83697HF_EFIR);
-       outb_p(data, W83697HF_EFDR);
-}
-
-static void
-w83697hf_write_timeout(int timeout)
-{
-       w83697hf_set_reg(0xF4, timeout);        /* Write Timeout counter to CRF4 */
-}
-
-static void
-w83697hf_select_wdt(void)
-{
-       w83697hf_unlock();
-       w83697hf_set_reg(0x07, 0x08);   /* Switch to logic device 8 (GPIO2) */
-}
-
-static inline void
-w83697hf_deselect_wdt(void)
-{
-       w83697hf_lock();
-}
-
-static void
-w83697hf_init(void)
-{
-       unsigned char bbuf;
-
-       w83697hf_select_wdt();
-
-       bbuf = w83697hf_get_reg(0x29);
-       bbuf &= ~0x60;
-       bbuf |= 0x20;
-       w83697hf_set_reg(0x29, bbuf);   /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
-
-       bbuf = w83697hf_get_reg(0xF3);
-       bbuf &= ~0x04;
-       w83697hf_set_reg(0xF3, bbuf);   /* Count mode is seconds */
-
-       w83697hf_deselect_wdt();
-}
-
-static int
-wdt_ping(void)
-{
-       spin_lock(&io_lock);
-       w83697hf_select_wdt();
-
-       w83697hf_write_timeout(timeout);
-
-       w83697hf_deselect_wdt();
-       spin_unlock(&io_lock);
-       return 0;
-}
-
-static int
-wdt_enable(void)
-{
-       spin_lock(&io_lock);
-       w83697hf_select_wdt();
-
-       w83697hf_write_timeout(timeout);
-       w83697hf_set_reg(0x30, 1);      /* Enable timer */
-
-       w83697hf_deselect_wdt();
-       spin_unlock(&io_lock);
-       return 0;
-}
-
-static int
-wdt_disable(void)
-{
-       spin_lock(&io_lock);
-       w83697hf_select_wdt();
-
-       w83697hf_set_reg(0x30, 0);      /* Disable timer */
-       w83697hf_write_timeout(0);
-
-       w83697hf_deselect_wdt();
-       spin_unlock(&io_lock);
-       return 0;
-}
-
-static int
-wdt_set_heartbeat(int t)
-{
-       if ((t < 1) || (t > 255))
-               return -EINVAL;
-
-       timeout = t;
-       return 0;
-}
-
-static ssize_t
-wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               wdt_ping();
-       }
-       return count;
-}
-
-static int
-wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_timeout;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "W83697HF WDT",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &ident, sizeof(ident)))
-                       return -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               wdt_ping();
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, p))
-                       return -EFAULT;
-               if (wdt_set_heartbeat(new_timeout))
-                       return -EINVAL;
-               wdt_ping();
-               /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, p);
-
-       case WDIOC_SETOPTIONS:
-       {
-               int options, retval = -EINVAL;
-
-               if (get_user(options, p))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       wdt_disable();
-                       retval = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       wdt_enable();
-                       retval = 0;
-               }
-
-               return retval;
-       }
-
-       default:
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-       /*
-        *      Activate
-        */
-
-       wdt_enable();
-       return nonseekable_open(inode, file);
-}
-
-static int
-wdt_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               wdt_disable();
-       } else {
-               printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-               wdt_ping();
-       }
-       expect_close = 0;
-       clear_bit(0, &wdt_is_open);
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int
-wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               wdt_disable();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdt_write,
-       .ioctl          = wdt_ioctl,
-       .open           = wdt_open,
-       .release        = wdt_close,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wdt_fops,
-};
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
-       .notifier_call = wdt_notify_sys,
-};
-
-static int
-w83697hf_check_wdt(void)
-{
-       if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
-               printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io);
-               return -EIO;
-       }
-
-       printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io);
-       w83697hf_unlock();
-       if (w83697hf_get_reg(0x20) == 0x60) {
-               printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io);
-               w83697hf_lock();
-               return 0;
-       }
-       w83697hf_lock();        /* Reprotect in case it was a compatible device */
-
-       printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
-       release_region(wdt_io, 2);
-       return -EIO;
-}
-
-static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 };
-
-static int __init
-wdt_init(void)
-{
-       int ret, i, found = 0;
-
-       spin_lock_init(&io_lock);
-
-       printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
-
-       if (wdt_io == 0) {
-               /* we will autodetect the W83697HF/HG watchdog */
-               for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) {
-                       wdt_io = w83697hf_ioports[i];
-                       if (!w83697hf_check_wdt())
-                               found++;
-               }
-       } else {
-               if (!w83697hf_check_wdt())
-                       found++;
-       }
-
-       if (!found) {
-               printk (KERN_ERR PFX "No W83697HF/HG could be found\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       w83697hf_init();
-       wdt_disable();  /* Disable watchdog until first use */
-
-       if (wdt_set_heartbeat(timeout)) {
-               wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n",
-                       WATCHDOG_TIMEOUT);
-       }
-
-       ret = register_reboot_notifier(&wdt_notifier);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto unreg_regions;
-       }
-
-       ret = misc_register(&wdt_miscdev);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto unreg_reboot;
-       }
-
-       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-out:
-       return ret;
-unreg_reboot:
-       unregister_reboot_notifier(&wdt_notifier);
-unreg_regions:
-       release_region(wdt_io, 2);
-       goto out;
-}
-
-static void __exit
-wdt_exit(void)
-{
-       misc_deregister(&wdt_miscdev);
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(wdt_io, 2);
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marcus Junker <junker@anduras.de>, Samuel Tardieu <sam@rfc1149.net>");
-MODULE_DESCRIPTION("w83697hf/hg WDT driver");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
deleted file mode 100644 (file)
index 3c88fe1..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *     W83877F Computer Watchdog Timer driver
- *
- *      Based on acquirewdt.c by Alan Cox,
- *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@unthought.net>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     The authors do NOT admit liability nor provide warranty for
- *     any of this software. This material is provided "AS-IS" in
- *      the hope that it may be useful for others.
- *
- *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
- *
- *           4/19 - 2001      [Initial revision]
- *           9/27 - 2001      Added spinlocking
- *           4/12 - 2002      [rob@osinvestor.com] Eliminate extra comments
- *                            Eliminate fop_read
- *                            Eliminate extra spin_unlock
- *                            Added KERN_* tags to printks
- *                            add CONFIG_WATCHDOG_NOWAYOUT support
- *                            fix possible wdt_is_open race
- *                            changed watchdog_info to correctly reflect what the driver offers
- *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
- *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
- *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
- *                            added extra printk's for startup problems
- *                            use module_param
- *                            made timeout (the emulated heartbeat) a module_param
- *                            made the keepalive ping an internal subroutine
- *
- *  This WDT driver is different from most other Linux WDT
- *  drivers in that the driver will ping the watchdog by itself,
- *  because this particular WDT has a very short timeout (1.6
- *  seconds) and it would be insane to count on any userspace
- *  daemon always getting scheduled within that time frame.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define OUR_NAME "w83877f_wdt"
-#define PFX OUR_NAME ": "
-
-#define ENABLE_W83877F_PORT 0x3F0
-#define ENABLE_W83877F 0x87
-#define DISABLE_W83877F 0xAA
-#define WDT_PING 0x443
-#define WDT_REGISTER 0x14
-#define WDT_ENABLE 0x9C
-#define WDT_DISABLE 0x8C
-
-/*
- * The W83877F seems to be fixed at 1.6s timeout (at least on the
- * EMACS PC-104 board I'm using). If we reset the watchdog every
- * ~250ms we should be safe.  */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 30 seconds.
- */
-
-#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
-static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
-
-
-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 wdt_timer_ping(unsigned long);
-static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
-static unsigned long next_heartbeat;
-static unsigned long wdt_is_open;
-static char wdt_expect_close;
-static spinlock_t wdt_spinlock;
-
-/*
- *     Whack the dog
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT
-        */
-       if(time_before(jiffies, next_heartbeat))
-       {
-               /* Ping the WDT */
-               spin_lock(&wdt_spinlock);
-
-               /* Ping the WDT by reading from WDT_PING */
-               inb_p(WDT_PING);
-
-               /* Re-set the timer interval */
-               mod_timer(&timer, jiffies + WDT_INTERVAL);
-
-               spin_unlock(&wdt_spinlock);
-
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-/*
- * Utility routines
- */
-
-static void wdt_change(int writeval)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&wdt_spinlock, flags);
-
-       /* buy some time */
-       inb_p(WDT_PING);
-
-       /* make W83877F available */
-       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
-       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
-
-       /* enable watchdog */
-       outb_p(WDT_REGISTER,    ENABLE_W83877F_PORT);
-       outb_p(writeval,        ENABLE_W83877F_PORT+1);
-
-       /* lock the W8387FF away */
-       outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT);
-
-       spin_unlock_irqrestore(&wdt_spinlock, flags);
-}
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + (timeout * HZ);
-
-       /* Start the timer */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-
-       wdt_change(WDT_ENABLE);
-
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
-}
-
-static void wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer(&timer);
-
-       wdt_change(WDT_DISABLE);
-
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
-}
-
-static void wdt_keepalive(void)
-{
-       /* user land ping */
-       next_heartbeat = jiffies + (timeout * HZ);
-}
-
-/*
- * /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count)
-       {
-               if (!nowayout)
-               {
-                       size_t ofs;
-
-                       /* note: just in case someone wrote the magic character
-                        * five months ago... */
-                       wdt_expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for(ofs = 0; ofs != count; ofs++)
-                       {
-                               char c;
-                               if (get_user(c, buf + ofs))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       wdt_expect_close = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should restart timer */
-               wdt_keepalive();
-       }
-       return count;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       /* Just in case we're already talking to someone... */
-       if(test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-
-       /* Good, fire up the show */
-       wdt_startup();
-       return nonseekable_open(inode, file);
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(wdt_expect_close == 42)
-               wdt_turnoff();
-       else {
-               del_timer(&timer);
-               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
-       }
-       clear_bit(0, &wdt_is_open);
-       wdt_expect_close = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident=
-       {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "W83877F",
-       };
-
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               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:
-                       wdt_keepalive();
-                       return 0;
-               case WDIOC_SETOPTIONS:
-               {
-                       int new_options, retval = -EINVAL;
-
-                       if(get_user(new_options, p))
-                               return -EFAULT;
-
-                       if(new_options & WDIOS_DISABLECARD) {
-                               wdt_turnoff();
-                               retval = 0;
-                       }
-
-                       if(new_options & WDIOS_ENABLECARD) {
-                               wdt_startup();
-                               retval = 0;
-                       }
-
-                       return retval;
-               }
-               case WDIOC_SETTIMEOUT:
-               {
-                       int new_timeout;
-
-                       if(get_user(new_timeout, p))
-                               return -EFAULT;
-
-                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
-                               return -EINVAL;
-
-                       timeout = new_timeout;
-                       wdt_keepalive();
-                       /* Fall through */
-               }
-               case WDIOC_GETTIMEOUT:
-                       return put_user(timeout, p);
-       }
-}
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = fop_write,
-       .open           = fop_open,
-       .release        = fop_close,
-       .ioctl          = fop_ioctl,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wdt_fops,
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-               wdt_turnoff();
-       return NOTIFY_DONE;
-}
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier=
-{
-       .notifier_call = wdt_notify_sys,
-};
-
-static void __exit w83877f_wdt_unload(void)
-{
-       wdt_turnoff();
-
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(WDT_PING,1);
-       release_region(ENABLE_W83877F_PORT,2);
-}
-
-static int __init w83877f_wdt_init(void)
-{
-       int rc = -EBUSY;
-
-       spin_lock_init(&wdt_spinlock);
-
-       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
-       {
-               timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
-                       timeout);
-       }
-
-       if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
-       {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       ENABLE_W83877F_PORT);
-               rc = -EIO;
-               goto err_out;
-       }
-
-       if (!request_region(WDT_PING, 1, "W8387FF WDT"))
-       {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       WDT_PING);
-               rc = -EIO;
-               goto err_out_region1;
-       }
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
-               goto err_out_region2;
-       }
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_miscdev;
-       }
-
-       printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out_region2:
-       release_region(WDT_PING,1);
-err_out_region1:
-       release_region(ENABLE_W83877F_PORT,2);
-err_out:
-       return rc;
-}
-
-module_init(w83877f_wdt_init);
-module_exit(w83877f_wdt_unload);
-
-MODULE_AUTHOR("Scott and Bill Jennings");
-MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
deleted file mode 100644 (file)
index 1579684..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- *     W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
- *
- *     (c) Copyright 2005  Jose Goncalves <jose.goncalves@inov.pt>
- *
- *      Based on w83877f_wdt.c by Scott Jennings,
- *           and wdt977.c by Woody Suwalski
- *
- *                     -----------------------
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- */
-
-#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/init.h>
-#include <linux/ioport.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#define WATCHDOG_VERSION  "1.00"
-#define WATCHDOG_NAME     "W83977F WDT"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
-
-#define IO_INDEX_PORT     0x3F0
-#define IO_DATA_PORT      (IO_INDEX_PORT+1)
-
-#define UNLOCK_DATA       0x87
-#define LOCK_DATA         0xAA
-#define DEVICE_REGISTER   0x07
-
-#define        DEFAULT_TIMEOUT   45            /* default timeout in seconds */
-
-static int timeout = DEFAULT_TIMEOUT;
-static int timeoutW;                   /* timeout in watchdog counter units */
-static unsigned long timer_alive;
-static int testmode;
-static char expect_close;
-static spinlock_t spinlock;
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
-module_param(testmode, int, 0);
-MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
-
-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) ")");
-
-/*
- * Start the watchdog
- */
-
-static int wdt_start(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* Unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-
-       /*
-        * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
-        * F2 has the timeout in watchdog counter units.
-        * F3 is set to enable watchdog LED blink at timeout.
-        * F4 is used to just clear the TIMEOUT'ed state (bit 0).
-        */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-       outb_p(0xF2,IO_INDEX_PORT);
-       outb_p(timeoutW,IO_DATA_PORT);
-       outb_p(0xF3,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-       outb_p(0xF4,IO_INDEX_PORT);
-       outb_p(0x00,IO_DATA_PORT);
-
-       /* Set device Aux2 active */
-       outb_p(0x30,IO_INDEX_PORT);
-       outb_p(0x01,IO_DATA_PORT);
-
-       /* 
-        * Select device Aux1 (dev=7) to set GP16 as the watchdog output
-        * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
-        * Map GP16 at pin 119.
-        * In test mode watch the bit 0 on F4 to indicate "triggered" or
-        * check watchdog LED on SBC.
-        */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x07,IO_DATA_PORT);
-       if (!testmode)
-       {
-               unsigned pin_map;
-
-               outb_p(0xE6,IO_INDEX_PORT);
-               outb_p(0x0A,IO_DATA_PORT);
-               outb_p(0x2C,IO_INDEX_PORT);
-               pin_map = inb_p(IO_DATA_PORT);
-               pin_map |= 0x10;
-               pin_map &= ~(0x20);
-               outb_p(0x2C,IO_INDEX_PORT);
-               outb_p(pin_map,IO_DATA_PORT);
-       }
-       outb_p(0xE3,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-
-       /* Set device Aux1 active */
-       outb_p(0x30,IO_INDEX_PORT);
-       outb_p(0x01,IO_DATA_PORT);
-
-       /* Lock the SuperIO chip */
-       outb_p(LOCK_DATA,IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       printk(KERN_INFO PFX "activated.\n");
-
-       return 0;
-}
-
-/*
- * Stop the watchdog
- */
-
-static int wdt_stop(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* Unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-
-       /* 
-        * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
-        * F2 is reset to its default value (watchdog timer disabled).
-        * F3 is reset to its default state.
-        * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
-        */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-       outb_p(0xF2,IO_INDEX_PORT);
-       outb_p(0xFF,IO_DATA_PORT);
-       outb_p(0xF3,IO_INDEX_PORT);
-       outb_p(0x00,IO_DATA_PORT);
-       outb_p(0xF4,IO_INDEX_PORT);
-       outb_p(0x00,IO_DATA_PORT);
-       outb_p(0xF2,IO_INDEX_PORT);
-       outb_p(0x00,IO_DATA_PORT);
-
-       /*
-        * Select device Aux1 (dev=7) to set GP16 (in reg E6) and 
-        * Gp13 (in reg E3) as inputs.
-        */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x07,IO_DATA_PORT);
-       if (!testmode)
-       {
-               outb_p(0xE6,IO_INDEX_PORT);
-               outb_p(0x01,IO_DATA_PORT);
-       }
-       outb_p(0xE3,IO_INDEX_PORT);
-       outb_p(0x01,IO_DATA_PORT);
-
-       /* Lock the SuperIO chip */
-       outb_p(LOCK_DATA,IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       printk(KERN_INFO PFX "shutdown.\n");
-
-       return 0;
-}
-
-/*
- * Send a keepalive ping to the watchdog
- * This is done by simply re-writing the timeout to reg. 0xF2
- */
-
-static int wdt_keepalive(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* Unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-
-       /* Select device Aux2 (device=8) to kick watchdog reg F2 */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-       outb_p(0xF2,IO_INDEX_PORT);
-       outb_p(timeoutW,IO_DATA_PORT);
-
-       /* Lock the SuperIO chip */
-       outb_p(LOCK_DATA,IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       return 0;
-}
-
-/*
- * Set the watchdog timeout value
- */
-
-static int wdt_set_timeout(int t)
-{
-       int tmrval;
-
-       /*
-        * Convert seconds to watchdog counter time units, rounding up.
-        * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup 
-        * value. This information is supplied in the PCM-5335 manual and was
-        * checked by me on a real board. This is a bit strange because W83977f
-        * datasheet says counter unit is in minutes!
-        */
-       if (t < 15)
-               return -EINVAL;
-
-       tmrval = ((t + 15) + 29) / 30;
-
-       if (tmrval > 255)
-               return -EINVAL;
-
-       /*
-        * timeout is the timeout in seconds, 
-        * timeoutW is the timeout in watchdog counter units.
-        */
-       timeoutW = tmrval;
-       timeout = (timeoutW * 30) - 15;
-       return 0;
-}
-
-/*
- * Get the watchdog status
- */
-
-static int wdt_get_status(int *status)
-{
-       int new_status;
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* Unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
-
-       /* Select device Aux2 (device=8) to read watchdog reg F4 */
-       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
-       outb_p(0x08,IO_DATA_PORT);
-       outb_p(0xF4,IO_INDEX_PORT);
-       new_status = inb_p(IO_DATA_PORT);
-
-       /* Lock the SuperIO chip */
-       outb_p(LOCK_DATA,IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       *status = 0;
-       if (new_status & 1)
-               *status |= WDIOF_CARDRESET;
-
-       return 0;
-}
-
-
-/*
- *     /dev/watchdog handling
- */
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
-       /* If the watchdog is alive we don't need to start it again */
-       if( test_and_set_bit(0, &timer_alive) )
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int wdt_release(struct inode *inode, struct file *file)
-{
-       /*
-        * Shut off the timer.
-        * Lock it in if it's a module and we set nowayout
-        */
-       if (expect_close == 42)
-       {
-               wdt_stop();
-               clear_bit(0, &timer_alive);
-       } else {
-               wdt_keepalive();
-               printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
-       }
-       expect_close = 0;
-       return 0;
-}
-
-/*
- *      wdt_write:
- *      @file: file handle to the watchdog
- *      @buf: buffer to write (unused as data does not matter here
- *      @count: count of bytes
- *      @ppos: pointer to the position to write. No seeks allowed
- *
- *      A write to a watchdog device is defined as a keepalive signal. Any
- *      write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t wdt_write(struct file *file, const char __user *buf,
-                           size_t count, loff_t *ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if(count)
-       {
-               if (!nowayout)
-               {
-                       size_t ofs;
-
-                       /* note: just in case someone wrote the magic character long ago */
-                       expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for(ofs = 0; ofs != count; ofs++)
-                       {
-                               char c;
-                               if (get_user(c, buf + ofs))
-                                       return -EFAULT;
-                               if (c == 'V') {
-                                       expect_close = 42;
-                               }
-                       }
-               }
-
-               /* someone wrote to us, we should restart timer */
-               wdt_keepalive();
-       }
-       return count;
-}
-
-/*
- *      wdt_ioctl:
- *      @inode: inode of the device
- *      @file: file handle to the device
- *      @cmd: watchdog command
- *      @arg: argument pointer
- *
- *      The watchdog API defines a common set of functions for all watchdogs
- *      according to their available features.
- */
-
-static struct watchdog_info ident = {
-       .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
-       .firmware_version =     1,
-       .identity = WATCHDOG_NAME,
-};
-
-static int wdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int status;
-       int new_options, retval = -EINVAL;
-       int new_timeout;
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-
-       uarg.i = (int __user *)arg;
-
-       switch(cmd)
-       {
-       default:
-               return -ENOTTY;
-
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
-
-       case WDIOC_GETSTATUS:
-               wdt_get_status(&status);
-               return put_user(status, uarg.i);
-
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, uarg.i);
-
-       case WDIOC_KEEPALIVE:
-               wdt_keepalive();
-               return 0;
-
-       case WDIOC_SETOPTIONS:
-               if (get_user (new_options, uarg.i))
-                       return -EFAULT;
-
-               if (new_options & WDIOS_DISABLECARD) {
-                       wdt_stop();
-                       retval = 0;
-               }
-
-               if (new_options & WDIOS_ENABLECARD) {
-                       wdt_start();
-                       retval = 0;
-               }
-
-               return retval;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, uarg.i))
-                       return -EFAULT;
-
-               if (wdt_set_timeout(new_timeout))
-                   return -EINVAL;
-
-               wdt_keepalive();
-               /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, uarg.i);
-
-       }
-}
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT)
-               wdt_stop();
-       return NOTIFY_DONE;
-}
-
-static const struct file_operations wdt_fops=
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdt_write,
-       .ioctl          = wdt_ioctl,
-       .open           = wdt_open,
-       .release        = wdt_release,
-};
-
-static struct miscdevice wdt_miscdev=
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &wdt_fops,
-};
-
-static struct notifier_block wdt_notifier = {
-       .notifier_call = wdt_notify_sys,
-};
-
-static int __init w83977f_wdt_init(void)
-{
-       int rc;
-
-        printk(KERN_INFO PFX DRIVER_VERSION);
-
-       spin_lock_init(&spinlock);
-
-       /*
-        * Check that the timeout value is within it's range ; 
-        * if not reset to the default
-        */
-       if (wdt_set_timeout(timeout)) {
-               wdt_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
-                       DEFAULT_TIMEOUT);
-       }
-
-       if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
-       {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       IO_INDEX_PORT);
-               rc = -EIO;
-               goto err_out;
-       }
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
-               goto err_out_region;
-       }
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_miscdev;
-       }
-
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
-               timeout, nowayout, testmode);
-
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out_region:
-       release_region(IO_INDEX_PORT,2);
-err_out:
-       return rc;
-}
-
-static void __exit w83977f_wdt_exit(void)
-{
-       wdt_stop();
-       misc_deregister(&wdt_miscdev);
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(IO_INDEX_PORT,2);
-}
-
-module_init(w83977f_wdt_init);
-module_exit(w83977f_wdt_exit);
-
-MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
-MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c
deleted file mode 100644 (file)
index 950905d..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- *     ICP Wafer 5823 Single Board Computer WDT driver
- *      http://www.icpamerica.com/wafer_5823.php
- *      May also work on other similar models
- *
- *     (c) Copyright 2002 Justin Cormack <justin@street-vision.com>
- *
- *      Release 0.02
- *
- *     Based on advantechwdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define WATCHDOG_NAME "Wafer 5823 WDT"
-#define PFX WATCHDOG_NAME ": "
-#define WD_TIMO 60                     /* 60 sec default timeout */
-
-static unsigned long wafwdt_is_open;
-static char expect_close;
-static spinlock_t wafwdt_lock;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- *
- *      To enable, write the timeout value in seconds (1 to 255) to I/O
- *      port WDT_START, then read the port to start the watchdog. To pat
- *      the dog, read port WDT_STOP to stop the timer, then read WDT_START
- *      to restart it again.
- */
-
-static int wdt_stop = 0x843;
-static int wdt_start = 0x443;
-
-static int timeout = WD_TIMO;  /* in seconds */
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) ".");
-
-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 wafwdt_ping(void)
-{
-       /* pat watchdog */
-       spin_lock(&wafwdt_lock);
-       inb_p(wdt_stop);
-       inb_p(wdt_start);
-       spin_unlock(&wafwdt_lock);
-}
-
-static void wafwdt_start(void)
-{
-       /* start up watchdog */
-       outb_p(timeout, wdt_start);
-       inb_p(wdt_start);
-}
-
-static void
-wafwdt_stop(void)
-{
-       /* stop watchdog */
-       inb_p(wdt_stop);
-}
-
-static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
-{
-       /* See if we got the magic character 'V' and reload the timer */
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       /* scan to see whether or not we got the magic character */
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               /* Well, anyhow someone wrote to us, we should return that favour */
-               wafwdt_ping();
-       }
-       return count;
-}
-
-static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-            unsigned long arg)
-{
-       int new_timeout;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       static struct watchdog_info ident = {
-               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-               .firmware_version = 1,
-               .identity = "Wafer 5823 WDT",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &ident, sizeof (ident)))
-                       return -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               wafwdt_ping();
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, p))
-                       return -EFAULT;
-               if ((new_timeout < 1) || (new_timeout > 255))
-                       return -EINVAL;
-               timeout = new_timeout;
-               wafwdt_stop();
-               wafwdt_start();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, p);
-
-       case WDIOC_SETOPTIONS:
-       {
-               int options, retval = -EINVAL;
-
-               if (get_user(options, p))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       wafwdt_start();
-                       retval = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       wafwdt_stop();
-                       retval = 0;
-               }
-
-               return retval;
-       }
-
-       default:
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-static int wafwdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &wafwdt_is_open))
-               return -EBUSY;
-
-       /*
-        *      Activate
-        */
-       wafwdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int
-wafwdt_close(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               wafwdt_stop();
-       } else {
-               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-               wafwdt_ping();
-       }
-       clear_bit(0, &wafwdt_is_open);
-       expect_close = 0;
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               wafwdt_stop();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static const struct file_operations wafwdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wafwdt_write,
-       .ioctl          = wafwdt_ioctl,
-       .open           = wafwdt_open,
-       .release        = wafwdt_close,
-};
-
-static struct miscdevice wafwdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wafwdt_fops,
-};
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wafwdt_notifier = {
-       .notifier_call = wafwdt_notify_sys,
-};
-
-static int __init wafwdt_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n");
-
-       spin_lock_init(&wafwdt_lock);
-
-       if (timeout < 1 || timeout > 255) {
-               timeout = WD_TIMO;
-               printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n",
-                       timeout);
-       }
-
-       if (wdt_stop != wdt_start) {
-               if(!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
-                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_stop);
-                       ret = -EIO;
-                       goto error;
-               }
-       }
-
-       if(!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
-               ret = -EIO;
-               goto error2;
-       }
-
-       ret = register_reboot_notifier(&wafwdt_notifier);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       ret);
-               goto error3;
-       }
-
-       ret = misc_register(&wafwdt_miscdev);
-       if (ret != 0) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto error4;
-       }
-
-       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
-               timeout, nowayout);
-
-       return ret;
-error4:
-       unregister_reboot_notifier(&wafwdt_notifier);
-error3:
-       release_region(wdt_start, 1);
-error2:
-       if (wdt_stop != wdt_start)
-               release_region(wdt_stop, 1);
-error:
-       return ret;
-}
-
-static void __exit wafwdt_exit(void)
-{
-       misc_deregister(&wafwdt_miscdev);
-       unregister_reboot_notifier(&wafwdt_notifier);
-       if(wdt_stop != wdt_start)
-               release_region(wdt_stop, 1);
-       release_region(wdt_start, 1);
-}
-
-module_init(wafwdt_init);
-module_exit(wafwdt_exit);
-
-MODULE_AUTHOR("Justin Cormack");
-MODULE_DESCRIPTION("ICP Wafer 5823 Single Board Computer WDT driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-/* end of wafer5823wdt.c */
diff --git a/drivers/char/watchdog/wd501p.h b/drivers/char/watchdog/wd501p.h
deleted file mode 100644 (file)
index a4504f4..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *     Industrial Computer Source WDT500/501 driver
- *
- *     (c) Copyright 1995      CymruNET Ltd
- *                             Innovation Centre
- *                             Singleton Park
- *                             Swansea
- *                             Wales
- *                             UK
- *                             SA2 8PP
- *
- *     http://www.cymru.net
- *
- *     This driver is provided under the GNU General Public License, incorporated
- *     herein by reference. The driver is provided without warranty or 
- *     support.
- *
- *     Release 0.04.
- *
- */
-
-
-#define WDT_COUNT0             (io+0)
-#define WDT_COUNT1             (io+1)
-#define WDT_COUNT2             (io+2)
-#define WDT_CR                 (io+3)
-#define WDT_SR                 (io+4)  /* Start buzzer on PCI write */
-#define WDT_RT                 (io+5)  /* Stop buzzer on PCI write */
-#define WDT_BUZZER             (io+6)  /* PCI only: rd=disable, wr=enable */
-#define WDT_DC                 (io+7)
-
-/* The following are only on the PCI card, they're outside of I/O space on
- * the ISA card: */
-#define WDT_CLOCK              (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */
-/* inverted opto isolated reset output: */
-#define WDT_OPTONOTRST         (io+13) /* wr=enable, rd=disable */
-/* opto isolated reset output: */
-#define WDT_OPTORST            (io+14) /* wr=enable, rd=disable */
-/* programmable outputs: */
-#define WDT_PROGOUT            (io+15) /* wr=enable, rd=disable */
-
-                                                               /* FAN 501 500 */
-#define WDC_SR_WCCR            1       /* Active low */        /*  X   X   X  */
-#define WDC_SR_TGOOD           2                               /*  X   X   -  */
-#define WDC_SR_ISOI0           4                               /*  X   X   X  */
-#define WDC_SR_ISII1           8                               /*  X   X   X  */
-#define WDC_SR_FANGOOD         16                              /*  X   -   -  */
-#define WDC_SR_PSUOVER         32      /* Active low */        /*  X   X   -  */
-#define WDC_SR_PSUUNDR         64      /* Active low */        /*  X   X   -  */
-#define WDC_SR_IRQ             128     /* Active low */        /*  X   X   X  */
-
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c
deleted file mode 100644 (file)
index 1d64e27..0000000
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
- * RTAS calls are available
- */
-
-/*
- * RTAS watchdog driver
- *
- * (C) Copyright IBM Corp. 2005
- * device driver to exploit watchdog RTAS functions
- *
- * Authors : Utz Bacher <utz.bacher@de.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/types.h>
-#include <linux/watchdog.h>
-
-#include <asm/rtas.h>
-#include <asm/uaccess.h>
-
-#define WDRTAS_MAGIC_CHAR              42
-#define WDRTAS_SUPPORTED_MASK          (WDIOF_SETTIMEOUT | \
-                                        WDIOF_MAGICCLOSE)
-
-MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
-MODULE_DESCRIPTION("RTAS watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int wdrtas_nowayout = 1;
-#else
-static int wdrtas_nowayout = 0;
-#endif
-
-static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
-static char wdrtas_expect_close = 0;
-
-static int wdrtas_interval;
-
-#define WDRTAS_THERMAL_SENSOR          3
-static int wdrtas_token_get_sensor_state;
-#define WDRTAS_SURVEILLANCE_IND                9000
-static int wdrtas_token_set_indicator;
-#define WDRTAS_SP_SPI                  28
-static int wdrtas_token_get_sp;
-static int wdrtas_token_event_scan;
-
-#define WDRTAS_DEFAULT_INTERVAL                300
-
-#define WDRTAS_LOGBUFFER_LEN           128
-static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
-
-
-/*** watchdog access functions */
-
-/**
- * wdrtas_set_interval - sets the watchdog interval
- * @interval: new interval
- *
- * returns 0 on success, <0 on failures
- *
- * wdrtas_set_interval sets the watchdog keepalive interval by calling the
- * RTAS function set-indicator (surveillance). The unit of interval is
- * seconds.
- */
-static int
-wdrtas_set_interval(int interval)
-{
-       long result;
-       static int print_msg = 10;
-
-       /* rtas uses minutes */
-       interval = (interval + 59) / 60;
-
-       result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
-                          WDRTAS_SURVEILLANCE_IND, 0, interval);
-       if ( (result < 0) && (print_msg) ) {
-               printk(KERN_ERR "wdrtas: setting the watchdog to %i "
-                      "timeout failed: %li\n", interval, result);
-               print_msg--;
-       }
-
-       return result;
-}
-
-/**
- * wdrtas_get_interval - returns the current watchdog interval
- * @fallback_value: value (in seconds) to use, if the RTAS call fails
- *
- * returns the interval
- *
- * wdrtas_get_interval returns the current watchdog keepalive interval
- * as reported by the RTAS function ibm,get-system-parameter. The unit
- * of the return value is seconds.
- */
-static int
-wdrtas_get_interval(int fallback_value)
-{
-       long result;
-       char value[4];
-
-       result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
-                          WDRTAS_SP_SPI, (void *)__pa(&value), 4);
-       if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
-            (result < 0) ) {
-               printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
-                      "timeout (%li). Continuing\n", result);
-               return fallback_value;
-       }
-
-       /* rtas uses minutes */
-       return ((int)value[2]) * 60;
-}
-
-/**
- * wdrtas_timer_start - starts watchdog
- *
- * wdrtas_timer_start starts the watchdog by calling the RTAS function
- * set-interval (surveillance)
- */
-static void
-wdrtas_timer_start(void)
-{
-       wdrtas_set_interval(wdrtas_interval);
-}
-
-/**
- * wdrtas_timer_stop - stops watchdog
- *
- * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
- * set-interval (surveillance)
- */
-static void
-wdrtas_timer_stop(void)
-{
-       wdrtas_set_interval(0);
-}
-
-/**
- * wdrtas_log_scanned_event - logs an event we received during keepalive
- *
- * wdrtas_log_scanned_event prints a message to the log buffer dumping
- * the results of the last event-scan call
- */
-static void
-wdrtas_log_scanned_event(void)
-{
-       int i;
-
-       for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
-               printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x   "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                      (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
-                      wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], 
-                      wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], 
-                      wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], 
-                      wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], 
-                      wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], 
-                      wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], 
-                      wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], 
-                      wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
-}
-
-/**
- * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
- *
- * wdrtas_timer_keepalive restarts the watchdog timer by calling the
- * RTAS function event-scan and repeats these calls as long as there are
- * events available. All events will be dumped.
- */
-static void
-wdrtas_timer_keepalive(void)
-{
-       long result;
-
-       do {
-               result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
-                                  RTAS_EVENT_SCAN_ALL_EVENTS, 0,
-                                  (void *)__pa(wdrtas_logbuffer),
-                                  WDRTAS_LOGBUFFER_LEN);
-               if (result < 0)
-                       printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
-                              result);
-               if (result == 0)
-                       wdrtas_log_scanned_event();
-       } while (result == 0);
-}
-
-/**
- * wdrtas_get_temperature - returns current temperature
- *
- * returns temperature or <0 on failures
- *
- * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
- * uses the RTAS call get-sensor-state, token 3 to do so
- */
-static int
-wdrtas_get_temperature(void)
-{
-       long result;
-       int temperature = 0;
-
-       result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
-                          (void *)__pa(&temperature),
-                          WDRTAS_THERMAL_SENSOR, 0);
-
-       if (result < 0)
-               printk(KERN_WARNING "wdrtas: reading the thermal sensor "
-                      "faild: %li\n", result);
-       else
-               temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
-
-       return temperature;
-}
-
-/**
- * wdrtas_get_status - returns the status of the watchdog
- *
- * returns a bitmask of defines WDIOF_... as defined in
- * include/linux/watchdog.h
- */
-static int
-wdrtas_get_status(void)
-{
-       return 0; /* TODO */
-}
-
-/**
- * wdrtas_get_boot_status - returns the reason for the last boot
- *
- * returns a bitmask of defines WDIOF_... as defined in
- * include/linux/watchdog.h, indicating why the watchdog rebooted the system
- */
-static int
-wdrtas_get_boot_status(void)
-{
-       return 0; /* TODO */
-}
-
-/*** watchdog API and operations stuff */
-
-/* wdrtas_write - called when watchdog device is written to
- * @file: file structure
- * @buf: user buffer with data
- * @len: amount to data written
- * @ppos: position in file
- *
- * returns the number of successfully processed characters, which is always
- * the number of bytes passed to this function
- *
- * wdrtas_write processes all the data given to it and looks for the magic
- * character 'V'. This character allows the watchdog device to be closed
- * properly.
- */
-static ssize_t
-wdrtas_write(struct file *file, const char __user *buf,
-            size_t len, loff_t *ppos)
-{
-       int i;
-       char c;
-
-       if (!len)
-               goto out;
-
-       if (!wdrtas_nowayout) {
-               wdrtas_expect_close = 0;
-               /* look for 'V' */
-               for (i = 0; i < len; i++) {
-                       if (get_user(c, buf + i))
-                               return -EFAULT;
-                       /* allow to close device */
-                       if (c == 'V')
-                               wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
-               }
-       }
-
-       wdrtas_timer_keepalive();
-
-out:
-       return len;
-}
-
-/**
- * wdrtas_ioctl - ioctl function for the watchdog device
- * @inode: inode structure
- * @file: file structure
- * @cmd: command for ioctl
- * @arg: argument pointer
- *
- * returns 0 on success, <0 on failure
- *
- * wdrtas_ioctl implements the watchdog API ioctls
- */
-static int
-wdrtas_ioctl(struct inode *inode, struct file *file,
-            unsigned int cmd, unsigned long arg)
-{
-       int __user *argp = (void __user *)arg;
-       int i;
-       static struct watchdog_info wdinfo = {
-               .options = WDRTAS_SUPPORTED_MASK,
-               .firmware_version = 0,
-               .identity = "wdrtas"
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
-                       return -EFAULT;
-               return 0;
-
-       case WDIOC_GETSTATUS:
-               i = wdrtas_get_status();
-               return put_user(i, argp);
-
-       case WDIOC_GETBOOTSTATUS:
-               i = wdrtas_get_boot_status();
-               return put_user(i, argp);
-
-       case WDIOC_GETTEMP:
-               if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
-                       return -EOPNOTSUPP;
-
-               i = wdrtas_get_temperature();
-               return put_user(i, argp);
-
-       case WDIOC_SETOPTIONS:
-               if (get_user(i, argp))
-                       return -EFAULT;
-               if (i & WDIOS_DISABLECARD)
-                       wdrtas_timer_stop();
-               if (i & WDIOS_ENABLECARD) {
-                       wdrtas_timer_keepalive();
-                       wdrtas_timer_start();
-               }
-               if (i & WDIOS_TEMPPANIC) {
-                       /* not implemented. Done by H8 */
-               }
-               return 0;
-
-       case WDIOC_KEEPALIVE:
-               wdrtas_timer_keepalive();
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(i, argp))
-                       return -EFAULT;
-
-               if (wdrtas_set_interval(i))
-                       return -EINVAL;
-
-               wdrtas_timer_keepalive();
-
-               if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
-                       wdrtas_interval = i;
-               else
-                       wdrtas_interval = wdrtas_get_interval(i);
-               /* fallthrough */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(wdrtas_interval, argp);
-
-       default:
-               return -ENOTTY;
-       }
-}
-
-/**
- * wdrtas_open - open function of watchdog device
- * @inode: inode structure
- * @file: file structure
- *
- * returns 0 on success, -EBUSY if the file has been opened already, <0 on
- * other failures
- *
- * function called when watchdog device is opened
- */
-static int
-wdrtas_open(struct inode *inode, struct file *file)
-{
-       /* only open once */
-       if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
-               atomic_dec(&wdrtas_miscdev_open);
-               return -EBUSY;
-       }
-
-       wdrtas_timer_start();
-       wdrtas_timer_keepalive();
-
-       return nonseekable_open(inode, file);
-}
-
-/**
- * wdrtas_close - close function of watchdog device
- * @inode: inode structure
- * @file: file structure
- *
- * returns 0 on success
- *
- * close function. Always succeeds
- */
-static int
-wdrtas_close(struct inode *inode, struct file *file)
-{
-       /* only stop watchdog, if this was announced using 'V' before */
-       if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
-               wdrtas_timer_stop();
-       else {
-               printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
-                      "not stopped.\n");
-               wdrtas_timer_keepalive();
-       }
-
-       wdrtas_expect_close = 0;
-       atomic_dec(&wdrtas_miscdev_open);
-       return 0;
-}
-
-/**
- * wdrtas_temp_read - gives back the temperature in fahrenheit
- * @file: file structure
- * @buf: user buffer
- * @count: number of bytes to be read
- * @ppos: position in file
- *
- * returns always 1 or -EFAULT in case of user space copy failures, <0 on
- * other failures
- *
- * wdrtas_temp_read gives the temperature to the users by copying this
- * value as one byte into the user space buffer. The unit is Fahrenheit...
- */
-static ssize_t
-wdrtas_temp_read(struct file *file, char __user *buf,
-                size_t count, loff_t *ppos)
-{
-       int temperature = 0;
-
-       temperature = wdrtas_get_temperature();
-       if (temperature < 0)
-               return temperature;
-
-       if (copy_to_user(buf, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-/**
- * wdrtas_temp_open - open function of temperature device
- * @inode: inode structure
- * @file: file structure
- *
- * returns 0 on success, <0 on failure
- *
- * function called when temperature device is opened
- */
-static int
-wdrtas_temp_open(struct inode *inode, struct file *file)
-{
-       return nonseekable_open(inode, file);
-}
-
-/**
- * wdrtas_temp_close - close function of temperature device
- * @inode: inode structure
- * @file: file structure
- *
- * returns 0 on success
- *
- * close function. Always succeeds
- */
-static int
-wdrtas_temp_close(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-/**
- * wdrtas_reboot - reboot notifier function
- * @nb: notifier block structure
- * @code: reboot code
- * @ptr: unused
- *
- * returns NOTIFY_DONE
- *
- * wdrtas_reboot stops the watchdog in case of a reboot
- */
-static int
-wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
-{
-       if ( (code==SYS_DOWN) || (code==SYS_HALT) )
-               wdrtas_timer_stop();
-
-       return NOTIFY_DONE;
-}
-
-/*** initialization stuff */
-
-static const struct file_operations wdrtas_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdrtas_write,
-       .ioctl          = wdrtas_ioctl,
-       .open           = wdrtas_open,
-       .release        = wdrtas_close,
-};
-
-static struct miscdevice wdrtas_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &wdrtas_fops,
-};
-
-static const struct file_operations wdrtas_temp_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = wdrtas_temp_read,
-       .open           = wdrtas_temp_open,
-       .release        = wdrtas_temp_close,
-};
-
-static struct miscdevice wdrtas_tempdev = {
-       .minor =        TEMP_MINOR,
-       .name =         "temperature",
-       .fops =         &wdrtas_temp_fops,
-};
-
-static struct notifier_block wdrtas_notifier = {
-       .notifier_call =        wdrtas_reboot,
-};
-
-/**
- * wdrtas_get_tokens - reads in RTAS tokens
- *
- * returns 0 on succes, <0 on failure
- *
- * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
- * this watchdog driver. It tolerates, if "get-sensor-state" and
- * "ibm,get-system-parameter" are not available.
- */
-static int
-wdrtas_get_tokens(void)
-{
-       wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
-       if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "get-sensor-state. Trying to continue without "
-                      "temperature support.\n");
-       }
-
-       wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
-       if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "ibm,get-system-parameter. Trying to continue with "
-                      "a default timeout value of %i seconds.\n",
-                      WDRTAS_DEFAULT_INTERVAL);
-       }
-
-       wdrtas_token_set_indicator = rtas_token("set-indicator");
-       if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for "
-                      "set-indicator. Terminating watchdog code.\n");
-               return -EIO;
-       }
-
-       wdrtas_token_event_scan = rtas_token("event-scan");
-       if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
-                      "Terminating watchdog code.\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/**
- * wdrtas_unregister_devs - unregisters the misc dev handlers
- *
- * wdrtas_register_devs unregisters the watchdog and temperature watchdog
- * misc devs
- */
-static void
-wdrtas_unregister_devs(void)
-{
-       misc_deregister(&wdrtas_miscdev);
-       if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
-               misc_deregister(&wdrtas_tempdev);
-}
-
-/**
- * wdrtas_register_devs - registers the misc dev handlers
- *
- * returns 0 on succes, <0 on failure
- *
- * wdrtas_register_devs registers the watchdog and temperature watchdog
- * misc devs
- */
-static int
-wdrtas_register_devs(void)
-{
-       int result;
-
-       result = misc_register(&wdrtas_miscdev);
-       if (result) {
-               printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
-                      "device. Terminating watchdog code.\n");
-               return result;
-       }
-
-       if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
-               result = misc_register(&wdrtas_tempdev);
-               if (result) {
-                       printk(KERN_WARNING "wdrtas: couldn't register "
-                              "watchdog temperature misc device. Continuing "
-                              "without temperature support.\n");
-                       wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
-               }
-       }
-
-       return 0;
-}
-
-/**
- * wdrtas_init - init function of the watchdog driver
- *
- * returns 0 on succes, <0 on failure
- *
- * registers the file handlers and the reboot notifier
- */
-static int __init
-wdrtas_init(void)
-{
-       if (wdrtas_get_tokens())
-               return -ENODEV;
-
-       if (wdrtas_register_devs())
-               return -ENODEV;
-
-       if (register_reboot_notifier(&wdrtas_notifier)) {
-               printk(KERN_ERR "wdrtas: could not register reboot notifier. "
-                      "Terminating watchdog code.\n");
-               wdrtas_unregister_devs();
-               return -ENODEV;
-       }
-
-       if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
-               wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
-       else
-               wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
-
-       return 0;
-}
-
-/**
- * wdrtas_exit - exit function of the watchdog driver
- *
- * unregisters the file handlers and the reboot notifier
- */
-static void __exit
-wdrtas_exit(void)
-{
-       if (!wdrtas_nowayout)
-               wdrtas_timer_stop();
-
-       wdrtas_unregister_devs();
-
-       unregister_reboot_notifier(&wdrtas_notifier);
-}
-
-module_init(wdrtas_init);
-module_exit(wdrtas_exit);
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
deleted file mode 100644 (file)
index 0a3de6a..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- *     Industrial Computer Source WDT500/501 driver
- *
- *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Release 0.10.
- *
- *     Fixes
- *             Dave Gregorich  :       Modularisation and minor bugs
- *             Alan Cox        :       Added the watchdog ioctl() stuff
- *             Alan Cox        :       Fixed the reboot problem (as noted by
- *                                     Matt Crocker).
- *             Alan Cox        :       Added wdt= boot option
- *             Alan Cox        :       Cleaned up copy/user stuff
- *             Tim Hockin      :       Added insmod parameters, comment cleanup
- *                                     Parameterized timeout
- *             Tigran Aivazian :       Restructured wdt_init() to handle failures
- *             Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
- *             Matt Domsch     :       Added nowayout module option
- */
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include "wd501p.h"
-
-static unsigned long wdt_is_open;
-static char expect_close;
-
-/*
- *     Module parameters
- */
-
-#define WD_TIMO 60                     /* Default heartbeat = 60 seconds */
-
-static int heartbeat = WD_TIMO;
-static int wd_heartbeat;
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
-
-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) ")");
-
-/* You must set these - there is no sane way to probe for this board. */
-static int io=0x240;
-static int irq=11;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq, "WDT irq (default=11)");
-
-#ifdef CONFIG_WDT_501
-/* Support for the Fan Tachometer on the WDT501-P */
-static int tachometer;
-
-module_param(tachometer, int, 0);
-MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)");
-#endif /* CONFIG_WDT_501 */
-
-/*
- *     Programming support
- */
-
-static void wdt_ctr_mode(int ctr, int mode)
-{
-       ctr<<=6;
-       ctr|=0x30;
-       ctr|=(mode<<1);
-       outb_p(ctr, WDT_CR);
-}
-
-static void wdt_ctr_load(int ctr, int val)
-{
-       outb_p(val&0xFF, WDT_COUNT0+ctr);
-       outb_p(val>>8, WDT_COUNT0+ctr);
-}
-
-/**
- *     wdt_start:
- *
- *     Start the watchdog driver.
- */
-
-static int wdt_start(void)
-{
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdt_ctr_mode(0,3);              /* Program CTR0 for Mode 3: Square Wave Generator */
-       wdt_ctr_mode(1,2);              /* Program CTR1 for Mode 2: Rate Generator */
-       wdt_ctr_mode(2,0);              /* Program CTR2 for Mode 0: Pulse on Terminal Count */
-       wdt_ctr_load(0, 8948);          /* Count at 100Hz */
-       wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
-       wdt_ctr_load(2,65535);          /* Length of reset pulse */
-       outb_p(0, WDT_DC);              /* Enable watchdog */
-       return 0;
-}
-
-/**
- *     wdt_stop:
- *
- *     Stop the watchdog driver.
- */
-
-static int wdt_stop (void)
-{
-       /* Turn the card off */
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdt_ctr_load(2,0);              /* 0 length reset pulses now */
-       return 0;
-}
-
-/**
- *     wdt_ping:
- *
- *     Reload counter one with the watchdog heartbeat. We don't bother reloading
- *     the cascade counter.
- */
-
-static int wdt_ping(void)
-{
-       /* Write a watchdog value */
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdt_ctr_mode(1,2);              /* Re-Program CTR1 for Mode 2: Rate Generator */
-       wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
-       outb_p(0, WDT_DC);              /* Enable watchdog */
-       return 0;
-}
-
-/**
- *     wdt_set_heartbeat:
- *     @t:             the new heartbeat value that needs to be set.
- *
- *     Set a new heartbeat value for the watchdog device. If the heartbeat value is
- *     incorrect we keep the old value and return -EINVAL. If successfull we
- *     return 0.
- */
-static int wdt_set_heartbeat(int t)
-{
-       if ((t < 1) || (t > 65535))
-               return -EINVAL;
-
-       heartbeat = t;
-       wd_heartbeat = t * 100;
-       return 0;
-}
-
-/**
- *     wdt_get_status:
- *     @status:                the new status.
- *
- *     Extract the status information from a WDT watchdog device. There are
- *     several board variants so we have to know which bits are valid. Some
- *     bits default to one and some to zero in order to be maximally painful.
- *
- *     we then map the bits onto the status ioctl flags.
- */
-
-static int wdt_get_status(int *status)
-{
-       unsigned char new_status=inb_p(WDT_SR);
-
-       *status=0;
-       if (new_status & WDC_SR_ISOI0)
-               *status |= WDIOF_EXTERN1;
-       if (new_status & WDC_SR_ISII1)
-               *status |= WDIOF_EXTERN2;
-#ifdef CONFIG_WDT_501
-       if (!(new_status & WDC_SR_TGOOD))
-               *status |= WDIOF_OVERHEAT;
-       if (!(new_status & WDC_SR_PSUOVER))
-               *status |= WDIOF_POWEROVER;
-       if (!(new_status & WDC_SR_PSUUNDR))
-               *status |= WDIOF_POWERUNDER;
-       if (tachometer) {
-               if (!(new_status & WDC_SR_FANGOOD))
-                       *status |= WDIOF_FANFAULT;
-       }
-#endif /* CONFIG_WDT_501 */
-       return 0;
-}
-
-#ifdef CONFIG_WDT_501
-/**
- *     wdt_get_temperature:
- *
- *     Reports the temperature in degrees Fahrenheit. The API is in
- *     farenheit. It was designed by an imperial measurement luddite.
- */
-
-static int wdt_get_temperature(int *temperature)
-{
-       unsigned short c=inb_p(WDT_RT);
-
-       *temperature = (c * 11 / 15) + 7;
-       return 0;
-}
-#endif /* CONFIG_WDT_501 */
-
-/**
- *     wdt_interrupt:
- *     @irq:           Interrupt number
- *     @dev_id:        Unused as we don't allow multiple devices.
- *
- *     Handle an interrupt from the board. These are raised when the status
- *     map changes in what the board considers an interesting way. That means
- *     a failure condition occurring.
- */
-
-static irqreturn_t wdt_interrupt(int irq, void *dev_id)
-{
-       /*
-        *      Read the status register see what is up and
-        *      then printk it.
-        */
-       unsigned char status=inb_p(WDT_SR);
-
-       printk(KERN_CRIT "WDT status %d\n", status);
-
-#ifdef CONFIG_WDT_501
-       if (!(status & WDC_SR_TGOOD))
-               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
-       if (!(status & WDC_SR_PSUOVER))
-               printk(KERN_CRIT "PSU over voltage.\n");
-       if (!(status & WDC_SR_PSUUNDR))
-               printk(KERN_CRIT "PSU under voltage.\n");
-       if (tachometer) {
-               if (!(status & WDC_SR_FANGOOD))
-                       printk(KERN_CRIT "Possible fan fault.\n");
-       }
-#endif /* CONFIG_WDT_501 */
-       if (!(status & WDC_SR_WCCR))
-#ifdef SOFTWARE_REBOOT
-#ifdef ONLY_TESTING
-               printk(KERN_CRIT "Would Reboot.\n");
-#else
-               printk(KERN_CRIT "Initiating system reboot.\n");
-               emergency_restart();
-#endif
-#else
-               printk(KERN_CRIT "Reset in 5ms.\n");
-#endif
-       return IRQ_HANDLED;
-}
-
-
-/**
- *     wdt_write:
- *     @file: file handle to the watchdog
- *     @buf: buffer to write (unused as data does not matter here
- *     @count: count of bytes
- *     @ppos: pointer to the position to write. No seeks allowed
- *
- *     A write to a watchdog device is defined as a keepalive signal. Any
- *     write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if(count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               wdt_ping();
-       }
-       return count;
-}
-
-/**
- *     wdt_ioctl:
- *     @inode: inode of the device
- *     @file: file handle to the device
- *     @cmd: watchdog command
- *     @arg: argument pointer
- *
- *     The watchdog API defines a common set of functions for all watchdogs
- *     according to their available features. We only actually usefully support
- *     querying capabilities and current status.
- */
-
-static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_heartbeat;
-       int status;
-
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT|
-                                       WDIOF_MAGICCLOSE|
-                                       WDIOF_KEEPALIVEPING,
-               .firmware_version =     1,
-               .identity =             "WDT500/501",
-       };
-
-       /* Add options according to the card we have */
-       ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
-#ifdef CONFIG_WDT_501
-       ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER);
-       if (tachometer)
-               ident.options |= WDIOF_FANFAULT;
-#endif /* CONFIG_WDT_501 */
-
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
-
-               case WDIOC_GETSTATUS:
-                       wdt_get_status(&status);
-                       return put_user(status, p);
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-               case WDIOC_KEEPALIVE:
-                       wdt_ping();
-                       return 0;
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_heartbeat, p))
-                               return -EFAULT;
-
-                       if (wdt_set_heartbeat(new_heartbeat))
-                               return -EINVAL;
-
-                       wdt_ping();
-                       /* Fall */
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, p);
-       }
-}
-
-/**
- *     wdt_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     The watchdog device has been opened. The watchdog device is single
- *     open and on opening we load the counters. Counter zero is a 100Hz
- *     cascade, into counter 1 which downcounts to reboot. When the counter
- *     triggers counter 2 downcounts the length of the reset pulse which
- *     set set to be as long as possible.
- */
-
-static int wdt_open(struct inode *inode, struct file *file)
-{
-       if(test_and_set_bit(0, &wdt_is_open))
-               return -EBUSY;
-       /*
-        *      Activate
-        */
-       wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     wdt_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute
- *     between people who want their watchdog to be able to shut down and
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-
-static int wdt_release(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               wdt_stop();
-               clear_bit(0, &wdt_is_open);
-       } else {
-               printk(KERN_CRIT "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
-               wdt_ping();
-       }
-       expect_close = 0;
-       return 0;
-}
-
-#ifdef CONFIG_WDT_501
-/**
- *     wdt_temp_read:
- *     @file: file handle to the watchdog board
- *     @buf: buffer to write 1 byte into
- *     @count: length of buffer
- *     @ptr: offset (no seek allowed)
- *
- *     Temp_read reports the temperature in degrees Fahrenheit. The API is in
- *     farenheit. It was designed by an imperial measurement luddite.
- */
-
-static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
-{
-       int temperature;
-
-       if (wdt_get_temperature(&temperature))
-               return -EFAULT;
-
-       if (copy_to_user (buf, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-/**
- *     wdt_temp_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     The temperature device has been opened.
- */
-
-static int wdt_temp_open(struct inode *inode, struct file *file)
-{
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     wdt_temp_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The temperature device has been closed.
- */
-
-static int wdt_temp_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-#endif /* CONFIG_WDT_501 */
-
-/**
- *     notify_sys:
- *     @this: our notifier block
- *     @code: the event being reported
- *     @unused: unused
- *
- *     Our notifier is called on system shutdowns. We want to turn the card
- *     off at reboot otherwise the machine will reboot again during memory
- *     test or worse yet during the following fsck. This would suck, in fact
- *     trust me - if it happens it does suck.
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the card off */
-               wdt_stop();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-
-static const struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdt_write,
-       .ioctl          = wdt_ioctl,
-       .open           = wdt_open,
-       .release        = wdt_release,
-};
-
-static struct miscdevice wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wdt_fops,
-};
-
-#ifdef CONFIG_WDT_501
-static const struct file_operations wdt_temp_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = wdt_temp_read,
-       .open           = wdt_temp_open,
-       .release        = wdt_temp_release,
-};
-
-static struct miscdevice temp_miscdev = {
-       .minor  = TEMP_MINOR,
-       .name   = "temperature",
-       .fops   = &wdt_temp_fops,
-};
-#endif /* CONFIG_WDT_501 */
-
-/*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdt_notifier = {
-       .notifier_call = wdt_notify_sys,
-};
-
-/**
- *     cleanup_module:
- *
- *     Unload the watchdog. You cannot do this with any file handles open.
- *     If your watchdog is set to continue ticking on close and you unload
- *     it, well it keeps ticking. We won't get the interrupt but the board
- *     will not touch PC memory so all is fine. You just have to load a new
- *     module in 60 seconds or reboot.
- */
-
-static void __exit wdt_exit(void)
-{
-       misc_deregister(&wdt_miscdev);
-#ifdef CONFIG_WDT_501
-       misc_deregister(&temp_miscdev);
-#endif /* CONFIG_WDT_501 */
-       unregister_reboot_notifier(&wdt_notifier);
-       free_irq(irq, NULL);
-       release_region(io,8);
-}
-
-/**
- *     wdt_init:
- *
- *     Set up the WDT watchdog board. All we have to do is grab the
- *     resources we require and bitch if anyone beat us to them.
- *     The open() function will actually kick the board off.
- */
-
-static int __init wdt_init(void)
-{
-       int ret;
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (wdt_set_heartbeat(heartbeat)) {
-               wdt_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO "wdt: heartbeat value must be 0<heartbeat<65536, using %d\n",
-                       WD_TIMO);
-       }
-
-       if (!request_region(io, 8, "wdt501p")) {
-               printk(KERN_ERR "wdt: I/O address 0x%04x already in use\n", io);
-               ret = -EBUSY;
-               goto out;
-       }
-
-       ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL);
-       if(ret) {
-               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
-               goto outreg;
-       }
-
-       ret = register_reboot_notifier(&wdt_notifier);
-       if(ret) {
-               printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret);
-               goto outirq;
-       }
-
-#ifdef CONFIG_WDT_501
-       ret = misc_register(&temp_miscdev);
-       if (ret) {
-               printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                       TEMP_MINOR, ret);
-               goto outrbt;
-       }
-#endif /* CONFIG_WDT_501 */
-
-       ret = misc_register(&wdt_miscdev);
-       if (ret) {
-               printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto outmisc;
-       }
-
-       ret = 0;
-       printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
-               io, irq, heartbeat, nowayout);
-#ifdef CONFIG_WDT_501
-       printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled"));
-#endif /* CONFIG_WDT_501 */
-
-out:
-       return ret;
-
-outmisc:
-#ifdef CONFIG_WDT_501
-       misc_deregister(&temp_miscdev);
-outrbt:
-#endif /* CONFIG_WDT_501 */
-       unregister_reboot_notifier(&wdt_notifier);
-outirq:
-       free_irq(irq, NULL);
-outreg:
-       release_region(io,8);
-       goto out;
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
deleted file mode 100644 (file)
index e4cf661..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- *     Intel 21285 watchdog driver
- *     Copyright (c) Phil Blundell <pb@nexus.co.uk>, 1998
- *
- *     based on
- *
- *     SoftDog 0.05:   A Software Watchdog Device
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/hardware/dec21285.h>
-
-/*
- * Define this to stop the watchdog actually rebooting the machine.
- */
-#undef ONLY_TESTING
-
-static unsigned int soft_margin = 60;          /* in seconds */
-static unsigned int reload;
-static unsigned long timer_alive;
-
-#ifdef ONLY_TESTING
-/*
- *     If the timer expires..
- */
-static void watchdog_fire(int irq, void *dev_id)
-{
-       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
-       *CSR_TIMER4_CNTL = 0;
-       *CSR_TIMER4_CLR = 0;
-}
-#endif
-
-/*
- *     Refresh the timer.
- */
-static void watchdog_ping(void)
-{
-       *CSR_TIMER4_LOAD = reload;
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int watchdog_open(struct inode *inode, struct file *file)
-{
-       int ret;
-
-       if (*CSR_SA110_CNTL & (1 << 13))
-               return -EBUSY;
-
-       if (test_and_set_bit(1, &timer_alive))
-               return -EBUSY;
-
-       reload = soft_margin * (mem_fclk_21285 / 256);
-
-       *CSR_TIMER4_CLR = 0;
-       watchdog_ping();
-       *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD
-               | TIMER_CNTL_DIV256;
-
-#ifdef ONLY_TESTING
-       ret = request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
-       if (ret) {
-               *CSR_TIMER4_CNTL = 0;
-               clear_bit(1, &timer_alive);
-       }
-#else
-       /*
-        * Setting this bit is irreversible; once enabled, there is
-        * no way to disable the watchdog.
-        */
-       *CSR_SA110_CNTL |= 1 << 13;
-
-       ret = 0;
-#endif
-       nonseekable_open(inode, file);
-       return ret;
-}
-
-/*
- *     Shut off the timer.
- *     Note: if we really have enabled the watchdog, there
- *     is no way to turn off.
- */
-static int watchdog_release(struct inode *inode, struct file *file)
-{
-#ifdef ONLY_TESTING
-       free_irq(IRQ_TIMER4, NULL);
-       clear_bit(1, &timer_alive);
-#endif
-       return 0;
-}
-
-static ssize_t
-watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       /*
-        *      Refresh the timer.
-        */
-       if (len)
-               watchdog_ping();
-
-       return len;
-}
-
-static struct watchdog_info ident = {
-       .options        = WDIOF_SETTIMEOUT,
-       .identity       = "Footbridge Watchdog",
-};
-
-static int
-watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-              unsigned long arg)
-{
-       unsigned int new_margin;
-       int ret = -ENOTTY;
-
-       switch(cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = 0;
-               if (copy_to_user((void *)arg, &ident, sizeof(ident)))
-                       ret = -EFAULT;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0,(int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               watchdog_ping();
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(new_margin, (int *)arg);
-               if (ret)
-                       break;
-
-               /* Arbitrary, can't find the card's limits */
-               if (new_margin < 0 || new_margin > 60) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               soft_margin = new_margin;
-               reload = soft_margin * (mem_fclk_21285 / 256);
-               watchdog_ping();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(soft_margin, (int *)arg);
-               break;
-       }
-       return ret;
-}
-
-static const struct file_operations watchdog_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = watchdog_write,
-       .ioctl          = watchdog_ioctl,
-       .open           = watchdog_open,
-       .release        = watchdog_release,
-};
-
-static struct miscdevice watchdog_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &watchdog_fops,
-};
-
-static int __init footbridge_watchdog_init(void)
-{
-       int retval;
-
-       if (machine_is_netwinder())
-               return -ENODEV;
-
-       retval = misc_register(&watchdog_miscdev);
-       if (retval < 0)
-               return retval;
-
-       printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
-              soft_margin);
-
-       if (machine_is_cats())
-               printk("Warning: Watchdog reset may not work on this machine.\n");
-       return 0;
-}
-
-static void __exit footbridge_watchdog_exit(void)
-{
-       misc_deregister(&watchdog_miscdev);
-}
-
-MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
-MODULE_DESCRIPTION("Footbridge watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-module_param(soft_margin, int, 0);
-MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
-
-module_init(footbridge_watchdog_init);
-module_exit(footbridge_watchdog_exit);
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
deleted file mode 100644 (file)
index 7d300ff..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- *     Wdt977  0.04:   A Watchdog Device for Netwinder W83977AF chip
- *
- *     (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
- *
- *                     -----------------------
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *                     -----------------------
- *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
- *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *     19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
- *     06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
- *                                 from minutes to seconds.
- *      07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
- *                                    nwwatchdog_init.
- *      25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
- *                                 remove limitiation to be used on Netwinders only
- */
-
-#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/init.h>
-#include <linux/ioport.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <asm/uaccess.h>
-
-#define WATCHDOG_VERSION  "0.04"
-#define WATCHDOG_NAME     "Wdt977"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
-
-#define IO_INDEX_PORT  0x370           /* on some systems it can be 0x3F0 */
-#define IO_DATA_PORT   (IO_INDEX_PORT+1)
-
-#define UNLOCK_DATA    0x87
-#define LOCK_DATA      0xAA
-#define DEVICE_REGISTER        0x07
-
-
-#define        DEFAULT_TIMEOUT 60                      /* default timeout in seconds */
-
-static int timeout = DEFAULT_TIMEOUT;
-static int timeoutM;                           /* timeout in minutes */
-static unsigned long timer_alive;
-static int testmode;
-static char expect_close;
-static spinlock_t spinlock;
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
-module_param(testmode, int, 0);
-MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
-
-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) ")");
-
-/*
- * Start the watchdog
- */
-
-static int wdt977_start(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-
-       /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
-        * F2 has the timeout in minutes
-        * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
-        *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
-        * F4 is used to just clear the TIMEOUT'ed state (bit 0)
-        */
-       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-       outb_p(0x08, IO_DATA_PORT);
-       outb_p(0xF2, IO_INDEX_PORT);
-       outb_p(timeoutM, IO_DATA_PORT);
-       outb_p(0xF3, IO_INDEX_PORT);
-       outb_p(0x00, IO_DATA_PORT);     /* another setting is 0E for kbd/mouse/LED */
-       outb_p(0xF4, IO_INDEX_PORT);
-       outb_p(0x00, IO_DATA_PORT);
-
-       /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
-       /* in test mode watch the bit 1 on F4 to indicate "triggered" */
-       if (!testmode)
-       {
-               outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-               outb_p(0x07, IO_DATA_PORT);
-               outb_p(0xE6, IO_INDEX_PORT);
-               outb_p(0x08, IO_DATA_PORT);
-       }
-
-       /* lock the SuperIO chip */
-       outb_p(LOCK_DATA, IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "activated.\n");
-
-       return 0;
-}
-
-/*
- * Stop the watchdog
- */
-
-static int wdt977_stop(void)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-
-       /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
-       * F3 is reset to its default state
-       * F4 can clear the TIMEOUT'ed state (bit 0) - back to default
-       * We can not use GP17 as a PowerLed, as we use its usage as a RedLed
-       */
-       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-       outb_p(0x08, IO_DATA_PORT);
-       outb_p(0xF2, IO_INDEX_PORT);
-       outb_p(0xFF, IO_DATA_PORT);
-       outb_p(0xF3, IO_INDEX_PORT);
-       outb_p(0x00, IO_DATA_PORT);
-       outb_p(0xF4, IO_INDEX_PORT);
-       outb_p(0x00, IO_DATA_PORT);
-       outb_p(0xF2, IO_INDEX_PORT);
-       outb_p(0x00, IO_DATA_PORT);
-
-       /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
-       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-       outb_p(0x07, IO_DATA_PORT);
-       outb_p(0xE6, IO_INDEX_PORT);
-       outb_p(0x08, IO_DATA_PORT);
-
-       /* lock the SuperIO chip */
-       outb_p(LOCK_DATA, IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "shutdown.\n");
-
-       return 0;
-}
-
-/*
- * Send a keepalive ping to the watchdog
- * This is done by simply re-writing the timeout to reg. 0xF2
- */
-
-static int wdt977_keepalive(void)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-
-       /* select device Aux2 (device=8) and kicks watchdog reg F2 */
-       /* F2 has the timeout in minutes */
-       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-       outb_p(0x08, IO_DATA_PORT);
-       outb_p(0xF2, IO_INDEX_PORT);
-       outb_p(timeoutM, IO_DATA_PORT);
-
-       /* lock the SuperIO chip */
-       outb_p(LOCK_DATA, IO_INDEX_PORT);
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       return 0;
-}
-
-/*
- * Set the watchdog timeout value
- */
-
-static int wdt977_set_timeout(int t)
-{
-       int tmrval;
-
-       /* convert seconds to minutes, rounding up */
-       tmrval = (t + 59) / 60;
-
-       if (machine_is_netwinder()) {
-               /* we have a hw bug somewhere, so each 977 minute is actually only 30sec
-                *  this limits the max timeout to half of device max of 255 minutes...
-                */
-               tmrval += tmrval;
-       }
-
-       if ((tmrval < 1) || (tmrval > 255))
-               return -EINVAL;
-
-       /* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */
-       timeout = t;
-       timeoutM = tmrval;
-       return 0;
-}
-
-/*
- * Get the watchdog status
- */
-
-static int wdt977_get_status(int *status)
-{
-       int new_status;
-       unsigned long flags;
-
-       spin_lock_irqsave(&spinlock, flags);
-
-       /* unlock the SuperIO chip */
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
-
-       /* select device Aux2 (device=8) and read watchdog reg F4 */
-       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
-       outb_p(0x08, IO_DATA_PORT);
-       outb_p(0xF4, IO_INDEX_PORT);
-       new_status = inb_p(IO_DATA_PORT);
-
-       /* lock the SuperIO chip */
-       outb_p(LOCK_DATA, IO_INDEX_PORT);
-
-       spin_unlock_irqrestore(&spinlock, flags);
-
-       *status=0;
-       if (new_status & 1)
-               *status |= WDIOF_CARDRESET;
-
-       return 0;
-}
-
-
-/*
- *     /dev/watchdog handling
- */
-
-static int wdt977_open(struct inode *inode, struct file *file)
-{
-       /* If the watchdog is alive we don't need to start it again */
-       if( test_and_set_bit(0,&timer_alive) )
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       wdt977_start();
-       return nonseekable_open(inode, file);
-}
-
-static int wdt977_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (expect_close == 42)
-       {
-               wdt977_stop();
-               clear_bit(0,&timer_alive);
-       } else {
-               wdt977_keepalive();
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-       }
-       expect_close = 0;
-       return 0;
-}
-
-
-/*
- *      wdt977_write:
- *      @file: file handle to the watchdog
- *      @buf: buffer to write (unused as data does not matter here
- *      @count: count of bytes
- *      @ppos: pointer to the position to write. No seeks allowed
- *
- *      A write to a watchdog device is defined as a keepalive signal. Any
- *      write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t wdt977_write(struct file *file, const char __user *buf,
-                           size_t count, loff_t *ppos)
-{
-       if (count)
-       {
-               if (!nowayout)
-               {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++)
-                       {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-
-               /* someone wrote to us, we should restart timer */
-               wdt977_keepalive();
-       }
-       return count;
-}
-
-/*
- *      wdt977_ioctl:
- *      @inode: inode of the device
- *      @file: file handle to the device
- *      @cmd: watchdog command
- *      @arg: argument pointer
- *
- *      The watchdog API defines a common set of functions for all watchdogs
- *      according to their available features.
- */
-
-static struct watchdog_info ident = {
-       .options =              WDIOF_SETTIMEOUT |
-                               WDIOF_MAGICCLOSE |
-                               WDIOF_KEEPALIVEPING,
-       .firmware_version =     1,
-       .identity =             WATCHDOG_NAME,
-};
-
-static int wdt977_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int status;
-       int new_options, retval = -EINVAL;
-       int new_timeout;
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-
-       uarg.i = (int __user *)arg;
-
-       switch(cmd)
-       {
-       default:
-               return -ENOTTY;
-
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(uarg.ident, &ident,
-                       sizeof(ident)) ? -EFAULT : 0;
-
-       case WDIOC_GETSTATUS:
-               wdt977_get_status(&status);
-               return put_user(status, uarg.i);
-
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, uarg.i);
-
-       case WDIOC_KEEPALIVE:
-               wdt977_keepalive();
-               return 0;
-
-       case WDIOC_SETOPTIONS:
-               if (get_user (new_options, uarg.i))
-                       return -EFAULT;
-
-               if (new_options & WDIOS_DISABLECARD) {
-                       wdt977_stop();
-                       retval = 0;
-               }
-
-               if (new_options & WDIOS_ENABLECARD) {
-                       wdt977_start();
-                       retval = 0;
-               }
-
-               return retval;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, uarg.i))
-                       return -EFAULT;
-
-               if (wdt977_set_timeout(new_timeout))
-                   return -EINVAL;
-
-               wdt977_keepalive();
-               /* Fall */
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, uarg.i);
-
-       }
-}
-
-static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-               wdt977_stop();
-       return NOTIFY_DONE;
-}
-
-static const struct file_operations wdt977_fops=
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdt977_write,
-       .ioctl          = wdt977_ioctl,
-       .open           = wdt977_open,
-       .release        = wdt977_release,
-};
-
-static struct miscdevice wdt977_miscdev=
-{
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &wdt977_fops,
-};
-
-static struct notifier_block wdt977_notifier = {
-       .notifier_call = wdt977_notify_sys,
-};
-
-static int __init wd977_init(void)
-{
-       int rc;
-
-       //if (!machine_is_netwinder())
-       //      return -ENODEV;
-
-       printk(KERN_INFO PFX DRIVER_VERSION);
-
-       spin_lock_init(&spinlock);
-
-       /* Check that the timeout value is within it's range ; if not reset to the default */
-       if (wdt977_set_timeout(timeout))
-       {
-               wdt977_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n",
-                       DEFAULT_TIMEOUT);
-       }
-
-       /* on Netwinder the IOports are already reserved by
-        * arch/arm/mach-footbridge/netwinder-hw.c
-        */
-       if (!machine_is_netwinder())
-       {
-               if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
-               {
-                       printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                               IO_INDEX_PORT);
-                       rc = -EIO;
-                       goto err_out;
-               }
-       }
-
-       rc = misc_register(&wdt977_miscdev);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt977_miscdev.minor, rc);
-               goto err_out_region;
-       }
-
-       rc = register_reboot_notifier(&wdt977_notifier);
-       if (rc)
-       {
-               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-                       rc);
-               goto err_out_miscdev;
-       }
-
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
-               timeout, nowayout, testmode);
-
-       return 0;
-
-err_out_miscdev:
-        misc_deregister(&wdt977_miscdev);
-err_out_region:
-       if (!machine_is_netwinder())
-               release_region(IO_INDEX_PORT,2);
-err_out:
-       return rc;
-}
-
-static void __exit wd977_exit(void)
-{
-       wdt977_stop();
-       misc_deregister(&wdt977_miscdev);
-       unregister_reboot_notifier(&wdt977_notifier);
-       release_region(IO_INDEX_PORT,2);
-}
-
-module_init(wd977_init);
-module_exit(wd977_exit);
-
-MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>");
-MODULE_DESCRIPTION("W83977AF Watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
deleted file mode 100644 (file)
index 6baf4ae..0000000
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- *     Industrial Computer Source PCI-WDT500/501 driver
- *
- *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Release 0.10.
- *
- *     Fixes
- *             Dave Gregorich  :       Modularisation and minor bugs
- *             Alan Cox        :       Added the watchdog ioctl() stuff
- *             Alan Cox        :       Fixed the reboot problem (as noted by
- *                                     Matt Crocker).
- *             Alan Cox        :       Added wdt= boot option
- *             Alan Cox        :       Cleaned up copy/user stuff
- *             Tim Hockin      :       Added insmod parameters, comment cleanup
- *                                     Parameterized timeout
- *             JP Nollmann     :       Added support for PCI wdt501p
- *             Alan Cox        :       Split ISA and PCI cards into two drivers
- *             Jeff Garzik     :       PCI cleanups
- *             Tigran Aivazian :       Restructured wdtpci_init_one() to handle failures
- *             Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
- *             Zwane Mwaikambo :       Magic char closing, locking changes, cleanups
- *             Matt Domsch     :       nowayout module option
- */
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define WDT_IS_PCI
-#include "wd501p.h"
-
-#define PFX "wdt_pci: "
-
-/*
- * Until Access I/O gets their application for a PCI vendor ID approved,
- * I don't think that it's appropriate to move these constants into the
- * regular pci_ids.h file. -- JPN 2000/01/18
- */
-
-#ifndef PCI_VENDOR_ID_ACCESSIO
-#define PCI_VENDOR_ID_ACCESSIO 0x494f
-#endif
-#ifndef PCI_DEVICE_ID_WDG_CSM
-#define PCI_DEVICE_ID_WDG_CSM 0x22c0
-#endif
-
-/* We can only use 1 card due to the /dev/watchdog restriction */
-static int dev_count;
-
-static struct semaphore open_sem;
-static spinlock_t wdtpci_lock;
-static char expect_close;
-
-static int io;
-static int irq;
-
-/* Default timeout */
-#define WD_TIMO 60                     /* Default heartbeat = 60 seconds */
-
-static int heartbeat = WD_TIMO;
-static int wd_heartbeat;
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
-
-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) ")");
-
-#ifdef CONFIG_WDT_501_PCI
-/* Support for the Fan Tachometer on the PCI-WDT501 */
-static int tachometer;
-
-module_param(tachometer, int, 0);
-MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
-#endif /* CONFIG_WDT_501_PCI */
-
-/*
- *     Programming support
- */
-
-static void wdtpci_ctr_mode(int ctr, int mode)
-{
-       ctr<<=6;
-       ctr|=0x30;
-       ctr|=(mode<<1);
-       outb_p(ctr, WDT_CR);
-}
-
-static void wdtpci_ctr_load(int ctr, int val)
-{
-       outb_p(val&0xFF, WDT_COUNT0+ctr);
-       outb_p(val>>8, WDT_COUNT0+ctr);
-}
-
-/**
- *     wdtpci_start:
- *
- *     Start the watchdog driver.
- */
-
-static int wdtpci_start(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdtpci_lock, flags);
-
-       /*
-        * "pet" the watchdog, as Access says.
-        * This resets the clock outputs.
-        */
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdtpci_ctr_mode(2,0);           /* Program CTR2 for Mode 0: Pulse on Terminal Count */
-       outb_p(0, WDT_DC);              /* Enable watchdog */
-
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       outb_p(0, WDT_CLOCK);           /* 2.0833MHz clock */
-       inb_p(WDT_BUZZER);              /* disable */
-       inb_p(WDT_OPTONOTRST);          /* disable */
-       inb_p(WDT_OPTORST);             /* disable */
-       inb_p(WDT_PROGOUT);             /* disable */
-       wdtpci_ctr_mode(0,3);           /* Program CTR0 for Mode 3: Square Wave Generator */
-       wdtpci_ctr_mode(1,2);           /* Program CTR1 for Mode 2: Rate Generator */
-       wdtpci_ctr_mode(2,1);           /* Program CTR2 for Mode 1: Retriggerable One-Shot */
-       wdtpci_ctr_load(0,20833);       /* count at 100Hz */
-       wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */
-       /* DO NOT LOAD CTR2 on PCI card! -- JPN */
-       outb_p(0, WDT_DC);              /* Enable watchdog */
-
-       spin_unlock_irqrestore(&wdtpci_lock, flags);
-       return 0;
-}
-
-/**
- *     wdtpci_stop:
- *
- *     Stop the watchdog driver.
- */
-
-static int wdtpci_stop (void)
-{
-       unsigned long flags;
-
-       /* Turn the card off */
-       spin_lock_irqsave(&wdtpci_lock, flags);
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdtpci_ctr_load(2,0);           /* 0 length reset pulses now */
-       spin_unlock_irqrestore(&wdtpci_lock, flags);
-       return 0;
-}
-
-/**
- *     wdtpci_ping:
- *
- *     Reload counter one with the watchdog heartbeat. We don't bother reloading
- *     the cascade counter.
- */
-
-static int wdtpci_ping(void)
-{
-       unsigned long flags;
-
-       /* Write a watchdog value */
-       spin_lock_irqsave(&wdtpci_lock, flags);
-       inb_p(WDT_DC);                  /* Disable watchdog */
-       wdtpci_ctr_mode(1,2);           /* Re-Program CTR1 for Mode 2: Rate Generator */
-       wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */
-       outb_p(0, WDT_DC);              /* Enable watchdog */
-       spin_unlock_irqrestore(&wdtpci_lock, flags);
-       return 0;
-}
-
-/**
- *     wdtpci_set_heartbeat:
- *     @t:             the new heartbeat value that needs to be set.
- *
- *     Set a new heartbeat value for the watchdog device. If the heartbeat value is
- *     incorrect we keep the old value and return -EINVAL. If successfull we
- *     return 0.
- */
-static int wdtpci_set_heartbeat(int t)
-{
-       /* Arbitrary, can't find the card's limits */
-       if ((t < 1) || (t > 65535))
-               return -EINVAL;
-
-       heartbeat = t;
-       wd_heartbeat = t * 100;
-       return 0;
-}
-
-/**
- *     wdtpci_get_status:
- *     @status:                the new status.
- *
- *     Extract the status information from a WDT watchdog device. There are
- *     several board variants so we have to know which bits are valid. Some
- *     bits default to one and some to zero in order to be maximally painful.
- *
- *     we then map the bits onto the status ioctl flags.
- */
-
-static int wdtpci_get_status(int *status)
-{
-       unsigned char new_status=inb_p(WDT_SR);
-
-       *status=0;
-       if (new_status & WDC_SR_ISOI0)
-               *status |= WDIOF_EXTERN1;
-       if (new_status & WDC_SR_ISII1)
-               *status |= WDIOF_EXTERN2;
-#ifdef CONFIG_WDT_501_PCI
-       if (!(new_status & WDC_SR_TGOOD))
-               *status |= WDIOF_OVERHEAT;
-       if (!(new_status & WDC_SR_PSUOVER))
-               *status |= WDIOF_POWEROVER;
-       if (!(new_status & WDC_SR_PSUUNDR))
-               *status |= WDIOF_POWERUNDER;
-       if (tachometer) {
-               if (!(new_status & WDC_SR_FANGOOD))
-                       *status |= WDIOF_FANFAULT;
-       }
-#endif /* CONFIG_WDT_501_PCI */
-       return 0;
-}
-
-#ifdef CONFIG_WDT_501_PCI
-/**
- *     wdtpci_get_temperature:
- *
- *     Reports the temperature in degrees Fahrenheit. The API is in
- *     farenheit. It was designed by an imperial measurement luddite.
- */
-
-static int wdtpci_get_temperature(int *temperature)
-{
-       unsigned short c=inb_p(WDT_RT);
-
-       *temperature = (c * 11 / 15) + 7;
-       return 0;
-}
-#endif /* CONFIG_WDT_501_PCI */
-
-/**
- *     wdtpci_interrupt:
- *     @irq:           Interrupt number
- *     @dev_id:        Unused as we don't allow multiple devices.
- *
- *     Handle an interrupt from the board. These are raised when the status
- *     map changes in what the board considers an interesting way. That means
- *     a failure condition occurring.
- */
-
-static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
-{
-       /*
-        *      Read the status register see what is up and
-        *      then printk it.
-        */
-       unsigned char status=inb_p(WDT_SR);
-
-       printk(KERN_CRIT PFX "status %d\n", status);
-
-#ifdef CONFIG_WDT_501_PCI
-       if (!(status & WDC_SR_TGOOD))
-               printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",inb_p(WDT_RT));
-       if (!(status & WDC_SR_PSUOVER))
-               printk(KERN_CRIT PFX "PSU over voltage.\n");
-       if (!(status & WDC_SR_PSUUNDR))
-               printk(KERN_CRIT PFX "PSU under voltage.\n");
-       if (tachometer) {
-               if (!(status & WDC_SR_FANGOOD))
-                       printk(KERN_CRIT PFX "Possible fan fault.\n");
-       }
-#endif /* CONFIG_WDT_501_PCI */
-       if (!(status&WDC_SR_WCCR))
-#ifdef SOFTWARE_REBOOT
-#ifdef ONLY_TESTING
-               printk(KERN_CRIT PFX "Would Reboot.\n");
-#else
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
-               emergency_restart(NULL);
-#endif
-#else
-               printk(KERN_CRIT PFX "Reset in 5ms.\n");
-#endif
-       return IRQ_HANDLED;
-}
-
-
-/**
- *     wdtpci_write:
- *     @file: file handle to the watchdog
- *     @buf: buffer to write (unused as data does not matter here
- *     @count: count of bytes
- *     @ppos: pointer to the position to write. No seeks allowed
- *
- *     A write to a watchdog device is defined as a keepalive signal. Any
- *     write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if(get_user(c, buf+i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               wdtpci_ping();
-       }
-
-       return count;
-}
-
-/**
- *     wdtpci_ioctl:
- *     @inode: inode of the device
- *     @file: file handle to the device
- *     @cmd: watchdog command
- *     @arg: argument pointer
- *
- *     The watchdog API defines a common set of functions for all watchdogs
- *     according to their available features. We only actually usefully support
- *     querying capabilities and current status.
- */
-
-static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       int new_heartbeat;
-       int status;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT|
-                                       WDIOF_MAGICCLOSE|
-                                       WDIOF_KEEPALIVEPING,
-               .firmware_version =     1,
-               .identity =             "PCI-WDT500/501",
-       };
-
-       /* Add options according to the card we have */
-       ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
-#ifdef CONFIG_WDT_501_PCI
-       ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER);
-       if (tachometer)
-               ident.options |= WDIOF_FANFAULT;
-#endif /* CONFIG_WDT_501_PCI */
-
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
-
-               case WDIOC_GETSTATUS:
-                       wdtpci_get_status(&status);
-                       return put_user(status, p);
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, p);
-               case WDIOC_KEEPALIVE:
-                       wdtpci_ping();
-                       return 0;
-               case WDIOC_SETTIMEOUT:
-                       if (get_user(new_heartbeat, p))
-                               return -EFAULT;
-
-                       if (wdtpci_set_heartbeat(new_heartbeat))
-                               return -EINVAL;
-
-                       wdtpci_ping();
-                       /* Fall */
-               case WDIOC_GETTIMEOUT:
-                       return put_user(heartbeat, p);
-       }
-}
-
-/**
- *     wdtpci_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     The watchdog device has been opened. The watchdog device is single
- *     open and on opening we load the counters. Counter zero is a 100Hz
- *     cascade, into counter 1 which downcounts to reboot. When the counter
- *     triggers counter 2 downcounts the length of the reset pulse which
- *     set set to be as long as possible.
- */
-
-static int wdtpci_open(struct inode *inode, struct file *file)
-{
-       if (down_trylock(&open_sem))
-               return -EBUSY;
-
-       if (nowayout) {
-               __module_get(THIS_MODULE);
-       }
-       /*
-        *      Activate
-        */
-       wdtpci_start();
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     wdtpci_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute
- *     between people who want their watchdog to be able to shut down and
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-
-static int wdtpci_release(struct inode *inode, struct file *file)
-{
-       if (expect_close == 42) {
-               wdtpci_stop();
-       } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
-               wdtpci_ping();
-       }
-       expect_close = 0;
-       up(&open_sem);
-       return 0;
-}
-
-#ifdef CONFIG_WDT_501_PCI
-/**
- *     wdtpci_temp_read:
- *     @file: file handle to the watchdog board
- *     @buf: buffer to write 1 byte into
- *     @count: length of buffer
- *     @ptr: offset (no seek allowed)
- *
- *     Read reports the temperature in degrees Fahrenheit. The API is in
- *     fahrenheit. It was designed by an imperial measurement luddite.
- */
-
-static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
-{
-       int temperature;
-
-       if (wdtpci_get_temperature(&temperature))
-               return -EFAULT;
-
-       if (copy_to_user (buf, &temperature, 1))
-               return -EFAULT;
-
-       return 1;
-}
-
-/**
- *     wdtpci_temp_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     The temperature device has been opened.
- */
-
-static int wdtpci_temp_open(struct inode *inode, struct file *file)
-{
-       return nonseekable_open(inode, file);
-}
-
-/**
- *     wdtpci_temp_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The temperature device has been closed.
- */
-
-static int wdtpci_temp_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-#endif /* CONFIG_WDT_501_PCI */
-
-/**
- *     notify_sys:
- *     @this: our notifier block
- *     @code: the event being reported
- *     @unused: unused
- *
- *     Our notifier is called on system shutdowns. We want to turn the card
- *     off at reboot otherwise the machine will reboot again during memory
- *     test or worse yet during the following fsck. This would suck, in fact
- *     trust me - if it happens it does suck.
- */
-
-static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code==SYS_DOWN || code==SYS_HALT) {
-               /* Turn the card off */
-               wdtpci_stop();
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-
-static const struct file_operations wdtpci_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = wdtpci_write,
-       .ioctl          = wdtpci_ioctl,
-       .open           = wdtpci_open,
-       .release        = wdtpci_release,
-};
-
-static struct miscdevice wdtpci_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wdtpci_fops,
-};
-
-#ifdef CONFIG_WDT_501_PCI
-static const struct file_operations wdtpci_temp_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = wdtpci_temp_read,
-       .open           = wdtpci_temp_open,
-       .release        = wdtpci_temp_release,
-};
-
-static struct miscdevice temp_miscdev = {
-       .minor  = TEMP_MINOR,
-       .name   = "temperature",
-       .fops   = &wdtpci_temp_fops,
-};
-#endif /* CONFIG_WDT_501_PCI */
-
-/*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block wdtpci_notifier = {
-       .notifier_call = wdtpci_notify_sys,
-};
-
-
-static int __devinit wdtpci_init_one (struct pci_dev *dev,
-                                  const struct pci_device_id *ent)
-{
-       int ret = -EIO;
-
-       dev_count++;
-       if (dev_count > 1) {
-               printk (KERN_ERR PFX "this driver only supports 1 device\n");
-               return -ENODEV;
-       }
-
-       if (pci_enable_device (dev)) {
-               printk (KERN_ERR PFX "Not possible to enable PCI Device\n");
-               return -ENODEV;
-       }
-
-       if (pci_resource_start (dev, 2) == 0x0000) {
-               printk (KERN_ERR PFX "No I/O-Address for card detected\n");
-               ret = -ENODEV;
-               goto out_pci;
-       }
-
-       sema_init(&open_sem, 1);
-       spin_lock_init(&wdtpci_lock);
-
-       irq = dev->irq;
-       io = pci_resource_start (dev, 2);
-
-       if (request_region (io, 16, "wdt_pci") == NULL) {
-               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", io);
-               goto out_pci;
-       }
-
-       if (request_irq (irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED,
-                        "wdt_pci", &wdtpci_miscdev)) {
-               printk (KERN_ERR PFX "IRQ %d is not free\n", irq);
-               goto out_reg;
-       }
-
-       printk ("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n",
-               io, irq);
-
-       /* Check that the heartbeat value is within it's range ; if not reset to the default */
-       if (wdtpci_set_heartbeat(heartbeat)) {
-               wdtpci_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
-                       WD_TIMO);
-       }
-
-       ret = register_reboot_notifier (&wdtpci_notifier);
-       if (ret) {
-               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
-               goto out_irq;
-       }
-
-#ifdef CONFIG_WDT_501_PCI
-       ret = misc_register (&temp_miscdev);
-       if (ret) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       TEMP_MINOR, ret);
-               goto out_rbt;
-       }
-#endif /* CONFIG_WDT_501_PCI */
-
-       ret = misc_register (&wdtpci_miscdev);
-       if (ret) {
-               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
-               goto out_misc;
-       }
-
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-               heartbeat, nowayout);
-#ifdef CONFIG_WDT_501_PCI
-       printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled"));
-#endif /* CONFIG_WDT_501_PCI */
-
-       ret = 0;
-out:
-       return ret;
-
-out_misc:
-#ifdef CONFIG_WDT_501_PCI
-       misc_deregister(&temp_miscdev);
-out_rbt:
-#endif /* CONFIG_WDT_501_PCI */
-       unregister_reboot_notifier(&wdtpci_notifier);
-out_irq:
-       free_irq(irq, &wdtpci_miscdev);
-out_reg:
-       release_region (io, 16);
-out_pci:
-       pci_disable_device(dev);
-       goto out;
-}
-
-
-static void __devexit wdtpci_remove_one (struct pci_dev *pdev)
-{
-       /* here we assume only one device will ever have
-        * been picked up and registered by probe function */
-       misc_deregister(&wdtpci_miscdev);
-#ifdef CONFIG_WDT_501_PCI
-       misc_deregister(&temp_miscdev);
-#endif /* CONFIG_WDT_501_PCI */
-       unregister_reboot_notifier(&wdtpci_notifier);
-       free_irq(irq, &wdtpci_miscdev);
-       release_region(io, 16);
-       pci_disable_device(pdev);
-       dev_count--;
-}
-
-
-static struct pci_device_id wdtpci_pci_tbl[] = {
-       {
-               .vendor    = PCI_VENDOR_ID_ACCESSIO,
-               .device    = PCI_DEVICE_ID_WDG_CSM,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-       },
-       { 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
-
-
-static struct pci_driver wdtpci_driver = {
-       .name           = "wdt_pci",
-       .id_table       = wdtpci_pci_tbl,
-       .probe          = wdtpci_init_one,
-       .remove         = __devexit_p(wdtpci_remove_one),
-};
-
-
-/**
- *     wdtpci_cleanup:
- *
- *     Unload the watchdog. You cannot do this with any file handles open.
- *     If your watchdog is set to continue ticking on close and you unload
- *     it, well it keeps ticking. We won't get the interrupt but the board
- *     will not touch PC memory so all is fine. You just have to load a new
- *     module in xx seconds or reboot.
- */
-
-static void __exit wdtpci_cleanup(void)
-{
-       pci_unregister_driver (&wdtpci_driver);
-}
-
-
-/**
- *     wdtpci_init:
- *
- *     Set up the WDT watchdog board. All we have to do is grab the
- *     resources we require and bitch if anyone beat us to them.
- *     The open() function will actually kick the board off.
- */
-
-static int __init wdtpci_init(void)
-{
-       return pci_register_driver (&wdtpci_driver);
-}
-
-
-module_init(wdtpci_init);
-module_exit(wdtpci_cleanup);
-
-MODULE_AUTHOR("JP Nollmann, Alan Cox");
-MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
new file mode 100644 (file)
index 0000000..37bddc1
--- /dev/null
@@ -0,0 +1,853 @@
+#
+# Watchdog device configuration
+#
+
+menuconfig WATCHDOG
+       bool "Watchdog Timer Support"
+       ---help---
+         If you say Y here (and to one of the following options) and create a
+         character special file /dev/watchdog with major number 10 and minor
+         number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
+         subsequently opening the file and then failing to write to it for
+         longer than 1 minute will result in rebooting the machine. This
+         could be useful for a networked machine that needs to come back
+         on-line as fast as possible after a lock-up. There's both a watchdog
+         implementation entirely in software (which can sometimes fail to
+         reboot the machine) and a driver for hardware watchdog boards, which
+         are more robust and can also keep track of the temperature inside
+         your computer. For details, read <file:Documentation/watchdog/watchdog.txt>
+         in the kernel source.
+
+         The watchdog is usually used together with the watchdog daemon
+         which is available from
+         <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+         also monitor NFS connections and can reboot the machine when the process
+         table is full.
+
+         If unsure, say N.
+
+if WATCHDOG
+
+config WATCHDOG_NOWAYOUT
+       bool "Disable watchdog shutdown on close"
+       help
+         The default watchdog behaviour (which you get if you say N here) is
+         to stop the timer if the process managing it closes the file
+         /dev/watchdog. It's always remotely possible that this process might
+         get killed. If you say Y here, the watchdog cannot be stopped once
+         it has been started.
+
+#
+# General Watchdog drivers
+#
+
+comment "Watchdog Device Drivers"
+
+# Architecture Independent
+
+config SOFT_WATCHDOG
+       tristate "Software watchdog"
+       help
+         A software monitoring watchdog. This will fail to reboot your system
+         from some situations that the hardware watchdog will recover
+         from. Equally it's a lot cheaper to install.
+
+         To compile this driver as a module, choose M here: the
+         module will be called softdog.
+
+# ALPHA Architecture
+
+# ARM Architecture
+
+config AT91RM9200_WATCHDOG
+       tristate "AT91RM9200 watchdog"
+       depends on ARCH_AT91RM9200
+       help
+         Watchdog timer embedded into AT91RM9200 chips. This will reboot your
+         system when the timeout is reached.
+
+config 21285_WATCHDOG
+       tristate "DC21285 watchdog"
+       depends on FOOTBRIDGE
+       help
+         The Intel Footbridge chip contains a built-in watchdog circuit. Say Y
+         here if you wish to use this. Alternatively say M to compile the
+         driver as a module, which will be called wdt285.
+
+         This driver does not work on all machines. In particular, early CATS
+         boards have hardware problems that will cause the machine to simply
+         lock up if the watchdog fires.
+
+         "If in doubt, leave it out" - say N.
+
+config 977_WATCHDOG
+       tristate "NetWinder WB83C977 watchdog"
+       depends on FOOTBRIDGE && ARCH_NETWINDER
+       help
+         Say Y here to include support for the WB977 watchdog included in
+         NetWinder machines. Alternatively say M to compile the driver as
+         a module, which will be called wdt977.
+
+         Not sure? It's safe to say N.
+
+config IXP2000_WATCHDOG
+       tristate "IXP2000 Watchdog"
+       depends on ARCH_IXP2000
+       help
+         Say Y here if to include support for the watchdog timer
+         in the Intel IXP2000(2400, 2800, 2850) network processors.
+         This driver can be built as a module by choosing M. The module
+         will be called ixp2000_wdt.
+
+         Say N if you are unsure.
+
+config IXP4XX_WATCHDOG
+       tristate "IXP4xx Watchdog"
+       depends on ARCH_IXP4XX
+       help
+         Say Y here if to include support for the watchdog timer
+         in the Intel IXP4xx network processors. This driver can
+         be built as a module by choosing M. The module will
+         be called ixp4xx_wdt.
+
+         Note: The internal IXP4xx watchdog does a soft CPU reset
+         which doesn't reset any peripherals. There are circumstances
+         where the watchdog will fail to reset the board correctly
+         (e.g., if the boot ROM is in an unreadable state).
+
+         Say N if you are unsure.
+
+config KS8695_WATCHDOG
+       tristate "KS8695 watchdog"
+       depends on ARCH_KS8695
+       help
+         Watchdog timer embedded into KS8695 processor. This will reboot your
+         system when the timeout is reached.
+
+config S3C2410_WATCHDOG
+       tristate "S3C2410 Watchdog"
+       depends on ARCH_S3C2410
+       help
+         Watchdog timer block in the Samsung S3C2410 chips. This will
+         reboot the system when the timer expires with the watchdog
+         enabled.
+
+         The driver is limited by the speed of the system's PCLK
+         signal, so with reasonably fast systems (PCLK around 50-66MHz)
+         then watchdog intervals of over approximately 20seconds are
+         unavailable.
+
+         The driver can be built as a module by choosing M, and will
+         be called s3c2410_wdt
+
+config SA1100_WATCHDOG
+       tristate "SA1100/PXA2xx watchdog"
+       depends on ARCH_SA1100 || ARCH_PXA
+       help
+         Watchdog timer embedded into SA11x0 and PXA2xx chips. This will
+         reboot your system when timeout is reached.
+
+         NOTE: once enabled, this timer cannot be disabled.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sa1100_wdt.
+
+config MPCORE_WATCHDOG
+       tristate "MPcore watchdog"
+       depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+       help
+         Watchdog timer embedded into the MPcore system.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mpcore_wdt.
+
+config EP93XX_WATCHDOG
+       tristate "EP93xx Watchdog"
+       depends on ARCH_EP93XX
+       help
+         Say Y here if to include support for the watchdog timer
+         embedded in the Cirrus Logic EP93xx family of devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ep93xx_wdt.
+
+config OMAP_WATCHDOG
+       tristate "OMAP Watchdog"
+       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+       help
+         Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
+         enable the OMAP1610/OMAP1710 watchdog timer.
+
+config PNX4008_WATCHDOG
+       tristate "PNX4008 Watchdog"
+       depends on ARCH_PNX4008
+       help
+         Say Y here if to include support for the watchdog timer
+         in the PNX4008 processor.
+         This driver can be built as a module by choosing M. The module
+         will be called pnx4008_wdt.
+
+         Say N if you are unsure.
+
+config IOP_WATCHDOG
+       tristate "IOP Watchdog"
+       depends on PLAT_IOP
+       select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
+       help
+         Say Y here if to include support for the watchdog timer
+         in the Intel IOP3XX & IOP13XX I/O Processors.  This driver can
+         be built as a module by choosing M. The module will
+         be called iop_wdt.
+
+         Note: The IOP13XX watchdog does an Internal Bus Reset which will
+         affect both cores and the peripherals of the IOP.  The ATU-X
+         and/or ATUe configuration registers will remain intact, but if
+         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 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
+       tristate "Acquire SBC Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on Single Board
+         Computers produced by Acquire Inc (and others). This watchdog
+         simply watches your kernel to make sure it doesn't freeze, and if
+         it does, it reboots your computer after a certain amount of time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called acquirewdt.
+
+         Most people will say N.
+
+config ADVANTECH_WDT
+       tristate "Advantech SBC Watchdog Timer"
+       depends on X86
+       help
+         If you are configuring a Linux kernel for the Advantech single-board
+         computer, say `Y' here to support its built-in watchdog timer
+         feature. More information can be found at
+         <http://www.advantech.com.tw/products/>
+
+config ALIM1535_WDT
+       tristate "ALi M1535 PMU Watchdog Timer"
+       depends on X86 && PCI
+       ---help---
+         This is the driver for the hardware watchdog on the ALi M1535 PMU.
+
+         To compile this driver as a module, choose M here: the
+         module will be called alim1535_wdt.
+
+         Most people will say N.
+
+config ALIM7101_WDT
+       tristate "ALi M7101 PMU Computer Watchdog"
+       depends on X86 && PCI
+       help
+         This is the driver for the hardware watchdog on the ALi M7101 PMU
+         as used in the x86 Cobalt servers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called alim7101_wdt.
+
+         Most people will say N.
+
+config SC520_WDT
+       tristate "AMD Elan SC520 processor Watchdog"
+       depends on X86
+       help
+         This is the driver for the hardware watchdog built in to the
+         AMD "Elan" SC520 microcomputer commonly used in embedded systems.
+         This watchdog simply watches your kernel to make sure it doesn't
+         freeze, and if it does, it reboots your computer after a certain
+         amount of time.
+
+         You can compile this driver directly into the kernel, or use
+         it as a module.  The module will be called sc520_wdt.
+
+config EUROTECH_WDT
+       tristate "Eurotech CPU-1220/1410 Watchdog Timer"
+       depends on X86
+       help
+         Enable support for the watchdog timer on the Eurotech CPU-1220 and
+         CPU-1410 cards.  These are PC/104 SBCs. Spec sheets and product
+         information are at <http://www.eurotech.it/>.
+
+config IB700_WDT
+       tristate "IB700 SBC Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the IB700 Single
+         Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
+         simply watches your kernel to make sure it doesn't freeze, and if
+         it does, it reboots your computer after a certain amount of time.
+
+         This driver is like the WDT501 driver but for slightly different hardware.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ib700wdt.
+
+         Most people will say N.
+
+config IBMASR
+       tristate "IBM Automatic Server Restart"
+       depends on X86
+       help
+         This is the driver for the IBM Automatic Server Restart watchdog
+         timer built-in into some eServer xSeries machines.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ibmasr.
+
+config WAFER_WDT
+       tristate "ICP Wafer 5823 Single Board Computer Watchdog"
+       depends on X86
+       help
+         This is a driver for the hardware watchdog on the ICP Wafer 5823
+         Single Board Computer (and probably other similar models).
+
+         To compile this driver as a module, choose M here: the
+         module will be called wafer5823wdt.
+
+config I6300ESB_WDT
+       tristate "Intel 6300ESB Timer/Watchdog"
+       depends on X86 && PCI
+       ---help---
+         Hardware driver for the watchdog timer built into the Intel
+         6300ESB controller hub.
+
+         To compile this driver as a module, choose M here: the
+         module will be called i6300esb.
+
+config ITCO_WDT
+       tristate "Intel TCO Timer/Watchdog"
+       depends on (X86 || IA64) && PCI
+       ---help---
+         Hardware driver for the intel TCO timer based watchdog devices.
+         These drivers are included in the Intel 82801 I/O Controller
+         Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB
+         controller hub.
+
+         The TCO (Total Cost of Ownership) timer is a watchdog timer
+         that will reboot the machine after its second expiration. The
+         expiration time can be configured with the "heartbeat" parameter.
+
+         On some motherboards the driver may fail to reset the chipset's
+         NO_REBOOT flag which prevents the watchdog from rebooting the
+         machine. If this is the case you will get a kernel message like
+         "failed to reset NO_REBOOT flag, reboot disabled by hardware".
+
+         To compile this driver as a module, choose M here: the
+         module will be called iTCO_wdt.
+
+config ITCO_VENDOR_SUPPORT
+       bool "Intel TCO Timer/Watchdog Specific Vendor Support"
+       depends on ITCO_WDT
+       ---help---
+         Add vendor specific support to the intel TCO timer based watchdog
+         devices. At this moment we only have additional support for some
+         SuperMicro Inc. motherboards.
+
+config SC1200_WDT
+       tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
+       depends on X86
+       help
+         This is a driver for National Semiconductor PC87307/PC97307 hardware
+         watchdog cards as found on the SC1200. This watchdog is mainly used
+         for power management purposes and can be used to power down the device
+         during inactivity periods (includes interrupt activity monitoring).
+
+         To compile this driver as a module, choose M here: the
+         module will be called sc1200wdt.
+
+         Most people will say N.
+
+config SCx200_WDT
+       tristate "National Semiconductor SCx200 Watchdog"
+       depends on SCx200 && PCI
+       help
+         Enable the built-in watchdog timer support on the National
+         Semiconductor SCx200 processors.
+
+         If compiled as a module, it will be called scx200_wdt.
+
+config PC87413_WDT
+       tristate "NS PC87413 watchdog"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the PC87413 chipset
+         This watchdog simply watches your kernel to make sure it doesn't
+         freeze, and if it does, it reboots your computer after a certain
+         amount of time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pc87413_wdt.
+
+         Most people will say N.
+config 60XX_WDT
+       tristate "SBC-60XX Watchdog Timer"
+       depends on X86
+       help
+         This driver can be used with the watchdog timer found on some
+         single board computers, namely the 6010 PII based computer.
+         It may well work with other cards.  It reads port 0x443 to enable
+         and re-set the watchdog timer, and reads port 0x45 to disable
+         the watchdog.  If you have a card that behave in similar ways,
+         you can probably make this driver work with your card as well.
+
+         You can compile this driver directly into the kernel, or use
+         it as a module.  The module will be called sbc60xxwdt.
+
+config SBC8360_WDT
+       tristate "SBC8360 Watchdog Timer"
+       depends on X86
+       ---help---
+
+         This is the driver for the hardware watchdog on the SBC8360 Single
+         Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+         To compile this driver as a module, choose M here: the
+         module will be called sbc8360.ko.
+
+         Most people will say N.
+
+config CPU5_WDT
+       tristate "SMA CPU5 Watchdog"
+       depends on X86
+       ---help---
+         TBD.
+         To compile this driver as a module, choose M here: the
+         module will be called cpu5wdt.
+
+config SMSC37B787_WDT
+       tristate "Winbond SMsC37B787 Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog component on the
+         Winbond SMsC37B787 chipset as used on the NetRunner Mainboard
+         from Vision Systems and maybe others.
+
+         This watchdog simply watches your kernel to make sure it doesn't
+         freeze, and if it does, it reboots your computer after a certain
+         amount of time.
+
+         Usually a userspace daemon will notify the kernel WDT driver that
+         userspace is still alive, at regular intervals.
+
+         To compile this driver as a module, choose M here: the
+         module will be called smsc37b787_wdt.
+
+         Most people will say N.
+
+config W83627HF_WDT
+       tristate "W83627HF Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the W83627HF chipset
+         as used in Advantech PC-9578 and Tyan S2721-533 motherboards
+         (and likely others).  This watchdog simply watches your kernel to
+         make sure it doesn't freeze, and if it does, it reboots your computer
+         after a certain amount of time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called w83627hf_wdt.
+
+         Most people will say N.
+
+config W83697HF_WDT
+       tristate "W83697HF/W83697HG Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the W83697HF/HG
+         chipset as used in Dedibox/VIA motherboards (and likely others).
+         This watchdog simply watches your kernel to make sure it doesn't
+         freeze, and if it does, it reboots your computer after a certain
+         amount of time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called w83697hf_wdt.
+
+         Most people will say N.
+
+config W83877F_WDT
+       tristate "W83877F (EMACS) Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the W83877F chipset
+         as used in EMACS PC-104 motherboards (and likely others).  This
+         watchdog simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called w83877f_wdt.
+
+         Most people will say N.
+
+config W83977F_WDT
+       tristate "W83977F (PCM-5335) Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog on the W83977F I/O chip
+         as used in AAEON's PCM-5335 SBC (and likely others).  This
+         watchdog simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called w83977f_wdt.
+
+config MACHZ_WDT
+       tristate "ZF MachZ Watchdog"
+       depends on X86
+       ---help---
+         If you are using a ZF Micro MachZ processor, say Y here, otherwise
+         N.  This is the driver for the watchdog timer built-in on that
+         processor using ZF-Logic interface.  This watchdog simply watches
+         your kernel to make sure it doesn't freeze, and if it does, it
+         reboots your computer after a certain amount of time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called machzwd.
+
+config SBC_EPX_C3_WATCHDOG
+       tristate "Winsystems SBC EPX-C3 watchdog"
+       depends on X86
+       ---help---
+         This is the driver for the built-in watchdog timer on the EPX-C3
+         Single-board computer made by Winsystems, Inc.
+
+         *Note*: This hardware watchdog is not probeable and thus there
+         is no way to know if writing to its IO address will corrupt
+         your system or have any real effect.  The only way to be sure
+         that this driver does what you want is to make sure you
+         are running it on an EPX-C3 from Winsystems with the watchdog
+         timer at IO address 0x1ee and 0x1ef.  It will write to both those
+         IO ports.  Basically, the assumption is made that if you compile
+         this driver into your kernel and/or load it as a module, that you
+         know what you are doing and that you are in fact running on an
+         EPX-C3 board!
+
+         To compile this driver as a module, choose M here: the
+         module will be called sbc_epx_c3.
+
+# M32R Architecture
+
+# M68K Architecture
+
+# M68KNOMMU Architecture
+
+# MIPS Architecture
+
+config INDYDOG
+       tristate "Indy/I2 Hardware Watchdog"
+       depends on SGI_IP22
+       help
+         Hardware driver for the Indy's/I2's watchdog. This is a
+         watchdog timer that will reboot the machine after a 60 second
+         timer expired and no process has written to /dev/watchdog during
+         that time.
+
+config WDT_MTX1
+       tristate "MTX-1 Hardware Watchdog"
+       depends on MIPS_MTX1
+       help
+         Hardware driver for the MTX-1 boards. This is a watchdog timer that
+         will reboot the machine after a 100 seconds timer expired.
+
+config WDT_RM9K_GPI
+       tristate "RM9000/GPI hardware watchdog"
+       depends on CPU_RM9000
+       help
+         Watchdog implementation using the GPI hardware found on
+         PMC-Sierra RM9xxx CPUs.
+
+         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
+       tristate "z/VM Watchdog Timer"
+       depends on S390
+       help
+         IBM s/390 and zSeries machines running under z/VM 5.1 or later
+         provide a virtual watchdog timer to their guest that cause a
+         user define Control Program command to be executed after a
+         timeout.
+
+         To compile this driver as a module, choose M here. The module
+         will be called vmwatchdog.
+
+# SUPERH (sh + sh64) Architecture
+
+config SH_WDT
+       tristate "SuperH Watchdog"
+       depends on SUPERH && (CPU_SH3 || CPU_SH4)
+       help
+         This driver adds watchdog support for the integrated watchdog in the
+         SuperH processors. If you have one of these processors and wish
+         to have watchdog support enabled, say Y, otherwise say N.
+
+         As a side note, saying Y here will automatically boost HZ to 1000
+         so that the timer has a chance to clear the overflow counter. On
+         slower systems (such as the SH-2 and SH-3) this will likely yield
+         some performance issues. As such, the WDT should be avoided here
+         unless it is absolutely necessary.
+
+         To compile this driver as a module, choose M here: the
+         module will be called shwdt.
+
+config SH_WDT_MMAP
+       bool "Allow mmap of SH WDT"
+       default n
+       depends on SH_WDT
+       help
+         If you say Y here, user applications will be able to mmap the
+         WDT/CPG registers.
+
+# SPARC Architecture
+
+# SPARC64 Architecture
+
+config WATCHDOG_CP1XXX
+       tristate "CP1XXX Hardware Watchdog support"
+       depends on SPARC64 && PCI
+       ---help---
+         This is the driver for the hardware watchdog timers present on
+         Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cpwatchdog.
+
+         If you do not have a CompactPCI model CP1400 or CP1500, or
+         another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
+         you should say N to this option.
+
+config WATCHDOG_RIO
+       tristate "RIO Hardware Watchdog support"
+       depends on SPARC64 && PCI
+       help
+         Say Y here to support the hardware watchdog capability on Sun 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
+#
+
+comment "ISA-based Watchdog Cards"
+       depends on ISA
+
+config PCWATCHDOG
+       tristate "Berkshire Products ISA-PC Watchdog"
+       depends on ISA
+       ---help---
+         This is the driver for the Berkshire Products ISA-PC Watchdog card.
+         This card simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time. This driver is like the WDT501 driver but for different
+         hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.txt>. The PC
+         watchdog cards can be ordered from <http://www.berkprod.com/>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pcwd.
+
+         Most people will say N.
+
+config MIXCOMWD
+       tristate "Mixcom Watchdog"
+       depends on ISA
+       ---help---
+         This is a driver for the Mixcom hardware watchdog cards.  This
+         watchdog simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mixcomwd.
+
+         Most people will say N.
+
+config WDT
+       tristate "WDT Watchdog timer"
+       depends on ISA
+       ---help---
+         If you have a WDT500P or WDT501P watchdog board, say Y here,
+         otherwise N. It is not possible to probe for this board, which means
+         that you have to inform the kernel about the IO port and IRQ that
+         is needed (you can do this via the io and irq parameters)
+
+         To compile this driver as a module, choose M here: the
+         module will be called wdt.
+
+config WDT_501
+       bool "WDT501 features"
+       depends on WDT
+       help
+         Saying Y here and creating a character special file /dev/temperature
+         with major number 10 and minor number 131 ("man mknod") will give
+         you a thermometer inside your computer: reading from
+         /dev/temperature yields one byte, the temperature in degrees
+         Fahrenheit. This works only if you have a WDT501P watchdog board
+         installed.
+
+         If you want to enable the Fan Tachometer on the WDT501P, then you
+         can do this via the tachometer parameter. Only do this if you have a
+         fan tachometer actually set up.
+
+#
+# PCI-based Watchdog Cards
+#
+
+comment "PCI-based Watchdog Cards"
+       depends on PCI
+
+config PCIPCWATCHDOG
+       tristate "Berkshire Products PCI-PC Watchdog"
+       depends on PCI
+       ---help---
+         This is the driver for the Berkshire Products PCI-PC Watchdog card.
+         This card simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time. The card can also monitor the internal temperature of the PC.
+         More info is available at <http://www.berkprod.com/pci_pc_watchdog.htm>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pcwd_pci.
+
+         Most people will say N.
+
+config WDTPCI
+       tristate "PCI-WDT500/501 Watchdog timer"
+       depends on PCI
+       ---help---
+         If you have a PCI-WDT500/501 watchdog board, say Y here, otherwise N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wdt_pci.
+
+config WDT_501_PCI
+       bool "PCI-WDT501 features"
+       depends on WDTPCI
+       help
+         Saying Y here and creating a character special file /dev/temperature
+         with major number 10 and minor number 131 ("man mknod") will give
+         you a thermometer inside your computer: reading from
+         /dev/temperature yields one byte, the temperature in degrees
+         Fahrenheit. This works only if you have a PCI-WDT501 watchdog board
+         installed.
+
+         If you want to enable the Fan Tachometer on the PCI-WDT501, then you
+         can do this via the tachometer parameter. Only do this if you have a
+         fan tachometer actually set up.
+
+#
+# USB-based Watchdog Cards
+#
+
+comment "USB-based Watchdog Cards"
+       depends on USB
+
+config USBPCWATCHDOG
+       tristate "Berkshire Products USB-PC Watchdog"
+       depends on USB
+       ---help---
+         This is the driver for the Berkshire Products USB-PC Watchdog card.
+         This card simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time. The card can also monitor the internal temperature of the PC.
+         More info is available at <http://www.berkprod.com/usb_pc_watchdog.htm>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pcwd_usb.
+
+         Most people will say N.
+
+endif # WATCHDOG
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
new file mode 100644 (file)
index 0000000..389f8b1
--- /dev/null
@@ -0,0 +1,120 @@
+#
+# Makefile for the WatchDog device drivers.
+#
+
+# Only one watchdog can succeed. We probe the ISA/PCI/USB based
+# watchdog-cards first, then the architecture specific watchdog
+# drivers and then the architecture independant "softdog" driver.
+# This means that if your ISA/PCI/USB card isn't detected that
+# you can fall back to an architecture specific driver and if
+# that also fails then you can fall back to the software watchdog
+# to give you some cover.
+
+# ISA-based Watchdog Cards
+obj-$(CONFIG_PCWATCHDOG) += pcwd.o
+obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
+obj-$(CONFIG_WDT) += wdt.o
+
+# PCI-based Watchdog Cards
+obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
+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
+obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
+obj-$(CONFIG_977_WATCHDOG) += wdt977.o
+obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
+obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
+obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
+obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
+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
+obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
+obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
+obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
+obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
+obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
+obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
+obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
+obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
+obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
+obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
+obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
+obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
+obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
+obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
+obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
+obj-$(CONFIG_MACHZ_WDT) += machzwd.o
+obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
+
+# 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
+
+# PPC64 Architecture
+obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
+
+# S390 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/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
new file mode 100644 (file)
index 0000000..85269c3
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ *     Acquire Single Board Computer Watchdog Timer driver
+ *
+ *      Based on wdt.c. Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Can't add timeout - driver doesn't allow changing value
+ */
+
+/*
+ *     Theory of Operation:
+ *             The Watch-Dog Timer is provided to ensure that standalone
+ *             Systems can always recover from catastrophic conditions that
+ *             caused the CPU to crash. This condition may have occured by
+ *             external EMI or a software bug. When the CPU stops working
+ *             correctly, hardware on the board will either perform a hardware
+ *             reset (cold boot) or a non-maskable interrupt (NMI) to bring the
+ *             system back to a known state.
+ *
+ *             The Watch-Dog Timer is controlled by two I/O Ports.
+ *               443 hex       - Read  - Enable or refresh the Watch-Dog Timer
+ *               043 hex       - Read  - Disable the Watch-Dog Timer
+ *
+ *             To enable the Watch-Dog Timer, a read from I/O port 443h must
+ *             be performed. This will enable and activate the countdown timer
+ *             which will eventually time out and either reset the CPU or cause
+ *             an NMI depending on the setting of a jumper. To ensure that this
+ *             reset condition does not occur, the Watch-Dog Timer must be
+ *             periodically refreshed by reading the same I/O port 443h.
+ *             The Watch-Dog Timer is disabled by reading I/O port 043h.
+ *
+ *             The Watch-Dog Timer Time-Out Period is set via jumpers.
+ *             It can be 1, 2, 10, 20, 110 or 220 seconds.
+ */
+
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
+
+/* Includes */
+#include <linux/module.h>              /* For module specific items */
+#include <linux/moduleparam.h>         /* For new moduleparam's */
+#include <linux/types.h>               /* For standard types (like size_t) */
+#include <linux/errno.h>               /* For the -ENODEV/... values */
+#include <linux/kernel.h>              /* For printk/panic/... */
+#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>            /* For the watchdog specific items */
+#include <linux/fs.h>                  /* For file operations */
+#include <linux/ioport.h>              /* For io-port access */
+#include <linux/platform_device.h>     /* For platform_driver framework */
+#include <linux/init.h>                        /* For __init/__exit/... */
+
+#include <asm/uaccess.h>               /* For copy_to_user/put_user/... */
+#include <asm/io.h>                    /* For inb/outb/... */
+
+/* Module information */
+#define DRV_NAME "acquirewdt"
+#define PFX DRV_NAME ": "
+#define WATCHDOG_NAME "Acquire WDT"
+#define WATCHDOG_HEARTBEAT 0   /* There is no way to see what the correct time-out period is */
+
+/* internal variables */
+static struct platform_device *acq_platform_device;    /* the watchdog platform device */
+static unsigned long acq_is_open;
+static char expect_close;
+
+/* module parameters */
+static int wdt_stop = 0x43;    /* You must set this - there is no sane way to probe for this board. */
+module_param(wdt_stop, int, 0);
+MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");
+
+static int wdt_start = 0x443;  /* You must set this - there is no sane way to probe for this board. */
+module_param(wdt_start, int, 0);
+MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
+
+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) ")");
+
+/*
+ *     Watchdog Operations
+ */
+
+static void acq_keepalive(void)
+{
+       /* Write a watchdog value */
+       inb_p(wdt_start);
+}
+
+static void acq_stop(void)
+{
+       /* Turn the card off */
+       inb_p(wdt_stop);
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+
+               /* Well, anyhow someone wrote to us, we should return that favour */
+               acq_keepalive();
+       }
+       return count;
+}
+
+static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       int options, retval = -EINVAL;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident =
+       {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = WATCHDOG_NAME,
+       };
+
+       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:
+         acq_keepalive();
+         return 0;
+
+       case WDIOC_GETTIMEOUT:
+         return put_user(WATCHDOG_HEARTBEAT, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+           if (get_user(options, p))
+             return -EFAULT;
+
+           if (options & WDIOS_DISABLECARD)
+           {
+             acq_stop();
+             retval = 0;
+           }
+
+           if (options & WDIOS_ENABLECARD)
+           {
+             acq_keepalive();
+             retval = 0;
+           }
+
+           return retval;
+       }
+
+       default:
+         return -ENOTTY;
+       }
+}
+
+static int acq_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &acq_is_open))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate */
+       acq_keepalive();
+       return nonseekable_open(inode, file);
+}
+
+static int acq_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               acq_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               acq_keepalive();
+       }
+       clear_bit(0, &acq_is_open);
+       expect_close = 0;
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations acq_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = acq_write,
+       .ioctl          = acq_ioctl,
+       .open           = acq_open,
+       .release        = acq_close,
+};
+
+static struct miscdevice acq_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &acq_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int __devinit acq_probe(struct platform_device *dev)
+{
+       int ret;
+
+       if (wdt_stop != wdt_start) {
+               if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
+                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                               wdt_stop);
+                       ret = -EIO;
+                       goto out;
+               }
+       }
+
+       if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
+               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_start);
+               ret = -EIO;
+               goto unreg_stop;
+       }
+
+       ret = misc_register(&acq_miscdev);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto unreg_regions;
+       }
+
+       printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
+               nowayout);
+
+       return 0;
+
+unreg_regions:
+       release_region(wdt_start, 1);
+unreg_stop:
+       if (wdt_stop != wdt_start)
+               release_region(wdt_stop, 1);
+out:
+       return ret;
+}
+
+static int __devexit acq_remove(struct platform_device *dev)
+{
+       misc_deregister(&acq_miscdev);
+       release_region(wdt_start,1);
+       if(wdt_stop != wdt_start)
+               release_region(wdt_stop,1);
+
+       return 0;
+}
+
+static void acq_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       acq_stop();
+}
+
+static struct platform_driver acquirewdt_driver = {
+       .probe          = acq_probe,
+       .remove         = __devexit_p(acq_remove),
+       .shutdown       = acq_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init acq_init(void)
+{
+       int err;
+
+       printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");
+
+       err = platform_driver_register(&acquirewdt_driver);
+       if (err)
+               return err;
+
+       acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(acq_platform_device)) {
+               err = PTR_ERR(acq_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&acquirewdt_driver);
+       return err;
+}
+
+static void __exit acq_exit(void)
+{
+       platform_device_unregister(acq_platform_device);
+       platform_driver_unregister(&acquirewdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(acq_init);
+module_exit(acq_exit);
+
+MODULE_AUTHOR("David Woodhouse");
+MODULE_DESCRIPTION("Acquire Inc. Single Board Computer Watchdog Timer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
new file mode 100644 (file)
index 0000000..8121cc2
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ *     Advantech Single Board Computer WDT driver
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     Based on acquirewdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
+ *
+ *     14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *         Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ *     16-Oct-2002 Rob Radez <rob@osinvestor.com>
+ *         Clean up ioctls, clean up init + exit, add expect close support,
+ *         add wdt_start and wdt_stop as parameters.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define DRV_NAME "advantechwdt"
+#define PFX DRV_NAME ": "
+#define WATCHDOG_NAME "Advantech WDT"
+#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
+
+static struct platform_device *advwdt_platform_device; /* the watchdog platform device */
+static unsigned long advwdt_is_open;
+static char adv_expect_close;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ *
+ *     To enable or restart, write the timeout value in seconds (1 to 63)
+ *     to I/O port wdt_start.  To disable, read I/O port wdt_stop.
+ *     Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
+ *     check your manual (at least the PCA-6159 seems to be different -
+ *     the manual says wdt_stop is 0x43, not 0x443).
+ *     (0x43 is also a write-only control register for the 8254 timer!)
+ */
+
+static int wdt_stop = 0x443;
+module_param(wdt_stop, int, 0);
+MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)");
+
+static int wdt_start = 0x443;
+module_param(wdt_start, int, 0);
+MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)");
+
+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) ".");
+
+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) ")");
+
+/*
+ *     Watchdog Operations
+ */
+
+static void
+advwdt_ping(void)
+{
+       /* Write a watchdog value */
+       outb_p(timeout, wdt_start);
+}
+
+static void
+advwdt_disable(void)
+{
+       inb_p(wdt_stop);
+}
+
+static int
+advwdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 63))
+               return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t
+advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       adv_expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       adv_expect_close = 42;
+                       }
+               }
+               advwdt_ping();
+       }
+       return count;
+}
+
+static int
+advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       int new_timeout;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = WATCHDOG_NAME,
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user(argp, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+         return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+         advwdt_ping();
+         break;
+
+       case WDIOC_SETTIMEOUT:
+         if (get_user(new_timeout, p))
+                 return -EFAULT;
+         if (advwdt_set_heartbeat(new_timeout))
+                 return -EINVAL;
+         advwdt_ping();
+         /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+         return put_user(timeout, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+         int options, retval = -EINVAL;
+
+         if (get_user(options, p))
+           return -EFAULT;
+
+         if (options & WDIOS_DISABLECARD) {
+           advwdt_disable();
+           retval = 0;
+         }
+
+         if (options & WDIOS_ENABLECARD) {
+           advwdt_ping();
+           retval = 0;
+         }
+
+         return retval;
+       }
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+advwdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &advwdt_is_open))
+               return -EBUSY;
+       /*
+        *      Activate
+        */
+
+       advwdt_ping();
+       return nonseekable_open(inode, file);
+}
+
+static int
+advwdt_close(struct inode *inode, struct file *file)
+{
+       if (adv_expect_close == 42) {
+               advwdt_disable();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               advwdt_ping();
+       }
+       clear_bit(0, &advwdt_is_open);
+       adv_expect_close = 0;
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations advwdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = advwdt_write,
+       .ioctl          = advwdt_ioctl,
+       .open           = advwdt_open,
+       .release        = advwdt_close,
+};
+
+static struct miscdevice advwdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &advwdt_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int __devinit
+advwdt_probe(struct platform_device *dev)
+{
+       int ret;
+
+       if (wdt_stop != wdt_start) {
+               if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
+                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                               wdt_stop);
+                       ret = -EIO;
+                       goto out;
+               }
+       }
+
+       if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
+               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_start);
+               ret = -EIO;
+               goto unreg_stop;
+       }
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (advwdt_set_heartbeat(timeout)) {
+               advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
+                       timeout);
+       }
+
+       ret = misc_register(&advwdt_miscdev);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto unreg_regions;
+       }
+
+       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+out:
+       return ret;
+unreg_regions:
+       release_region(wdt_start, 1);
+unreg_stop:
+       if (wdt_stop != wdt_start)
+               release_region(wdt_stop, 1);
+       goto out;
+}
+
+static int __devexit
+advwdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&advwdt_miscdev);
+       release_region(wdt_start,1);
+       if(wdt_stop != wdt_start)
+               release_region(wdt_stop,1);
+
+       return 0;
+}
+
+static void
+advwdt_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       advwdt_disable();
+}
+
+static struct platform_driver advwdt_driver = {
+       .probe          = advwdt_probe,
+       .remove         = __devexit_p(advwdt_remove),
+       .shutdown       = advwdt_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init
+advwdt_init(void)
+{
+       int err;
+
+       printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
+
+       err = platform_driver_register(&advwdt_driver);
+       if (err)
+               return err;
+
+       advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(advwdt_platform_device)) {
+               err = PTR_ERR(advwdt_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&advwdt_driver);
+       return err;
+}
+
+static void __exit
+advwdt_exit(void)
+{
+       platform_device_unregister(advwdt_platform_device);
+       platform_driver_unregister(&advwdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(advwdt_init);
+module_exit(advwdt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Michalkiewicz <marekm@linux.org.pl>");
+MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
new file mode 100644 (file)
index 0000000..c404fc6
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ *     Watchdog for the 7101 PMU version found in the ALi M1535 chipsets
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define WATCHDOG_NAME "ALi_M1535"
+#define PFX WATCHDOG_NAME ": "
+#define WATCHDOG_TIMEOUT 60    /* 60 sec default timeout */
+
+/* internal variables */
+static unsigned long ali_is_open;
+static char ali_expect_release;
+static struct pci_dev *ali_pci;
+static u32 ali_timeout_bits;   /* stores the computed timeout */
+static spinlock_t ali_lock;    /* Guards the hardware */
+
+/* module parameters */
+static int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+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) ")");
+
+/*
+ *     ali_start       -       start watchdog countdown
+ *
+ *     Starts the timer running providing the timer has a counter
+ *     configuration set.
+ */
+
+static void ali_start(void)
+{
+       u32 val;
+
+       spin_lock(&ali_lock);
+
+       pci_read_config_dword(ali_pci, 0xCC, &val);
+       val &= ~0x3F;   /* Mask count */
+       val |= (1<<25) | ali_timeout_bits;
+       pci_write_config_dword(ali_pci, 0xCC, val);
+
+       spin_unlock(&ali_lock);
+}
+
+/*
+ *     ali_stop        -       stop the timer countdown
+ *
+ *     Stop the ALi watchdog countdown
+ */
+
+static void ali_stop(void)
+{
+       u32 val;
+
+       spin_lock(&ali_lock);
+
+       pci_read_config_dword(ali_pci, 0xCC, &val);
+       val &= ~0x3F;   /* Mask count to zero (disabled) */
+       val &= ~(1<<25);/* and for safety mask the reset enable */
+       pci_write_config_dword(ali_pci, 0xCC, val);
+
+       spin_unlock(&ali_lock);
+}
+
+/*
+ *     ali_keepalive   -       send a keepalive to the watchdog
+ *
+ *      Send a keepalive to the timer (actually we restart the timer).
+ */
+
+static void ali_keepalive(void)
+{
+       ali_start();
+}
+
+/*
+ *     ali_settimer    -       compute the timer reload value
+ *     @t: time in seconds
+ *
+ *     Computes the timeout values needed
+ */
+
+static int ali_settimer(int t)
+{
+       if(t < 0)
+               return -EINVAL;
+       else if(t < 60)
+               ali_timeout_bits = t|(1<<6);
+       else if(t < 3600)
+               ali_timeout_bits = (t/60)|(1<<7);
+       else if(t < 18000)
+               ali_timeout_bits = (t/300)|(1<<6)|(1<<7);
+       else return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+/*
+ *     ali_write       -       writes to ALi watchdog
+ *     @file: file from VFS
+ *     @data: user address of data
+ *     @len: length of data
+ *     @ppos: pointer to the file offset
+ *
+ *     Handle a write to the ALi watchdog. Writing to the file pings
+ *     the watchdog and resets it. Writing the magic 'V' sequence allows
+ *     the next close to turn off the watchdog.
+ */
+
+static ssize_t ali_write(struct file *file, const char __user *data,
+                             size_t len, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       ali_expect_release = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if(get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       ali_expect_release = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               ali_start();
+       }
+       return len;
+}
+
+/*
+ *     ali_ioctl       -       handle watchdog ioctls
+ *     @inode: VFS inode
+ *     @file: VFS file pointer
+ *     @cmd: ioctl number
+ *     @arg: arguments to the ioctl
+ *
+ *     Handle the watchdog ioctls supported by the ALi driver. Really
+ *     we want an extension to enable irq ack monitoring and the like
+ */
+
+static int ali_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_KEEPALIVEPING |
+                                       WDIOF_SETTIMEOUT |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     0,
+               .identity =             "ALi M1535 WatchDog Timer",
+       };
+
+       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:
+                       ali_keepalive();
+                       return 0;
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if (get_user (new_options, p))
+                               return -EFAULT;
+
+                       if (new_options & WDIOS_DISABLECARD) {
+                               ali_stop();
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_ENABLECARD) {
+                               ali_start();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_timeout;
+
+                       if (get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       if (ali_settimer(new_timeout))
+                           return -EINVAL;
+
+                       ali_keepalive();
+                       /* Fall */
+               }
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout, p);
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+/*
+ *     ali_open        -       handle open of ali watchdog
+ *     @inode: inode from VFS
+ *     @file: file from VFS
+ *
+ *     Open the ALi watchdog device. Ensure only one person opens it
+ *     at a time. Also start the watchdog running.
+ */
+
+static int ali_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+       if (test_and_set_bit(0, &ali_is_open))
+               return -EBUSY;
+
+       /* Activate */
+       ali_start();
+       return nonseekable_open(inode, file);
+}
+
+/*
+ *     ali_release     -       close an ALi watchdog
+ *     @inode: inode from VFS
+ *     @file: file from VFS
+ *
+ *     Close the ALi watchdog device. Actual shutdown of the timer
+ *     only occurs if the magic sequence has been set.
+ */
+
+static int ali_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       if (ali_expect_release == 42) {
+               ali_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               ali_keepalive();
+       }
+       clear_bit(0, &ali_is_open);
+       ali_expect_release = 0;
+       return 0;
+}
+
+/*
+ *     ali_notify_sys  -       System down notifier
+ *
+ *     Notifier for system down
+ */
+
+
+static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the WDT off */
+               ali_stop();
+       }
+
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Data for PCI driver interface
+ *
+ *     This data only exists for exporting the supported
+ *     PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ *     register a pci_driver, because someone else might one day
+ *     want to register another driver on the same PCI id.
+ */
+
+static struct pci_device_id ali_pci_tbl[] = {
+       { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
+       { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, ali_pci_tbl);
+
+/*
+ *     ali_find_watchdog       -       find a 1535 and 7101
+ *
+ *     Scans the PCI hardware for a 1535 series bridge and matching 7101
+ *     watchdog device. This may be overtight but it is better to be safe
+ */
+
+static int __init ali_find_watchdog(void)
+{
+       struct pci_dev *pdev;
+       u32 wdog;
+
+       /* Check for a 1533/1535 series bridge */
+       pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
+       if (pdev == NULL)
+               pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL);
+       if (pdev == NULL)
+               return -ENODEV;
+       pci_dev_put(pdev);
+
+       /* Check for the a 7101 PMU */
+       pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
+       if(pdev == NULL)
+               return -ENODEV;
+
+       if(pci_enable_device(pdev)) {
+               pci_dev_put(pdev);
+               return -EIO;
+       }
+
+       ali_pci = pdev;
+
+       /*
+        *      Initialize the timer bits
+        */
+       pci_read_config_dword(pdev, 0xCC, &wdog);
+
+       wdog &= ~0x3F;          /* Timer bits */
+       wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24));     /* Issued events */
+       wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9));      /* No monitor bits */
+
+       pci_write_config_dword(pdev, 0xCC, wdog);
+
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations ali_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .write =        ali_write,
+       .ioctl =        ali_ioctl,
+       .open =         ali_open,
+       .release =      ali_release,
+};
+
+static struct miscdevice ali_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &ali_fops,
+};
+
+static struct notifier_block ali_notifier = {
+       .notifier_call =        ali_notify_sys,
+};
+
+/*
+ *     watchdog_init   -       module initialiser
+ *
+ *     Scan for a suitable watchdog and if so initialize it. Return an error
+ *     if we cannot, the error causes the module to unload
+ */
+
+static int __init watchdog_init(void)
+{
+       int ret;
+
+       spin_lock_init(&ali_lock);
+
+       /* Check whether or not the hardware watchdog is there */
+       if (ali_find_watchdog() != 0) {
+               return -ENODEV;
+       }
+
+       /* Check that the timeout value is within it's range ; if not reset to the default */
+       if (timeout < 1 || timeout >= 18000) {
+               timeout = WATCHDOG_TIMEOUT;
+               printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n",
+                       timeout);
+       }
+
+       /* Calculate the watchdog's timeout */
+       ali_settimer(timeout);
+
+       ret = misc_register(&ali_miscdev);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto out;
+       }
+
+       ret = register_reboot_notifier(&ali_notifier);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               goto unreg_miscdev;
+       }
+
+       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+out:
+       return ret;
+unreg_miscdev:
+       misc_deregister(&ali_miscdev);
+       goto out;
+}
+
+/*
+ *     watchdog_exit   -       module de-initialiser
+ *
+ *     Called while unloading a successfully installed watchdog module.
+ */
+
+static void __exit watchdog_exit(void)
+{
+       /* Stop the timer before we leave */
+       ali_stop();
+
+       /* Deregister */
+       unregister_reboot_notifier(&ali_notifier);
+       misc_deregister(&ali_miscdev);
+       pci_dev_put(ali_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("ALi M1535 PMU Watchdog Timer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
new file mode 100644 (file)
index 0000000..67aed9f
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *     ALi M7101 PMU Computer Watchdog Timer driver
+ *
+ *     Based on w83877f_wdt.c by Scott Jennings <linuxdrivers@oro.net>
+ *     and the Cobalt kernel WDT timer driver by Tim Hockin
+ *                                           <thockin@cobaltnet.com>
+ *
+ *     (c)2002 Steve Hill <steve@navaho.co.uk>
+ *
+ *  This WDT driver is different from most other Linux WDT
+ *  drivers in that the driver will ping the watchdog by itself,
+ *  because this particular WDT has a very short timeout (1.6
+ *  seconds) and it would be insane to count on any userspace
+ *  daemon always getting scheduled within that time frame.
+ *
+ *  Additions:
+ *   Aug 23, 2004 - Added use_gpio module parameter for use on revision a1d PMUs
+ *                  found on very old cobalt hardware.
+ *                  -- Mike Waychison <michael.waychison@sun.com>
+ */
+
+#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/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define OUR_NAME "alim7101_wdt"
+#define PFX OUR_NAME ": "
+
+#define WDT_ENABLE 0x9C
+#define WDT_DISABLE 0x8C
+
+#define ALI_7101_WDT    0x92
+#define ALI_7101_GPIO   0x7D
+#define ALI_7101_GPIO_O 0x7E
+#define ALI_WDT_ARM     0x01
+
+/*
+ * We're going to use a 1 second timeout.
+ * If we reset the watchdog every ~250ms we should be safe.  */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 30 seconds.
+ */
+
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static int use_gpio = 0; /* Use the pic (for a1d revision alim7101) */
+module_param(use_gpio, int, 0);
+MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog.  (required by old cobalt boards)");
+
+static void wdt_timer_ping(unsigned long);
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static char wdt_expect_close;
+static struct pci_dev *alim7101_pmu;
+
+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) ")");
+
+/*
+ *     Whack the dog
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT
+        */
+       char    tmp;
+
+       if(time_before(jiffies, next_heartbeat))
+       {
+               /* Ping the WDT (this is actually a disarm/arm sequence) */
+               pci_read_config_byte(alim7101_pmu, 0x92, &tmp);
+               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
+               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM));
+               if (use_gpio) {
+                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
+                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp
+                                       | 0x20);
+                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp
+                                       & ~0x20);
+               }
+       } else {
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
+       }
+       /* Re-set the timer interval */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+/*
+ * Utility routines
+ */
+
+static void wdt_change(int writeval)
+{
+       char    tmp;
+
+       pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp);
+       if (writeval == WDT_ENABLE) {
+               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM));
+               if (use_gpio) {
+                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
+                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp & ~0x20);
+               }
+
+       } else {
+               pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM));
+               if (use_gpio) {
+                       pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp);
+                       pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 0x20);
+               }
+       }
+}
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + (timeout * HZ);
+
+       /* We must enable before we kick off the timer in case the timer
+          occurs as we ping it */
+
+       wdt_change(WDT_ENABLE);
+
+       /* Start the timer */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+}
+
+static void wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer_sync(&timer);
+       wdt_change(WDT_DISABLE);
+       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+}
+
+static void wdt_keepalive(void)
+{
+       /* user land ping */
+       next_heartbeat = jiffies + (timeout * HZ);
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count) {
+               if (!nowayout) {
+                       size_t ofs;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       wdt_expect_close = 0;
+
+                       /* now scan */
+                       for (ofs = 0; ofs != count; ofs++) {
+                               char c;
+                               if (get_user(c, buf+ofs))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       wdt_expect_close = 42;
+                       }
+               }
+               /* someone wrote to us, we should restart timer */
+               wdt_keepalive();
+       }
+       return count;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       /* Just in case we're already talking to someone... */
+       if(test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+       /* Good, fire up the show */
+       wdt_startup();
+       return nonseekable_open(inode, file);
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(wdt_expect_close == 42)
+               wdt_turnoff();
+       else {
+               /* wim: shouldn't there be a: del_timer(&timer); */
+               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
+       }
+       clear_bit(0, &wdt_is_open);
+       wdt_expect_close = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident =
+       {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "ALiM7101",
+       };
+
+       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:
+                       wdt_keepalive();
+                       return 0;
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if(get_user(new_options, p))
+                               return -EFAULT;
+
+                       if(new_options & WDIOS_DISABLECARD) {
+                               wdt_turnoff();
+                               retval = 0;
+                       }
+
+                       if(new_options & WDIOS_ENABLECARD) {
+                               wdt_startup();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_timeout;
+
+                       if(get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       wdt_keepalive();
+                       /* Fall through */
+               }
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout, p);
+               default:
+                       return -ENOTTY;
+       }
+}
+
+static const struct file_operations wdt_fops = {
+       .owner=         THIS_MODULE,
+       .llseek=        no_llseek,
+       .write=         fop_write,
+       .open=          fop_open,
+       .release=       fop_close,
+       .ioctl=         fop_ioctl,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor=WATCHDOG_MINOR,
+       .name="watchdog",
+       .fops=&wdt_fops,
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT)
+               wdt_turnoff();
+
+       if (code==SYS_RESTART) {
+               /*
+                * Cobalt devices have no way of rebooting themselves other than
+                * getting the watchdog to pull reset, so we restart the watchdog on
+                * reboot with no heartbeat
+                */
+               wdt_change(WDT_ENABLE);
+               printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n");
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier=
+{
+       .notifier_call = wdt_notify_sys,
+};
+
+static void __exit alim7101_wdt_unload(void)
+{
+       wdt_turnoff();
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+       unregister_reboot_notifier(&wdt_notifier);
+       pci_dev_put(alim7101_pmu);
+}
+
+static int __init alim7101_wdt_init(void)
+{
+       int rc = -EBUSY;
+       struct pci_dev *ali1543_south;
+       char tmp;
+
+       printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n");
+       alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+               NULL);
+       if (!alim7101_pmu) {
+               printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n");
+               return -EBUSY;
+       }
+
+       /* Set the WDT in the PMU to 1 second */
+       pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02);
+
+       ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+               NULL);
+       if (!ali1543_south) {
+               printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n");
+               goto err_out;
+       }
+       pci_read_config_byte(ali1543_south, 0x5e, &tmp);
+       pci_dev_put(ali1543_south);
+       if ((tmp & 0x1e) == 0x00) {
+               if (!use_gpio) {
+                       printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'.  If this is a cobalt board, set the 'use_gpio' module parameter.\n");
+                       goto err_out;
+               } 
+               nowayout = 1;
+       } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
+               printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
+               goto err_out;
+       }
+
+       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
+       {
+               timeout = WATCHDOG_TIMEOUT;
+               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
+                       timeout);
+       }
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       wdt_miscdev.minor, rc);
+               goto err_out;
+       }
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_miscdev;
+       }
+
+       if (nowayout) {
+               __module_get(THIS_MODULE);
+       }
+
+       printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out:
+       pci_dev_put(alim7101_pmu);
+       return rc;
+}
+
+module_init(alim7101_wdt_init);
+module_exit(alim7101_wdt_unload);
+
+static struct pci_device_id alim7101_pci_tbl[] __devinitdata = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl);
+
+MODULE_AUTHOR("Steve Hill");
+MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
new file mode 100644 (file)
index 0000000..54a5161
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Watchdog driver for Atmel AT32AP700X devices
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#define TIMEOUT_MIN            1
+#define TIMEOUT_MAX            2
+#define TIMEOUT_DEFAULT                TIMEOUT_MAX
+
+/* module parameters */
+static int timeout =  TIMEOUT_DEFAULT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+               "Timeout value. Limited to be 1 or 2 seconds. (default="
+               __MODULE_STRING(TIMEOUT_DEFAULT) ")");
+
+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) ")");
+
+/* Watchdog registers and write/read macro */
+#define WDT_CTRL               0x00
+#define WDT_CTRL_EN               0
+#define WDT_CTRL_PSEL             8
+#define WDT_CTRL_KEY             24
+
+#define WDT_CLR                        0x04
+
+#define WDT_BIT(name)          (1 << WDT_##name)
+#define WDT_BF(name, value)    ((value) << WDT_##name)
+
+#define wdt_readl(dev, reg)                            \
+       __raw_readl((dev)->regs + WDT_##reg)
+#define wdt_writel(dev, reg, value)                    \
+       __raw_writel((value), (dev)->regs + WDT_##reg)
+
+struct wdt_at32ap700x {
+       void __iomem            *regs;
+       spinlock_t              io_lock;
+       int                     timeout;
+       unsigned long           users;
+       struct miscdevice       miscdev;
+};
+
+static struct wdt_at32ap700x *wdt;
+static char expect_release;
+
+/*
+ * Disable the watchdog.
+ */
+static inline void at32_wdt_stop(void)
+{
+       unsigned long psel;
+
+       spin_lock(&wdt->io_lock);
+       psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f);
+       wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55));
+       wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa));
+       spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static inline void at32_wdt_start(void)
+{
+       /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */
+       unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe;
+
+       spin_lock(&wdt->io_lock);
+       wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
+                       | WDT_BF(CTRL_PSEL, psel)
+                       | WDT_BF(CTRL_KEY, 0x55));
+       wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
+                       | WDT_BF(CTRL_PSEL, psel)
+                       | WDT_BF(CTRL_KEY, 0xaa));
+       spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Pat the watchdog timer.
+ */
+static inline void at32_wdt_pat(void)
+{
+       spin_lock(&wdt->io_lock);
+       wdt_writel(wdt, CLR, 0x42);
+       spin_unlock(&wdt->io_lock);
+}
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at32_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(1, &wdt->users))
+               return -EBUSY;
+
+       at32_wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ */
+static int at32_wdt_close(struct inode *inode, struct file *file)
+{
+       if (expect_release == 42) {
+               at32_wdt_stop();
+       } else {
+               dev_dbg(wdt->miscdev.parent,
+                       "Unexpected close, not stopping watchdog!\n");
+               at32_wdt_pat();
+       }
+       clear_bit(1, &wdt->users);
+       expect_release = 0;
+       return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at32_wdt_settimeout(int time)
+{
+       /*
+        * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
+        * 2 ^ 16 allowing up to 2 seconds timeout.
+        */
+       if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
+               return -EINVAL;
+
+       /*
+        * Set new watchdog time. It will be used when at32_wdt_start() is
+        * called.
+        */
+       wdt->timeout = time;
+       return 0;
+}
+
+static struct watchdog_info at32_wdt_info = {
+       .identity       = "at32ap700x watchdog",
+       .options        = WDIOF_SETTIMEOUT |
+                         WDIOF_KEEPALIVEPING |
+                         WDIOF_MAGICCLOSE,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at32_wdt_ioctl(struct inode *inode, struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       int ret = -ENOTTY;
+       int time;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+
+       switch (cmd) {
+       case WDIOC_KEEPALIVE:
+               at32_wdt_pat();
+               ret = 0;
+               break;
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user(argp, &at32_wdt_info,
+                               sizeof(at32_wdt_info)) ? -EFAULT : 0;
+               break;
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, p);
+               if (ret)
+                       break;
+               ret = at32_wdt_settimeout(time);
+               if (ret)
+                       break;
+               /* Enable new time value */
+               at32_wdt_start();
+               /* fall through */
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(wdt->timeout, p);
+               break;
+       case WDIOC_GETSTATUS: /* fall through */
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(0, p);
+               break;
+       case WDIOC_SETOPTIONS:
+               ret = get_user(time, p);
+               if (ret)
+                       break;
+               if (time & WDIOS_DISABLECARD)
+                       at32_wdt_stop();
+               if (time & WDIOS_ENABLECARD)
+                       at32_wdt_start();
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+static ssize_t at32_wdt_write(struct file *file, const char __user *data,
+                               size_t len, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /*
+                        * note: just in case someone wrote the magic
+                        * character five months ago...
+                        */
+                       expect_release = 0;
+
+                       /*
+                        * scan to see whether or not we got the magic
+                        * character
+                        */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if (get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_release = 42;
+                       }
+               }
+               /* someone wrote to us, we should pat the watchdog */
+               at32_wdt_pat();
+       }
+       return len;
+}
+
+static const struct file_operations at32_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .ioctl          = at32_wdt_ioctl,
+       .open           = at32_wdt_open,
+       .release        = at32_wdt_close,
+       .write          = at32_wdt_write,
+};
+
+static int __init at32_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *regs;
+       int ret;
+
+       if (wdt) {
+               dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n");
+               return -EBUSY;
+       }
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs) {
+               dev_dbg(&pdev->dev, "missing mmio resource\n");
+               return -ENXIO;
+       }
+
+       wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL);
+       if (!wdt) {
+               dev_dbg(&pdev->dev, "no memory for wdt structure\n");
+               return -ENOMEM;
+       }
+
+       wdt->regs = ioremap(regs->start, regs->end - regs->start + 1);
+       if (!wdt->regs) {
+               ret = -ENOMEM;
+               dev_dbg(&pdev->dev, "could not map I/O memory\n");
+               goto err_free;
+       }
+       spin_lock_init(&wdt->io_lock);
+       wdt->users = 0;
+       wdt->miscdev.minor = WATCHDOG_MINOR;
+       wdt->miscdev.name = "watchdog";
+       wdt->miscdev.fops = &at32_wdt_fops;
+
+       if (at32_wdt_settimeout(timeout)) {
+               at32_wdt_settimeout(TIMEOUT_DEFAULT);
+               dev_dbg(&pdev->dev,
+                       "default timeout invalid, set to %d sec.\n",
+                       TIMEOUT_DEFAULT);
+       }
+
+       ret = misc_register(&wdt->miscdev);
+       if (ret) {
+               dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
+               goto err_iounmap;
+       }
+
+       platform_set_drvdata(pdev, wdt);
+       wdt->miscdev.parent = &pdev->dev;
+       dev_info(&pdev->dev,
+               "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
+               wdt->regs, wdt->timeout, nowayout);
+
+       return 0;
+
+err_iounmap:
+       iounmap(wdt->regs);
+err_free:
+       kfree(wdt);
+       wdt = NULL;
+       return ret;
+}
+
+static int __exit at32_wdt_remove(struct platform_device *pdev)
+{
+       if (wdt && platform_get_drvdata(pdev) == wdt) {
+               /* Stop the timer before we leave */
+               if (!nowayout)
+                       at32_wdt_stop();
+
+               misc_deregister(&wdt->miscdev);
+               iounmap(wdt->regs);
+               kfree(wdt);
+               wdt = NULL;
+               platform_set_drvdata(pdev, NULL);
+       }
+
+       return 0;
+}
+
+static void at32_wdt_shutdown(struct platform_device *pdev)
+{
+       at32_wdt_stop();
+}
+
+#ifdef CONFIG_PM
+static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       at32_wdt_stop();
+       return 0;
+}
+
+static int at32_wdt_resume(struct platform_device *pdev)
+{
+       if (wdt->users)
+               at32_wdt_start();
+       return 0;
+}
+#else
+#define at32_wdt_suspend NULL
+#define at32_wdt_resume NULL
+#endif
+
+static struct platform_driver at32_wdt_driver = {
+       .remove         = __exit_p(at32_wdt_remove),
+       .suspend        = at32_wdt_suspend,
+       .resume         = at32_wdt_resume,
+       .driver         = {
+               .name   = "at32_wdt",
+               .owner  = THIS_MODULE,
+       },
+       .shutdown       = at32_wdt_shutdown,
+};
+
+static int __init at32_wdt_init(void)
+{
+       return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe);
+}
+module_init(at32_wdt_init);
+
+static void __exit at32_wdt_exit(void)
+{
+       platform_driver_unregister(&at32_wdt_driver);
+}
+module_exit(at32_wdt_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
new file mode 100644 (file)
index 0000000..38bd373
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
+ *
+ *  Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/arch/at91_st.h>
+
+
+#define WDT_DEFAULT_TIME       5       /* seconds */
+#define WDT_MAX_TIME           256     /* seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+#endif
+
+
+static unsigned long at91wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline at91_wdt_stop(void)
+{
+       at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline at91_wdt_start(void)
+{
+       at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
+       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/*
+ * Reload the watchdog timer.  (ie, pat the watchdog)
+ */
+static void inline at91_wdt_reload(void)
+{
+       at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &at91wdt_busy))
+               return -EBUSY;
+
+       at91_wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ *  disabled.
+ */
+static int at91_wdt_close(struct inode *inode, struct file *file)
+{
+       if (!nowayout)
+               at91_wdt_stop();        /* Disable the watchdog when file is closed */
+
+       clear_bit(0, &at91wdt_busy);
+       return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at91_wdt_settimeout(int new_time)
+{
+       /*
+        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+        *
+        * Since WDV is a 16-bit counter, the maximum period is
+        * 65536 / 0.256 = 256 seconds.
+        */
+       if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+               return -EINVAL;
+
+       /* Set new watchdog time. It will be used when at91_wdt_start() is called. */
+       wdt_time = new_time;
+       return 0;
+}
+
+static struct watchdog_info at91_wdt_info = {
+       .identity       = "at91 watchdog",
+       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_value;
+
+       switch(cmd) {
+               case WDIOC_KEEPALIVE:
+                       at91_wdt_reload();      /* pat the watchdog */
+                       return 0;
+
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_value, p))
+                               return -EFAULT;
+
+                       if (at91_wdt_settimeout(new_value))
+                               return -EINVAL;
+
+                       /* Enable new time value */
+                       at91_wdt_start();
+
+                       /* Return current value */
+                       return put_user(wdt_time, p);
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(wdt_time, p);
+
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+
+               case WDIOC_SETOPTIONS:
+                       if (get_user(new_value, p))
+                               return -EFAULT;
+
+                       if (new_value & WDIOS_DISABLECARD)
+                               at91_wdt_stop();
+                       if (new_value & WDIOS_ENABLECARD)
+                               at91_wdt_start();
+                       return 0;
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       at91_wdt_reload();              /* pat the watchdog */
+       return len;
+}
+
+/* ......................................................................... */
+
+static const struct file_operations at91wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .ioctl          = at91_wdt_ioctl,
+       .open           = at91_wdt_open,
+       .release        = at91_wdt_close,
+       .write          = at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &at91wdt_fops,
+};
+
+static int __init at91wdt_probe(struct platform_device *pdev)
+{
+       int res;
+
+       if (at91wdt_miscdev.parent)
+               return -EBUSY;
+       at91wdt_miscdev.parent = &pdev->dev;
+
+       res = misc_register(&at91wdt_miscdev);
+       if (res)
+               return res;
+
+       printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : "");
+       return 0;
+}
+
+static int __exit at91wdt_remove(struct platform_device *pdev)
+{
+       int res;
+
+       res = misc_deregister(&at91wdt_miscdev);
+       if (!res)
+               at91wdt_miscdev.parent = NULL;
+
+       return res;
+}
+
+static void at91wdt_shutdown(struct platform_device *pdev)
+{
+       at91_wdt_stop();
+}
+
+#ifdef CONFIG_PM
+
+static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       at91_wdt_stop();
+       return 0;
+}
+
+static int at91wdt_resume(struct platform_device *pdev)
+{
+       if (at91wdt_busy)
+               at91_wdt_start();
+               return 0;
+}
+
+#else
+#define at91wdt_suspend NULL
+#define at91wdt_resume NULL
+#endif
+
+static struct platform_driver at91wdt_driver = {
+       .probe          = at91wdt_probe,
+       .remove         = __exit_p(at91wdt_remove),
+       .shutdown       = at91wdt_shutdown,
+       .suspend        = at91wdt_suspend,
+       .resume         = at91wdt_resume,
+       .driver         = {
+               .name   = "at91_wdt",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init at91_wdt_init(void)
+{
+       /* Check that the heartbeat value is within range; if not reset to the default */
+       if (at91_wdt_settimeout(wdt_time)) {
+               at91_wdt_settimeout(WDT_DEFAULT_TIME);
+               pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+       }
+
+       return platform_driver_register(&at91wdt_driver);
+}
+
+static void __exit at91_wdt_exit(void)
+{
+       platform_driver_unregister(&at91wdt_driver);
+}
+
+module_init(at91_wdt_init);
+module_exit(at91_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
new file mode 100644 (file)
index 0000000..309d279
--- /dev/null
@@ -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/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
new file mode 100644 (file)
index 0000000..d362f5b
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * drivers/char/watchdog/booke_wdt.c
+ *
+ * Watchdog timer for PowerPC Book-E systems
+ *
+ * Author: Matthew McClintock
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/notifier.h>
+#include <linux/watchdog.h>
+
+#include <asm/reg_booke.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
+ * Also, the wdt_period sets the watchdog timer period timeout.
+ * For E500 cpus the wdt_period sets which bit changing from 0->1 will
+ * trigger a watchog timeout. This watchdog timeout will occur 3 times, the
+ * first time nothing will happen, the second time a watchdog exception will
+ * occur, and the final time the board will reset.
+ */
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDT_PERIOD_DEFAULT 63  /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */
+#else
+#define WDT_PERIOD_DEFAULT 3   /* Refer to the PPC40x and PPC4xx manuals */
+#endif                         /* for timing information */
+
+u32 booke_wdt_enabled = 0;
+u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
+
+#ifdef CONFIG_FSL_BOOKE
+#define WDTP(x)                ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
+#else
+#define WDTP(x)                (TCR_WP(x))
+#endif
+
+/*
+ * booke_wdt_ping:
+ */
+static __inline__ void booke_wdt_ping(void)
+{
+       mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
+}
+
+/*
+ * booke_wdt_enable:
+ */
+static __inline__ void booke_wdt_enable(void)
+{
+       u32 val;
+
+       /* clear status before enabling watchdog */
+       booke_wdt_ping();
+       val = mfspr(SPRN_TCR);
+       val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
+
+       mtspr(SPRN_TCR, val);
+}
+
+/*
+ * booke_wdt_write:
+ */
+static ssize_t booke_wdt_write (struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       booke_wdt_ping();
+       return count;
+}
+
+static struct watchdog_info ident = {
+  .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+  .firmware_version = 0,
+  .identity = "PowerPC Book-E Watchdog",
+};
+
+/*
+ * booke_wdt_ioctl:
+ */
+static int booke_wdt_ioctl (struct inode *inode, struct file *file,
+                           unsigned int cmd, unsigned long arg)
+{
+       u32 tmp = 0;
+       u32 __user *p = (u32 __user *)arg;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user ((struct watchdog_info __user *) arg, &ident,
+                               sizeof(struct watchdog_info)))
+                       return -EFAULT;
+       case WDIOC_GETSTATUS:
+               return put_user(ident.options, p);
+       case WDIOC_GETBOOTSTATUS:
+               /* XXX: something is clearing TSR */
+               tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
+               /* returns 1 if last reset was caused by the WDT */
+               return (tmp ? 1 : 0);
+       case WDIOC_KEEPALIVE:
+               booke_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(booke_wdt_period, p))
+                       return -EFAULT;
+               mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period));
+               return 0;
+       case WDIOC_GETTIMEOUT:
+               return put_user(booke_wdt_period, p);
+       case WDIOC_SETOPTIONS:
+               if (get_user(tmp, p))
+                       return -EINVAL;
+               if (tmp == WDIOS_ENABLECARD) {
+                       booke_wdt_ping();
+                       break;
+               } else
+                       return -EINVAL;
+               return 0;
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+/*
+ * booke_wdt_open:
+ */
+static int booke_wdt_open (struct inode *inode, struct file *file)
+{
+       if (booke_wdt_enabled == 0) {
+               booke_wdt_enabled = 1;
+               booke_wdt_enable();
+               printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+                               booke_wdt_period);
+       }
+
+       return nonseekable_open(inode, file);
+}
+
+static const struct file_operations booke_wdt_fops = {
+  .owner = THIS_MODULE,
+  .llseek = no_llseek,
+  .write = booke_wdt_write,
+  .ioctl = booke_wdt_ioctl,
+  .open = booke_wdt_open,
+};
+
+static struct miscdevice booke_wdt_miscdev = {
+  .minor = WATCHDOG_MINOR,
+  .name = "watchdog",
+  .fops = &booke_wdt_fops,
+};
+
+static void __exit booke_wdt_exit(void)
+{
+       misc_deregister(&booke_wdt_miscdev);
+}
+
+/*
+ * booke_wdt_init:
+ */
+static int __init booke_wdt_init(void)
+{
+       int ret = 0;
+
+       printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
+       ident.firmware_version = cur_cpu_spec->pvr_value;
+
+       ret = misc_register(&booke_wdt_miscdev);
+       if (ret) {
+               printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
+                               WATCHDOG_MINOR, ret);
+               return ret;
+       }
+
+       if (booke_wdt_enabled == 1) {
+               printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
+                               booke_wdt_period);
+               booke_wdt_enable();
+       }
+
+       return ret;
+}
+device_initcall(booke_wdt_init);
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
new file mode 100644 (file)
index 0000000..5941ca6
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * sma cpu5 watchdog driver
+ *
+ * Copyright (C) 2003 Heiko Ronsdorf <hero@ihg.uni-duisburg.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <linux/watchdog.h>
+
+/* adjustable parameters */
+
+static int verbose = 0;
+static int port = 0x91;
+static int ticks = 10000;
+
+#define PFX                    "cpu5wdt: "
+
+#define CPU5WDT_EXTENT          0x0A
+
+#define CPU5WDT_STATUS_REG      0x00
+#define CPU5WDT_TIME_A_REG      0x02
+#define CPU5WDT_TIME_B_REG      0x03
+#define CPU5WDT_MODE_REG        0x04
+#define CPU5WDT_TRIGGER_REG     0x07
+#define CPU5WDT_ENABLE_REG      0x08
+#define CPU5WDT_RESET_REG       0x09
+
+#define CPU5WDT_INTERVAL       (HZ/10+1)
+
+/* some device data */
+
+static struct {
+       struct completion stop;
+       volatile int running;
+       struct timer_list timer;
+       volatile int queue;
+       int default_ticks;
+       unsigned long inuse;
+} cpu5wdt_device;
+
+/* generic helper functions */
+
+static void cpu5wdt_trigger(unsigned long unused)
+{
+       if ( verbose > 2 )
+               printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
+
+       if( cpu5wdt_device.running )
+               ticks--;
+
+       /* keep watchdog alive */
+       outb(1, port + CPU5WDT_TRIGGER_REG);
+
+       /* requeue?? */
+       if (cpu5wdt_device.queue && ticks)
+               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
+       else {
+               /* ticks doesn't matter anyway */
+               complete(&cpu5wdt_device.stop);
+       }
+
+}
+
+static void cpu5wdt_reset(void)
+{
+       ticks = cpu5wdt_device.default_ticks;
+
+       if ( verbose )
+               printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
+
+}
+
+static void cpu5wdt_start(void)
+{
+       if ( !cpu5wdt_device.queue ) {
+               cpu5wdt_device.queue = 1;
+               outb(0, port + CPU5WDT_TIME_A_REG);
+               outb(0, port + CPU5WDT_TIME_B_REG);
+               outb(1, port + CPU5WDT_MODE_REG);
+               outb(0, port + CPU5WDT_RESET_REG);
+               outb(0, port + CPU5WDT_ENABLE_REG);
+               mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
+       }
+       /* if process dies, counter is not decremented */
+       cpu5wdt_device.running++;
+}
+
+static int cpu5wdt_stop(void)
+{
+       if ( cpu5wdt_device.running )
+               cpu5wdt_device.running = 0;
+
+       ticks = cpu5wdt_device.default_ticks;
+
+       if ( verbose )
+               printk(KERN_CRIT PFX "stop not possible\n");
+
+       return -EIO;
+}
+
+/* filesystem operations */
+
+static int cpu5wdt_open(struct inode *inode, struct file *file)
+{
+       if ( test_and_set_bit(0, &cpu5wdt_device.inuse) )
+               return -EBUSY;
+
+       return nonseekable_open(inode, file);
+}
+
+static int cpu5wdt_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &cpu5wdt_device.inuse);
+       return 0;
+}
+
+static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       unsigned int value;
+       static struct watchdog_info ident =
+       {
+               .options = WDIOF_CARDRESET,
+               .identity = "CPU5 WDT",
+       };
+
+       switch(cmd) {
+               case WDIOC_KEEPALIVE:
+                       cpu5wdt_reset();
+                       break;
+               case WDIOC_GETSTATUS:
+                       value = inb(port + CPU5WDT_STATUS_REG);
+                       value = (value >> 2) & 1;
+                       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;
+                       break;
+               case WDIOC_SETOPTIONS:
+                       if ( copy_from_user(&value, argp, sizeof(int)) )
+                               return -EFAULT;
+                       switch(value) {
+                               case WDIOS_ENABLECARD:
+                                       cpu5wdt_start();
+                                       break;
+                               case WDIOS_DISABLECARD:
+                                       return cpu5wdt_stop();
+                               default:
+                                       return -EINVAL;
+                       }
+                       break;
+               default:
+                       return -ENOTTY;
+       }
+       return 0;
+}
+
+static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if ( !count )
+               return -EIO;
+
+       cpu5wdt_reset();
+
+       return count;
+}
+
+static const struct file_operations cpu5wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .ioctl          = cpu5wdt_ioctl,
+       .open           = cpu5wdt_open,
+       .write          = cpu5wdt_write,
+       .release        = cpu5wdt_release,
+};
+
+static struct miscdevice cpu5wdt_misc = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &cpu5wdt_fops,
+};
+
+/* init/exit function */
+
+static int __devinit cpu5wdt_init(void)
+{
+       unsigned int val;
+       int err;
+
+       if ( verbose )
+               printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose);
+
+       if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) {
+               printk(KERN_ERR PFX "request_region failed\n");
+               err = -EBUSY;
+               goto no_port;
+       }
+
+       if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
+               printk(KERN_ERR PFX "misc_register failed\n");
+               goto no_misc;
+       }
+
+       /* watchdog reboot? */
+       val = inb(port + CPU5WDT_STATUS_REG);
+       val = (val >> 2) & 1;
+       if ( !val )
+               printk(KERN_INFO PFX "sorry, was my fault\n");
+
+       init_completion(&cpu5wdt_device.stop);
+       cpu5wdt_device.queue = 0;
+
+       clear_bit(0, &cpu5wdt_device.inuse);
+
+       setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
+
+       cpu5wdt_device.default_ticks = ticks;
+
+       printk(KERN_INFO PFX "init success\n");
+
+       return 0;
+
+no_misc:
+       release_region(port, CPU5WDT_EXTENT);
+no_port:
+       return err;
+}
+
+static int __devinit cpu5wdt_init_module(void)
+{
+       return cpu5wdt_init();
+}
+
+static void __devexit cpu5wdt_exit(void)
+{
+       if ( cpu5wdt_device.queue ) {
+               cpu5wdt_device.queue = 0;
+               wait_for_completion(&cpu5wdt_device.stop);
+       }
+
+       misc_deregister(&cpu5wdt_misc);
+
+       release_region(port, CPU5WDT_EXTENT);
+
+}
+
+static void __devexit cpu5wdt_exit_module(void)
+{
+       cpu5wdt_exit();
+}
+
+/* module entry points */
+
+module_init(cpu5wdt_init_module);
+module_exit(cpu5wdt_exit_module);
+
+MODULE_AUTHOR("Heiko Ronsdorf <hero@ihg.uni-duisburg.de>");
+MODULE_DESCRIPTION("sma cpu5 watchdog driver");
+MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(port, int, 0);
+MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
+
+module_param(verbose, int, 0);
+MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
+
+module_param(ticks, int, 0);
+MODULE_PARM_DESC(ticks, "count down ticks, default is 10000");
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
new file mode 100644 (file)
index 0000000..19db530
--- /dev/null
@@ -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);
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
new file mode 100644 (file)
index 0000000..0e4787a
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Watchdog driver for Cirrus Logic EP93xx family of devices.
+ *
+ * Copyright (c) 2004 Ray Lehtiniemi
+ * Copyright (c) 2006 Tower Technologies
+ * Based on ep93xx driver, bits from alim7101_wdt.c
+ *
+ * Authors: Ray Lehtiniemi <rayl@mail.com>,
+ *     Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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.
+ *
+ * This watchdog fires after 250msec, which is a too short interval
+ * for us to rely on the user space daemon alone. So we ping the
+ * wdt each ~200msec and eventually stop doing it if the user space
+ * daemon dies.
+ *
+ * TODO:
+ *
+ *     - Test last reset from watchdog status
+ *     - Add a few missing ioctls
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+
+#define WDT_VERSION    "0.3"
+#define PFX            "ep93xx_wdt: "
+
+/* default timeout (secs) */
+#define WDT_TIMEOUT 30
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int timeout = WDT_TIMEOUT;
+
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define WDT_IN_USE             0
+#define WDT_OK_TO_CLOSE                1
+
+#define EP93XX_WDT_REG(x)      (EP93XX_WATCHDOG_BASE + (x))
+#define EP93XX_WDT_WATCHDOG    EP93XX_WDT_REG(0x00)
+#define EP93XX_WDT_WDSTATUS    EP93XX_WDT_REG(0x04)
+
+/* reset the wdt every ~200ms */
+#define WDT_INTERVAL (HZ/5)
+
+static void wdt_enable(void)
+{
+       __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_disable(void)
+{
+       __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG);
+}
+
+static inline void wdt_ping(void)
+{
+       __raw_writew(0x5555, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + (timeout * HZ);
+
+       wdt_enable();
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static void wdt_shutdown(void)
+{
+       del_timer_sync(&timer);
+       wdt_disable();
+}
+
+static void wdt_keepalive(void)
+{
+       /* user land ping */
+       next_heartbeat = jiffies + (timeout * HZ);
+}
+
+static int ep93xx_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+               return -EBUSY;
+
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       wdt_startup();
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t
+ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
+                loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+
+                               if (c == 'V')
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                               else
+                                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                       }
+               }
+               wdt_keepalive();
+       }
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
+       .identity = "EP93xx Watchdog",
+};
+
+static int
+ep93xx_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 __user *)arg, &ident,
+                               sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int __user *)arg);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(boot_status, (int __user *)arg);
+               break;
+
+       case WDIOC_GETTIMEOUT:
+               /* actually, it is 0.250 seconds.... */
+               ret = put_user(1, (int __user *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_keepalive();
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+static int ep93xx_wdt_release(struct inode *inode, struct file *file)
+{
+       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+               wdt_shutdown();
+       else
+               printk(KERN_CRIT PFX "Device closed unexpectedly - "
+                       "timer will not stop\n");
+
+       clear_bit(WDT_IN_USE, &wdt_status);
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       return 0;
+}
+
+static const struct file_operations ep93xx_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .write          = ep93xx_wdt_write,
+       .ioctl          = ep93xx_wdt_ioctl,
+       .open           = ep93xx_wdt_open,
+       .release        = ep93xx_wdt_release,
+};
+
+static struct miscdevice ep93xx_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ep93xx_wdt_fops,
+};
+
+static void ep93xx_timer_ping(unsigned long data)
+{
+       if (time_before(jiffies, next_heartbeat))
+               wdt_ping();
+
+       /* Re-set the timer interval */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static int __init ep93xx_wdt_init(void)
+{
+       int err;
+
+       err = misc_register(&ep93xx_wdt_miscdev);
+
+       boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0;
+
+       printk(KERN_INFO PFX "EP93XX watchdog, driver version "
+               WDT_VERSION "%s\n",
+               (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08)
+               ? " (nCS1 disable detected)" : "");
+
+       if (timeout < 1 || timeout > 3600) {
+               timeout = WDT_TIMEOUT;
+               printk(KERN_INFO PFX
+                       "timeout value must be 1<=x<=3600, using %d\n",
+                       timeout);
+       }
+
+       setup_timer(&timer, ep93xx_timer_ping, 1);
+       return err;
+}
+
+static void __exit ep93xx_wdt_exit(void)
+{
+       wdt_shutdown();
+       misc_deregister(&ep93xx_wdt_miscdev);
+}
+
+module_init(ep93xx_wdt_init);
+module_exit(ep93xx_wdt_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
+               "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("EP93xx Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(WDT_VERSION);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
new file mode 100644 (file)
index 0000000..b14e9d1
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ *     Eurotech CPU-1220/1410/1420 on board WDT driver
+ *
+ *     (c) Copyright 2001 Ascensit <support@ascensit.com>
+ *     (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
+ *     (c) Copyright 2002 Rob Radez <rob@osinvestor.com>
+ *
+ *     Based on wdt.c.
+ *     Original copyright messages:
+ *
+ *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                              http://www.redhat.com
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *      warranty for any of this software. This material is provided
+ *      "AS-IS" and at no charge.
+ *
+ *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>*
+ */
+
+/* Changelog:
+ *
+ * 2001 - Rodolfo Giometti
+ *     Initial release
+ *
+ * 2002/04/25 - Rob Radez
+ *     clean up #includes
+ *     clean up locking
+ *     make __setup param unique
+ *     proper options in watchdog_info
+ *     add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls
+ *     add expect_close support
+ *
+ * 2002.05.30 - Joel Becker <joel.becker@oracle.com>
+ *     Added Matt Domsch's nowayout module option.
+ */
+
+/*
+ *     The eurotech CPU-1220/1410/1420's watchdog is a part
+ *     of the on-board SUPER I/O device SMSC FDC 37B782.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long eurwdt_is_open;
+static int eurwdt_timeout;
+static char eur_expect_close;
+
+/*
+ * You must set these - there is no sane way to probe for this board.
+ * You can use eurwdt=x,y to set these now.
+ */
+
+static int io = 0x3f0;
+static int irq = 10;
+static char *ev = "int";
+
+#define WDT_TIMEOUT            60                /* 1 minute */
+
+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) ")");
+
+/*
+ * Some symbolic names
+ */
+
+#define WDT_CTRL_REG           0x30
+#define WDT_OUTPIN_CFG         0xe2
+#define WDT_EVENT_INT          0x00
+#define WDT_EVENT_REBOOT       0x08
+#define WDT_UNIT_SEL           0xf1
+#define WDT_UNIT_SECS          0x80
+#define WDT_TIMEOUT_VAL                0xf2
+#define WDT_TIMER_CFG          0xf3
+
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
+module_param(ev, charp, 0);
+MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `int')");
+
+
+/*
+ * Programming support
+ */
+
+static inline void eurwdt_write_reg(u8 index, u8 data)
+{
+       outb(index, io);
+       outb(data, io+1);
+}
+
+static inline void eurwdt_lock_chip(void)
+{
+       outb(0xaa, io);
+}
+
+static inline void eurwdt_unlock_chip(void)
+{
+       outb(0x55, io);
+       eurwdt_write_reg(0x07, 0x08);   /* set the logical device */
+}
+
+static inline void eurwdt_set_timeout(int timeout)
+{
+       eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout);
+}
+
+static inline void eurwdt_disable_timer(void)
+{
+       eurwdt_set_timeout(0);
+}
+
+static void eurwdt_activate_timer(void)
+{
+       eurwdt_disable_timer();
+       eurwdt_write_reg(WDT_CTRL_REG, 0x01);   /* activate the WDT */
+       eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT);
+
+       /* Setting interrupt line */
+       if (irq == 2 || irq > 15 || irq < 0) {
+               printk(KERN_ERR ": invalid irq number\n");
+               irq = 0;        /* if invalid we disable interrupt */
+       }
+       if (irq == 0)
+               printk(KERN_INFO ": interrupt disabled\n");
+
+       eurwdt_write_reg(WDT_TIMER_CFG, irq<<4);
+
+       eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS);  /* we use seconds */
+       eurwdt_set_timeout(0);  /* the default timeout */
+}
+
+
+/*
+ * Kernel methods.
+ */
+
+static irqreturn_t eurwdt_interrupt(int irq, void *dev_id)
+{
+       printk(KERN_CRIT "timeout WDT timeout\n");
+
+#ifdef ONLY_TESTING
+       printk(KERN_CRIT "Would Reboot.\n");
+#else
+       printk(KERN_CRIT "Initiating system reboot.\n");
+       emergency_restart();
+#endif
+       return IRQ_HANDLED;
+}
+
+
+/**
+ * eurwdt_ping:
+ *
+ * Reload counter one with the watchdog timeout.
+ */
+
+static void eurwdt_ping(void)
+{
+       /* Write the watchdog default value */
+       eurwdt_set_timeout(eurwdt_timeout);
+}
+
+/**
+ * eurwdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t eurwdt_write(struct file *file, const char __user *buf,
+size_t count, loff_t *ppos)
+{
+       if (count)      {
+               if (!nowayout) {
+                       size_t i;
+
+                       eur_expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if(get_user(c, buf+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       eur_expect_close = 42;
+                       }
+               }
+               eurwdt_ping();  /* the default timeout */
+       }
+
+       return count;
+}
+
+/**
+ * eurwdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features.
+ */
+
+static int eurwdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options          = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity         = "WDT Eurotech CPU-1220/1410",
+       };
+
+       int time;
+       int options, retval = -EINVAL;
+
+       switch(cmd) {
+       default:
+               return -ENOTTY;
+
+       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:
+               eurwdt_ping();
+               return 0;
+
+       case WDIOC_SETTIMEOUT:
+               if (copy_from_user(&time, p, sizeof(int)))
+                       return -EFAULT;
+
+               /* Sanity check */
+               if (time < 0 || time > 255)
+                       return -EINVAL;
+
+               eurwdt_timeout = time;
+               eurwdt_set_timeout(time);
+               /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(eurwdt_timeout, p);
+
+       case WDIOC_SETOPTIONS:
+               if (get_user(options, p))
+                       return -EFAULT;
+               if (options & WDIOS_DISABLECARD) {
+                       eurwdt_disable_timer();
+                       retval = 0;
+               }
+               if (options & WDIOS_ENABLECARD) {
+                       eurwdt_activate_timer();
+                       eurwdt_ping();
+                       retval = 0;
+               }
+               return retval;
+       }
+}
+
+/**
+ * eurwdt_open:
+ * @inode: inode of device
+ * @file: file handle to device
+ *
+ * The misc device has been opened. The watchdog device is single
+ * open and on opening we load the counter.
+ */
+
+static int eurwdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &eurwdt_is_open))
+               return -EBUSY;
+       eurwdt_timeout = WDT_TIMEOUT;   /* initial timeout */
+       /* Activate the WDT */
+       eurwdt_activate_timer();
+       return nonseekable_open(inode, file);
+}
+
+/**
+ * eurwdt_release:
+ * @inode: inode to board
+ * @file: file handle to board
+ *
+ * The watchdog has a configurable API. There is a religious dispute
+ * between people who want their watchdog to be able to shut down and
+ * those who want to be sure if the watchdog manager dies the machine
+ * reboots. In the former case we disable the counters, in the latter
+ * case you have to open it again very soon.
+ */
+
+static int eurwdt_release(struct inode *inode, struct file *file)
+{
+       if (eur_expect_close == 42) {
+               eurwdt_disable_timer();
+       } else {
+               printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
+               eurwdt_ping();
+       }
+       clear_bit(0, &eurwdt_is_open);
+       eur_expect_close = 0;
+       return 0;
+}
+
+/**
+ * eurwdt_notify_sys:
+ * @this: our notifier block
+ * @code: the event being reported
+ * @unused: unused
+ *
+ * Our notifier is called on system shutdowns. We want to turn the card
+ * off at reboot otherwise the machine will reboot again during memory
+ * test or worse yet during the following fsck. This would suck, in fact
+ * trust me - if it happens it does suck.
+ */
+
+static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the card off */
+               eurwdt_disable_timer();
+       }
+
+       return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+
+static const struct file_operations eurwdt_fops = {
+       .owner  = THIS_MODULE,
+       .llseek = no_llseek,
+       .write  = eurwdt_write,
+       .ioctl  = eurwdt_ioctl,
+       .open   = eurwdt_open,
+       .release        = eurwdt_release,
+};
+
+static struct miscdevice eurwdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &eurwdt_fops,
+};
+
+/*
+ * The WDT card needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block eurwdt_notifier = {
+       .notifier_call = eurwdt_notify_sys,
+};
+
+/**
+ * cleanup_module:
+ *
+ * Unload the watchdog. You cannot do this with any file handles open.
+ * If your watchdog is set to continue ticking on close and you unload
+ * it, well it keeps ticking. We won't get the interrupt but the board
+ * will not touch PC memory so all is fine. You just have to load a new
+ * module in 60 seconds or reboot.
+ */
+
+static void __exit eurwdt_exit(void)
+{
+       eurwdt_lock_chip();
+
+       misc_deregister(&eurwdt_miscdev);
+
+       unregister_reboot_notifier(&eurwdt_notifier);
+       release_region(io, 2);
+       free_irq(irq, NULL);
+}
+
+/**
+ * eurwdt_init:
+ *
+ * Set up the WDT watchdog board. After grabbing the resources
+ * we require we need also to unlock the device.
+ * The open() function will actually kick the board off.
+ */
+
+static int __init eurwdt_init(void)
+{
+       int ret;
+
+       ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
+       if(ret) {
+               printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
+               goto out;
+       }
+
+       if (!request_region(io, 2, "eurwdt")) {
+               printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
+               ret = -EBUSY;
+               goto outirq;
+       }
+
+       ret = register_reboot_notifier(&eurwdt_notifier);
+       if (ret) {
+               printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret);
+               goto outreg;
+       }
+
+       ret = misc_register(&eurwdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
+               WATCHDOG_MINOR);
+               goto outreboot;
+       }
+
+       eurwdt_unlock_chip();
+
+       ret = 0;
+       printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
+               " - timeout event: %s\n",
+               io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
+
+out:
+       return ret;
+
+outreboot:
+       unregister_reboot_notifier(&eurwdt_notifier);
+
+outreg:
+       release_region(io, 2);
+
+outirq:
+       free_irq(irq, NULL);
+       goto out;
+}
+
+module_init(eurwdt_init);
+module_exit(eurwdt_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti");
+MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
new file mode 100644 (file)
index 0000000..c598250
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ *     i6300esb:       Watchdog timer driver for Intel 6300ESB chipset
+ *
+ *     (c) Copyright 2004 Google Inc.
+ *     (c) Copyright 2005 David Härdeman <david@2gen.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *      based on i810-tco.c which is in turn based on softdog.c
+ *
+ *     The timer is implemented in the following I/O controller hubs:
+ *     (See the intel documentation on http://developer.intel.com.)
+ *     6300ESB chip : document number 300641-003
+ *
+ *  2004YYZZ Ross Biro
+ *     Initial version 0.01
+ *  2004YYZZ Ross Biro
+ *     Version 0.02
+ *  20050210 David Härdeman <david@2gen.com>
+ *      Ported driver to kernel 2.6
+ */
+
+/*
+ *      Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG  0x60            /* Config register                   */
+#define ESB_LOCK_REG    0x68            /* WDT lock register                 */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG  BASEADDR + 0x00 /* Timer1 value after each reset     */
+#define ESB_TIMER2_REG  BASEADDR + 0x04 /* Timer2 value after each reset     */
+#define ESB_GINTSR_REG  BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG  BASEADDR + 0x0c /* Reload register                   */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC    ( 0x01 << 2 )   /* Watchdog functionality            */
+#define ESB_WDT_ENABLE  ( 0x01 << 1 )   /* Enable WDT                        */
+#define ESB_WDT_LOCK    ( 0x01 << 0 )   /* Lock (nowayout)                   */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT  ( 0x01 << 5 )   /* Enable reboot on timeout          */
+#define ESB_WDT_FREQ    ( 0x01 << 2 )   /* Decrement frequency               */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 )   /* Interrupt type on timer1 timeout  */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 )    /* prevent timeout                   */
+
+/* Magic constants */
+#define ESB_UNLOCK1     0x80            /* Step 1 to unlock reset registers  */
+#define ESB_UNLOCK2     0x86            /* Step 2 to unlock reset registers  */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30   /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+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) ")");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+        writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+        writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+       u8 val;
+
+       /* Enable or Enable + Lock? */
+       val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+        pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+       u8 val;
+
+       spin_lock(&esb_lock);
+       /* First, reset timers as suggested by the docs */
+       esb_unlock_registers();
+       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+       /* Then disable the WDT */
+       pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+       pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+       spin_unlock(&esb_lock);
+
+       /* Returns 0 if the timer was disabled, non-zero otherwise */
+       return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+       spin_lock(&esb_lock);
+       esb_unlock_registers();
+       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+        /* FIXME: Do we need to flush anything here? */
+       spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+       u32 val;
+
+       if (time < 0x1 || time > (2 * 0x03ff))
+               return -EINVAL;
+
+       spin_lock(&esb_lock);
+
+       /* We shift by 9, so if we are passed a value of 1 sec,
+        * val will be 1 << 9 = 512, then write that to two
+        * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+        */
+       val = time << 9;
+
+       /* Write timer 1 */
+       esb_unlock_registers();
+       writel(val, ESB_TIMER1_REG);
+
+       /* Write timer 2 */
+       esb_unlock_registers();
+        writel(val, ESB_TIMER2_REG);
+
+        /* Reload */
+       esb_unlock_registers();
+       writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+       /* FIXME: Do we need to flush everything out? */
+
+       /* Done */
+       heartbeat = time;
+       spin_unlock(&esb_lock);
+       return 0;
+}
+
+static int esb_timer_read (void)
+{
+               u32 count;
+
+       /* This isn't documented, and doesn't take into
+         * acount which stage is running, but it looks
+         * like a 20 bit count down, so we might as well report it.
+         */
+        pci_read_config_dword(esb_pci, 0x64, &count);
+        return (int)count;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+        /* /dev/watchdog can only be opened once */
+        if (test_and_set_bit(0, &timer_alive))
+                return -EBUSY;
+
+        /* Reload and activate timer */
+        esb_timer_keepalive ();
+        esb_timer_start ();
+
+       return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+        /* Shut off the timer. */
+        if (esb_expect_close == 42) {
+                esb_timer_stop ();
+        } else {
+                printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+                esb_timer_keepalive ();
+        }
+        clear_bit(0, &timer_alive);
+        esb_expect_close = 0;
+        return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+                         size_t len, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+        if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       esb_expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if(get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       esb_expect_close = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               esb_timer_keepalive ();
+       }
+       return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+                     unsigned int cmd, unsigned long arg)
+{
+       int new_options, retval = -EINVAL;
+       int new_heartbeat;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT |
+                                       WDIOF_KEEPALIVEPING |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     0,
+               .identity =             ESB_MODULE_NAME,
+       };
+
+       switch (cmd) {
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &ident,
+                                           sizeof (ident)) ? -EFAULT : 0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user (esb_timer_read(), p);
+
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user (triggered, p);
+
+                case WDIOC_KEEPALIVE:
+                        esb_timer_keepalive ();
+                        return 0;
+
+                case WDIOC_SETOPTIONS:
+                {
+                        if (get_user (new_options, p))
+                                return -EFAULT;
+
+                        if (new_options & WDIOS_DISABLECARD) {
+                                esb_timer_stop ();
+                                retval = 0;
+                        }
+
+                        if (new_options & WDIOS_ENABLECARD) {
+                                esb_timer_keepalive ();
+                                esb_timer_start ();
+                                retval = 0;
+                        }
+
+                        return retval;
+                }
+
+                case WDIOC_SETTIMEOUT:
+                {
+                        if (get_user(new_heartbeat, p))
+                                return -EFAULT;
+
+                        if (esb_timer_set_heartbeat(new_heartbeat))
+                            return -EINVAL;
+
+                        esb_timer_keepalive ();
+                        /* Fall */
+                }
+
+                case WDIOC_GETTIMEOUT:
+                        return put_user(heartbeat, p);
+
+                default:
+                        return -ENOTTY;
+        }
+}
+
+/*
+ *      Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+        if (code==SYS_DOWN || code==SYS_HALT) {
+                /* Turn the WDT off */
+                esb_timer_stop ();
+        }
+
+        return NOTIFY_DONE;
+}
+
+/*
+ *      Kernel Interfaces
+ */
+
+static const struct file_operations esb_fops = {
+        .owner =        THIS_MODULE,
+        .llseek =       no_llseek,
+        .write =        esb_write,
+        .ioctl =        esb_ioctl,
+        .open =         esb_open,
+        .release =      esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+        .minor =        WATCHDOG_MINOR,
+        .name =         "watchdog",
+        .fops =         &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+        .notifier_call =        esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+        { 0, },                 /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ *      Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+       u8 val1;
+       unsigned short val2;
+
+        struct pci_dev *dev = NULL;
+        /*
+         *      Find the PCI device
+         */
+
+        for_each_pci_dev(dev) {
+                if (pci_match_id(esb_pci_tbl, dev)) {
+                        esb_pci = dev;
+                        break;
+                }
+       }
+
+        if (esb_pci) {
+               if (pci_enable_device(esb_pci)) {
+                       printk (KERN_ERR PFX "failed to enable device\n");
+                       goto err_devput;
+               }
+
+               if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+                       printk (KERN_ERR PFX "failed to request region\n");
+                       goto err_disable;
+               }
+
+               BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+                                  pci_resource_len(esb_pci, 0));
+               if (BASEADDR == NULL) {
+                       /* Something's wrong here, BASEADDR has to be set */
+                       printk (KERN_ERR PFX "failed to get BASEADDR\n");
+                        goto err_release;
+                }
+
+               /*
+                * The watchdog has two timers, it can be setup so that the
+                * expiry of timer1 results in an interrupt and the expiry of
+                * timer2 results in a reboot. We set it to not generate
+                * any interrupts as there is not much we can do with it
+                * right now.
+                *
+                * We also enable reboots and set the timer frequency to
+                * the PCI clock divided by 2^15 (approx 1KHz).
+                */
+               pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+               /* Check that the WDT isn't already locked */
+               pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+               if (val1 & ESB_WDT_LOCK)
+                       printk (KERN_WARNING PFX "nowayout already set\n");
+
+               /* Set the timer to watchdog mode and disable it for now */
+               pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+               /* Check if the watchdog was previously triggered */
+               esb_unlock_registers();
+               val2 = readw(ESB_RELOAD_REG);
+               triggered = (val2 & (0x01 << 9) >> 9);
+
+               /* Reset trigger flag and timers */
+               esb_unlock_registers();
+               writew((0x11 << 8), ESB_RELOAD_REG);
+
+               /* Done */
+               return 1;
+
+err_release:
+               pci_release_region(esb_pci, 0);
+err_disable:
+               pci_disable_device(esb_pci);
+err_devput:
+               pci_dev_put(esb_pci);
+       }
+       return 0;
+}
+
+static int __init watchdog_init (void)
+{
+        int ret;
+
+        spin_lock_init(&esb_lock);
+
+        /* Check whether or not the hardware watchdog is there */
+        if (!esb_getdevice () || esb_pci == NULL)
+                return -ENODEV;
+
+        /* Check that the heartbeat value is within it's range ; if not reset to the default */
+        if (esb_timer_set_heartbeat (heartbeat)) {
+                esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+                printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+                      heartbeat);
+        }
+
+        ret = register_reboot_notifier(&esb_notifier);
+        if (ret != 0) {
+                printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                        ret);
+                goto err_unmap;
+        }
+
+        ret = misc_register(&esb_miscdev);
+        if (ret != 0) {
+                printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                        WATCHDOG_MINOR, ret);
+                goto err_notifier;
+        }
+
+        esb_timer_stop ();
+
+        printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+                BASEADDR, heartbeat, nowayout);
+
+        return 0;
+
+err_notifier:
+        unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+       iounmap(BASEADDR);
+/* err_release: */
+       pci_release_region(esb_pci, 0);
+/* err_disable: */
+       pci_disable_device(esb_pci);
+/* err_devput: */
+       pci_dev_put(esb_pci);
+        return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+               esb_timer_stop ();
+
+       /* Deregister */
+       misc_deregister(&esb_miscdev);
+        unregister_reboot_notifier(&esb_notifier);
+       iounmap(BASEADDR);
+       pci_release_region(esb_pci, 0);
+       pci_disable_device(esb_pci);
+       pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
new file mode 100644 (file)
index 0000000..4150839
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ *     intel TCO vendor specific watchdog driver support
+ *
+ *     (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ */
+
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
+
+/* Module and version information */
+#define DRV_NAME        "iTCO_vendor_support"
+#define DRV_VERSION     "1.01"
+#define DRV_RELDATE     "11-Nov-2006"
+#define PFX            DRV_NAME ": "
+
+/* Includes */
+#include <linux/module.h>              /* For module specific items */
+#include <linux/moduleparam.h>         /* For new moduleparam's */
+#include <linux/types.h>               /* For standard types (like size_t) */
+#include <linux/errno.h>               /* For the -ENODEV/... values */
+#include <linux/kernel.h>              /* For printk/panic/... */
+#include <linux/init.h>                        /* For __init/__exit/... */
+#include <linux/ioport.h>              /* For io-port access */
+
+#include <asm/io.h>                    /* For inb/outb/... */
+
+/* iTCO defines */
+#define        SMI_EN          acpibase + 0x30 /* SMI Control and Enable Register */
+#define        TCOBASE         acpibase + 0x60 /* TCO base address             */
+#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
+
+/* List of vendor support modes */
+#define SUPERMICRO_OLD_BOARD   1       /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */
+#define SUPERMICRO_NEW_BOARD   2       /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */
+
+static int vendorsupport = 0;
+module_param(vendorsupport, int, 0);
+MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+");
+
+/*
+ *     Vendor Specific Support
+ */
+
+/*
+ *     Vendor Support: 1
+ *     Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE
+ *     iTCO chipset: ICH2
+ *
+ *     Code contributed by: R. Seretny <lkpatches@paypc.com>
+ *     Documentation obtained by R. Seretny from SuperMicro Technical Support
+ *
+ *     To enable Watchdog function:
+ *         BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes
+ *         This setting enables SMI to clear the watchdog expired flag.
+ *         If BIOS or CPU fail which may cause SMI hang, then system will
+ *         reboot. When application starts to use watchdog function,
+ *         application has to take over the control from SMI.
+ *
+ *         For P3TSSE, J36 jumper needs to be removed to enable the Watchdog
+ *         function.
+ *
+ *         Note: The system will reboot when Expire Flag is set TWICE.
+ *         So, if the watchdog timer is 20 seconds, then the maximum hang
+ *         time is about 40 seconds, and the minimum hang time is about
+ *         20.6 seconds.
+ */
+
+static void supermicro_old_pre_start(unsigned long acpibase)
+{
+       unsigned long val32;
+
+       val32 = inl(SMI_EN);
+       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
+       outl(val32, SMI_EN);    /* Needed to activate watchdog */
+}
+
+static void supermicro_old_pre_stop(unsigned long acpibase)
+{
+       unsigned long val32;
+
+       val32 = inl(SMI_EN);
+       val32 &= 0x00002000;    /* Turn on SMI clearing watchdog */
+       outl(val32, SMI_EN);    /* Needed to deactivate watchdog */
+}
+
+static void supermicro_old_pre_keepalive(unsigned long acpibase)
+{
+       /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
+       /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */
+       outb(0x08, TCO1_STS);
+}
+
+/*
+ *     Vendor Support: 2
+ *     Board: Super Micro Computer Inc. P4SBx, P4DPx
+ *     iTCO chipset: ICH4
+ *
+ *     Code contributed by: R. Seretny <lkpatches@paypc.com>
+ *     Documentation obtained by R. Seretny from SuperMicro Technical Support
+ *
+ *     To enable Watchdog function:
+ *      1. BIOS
+ *       For P4SBx:
+ *       BIOS setup -> Advanced -> Integrated Peripherals -> Watch Dog Feature
+ *       For P4DPx:
+ *       BIOS setup -> Advanced -> I/O Device Configuration -> Watch Dog
+ *      This setting enables or disables Watchdog function. When enabled, the
+ *      default watchdog timer is set to be 5 minutes (about 4’35”). It is
+ *      enough to load and run the OS. The application (service or driver) has
+ *      to take over the control once OS is running up and before watchdog
+ *      expires.
+ *
+ *      2. JUMPER
+ *       For P4SBx: JP39
+ *       For P4DPx: JP37
+ *       This jumper is used for safety.  Closed is enabled. This jumper
+ *       prevents user enables watchdog in BIOS by accident.
+ *
+ *      To enable Watch Dog function, both BIOS and JUMPER must be enabled.
+ *
+ *     The documentation lists motherboards P4SBx and P4DPx series as of
+ *     20-March-2002. However, this code works flawlessly with much newer
+ *     motherboards, such as my X6DHR-8G2 (SuperServer 6014H-82).
+ *
+ *     The original iTCO driver as written does not actually reset the
+ *     watchdog timer on these machines, as a result they reboot after five
+ *     minutes.
+ *
+ *     NOTE: You may leave the Watchdog function disabled in the SuperMicro
+ *     BIOS to avoid a "boot-race"... This driver will enable watchdog
+ *     functionality even if it's disabled in the BIOS once the /dev/watchdog
+ *     file is opened.
+ */
+
+/* I/O Port's */
+#define SM_REGINDEX    0x2e            /* SuperMicro ICH4+ Register Index */
+#define SM_DATAIO      0x2f            /* SuperMicro ICH4+ Register Data I/O */
+
+/* Control Register's */
+#define SM_CTLPAGESW   0x07            /* SuperMicro ICH4+ Control Page Switch */
+#define SM_CTLPAGE             0x08    /* SuperMicro ICH4+ Control Page Num */
+
+#define SM_WATCHENABLE 0x30            /* Watchdog enable: Bit 0: 0=off, 1=on */
+
+#define SM_WATCHPAGE   0x87            /* Watchdog unlock control page */
+
+#define SM_ENDWATCH    0xAA            /* Watchdog lock control page */
+
+#define SM_COUNTMODE   0xf5            /* Watchdog count mode select */
+                                       /* (Bit 3: 0 = seconds, 1 = minutes */
+
+#define SM_WATCHTIMER  0xf6            /* 8-bits, Watchdog timer counter (RW) */
+
+#define SM_RESETCONTROL        0xf7            /* Watchdog reset control */
+                                       /* Bit 6: timer is reset by kbd interrupt */
+                                       /* Bit 7: timer is reset by mouse interrupt */
+
+static void supermicro_new_unlock_watchdog(void)
+{
+       outb(SM_WATCHPAGE, SM_REGINDEX);        /* Write 0x87 to port 0x2e twice */
+       outb(SM_WATCHPAGE, SM_REGINDEX);
+
+       outb(SM_CTLPAGESW, SM_REGINDEX);        /* Switch to watchdog control page */
+       outb(SM_CTLPAGE, SM_DATAIO);
+}
+
+static void supermicro_new_lock_watchdog(void)
+{
+       outb(SM_ENDWATCH, SM_REGINDEX);
+}
+
+static void supermicro_new_pre_start(unsigned int heartbeat)
+{
+       unsigned int val;
+
+       supermicro_new_unlock_watchdog();
+
+       /* Watchdog timer setting needs to be in seconds*/
+       outb(SM_COUNTMODE, SM_REGINDEX);
+       val = inb(SM_DATAIO);
+       val &= 0xF7;
+       outb(val, SM_DATAIO);
+
+       /* Write heartbeat interval to WDOG */
+       outb (SM_WATCHTIMER, SM_REGINDEX);
+       outb((heartbeat & 255), SM_DATAIO);
+
+       /* Make sure keyboard/mouse interrupts don't interfere */
+       outb(SM_RESETCONTROL, SM_REGINDEX);
+       val = inb(SM_DATAIO);
+       val &= 0x3f;
+       outb(val, SM_DATAIO);
+
+       /* enable watchdog by setting bit 0 of Watchdog Enable to 1 */
+       outb(SM_WATCHENABLE, SM_REGINDEX);
+       val = inb(SM_DATAIO);
+       val |= 0x01;
+       outb(val, SM_DATAIO);
+
+       supermicro_new_lock_watchdog();
+}
+
+static void supermicro_new_pre_stop(void)
+{
+       unsigned int val;
+
+       supermicro_new_unlock_watchdog();
+
+       /* disable watchdog by setting bit 0 of Watchdog Enable to 0 */
+       outb(SM_WATCHENABLE, SM_REGINDEX);
+       val = inb(SM_DATAIO);
+       val &= 0xFE;
+       outb(val, SM_DATAIO);
+
+       supermicro_new_lock_watchdog();
+}
+
+static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
+{
+       supermicro_new_unlock_watchdog();
+
+       /* reset watchdog timeout to heartveat value */
+       outb(SM_WATCHTIMER, SM_REGINDEX);
+       outb((heartbeat & 255), SM_DATAIO);
+
+       supermicro_new_lock_watchdog();
+}
+
+/*
+ *     Generic Support Functions
+ */
+
+void iTCO_vendor_pre_start(unsigned long acpibase,
+                          unsigned int heartbeat)
+{
+       if (vendorsupport == SUPERMICRO_OLD_BOARD)
+               supermicro_old_pre_start(acpibase);
+       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+               supermicro_new_pre_start(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_start);
+
+void iTCO_vendor_pre_stop(unsigned long acpibase)
+{
+       if (vendorsupport == SUPERMICRO_OLD_BOARD)
+               supermicro_old_pre_stop(acpibase);
+       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+               supermicro_new_pre_stop();
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_stop);
+
+void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
+{
+       if (vendorsupport == SUPERMICRO_OLD_BOARD)
+               supermicro_old_pre_keepalive(acpibase);
+       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
+               supermicro_new_pre_set_heartbeat(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
+
+void iTCO_vendor_pre_set_heartbeat(unsigned int heartbeat)
+{
+       if (vendorsupport == SUPERMICRO_NEW_BOARD)
+               supermicro_new_pre_set_heartbeat(heartbeat);
+}
+EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat);
+
+int iTCO_vendor_check_noreboot_on(void)
+{
+       switch(vendorsupport) {
+       case SUPERMICRO_OLD_BOARD:
+               return 0;
+       default:
+               return 1;
+       }
+}
+EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
+
+static int __init iTCO_vendor_init_module(void)
+{
+       printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
+       return 0;
+}
+
+static void __exit iTCO_vendor_exit_module(void)
+{
+       printk (KERN_INFO PFX "Module Unloaded\n");
+}
+
+module_init(iTCO_vendor_init_module);
+module_exit(iTCO_vendor_exit_module);
+
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>, R. Seretny <lkpatches@paypc.com>");
+MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
new file mode 100644 (file)
index 0000000..cd5a565
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+ *     intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
+ *
+ *     (c) Copyright 2006-2007 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ *
+ *     The TCO watchdog is implemented in the following I/O controller hubs:
+ *     (See the intel documentation on http://developer.intel.com.)
+ *     82801AA  (ICH)       : document number 290655-003, 290677-014,
+ *     82801AB  (ICHO)      : document number 290655-003, 290677-014,
+ *     82801BA  (ICH2)      : document number 290687-002, 298242-027,
+ *     82801BAM (ICH2-M)    : document number 290687-002, 298242-027,
+ *     82801CA  (ICH3-S)    : document number 290733-003, 290739-013,
+ *     82801CAM (ICH3-M)    : document number 290716-001, 290718-007,
+ *     82801DB  (ICH4)      : document number 290744-001, 290745-020,
+ *     82801DBM (ICH4-M)    : document number 252337-001, 252663-005,
+ *     82801E   (C-ICH)     : document number 273599-001, 273645-002,
+ *     82801EB  (ICH5)      : document number 252516-001, 252517-003,
+ *     82801ER  (ICH5R)     : document number 252516-001, 252517-003,
+ *     82801FB  (ICH6)      : document number 301473-002, 301474-007,
+ *     82801FR  (ICH6R)     : document number 301473-002, 301474-007,
+ *     82801FBM (ICH6-M)    : document number 301473-002, 301474-007,
+ *     82801FW  (ICH6W)     : document number 301473-001, 301474-007,
+ *     82801FRW (ICH6RW)    : document number 301473-001, 301474-007,
+ *     82801GB  (ICH7)      : document number 307013-002, 307014-009,
+ *     82801GR  (ICH7R)     : document number 307013-002, 307014-009,
+ *     82801GDH (ICH7DH)    : document number 307013-002, 307014-009,
+ *     82801GBM (ICH7-M)    : document number 307013-002, 307014-009,
+ *     82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
+ *     82801HB  (ICH8)      : document number 313056-002, 313057-004,
+ *     82801HR  (ICH8R)     : document number 313056-002, 313057-004,
+ *     82801HH  (ICH8DH)    : document number 313056-002, 313057-004,
+ *     82801HO  (ICH8DO)    : document number 313056-002, 313057-004,
+ *     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
+ */
+
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
+
+/* Module and version information */
+#define DRV_NAME        "iTCO_wdt"
+#define DRV_VERSION     "1.02"
+#define DRV_RELDATE     "26-Jul-2007"
+#define PFX            DRV_NAME ": "
+
+/* Includes */
+#include <linux/module.h>              /* For module specific items */
+#include <linux/moduleparam.h>         /* For new moduleparam's */
+#include <linux/types.h>               /* For standard types (like size_t) */
+#include <linux/errno.h>               /* For the -ENODEV/... values */
+#include <linux/kernel.h>              /* For printk/panic/... */
+#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>            /* For the watchdog specific items */
+#include <linux/init.h>                        /* For __init/__exit/... */
+#include <linux/fs.h>                  /* For file operations */
+#include <linux/platform_device.h>     /* For platform_driver framework */
+#include <linux/pci.h>                 /* For pci functions */
+#include <linux/ioport.h>              /* For io-port access */
+#include <linux/spinlock.h>            /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h>               /* For copy_to_user/put_user/... */
+#include <asm/io.h>                    /* For inb/outb/... */
+
+/* TCO related info */
+enum iTCO_chipsets {
+       TCO_ICH = 0,    /* ICH */
+       TCO_ICH0,       /* ICH0 */
+       TCO_ICH2,       /* ICH2 */
+       TCO_ICH2M,      /* ICH2-M */
+       TCO_ICH3,       /* ICH3-S */
+       TCO_ICH3M,      /* ICH3-M */
+       TCO_ICH4,       /* ICH4 */
+       TCO_ICH4M,      /* ICH4-M */
+       TCO_CICH,       /* C-ICH */
+       TCO_ICH5,       /* ICH5 & ICH5R */
+       TCO_6300ESB,    /* 6300ESB */
+       TCO_ICH6,       /* ICH6 & ICH6R */
+       TCO_ICH6M,      /* ICH6-M */
+       TCO_ICH6W,      /* ICH6W & ICH6RW */
+       TCO_ICH7,       /* ICH7 & ICH7R */
+       TCO_ICH7M,      /* ICH7-M */
+       TCO_ICH7MDH,    /* ICH7-M DH */
+       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 {
+       char *name;
+       unsigned int iTCO_version;
+} iTCO_chipset_info[] __devinitdata = {
+       {"ICH", 1},
+       {"ICH0", 1},
+       {"ICH2", 1},
+       {"ICH2-M", 1},
+       {"ICH3-S", 1},
+       {"ICH3-M", 1},
+       {"ICH4", 1},
+       {"ICH4-M", 1},
+       {"C-ICH", 1},
+       {"ICH5 or ICH5R", 1},
+       {"6300ESB", 1},
+       {"ICH6 or ICH6R", 2},
+       {"ICH6-M", 2},
+       {"ICH6W or ICH6RW", 2},
+       {"ICH7 or ICH7R", 2},
+       {"ICH7-M", 2},
+       {"ICH7-M DH", 2},
+       {"ICH8 or ICH8R", 2},
+       {"ICH8DH", 2},
+       {"ICH8DO", 2},
+       {"ICH9", 2},
+       {"ICH9R", 2},
+       {"ICH9DH", 2},
+       {"631xESB/632xESB", 2},
+       {NULL,0}
+};
+
+/*
+ * This data only exists for exporting the supported PCI ids
+ * via MODULE_DEVICE_TABLE.  We do not actually register a
+ * pci_driver, because the I/O Controller Hub has also other
+ * functions that probably will be registered by other drivers.
+ */
+static struct pci_device_id iTCO_wdt_pci_tbl[] = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH     },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,       PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7    },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M   },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
+       { 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);
+
+/* Address definitions for the TCO */
+#define        TCOBASE         iTCO_wdt_private.ACPIBASE + 0x60        /* TCO base address                */
+#define        SMI_EN          iTCO_wdt_private.ACPIBASE + 0x30        /* SMI Control and Enable Register */
+
+#define TCO_RLD                TCOBASE + 0x00  /* TCO Timer Reload and Current Value */
+#define TCOv1_TMR      TCOBASE + 0x01  /* TCOv1 Timer Initial Value    */
+#define        TCO_DAT_IN      TCOBASE + 0x02  /* TCO Data In Register         */
+#define        TCO_DAT_OUT     TCOBASE + 0x03  /* TCO Data Out Register        */
+#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
+#define        TCO2_STS        TCOBASE + 0x06  /* TCO2 Status Register         */
+#define TCO1_CNT       TCOBASE + 0x08  /* TCO1 Control Register        */
+#define TCO2_CNT       TCOBASE + 0x0a  /* TCO2 Control Register        */
+#define TCOv2_TMR      TCOBASE + 0x12  /* TCOv2 Timer Initial Value    */
+
+/* internal variables */
+static unsigned long is_active;
+static char expect_release;
+static struct {                                /* this is private data for the iTCO_wdt device */
+       unsigned int iTCO_version;      /* TCO version/generation */
+       unsigned long ACPIBASE;         /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
+       unsigned long __iomem *gcs;     /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */
+       spinlock_t io_lock;             /* the lock for io operations */
+       struct pci_dev *pdev;           /* the PCI-device */
+} iTCO_wdt_private;
+
+static struct platform_device *iTCO_wdt_platform_device;       /* the watchdog platform device */
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30  /* 30 sec default heartbeat */
+static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+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) ")");
+
+/* iTCO Vendor Specific Support hooks */
+#ifdef CONFIG_ITCO_VENDOR_SUPPORT
+extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_stop(unsigned long);
+extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
+extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
+extern int iTCO_vendor_check_noreboot_on(void);
+#else
+#define iTCO_vendor_pre_start(acpibase, heartbeat)     {}
+#define iTCO_vendor_pre_stop(acpibase)                 {}
+#define iTCO_vendor_pre_keepalive(acpibase,heartbeat)  {}
+#define iTCO_vendor_pre_set_heartbeat(heartbeat)       {}
+#define iTCO_vendor_check_noreboot_on()                        1       /* 1=check noreboot; 0=don't check */
+#endif
+
+/*
+ * Some TCO specific functions
+ */
+
+static inline unsigned int seconds_to_ticks(int seconds)
+{
+       /* the internal timer is stored as ticks which decrement
+        * every 0.6 seconds */
+       return (seconds * 10) / 6;
+}
+
+static void iTCO_wdt_set_NO_REBOOT_bit(void)
+{
+       u32 val32;
+
+       /* Set the NO_REBOOT bit: this disables reboots */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               val32 = readl(iTCO_wdt_private.gcs);
+               val32 |= 0x00000020;
+               writel(val32, iTCO_wdt_private.gcs);
+       } else if (iTCO_wdt_private.iTCO_version == 1) {
+               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
+               val32 |= 0x00000002;
+               pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
+       }
+}
+
+static int iTCO_wdt_unset_NO_REBOOT_bit(void)
+{
+       int ret = 0;
+       u32 val32;
+
+       /* Unset the NO_REBOOT bit: this enables reboots */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               val32 = readl(iTCO_wdt_private.gcs);
+               val32 &= 0xffffffdf;
+               writel(val32, iTCO_wdt_private.gcs);
+
+               val32 = readl(iTCO_wdt_private.gcs);
+               if (val32 & 0x00000020)
+                       ret = -EIO;
+       } else if (iTCO_wdt_private.iTCO_version == 1) {
+               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
+               val32 &= 0xfffffffd;
+               pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
+
+               pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
+               if (val32 & 0x00000002)
+                       ret = -EIO;
+       }
+
+       return ret; /* returns: 0 = OK, -EIO = Error */
+}
+
+static int iTCO_wdt_start(void)
+{
+       unsigned int val;
+
+       spin_lock(&iTCO_wdt_private.io_lock);
+
+       iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
+
+       /* disable chipset's NO_REBOOT bit */
+       if (iTCO_wdt_unset_NO_REBOOT_bit()) {
+               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
+               return -EIO;
+       }
+
+       /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
+       val = inw(TCO1_CNT);
+       val &= 0xf7ff;
+       outw(val, TCO1_CNT);
+       val = inw(TCO1_CNT);
+       spin_unlock(&iTCO_wdt_private.io_lock);
+
+       if (val & 0x0800)
+               return -1;
+       return 0;
+}
+
+static int iTCO_wdt_stop(void)
+{
+       unsigned int val;
+
+       spin_lock(&iTCO_wdt_private.io_lock);
+
+       iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
+
+       /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
+       val = inw(TCO1_CNT);
+       val |= 0x0800;
+       outw(val, TCO1_CNT);
+       val = inw(TCO1_CNT);
+
+       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+       iTCO_wdt_set_NO_REBOOT_bit();
+
+       spin_unlock(&iTCO_wdt_private.io_lock);
+
+       if ((val & 0x0800) == 0)
+               return -1;
+       return 0;
+}
+
+static int iTCO_wdt_keepalive(void)
+{
+       spin_lock(&iTCO_wdt_private.io_lock);
+
+       iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
+
+       /* Reload the timer by writing to the TCO Timer Counter register */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               outw(0x01, TCO_RLD);
+       } else if (iTCO_wdt_private.iTCO_version == 1) {
+               outb(0x01, TCO_RLD);
+       }
+
+       spin_unlock(&iTCO_wdt_private.io_lock);
+       return 0;
+}
+
+static int iTCO_wdt_set_heartbeat(int t)
+{
+       unsigned int val16;
+       unsigned char val8;
+       unsigned int tmrval;
+
+       tmrval = seconds_to_ticks(t);
+       /* from the specs: */
+       /* "Values of 0h-3h are ignored and should not be attempted" */
+       if (tmrval < 0x04)
+               return -EINVAL;
+       if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
+           ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
+               return -EINVAL;
+
+       iTCO_vendor_pre_set_heartbeat(tmrval);
+
+       /* Write new heartbeat to watchdog */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               spin_lock(&iTCO_wdt_private.io_lock);
+               val16 = inw(TCOv2_TMR);
+               val16 &= 0xfc00;
+               val16 |= tmrval;
+               outw(val16, TCOv2_TMR);
+               val16 = inw(TCOv2_TMR);
+               spin_unlock(&iTCO_wdt_private.io_lock);
+
+               if ((val16 & 0x3ff) != tmrval)
+                       return -EINVAL;
+       } else if (iTCO_wdt_private.iTCO_version == 1) {
+               spin_lock(&iTCO_wdt_private.io_lock);
+               val8 = inb(TCOv1_TMR);
+               val8 &= 0xc0;
+               val8 |= (tmrval & 0xff);
+               outb(val8, TCOv1_TMR);
+               val8 = inb(TCOv1_TMR);
+               spin_unlock(&iTCO_wdt_private.io_lock);
+
+               if ((val8 & 0x3f) != tmrval)
+                       return -EINVAL;
+       }
+
+       heartbeat = t;
+       return 0;
+}
+
+static int iTCO_wdt_get_timeleft (int *time_left)
+{
+       unsigned int val16;
+       unsigned char val8;
+
+       /* read the TCO Timer */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               spin_lock(&iTCO_wdt_private.io_lock);
+               val16 = inw(TCO_RLD);
+               val16 &= 0x3ff;
+               spin_unlock(&iTCO_wdt_private.io_lock);
+
+               *time_left = (val16 * 6) / 10;
+       } else if (iTCO_wdt_private.iTCO_version == 1) {
+               spin_lock(&iTCO_wdt_private.io_lock);
+               val8 = inb(TCO_RLD);
+               val8 &= 0x3f;
+               spin_unlock(&iTCO_wdt_private.io_lock);
+
+               *time_left = (val8 * 6) / 10;
+       } else
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int iTCO_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;
+
+       /*
+        *      Reload and activate timer
+        */
+       iTCO_wdt_keepalive();
+       iTCO_wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+static int iTCO_wdt_release (struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       if (expect_release == 42) {
+               iTCO_wdt_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               iTCO_wdt_keepalive();
+       }
+       clear_bit(0, &is_active);
+       expect_release = 0;
+       return 0;
+}
+
+static ssize_t iTCO_wdt_write (struct file *file, const char __user *data,
+                             size_t len, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       expect_release = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if (get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_release = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               iTCO_wdt_keepalive();
+       }
+       return len;
+}
+
+static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       int new_options, retval = -EINVAL;
+       int new_heartbeat;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT |
+                                       WDIOF_KEEPALIVEPING |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     0,
+               .identity =             DRV_NAME,
+       };
+
+       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:
+                       iTCO_wdt_keepalive();
+                       return 0;
+
+               case WDIOC_SETOPTIONS:
+               {
+                       if (get_user(new_options, p))
+                               return -EFAULT;
+
+                       if (new_options & WDIOS_DISABLECARD) {
+                               iTCO_wdt_stop();
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_ENABLECARD) {
+                               iTCO_wdt_keepalive();
+                               iTCO_wdt_start();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+
+               case WDIOC_SETTIMEOUT:
+               {
+                       if (get_user(new_heartbeat, p))
+                               return -EFAULT;
+
+                       if (iTCO_wdt_set_heartbeat(new_heartbeat))
+                               return -EINVAL;
+
+                       iTCO_wdt_keepalive();
+                       /* Fall */
+               }
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, p);
+
+               case WDIOC_GETTIMELEFT:
+               {
+                       int time_left;
+
+                       if (iTCO_wdt_get_timeleft(&time_left))
+                               return -EINVAL;
+
+                       return put_user(time_left, p);
+               }
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations iTCO_wdt_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .write =        iTCO_wdt_write,
+       .ioctl =        iTCO_wdt_ioctl,
+       .open =         iTCO_wdt_open,
+       .release =      iTCO_wdt_release,
+};
+
+static struct miscdevice iTCO_wdt_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &iTCO_wdt_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
+{
+       int ret;
+       u32 base_address;
+       unsigned long RCBA;
+       unsigned long val32;
+
+       /*
+        *      Find the ACPI/PM base I/O address which is the base
+        *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
+        *      ACPIBASE is bits [15:7] from 0x40-0x43
+        */
+       pci_read_config_dword(pdev, 0x40, &base_address);
+       base_address &= 0x0000ff80;
+       if (base_address == 0x00000000) {
+               /* Something's wrong here, ACPIBASE has to be set */
+               printk(KERN_ERR PFX "failed to get TCOBASE address\n");
+               pci_dev_put(pdev);
+               return -ENODEV;
+       }
+       iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version;
+       iTCO_wdt_private.ACPIBASE = base_address;
+       iTCO_wdt_private.pdev = pdev;
+
+       /* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */
+       /* To get access to it you have to read RCBA from PCI Config space 0xf0
+          and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */
+       if (iTCO_wdt_private.iTCO_version == 2) {
+               pci_read_config_dword(pdev, 0xf0, &base_address);
+               RCBA = base_address & 0xffffc000;
+               iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4);
+       }
+
+       /* Check chipset's NO_REBOOT bit */
+       if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
+               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
+               ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
+               goto out;
+       }
+
+       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+       iTCO_wdt_set_NO_REBOOT_bit();
+
+       /* Set the TCO_EN bit in SMI_EN register */
+       if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
+               printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
+                       SMI_EN );
+               ret = -EIO;
+               goto out;
+       }
+       val32 = inl(SMI_EN);
+       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
+       outl(val32, SMI_EN);
+       release_region(SMI_EN, 4);
+
+       /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */
+       if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) {
+               printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n",
+                       TCOBASE);
+               ret = -EIO;
+               goto out;
+       }
+
+       printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
+               iTCO_chipset_info[ent->driver_data].name,
+               iTCO_chipset_info[ent->driver_data].iTCO_version,
+               TCOBASE);
+
+       /* Clear out the (probably old) status */
+       outb(0, TCO1_STS);
+       outb(3, TCO2_STS);
+
+       /* Make sure the watchdog is not running */
+       iTCO_wdt_stop();
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (iTCO_wdt_set_heartbeat(heartbeat)) {
+               iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
+               printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n",
+                       heartbeat);
+       }
+
+       ret = misc_register(&iTCO_wdt_miscdev);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto unreg_region;
+       }
+
+       printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+
+       return 0;
+
+unreg_region:
+       release_region (TCOBASE, 0x20);
+out:
+       if (iTCO_wdt_private.iTCO_version == 2)
+               iounmap(iTCO_wdt_private.gcs);
+       pci_dev_put(iTCO_wdt_private.pdev);
+       iTCO_wdt_private.ACPIBASE = 0;
+       return ret;
+}
+
+static void iTCO_wdt_cleanup(void)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+               iTCO_wdt_stop();
+
+       /* Deregister */
+       misc_deregister(&iTCO_wdt_miscdev);
+       release_region(TCOBASE, 0x20);
+       if (iTCO_wdt_private.iTCO_version == 2)
+               iounmap(iTCO_wdt_private.gcs);
+       pci_dev_put(iTCO_wdt_private.pdev);
+       iTCO_wdt_private.ACPIBASE = 0;
+}
+
+static int iTCO_wdt_probe(struct platform_device *dev)
+{
+       int found = 0;
+       struct pci_dev *pdev = NULL;
+       const struct pci_device_id *ent;
+
+       spin_lock_init(&iTCO_wdt_private.io_lock);
+
+       for_each_pci_dev(pdev) {
+               ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
+               if (ent) {
+                       if (!(iTCO_wdt_init(pdev, ent, dev))) {
+                               found++;
+                               break;
+                       }
+               }
+       }
+
+       if (!found) {
+               printk(KERN_INFO PFX "No card detected\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int iTCO_wdt_remove(struct platform_device *dev)
+{
+       if (iTCO_wdt_private.ACPIBASE)
+               iTCO_wdt_cleanup();
+
+       return 0;
+}
+
+static void iTCO_wdt_shutdown(struct platform_device *dev)
+{
+       iTCO_wdt_stop();
+}
+
+#define iTCO_wdt_suspend NULL
+#define iTCO_wdt_resume  NULL
+
+static struct platform_driver iTCO_wdt_driver = {
+       .probe          = iTCO_wdt_probe,
+       .remove         = iTCO_wdt_remove,
+       .shutdown       = iTCO_wdt_shutdown,
+       .suspend        = iTCO_wdt_suspend,
+       .resume         = iTCO_wdt_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init iTCO_wdt_init_module(void)
+{
+       int err;
+
+       printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n",
+               DRV_VERSION, DRV_RELDATE);
+
+       err = platform_driver_register(&iTCO_wdt_driver);
+       if (err)
+               return err;
+
+       iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(iTCO_wdt_platform_device)) {
+               err = PTR_ERR(iTCO_wdt_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&iTCO_wdt_driver);
+       return err;
+}
+
+static void __exit iTCO_wdt_cleanup_module(void)
+{
+       platform_device_unregister(iTCO_wdt_platform_device);
+       platform_driver_unregister(&iTCO_wdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(iTCO_wdt_init_module);
+module_exit(iTCO_wdt_cleanup_module);
+
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
+MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
new file mode 100644 (file)
index 0000000..c3a60f5
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ *     IB700 Single Board Computer WDT driver
+ *
+ *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ *     Based on advantechwdt.c which is based on acquirewdt.c which
+ *     is based on wdt.c.
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     Based on acquirewdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
+ *
+ *     14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static struct platform_device *ibwdt_platform_device;
+static unsigned long ibwdt_is_open;
+static spinlock_t ibwdt_lock;
+static char expect_close;
+
+/* Module information */
+#define DRV_NAME "ib700wdt"
+#define PFX DRV_NAME ": "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system
+ * automatically and is defined at I/O port 0443H.  To enable the
+ * watchdog timer and allow the system to reset, write I/O port 0443H.
+ * To disable the timer, write I/O port 0441H for the system to stop the
+ * watchdog function.  The timer has a tolerance of 20% for its
+ * intervals.
+ *
+ * The following describes how the timer should be programmed.
+ *
+ * Enabling Watchdog:
+ * MOV AX,000FH (Choose the values from 0 to F)
+ * MOV DX,0443H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,000FH (Any value is fine.)
+ * MOV DX,0441H
+ * OUT DX,AX
+ *
+ * Watchdog timer control table:
+ * Level   Value  Time/sec | Level Value Time/sec
+ *   1       F       0     |   9     7      16
+ *   2       E       2     |   10    6      18
+ *   3       D       4     |   11    5      20
+ *   4       C       6     |   12    4      22
+ *   5       B       8     |   13    3      24
+ *   6       A       10    |   14    2      26
+ *   7       9       12    |   15    1      28
+ *   8       8       14    |   16    0      30
+ *
+ */
+
+static int wd_times[] = {
+       30,     /* 0x0 */
+       28,     /* 0x1 */
+       26,     /* 0x2 */
+       24,     /* 0x3 */
+       22,     /* 0x4 */
+       20,     /* 0x5 */
+       18,     /* 0x6 */
+       16,     /* 0x7 */
+       14,     /* 0x8 */
+       12,     /* 0x9 */
+       10,     /* 0xA */
+       8,      /* 0xB */
+       6,      /* 0xC */
+       4,      /* 0xD */
+       2,      /* 0xE */
+       0,      /* 0xF */
+};
+
+#define WDT_STOP 0x441
+#define WDT_START 0x443
+
+/* Default timeout */
+#define WD_TIMO 0              /* 30 seconds +/- 20%, from table */
+
+static int wd_margin = WD_TIMO;
+
+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) ")");
+
+
+/*
+ *     Watchdog Operations
+ */
+
+static void
+ibwdt_ping(void)
+{
+       spin_lock(&ibwdt_lock);
+
+       /* Write a watchdog value */
+       outb_p(wd_margin, WDT_START);
+
+       spin_unlock(&ibwdt_lock);
+}
+
+static void
+ibwdt_disable(void)
+{
+       spin_lock(&ibwdt_lock);
+       outb_p(0, WDT_STOP);
+       spin_unlock(&ibwdt_lock);
+}
+
+static int
+ibwdt_set_heartbeat(int t)
+{
+       int i;
+
+       if ((t < 0) || (t > 30))
+               return -EINVAL;
+
+       for (i = 0x0F; i > -1; i--)
+               if (wd_times[i] > t)
+                       break;
+       wd_margin = i;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t
+ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               ibwdt_ping();
+       }
+       return count;
+}
+
+static int
+ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       int new_margin;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "IB700 WDT",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user(argp, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+         return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+         ibwdt_ping();
+         break;
+
+       case WDIOC_SETTIMEOUT:
+         if (get_user(new_margin, p))
+                 return -EFAULT;
+         if (ibwdt_set_heartbeat(new_margin))
+                 return -EINVAL;
+         ibwdt_ping();
+         /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+         return put_user(wd_times[wd_margin], p);
+
+       case WDIOC_SETOPTIONS:
+       {
+         int options, retval = -EINVAL;
+
+         if (get_user(options, p))
+           return -EFAULT;
+
+         if (options & WDIOS_DISABLECARD) {
+           ibwdt_disable();
+           retval = 0;
+         }
+
+         if (options & WDIOS_ENABLECARD) {
+           ibwdt_ping();
+           retval = 0;
+         }
+
+         return retval;
+       }
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+ibwdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &ibwdt_is_open)) {
+               return -EBUSY;
+       }
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate */
+       ibwdt_ping();
+       return nonseekable_open(inode, file);
+}
+
+static int
+ibwdt_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               ibwdt_disable();
+       } else {
+               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
+               ibwdt_ping();
+       }
+       clear_bit(0, &ibwdt_is_open);
+       expect_close = 0;
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations ibwdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = ibwdt_write,
+       .ioctl          = ibwdt_ioctl,
+       .open           = ibwdt_open,
+       .release        = ibwdt_close,
+};
+
+static struct miscdevice ibwdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &ibwdt_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int __devinit ibwdt_probe(struct platform_device *dev)
+{
+       int res;
+
+       spin_lock_init(&ibwdt_lock);
+
+#if WDT_START != WDT_STOP
+       if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
+               printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP);
+               res = -EIO;
+               goto out_nostopreg;
+       }
+#endif
+
+       if (!request_region(WDT_START, 1, "IB700 WDT")) {
+               printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START);
+               res = -EIO;
+               goto out_nostartreg;
+       }
+
+       res = misc_register(&ibwdt_miscdev);
+       if (res) {
+               printk (KERN_ERR PFX "failed to register misc device\n");
+               goto out_nomisc;
+       }
+       return 0;
+
+out_nomisc:
+       release_region(WDT_START, 1);
+out_nostartreg:
+#if WDT_START != WDT_STOP
+       release_region(WDT_STOP, 1);
+#endif
+out_nostopreg:
+       return res;
+}
+
+static int __devexit ibwdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&ibwdt_miscdev);
+       release_region(WDT_START,1);
+#if WDT_START != WDT_STOP
+       release_region(WDT_STOP,1);
+#endif
+       return 0;
+}
+
+static void ibwdt_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       ibwdt_disable();
+}
+
+static struct platform_driver ibwdt_driver = {
+       .probe          = ibwdt_probe,
+       .remove         = __devexit_p(ibwdt_remove),
+       .shutdown       = ibwdt_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init ibwdt_init(void)
+{
+       int err;
+
+       printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n");
+
+       err = platform_driver_register(&ibwdt_driver);
+       if (err)
+               return err;
+
+       ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
+       if (IS_ERR(ibwdt_platform_device)) {
+               err = PTR_ERR(ibwdt_platform_device);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&ibwdt_driver);
+       return err;
+}
+
+static void __exit ibwdt_exit(void)
+{
+       platform_device_unregister(ibwdt_platform_device);
+       platform_driver_unregister(&ibwdt_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(ibwdt_init);
+module_exit(ibwdt_exit);
+
+MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
+MODULE_DESCRIPTION("IB700 SBC watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of ib700wdt.c */
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
new file mode 100644 (file)
index 0000000..94155f6
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+       ASMTYPE_UNKNOWN,
+       ASMTYPE_TOPAZ,
+       ASMTYPE_JASPER,
+       ASMTYPE_PEARL,
+       ASMTYPE_JUNIPER,
+       ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET   4
+#define TOPAZ_ASR_TOGGLE       0x40
+#define TOPAZ_ASR_DISABLE      0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE     0xe04
+#define PEARL_WRITE    0xe06
+#define PEARL_READ     0xe07
+
+#define PEARL_ASR_DISABLE_MASK 0x80    /* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK  0x40    /* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET  0x38
+
+#define JASPER_ASR_DISABLE_MASK        0x01    /* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK 0x02    /* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS   0x54b   /* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01  /* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK        0x02    /* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS    0x118e  /* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK        0x01    /* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK 0x02    /* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+       unsigned char reg = inb(asr_read_addr);
+
+       outb(reg & ~asr_toggle_mask, asr_write_addr);
+       reg = inb(asr_read_addr);
+
+       outb(reg | asr_toggle_mask, asr_write_addr);
+       reg = inb(asr_read_addr);
+
+       outb(reg & ~asr_toggle_mask, asr_write_addr);
+       reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+       unsigned char reg;
+
+       if (asr_type == ASMTYPE_TOPAZ) {
+               /* asr_write_addr == asr_read_addr */
+               reg = inb(asr_read_addr);
+               outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+                    asr_read_addr);
+       } else {
+               /*
+                * First make sure the hardware timer is reset by toggling
+                * ASR hardware timer line.
+                */
+               asr_toggle();
+
+               reg = inb(asr_read_addr);
+               outb(reg & ~asr_disable_mask, asr_write_addr);
+       }
+       reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+       unsigned char reg = inb(asr_read_addr);
+
+       if (asr_type == ASMTYPE_TOPAZ)
+               /* asr_write_addr == asr_read_addr */
+               outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+                    asr_read_addr);
+       else {
+               outb(reg | asr_toggle_mask, asr_write_addr);
+               reg = inb(asr_read_addr);
+
+               outb(reg | asr_disable_mask, asr_write_addr);
+       }
+       reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+       unsigned char low, high;
+       const char *type = "";
+
+       asr_length = 1;
+
+       switch (asr_type) {
+       case ASMTYPE_TOPAZ:
+               /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+               outb(0x07, 0x2e);
+               outb(0x07, 0x2f);
+
+               /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+               outb(0x60, 0x2e);
+               high = inb(0x2f);
+
+               /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+               outb(0x61, 0x2e);
+               low = inb(0x2f);
+
+               asr_base = (high << 16) | low;
+               asr_read_addr = asr_write_addr =
+                       asr_base + TOPAZ_ASR_REG_OFFSET;
+               asr_length = 5;
+
+               break;
+
+       case ASMTYPE_JASPER:
+               type = "Jaspers ";
+
+               /* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/*             spin_lock_irqsave(&pci_config_lock, flags);*/
+
+               /* Select the SuperIO chip in the PCI I/O port register */
+               outl(0x8000f858, 0xcf8);
+
+               /*
+                * Read the base address for the SuperIO chip.
+                * Only the lower 16 bits are valid, but the address is word
+                * aligned so the last bit must be masked off.
+                */
+               asr_base = inl(0xcfc) & 0xfffe;
+
+/*             spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+               asr_read_addr = asr_write_addr =
+                       asr_base + JASPER_ASR_REG_OFFSET;
+               asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+               asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+               asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+               break;
+
+       case ASMTYPE_PEARL:
+               type = "Pearls ";
+               asr_base = PEARL_BASE;
+               asr_read_addr = PEARL_READ;
+               asr_write_addr = PEARL_WRITE;
+               asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+               asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+               asr_length = 4;
+               break;
+
+       case ASMTYPE_JUNIPER:
+               type = "Junipers ";
+               asr_base = JUNIPER_BASE_ADDRESS;
+               asr_read_addr = asr_write_addr = asr_base;
+               asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+               asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+               break;
+
+       case ASMTYPE_SPRUCE:
+               type = "Spruce's ";
+               asr_base = SPRUCE_BASE_ADDRESS;
+               asr_read_addr = asr_write_addr = asr_base;
+               asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+               asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+               break;
+       }
+
+       if (!request_region(asr_base, asr_length, "ibmasr")) {
+               printk(KERN_ERR PFX "address %#x already in use\n",
+                       asr_base);
+               return -EBUSY;
+       }
+
+       printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+       return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       asr_expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       asr_expect_close = 42;
+                       }
+               }
+               asr_toggle();
+       }
+       return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+                    unsigned int cmd, unsigned long arg)
+{
+       static const struct watchdog_info ident = {
+               .options =      WDIOF_KEEPALIVEPING | 
+                               WDIOF_MAGICCLOSE,
+               .identity =     "IBM ASR"
+       };
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int heartbeat;
+
+       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:
+                       asr_toggle();
+                       return 0;
+
+               /*
+                * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+                * and WDIOC_GETTIMEOUT always returns 256.
+                */
+               case WDIOC_GETTIMEOUT:
+                       heartbeat = 256;
+                       return put_user(heartbeat, p);
+
+               case WDIOC_SETOPTIONS: {
+                       int new_options, retval = -EINVAL;
+
+                       if (get_user(new_options, p))
+                               return -EFAULT;
+
+                       if (new_options & WDIOS_DISABLECARD) {
+                               asr_disable();
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_ENABLECARD) {
+                               asr_enable();
+                               asr_toggle();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+       }
+
+       return -ENOTTY;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+       if(test_and_set_bit(0, &asr_is_open))
+               return -EBUSY;
+
+       asr_toggle();
+       asr_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+       if (asr_expect_close == 42)
+               asr_disable();
+       else {
+               printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+               asr_toggle();
+       }
+       clear_bit(0, &asr_is_open);
+       asr_expect_close = 0;
+       return 0;
+}
+
+static const struct file_operations asr_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .write =        asr_write,
+       .ioctl =        asr_ioctl,
+       .open =         asr_open,
+       .release =      asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &asr_fops,
+};
+
+
+struct ibmasr_id {
+       const char *desc;
+       int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+       { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+       { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+       { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+       { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+       { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+       { NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+       struct ibmasr_id *id;
+       int rc;
+
+       for (id = ibmasr_id_table; id->desc; id++) {
+               if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+                       asr_type = id->type;
+                       break;
+               }
+       }
+
+       if (!asr_type)
+               return -ENODEV;
+
+       rc = asr_get_base_address();
+       if (rc)
+               return rc;
+
+       rc = misc_register(&asr_miscdev);
+       if (rc < 0) {
+               release_region(asr_base, asr_length);
+               printk(KERN_ERR PFX "failed to register misc device\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+       if (!nowayout)
+               asr_disable();
+
+       misc_deregister(&asr_miscdev);
+
+       release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
new file mode 100644 (file)
index 0000000..788245b
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ *     IndyDog 0.3     A Hardware Watchdog Device for SGI IP22
+ *
+ *     (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     based on softdog.c by Alan Cox <alan@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/sgi/mc.h>
+
+#define PFX "indydog: "
+static int indydog_alive;
+
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+
+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 indydog_start(void)
+{
+       u32 mc_ctrl0 = sgimc->cpuctrl0;
+
+       mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
+       sgimc->cpuctrl0 = mc_ctrl0;
+}
+
+static void indydog_stop(void)
+{
+       u32 mc_ctrl0 = sgimc->cpuctrl0;
+
+       mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
+       sgimc->cpuctrl0 = mc_ctrl0;
+
+       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+}
+
+static void indydog_ping(void)
+{
+       sgimc->watchdogt = 0;
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int indydog_open(struct inode *inode, struct file *file)
+{
+       if (indydog_alive)
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate timer */
+       indydog_start();
+       indydog_ping();
+
+       indydog_alive = 1;
+       printk(KERN_INFO "Started watchdog timer.\n");
+
+       return nonseekable_open(inode, file);
+}
+
+static int indydog_release(struct inode *inode, struct file *file)
+{
+       /* Shut off the timer.
+        * Lock it in if it's a module and we defined ...NOWAYOUT */
+       if (!nowayout)
+               indydog_stop();         /* Turn the WDT off */
+
+       indydog_alive = 0;
+
+       return 0;
+}
+
+static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       /* Refresh the timer. */
+       if (len) {
+               indydog_ping();
+       }
+       return len;
+}
+
+static int indydog_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int options, retval = -EINVAL;
+       static struct watchdog_info ident = {
+               .options                = WDIOF_KEEPALIVEPING |
+                                         WDIOF_MAGICCLOSE,
+               .firmware_version       = 0,
+               .identity               = "Hardware Watchdog for SGI IP22",
+       };
+
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user((struct watchdog_info *)arg,
+                                        &ident, sizeof(ident)))
+                               return -EFAULT;
+                       return 0;
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0,(int *)arg);
+               case WDIOC_KEEPALIVE:
+                       indydog_ping();
+                       return 0;
+               case WDIOC_GETTIMEOUT:
+                       return put_user(WATCHDOG_TIMEOUT,(int *)arg);
+               case WDIOC_SETOPTIONS:
+               {
+                       if (get_user(options, (int *)arg))
+                               return -EFAULT;
+
+                       if (options & WDIOS_DISABLECARD) {
+                               indydog_stop();
+                               retval = 0;
+                       }
+
+                       if (options & WDIOS_ENABLECARD) {
+                               indydog_start();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+       }
+}
+
+static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+               indydog_stop();         /* Turn the WDT off */
+
+       return NOTIFY_DONE;
+}
+
+static const struct file_operations indydog_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = indydog_write,
+       .ioctl          = indydog_ioctl,
+       .open           = indydog_open,
+       .release        = indydog_release,
+};
+
+static struct miscdevice indydog_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &indydog_fops,
+};
+
+static struct notifier_block indydog_notifier = {
+       .notifier_call = indydog_notify_sys,
+};
+
+static char banner[] __initdata =
+       KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
+
+static int __init watchdog_init(void)
+{
+       int ret;
+
+       ret = register_reboot_notifier(&indydog_notifier);
+       if (ret) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = misc_register(&indydog_miscdev);
+       if (ret) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               unregister_reboot_notifier(&indydog_notifier);
+               return ret;
+       }
+
+       printk(banner);
+
+       return 0;
+}
+
+static void __exit watchdog_exit(void)
+{
+       misc_deregister(&indydog_miscdev);
+       unregister_reboot_notifier(&indydog_notifier);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
+MODULE_DESCRIPTION("Hardware Watchdog Device for SGI IP22");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c
new file mode 100644 (file)
index 0000000..bbbd91a
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * drivers/char/watchdog/iop_wdt.c
+ *
+ * WDT driver for Intel I/O Processors
+ * Copyright (C) 2005, Intel Corporation.
+ *
+ * Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ *     Curt E Bruns <curt.e.bruns@intel.com>
+ *     Peter Milne <peter.milne@d-tacq.com>
+ *     Dan Williams <dan.j.williams@intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+#include <asm/hardware.h>
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define WDT_IN_USE             0
+#define WDT_OK_TO_CLOSE                1
+#define WDT_ENABLED            2
+
+static unsigned long iop_watchdog_timeout(void)
+{
+       return (0xffffffffUL / get_iop_tick_rate());
+}
+
+/**
+ * wdt_supports_disable - determine if we are accessing a iop13xx watchdog
+ * or iop3xx by whether it has a disable command
+ */
+static int wdt_supports_disable(void)
+{
+       int can_disable;
+
+       if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM)
+               can_disable = 1;
+       else
+               can_disable = 0;
+
+       return can_disable;
+}
+
+static void wdt_enable(void)
+{
+       /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
+        * Takes approx. 10.7s to timeout
+        */
+       write_wdtcr(IOP_WDTCR_EN_ARM);
+       write_wdtcr(IOP_WDTCR_EN);
+}
+
+/* returns 0 if the timer was successfully disabled */
+static int wdt_disable(void)
+{
+       /* Stop Counting */
+       if (wdt_supports_disable()) {
+               write_wdtcr(IOP_WDTCR_DIS_ARM);
+               write_wdtcr(IOP_WDTCR_DIS);
+               clear_bit(WDT_ENABLED, &wdt_status);
+               printk(KERN_INFO "WATCHDOG: Disabled\n");
+               return 0;
+       } else
+               return 1;
+}
+
+static int iop_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+               return -EBUSY;
+
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       wdt_enable();
+
+       set_bit(WDT_ENABLED, &wdt_status);
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t
+iop_wdt_write(struct file *file, const char *data, size_t len,
+                 loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                       }
+               }
+               wdt_enable();
+       }
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+       .identity = "iop watchdog",
+};
+
+static int
+iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                 unsigned long arg)
+{
+       int options;
+       int ret = -ENOTTY;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user
+                   ((struct watchdog_info *)arg, &ident, sizeof ident))
+                       ret = -EFAULT;
+               else
+                       ret = 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int *)arg);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(boot_status, (int *)arg);
+               break;
+
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(iop_watchdog_timeout(), (int *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_enable();
+               ret = 0;
+               break;
+
+       case WDIOC_SETOPTIONS:
+               if (get_user(options, (int *)arg))
+                       return -EFAULT;
+
+               if (options & WDIOS_DISABLECARD) {
+                       if (!nowayout) {
+                               if (wdt_disable() == 0) {
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                                       ret = 0;
+                               } else
+                                       ret = -ENXIO;
+                       } else
+                               ret = 0;
+               }
+
+               if (options & WDIOS_ENABLECARD) {
+                       wdt_enable();
+                       ret = 0;
+               }
+               break;
+       }
+
+       return ret;
+}
+
+static int iop_wdt_release(struct inode *inode, struct file *file)
+{
+       int state = 1;
+       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+               if (test_bit(WDT_ENABLED, &wdt_status))
+                       state = wdt_disable();
+
+       /* if the timer is not disbaled reload and notify that we are still
+        * going down
+        */
+       if (state != 0) {
+               wdt_enable();
+               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+                      "reset in %lu seconds\n", iop_watchdog_timeout());
+       }
+
+       clear_bit(WDT_IN_USE, &wdt_status);
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       return 0;
+}
+
+static const struct file_operations iop_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = iop_wdt_write,
+       .ioctl = iop_wdt_ioctl,
+       .open = iop_wdt_open,
+       .release = iop_wdt_release,
+};
+
+static struct miscdevice iop_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &iop_wdt_fops,
+};
+
+static int __init iop_wdt_init(void)
+{
+       int ret;
+
+       ret = misc_register(&iop_wdt_miscdev);
+       if (ret == 0)
+               printk("iop watchdog timer: timeout %lu sec\n",
+                      iop_watchdog_timeout());
+
+       /* check if the reset was caused by the watchdog timer */
+       boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
+
+       /* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset
+        * NOTE: An IB Reset will Reset both cores in the IOP342
+        */
+       write_wdtsr(IOP13XX_WDTCR_IB_RESET);
+
+       return ret;
+}
+
+static void __exit iop_wdt_exit(void)
+{
+       misc_deregister(&iop_wdt_miscdev);
+}
+
+module_init(iop_wdt_init);
+module_exit(iop_wdt_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
+MODULE_DESCRIPTION("iop watchdog timer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
new file mode 100644 (file)
index 0000000..dc7548d
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * drivers/char/watchdog/ixp2000_wdt.c
+ *
+ * Watchdog driver for Intel IXP2000 network processors
+ *
+ * Adapted from the IXP4xx watchdog driver by Lennert Buytenhek.
+ * The original version carries these notices:
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista, Software, Inc.
+ * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
+ *
+ * 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 <asm/hardware.h>
+#include <asm/uaccess.h>
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static unsigned int heartbeat = 60;    /* (secs) Default is 1 minute */
+static unsigned long wdt_status;
+
+#define        WDT_IN_USE              0
+#define        WDT_OK_TO_CLOSE         1
+
+static unsigned long wdt_tick_rate;
+
+static void
+wdt_enable(void)
+{
+       ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
+       ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
+       ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
+       ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
+}
+
+static void
+wdt_disable(void)
+{
+       ixp2000_reg_write(IXP2000_T4_CTL, 0);
+}
+
+static void
+wdt_keepalive(void)
+{
+       ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
+}
+
+static int
+ixp2000_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+               return -EBUSY;
+
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       wdt_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t
+ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                       }
+               }
+               wdt_keepalive();
+       }
+
+       return len;
+}
+
+
+static struct watchdog_info ident = {
+       .options        = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
+                               WDIOF_KEEPALIVEPING,
+       .identity       = "IXP2000 Watchdog",
+};
+
+static int
+ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                       unsigned long arg)
+{
+       int ret = -ENOTTY;
+       int time;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user((struct watchdog_info *)arg, &ident,
+                                  sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int *)arg);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(0, (int *)arg);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, (int *)arg);
+               if (ret)
+                       break;
+
+               if (time <= 0 || time > 60) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               heartbeat = time;
+               wdt_keepalive();
+               /* Fall through */
+
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(heartbeat, (int *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_enable();
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+static int
+ixp2000_wdt_release(struct inode *inode, struct file *file)
+{
+       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
+               wdt_disable();
+       } else {
+               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+                                       "timer will not stop\n");
+       }
+
+       clear_bit(WDT_IN_USE, &wdt_status);
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       return 0;
+}
+
+
+static const struct file_operations ixp2000_wdt_fops =
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = ixp2000_wdt_write,
+       .ioctl          = ixp2000_wdt_ioctl,
+       .open           = ixp2000_wdt_open,
+       .release        = ixp2000_wdt_release,
+};
+
+static struct miscdevice ixp2000_wdt_miscdev =
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ixp2000_wdt_fops,
+};
+
+static int __init ixp2000_wdt_init(void)
+{
+       if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+               printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+               return -EIO;
+       }
+
+       wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
+
+       return misc_register(&ixp2000_wdt_miscdev);
+}
+
+static void __exit ixp2000_wdt_exit(void)
+{
+       misc_deregister(&ixp2000_wdt_miscdev);
+}
+
+module_init(ixp2000_wdt_init);
+module_exit(ixp2000_wdt_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
new file mode 100644 (file)
index 0000000..5864bb8
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * drivers/char/watchdog/ixp4xx_wdt.c
+ *
+ * Watchdog driver for Intel IXP4xx network processors
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista, Software, Inc.
+ * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
+ *
+ * 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 <asm/hardware.h>
+#include <asm/uaccess.h>
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int heartbeat = 60;     /* (secs) Default is 1 minute */
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL)
+
+#define        WDT_IN_USE              0
+#define        WDT_OK_TO_CLOSE         1
+
+static void
+wdt_enable(void)
+{
+       *IXP4XX_OSWK = IXP4XX_WDT_KEY;
+       *IXP4XX_OSWE = 0;
+       *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat;
+       *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE;
+       *IXP4XX_OSWK = 0;
+}
+
+static void
+wdt_disable(void)
+{
+       *IXP4XX_OSWK = IXP4XX_WDT_KEY;
+       *IXP4XX_OSWE = 0;
+       *IXP4XX_OSWK = 0;
+}
+
+static int
+ixp4xx_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+               return -EBUSY;
+
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       wdt_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t
+ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                       }
+               }
+               wdt_enable();
+       }
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options        = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
+                         WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity       = "IXP4xx Watchdog",
+};
+
+
+static int
+ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                       unsigned long arg)
+{
+       int ret = -ENOTTY;
+       int time;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user((struct watchdog_info *)arg, &ident,
+                                  sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int *)arg);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(boot_status, (int *)arg);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, (int *)arg);
+               if (ret)
+                       break;
+
+               if (time <= 0 || time > 60) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               heartbeat = time;
+               wdt_enable();
+               /* Fall through */
+
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(heartbeat, (int *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_enable();
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+static int
+ixp4xx_wdt_release(struct inode *inode, struct file *file)
+{
+       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
+               wdt_disable();
+       } else {
+               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+                                       "timer will not stop\n");
+       }
+
+       clear_bit(WDT_IN_USE, &wdt_status);
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       return 0;
+}
+
+
+static const struct file_operations ixp4xx_wdt_fops =
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = ixp4xx_wdt_write,
+       .ioctl          = ixp4xx_wdt_ioctl,
+       .open           = ixp4xx_wdt_open,
+       .release        = ixp4xx_wdt_release,
+};
+
+static struct miscdevice ixp4xx_wdt_miscdev =
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ixp4xx_wdt_fops,
+};
+
+static int __init ixp4xx_wdt_init(void)
+{
+       int ret;
+       unsigned long processor_id;
+
+       asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
+       if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
+               printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - "
+                       "watchdog disabled\n");
+
+               return -ENODEV;
+       }
+
+       ret = misc_register(&ixp4xx_wdt_miscdev);
+       if (ret == 0)
+               printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat);
+
+       boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ?
+                       WDIOF_CARDRESET : 0;
+
+       return ret;
+}
+
+static void __exit ixp4xx_wdt_exit(void)
+{
+       misc_deregister(&ixp4xx_wdt_miscdev);
+}
+
+
+module_init(ixp4xx_wdt_init);
+module_exit(ixp4xx_wdt_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
new file mode 100644 (file)
index 0000000..7150fb9
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Watchdog driver for Kendin/Micrel KS8695.
+ *
+ * (C) 2007 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/arch/regs-timer.h>
+
+
+#define WDT_DEFAULT_TIME       5       /* seconds */
+#define WDT_MAX_TIME           171     /* seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+#endif
+
+
+static unsigned long ks8695wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline ks8695_wdt_stop(void)
+{
+       unsigned long tmcon;
+
+       /* disable timer0 */
+       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline ks8695_wdt_start(void)
+{
+       unsigned long tmcon;
+       unsigned long tval = wdt_time * CLOCK_TICK_RATE;
+
+       /* disable timer0 */
+       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+
+       /* program timer0 */
+       __raw_writel(tval | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
+
+       /* re-enable timer0 */
+       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+       __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Reload the watchdog timer.  (ie, pat the watchdog)
+ */
+static void inline ks8695_wdt_reload(void)
+{
+       unsigned long tmcon;
+
+       /* disable, then re-enable timer0 */
+       tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+       __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+       __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int ks8695_wdt_settimeout(int new_time)
+{
+       /*
+        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+        *
+        * Since WDV is a 16-bit counter, the maximum period is
+        * 65536 / 0.256 = 256 seconds.
+        */
+       if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+               return -EINVAL;
+
+       /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */
+       wdt_time = new_time;
+       return 0;
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int ks8695_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &ks8695wdt_busy))
+               return -EBUSY;
+
+       ks8695_wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ *  disabled.
+ */
+static int ks8695_wdt_close(struct inode *inode, struct file *file)
+{
+       if (!nowayout)
+               ks8695_wdt_stop();      /* Disable the watchdog when file is closed */
+
+       clear_bit(0, &ks8695wdt_busy);
+       return 0;
+}
+
+static struct watchdog_info ks8695_wdt_info = {
+       .identity       = "ks8695 watchdog",
+       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int ks8695_wdt_ioctl(struct inode *inode, struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_value;
+
+       switch(cmd) {
+               case WDIOC_KEEPALIVE:
+                       ks8695_wdt_reload();    /* pat the watchdog */
+                       return 0;
+
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_value, p))
+                               return -EFAULT;
+
+                       if (ks8695_wdt_settimeout(new_value))
+                               return -EINVAL;
+
+                       /* Enable new time value */
+                       ks8695_wdt_start();
+
+                       /* Return current value */
+                       return put_user(wdt_time, p);
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(wdt_time, p);
+
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+
+               case WDIOC_SETOPTIONS:
+                       if (get_user(new_value, p))
+                               return -EFAULT;
+
+                       if (new_value & WDIOS_DISABLECARD)
+                               ks8695_wdt_stop();
+                       if (new_value & WDIOS_ENABLECARD)
+                               ks8695_wdt_start();
+                       return 0;
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       ks8695_wdt_reload();            /* pat the watchdog */
+       return len;
+}
+
+/* ......................................................................... */
+
+static const struct file_operations ks8695wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .ioctl          = ks8695_wdt_ioctl,
+       .open           = ks8695_wdt_open,
+       .release        = ks8695_wdt_close,
+       .write          = ks8695_wdt_write,
+};
+
+static struct miscdevice ks8695wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ks8695wdt_fops,
+};
+
+static int __init ks8695wdt_probe(struct platform_device *pdev)
+{
+       int res;
+
+       if (ks8695wdt_miscdev.parent)
+               return -EBUSY;
+       ks8695wdt_miscdev.parent = &pdev->dev;
+
+       res = misc_register(&ks8695wdt_miscdev);
+       if (res)
+               return res;
+
+       printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : "");
+       return 0;
+}
+
+static int __exit ks8695wdt_remove(struct platform_device *pdev)
+{
+       int res;
+
+       res = misc_deregister(&ks8695wdt_miscdev);
+       if (!res)
+               ks8695wdt_miscdev.parent = NULL;
+
+       return res;
+}
+
+static void ks8695wdt_shutdown(struct platform_device *pdev)
+{
+       ks8695_wdt_stop();
+}
+
+#ifdef CONFIG_PM
+
+static int ks8695wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       ks8695_wdt_stop();
+       return 0;
+}
+
+static int ks8695wdt_resume(struct platform_device *pdev)
+{
+       if (ks8695wdt_busy)
+               ks8695_wdt_start();
+       return 0;
+}
+
+#else
+#define ks8695wdt_suspend NULL
+#define ks8695wdt_resume       NULL
+#endif
+
+static struct platform_driver ks8695wdt_driver = {
+       .probe          = ks8695wdt_probe,
+       .remove         = __exit_p(ks8695wdt_remove),
+       .shutdown       = ks8695wdt_shutdown,
+       .suspend        = ks8695wdt_suspend,
+       .resume         = ks8695wdt_resume,
+       .driver         = {
+               .name   = "ks8695_wdt",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init ks8695_wdt_init(void)
+{
+       /* Check that the heartbeat value is within range; if not reset to the default */
+       if (ks8695_wdt_settimeout(wdt_time)) {
+               ks8695_wdt_settimeout(WDT_DEFAULT_TIME);
+               pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", wdt_time, WDT_MAX_TIME);
+       }
+
+       return platform_driver_register(&ks8695wdt_driver);
+}
+
+static void __exit ks8695_wdt_exit(void)
+{
+       platform_driver_unregister(&ks8695wdt_driver);
+}
+
+module_init(ks8695_wdt_init);
+module_exit(ks8695_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for KS8695");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
new file mode 100644 (file)
index 0000000..6d35bb1
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ *  MachZ ZF-Logic Watchdog Timer driver for Linux
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ *  The author does NOT admit liability nor provide warranty for
+ *  any of this software. This material is provided "AS-IS" in
+ *  the hope that it may be useful for others.
+ *
+ *  Author: Fernando Fuganti <fuganti@conectiva.com.br>
+ *
+ *  Based on sbc60xxwdt.c by Jakob Oestergaard
+ *
+ *
+ *  We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the
+ *  following periods:
+ *      wd#1 - 2 seconds;
+ *      wd#2 - 7.2 ms;
+ *  After the expiration of wd#1, it can generate a NMI, SCI, SMI, or
+ *  a system RESET and it starts wd#2 that unconditionaly will RESET
+ *  the system when the counter reaches zero.
+ *
+ *  14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* ports */
+#define ZF_IOBASE      0x218
+#define INDEX          0x218
+#define DATA_B         0x219
+#define DATA_W         0x21A
+#define DATA_D         0x21A
+
+/* indexes */                  /* size */
+#define ZFL_VERSION    0x02    /* 16   */
+#define CONTROL        0x10    /* 16   */
+#define STATUS         0x12    /* 8    */
+#define COUNTER_1      0x0C    /* 16   */
+#define COUNTER_2      0x0E    /* 8    */
+#define PULSE_LEN      0x0F    /* 8    */
+
+/* controls */
+#define ENABLE_WD1     0x0001
+#define ENABLE_WD2     0x0002
+#define RESET_WD1      0x0010
+#define RESET_WD2      0x0020
+#define GEN_SCI                0x0100
+#define GEN_NMI                0x0200
+#define GEN_SMI                0x0400
+#define GEN_RESET      0x0800
+
+
+/* utilities */
+
+#define WD1    0
+#define WD2    1
+
+#define zf_writew(port, data)  { outb(port, INDEX); outw(data, DATA_W); }
+#define zf_writeb(port, data)  { outb(port, INDEX); outb(data, DATA_B); }
+#define zf_get_ZFL_version()   zf_readw(ZFL_VERSION)
+
+
+static unsigned short zf_readw(unsigned char port)
+{
+       outb(port, INDEX);
+       return inw(DATA_W);
+}
+
+
+MODULE_AUTHOR("Fernando Fuganti <fuganti@conectiva.com.br>");
+MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+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) ")");
+
+#define PFX "machzwd"
+
+static struct watchdog_info zf_info = {
+       .options                = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+       .firmware_version       = 1,
+       .identity               = "ZF-Logic watchdog",
+};
+
+
+/*
+ * action refers to action taken when watchdog resets
+ * 0 = GEN_RESET
+ * 1 = GEN_SMI
+ * 2 = GEN_NMI
+ * 3 = GEN_SCI
+ * defaults to GEN_RESET (0)
+ */
+static int action = 0;
+module_param(action, int, 0);
+MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
+
+static void zf_ping(unsigned long data);
+
+static int zf_action = GEN_RESET;
+static unsigned long zf_is_open;
+static char zf_expect_close;
+static spinlock_t zf_lock;
+static spinlock_t zf_port_lock;
+static DEFINE_TIMER(zf_timer, zf_ping, 0, 0);
+static unsigned long next_heartbeat = 0;
+
+
+/* timeout for user land heart beat (10 seconds) */
+#define ZF_USER_TIMEO (HZ*10)
+
+/* timeout for hardware watchdog (~500ms) */
+#define ZF_HW_TIMEO (HZ/2)
+
+/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */
+#define ZF_CTIMEOUT 0xffff
+
+#ifndef ZF_DEBUG
+#      define dprintk(format, args...)
+#else
+#      define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args)
+#endif
+
+
+static inline void zf_set_status(unsigned char new)
+{
+       zf_writeb(STATUS, new);
+}
+
+
+/* CONTROL register functions */
+
+static inline unsigned short zf_get_control(void)
+{
+       return zf_readw(CONTROL);
+}
+
+static inline void zf_set_control(unsigned short new)
+{
+       zf_writew(CONTROL, new);
+}
+
+
+/* WD#? counter functions */
+/*
+ *     Just set counter value
+ */
+
+static inline void zf_set_timer(unsigned short new, unsigned char n)
+{
+       switch(n){
+               case WD1:
+                       zf_writew(COUNTER_1, new);
+               case WD2:
+                       zf_writeb(COUNTER_2, new > 0xff ? 0xff : new);
+               default:
+                       return;
+       }
+}
+
+/*
+ * stop hardware timer
+ */
+static void zf_timer_off(void)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+
+       /* stop internal ping */
+       del_timer_sync(&zf_timer);
+
+       spin_lock_irqsave(&zf_port_lock, flags);
+       /* stop watchdog timer */
+       ctrl_reg = zf_get_control();
+       ctrl_reg |= (ENABLE_WD1|ENABLE_WD2);    /* disable wd1 and wd2 */
+       ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2);
+       zf_set_control(ctrl_reg);
+       spin_unlock_irqrestore(&zf_port_lock, flags);
+
+       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
+}
+
+
+/*
+ * start hardware timer
+ */
+static void zf_timer_on(void)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&zf_port_lock, flags);
+
+       zf_writeb(PULSE_LEN, 0xff);
+
+       zf_set_timer(ZF_CTIMEOUT, WD1);
+
+       /* user land ping */
+       next_heartbeat = jiffies + ZF_USER_TIMEO;
+
+       /* start the timer for internal ping */
+       mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
+
+       /* start watchdog timer */
+       ctrl_reg = zf_get_control();
+       ctrl_reg |= (ENABLE_WD1|zf_action);
+       zf_set_control(ctrl_reg);
+       spin_unlock_irqrestore(&zf_port_lock, flags);
+
+       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
+}
+
+
+static void zf_ping(unsigned long data)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+
+       zf_writeb(COUNTER_2, 0xff);
+
+       if(time_before(jiffies, next_heartbeat)){
+
+               dprintk("time_before: %ld\n", next_heartbeat - jiffies);
+
+               /*
+                * reset event is activated by transition from 0 to 1 on
+                * RESET_WD1 bit and we assume that it is already zero...
+                */
+
+               spin_lock_irqsave(&zf_port_lock, flags);
+               ctrl_reg = zf_get_control();
+               ctrl_reg |= RESET_WD1;
+               zf_set_control(ctrl_reg);
+
+               /* ...and nothing changes until here */
+               ctrl_reg &= ~(RESET_WD1);
+               zf_set_control(ctrl_reg);
+               spin_unlock_irqrestore(&zf_port_lock, flags);
+
+               mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
+       }else{
+               printk(KERN_CRIT PFX ": I will reset your machine\n");
+       }
+}
+
+static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
+                                                               loff_t *ppos)
+{
+       /* See if we got the magic character */
+       if(count){
+
+               /*
+                * no need to check for close confirmation
+                * no way to disable watchdog ;)
+                */
+               if (!nowayout) {
+                       size_t ofs;
+
+                       /*
+                        * note: just in case someone wrote the magic character
+                        * five months ago...
+                        */
+                       zf_expect_close = 0;
+
+                       /* now scan */
+                       for (ofs = 0; ofs != count; ofs++){
+                               char c;
+                               if (get_user(c, buf + ofs))
+                                       return -EFAULT;
+                               if (c == 'V'){
+                                       zf_expect_close = 42;
+                                       dprintk("zf_expect_close = 42\n");
+                               }
+                       }
+               }
+
+               /*
+                * Well, anyhow someone wrote to us,
+                * we should return that favour
+                */
+               next_heartbeat = jiffies + ZF_USER_TIMEO;
+               dprintk("user ping at %ld\n", jiffies);
+
+       }
+
+       return count;
+}
+
+static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &zf_info, sizeof(zf_info)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+               zf_ping(0);
+               break;
+
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static int zf_open(struct inode *inode, struct file *file)
+{
+       spin_lock(&zf_lock);
+       if(test_and_set_bit(0, &zf_is_open)) {
+               spin_unlock(&zf_lock);
+               return -EBUSY;
+       }
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       spin_unlock(&zf_lock);
+
+       zf_timer_on();
+
+       return nonseekable_open(inode, file);
+}
+
+static int zf_close(struct inode *inode, struct file *file)
+{
+       if(zf_expect_close == 42){
+               zf_timer_off();
+       } else {
+               del_timer(&zf_timer);
+               printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
+       }
+
+       spin_lock(&zf_lock);
+       clear_bit(0, &zf_is_open);
+       spin_unlock(&zf_lock);
+
+       zf_expect_close = 0;
+
+       return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int zf_notify_sys(struct notifier_block *this, unsigned long code,
+                                                               void *unused)
+{
+       if(code == SYS_DOWN || code == SYS_HALT){
+               zf_timer_off();
+       }
+
+       return NOTIFY_DONE;
+}
+
+
+
+
+static const struct file_operations zf_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = zf_write,
+       .ioctl          = zf_ioctl,
+       .open           = zf_open,
+       .release        = zf_close,
+};
+
+static struct miscdevice zf_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &zf_fops,
+};
+
+/*
+ * The device needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+static struct notifier_block zf_notifier = {
+       .notifier_call = zf_notify_sys,
+};
+
+static void __init zf_show_action(int act)
+{
+       char *str[] = { "RESET", "SMI", "NMI", "SCI" };
+
+       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
+}
+
+static int __init zf_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n");
+
+       ret = zf_get_ZFL_version();
+       if ((!ret) || (ret == 0xffff)) {
+               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
+               return -ENODEV;
+       }
+
+       if((action <= 3) && (action >= 0)){
+               zf_action = zf_action>>action;
+       } else
+               action = 0;
+
+       zf_show_action(action);
+
+       spin_lock_init(&zf_lock);
+       spin_lock_init(&zf_port_lock);
+
+       if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
+               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
+                                                       ZF_IOBASE);
+               ret = -EBUSY;
+               goto no_region;
+       }
+
+       ret = register_reboot_notifier(&zf_notifier);
+       if(ret){
+               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
+                                                                       ret);
+               goto no_reboot;
+       }
+
+       ret = misc_register(&zf_miscdev);
+       if (ret){
+               printk(KERN_ERR "can't misc_register on minor=%d\n",
+                                                       WATCHDOG_MINOR);
+               goto no_misc;
+       }
+
+       zf_set_status(0);
+       zf_set_control(0);
+
+       return 0;
+
+no_misc:
+       unregister_reboot_notifier(&zf_notifier);
+no_reboot:
+       release_region(ZF_IOBASE, 3);
+no_region:
+       return ret;
+}
+
+
+static void __exit zf_exit(void)
+{
+       zf_timer_off();
+
+       misc_deregister(&zf_miscdev);
+       unregister_reboot_notifier(&zf_notifier);
+       release_region(ZF_IOBASE, 3);
+}
+
+module_init(zf_init);
+module_exit(zf_exit);
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
new file mode 100644 (file)
index 0000000..1adf1d5
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * MixCom Watchdog: A Simple Hardware Watchdog Device
+ * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
+ *
+ * Author: Gergely Madarasz <gorgo@itc.hu>
+ *
+ * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Version 0.1 (99/04/15):
+ *             - first version
+ *
+ * Version 0.2 (99/06/16):
+ *             - added kernel timer watchdog ping after close
+ *               since the hardware does not support watchdog shutdown
+ *
+ * Version 0.3 (99/06/21):
+ *             - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls
+ *
+ * Version 0.3.1 (99/06/22):
+ *             - allow module removal while internal timer is active,
+ *               print warning about probable reset
+ *
+ * Version 0.4 (99/11/15):
+ *             - support for one more type board
+ *
+ * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
+ *             - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
+ *             - make mixcomwd_opened unsigned,
+ *               removed lock_kernel/unlock_kernel from mixcomwd_release,
+ *               modified ioctl a bit to conform to API
+ *
+ */
+
+#define VERSION "0.6"
+#define WATCHDOG_NAME "mixcomwd"
+#define PFX WATCHDOG_NAME ": "
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/*
+ * We have two types of cards that can be probed:
+ * 1) The Mixcom cards: these cards can be found at addresses
+ *    0x180, 0x280, 0x380 with an additional offset of 0xc10.
+ *    (Or 0xd90, 0xe90, 0xf90).
+ * 2) The FlashCOM cards: these cards can be set up at
+ *    0x300 -> 0x378, in 0x8 jumps with an offset of 0x04.
+ *    (Or 0x304 -> 0x37c in 0x8 jumps).
+ *    Each card has it's own ID.
+ */
+#define MIXCOM_ID 0x11
+#define FLASHCOM_ID 0x18
+static struct {
+       int ioport;
+       int id;
+} mixcomwd_io_info[] __devinitdata = {
+       /* The Mixcom cards */
+       {0x0d90, MIXCOM_ID},
+       {0x0e90, MIXCOM_ID},
+       {0x0f90, MIXCOM_ID},
+       /* The FlashCOM cards */
+       {0x0304, FLASHCOM_ID},
+       {0x030c, FLASHCOM_ID},
+       {0x0314, FLASHCOM_ID},
+       {0x031c, FLASHCOM_ID},
+       {0x0324, FLASHCOM_ID},
+       {0x032c, FLASHCOM_ID},
+       {0x0334, FLASHCOM_ID},
+       {0x033c, FLASHCOM_ID},
+       {0x0344, FLASHCOM_ID},
+       {0x034c, FLASHCOM_ID},
+       {0x0354, FLASHCOM_ID},
+       {0x035c, FLASHCOM_ID},
+       {0x0364, FLASHCOM_ID},
+       {0x036c, FLASHCOM_ID},
+       {0x0374, FLASHCOM_ID},
+       {0x037c, FLASHCOM_ID},
+       /* The end of the list */
+       {0x0000, 0},
+};
+
+static void mixcomwd_timerfun(unsigned long d);
+
+static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
+
+static int watchdog_port;
+static int mixcomwd_timer_alive;
+static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
+static char expect_close;
+
+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 mixcomwd_ping(void)
+{
+       outb_p(55,watchdog_port);
+       return;
+}
+
+static void mixcomwd_timerfun(unsigned long d)
+{
+       mixcomwd_ping();
+
+       mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+
+static int mixcomwd_open(struct inode *inode, struct file *file)
+{
+       if(test_and_set_bit(0,&mixcomwd_opened)) {
+               return -EBUSY;
+       }
+       mixcomwd_ping();
+
+       if (nowayout) {
+               /*
+                * fops_get() code via open() has already done
+                * a try_module_get() so it is safe to do the
+                * __module_get().
+                */
+               __module_get(THIS_MODULE);
+       } else {
+               if(mixcomwd_timer_alive) {
+                       del_timer(&mixcomwd_timer);
+                       mixcomwd_timer_alive=0;
+               }
+       }
+       return nonseekable_open(inode, file);
+}
+
+static int mixcomwd_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               if(mixcomwd_timer_alive) {
+                       printk(KERN_ERR PFX "release called while internal timer alive");
+                       return -EBUSY;
+               }
+               mixcomwd_timer_alive=1;
+               mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
+       } else {
+               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
+       }
+
+       clear_bit(0,&mixcomwd_opened);
+       expect_close=0;
+       return 0;
+}
+
+
+static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
+{
+       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;
+                       }
+               }
+               mixcomwd_ping();
+       }
+       return len;
+}
+
+static int mixcomwd_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int status;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "MixCOM watchdog",
+       };
+
+       switch(cmd)
+       {
+               case WDIOC_GETSTATUS:
+                       status=mixcomwd_opened;
+                       if (!nowayout) {
+                               status|=mixcomwd_timer_alive;
+                       }
+                       if (copy_to_user(p, &status, sizeof(int))) {
+                               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;
+                       }
+                       break;
+               case WDIOC_KEEPALIVE:
+                       mixcomwd_ping();
+                       break;
+               default:
+                       return -ENOTTY;
+       }
+       return 0;
+}
+
+static const struct file_operations mixcomwd_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = mixcomwd_write,
+       .ioctl          = mixcomwd_ioctl,
+       .open           = mixcomwd_open,
+       .release        = mixcomwd_release,
+};
+
+static struct miscdevice mixcomwd_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &mixcomwd_fops,
+};
+
+static int __init checkcard(int port, int card_id)
+{
+       int id;
+
+       if (!request_region(port, 1, "MixCOM watchdog")) {
+               return 0;
+       }
+
+       id=inb_p(port);
+       if (card_id==MIXCOM_ID)
+               id &= 0x3f;
+
+       if (id!=card_id) {
+               release_region(port, 1);
+               return 0;
+       }
+       return 1;
+}
+
+static int __init mixcomwd_init(void)
+{
+       int i;
+       int ret;
+       int found=0;
+
+       for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
+               if (checkcard(mixcomwd_io_info[i].ioport,
+                             mixcomwd_io_info[i].id)) {
+                       found = 1;
+                       watchdog_port = mixcomwd_io_info[i].ioport;
+               }
+       }
+
+       if (!found) {
+               printk(KERN_ERR PFX "No card detected, or port not available.\n");
+               return -ENODEV;
+       }
+
+       ret = misc_register(&mixcomwd_miscdev);
+       if (ret)
+       {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto error_misc_register_watchdog;
+       }
+
+       printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
+               VERSION, watchdog_port);
+
+       return 0;
+
+error_misc_register_watchdog:
+       release_region(watchdog_port, 1);
+       watchdog_port = 0x0000;
+       return ret;
+}
+
+static void __exit mixcomwd_exit(void)
+{
+       if (!nowayout) {
+               if(mixcomwd_timer_alive) {
+                       printk(KERN_WARNING PFX "I quit now, hardware will"
+                              " probably reboot!\n");
+                       del_timer_sync(&mixcomwd_timer);
+                       mixcomwd_timer_alive=0;
+               }
+       }
+       misc_deregister(&mixcomwd_miscdev);
+       release_region(watchdog_port,1);
+}
+
+module_init(mixcomwd_init);
+module_exit(mixcomwd_exit);
+
+MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
+MODULE_DESCRIPTION("MixCom Watchdog driver");
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
new file mode 100644 (file)
index 0000000..9cfb975
--- /dev/null
@@ -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 __user *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);
diff --git a/drivers/watchdog/mpc83xx_wdt.c b/drivers/watchdog/mpc83xx_wdt.c
new file mode 100644 (file)
index 0000000..a0bf95f
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
+ *
+ * Authors: Dave Updegraff <dave@cray.org>
+ *         Kumar Gala <galak@kernel.crashing.org>
+ *             Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
+ *                             ..and from sc520_wdt
+ *
+ * Note: it appears that you can only actually ENABLE or DISABLE the thing
+ * once after POR. Once enabled, you cannot disable, and vice versa.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+struct mpc83xx_wdt {
+       __be32 res0;
+       __be32 swcrr; /* System watchdog control register */
+#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
+#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
+#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
+#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
+       __be32 swcnr; /* System watchdog count register */
+       u8 res1[2];
+       __be16 swsrr; /* System watchdog service register */
+       u8 res2[0xF0];
+};
+
+static struct mpc83xx_wdt __iomem *wd_base;
+
+static u16 timeout = 0xffff;
+module_param(timeout, ushort, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
+
+static int reset = 1;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
+
+/*
+ * We always prescale, but if someone really doesn't want to they can set this
+ * to 0
+ */
+static int prescale = 1;
+static unsigned int timeout_sec;
+
+static unsigned long wdt_is_open;
+static spinlock_t wdt_spinlock;
+
+static void mpc83xx_wdt_keepalive(void)
+{
+       /* Ping the WDT */
+       spin_lock(&wdt_spinlock);
+       out_be16(&wd_base->swsrr, 0x556c);
+       out_be16(&wd_base->swsrr, 0xaa39);
+       spin_unlock(&wdt_spinlock);
+}
+
+static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       if (count)
+               mpc83xx_wdt_keepalive();
+       return count;
+}
+
+static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
+{
+       u32 tmp = SWCRR_SWEN;
+       if (test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+
+       /* Once we start the watchdog we can't stop it */
+       __module_get(THIS_MODULE);
+
+       /* Good, fire up the show */
+       if (prescale)
+               tmp |= SWCRR_SWPR;
+       if (reset)
+               tmp |= SWCRR_SWRI;
+
+       tmp |= timeout << 16;
+
+       out_be32(&wd_base->swcrr, tmp);
+
+       return nonseekable_open(inode, file);
+}
+
+static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
+{
+       printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
+       mpc83xx_wdt_keepalive();
+       clear_bit(0, &wdt_is_open);
+       return 0;
+}
+
+static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING,
+               .firmware_version = 1,
+               .identity = "MPC83xx",
+       };
+
+       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;
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout_sec, p);
+       default:
+               return -ENOTTY;
+       }
+}
+
+static const struct file_operations mpc83xx_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = mpc83xx_wdt_write,
+       .ioctl          = mpc83xx_wdt_ioctl,
+       .open           = mpc83xx_wdt_open,
+       .release        = mpc83xx_wdt_release,
+};
+
+static struct miscdevice mpc83xx_wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &mpc83xx_wdt_fops,
+};
+
+static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
+{
+       struct resource *r;
+       int ret;
+       unsigned int *freq = dev->dev.platform_data;
+
+       /* get a pointer to the register memory */
+       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+       if (!r) {
+               ret = -ENODEV;
+               goto err_out;
+       }
+
+       wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
+
+       if (wd_base == NULL) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
+
+       ret = misc_register(&mpc83xx_wdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR "cannot register miscdev on minor=%d "
+                               "(err=%d)\n",
+                               WATCHDOG_MINOR, ret);
+               goto err_unmap;
+       }
+
+       /* Calculate the timeout in seconds */
+       if (prescale)
+               timeout_sec = (timeout * 0x10000) / (*freq);
+       else
+               timeout_sec = timeout / (*freq);
+
+       printk(KERN_INFO "WDT driver for MPC83xx initialized. "
+               "mode:%s timeout=%d (%d seconds)\n",
+               reset ? "reset":"interrupt", timeout, timeout_sec);
+
+       spin_lock_init(&wdt_spinlock);
+
+       return 0;
+
+err_unmap:
+       iounmap(wd_base);
+err_out:
+       return ret;
+}
+
+static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&mpc83xx_wdt_miscdev);
+       iounmap(wd_base);
+
+       return 0;
+}
+
+static struct platform_driver mpc83xx_wdt_driver = {
+       .probe          = mpc83xx_wdt_probe,
+       .remove         = __devexit_p(mpc83xx_wdt_remove),
+       .driver         = {
+               .name   = "mpc83xx_wdt",
+       },
+};
+
+static int __init mpc83xx_wdt_init(void)
+{
+       return platform_driver_register(&mpc83xx_wdt_driver);
+}
+
+static void __exit mpc83xx_wdt_exit(void)
+{
+       platform_driver_unregister(&mpc83xx_wdt_driver);
+}
+
+module_init(mpc83xx_wdt_init);
+module_exit(mpc83xx_wdt_exit);
+
+MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
+MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
new file mode 100644 (file)
index 0000000..85b5734
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/8xx_immap.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <syslib/m8xx_wdt.h>
+
+static unsigned long wdt_opened;
+static int wdt_status;
+
+static void mpc8xx_wdt_handler_disable(void)
+{
+       volatile uint __iomem *piscr;
+       piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
+
+       if (!m8xx_has_internal_rtc)
+               m8xx_wdt_stop_timer();
+       else
+               out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
+
+       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
+}
+
+static void mpc8xx_wdt_handler_enable(void)
+{
+       volatile uint __iomem *piscr;
+       piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
+
+       if (!m8xx_has_internal_rtc)
+               m8xx_wdt_install_timer();
+       else
+               out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
+
+       printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
+}
+
+static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &wdt_opened))
+               return -EBUSY;
+
+       m8xx_wdt_reset();
+       mpc8xx_wdt_handler_disable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
+{
+       m8xx_wdt_reset();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+       mpc8xx_wdt_handler_enable();
+#endif
+
+       clear_bit(0, &wdt_opened);
+
+       return 0;
+}
+
+static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
+                               loff_t * ppos)
+{
+       if (len)
+               m8xx_wdt_reset();
+
+       return len;
+}
+
+static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
+                           unsigned int cmd, unsigned long arg)
+{
+       int timeout;
+       static struct watchdog_info info = {
+               .options = WDIOF_KEEPALIVEPING,
+               .firmware_version = 0,
+               .identity = "MPC8xx watchdog",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(wdt_status, (int *)arg))
+                       return -EFAULT;
+               wdt_status &= ~WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_GETTEMP:
+               return -EOPNOTSUPP;
+
+       case WDIOC_SETOPTIONS:
+               return -EOPNOTSUPP;
+
+       case WDIOC_KEEPALIVE:
+               m8xx_wdt_reset();
+               wdt_status |= WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               return -EOPNOTSUPP;
+
+       case WDIOC_GETTIMEOUT:
+               timeout = m8xx_wdt_get_timeout();
+               if (put_user(timeout, (int *)arg))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static const struct file_operations mpc8xx_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = mpc8xx_wdt_write,
+       .ioctl = mpc8xx_wdt_ioctl,
+       .open = mpc8xx_wdt_open,
+       .release = mpc8xx_wdt_release,
+};
+
+static struct miscdevice mpc8xx_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &mpc8xx_wdt_fops,
+};
+
+static int __init mpc8xx_wdt_init(void)
+{
+       return misc_register(&mpc8xx_wdt_miscdev);
+}
+
+static void __exit mpc8xx_wdt_exit(void)
+{
+       misc_deregister(&mpc8xx_wdt_miscdev);
+
+       m8xx_wdt_reset();
+       mpc8xx_wdt_handler_enable();
+}
+
+module_init(mpc8xx_wdt_init);
+module_exit(mpc8xx_wdt_exit);
+
+MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
+MODULE_DESCRIPTION("MPC8xx watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
new file mode 100644 (file)
index 0000000..0d2b277
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ *     Watchdog driver for the mpcore watchdog timer
+ *
+ *     (c) Copyright 2004 ARM Limited
+ *
+ *     Based on the SoftDog driver:
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware/arm_twd.h>
+#include <asm/uaccess.h>
+
+struct mpcore_wdt {
+       unsigned long   timer_alive;
+       struct device   *dev;
+       void __iomem    *base;
+       int             irq;
+       unsigned int    perturb;
+       char            expect_close;
+};
+
+static struct platform_device *mpcore_wdt_dev;
+
+extern unsigned int mpcore_timer_rate;
+
+#define TIMER_MARGIN   60
+static int mpcore_margin = TIMER_MARGIN;
+module_param(mpcore_margin, int, 0);
+MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+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) ")");
+
+#define ONLY_TESTING   0
+static int mpcore_noboot = ONLY_TESTING;
+module_param(mpcore_noboot, int, 0);
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+
+/*
+ *     This is the interrupt handler.  Note that we only use this
+ *     in testing mode, so don't actually do a reboot here.
+ */
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
+{
+       struct mpcore_wdt *wdt = arg;
+
+       /* Check it really was our interrupt */
+       if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
+               dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
+
+               /* Clear the interrupt on the watchdog */
+               writel(1, wdt->base + TWD_WDOG_INTSTAT);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+/*
+ *     mpcore_wdt_keepalive - reload the timer
+ *
+ *     Note that the spec says a DIFFERENT value must be written to the reload
+ *     register each time.  The "perturb" variable deals with this by adding 1
+ *     to the count every other time the function is called.
+ */
+static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
+{
+       unsigned int count;
+
+       /* Assume prescale is set to 256 */
+       count = (mpcore_timer_rate / 256) * mpcore_margin;
+
+       /* Reload the counter */
+       writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
+
+       wdt->perturb = wdt->perturb ? 0 : 1;
+}
+
+static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
+{
+       writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
+       writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
+       writel(0x0, wdt->base + TWD_WDOG_CONTROL);
+}
+
+static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+{
+       dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+       /* This loads the count register but does NOT start the count yet */
+       mpcore_wdt_keepalive(wdt);
+
+       if (mpcore_noboot) {
+               /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+               writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+       } else {
+               /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+               writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+       }
+}
+
+static int mpcore_wdt_set_heartbeat(int t)
+{
+       if (t < 0x0001 || t > 0xFFFF)
+               return -EINVAL;
+
+       mpcore_margin = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+static int mpcore_wdt_open(struct inode *inode, struct file *file)
+{
+       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev);
+
+       if (test_and_set_bit(0, &wdt->timer_alive))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       file->private_data = wdt;
+
+       /*
+        *      Activate timer
+        */
+       mpcore_wdt_start(wdt);
+
+       return nonseekable_open(inode, file);
+}
+
+static int mpcore_wdt_release(struct inode *inode, struct file *file)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if (wdt->expect_close == 42) {
+               mpcore_wdt_stop(wdt);
+       } else {
+               dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
+               mpcore_wdt_keepalive(wdt);
+       }
+       clear_bit(0, &wdt->timer_alive);
+       wdt->expect_close = 0;
+       return 0;
+}
+
+static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+
+       /*
+        *      Refresh the timer.
+        */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       wdt->expect_close = 0;
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       wdt->expect_close = 42;
+                       }
+               }
+               mpcore_wdt_keepalive(wdt);
+       }
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options                = WDIOF_SETTIMEOUT |
+                                 WDIOF_KEEPALIVEPING |
+                                 WDIOF_MAGICCLOSE,
+       .identity               = "MPcore Watchdog",
+};
+
+static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg)
+{
+       struct mpcore_wdt *wdt = file->private_data;
+       int ret;
+       union {
+               struct watchdog_info ident;
+               int i;
+       } uarg;
+
+       if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+               return -ENOTTY;
+
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
+               ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+               if (ret)
+                       return -EFAULT;
+       }
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               uarg.ident = ident;
+               ret = 0;
+               break;
+
+       case WDIOC_SETOPTIONS:
+               ret = -EINVAL;
+               if (uarg.i & WDIOS_DISABLECARD) {
+                       mpcore_wdt_stop(wdt);
+                       ret = 0;
+               }
+               if (uarg.i & WDIOS_ENABLECARD) {
+                       mpcore_wdt_start(wdt);
+                       ret = 0;
+               }
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               uarg.i = 0;
+               ret = 0;
+               break;
+
+       case WDIOC_KEEPALIVE:
+               mpcore_wdt_keepalive(wdt);
+               ret = 0;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = mpcore_wdt_set_heartbeat(uarg.i);
+               if (ret)
+                       break;
+
+               mpcore_wdt_keepalive(wdt);
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               uarg.i = mpcore_margin;
+               ret = 0;
+               break;
+
+       default:
+               return -ENOTTY;
+       }
+
+       if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+               ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
+               if (ret)
+                       ret = -EFAULT;
+       }
+       return ret;
+}
+
+/*
+ *     System shutdown handler.  Turn off the watchdog if we're
+ *     restarting or halting the system.
+ */
+static void mpcore_wdt_shutdown(struct platform_device *dev)
+{
+       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+
+       if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
+               mpcore_wdt_stop(wdt);
+}
+
+/*
+ *     Kernel Interfaces
+ */
+static const struct file_operations mpcore_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = mpcore_wdt_write,
+       .ioctl          = mpcore_wdt_ioctl,
+       .open           = mpcore_wdt_open,
+       .release        = mpcore_wdt_release,
+};
+
+static struct miscdevice mpcore_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &mpcore_wdt_fops,
+};
+
+static int __devinit mpcore_wdt_probe(struct platform_device *dev)
+{
+       struct mpcore_wdt *wdt;
+       struct resource *res;
+       int ret;
+
+       /* We only accept one device, and it must have an id of -1 */
+       if (dev->id != -1)
+               return -ENODEV;
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto err_out;
+       }
+
+       wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
+       if (!wdt) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
+
+       wdt->dev = &dev->dev;
+       wdt->irq = platform_get_irq(dev, 0);
+       if (wdt->irq < 0) {
+               ret = -ENXIO;
+               goto err_free;
+       }
+       wdt->base = ioremap(res->start, res->end - res->start + 1);
+       if (!wdt->base) {
+               ret = -ENOMEM;
+               goto err_free;
+       }
+
+       mpcore_wdt_miscdev.parent = &dev->dev;
+       ret = misc_register(&mpcore_wdt_miscdev);
+       if (ret) {
+               dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
+                          WATCHDOG_MINOR, ret);
+               goto err_misc;
+       }
+
+       ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt);
+       if (ret) {
+               dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
+               goto err_irq;
+       }
+
+       mpcore_wdt_stop(wdt);
+       platform_set_drvdata(&dev->dev, wdt);
+       mpcore_wdt_dev = dev;
+
+       return 0;
+
+ err_irq:
+       misc_deregister(&mpcore_wdt_miscdev);
+ err_misc:
+       iounmap(wdt->base);
+ err_free:
+       kfree(wdt);
+ err_out:
+       return ret;
+}
+
+static int __devexit mpcore_wdt_remove(struct platform_device *dev)
+{
+       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+
+       platform_set_drvdata(dev, NULL);
+
+       misc_deregister(&mpcore_wdt_miscdev);
+
+       mpcore_wdt_dev = NULL;
+
+       free_irq(wdt->irq, wdt);
+       iounmap(wdt->base);
+       kfree(wdt);
+       return 0;
+}
+
+static struct platform_driver mpcore_wdt_driver = {
+       .probe          = mpcore_wdt_probe,
+       .remove         = __devexit_p(mpcore_wdt_remove),
+       .shutdown       = mpcore_wdt_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "mpcore_wdt",
+       },
+};
+
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+
+static int __init mpcore_wdt_init(void)
+{
+       /*
+        * Check that the margin value is within it's range;
+        * if not reset to the default
+        */
+       if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
+               mpcore_wdt_set_heartbeat(TIMER_MARGIN);
+               printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
+                       TIMER_MARGIN);
+       }
+
+       printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+
+       return platform_driver_register(&mpcore_wdt_driver);
+}
+
+static void __exit mpcore_wdt_exit(void)
+{
+       platform_driver_unregister(&mpcore_wdt_driver);
+}
+
+module_init(mpcore_wdt_init);
+module_exit(mpcore_wdt_exit);
+
+MODULE_AUTHOR("ARM Limited");
+MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
new file mode 100644 (file)
index 0000000..dcfd401
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ *      Driver for the MTX-1 Watchdog.
+ *
+ *      (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
+ *                              http://www.4g-systems.biz
+ *
+ *     (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Neither Michael Stickel nor 4G Systems admit liability nor provide
+ *      warranty for any of this software. This material is provided
+ *      "AS-IS" and at no charge.
+ *
+ *      (c) Copyright 2005    4G Systems <info@4g-systems.biz>
+ *
+ *      Release 0.01.
+ *      Author: Michael Stickel  michael.stickel@4g-systems.biz
+ *
+ *      Release 0.02.
+ *     Author: Florian Fainelli florian@openwrt.org
+ *             use the Linux watchdog/timer APIs
+ *
+ *      The Watchdog is configured to reset the MTX-1
+ *      if it is not triggered for 100 seconds.
+ *      It should not be triggered more often than 1.6 seconds.
+ *
+ *      A timer triggers the watchdog every 5 seconds, until
+ *      it is opened for the first time. After the first open
+ *      it MUST be triggered every 2..95 seconds.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#define MTX1_WDT_INTERVAL      (5 * HZ)
+
+static int ticks = 100 * HZ;
+
+static struct {
+       struct completion stop;
+       volatile int running;
+       struct timer_list timer;
+       volatile int queue;
+       int default_ticks;
+       unsigned long inuse;
+} mtx1_wdt_device;
+
+static void mtx1_wdt_trigger(unsigned long unused)
+{
+       u32 tmp;
+
+       if (mtx1_wdt_device.running)
+               ticks--;
+       /*
+        * toggle GPIO2_15
+        */
+       tmp = au_readl(GPIO2_DIR);
+       tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15));
+       au_writel (tmp, GPIO2_DIR);
+
+       if (mtx1_wdt_device.queue && ticks)
+               mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
+       else {
+               complete(&mtx1_wdt_device.stop);
+       }
+}
+
+static void mtx1_wdt_reset(void)
+{
+       ticks = mtx1_wdt_device.default_ticks;
+}
+
+
+static void mtx1_wdt_start(void)
+{
+       if (!mtx1_wdt_device.queue) {
+               mtx1_wdt_device.queue = 1;
+               au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR);
+               mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
+       }
+       mtx1_wdt_device.running++;
+}
+
+static int mtx1_wdt_stop(void)
+{
+       if (mtx1_wdt_device.queue) {
+               mtx1_wdt_device.queue = 0;
+               au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR);
+       }
+
+       ticks = mtx1_wdt_device.default_ticks;
+
+       return 0;
+}
+
+/* Filesystem functions */
+
+static int mtx1_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &mtx1_wdt_device.inuse))
+               return -EBUSY;
+
+       return nonseekable_open(inode, file);
+}
+
+
+static int mtx1_wdt_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &mtx1_wdt_device.inuse);
+       return 0;
+}
+
+static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       unsigned int value;
+       static struct watchdog_info ident =
+       {
+               .options = WDIOF_CARDRESET,
+               .identity = "MTX-1 WDT",
+       };
+
+       switch(cmd) {
+               case WDIOC_KEEPALIVE:
+                       mtx1_wdt_reset();
+                       break;
+               case WDIOC_GETSTATUS:
+               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;
+                       break;
+               case WDIOC_SETOPTIONS:
+                       if ( copy_from_user(&value, argp, sizeof(int)) )
+                               return -EFAULT;
+                       switch(value) {
+                               case WDIOS_ENABLECARD:
+                                       mtx1_wdt_start();
+                                       break;
+                               case WDIOS_DISABLECARD:
+                                       return mtx1_wdt_stop();
+                               default:
+                                       return -EINVAL;
+                       }
+                       break;
+               default:
+                       return -ENOTTY;
+       }
+       return 0;
+}
+
+
+static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+       if (!count)
+               return -EIO;
+
+       mtx1_wdt_reset();
+       return count;
+}
+
+static struct file_operations mtx1_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .ioctl          = mtx1_wdt_ioctl,
+       .open           = mtx1_wdt_open,
+       .write          = mtx1_wdt_write,
+       .release        = mtx1_wdt_release
+};
+
+
+static struct miscdevice mtx1_wdt_misc = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &mtx1_wdt_fops
+};
+
+
+static int __init mtx1_wdt_init(void)
+{
+       int ret;
+
+       if ((ret = misc_register(&mtx1_wdt_misc)) < 0) {
+               printk(KERN_ERR " mtx-1_wdt : failed to register\n");
+               return ret;
+       }
+
+       init_completion(&mtx1_wdt_device.stop);
+       mtx1_wdt_device.queue = 0;
+
+       clear_bit(0, &mtx1_wdt_device.inuse);
+
+       setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
+
+       mtx1_wdt_device.default_ticks = ticks;
+
+       mtx1_wdt_start();
+
+       printk(KERN_INFO "MTX-1 Watchdog driver\n");
+
+       return 0;
+}
+
+static void __exit mtx1_wdt_exit(void)
+{
+       if (mtx1_wdt_device.queue) {
+               mtx1_wdt_device.queue = 0;
+               wait_for_completion(&mtx1_wdt_device.stop);
+       }
+       misc_deregister(&mtx1_wdt_misc);
+}
+
+module_init(mtx1_wdt_init);
+module_exit(mtx1_wdt_exit);
+
+MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
+MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
new file mode 100644 (file)
index 0000000..0365c31
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required.  This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ * 
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> 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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+
+#include <linux/mv643xx.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#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
+
+static unsigned long wdt_flags;
+static int wdt_status;
+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 int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift)
+{
+       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)
+{
+       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 (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
+                                  MV64x60_WDC_ENABLE_SHIFT))
+               printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+}
+
+static void mv64x60_wdt_set_timeout(unsigned int timeout)
+{
+       /* 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)
+{
+       if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       mv64x60_wdt_handler_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+       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);
+
+       return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
+                                size_t len, loff_t * ppos)
+{
+       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;
+}
+
+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_SETTIMEOUT        |
+                               WDIOF_MAGICCLOSE        |
+                               WDIOF_KEEPALIVEPING,
+               .firmware_version = 0,
+               .identity = "MV64x60 watchdog",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &info, sizeof(info)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(wdt_status, (int __user *)argp))
+                       return -EFAULT;
+               wdt_status &= ~WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_GETTEMP:
+               return -EOPNOTSUPP;
+
+       case WDIOC_SETOPTIONS:
+               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();
+               wdt_status |= WDIOF_KEEPALIVEPING;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(timeout, (int __user *)argp))
+                       return -EFAULT;
+               mv64x60_wdt_set_timeout(timeout);
+               /* Fall through */
+
+       case WDIOC_GETTIMEOUT:
+               if (put_user(mv64x60_wdt_timeout, (int __user *)argp))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static const struct file_operations mv64x60_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = mv64x60_wdt_write,
+       .ioctl = mv64x60_wdt_ioctl,
+       .open = mv64x60_wdt_open,
+       .release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
+{
+       struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
+       struct resource *r;
+       int timeout = 10;
+
+       bus_clk = 133;                  /* in MHz */
+       if (pdata) {
+               timeout = pdata->timeout;
+               bus_clk = pdata->bus_clk;
+       }
+
+       /* 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;
+
+       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);
+}
+
+static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
+{
+       misc_deregister(&mv64x60_wdt_miscdev);
+
+       mv64x60_wdt_handler_disable();
+
+       iounmap(mv64x60_wdt_regs);
+
+       return 0;
+}
+
+static struct platform_driver mv64x60_wdt_driver = {
+       .probe = mv64x60_wdt_probe,
+       .remove = __devexit_p(mv64x60_wdt_remove),
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = MV64x60_WDT_NAME,
+       },
+};
+
+static int __init mv64x60_wdt_init(void)
+{
+       printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+       return platform_driver_register(&mv64x60_wdt_driver);
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+       platform_driver_unregister(&mv64x60_wdt_driver);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
new file mode 100644 (file)
index 0000000..719b066
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * linux/drivers/char/watchdog/omap_wdt.c
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *      <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (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.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *     Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *     (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *     Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *     1. Modified to support OMAP1610 32-KHz watchdog timer
+ *     2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *     Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/moduleparam.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+
+#include <asm/arch/prcm.h>
+
+#include "omap_wdt.h"
+
+static unsigned timer_margin;
+module_param(timer_margin, uint, 0);
+MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
+
+static int omap_wdt_users;
+static struct clk *armwdt_ck = NULL;
+static struct clk *mpu_wdt_ick = NULL;
+static struct clk *mpu_wdt_fck = NULL;
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+static void omap_wdt_ping(void)
+{
+       /* wait for posted write to complete */
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+               cpu_relax();
+       wdt_trgr_pattern = ~wdt_trgr_pattern;
+       omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+       /* wait for posted write to complete */
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+               cpu_relax();
+       /* reloaded WCRR from WLDR */
+}
+
+static void omap_wdt_enable(void)
+{
+       /* Sequence to enable the watchdog */
+       omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+               cpu_relax();
+       omap_writel(0x4444, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+               cpu_relax();
+}
+
+static void omap_wdt_disable(void)
+{
+       /* sequence required to disable watchdog */
+       omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+               cpu_relax();
+       omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+               cpu_relax();
+}
+
+static void omap_wdt_adjust_timeout(unsigned new_timeout)
+{
+       if (new_timeout < TIMER_MARGIN_MIN)
+               new_timeout = TIMER_MARGIN_DEFAULT;
+       if (new_timeout > TIMER_MARGIN_MAX)
+               new_timeout = TIMER_MARGIN_MAX;
+       timer_margin = new_timeout;
+}
+
+static void omap_wdt_set_timeout(void)
+{
+       u32 pre_margin = GET_WLDR_VAL(timer_margin);
+
+       /* just count up at 32 KHz */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               cpu_relax();
+       omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               cpu_relax();
+}
+
+/*
+ *     Allow only one task to hold it open
+ */
+
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+               return -EBUSY;
+
+       if (cpu_is_omap16xx())
+               clk_enable(armwdt_ck);  /* Enable the clock */
+
+       if (cpu_is_omap24xx()) {
+               clk_enable(mpu_wdt_ick);    /* Enable the interface clock */
+               clk_enable(mpu_wdt_fck);    /* Enable the functional clock */
+       }
+
+       /* initialize prescaler */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               cpu_relax();
+       omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               cpu_relax();
+
+       omap_wdt_set_timeout();
+       omap_wdt_enable();
+       return nonseekable_open(inode, file);
+}
+
+static int omap_wdt_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer unless NOWAYOUT is defined.
+        */
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+       omap_wdt_disable();
+
+       if (cpu_is_omap16xx()) {
+               clk_disable(armwdt_ck); /* Disable the clock */
+               clk_put(armwdt_ck);
+               armwdt_ck = NULL;
+       }
+
+       if (cpu_is_omap24xx()) {
+               clk_disable(mpu_wdt_ick);       /* Disable the clock */
+               clk_disable(mpu_wdt_fck);       /* Disable the clock */
+               clk_put(mpu_wdt_ick);
+               clk_put(mpu_wdt_fck);
+               mpu_wdt_ick = NULL;
+               mpu_wdt_fck = NULL;
+       }
+#else
+       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+#endif
+       omap_wdt_users = 0;
+       return 0;
+}
+
+static ssize_t
+omap_wdt_write(struct file *file, const char __user *data,
+               size_t len, loff_t *ppos)
+{
+       /* Refresh LOAD_TIME. */
+       if (len)
+               omap_wdt_ping();
+       return len;
+}
+
+static int
+omap_wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int new_margin;
+       static struct watchdog_info ident = {
+               .identity = "OMAP Watchdog",
+               .options = WDIOF_SETTIMEOUT,
+               .firmware_version = 0,
+       };
+
+       switch (cmd) {
+       default:
+               return -ENOTTY;
+       case WDIOC_GETSUPPORT:
+               return copy_to_user((struct watchdog_info __user *)arg, &ident,
+                               sizeof(ident));
+       case WDIOC_GETSTATUS:
+               return put_user(0, (int __user *)arg);
+       case WDIOC_GETBOOTSTATUS:
+               if (cpu_is_omap16xx())
+                       return put_user(omap_readw(ARM_SYSST),
+                                       (int __user *)arg);
+               if (cpu_is_omap24xx())
+                       return put_user(omap_prcm_get_reset_sources(),
+                                       (int __user *)arg);
+       case WDIOC_KEEPALIVE:
+               omap_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int __user *)arg))
+                       return -EFAULT;
+               omap_wdt_adjust_timeout(new_margin);
+
+               omap_wdt_disable();
+               omap_wdt_set_timeout();
+               omap_wdt_enable();
+
+               omap_wdt_ping();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               return put_user(timer_margin, (int __user *)arg);
+       }
+}
+
+static const struct file_operations omap_wdt_fops = {
+       .owner = THIS_MODULE,
+       .write = omap_wdt_write,
+       .ioctl = omap_wdt_ioctl,
+       .open = omap_wdt_open,
+       .release = omap_wdt_release,
+};
+
+static struct miscdevice omap_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &omap_wdt_fops
+};
+
+static int __init omap_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res, *mem;
+       int ret;
+
+       /* reserve static register mappings */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       mem = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (mem == NULL)
+               return -EBUSY;
+
+       platform_set_drvdata(pdev, mem);
+
+       omap_wdt_users = 0;
+
+       if (cpu_is_omap16xx()) {
+               armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
+               if (IS_ERR(armwdt_ck)) {
+                       ret = PTR_ERR(armwdt_ck);
+                       armwdt_ck = NULL;
+                       goto fail;
+               }
+       }
+
+       if (cpu_is_omap24xx()) {
+               mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
+               if (IS_ERR(mpu_wdt_ick)) {
+                       ret = PTR_ERR(mpu_wdt_ick);
+                       mpu_wdt_ick = NULL;
+                       goto fail;
+               }
+               mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
+               if (IS_ERR(mpu_wdt_fck)) {
+                       ret = PTR_ERR(mpu_wdt_fck);
+                       mpu_wdt_fck = NULL;
+                       goto fail;
+               }
+       }
+
+       omap_wdt_disable();
+       omap_wdt_adjust_timeout(timer_margin);
+
+       omap_wdt_miscdev.parent = &pdev->dev;
+       ret = misc_register(&omap_wdt_miscdev);
+       if (ret)
+               goto fail;
+
+       pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+
+       /* autogate OCP interface clock */
+       omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+       return 0;
+
+fail:
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       release_resource(mem);
+       return ret;
+}
+
+static void omap_wdt_shutdown(struct platform_device *pdev)
+{
+       omap_wdt_disable();
+}
+
+static int omap_wdt_remove(struct platform_device *pdev)
+{
+       struct resource *mem = platform_get_drvdata(pdev);
+       misc_deregister(&omap_wdt_miscdev);
+       release_resource(mem);
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (omap_wdt_users)
+               omap_wdt_disable();
+       return 0;
+}
+
+static int omap_wdt_resume(struct platform_device *pdev)
+{
+       if (omap_wdt_users) {
+               omap_wdt_enable();
+               omap_wdt_ping();
+       }
+       return 0;
+}
+
+#else
+#define        omap_wdt_suspend        NULL
+#define        omap_wdt_resume         NULL
+#endif
+
+static struct platform_driver omap_wdt_driver = {
+       .probe          = omap_wdt_probe,
+       .remove         = omap_wdt_remove,
+       .shutdown       = omap_wdt_shutdown,
+       .suspend        = omap_wdt_suspend,
+       .resume         = omap_wdt_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "omap_wdt",
+       },
+};
+
+static int __init omap_wdt_init(void)
+{
+       return platform_driver_register(&omap_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+       platform_driver_unregister(&omap_wdt_driver);
+}
+
+module_init(omap_wdt_init);
+module_exit(omap_wdt_exit);
+
+MODULE_AUTHOR("George G. Davis");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
new file mode 100644 (file)
index 0000000..52a532a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/char/watchdog/omap_wdt.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP Watchdog timer register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _OMAP_WATCHDOG_H
+#define _OMAP_WATCHDOG_H
+
+#define OMAP1610_WATCHDOG_BASE         0xfffeb000
+#define OMAP2420_WATCHDOG_BASE         0x48022000      /*WDT Timer 2 */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP_WATCHDOG_BASE             OMAP2420_WATCHDOG_BASE
+#else
+#define OMAP_WATCHDOG_BASE             OMAP1610_WATCHDOG_BASE
+#define RM_RSTST_WKUP                  0
+#endif
+
+#define OMAP_WATCHDOG_REV              (OMAP_WATCHDOG_BASE + 0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG       (OMAP_WATCHDOG_BASE + 0x10)
+#define OMAP_WATCHDOG_STATUS           (OMAP_WATCHDOG_BASE + 0x14)
+#define OMAP_WATCHDOG_CNTRL            (OMAP_WATCHDOG_BASE + 0x24)
+#define OMAP_WATCHDOG_CRR              (OMAP_WATCHDOG_BASE + 0x28)
+#define OMAP_WATCHDOG_LDR              (OMAP_WATCHDOG_BASE + 0x2c)
+#define OMAP_WATCHDOG_TGR              (OMAP_WATCHDOG_BASE + 0x30)
+#define OMAP_WATCHDOG_WPS              (OMAP_WATCHDOG_BASE + 0x34)
+#define OMAP_WATCHDOG_SPR              (OMAP_WATCHDOG_BASE + 0x48)
+
+/* Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX       (24 * 60 * 60)  /* 1 day */
+#define TIMER_MARGIN_DEFAULT   60      /* 60 secs */
+#define TIMER_MARGIN_MIN       1
+
+#define PTV                    0       /* prescale */
+#define GET_WLDR_VAL(secs)     (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+
+#endif                         /* _OMAP_WATCHDOG_H */
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
new file mode 100644 (file)
index 0000000..3d3deae
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ *      NS pc87413-wdt Watchdog Timer driver for Linux 2.6.x.x
+ *
+ *      This code is based on wdt.c with original copyright.
+ *
+ *      (C) Copyright 2006 Sven Anders, <anders@anduras.de>
+ *                     and Marcus Junker, <junker@anduras.de>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Neither Sven Anders, Marcus Junker nor ANDURAS AG
+ *      admit liability nor provide warranty for any of this software.
+ *      This material is provided "AS-IS" and at no charge.
+ *
+ *      Release 1.1
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* #define DEBUG 1 */
+
+#define DEFAULT_TIMEOUT     1            /* 1 minute */
+#define MAX_TIMEOUT         255
+
+#define VERSION             "1.1"
+#define MODNAME             "pc87413 WDT"
+#define PFX                 MODNAME ": "
+#define DPFX                MODNAME " - DEBUG: "
+
+#define WDT_INDEX_IO_PORT   (io+0)       /* I/O port base (index register) */
+#define WDT_DATA_IO_PORT    (WDT_INDEX_IO_PORT+1)
+#define SWC_LDN             0x04
+#define SIOCFG2             0x22         /* Serial IO register */
+#define WDCTL               0x10         /* Watchdog-Timer-Controll-Register */
+#define WDTO                0x11         /* Watchdog timeout register */
+#define WDCFG               0x12         /* Watchdog config register */
+
+static int io = 0x2E;                   /* Address used on Portwell Boards */
+
+static int timeout = DEFAULT_TIMEOUT;    /* timeout value */
+static unsigned long timer_enabled = 0;  /* is the timer enabled? */
+
+static char expect_close;                /* is the close expected? */
+
+static spinlock_t io_lock;               /* to guard the watchdog from io races */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+/* -- Low level function ----------------------------------------*/
+
+/* Select pins for Watchdog output */
+
+static inline void pc87413_select_wdt_out (void)
+{
+       unsigned int cr_data = 0;
+
+       /* Step 1: Select multiple pin,pin55,as WDT output */
+
+       outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
+
+       cr_data = inb (WDT_DATA_IO_PORT);
+
+       cr_data |= 0x80; /* Set Bit7 to 1*/
+       outb_p(SIOCFG2, WDT_INDEX_IO_PORT);
+
+       outb_p(cr_data, WDT_DATA_IO_PORT);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:"
+                             " Bit7 to 1: %d\n", cr_data);
+#endif
+}
+
+/* Enable SWC functions */
+
+static inline void pc87413_enable_swc(void)
+{
+       unsigned int cr_data=0;
+
+       /* Step 2: Enable SWC functions */
+
+       outb_p(0x07, WDT_INDEX_IO_PORT);        /* Point SWC_LDN (LDN=4) */
+       outb_p(SWC_LDN, WDT_DATA_IO_PORT);
+
+       outb_p(0x30, WDT_INDEX_IO_PORT);        /* Read Index 0x30 First */
+       cr_data = inb(WDT_DATA_IO_PORT);
+       cr_data |= 0x01;                        /* Set Bit0 to 1 */
+       outb_p(0x30, WDT_INDEX_IO_PORT);
+       outb_p(cr_data, WDT_DATA_IO_PORT);      /* Index0x30_bit0P1 */
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
+#endif
+}
+
+/* Read SWC I/O base address */
+
+static inline unsigned int pc87413_get_swc_base(void)
+{
+       unsigned int  swc_base_addr = 0;
+       unsigned char addr_l, addr_h = 0;
+
+       /* Step 3: Read SWC I/O Base Address */
+
+       outb_p(0x60, WDT_INDEX_IO_PORT);        /* Read Index 0x60 */
+       addr_h = inb(WDT_DATA_IO_PORT);
+
+       outb_p(0x61, WDT_INDEX_IO_PORT);        /* Read Index 0x61 */
+
+       addr_l = inb(WDT_DATA_IO_PORT);
+
+       swc_base_addr = (addr_h << 8) + addr_l;
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d,"
+                             " res %d\n", addr_l, addr_h, swc_base_addr);
+#endif
+
+       return swc_base_addr;
+}
+
+/* Select Bank 3 of SWC */
+
+static inline void pc87413_swc_bank3(unsigned int swc_base_addr)
+{
+       /* Step 4: Select Bank3 of SWC */
+
+       outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
+#endif
+}
+
+/* Set watchdog timeout to x minutes */
+
+static inline void pc87413_programm_wdto(unsigned int swc_base_addr,
+                                        char pc87413_time)
+{
+       /* Step 5: Programm WDTO, Twd. */
+
+       outb_p(pc87413_time, swc_base_addr + WDTO);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
+#endif
+}
+
+/* Enable WDEN */
+
+static inline void pc87413_enable_wden(unsigned int swc_base_addr)
+{
+       /* Step 6: Enable WDEN */
+
+       outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Enable WDEN\n");
+#endif
+}
+
+/* Enable SW_WD_TREN */
+static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr)
+{
+       /* Enable SW_WD_TREN */
+
+       outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
+#endif
+}
+
+/* Disable SW_WD_TREN */
+
+static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr)
+{
+       /* Disable SW_WD_TREN */
+
+       outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
+#endif
+}
+
+/* Enable SW_WD_TRG */
+
+static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr)
+{
+       /* Enable SW_WD_TRG */
+
+       outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
+#endif
+}
+
+/* Disable SW_WD_TRG */
+
+static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr)
+{
+       /* Disable SW_WD_TRG */
+
+       outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
+
+#ifdef DEBUG
+       printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
+#endif
+}
+
+/* -- Higher level functions ------------------------------------*/
+
+/* Enable the watchdog */
+
+static void pc87413_enable(void)
+{
+       unsigned int swc_base_addr;
+
+       spin_lock(&io_lock);
+
+       pc87413_select_wdt_out();
+       pc87413_enable_swc();
+       swc_base_addr = pc87413_get_swc_base();
+       pc87413_swc_bank3(swc_base_addr);
+       pc87413_programm_wdto(swc_base_addr, timeout);
+       pc87413_enable_wden(swc_base_addr);
+       pc87413_enable_sw_wd_tren(swc_base_addr);
+       pc87413_enable_sw_wd_trg(swc_base_addr);
+
+       spin_unlock(&io_lock);
+}
+
+/* Disable the watchdog */
+
+static void pc87413_disable(void)
+{
+       unsigned int swc_base_addr;
+
+       spin_lock(&io_lock);
+
+       pc87413_select_wdt_out();
+       pc87413_enable_swc();
+       swc_base_addr = pc87413_get_swc_base();
+       pc87413_swc_bank3(swc_base_addr);
+       pc87413_disable_sw_wd_tren(swc_base_addr);
+       pc87413_disable_sw_wd_trg(swc_base_addr);
+       pc87413_programm_wdto(swc_base_addr, 0);
+
+       spin_unlock(&io_lock);
+}
+
+/* Refresh the watchdog */
+
+static void pc87413_refresh(void)
+{
+       unsigned int swc_base_addr;
+
+       spin_lock(&io_lock);
+
+       pc87413_select_wdt_out();
+       pc87413_enable_swc();
+       swc_base_addr = pc87413_get_swc_base();
+       pc87413_swc_bank3(swc_base_addr);
+       pc87413_disable_sw_wd_tren(swc_base_addr);
+       pc87413_disable_sw_wd_trg(swc_base_addr);
+       pc87413_programm_wdto(swc_base_addr, timeout);
+       pc87413_enable_wden(swc_base_addr);
+       pc87413_enable_sw_wd_tren(swc_base_addr);
+       pc87413_enable_sw_wd_trg(swc_base_addr);
+
+       spin_unlock(&io_lock);
+}
+
+/* -- File operations -------------------------------------------*/
+
+/**
+ *     pc87413_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ */
+
+static int pc87413_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+
+       if (test_and_set_bit(0, &timer_enabled))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Reload and activate timer */
+       pc87413_refresh();
+
+       printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to"
+                                " %d minute(s).\n", timeout);
+
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     pc87413_release:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The watchdog has a configurable API. There is a religious dispute
+ *     between people who want their watchdog to be able to shut down and
+ *     those who want to be sure if the watchdog manager dies the machine
+ *     reboots. In the former case we disable the counters, in the latter
+ *     case you have to open it again very soon.
+ */
+
+static int pc87413_release(struct inode *inode, struct file *file)
+{
+       /* Shut off the timer. */
+
+       if (expect_close == 42) {
+               pc87413_disable();
+               printk(KERN_INFO MODNAME "Watchdog disabled,"
+                                        " sleeping again...\n");
+       } else {
+               printk(KERN_CRIT MODNAME "Unexpected close, not stopping"
+                                        " watchdog!\n");
+               pc87413_refresh();
+       }
+
+       clear_bit(0, &timer_enabled);
+       expect_close = 0;
+
+       return 0;
+}
+
+/**
+ *     pc87413_status:
+ *
+ *      return, if the watchdog is enabled (timeout is set...)
+ */
+
+
+static int pc87413_status(void)
+{
+         return 0; /* currently not supported */
+}
+
+/**
+ *     pc87413_write:
+ *     @file: file handle to the watchdog
+ *     @data: data buffer to write
+ *     @len: length in bytes
+ *     @ppos: pointer to the position to write. No seeks allowed
+ *
+ *     A write to a watchdog device is defined as a keepalive signal. Any
+ *     write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t pc87413_write(struct file *file, const char __user *data,
+                            size_t len, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* reset expect flag */
+                       expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if (get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               pc87413_refresh();
+       }
+       return len;
+}
+
+/**
+ *     pc87413_ioctl:
+ *     @inode: inode of the device
+ *     @file: file handle to the device
+ *     @cmd: watchdog command
+ *     @arg: argument pointer
+ *
+ *     The watchdog API defines a common set of functions for all watchdogs
+ *     according to their available features. We only actually usefully support
+ *     querying capabilities and current status.
+ */
+
+static int pc87413_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       int new_timeout;
+
+       union {
+               struct watchdog_info __user *ident;
+               int __user *i;
+       } uarg;
+
+       static struct watchdog_info ident = {
+               .options          = WDIOF_KEEPALIVEPING |
+                                   WDIOF_SETTIMEOUT |
+                                   WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity         = "PC87413(HF/F) watchdog"
+       };
+
+       uarg.i = (int __user *)arg;
+
+       switch(cmd) {
+               default:
+                       return -ENOTTY;
+
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(uarg.ident, &ident,
+                               sizeof(ident)) ? -EFAULT : 0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user(pc87413_status(), uarg.i);
+
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, uarg.i);
+
+               case WDIOC_KEEPALIVE:
+                       pc87413_refresh();
+#ifdef DEBUG
+                       printk(KERN_INFO DPFX "keepalive\n");
+#endif
+                       return 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_timeout, uarg.i))
+                               return -EFAULT;
+
+                       // the API states this is given in secs
+                       new_timeout /= 60;
+
+                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       pc87413_refresh();
+
+                       // fall through and return the new timeout...
+
+               case WDIOC_GETTIMEOUT:
+
+                       new_timeout = timeout * 60;
+
+                       return put_user(new_timeout, uarg.i);
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int options, retval = -EINVAL;
+
+                       if (get_user(options, uarg.i))
+                               return -EFAULT;
+
+                       if (options & WDIOS_DISABLECARD) {
+                               pc87413_disable();
+                               retval = 0;
+                       }
+
+                       if (options & WDIOS_ENABLECARD) {
+                               pc87413_enable();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+       }
+}
+
+/* -- Notifier funtions -----------------------------------------*/
+
+/**
+ *     notify_sys:
+ *     @this: our notifier block
+ *     @code: the event being reported
+ *     @unused: unused
+ *
+ *     Our notifier is called on system shutdowns. We want to turn the card
+ *     off at reboot otherwise the machine will reboot again during memory
+ *     test or worse yet during the following fsck. This would suck, in fact
+ *     trust me - if it happens it does suck.
+ */
+
+static int pc87413_notify_sys(struct notifier_block *this,
+                             unsigned long code,
+                             void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+       {
+               /* Turn the card off */
+               pc87413_disable();
+       }
+       return NOTIFY_DONE;
+}
+
+/* -- Module's structures ---------------------------------------*/
+
+static const struct file_operations pc87413_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = pc87413_write,
+       .ioctl          = pc87413_ioctl,
+       .open           = pc87413_open,
+       .release        = pc87413_release,
+};
+
+static struct notifier_block pc87413_notifier =
+{
+       .notifier_call  = pc87413_notify_sys,
+};
+
+static struct miscdevice pc87413_miscdev=
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &pc87413_fops
+};
+
+/* -- Module init functions -------------------------------------*/
+
+/**
+ *     pc87413_init: module's "constructor"
+ *
+ *     Set up the WDT watchdog board. All we have to do is grab the
+ *     resources we require and bitch if anyone beat us to them.
+ *     The open() function will actually kick the board off.
+ */
+
+static int __init pc87413_init(void)
+{
+       int ret;
+
+       spin_lock_init(&io_lock);
+
+       printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT);
+
+       /* request_region(io, 2, "pc87413"); */
+
+       ret = register_reboot_notifier(&pc87413_notifier);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+       }
+
+       ret = misc_register(&pc87413_miscdev);
+
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               unregister_reboot_notifier(&pc87413_notifier);
+               return ret;
+       }
+
+       printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
+
+       pc87413_enable();
+
+       return 0;
+}
+
+/**
+ *     pc87413_exit: module's "destructor"
+ *
+ *     Unload the watchdog. You cannot do this with any file handles open.
+ *     If your watchdog is set to continue ticking on close and you unload
+ *     it, well it keeps ticking. We won't get the interrupt but the board
+ *     will not touch PC memory so all is fine. You just have to load a new
+ *     module in 60 seconds or reboot.
+ */
+
+static void __exit pc87413_exit(void)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+       {
+               pc87413_disable();
+               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+       }
+
+       misc_deregister(&pc87413_miscdev);
+       unregister_reboot_notifier(&pc87413_notifier);
+       /* release_region(io,2); */
+
+       printk(MODNAME " watchdog component driver removed.\n");
+}
+
+module_init(pc87413_init);
+module_exit(pc87413_exit);
+
+MODULE_AUTHOR("Sven Anders <anders@anduras.de>, Marcus Junker <junker@anduras.de>,");
+MODULE_DESCRIPTION("PC87413 WDT driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ").");
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(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/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
new file mode 100644 (file)
index 0000000..7b41434
--- /dev/null
@@ -0,0 +1,1013 @@
+/*
+ * PC Watchdog Driver
+ * by Ken Hollis (khollis@bitgate.com)
+ *
+ * Permission granted from Simon Machell (smachell@berkprod.com)
+ * Written for the Linux Kernel, and GPLed by Ken Hollis
+ *
+ * 960107      Added request_region routines, modulized the whole thing.
+ * 960108      Fixed end-of-file pointer (Thanks to Dan Hollis), added
+ *             WD_TIMEOUT define.
+ * 960216      Added eof marker on the file, and changed verbose messages.
+ * 960716      Made functional and cosmetic changes to the source for
+ *             inclusion in Linux 2.0.x kernels, thanks to Alan Cox.
+ * 960717      Removed read/seek routines, replaced with ioctl.  Also, added
+ *             check_region command due to Alan's suggestion.
+ * 960821      Made changes to compile in newer 2.0.x kernels.  Added
+ *             "cold reboot sense" entry.
+ * 960825      Made a few changes to code, deleted some defines and made
+ *             typedefs to replace them.  Made heartbeat reset only available
+ *             via ioctl, and removed the write routine.
+ * 960828      Added new items for PC Watchdog Rev.C card.
+ * 960829      Changed around all of the IOCTLs, added new features,
+ *             added watchdog disable/re-enable routines.  Added firmware
+ *             version reporting.  Added read routine for temperature.
+ *             Removed some extra defines, added an autodetect Revision
+ *             routine.
+ * 961006       Revised some documentation, fixed some cosmetic bugs.  Made
+ *              drivers to panic the system if it's overheating at bootup.
+ * 961118      Changed some verbiage on some of the output, tidied up
+ *             code bits, and added compatibility to 2.1.x.
+ * 970912       Enabled board on open and disable on close.
+ * 971107      Took account of recent VFS changes (broke read).
+ * 971210       Disable board on initialisation in case board already ticking.
+ * 971222       Changed open/close for temperature handling
+ *              Michael Meskes <meskes@debian.org>.
+ * 980112       Used minor numbers from include/linux/miscdevice.h
+ * 990403       Clear reset status after reading control status register in
+ *              pcwd_showprevstate(). [Marc Boucher <marc@mbsi.ca>]
+ * 990605      Made changes to code to support Firmware 1.22a, added
+ *             fairly useless proc entry.
+ * 990610      removed said useless proc code for the merge <alan>
+ * 000403      Removed last traces of proc code. <davej>
+ * 011214      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com>
+ *              Added timeout module option to override default
+ */
+
+/*
+ *     A bells and whistles driver is available from http://www.pcwd.de/
+ *     More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
+ */
+
+#include <linux/module.h>      /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h>       /* For standard types (like size_t) */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/delay.h>       /* For mdelay function */
+#include <linux/timer.h>       /* For timer related operations */
+#include <linux/jiffies.h>     /* For jiffies stuff */
+#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>    /* For the watchdog specific items */
+#include <linux/reboot.h>      /* For kernel_power_off() */
+#include <linux/init.h>                /* For __init/__exit/... */
+#include <linux/fs.h>          /* For file operations */
+#include <linux/isa.h>         /* For isa devices */
+#include <linux/ioport.h>      /* For io-port access */
+#include <linux/spinlock.h>    /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
+#include <asm/io.h>            /* For inb/outb/... */
+
+/* Module and version information */
+#define WATCHDOG_VERSION "1.20"
+#define WATCHDOG_DATE "18 Feb 2007"
+#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
+#define WATCHDOG_NAME "pcwd"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
+#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
+
+/*
+ * It should be noted that PCWD_REVISION_B was removed because A and B
+ * are essentially the same types of card, with the exception that B
+ * has temperature reporting.  Since I didn't receive a Rev.B card,
+ * the Rev.B card is not supported.  (It's a good thing too, as they
+ * are no longer in production.)
+ */
+#define        PCWD_REVISION_A         1
+#define        PCWD_REVISION_C         2
+
+/*
+ * These are the auto-probe addresses available.
+ *
+ * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
+ * Revision A has an address range of 2 addresses, while Revision C has 4.
+ */
+#define PCWD_ISA_NR_CARDS      3
+static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
+
+/*
+ * These are the defines that describe the control status bits for the
+ * PCI-PC Watchdog card.
+*/
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
+#define WD_WDRST               0x01    /* Previously reset state */
+#define WD_T110                        0x02    /* Temperature overheat sense */
+#define WD_HRTBT               0x04    /* Heartbeat sense */
+#define WD_RLY2                        0x08    /* External relay triggered */
+#define WD_SRLY2               0x80    /* Software external relay triggered */
+/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
+#define WD_REVC_WTRP           0x01    /* Watchdog Trip status */
+#define WD_REVC_HRBT           0x02    /* Watchdog Heartbeat */
+#define WD_REVC_TTRP           0x04    /* Temperature Trip status */
+#define WD_REVC_RL2A           0x08    /* Relay 2 activated by on-board processor */
+#define WD_REVC_RL1A           0x10    /* Relay 1 active */
+#define WD_REVC_R2DS           0x40    /* Relay 2 disable */
+#define WD_REVC_RLY2           0x80    /* Relay 2 activated? */
+/* Port 2 : Control Status #2 */
+#define WD_WDIS                        0x10    /* Watchdog Disabled */
+#define WD_ENTP                        0x20    /* Watchdog Enable Temperature Trip */
+#define WD_SSEL                        0x40    /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
+#define WD_WCMD                        0x80    /* Watchdog Command Mode */
+
+/* max. time we give an ISA watchdog card to process a command */
+/* 500ms for each 4 bit response (according to spec.) */
+#define ISA_COMMAND_TIMEOUT     1000
+
+/* Watchdog's internal commands */
+#define CMD_ISA_IDLE                   0x00
+#define CMD_ISA_VERSION_INTEGER                0x01
+#define CMD_ISA_VERSION_TENTH          0x02
+#define CMD_ISA_VERSION_HUNDRETH       0x03
+#define CMD_ISA_VERSION_MINOR          0x04
+#define CMD_ISA_SWITCH_SETTINGS                0x05
+#define CMD_ISA_RESET_PC               0x06
+#define CMD_ISA_ARM_0                  0x07
+#define CMD_ISA_ARM_30                 0x08
+#define CMD_ISA_ARM_60                 0x09
+#define CMD_ISA_DELAY_TIME_2SECS       0x0A
+#define CMD_ISA_DELAY_TIME_4SECS       0x0B
+#define CMD_ISA_DELAY_TIME_8SECS       0x0C
+#define CMD_ISA_RESET_RELAYS           0x0D
+
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       20,     /* OFF-OFF-OFF  = 20 Sec  */
+       40,     /* OFF-OFF-ON   = 40 Sec  */
+       60,     /* OFF-ON-OFF   =  1 Min  */
+       300,    /* OFF-ON-ON    =  5 Min  */
+       600,    /* ON-OFF-OFF   = 10 Min  */
+       1800,   /* ON-OFF-ON    = 30 Min  */
+       3600,   /* ON-ON-OFF    =  1 Hour */
+       7200,   /* ON-ON-ON     =  2 hour */
+};
+
+/*
+ * We are using an kernel timer to do the pinging of the watchdog
+ * every ~500ms. We try to set the internal heartbeat of the
+ * watchdog to 2 ms.
+ */
+
+#define WDT_INTERVAL (HZ/2+1)
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
+
+/* internal variables */
+static atomic_t open_allowed = ATOMIC_INIT(1);
+static char expect_close;
+static int temp_panic;
+static struct {                                /* this is private data for each ISA-PC watchdog card */
+       char fw_ver_str[6];             /* The cards firmware version */
+       int revision;                   /* The card's revision */
+       int supports_temp;              /* Wether or not the card has a temperature device */
+       int command_mode;               /* Wether or not the card is in command mode */
+       int boot_status;                /* The card's boot status */
+       int io_addr;                    /* The cards I/O address */
+       spinlock_t io_lock;             /* the lock for io operations */
+       struct timer_list timer;        /* The timer that pings the watchdog */
+       unsigned long next_heartbeat;   /* the next_heartbeat for the timer */
+} pcwd_private;
+
+/* module parameters */
+#define QUIET  0       /* Default */
+#define VERBOSE        1       /* Verbose */
+#define DEBUG  2       /* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
+#define WATCHDOG_HEARTBEAT 0           /* default heartbeat = delay-time from dip-switches */
+static int heartbeat = WATCHDOG_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+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) ")");
+
+/*
+ *     Internal functions
+ */
+
+static int send_isa_command(int cmd)
+{
+       int i;
+       int control_status;
+       int port0, last_port0;  /* Double read for stabilising */
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
+                       cmd);
+
+       /* The WCMD bit must be 1 and the command is only 4 bits in size */
+       control_status = (cmd & 0x0F) | WD_WCMD;
+       outb_p(control_status, pcwd_private.io_addr + 2);
+       udelay(ISA_COMMAND_TIMEOUT);
+
+       port0 = inb_p(pcwd_private.io_addr);
+       for (i = 0; i < 25; ++i) {
+               last_port0 = port0;
+               port0 = inb_p(pcwd_private.io_addr);
+
+               if (port0 == last_port0)
+                       break;  /* Data is stable */
+
+               udelay (250);
+       }
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+                       cmd, port0, last_port0);
+
+       return port0;
+}
+
+static int set_command_mode(void)
+{
+       int i, found=0, count=0;
+
+       /* Set the card into command mode */
+       spin_lock(&pcwd_private.io_lock);
+       while ((!found) && (count < 3)) {
+               i = send_isa_command(CMD_ISA_IDLE);
+
+               if (i == 0x00)
+                       found = 1;
+               else if (i == 0xF3) {
+                       /* Card does not like what we've done to it */
+                       outb_p(0x00, pcwd_private.io_addr + 2);
+                       udelay(1200);   /* Spec says wait 1ms */
+                       outb_p(0x00, pcwd_private.io_addr + 2);
+                       udelay(ISA_COMMAND_TIMEOUT);
+               }
+               count++;
+       }
+       spin_unlock(&pcwd_private.io_lock);
+       pcwd_private.command_mode = found;
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "command_mode=%d\n",
+                               pcwd_private.command_mode);
+
+       return(found);
+}
+
+static void unset_command_mode(void)
+{
+       /* Set the card into normal mode */
+       spin_lock(&pcwd_private.io_lock);
+       outb_p(0x00, pcwd_private.io_addr + 2);
+       udelay(ISA_COMMAND_TIMEOUT);
+       spin_unlock(&pcwd_private.io_lock);
+
+       pcwd_private.command_mode = 0;
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "command_mode=%d\n",
+                               pcwd_private.command_mode);
+}
+
+static inline void pcwd_check_temperature_support(void)
+{
+       if (inb(pcwd_private.io_addr) != 0xF0)
+               pcwd_private.supports_temp = 1;
+}
+
+static inline void pcwd_get_firmware(void)
+{
+       int one, ten, hund, minor;
+
+       strcpy(pcwd_private.fw_ver_str, "ERROR");
+
+       if (set_command_mode()) {
+               one = send_isa_command(CMD_ISA_VERSION_INTEGER);
+               ten = send_isa_command(CMD_ISA_VERSION_TENTH);
+               hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
+               minor = send_isa_command(CMD_ISA_VERSION_MINOR);
+               sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
+       }
+       unset_command_mode();
+
+       return;
+}
+
+static inline int pcwd_get_option_switches(void)
+{
+       int option_switches=0;
+
+       if (set_command_mode()) {
+               /* Get switch settings */
+               option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS);
+       }
+
+       unset_command_mode();
+       return(option_switches);
+}
+
+static void pcwd_show_card_info(void)
+{
+       int option_switches;
+
+       /* Get some extra info from the hardware (in command/debug/diag mode) */
+       if (pcwd_private.revision == PCWD_REVISION_A)
+               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
+       else if (pcwd_private.revision == PCWD_REVISION_C) {
+               pcwd_get_firmware();
+               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
+                       pcwd_private.io_addr, pcwd_private.fw_ver_str);
+               option_switches = pcwd_get_option_switches();
+               printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+                       option_switches,
+                       ((option_switches & 0x10) ? "ON" : "OFF"),
+                       ((option_switches & 0x08) ? "ON" : "OFF"));
+
+               /* Reprogram internal heartbeat to 2 seconds */
+               if (set_command_mode()) {
+                       send_isa_command(CMD_ISA_DELAY_TIME_2SECS);
+                       unset_command_mode();
+               }
+       }
+
+       if (pcwd_private.supports_temp)
+               printk(KERN_INFO PFX "Temperature Option Detected\n");
+
+       if (pcwd_private.boot_status & WDIOF_CARDRESET)
+               printk(KERN_INFO PFX "Previous reboot was caused by the card\n");
+
+       if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
+               printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n");
+               printk(KERN_EMERG PFX "CPU Overheat\n");
+       }
+
+       if (pcwd_private.boot_status == 0)
+               printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+}
+
+static void pcwd_timer_ping(unsigned long data)
+{
+       int wdrst_stat;
+
+       /* If we got a heartbeat pulse within the WDT_INTERVAL
+        * we agree to ping the WDT */
+       if(time_before(jiffies, pcwd_private.next_heartbeat)) {
+               /* Ping the watchdog */
+               spin_lock(&pcwd_private.io_lock);
+               if (pcwd_private.revision == PCWD_REVISION_A) {
+                       /*  Rev A cards are reset by setting the WD_WDRST bit in register 1 */
+                       wdrst_stat = inb_p(pcwd_private.io_addr);
+                       wdrst_stat &= 0x0F;
+                       wdrst_stat |= WD_WDRST;
+
+                       outb_p(wdrst_stat, pcwd_private.io_addr + 1);
+               } else {
+                       /* Re-trigger watchdog by writing to port 0 */
+                       outb_p(0x00, pcwd_private.io_addr);
+               }
+
+               /* Re-set the timer interval */
+               mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
+
+               spin_unlock(&pcwd_private.io_lock);
+       } else {
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+static int pcwd_start(void)
+{
+       int stat_reg;
+
+       pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+       /* Start the timer */
+       mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL);
+
+       /* Enable the port */
+       if (pcwd_private.revision == PCWD_REVISION_C) {
+               spin_lock(&pcwd_private.io_lock);
+               outb_p(0x00, pcwd_private.io_addr + 3);
+               udelay(ISA_COMMAND_TIMEOUT);
+               stat_reg = inb_p(pcwd_private.io_addr + 2);
+               spin_unlock(&pcwd_private.io_lock);
+               if (stat_reg & WD_WDIS) {
+                       printk(KERN_INFO PFX "Could not start watchdog\n");
+                       return -EIO;
+               }
+       }
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "Watchdog started\n");
+
+       return 0;
+}
+
+static int pcwd_stop(void)
+{
+       int stat_reg;
+
+       /* Stop the timer */
+       del_timer(&pcwd_private.timer);
+
+       /*  Disable the board  */
+       if (pcwd_private.revision == PCWD_REVISION_C) {
+               spin_lock(&pcwd_private.io_lock);
+               outb_p(0xA5, pcwd_private.io_addr + 3);
+               udelay(ISA_COMMAND_TIMEOUT);
+               outb_p(0xA5, pcwd_private.io_addr + 3);
+               udelay(ISA_COMMAND_TIMEOUT);
+               stat_reg = inb_p(pcwd_private.io_addr + 2);
+               spin_unlock(&pcwd_private.io_lock);
+               if ((stat_reg & WD_WDIS) == 0) {
+                       printk(KERN_INFO PFX "Could not stop watchdog\n");
+                       return -EIO;
+               }
+       }
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
+       return 0;
+}
+
+static int pcwd_keepalive(void)
+{
+       /* user land ping */
+       pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
+       return 0;
+}
+
+static int pcwd_set_heartbeat(int t)
+{
+       if ((t < 2) || (t > 7200)) /* arbitrary upper limit */
+               return -EINVAL;
+
+       heartbeat = t;
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+                      heartbeat);
+
+       return 0;
+}
+
+static int pcwd_get_status(int *status)
+{
+       int control_status;
+
+       *status=0;
+       spin_lock(&pcwd_private.io_lock);
+       if (pcwd_private.revision == PCWD_REVISION_A)
+               /* Rev A cards return status information from
+                * the base register, which is used for the
+                * temperature in other cards. */
+               control_status = inb(pcwd_private.io_addr);
+       else {
+               /* Rev C cards return card status in the base
+                * address + 1 register. And use different bits
+                * to indicate a card initiated reset, and an
+                * over-temperature condition. And the reboot
+                * status can be reset. */
+               control_status = inb(pcwd_private.io_addr + 1);
+       }
+       spin_unlock(&pcwd_private.io_lock);
+
+       if (pcwd_private.revision == PCWD_REVISION_A) {
+               if (control_status & WD_WDRST)
+                       *status |= WDIOF_CARDRESET;
+
+               if (control_status & WD_T110) {
+                       *status |= WDIOF_OVERHEAT;
+                       if (temp_panic) {
+                               printk(KERN_INFO PFX "Temperature overheat trip!\n");
+                               kernel_power_off();
+                               /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
+                       }
+               }
+       } else {
+               if (control_status & WD_REVC_WTRP)
+                       *status |= WDIOF_CARDRESET;
+
+               if (control_status & WD_REVC_TTRP) {
+                       *status |= WDIOF_OVERHEAT;
+                       if (temp_panic) {
+                               printk(KERN_INFO PFX "Temperature overheat trip!\n");
+                               kernel_power_off();
+                               /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int pcwd_clear_status(void)
+{
+       int control_status;
+
+       if (pcwd_private.revision == PCWD_REVISION_C) {
+               spin_lock(&pcwd_private.io_lock);
+
+               if (debug >= VERBOSE)
+                       printk(KERN_INFO PFX "clearing watchdog trip status\n");
+
+               control_status = inb_p(pcwd_private.io_addr + 1);
+
+               if (debug >= DEBUG) {
+                       printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+                       printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+                               (control_status & WD_REVC_R2DS));
+               }
+
+               /* clear reset status & Keep Relay 2 disable state as it is */
+               outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
+
+               spin_unlock(&pcwd_private.io_lock);
+       }
+       return 0;
+}
+
+static int pcwd_get_temperature(int *temperature)
+{
+       /* check that port 0 gives temperature info and no command results */
+       if (pcwd_private.command_mode)
+               return -1;
+
+       *temperature = 0;
+       if (!pcwd_private.supports_temp)
+               return -ENODEV;
+
+       /*
+        * Convert celsius to fahrenheit, since this was
+        * the decided 'standard' for this return value.
+        */
+       spin_lock(&pcwd_private.io_lock);
+       *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
+       spin_unlock(&pcwd_private.io_lock);
+
+       if (debug >= DEBUG) {
+               printk(KERN_DEBUG PFX "temperature is: %d F\n",
+                       *temperature);
+       }
+
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int pcwd_ioctl(struct inode *inode, struct file *file,
+                     unsigned int cmd, unsigned long arg)
+{
+       int rv;
+       int status;
+       int temperature;
+       int new_heartbeat;
+       int __user *argp = (int __user *)arg;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_OVERHEAT |
+                                       WDIOF_CARDRESET |
+                                       WDIOF_KEEPALIVEPING |
+                                       WDIOF_SETTIMEOUT |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     1,
+               .identity =             "PCWD",
+       };
+
+       switch(cmd) {
+       default:
+               return -ENOTTY;
+
+       case WDIOC_GETSUPPORT:
+               if(copy_to_user(argp, &ident, sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+
+       case WDIOC_GETSTATUS:
+               pcwd_get_status(&status);
+               return put_user(status, argp);
+
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(pcwd_private.boot_status, argp);
+
+       case WDIOC_GETTEMP:
+               if (pcwd_get_temperature(&temperature))
+                       return -EFAULT;
+
+               return put_user(temperature, argp);
+
+       case WDIOC_SETOPTIONS:
+               if (pcwd_private.revision == PCWD_REVISION_C)
+               {
+                       if(copy_from_user(&rv, argp, sizeof(int)))
+                               return -EFAULT;
+
+                       if (rv & WDIOS_DISABLECARD)
+                       {
+                               return pcwd_stop();
+                       }
+
+                       if (rv & WDIOS_ENABLECARD)
+                       {
+                               return pcwd_start();
+                       }
+
+                       if (rv & WDIOS_TEMPPANIC)
+                       {
+                               temp_panic = 1;
+                       }
+               }
+               return -EINVAL;
+
+       case WDIOC_KEEPALIVE:
+               pcwd_keepalive();
+               return 0;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_heartbeat, argp))
+                       return -EFAULT;
+
+               if (pcwd_set_heartbeat(new_heartbeat))
+                       return -EINVAL;
+
+               pcwd_keepalive();
+               /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(heartbeat, argp);
+       }
+
+       return 0;
+}
+
+static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
+                         loff_t *ppos)
+{
+       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, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               pcwd_keepalive();
+       }
+       return len;
+}
+
+static int pcwd_open(struct inode *inode, struct file *file)
+{
+       if (!atomic_dec_and_test(&open_allowed) ) {
+               if (debug >= VERBOSE)
+                       printk(KERN_ERR PFX "Attempt to open already opened device.\n");
+               atomic_inc( &open_allowed );
+               return -EBUSY;
+       }
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate */
+       pcwd_start();
+       pcwd_keepalive();
+       return nonseekable_open(inode, file);
+}
+
+static int pcwd_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               pcwd_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               pcwd_keepalive();
+       }
+       expect_close = 0;
+       atomic_inc( &open_allowed );
+       return 0;
+}
+
+/*
+ *     /dev/temperature handling
+ */
+
+static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count,
+                        loff_t *ppos)
+{
+       int temperature;
+
+       if (pcwd_get_temperature(&temperature))
+               return -EFAULT;
+
+       if (copy_to_user(buf, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+static int pcwd_temp_open(struct inode *inode, struct file *file)
+{
+       if (!pcwd_private.supports_temp)
+               return -ENODEV;
+
+       return nonseekable_open(inode, file);
+}
+
+static int pcwd_temp_close(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations pcwd_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = pcwd_write,
+       .ioctl          = pcwd_ioctl,
+       .open           = pcwd_open,
+       .release        = pcwd_close,
+};
+
+static struct miscdevice pcwd_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &pcwd_fops,
+};
+
+static const struct file_operations pcwd_temp_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = pcwd_temp_read,
+       .open           = pcwd_temp_open,
+       .release        = pcwd_temp_close,
+};
+
+static struct miscdevice temp_miscdev = {
+       .minor =        TEMP_MINOR,
+       .name =         "temperature",
+       .fops =         &pcwd_temp_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static inline int get_revision(void)
+{
+       int r = PCWD_REVISION_C;
+
+       spin_lock(&pcwd_private.io_lock);
+       /* REV A cards use only 2 io ports; test
+        * presumes a floating bus reads as 0xff. */
+       if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
+           (inb(pcwd_private.io_addr + 3) == 0xFF))
+               r=PCWD_REVISION_A;
+       spin_unlock(&pcwd_private.io_lock);
+
+       return r;
+}
+
+/*
+ *  The ISA cards have a heartbeat bit in one of the registers, which
+ *  register is card dependent.  The heartbeat bit is monitored, and if
+ *  found, is considered proof that a Berkshire card has been found.
+ *  The initial rate is once per second at board start up, then twice
+ *  per second for normal operation.
+ */
+static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
+{
+       int base_addr=pcwd_ioports[id];
+       int port0, last_port0;  /* Reg 0, in case it's REV A */
+       int port1, last_port1;  /* Register 1 for REV C cards */
+       int i;
+       int retval;
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
+                       id);
+
+       if (!request_region (base_addr, 4, "PCWD")) {
+               printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
+               return 0;
+       }
+
+       retval = 0;
+
+       port0 = inb_p(base_addr);       /* For REV A boards */
+       port1 = inb_p(base_addr + 1);   /* For REV C boards */
+       if (port0 != 0xff || port1 != 0xff) {
+               /* Not an 'ff' from a floating bus, so must be a card! */
+               for (i = 0; i < 4; ++i) {
+
+                       msleep(500);
+
+                       last_port0 = port0;
+                       last_port1 = port1;
+
+                       port0 = inb_p(base_addr);
+                       port1 = inb_p(base_addr + 1);
+
+                       /* Has either hearbeat bit changed?  */
+                       if ((port0 ^ last_port0) & WD_HRTBT ||
+                           (port1 ^ last_port1) & WD_REVC_HRBT) {
+                               retval = 1;
+                               break;
+                       }
+               }
+       }
+       release_region (base_addr, 4);
+
+       return retval;
+}
+
+static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
+{
+       int ret;
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
+                       id);
+
+       cards_found++;
+       if (cards_found == 1)
+               printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
+
+       if (cards_found > 1) {
+               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               return -ENODEV;
+       }
+
+       if (pcwd_ioports[id] == 0x0000) {
+               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               return -ENODEV;
+       }
+       pcwd_private.io_addr = pcwd_ioports[id];
+
+       spin_lock_init(&pcwd_private.io_lock);
+
+       /* Check card's revision */
+       pcwd_private.revision = get_revision();
+
+       if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       pcwd_private.io_addr);
+               ret=-EIO;
+               goto error_request_region;
+       }
+
+       /* Initial variables */
+       pcwd_private.supports_temp = 0;
+       temp_panic = 0;
+       pcwd_private.boot_status = 0x0000;
+
+       /* get the boot_status */
+       pcwd_get_status(&pcwd_private.boot_status);
+
+       /* clear the "card caused reboot" flag */
+       pcwd_clear_status();
+
+       setup_timer(&pcwd_private.timer, pcwd_timer_ping, 0);
+
+       /*  Disable the board  */
+       pcwd_stop();
+
+       /*  Check whether or not the card supports the temperature device */
+       pcwd_check_temperature_support();
+
+       /* Show info about the card itself */
+       pcwd_show_card_info();
+
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (pcwd_set_heartbeat(heartbeat)) {
+               pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
+               printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n",
+                       WATCHDOG_HEARTBEAT);
+       }
+
+       if (pcwd_private.supports_temp) {
+               ret = misc_register(&temp_miscdev);
+               if (ret) {
+                       printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                               TEMP_MINOR, ret);
+                       goto error_misc_register_temp;
+               }
+       }
+
+       ret = misc_register(&pcwd_miscdev);
+       if (ret) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto error_misc_register_watchdog;
+       }
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+
+       return 0;
+
+error_misc_register_watchdog:
+       if (pcwd_private.supports_temp)
+               misc_deregister(&temp_miscdev);
+error_misc_register_temp:
+       release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+error_request_region:
+       pcwd_private.io_addr = 0x0000;
+       cards_found--;
+       return ret;
+}
+
+static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
+{
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
+                       id);
+
+       if (!pcwd_private.io_addr)
+               return 1;
+
+       /*  Disable the board  */
+       if (!nowayout)
+               pcwd_stop();
+
+       /* Deregister */
+       misc_deregister(&pcwd_miscdev);
+       if (pcwd_private.supports_temp)
+               misc_deregister(&temp_miscdev);
+       release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+       pcwd_private.io_addr = 0x0000;
+       cards_found--;
+
+       return 0;
+}
+
+static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
+{
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n",
+                       id);
+
+       pcwd_stop();
+}
+
+static struct isa_driver pcwd_isa_driver = {
+       .match          = pcwd_isa_match,
+       .probe          = pcwd_isa_probe,
+       .remove         = __devexit_p(pcwd_isa_remove),
+       .shutdown       = pcwd_isa_shutdown,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = WATCHDOG_NAME,
+       },
+};
+
+static int __init pcwd_init_module(void)
+{
+       return isa_register_driver(&pcwd_isa_driver, PCWD_ISA_NR_CARDS);
+}
+
+static void __exit pcwd_cleanup_module(void)
+{
+       isa_unregister_driver(&pcwd_isa_driver);
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(pcwd_init_module);
+module_exit(pcwd_cleanup_module);
+
+MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>, Wim Van Sebroeck <wim@iguana.be>");
+MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver");
+MODULE_VERSION(WATCHDOG_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
new file mode 100644 (file)
index 0000000..61a89e9
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ *     Berkshire PCI-PC Watchdog Card Driver
+ *
+ *     (c) Copyright 2003-2007 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     Based on source code of the following authors:
+ *       Ken Hollis <kenji@bitgate.com>,
+ *       Lindsay Harris <lindsay@bluegum.com>,
+ *       Alan Cox <alan@redhat.com>,
+ *       Matt Domsch <Matt_Domsch@dell.com>,
+ *       Rob Radez <rob@osinvestor.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ */
+
+/*
+ *     A bells and whistles driver is available from:
+ *     http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/
+ *
+ *     More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
+ */
+
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>      /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h>       /* For standard types (like size_t) */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/delay.h>       /* For mdelay function */
+#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>    /* For the watchdog specific items */
+#include <linux/notifier.h>    /* For notifier support */
+#include <linux/reboot.h>      /* For reboot_notifier stuff */
+#include <linux/init.h>                /* For __init/__exit/... */
+#include <linux/fs.h>          /* For file operations */
+#include <linux/pci.h>         /* For pci functions */
+#include <linux/ioport.h>      /* For io-port access */
+#include <linux/spinlock.h>    /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
+#include <asm/io.h>            /* For inb/outb/... */
+
+/* Module and version information */
+#define WATCHDOG_VERSION "1.03"
+#define WATCHDOG_DATE "21 Jan 2007"
+#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
+#define WATCHDOG_NAME "pcwd_pci"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
+
+/* Stuff for the PCI ID's  */
+#ifndef PCI_VENDOR_ID_QUICKLOGIC
+#define PCI_VENDOR_ID_QUICKLOGIC    0x11e3
+#endif
+
+#ifndef PCI_DEVICE_ID_WATCHDOG_PCIPCWD
+#define PCI_DEVICE_ID_WATCHDOG_PCIPCWD 0x5030
+#endif
+
+/*
+ * These are the defines that describe the control status bits for the
+ * PCI-PC Watchdog card.
+ */
+/* Port 1 : Control Status #1 */
+#define WD_PCI_WTRP            0x01    /* Watchdog Trip status */
+#define WD_PCI_HRBT            0x02    /* Watchdog Heartbeat */
+#define WD_PCI_TTRP            0x04    /* Temperature Trip status */
+#define WD_PCI_RL2A            0x08    /* Relay 2 Active */
+#define WD_PCI_RL1A            0x10    /* Relay 1 Active */
+#define WD_PCI_R2DS            0x40    /* Relay 2 Disable Temperature-trip/reset */
+#define WD_PCI_RLY2            0x80    /* Activate Relay 2 on the board */
+/* Port 2 : Control Status #2 */
+#define WD_PCI_WDIS            0x10    /* Watchdog Disable */
+#define WD_PCI_ENTP            0x20    /* Enable Temperature Trip Reset */
+#define WD_PCI_WRSP            0x40    /* Watchdog wrote response */
+#define WD_PCI_PCMD            0x80    /* PC has sent command */
+
+/* according to documentation max. time to process a command for the pci
+ * watchdog card is 100 ms, so we give it 150 ms to do it's job */
+#define PCI_COMMAND_TIMEOUT    150
+
+/* Watchdog's internal commands */
+#define CMD_GET_STATUS                         0x04
+#define CMD_GET_FIRMWARE_VERSION               0x08
+#define CMD_READ_WATCHDOG_TIMEOUT              0x18
+#define CMD_WRITE_WATCHDOG_TIMEOUT             0x19
+#define CMD_GET_CLEAR_RESET_COUNT              0x84
+
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       5,      /* OFF-OFF-OFF  =  5 Sec  */
+       10,     /* OFF-OFF-ON   = 10 Sec  */
+       30,     /* OFF-ON-OFF   = 30 Sec  */
+       60,     /* OFF-ON-ON    =  1 Min  */
+       300,    /* ON-OFF-OFF   =  5 Min  */
+       600,    /* ON-OFF-ON    = 10 Min  */
+       1800,   /* ON-ON-OFF    = 30 Min  */
+       3600,   /* ON-ON-ON     =  1 hour */
+};
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
+
+/* internal variables */
+static int temp_panic;
+static unsigned long is_active;
+static char expect_release;
+static struct {                                /* this is private data for each PCI-PC watchdog card */
+       int supports_temp;              /* Wether or not the card has a temperature device */
+       int boot_status;                /* The card's boot status */
+       unsigned long io_addr;          /* The cards I/O address */
+       spinlock_t io_lock;             /* the lock for io operations */
+       struct pci_dev *pdev;           /* the PCI-device */
+} pcipcwd_private;
+
+/* module parameters */
+#define QUIET  0       /* Default */
+#define VERBOSE        1       /* Verbose */
+#define DEBUG  2       /* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
+#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
+static int heartbeat = WATCHDOG_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+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) ")");
+
+/*
+ *     Internal functions
+ */
+
+static int send_command(int cmd, int *msb, int *lsb)
+{
+       int got_response, count;
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n",
+               cmd, *msb, *lsb);
+
+       spin_lock(&pcipcwd_private.io_lock);
+       /* If a command requires data it should be written first.
+        * Data for commands with 8 bits of data should be written to port 4.
+        * Commands with 16 bits of data, should be written as LSB to port 4
+        * and MSB to port 5.
+        * After the required data has been written then write the command to
+        * port 6. */
+       outb_p(*lsb, pcipcwd_private.io_addr + 4);
+       outb_p(*msb, pcipcwd_private.io_addr + 5);
+       outb_p(cmd, pcipcwd_private.io_addr + 6);
+
+       /* wait till the pci card processed the command, signaled by
+        * the WRSP bit in port 2 and give it a max. timeout of
+        * PCI_COMMAND_TIMEOUT to process */
+       got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
+       for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) {
+               mdelay(1);
+               got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP;
+       }
+
+       if (debug >= DEBUG) {
+               if (got_response) {
+                       printk(KERN_DEBUG PFX "time to process command was: %d ms\n",
+                               count);
+               } else {
+                       printk(KERN_DEBUG PFX "card did not respond on command!\n");
+               }
+       }
+
+       if (got_response) {
+               /* read back response */
+               *lsb = inb_p(pcipcwd_private.io_addr + 4);
+               *msb = inb_p(pcipcwd_private.io_addr + 5);
+
+               /* clear WRSP bit */
+               inb_p(pcipcwd_private.io_addr + 6);
+
+               if (debug >= DEBUG)
+                       printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
+                               cmd, *msb, *lsb);
+       }
+
+       spin_unlock(&pcipcwd_private.io_lock);
+
+       return got_response;
+}
+
+static inline void pcipcwd_check_temperature_support(void)
+{
+       if (inb_p(pcipcwd_private.io_addr) != 0xF0)
+               pcipcwd_private.supports_temp = 1;
+}
+
+static int pcipcwd_get_option_switches(void)
+{
+       int option_switches;
+
+       option_switches = inb_p(pcipcwd_private.io_addr + 3);
+       return option_switches;
+}
+
+static void pcipcwd_show_card_info(void)
+{
+       int got_fw_rev, fw_rev_major, fw_rev_minor;
+       char fw_ver_str[20];            /* The cards firmware version */
+       int option_switches;
+
+       got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
+       if (got_fw_rev) {
+               sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
+       } else {
+               sprintf(fw_ver_str, "<card no answer>");
+       }
+
+       /* Get switch settings */
+       option_switches = pcipcwd_get_option_switches();
+
+       printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n",
+               (int) pcipcwd_private.io_addr, fw_ver_str,
+               (pcipcwd_private.supports_temp ? "with" : "without"));
+
+       printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+               option_switches,
+               ((option_switches & 0x10) ? "ON" : "OFF"),
+               ((option_switches & 0x08) ? "ON" : "OFF"));
+
+       if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
+               printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n");
+
+       if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
+               printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
+
+       if (pcipcwd_private.boot_status == 0)
+               printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
+}
+
+static int pcipcwd_start(void)
+{
+       int stat_reg;
+
+       spin_lock(&pcipcwd_private.io_lock);
+       outb_p(0x00, pcipcwd_private.io_addr + 3);
+       udelay(1000);
+
+       stat_reg = inb_p(pcipcwd_private.io_addr + 2);
+       spin_unlock(&pcipcwd_private.io_lock);
+
+       if (stat_reg & WD_PCI_WDIS) {
+               printk(KERN_ERR PFX "Card timer not enabled\n");
+               return -1;
+       }
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "Watchdog started\n");
+
+       return 0;
+}
+
+static int pcipcwd_stop(void)
+{
+       int stat_reg;
+
+       spin_lock(&pcipcwd_private.io_lock);
+       outb_p(0xA5, pcipcwd_private.io_addr + 3);
+       udelay(1000);
+
+       outb_p(0xA5, pcipcwd_private.io_addr + 3);
+       udelay(1000);
+
+       stat_reg = inb_p(pcipcwd_private.io_addr + 2);
+       spin_unlock(&pcipcwd_private.io_lock);
+
+       if (!(stat_reg & WD_PCI_WDIS)) {
+               printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
+               return -1;
+       }
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
+       return 0;
+}
+
+static int pcipcwd_keepalive(void)
+{
+       /* Re-trigger watchdog by writing to port 0 */
+       spin_lock(&pcipcwd_private.io_lock);
+       outb_p(0x42, pcipcwd_private.io_addr);  /* send out any data */
+       spin_unlock(&pcipcwd_private.io_lock);
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
+       return 0;
+}
+
+static int pcipcwd_set_heartbeat(int t)
+{
+       int t_msb = t / 256;
+       int t_lsb = t % 256;
+
+       if ((t < 0x0001) || (t > 0xFFFF))
+               return -EINVAL;
+
+       /* Write new heartbeat to watchdog */
+       send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb);
+
+       heartbeat = t;
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+                      heartbeat);
+
+       return 0;
+}
+
+static int pcipcwd_get_status(int *status)
+{
+       int control_status;
+
+       *status=0;
+       control_status = inb_p(pcipcwd_private.io_addr + 1);
+       if (control_status & WD_PCI_WTRP)
+               *status |= WDIOF_CARDRESET;
+       if (control_status & WD_PCI_TTRP) {
+               *status |= WDIOF_OVERHEAT;
+               if (temp_panic)
+                       panic(PFX "Temperature overheat trip!\n");
+       }
+
+       if (debug >= DEBUG)
+               printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n",
+                      control_status);
+
+       return 0;
+}
+
+static int pcipcwd_clear_status(void)
+{
+       int control_status;
+       int msb;
+       int reset_counter;
+
+       if (debug >= VERBOSE)
+               printk(KERN_INFO PFX "clearing watchdog trip status & LED\n");
+
+       control_status = inb_p(pcipcwd_private.io_addr + 1);
+
+       if (debug >= DEBUG) {
+               printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+               printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+                      (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
+       }
+
+       /* clear trip status & LED and keep mode of relay 2 */
+       outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1);
+
+       /* clear reset counter */
+       msb=0;
+       reset_counter=0xff;
+       send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
+
+       if (debug >= DEBUG) {
+               printk(KERN_DEBUG PFX "reset count was: 0x%02x\n",
+                      reset_counter);
+       }
+
+       return 0;
+}
+
+static int pcipcwd_get_temperature(int *temperature)
+{
+       *temperature = 0;
+       if (!pcipcwd_private.supports_temp)
+               return -ENODEV;
+
+       spin_lock(&pcipcwd_private.io_lock);
+       *temperature = inb_p(pcipcwd_private.io_addr);
+       spin_unlock(&pcipcwd_private.io_lock);
+
+       /*
+        * Convert celsius to fahrenheit, since this was
+        * the decided 'standard' for this return value.
+        */
+       *temperature = (*temperature * 9 / 5) + 32;
+
+       if (debug >= DEBUG) {
+               printk(KERN_DEBUG PFX "temperature is: %d F\n",
+                      *temperature);
+       }
+
+       return 0;
+}
+
+static int pcipcwd_get_timeleft(int *time_left)
+{
+       int msb;
+       int lsb;
+
+       /* Read the time that's left before rebooting */
+       /* Note: if the board is not yet armed then we will read 0xFFFF */
+       send_command(CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
+
+       *time_left = (msb << 8) + lsb;
+
+       if (debug >= VERBOSE)
+               printk(KERN_DEBUG PFX "Time left before next reboot: %d\n",
+                      *time_left);
+
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t pcipcwd_write(struct file *file, const char __user *data,
+                            size_t len, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       expect_release = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if(get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_release = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               pcipcwd_keepalive();
+       }
+       return len;
+}
+
+static int pcipcwd_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_OVERHEAT |
+                                       WDIOF_CARDRESET |
+                                       WDIOF_KEEPALIVEPING |
+                                       WDIOF_SETTIMEOUT |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     1,
+               .identity =             WATCHDOG_DRIVER_NAME,
+       };
+
+       switch (cmd) {
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &ident,
+                               sizeof (ident)) ? -EFAULT : 0;
+
+               case WDIOC_GETSTATUS:
+               {
+                       int status;
+
+                       pcipcwd_get_status(&status);
+
+                       return put_user(status, p);
+               }
+
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(pcipcwd_private.boot_status, p);
+
+               case WDIOC_GETTEMP:
+               {
+                       int temperature;
+
+                       if (pcipcwd_get_temperature(&temperature))
+                               return -EFAULT;
+
+                       return put_user(temperature, p);
+               }
+
+               case WDIOC_KEEPALIVE:
+                       pcipcwd_keepalive();
+                       return 0;
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if (get_user (new_options, p))
+                               return -EFAULT;
+
+                       if (new_options & WDIOS_DISABLECARD) {
+                               if (pcipcwd_stop())
+                                       return -EIO;
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_ENABLECARD) {
+                               if (pcipcwd_start())
+                                       return -EIO;
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_TEMPPANIC) {
+                               temp_panic = 1;
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_heartbeat;
+
+                       if (get_user(new_heartbeat, p))
+                               return -EFAULT;
+
+                       if (pcipcwd_set_heartbeat(new_heartbeat))
+                           return -EINVAL;
+
+                       pcipcwd_keepalive();
+                       /* Fall */
+               }
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, p);
+
+               case WDIOC_GETTIMELEFT:
+               {
+                       int time_left;
+
+                       if (pcipcwd_get_timeleft(&time_left))
+                               return -EFAULT;
+
+                       return put_user(time_left, p);
+               }
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+static int pcipcwd_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+       if (test_and_set_bit(0, &is_active)) {
+               if (debug >= VERBOSE)
+                       printk(KERN_ERR PFX "Attempt to open already opened device.\n");
+               return -EBUSY;
+       }
+
+       /* Activate */
+       pcipcwd_start();
+       pcipcwd_keepalive();
+       return nonseekable_open(inode, file);
+}
+
+static int pcipcwd_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       if (expect_release == 42) {
+               pcipcwd_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               pcipcwd_keepalive();
+       }
+       expect_release = 0;
+       clear_bit(0, &is_active);
+       return 0;
+}
+
+/*
+ *     /dev/temperature handling
+ */
+
+static ssize_t pcipcwd_temp_read(struct file *file, char __user *data,
+                               size_t len, loff_t *ppos)
+{
+       int temperature;
+
+       if (pcipcwd_get_temperature(&temperature))
+               return -EFAULT;
+
+       if (copy_to_user (data, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+static int pcipcwd_temp_open(struct inode *inode, struct file *file)
+{
+       if (!pcipcwd_private.supports_temp)
+               return -ENODEV;
+
+       return nonseekable_open(inode, file);
+}
+
+static int pcipcwd_temp_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+/*
+ *     Notify system
+ */
+
+static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the WDT off */
+               pcipcwd_stop();
+       }
+
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations pcipcwd_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .write =        pcipcwd_write,
+       .ioctl =        pcipcwd_ioctl,
+       .open =         pcipcwd_open,
+       .release =      pcipcwd_release,
+};
+
+static struct miscdevice pcipcwd_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &pcipcwd_fops,
+};
+
+static const struct file_operations pcipcwd_temp_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .read =         pcipcwd_temp_read,
+       .open =         pcipcwd_temp_open,
+       .release =      pcipcwd_temp_release,
+};
+
+static struct miscdevice pcipcwd_temp_miscdev = {
+       .minor =        TEMP_MINOR,
+       .name =         "temperature",
+       .fops =         &pcipcwd_temp_fops,
+};
+
+static struct notifier_block pcipcwd_notifier = {
+       .notifier_call =        pcipcwd_notify_sys,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       int ret = -EIO;
+
+       cards_found++;
+       if (cards_found == 1)
+               printk(KERN_INFO PFX DRIVER_VERSION);
+
+       if (cards_found > 1) {
+               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               return -ENODEV;
+       }
+
+       if (pci_enable_device(pdev)) {
+               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
+               return -ENODEV;
+       }
+
+       if (pci_resource_start(pdev, 0) == 0x0000) {
+               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               ret = -ENODEV;
+               goto err_out_disable_device;
+       }
+
+       pcipcwd_private.pdev = pdev;
+       pcipcwd_private.io_addr = pci_resource_start(pdev, 0);
+
+       if (pci_request_regions(pdev, WATCHDOG_NAME)) {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       (int) pcipcwd_private.io_addr);
+               ret = -EIO;
+               goto err_out_disable_device;
+       }
+
+       /* get the boot_status */
+       pcipcwd_get_status(&pcipcwd_private.boot_status);
+
+       /* clear the "card caused reboot" flag */
+       pcipcwd_clear_status();
+
+       /* disable card */
+       pcipcwd_stop();
+
+       /* Check whether or not the card supports the temperature device */
+       pcipcwd_check_temperature_support();
+
+       /* Show info about the card itself */
+       pcipcwd_show_card_info();
+
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)];
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (pcipcwd_set_heartbeat(heartbeat)) {
+               pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
+               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
+                       WATCHDOG_HEARTBEAT);
+       }
+
+       ret = register_reboot_notifier(&pcipcwd_notifier);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               goto err_out_release_region;
+       }
+
+       if (pcipcwd_private.supports_temp) {
+               ret = misc_register(&pcipcwd_temp_miscdev);
+               if (ret != 0) {
+                       printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                               TEMP_MINOR, ret);
+                       goto err_out_unregister_reboot;
+               }
+       }
+
+       ret = misc_register(&pcipcwd_miscdev);
+       if (ret != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto err_out_misc_deregister;
+       }
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+
+       return 0;
+
+err_out_misc_deregister:
+       if (pcipcwd_private.supports_temp)
+               misc_deregister(&pcipcwd_temp_miscdev);
+err_out_unregister_reboot:
+       unregister_reboot_notifier(&pcipcwd_notifier);
+err_out_release_region:
+       pci_release_regions(pdev);
+err_out_disable_device:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+               pcipcwd_stop();
+
+       /* Deregister */
+       misc_deregister(&pcipcwd_miscdev);
+       if (pcipcwd_private.supports_temp)
+               misc_deregister(&pcipcwd_temp_miscdev);
+       unregister_reboot_notifier(&pcipcwd_notifier);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       cards_found--;
+}
+
+static struct pci_device_id pcipcwd_pci_tbl[] = {
+       { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { 0 },                  /* End of list */
+};
+MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
+
+static struct pci_driver pcipcwd_driver = {
+       .name           = WATCHDOG_NAME,
+       .id_table       = pcipcwd_pci_tbl,
+       .probe          = pcipcwd_card_init,
+       .remove         = __devexit_p(pcipcwd_card_exit),
+};
+
+static int __init pcipcwd_init_module(void)
+{
+       spin_lock_init(&pcipcwd_private.io_lock);
+
+       return pci_register_driver(&pcipcwd_driver);
+}
+
+static void __exit pcipcwd_cleanup_module(void)
+{
+       pci_unregister_driver(&pcipcwd_driver);
+
+       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+}
+
+module_init(pcipcwd_init_module);
+module_exit(pcipcwd_cleanup_module);
+
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
+MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
new file mode 100644 (file)
index 0000000..0f3fd6c
--- /dev/null
@@ -0,0 +1,824 @@
+/*
+ *     Berkshire USB-PC Watchdog Card Driver
+ *
+ *     (c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     Based on source code of the following authors:
+ *       Ken Hollis <kenji@bitgate.com>,
+ *       Alan Cox <alan@redhat.com>,
+ *       Matt Domsch <Matt_Domsch@dell.com>,
+ *       Rob Radez <rob@osinvestor.com>,
+ *       Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Thanks also to Simon Machell at Berkshire Products Inc. for
+ *     providing the test hardware. More info is available at
+ *     http://www.berkprod.com/ or http://www.pcwatchdog.com/
+ */
+
+#include <linux/module.h>      /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h>       /* For standard types (like size_t) */
+#include <linux/errno.h>       /* For the -ENODEV/... values */
+#include <linux/kernel.h>      /* For printk/panic/... */
+#include <linux/delay.h>       /* For mdelay function */
+#include <linux/miscdevice.h>  /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>    /* For the watchdog specific items */
+#include <linux/notifier.h>    /* For notifier support */
+#include <linux/reboot.h>      /* For reboot_notifier stuff */
+#include <linux/init.h>                /* For __init/__exit/... */
+#include <linux/fs.h>          /* For file operations */
+#include <linux/usb.h>         /* For USB functions */
+#include <linux/slab.h>                /* For kmalloc, ... */
+#include <linux/mutex.h>       /* For mutex locking */
+#include <linux/hid.h>         /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
+
+#include <asm/uaccess.h>       /* For copy_to_user/put_user/... */
+
+
+#ifdef CONFIG_USB_DEBUG
+       static int debug = 1;
+#else
+       static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0)
+
+
+/* Module and Version Information */
+#define DRIVER_VERSION "1.02"
+#define DRIVER_DATE "21 Jan 2007"
+#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
+#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
+#define DRIVER_LICENSE "GPL"
+#define DRIVER_NAME "pcwd_usb"
+#define PFX DRIVER_NAME ": "
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+
+/* Module Parameters */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+#define WATCHDOG_HEARTBEAT 0   /* default heartbeat = delay-time from dip-switches */
+static int heartbeat = WATCHDOG_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+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) ")");
+
+/* The vendor and product id's for the USB-PC Watchdog card */
+#define USB_PCWD_VENDOR_ID     0x0c98
+#define USB_PCWD_PRODUCT_ID    0x1140
+
+/* table of devices that work with this driver */
+static struct usb_device_id usb_pcwd_table [] = {
+       { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
+
+/* according to documentation max. time to process a command for the USB
+ * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
+#define USB_COMMAND_TIMEOUT    250
+
+/* Watchdog's internal commands */
+#define CMD_READ_TEMP                  0x02    /* Read Temperature; Re-trigger Watchdog */
+#define CMD_TRIGGER                    CMD_READ_TEMP
+#define CMD_GET_STATUS                 0x04    /* Get Status Information */
+#define CMD_GET_FIRMWARE_VERSION       0x08    /* Get Firmware Version */
+#define CMD_GET_DIP_SWITCH_SETTINGS    0x0c    /* Get Dip Switch Settings */
+#define CMD_READ_WATCHDOG_TIMEOUT      0x18    /* Read Current Watchdog Time */
+#define CMD_WRITE_WATCHDOG_TIMEOUT     0x19    /* Write Current Watchdog Time */
+#define CMD_ENABLE_WATCHDOG            0x30    /* Enable / Disable Watchdog */
+#define CMD_DISABLE_WATCHDOG           CMD_ENABLE_WATCHDOG
+
+/* Watchdog's Dip Switch heartbeat values */
+static const int heartbeat_tbl [] = {
+       5,      /* OFF-OFF-OFF  =  5 Sec  */
+       10,     /* OFF-OFF-ON   = 10 Sec  */
+       30,     /* OFF-ON-OFF   = 30 Sec  */
+       60,     /* OFF-ON-ON    =  1 Min  */
+       300,    /* ON-OFF-OFF   =  5 Min  */
+       600,    /* ON-OFF-ON    = 10 Min  */
+       1800,   /* ON-ON-OFF    = 30 Min  */
+       3600,   /* ON-ON-ON     =  1 hour */
+};
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
+
+/* some internal variables */
+static unsigned long is_active;
+static char expect_release;
+
+/* Structure to hold all of our device specific stuff */
+struct usb_pcwd_private {
+       struct usb_device *     udev;                   /* save off the usb device pointer */
+       struct usb_interface *  interface;              /* the interface for this device */
+
+       unsigned int            interface_number;       /* the interface number used for cmd's */
+
+       unsigned char *         intr_buffer;            /* the buffer to intr data */
+       dma_addr_t              intr_dma;               /* the dma address for the intr buffer */
+       size_t                  intr_size;              /* the size of the intr buffer */
+       struct urb *            intr_urb;               /* the urb used for the intr pipe */
+
+       unsigned char           cmd_command;            /* The command that is reported back */
+       unsigned char           cmd_data_msb;           /* The data MSB that is reported back */
+       unsigned char           cmd_data_lsb;           /* The data LSB that is reported back */
+       atomic_t                cmd_received;           /* true if we received a report after a command */
+
+       int                     exists;                 /* Wether or not the device exists */
+       struct mutex            mtx;                    /* locks this structure */
+};
+static struct usb_pcwd_private *usb_pcwd_device;
+
+/* prevent races between open() and disconnect() */
+static DEFINE_MUTEX(disconnect_mutex);
+
+/* local function prototypes */
+static int usb_pcwd_probe      (struct usb_interface *interface, const struct usb_device_id *id);
+static void usb_pcwd_disconnect        (struct usb_interface *interface);
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver usb_pcwd_driver = {
+       .name =         DRIVER_NAME,
+       .probe =        usb_pcwd_probe,
+       .disconnect =   usb_pcwd_disconnect,
+       .id_table =     usb_pcwd_table,
+};
+
+
+static void usb_pcwd_intr_done(struct urb *urb)
+{
+       struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context;
+       unsigned char *data = usb_pcwd->intr_buffer;
+       int retval;
+
+       switch (urb->status) {
+       case 0:                 /* success */
+               break;
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               return;
+       /* -EPIPE:  should clear the halt */
+       default:                /* error */
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               goto resubmit;
+       }
+
+       dbg("received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
+               data[0], data[1], data[2]);
+
+       usb_pcwd->cmd_command  = data[0];
+       usb_pcwd->cmd_data_msb = data[1];
+       usb_pcwd->cmd_data_lsb = data[2];
+
+       /* notify anyone waiting that the cmd has finished */
+       atomic_set (&usb_pcwd->cmd_received, 1);
+
+resubmit:
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n",
+                       retval);
+}
+
+static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd,
+       unsigned char *msb, unsigned char *lsb)
+{
+       int got_response, count;
+       unsigned char buf[6];
+
+       /* We will not send any commands if the USB PCWD device does not exist */
+       if ((!usb_pcwd) || (!usb_pcwd->exists))
+               return -1;
+
+       /* The USB PC Watchdog uses a 6 byte report format. The board currently uses
+        * only 3 of the six bytes of the report. */
+       buf[0] = cmd;                   /* Byte 0 = CMD */
+       buf[1] = *msb;                  /* Byte 1 = Data MSB */
+       buf[2] = *lsb;                  /* Byte 2 = Data LSB */
+       buf[3] = buf[4] = buf[5] = 0;   /* All other bytes not used */
+
+       dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
+               buf[0], buf[1], buf[2]);
+
+       atomic_set (&usb_pcwd->cmd_received, 0);
+
+       if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
+                       HID_REQ_SET_REPORT, HID_DT_REPORT,
+                       0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
+                       USB_COMMAND_TIMEOUT) != sizeof(buf)) {
+               dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
+       }
+       /* wait till the usb card processed the command,
+        * with a max. timeout of USB_COMMAND_TIMEOUT */
+       got_response = 0;
+       for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) {
+               mdelay(1);
+               if (atomic_read (&usb_pcwd->cmd_received))
+                       got_response = 1;
+       }
+
+       if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
+               /* read back response */
+               *msb = usb_pcwd->cmd_data_msb;
+               *lsb = usb_pcwd->cmd_data_lsb;
+       }
+
+       return got_response;
+}
+
+static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
+{
+       unsigned char msb = 0x00;
+       unsigned char lsb = 0x00;
+       int retval;
+
+       /* Enable Watchdog */
+       retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb);
+
+       if ((retval == 0) || (lsb == 0)) {
+               printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
+{
+       unsigned char msb = 0xA5;
+       unsigned char lsb = 0xC3;
+       int retval;
+
+       /* Disable Watchdog */
+       retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb);
+
+       if ((retval == 0) || (lsb != 0)) {
+               printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
+{
+       unsigned char dummy;
+
+       /* Re-trigger Watchdog */
+       usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
+
+       return 0;
+}
+
+static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
+{
+       unsigned char msb = t / 256;
+       unsigned char lsb = t % 256;
+
+       if ((t < 0x0001) || (t > 0xFFFF))
+               return -EINVAL;
+
+       /* Write new heartbeat to watchdog */
+       usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
+
+       heartbeat = t;
+       return 0;
+}
+
+static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature)
+{
+       unsigned char msb, lsb;
+
+       usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
+
+       /*
+        * Convert celsius to fahrenheit, since this was
+        * the decided 'standard' for this return value.
+        */
+       *temperature = (lsb * 9 / 5) + 32;
+
+       return 0;
+}
+
+static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left)
+{
+       unsigned char msb, lsb;
+
+       /* Read the time that's left before rebooting */
+       /* Note: if the board is not yet armed then we will read 0xFFFF */
+       usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
+
+       *time_left = (msb << 8) + lsb;
+
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
+                             size_t len, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       expect_release = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if(get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_release = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               usb_pcwd_keepalive(usb_pcwd_device);
+       }
+       return len;
+}
+
+static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_KEEPALIVEPING |
+                                       WDIOF_SETTIMEOUT |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     1,
+               .identity =             DRIVER_NAME,
+       };
+
+       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_GETTEMP:
+               {
+                       int temperature;
+
+                       if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
+                               return -EFAULT;
+
+                       return put_user(temperature, p);
+               }
+
+               case WDIOC_KEEPALIVE:
+                       usb_pcwd_keepalive(usb_pcwd_device);
+                       return 0;
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if (get_user (new_options, p))
+                               return -EFAULT;
+
+                       if (new_options & WDIOS_DISABLECARD) {
+                               usb_pcwd_stop(usb_pcwd_device);
+                               retval = 0;
+                       }
+
+                       if (new_options & WDIOS_ENABLECARD) {
+                               usb_pcwd_start(usb_pcwd_device);
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_heartbeat;
+
+                       if (get_user(new_heartbeat, p))
+                               return -EFAULT;
+
+                       if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
+                           return -EINVAL;
+
+                       usb_pcwd_keepalive(usb_pcwd_device);
+                       /* Fall */
+               }
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, p);
+
+               case WDIOC_GETTIMELEFT:
+               {
+                       int time_left;
+
+                       if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
+                               return -EFAULT;
+
+                       return put_user(time_left, p);
+               }
+
+               default:
+                       return -ENOTTY;
+       }
+}
+
+static int usb_pcwd_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+       if (test_and_set_bit(0, &is_active))
+               return -EBUSY;
+
+       /* Activate */
+       usb_pcwd_start(usb_pcwd_device);
+       usb_pcwd_keepalive(usb_pcwd_device);
+       return nonseekable_open(inode, file);
+}
+
+static int usb_pcwd_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       if (expect_release == 42) {
+               usb_pcwd_stop(usb_pcwd_device);
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               usb_pcwd_keepalive(usb_pcwd_device);
+       }
+       expect_release = 0;
+       clear_bit(0, &is_active);
+       return 0;
+}
+
+/*
+ *     /dev/temperature handling
+ */
+
+static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
+                               size_t len, loff_t *ppos)
+{
+       int temperature;
+
+       if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
+               return -EFAULT;
+
+       if (copy_to_user(data, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+/*
+ *     Notify system
+ */
+
+static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the WDT off */
+               usb_pcwd_stop(usb_pcwd_device);
+       }
+
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations usb_pcwd_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .write =        usb_pcwd_write,
+       .ioctl =        usb_pcwd_ioctl,
+       .open =         usb_pcwd_open,
+       .release =      usb_pcwd_release,
+};
+
+static struct miscdevice usb_pcwd_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &usb_pcwd_fops,
+};
+
+static const struct file_operations usb_pcwd_temperature_fops = {
+       .owner =        THIS_MODULE,
+       .llseek =       no_llseek,
+       .read =         usb_pcwd_temperature_read,
+       .open =         usb_pcwd_temperature_open,
+       .release =      usb_pcwd_temperature_release,
+};
+
+static struct miscdevice usb_pcwd_temperature_miscdev = {
+       .minor =        TEMP_MINOR,
+       .name =         "temperature",
+       .fops =         &usb_pcwd_temperature_fops,
+};
+
+static struct notifier_block usb_pcwd_notifier = {
+       .notifier_call =        usb_pcwd_notify_sys,
+};
+
+/**
+ *     usb_pcwd_delete
+ */
+static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd)
+{
+       usb_free_urb(usb_pcwd->intr_urb);
+       if (usb_pcwd->intr_buffer != NULL)
+               usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
+                               usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
+       kfree (usb_pcwd);
+}
+
+/**
+ *     usb_pcwd_probe
+ *
+ *     Called by the usb core when a new device is connected that it thinks
+ *     this driver might be interested in.
+ */
+static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct usb_pcwd_private *usb_pcwd = NULL;
+       int pipe, maxp;
+       int retval = -ENOMEM;
+       int got_fw_rev;
+       unsigned char fw_rev_major, fw_rev_minor;
+       char fw_ver_str[20];
+       unsigned char option_switches, dummy;
+
+       cards_found++;
+       if (cards_found > 1) {
+               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               return -ENODEV;
+       }
+
+       /* get the active interface descriptor */
+       iface_desc = interface->cur_altsetting;
+
+       /* check out that we have a HID device */
+       if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
+               printk(KERN_ERR PFX "The device isn't a Human Interface Device\n");
+               return -ENODEV;
+       }
+
+       /* check out the endpoint: it has to be Interrupt & IN */
+       endpoint = &iface_desc->endpoint[0].desc;
+
+       if (!((endpoint->bEndpointAddress & USB_DIR_IN) &&
+            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                               == USB_ENDPOINT_XFER_INT))) {
+               /* we didn't find a Interrupt endpoint with direction IN */
+               printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");
+               return -ENODEV;
+       }
+
+       /* get a handle to the interrupt data pipe */
+       pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+       maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+
+       /* allocate memory for our device and initialize it */
+       usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);
+       if (usb_pcwd == NULL) {
+               printk(KERN_ERR PFX "Out of memory\n");
+               goto error;
+       }
+
+       usb_pcwd_device = usb_pcwd;
+
+       mutex_init(&usb_pcwd->mtx);
+       usb_pcwd->udev = udev;
+       usb_pcwd->interface = interface;
+       usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
+       usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
+
+       /* set up the memory buffer's */
+       if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) {
+               printk(KERN_ERR PFX "Out of memory\n");
+               goto error;
+       }
+
+       /* allocate the urb's */
+       usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!usb_pcwd->intr_urb) {
+               printk(KERN_ERR PFX "Out of memory\n");
+               goto error;
+       }
+
+       /* initialise the intr urb's */
+       usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
+                       usb_pcwd->intr_buffer, usb_pcwd->intr_size,
+                       usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
+       usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
+       usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       /* register our interrupt URB with the USB system */
+       if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
+               printk(KERN_ERR PFX "Problem registering interrupt URB\n");
+               retval = -EIO; /* failure */
+               goto error;
+       }
+
+       /* The device exists and can be communicated with */
+       usb_pcwd->exists = 1;
+
+       /* disable card */
+       usb_pcwd_stop(usb_pcwd);
+
+       /* Get the Firmware Version */
+       got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
+       if (got_fw_rev) {
+               sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
+       } else {
+               sprintf(fw_ver_str, "<card no answer>");
+       }
+
+       printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
+               fw_ver_str);
+
+       /* Get switch settings */
+       usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches);
+
+       printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+               option_switches,
+               ((option_switches & 0x10) ? "ON" : "OFF"),
+               ((option_switches & 0x08) ? "ON" : "OFF"));
+
+       /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
+       if (heartbeat == 0)
+               heartbeat = heartbeat_tbl[(option_switches & 0x07)];
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
+               usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
+               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
+                       WATCHDOG_HEARTBEAT);
+       }
+
+       retval = register_reboot_notifier(&usb_pcwd_notifier);
+       if (retval != 0) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       retval);
+               goto error;
+       }
+
+       retval = misc_register(&usb_pcwd_temperature_miscdev);
+       if (retval != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       TEMP_MINOR, retval);
+               goto err_out_unregister_reboot;
+       }
+
+       retval = misc_register(&usb_pcwd_miscdev);
+       if (retval != 0) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, retval);
+               goto err_out_misc_deregister;
+       }
+
+       /* we can register the device now, as it is ready */
+       usb_set_intfdata (interface, usb_pcwd);
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+
+       return 0;
+
+err_out_misc_deregister:
+       misc_deregister(&usb_pcwd_temperature_miscdev);
+err_out_unregister_reboot:
+       unregister_reboot_notifier(&usb_pcwd_notifier);
+error:
+       if (usb_pcwd)
+               usb_pcwd_delete(usb_pcwd);
+       usb_pcwd_device = NULL;
+       return retval;
+}
+
+
+/**
+ *     usb_pcwd_disconnect
+ *
+ *     Called by the usb core when the device is removed from the system.
+ *
+ *     This routine guarantees that the driver will not submit any more urbs
+ *     by clearing dev->udev.
+ */
+static void usb_pcwd_disconnect(struct usb_interface *interface)
+{
+       struct usb_pcwd_private *usb_pcwd;
+
+       /* prevent races with open() */
+       mutex_lock(&disconnect_mutex);
+
+       usb_pcwd = usb_get_intfdata (interface);
+       usb_set_intfdata (interface, NULL);
+
+       mutex_lock(&usb_pcwd->mtx);
+
+       /* Stop the timer before we leave */
+       if (!nowayout)
+               usb_pcwd_stop(usb_pcwd);
+
+       /* We should now stop communicating with the USB PCWD device */
+       usb_pcwd->exists = 0;
+
+       /* Deregister */
+       misc_deregister(&usb_pcwd_miscdev);
+       misc_deregister(&usb_pcwd_temperature_miscdev);
+       unregister_reboot_notifier(&usb_pcwd_notifier);
+
+       mutex_unlock(&usb_pcwd->mtx);
+
+       /* Delete the USB PCWD device */
+       usb_pcwd_delete(usb_pcwd);
+
+       cards_found--;
+
+       mutex_unlock(&disconnect_mutex);
+
+       printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
+}
+
+
+
+/**
+ *     usb_pcwd_init
+ */
+static int __init usb_pcwd_init(void)
+{
+       int result;
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&usb_pcwd_driver);
+       if (result) {
+               printk(KERN_ERR PFX "usb_register failed. Error number %d\n",
+                   result);
+               return result;
+       }
+
+       printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION " (" DRIVER_DATE ")\n");
+       return 0;
+}
+
+
+/**
+ *     usb_pcwd_exit
+ */
+static void __exit usb_pcwd_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&usb_pcwd_driver);
+}
+
+
+module_init (usb_pcwd_init);
+module_exit (usb_pcwd_exit);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
new file mode 100644 (file)
index 0000000..22f8873
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * drivers/char/watchdog/pnx4008_wdt.c
+ *
+ * Watchdog driver for PNX4008 board
+ *
+ * Authors: Dmitry Chigirev <source@mvista.com>,
+ *         Vitaly Wool <vitalywool@gmail.com>
+ * Based on sa1100 driver,
+ * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
+ *
+ * 2005-2006 (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/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define MODULE_NAME "PNX4008-WDT: "
+
+/* WatchDog Timer - Chapter 23 Page 207 */
+
+#define DEFAULT_HEARTBEAT 19
+#define MAX_HEARTBEAT     60
+
+/* Watchdog timer register set definition */
+#define WDTIM_INT(p)     ((p) + 0x0)
+#define WDTIM_CTRL(p)    ((p) + 0x4)
+#define WDTIM_COUNTER(p) ((p) + 0x8)
+#define WDTIM_MCTRL(p)   ((p) + 0xC)
+#define WDTIM_MATCH0(p)  ((p) + 0x10)
+#define WDTIM_EMR(p)     ((p) + 0x14)
+#define WDTIM_PULSE(p)   ((p) + 0x18)
+#define WDTIM_RES(p)     ((p) + 0x1C)
+
+/* WDTIM_INT bit definitions */
+#define MATCH_INT      1
+
+/* WDTIM_CTRL bit definitions */
+#define COUNT_ENAB     1
+#define RESET_COUNT    (1<<1)
+#define DEBUG_EN       (1<<2)
+
+/* WDTIM_MCTRL bit definitions */
+#define MR0_INT        1
+#undef  RESET_COUNT0
+#define RESET_COUNT0   (1<<2)
+#define STOP_COUNT0    (1<<2)
+#define M_RES1         (1<<3)
+#define M_RES2         (1<<4)
+#define RESFRC1        (1<<5)
+#define RESFRC2        (1<<6)
+
+/* WDTIM_EMR bit definitions */
+#define EXT_MATCH0      1
+#define MATCH_OUTPUT_HIGH (2<<4)       /*a MATCH_CTRL setting */
+
+/* WDTIM_RES bit definitions */
+#define WDOG_RESET      1      /* read only */
+
+#define WDOG_COUNTER_RATE 13000000     /*the counter clock is 13 MHz fixed */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+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 unsigned long boot_status;
+
+static struct resource *wdt_mem;
+static void __iomem    *wdt_base;
+struct clk             *wdt_clk;
+
+static void wdt_enable(void)
+{
+       spin_lock(&io_lock);
+
+       if (wdt_clk)
+               clk_set_rate(wdt_clk, 1);
+
+       /* stop counter, initiate counter reset */
+       __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
+       /*wait for reset to complete. 100% guarantee event */
+       while (__raw_readl(WDTIM_COUNTER(wdt_base)))
+               cpu_relax();
+       /* internal and external reset, stop after that */
+       __raw_writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0,
+               WDTIM_MCTRL(wdt_base));
+       /* configure match output */
+       __raw_writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
+       /* clear interrupt, just in case */
+       __raw_writel(MATCH_INT, WDTIM_INT(wdt_base));
+       /* the longest pulse period 65541/(13*10^6) seconds ~ 5 ms. */
+       __raw_writel(0xFFFF, WDTIM_PULSE(wdt_base));
+       __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
+       /*enable counter, stop when debugger active */
+       __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
+
+       spin_unlock(&io_lock);
+}
+
+static void wdt_disable(void)
+{
+       spin_lock(&io_lock);
+
+       __raw_writel(0, WDTIM_CTRL(wdt_base));  /*stop counter */
+       if (wdt_clk)
+               clk_set_rate(wdt_clk, 0);
+
+       spin_unlock(&io_lock);
+}
+
+static int pnx4008_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+               return -EBUSY;
+
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       wdt_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t
+pnx4008_wdt_write(struct file *file, const char *data, size_t len,
+                 loff_t * ppos)
+{
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+                       }
+               }
+               wdt_enable();
+       }
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
+           WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = "PNX4008 Watchdog",
+};
+
+static int
+pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                 unsigned long arg)
+{
+       int ret = -ENOTTY;
+       int time;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user((struct watchdog_info *)arg, &ident,
+                                  sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, (int *)arg);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(boot_status, (int *)arg);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, (int *)arg);
+               if (ret)
+                       break;
+
+               if (time <= 0 || time > MAX_HEARTBEAT) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               heartbeat = time;
+               wdt_enable();
+               /* Fall through */
+
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(heartbeat, (int *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_enable();
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+static int pnx4008_wdt_release(struct inode *inode, struct file *file)
+{
+       if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+               printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
+
+       wdt_disable();
+       clear_bit(WDT_IN_USE, &wdt_status);
+       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+       return 0;
+}
+
+static const struct file_operations pnx4008_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = pnx4008_wdt_write,
+       .ioctl = pnx4008_wdt_ioctl,
+       .open = pnx4008_wdt_open,
+       .release = pnx4008_wdt_release,
+};
+
+static struct miscdevice pnx4008_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &pnx4008_wdt_fops,
+};
+
+static int pnx4008_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
+               "PNX4008 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 resouce\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 *)IO_ADDRESS(res->start);
+
+       wdt_clk = clk_get(&pdev->dev, "wdt_ck");
+       if (IS_ERR(wdt_clk)) {
+               ret = PTR_ERR(wdt_clk);
+               release_resource(wdt_mem);
+               kfree(wdt_mem);
+               goto out;
+       } else
+               clk_set_rate(wdt_clk, 1);
+
+       ret = misc_register(&pnx4008_wdt_miscdev);
+       if (ret < 0) {
+               printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
+               release_resource(wdt_mem);
+               kfree(wdt_mem);
+               clk_set_rate(wdt_clk, 0);
+       } else {
+               boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
+                   WDIOF_CARDRESET : 0;
+               wdt_disable();          /*disable for now */
+               set_bit(WDT_DEVICE_INITED, &wdt_status);
+       }
+
+out:
+       return ret;
+}
+
+static int pnx4008_wdt_remove(struct platform_device *pdev)
+{
+       misc_deregister(&pnx4008_wdt_miscdev);
+       if (wdt_clk) {
+               clk_set_rate(wdt_clk, 0);
+               clk_put(wdt_clk);
+               wdt_clk = NULL;
+       }
+       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 = pnx4008_wdt_probe,
+       .remove = pnx4008_wdt_remove,
+};
+
+static int __init pnx4008_wdt_init(void)
+{
+       return platform_driver_register(&platform_wdt_driver);
+}
+
+static void __exit pnx4008_wdt_exit(void)
+{
+       return platform_driver_unregister(&platform_wdt_driver);
+}
+
+module_init(pnx4008_wdt_init);
+module_exit(pnx4008_wdt_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("PNX4008 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_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+                "Set to 1 to keep watchdog running after device release");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
new file mode 100644 (file)
index 0000000..5c921e4
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ *  Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx
+ *  chips.
+ *
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/notifier.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <rm9k_wdt.h>
+
+
+#define CLOCK                  125000000
+#define MAX_TIMEOUT_SECONDS    32
+#define CPCCR                  0x0080
+#define CPGIG1SR               0x0044
+#define CPGIG1ER               0x0054
+
+
+/* Function prototypes */
+static irqreturn_t wdt_gpi_irqhdl(int, void *);
+static void wdt_gpi_start(void);
+static void wdt_gpi_stop(void);
+static void wdt_gpi_set_timeout(unsigned int);
+static int wdt_gpi_open(struct inode *, struct file *);
+static int wdt_gpi_release(struct inode *, struct file *);
+static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *);
+static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
+static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
+static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int);
+static int __init wdt_gpi_probe(struct device *);
+static int __exit wdt_gpi_remove(struct device *);
+
+
+static const char wdt_gpi_name[] = "wdt_gpi";
+static atomic_t opencnt;
+static int expect_close;
+static int locked;
+
+
+/* These are set from device resources */
+static void __iomem * wd_regs;
+static unsigned int wd_irq, wd_ctr;
+
+
+/* Module arguments */
+static int timeout = MAX_TIMEOUT_SECONDS;
+module_param(timeout, int, 0444);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static unsigned long resetaddr = 0xbffdc200;
+module_param(resetaddr, ulong, 0444);
+MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset");
+
+static unsigned long flagaddr = 0xbffdc104;
+module_param(flagaddr, ulong, 0444);
+MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to");
+
+static int powercycle;
+module_param(powercycle, bool, 0444);
+MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
+
+
+/* Kernel interfaces */
+static const struct file_operations fops = {
+       .owner          = THIS_MODULE,
+       .open           = wdt_gpi_open,
+       .release        = wdt_gpi_release,
+       .write          = wdt_gpi_write,
+       .unlocked_ioctl = wdt_gpi_ioctl,
+};
+
+static struct miscdevice miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = wdt_gpi_name,
+       .fops           = &fops,
+};
+
+static struct notifier_block wdt_gpi_shutdown = {
+       .notifier_call  = wdt_gpi_notify,
+};
+
+
+/* Interrupt handler */
+static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt)
+{
+       if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
+               return IRQ_NONE;
+       __raw_writel(0x1, wd_regs + 0x0008);
+
+
+       printk(KERN_CRIT "%s: watchdog expired - resetting system\n",
+               wdt_gpi_name);
+
+       *(volatile char *) flagaddr |= 0x01;
+       *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2;
+       iob();
+       while (1)
+               cpu_relax();
+}
+
+
+/* Watchdog functions */
+static void wdt_gpi_start(void)
+{
+       u32 reg;
+
+       lock_titan_regs();
+       reg = titan_readl(CPGIG1ER);
+       titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER);
+       iob();
+       unlock_titan_regs();
+}
+
+static void wdt_gpi_stop(void)
+{
+       u32 reg;
+
+       lock_titan_regs();
+       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
+       titan_writel(reg, CPCCR);
+       reg = titan_readl(CPGIG1ER);
+       titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER);
+       iob();
+       unlock_titan_regs();
+}
+
+static void wdt_gpi_set_timeout(unsigned int to)
+{
+       u32 reg;
+       const u32 wdval = (to * CLOCK) & ~0x0000000f;
+
+       lock_titan_regs();
+       reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
+       titan_writel(reg, CPCCR);
+       wmb();
+       __raw_writel(wdval, wd_regs + 0x0000);
+       wmb();
+       titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR);
+       wmb();
+       titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR);
+       iob();
+       unlock_titan_regs();
+}
+
+
+/* /dev/watchdog operations */
+static int wdt_gpi_open(struct inode *inode, struct file *file)
+{
+       int res;
+
+       if (unlikely(atomic_dec_if_positive(&opencnt) < 0))
+               return -EBUSY;
+
+       expect_close = 0;
+       if (locked) {
+               module_put(THIS_MODULE);
+               free_irq(wd_irq, &miscdev);
+               locked = 0;
+       }
+
+       res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
+                         wdt_gpi_name, &miscdev);
+       if (unlikely(res))
+               return res;
+
+       wdt_gpi_set_timeout(timeout);
+       wdt_gpi_start();
+
+       printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n",
+               wdt_gpi_name, timeout);
+       return nonseekable_open(inode, file);
+}
+
+static int wdt_gpi_release(struct inode *inode, struct file *file)
+{
+       if (nowayout) {
+               printk(KERN_INFO "%s: no way out - watchdog left running\n",
+                       wdt_gpi_name);
+               __module_get(THIS_MODULE);
+               locked = 1;
+       } else {
+               if (expect_close) {
+                       wdt_gpi_stop();
+                       free_irq(wd_irq, &miscdev);
+                       printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name);
+               } else {
+                       printk(KERN_CRIT "%s: unexpected close() -"
+                               " watchdog left running\n",
+                               wdt_gpi_name);
+                       wdt_gpi_set_timeout(timeout);
+                       __module_get(THIS_MODULE);
+                       locked = 1;
+               }
+       }
+
+       atomic_inc(&opencnt);
+       return 0;
+}
+
+static ssize_t
+wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o)
+{
+       char val;
+
+       wdt_gpi_set_timeout(timeout);
+       expect_close = (s > 0) && !get_user(val, d) && (val == 'V');
+       return s ? 1 : 0;
+}
+
+static long
+wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+       long res = -ENOTTY;
+       const long size = _IOC_SIZE(cmd);
+       int stat;
+       void __user *argp = (void __user *)arg;
+       static struct watchdog_info wdinfo = {
+               .identity               = "RM9xxx/GPI watchdog",
+               .firmware_version       = 0,
+               .options                = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+       };
+
+       if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE))
+               return -ENOTTY;
+
+       if ((_IOC_DIR(cmd) & _IOC_READ)
+           && !access_ok(VERIFY_WRITE, arg, size))
+               return -EFAULT;
+
+       if ((_IOC_DIR(cmd) & _IOC_WRITE)
+           && !access_ok(VERIFY_READ, arg, size))
+               return -EFAULT;
+
+       expect_close = 0;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               wdinfo.options = nowayout ?
+                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
+                       WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE;
+               res = __copy_to_user(argp, &wdinfo, size) ?  -EFAULT : size;
+               break;
+
+       case WDIOC_GETSTATUS:
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               stat = (*(volatile char *) flagaddr & 0x01)
+                       ? WDIOF_CARDRESET : 0;
+               res = __copy_to_user(argp, &stat, size) ?
+                       -EFAULT : size;
+               break;
+
+       case WDIOC_SETOPTIONS:
+               break;
+
+       case WDIOC_KEEPALIVE:
+               wdt_gpi_set_timeout(timeout);
+               res = size;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               {
+                       int val;
+                       if (unlikely(__copy_from_user(&val, argp, size))) {
+                               res = -EFAULT;
+                               break;
+                       }
+
+                       if (val > MAX_TIMEOUT_SECONDS)
+                               val = MAX_TIMEOUT_SECONDS;
+                       timeout = val;
+                       wdt_gpi_set_timeout(val);
+                       res = size;
+                       printk(KERN_INFO "%s: timeout set to %u seconds\n",
+                               wdt_gpi_name, timeout);
+               }
+               break;
+
+       case WDIOC_GETTIMEOUT:
+               res = __copy_to_user(argp, &timeout, size) ?
+                       -EFAULT : size;
+               break;
+       }
+
+       return res;
+}
+
+
+/* Shutdown notifier */
+static int
+wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+               wdt_gpi_stop();
+
+       return NOTIFY_DONE;
+}
+
+
+/* Init & exit procedures */
+static const struct resource *
+wdt_gpi_get_resource(struct platform_device *pdv, const char *name,
+                     unsigned int type)
+{
+       char buf[80];
+       if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
+               return NULL;
+       return platform_get_resource_byname(pdv, type, buf);
+}
+
+/* No hotplugging on the platform bus - use __init */
+static int __init wdt_gpi_probe(struct device *dev)
+{
+       int res;
+       struct platform_device * const pdv = to_platform_device(dev);
+       const struct resource
+               * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
+                                                 IORESOURCE_MEM),
+               * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ,
+                                                 IORESOURCE_IRQ),
+               * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER,
+                                                 0);
+
+       if (unlikely(!rr || !ri || !rc))
+               return -ENXIO;
+
+       wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start);
+       if (unlikely(!wd_regs))
+               return -ENOMEM;
+       wd_irq = ri->start;
+       wd_ctr = rc->start;
+       res = misc_register(&miscdev);
+       if (res)
+               iounmap(wd_regs);
+       else
+               register_reboot_notifier(&wdt_gpi_shutdown);
+       return res;
+}
+
+static int __exit wdt_gpi_remove(struct device *dev)
+{
+       int res;
+
+       unregister_reboot_notifier(&wdt_gpi_shutdown);
+       res = misc_deregister(&miscdev);
+       iounmap(wd_regs);
+       wd_regs = NULL;
+       return res;
+}
+
+
+/* Device driver init & exit */
+static struct device_driver wdt_gpi_driver = {
+       .name           = (char *) wdt_gpi_name,
+       .bus            = &platform_bus_type,
+       .owner          = THIS_MODULE,
+       .probe          = wdt_gpi_probe,
+       .remove         = __exit_p(wdt_gpi_remove),
+       .shutdown       = NULL,
+       .suspend        = NULL,
+       .resume         = NULL,
+};
+
+static int __init wdt_gpi_init_module(void)
+{
+       atomic_set(&opencnt, 1);
+       if (timeout > MAX_TIMEOUT_SECONDS)
+               timeout = MAX_TIMEOUT_SECONDS;
+       return driver_register(&wdt_gpi_driver);
+}
+
+static void __exit wdt_gpi_cleanup_module(void)
+{
+       driver_unregister(&wdt_gpi_driver);
+}
+
+module_init(wdt_gpi_init_module);
+module_exit(wdt_gpi_cleanup_module);
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
new file mode 100644 (file)
index 0000000..5d1c15f
--- /dev/null
@@ -0,0 +1,563 @@
+/* linux/drivers/char/watchdog/s3c2410_wdt.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Watchdog Timer Support
+ *
+ * Based on, softdog.c by Alan Cox,
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *     05-Oct-2004     BJD     Added semaphore init to stop crashes on open
+ *                             Fixed tmr_count / wdt_count confusion
+ *                             Added configurable debug
+ *
+ *     11-Jan-2005     BJD     Fixed divide-by-2 in timeout code
+ *
+ *     25-Jan-2005     DA      Added suspend/resume support
+ *                             Replaced reboot notifier with .shutdown method
+ *
+ *     10-Mar-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
+*/
+
+#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/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include <asm/arch/map.h>
+
+#undef S3C_VA_WATCHDOG
+#define S3C_VA_WATCHDOG (0)
+
+#include <asm/plat-s3c/regs-watchdog.h>
+
+#define PFX "s3c2410-wdt: "
+
+#define CONFIG_S3C2410_WATCHDOG_ATBOOT         (0)
+#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME   (15)
+
+static int nowayout    = WATCHDOG_NOWAYOUT;
+static int tmr_margin  = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
+static int tmr_atboot  = CONFIG_S3C2410_WATCHDOG_ATBOOT;
+static int soft_noboot = 0;
+static int debug       = 0;
+
+module_param(tmr_margin,  int, 0);
+module_param(tmr_atboot,  int, 0);
+module_param(nowayout,    int, 0);
+module_param(soft_noboot, int, 0);
+module_param(debug,      int, 0);
+
+MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")");
+
+MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set to 1, default=" __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
+
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
+
+MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)");
+
+
+typedef enum close_state {
+       CLOSE_STATE_NOT,
+       CLOSE_STATE_ALLOW=0x4021
+} close_state_t;
+
+static DECLARE_MUTEX(open_lock);
+
+static struct device    *wdt_dev;      /* platform device attached to */
+static struct resource *wdt_mem;
+static struct resource *wdt_irq;
+static struct clk      *wdt_clock;
+static void __iomem    *wdt_base;
+static unsigned int     wdt_count;
+static close_state_t    allow_close;
+
+/* watchdog control routines */
+
+#define DBG(msg...) do { \
+       if (debug) \
+               printk(KERN_INFO msg); \
+       } while(0)
+
+/* functions */
+
+static int s3c2410wdt_keepalive(void)
+{
+       writel(wdt_count, wdt_base + S3C2410_WTCNT);
+       return 0;
+}
+
+static int s3c2410wdt_stop(void)
+{
+       unsigned long wtcon;
+
+       wtcon = readl(wdt_base + S3C2410_WTCON);
+       wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);
+       writel(wtcon, wdt_base + S3C2410_WTCON);
+
+       return 0;
+}
+
+static int s3c2410wdt_start(void)
+{
+       unsigned long wtcon;
+
+       s3c2410wdt_stop();
+
+       wtcon = readl(wdt_base + S3C2410_WTCON);
+       wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;
+
+       if (soft_noboot) {
+               wtcon |= S3C2410_WTCON_INTEN;
+               wtcon &= ~S3C2410_WTCON_RSTEN;
+       } else {
+               wtcon &= ~S3C2410_WTCON_INTEN;
+               wtcon |= S3C2410_WTCON_RSTEN;
+       }
+
+       DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
+           __FUNCTION__, wdt_count, wtcon);
+
+       writel(wdt_count, wdt_base + S3C2410_WTDAT);
+       writel(wdt_count, wdt_base + S3C2410_WTCNT);
+       writel(wtcon, wdt_base + S3C2410_WTCON);
+
+       return 0;
+}
+
+static int s3c2410wdt_set_heartbeat(int timeout)
+{
+       unsigned int freq = clk_get_rate(wdt_clock);
+       unsigned int count;
+       unsigned int divisor = 1;
+       unsigned long wtcon;
+
+       if (timeout < 1)
+               return -EINVAL;
+
+       freq /= 128;
+       count = timeout * freq;
+
+       DBG("%s: count=%d, timeout=%d, freq=%d\n",
+           __FUNCTION__, count, timeout, freq);
+
+       /* if the count is bigger than the watchdog register,
+          then work out what we need to do (and if) we can
+          actually make this value
+       */
+
+       if (count >= 0x10000) {
+               for (divisor = 1; divisor <= 0x100; divisor++) {
+                       if ((count / divisor) < 0x10000)
+                               break;
+               }
+
+               if ((count / divisor) >= 0x10000) {
+                       dev_err(wdt_dev, "timeout %d too big\n", timeout);
+                       return -EINVAL;
+               }
+       }
+
+       tmr_margin = timeout;
+
+       DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
+           __FUNCTION__, timeout, divisor, count, count/divisor);
+
+       count /= divisor;
+       wdt_count = count;
+
+       /* update the pre-scaler */
+       wtcon = readl(wdt_base + S3C2410_WTCON);
+       wtcon &= ~S3C2410_WTCON_PRESCALE_MASK;
+       wtcon |= S3C2410_WTCON_PRESCALE(divisor-1);
+
+       writel(count, wdt_base + S3C2410_WTDAT);
+       writel(wtcon, wdt_base + S3C2410_WTCON);
+
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int s3c2410wdt_open(struct inode *inode, struct file *file)
+{
+       if(down_trylock(&open_lock))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       allow_close = CLOSE_STATE_NOT;
+
+       /* start the timer */
+       s3c2410wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+static int s3c2410wdt_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+
+       if (allow_close == CLOSE_STATE_ALLOW) {
+               s3c2410wdt_stop();
+       } else {
+               dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
+               s3c2410wdt_keepalive();
+       }
+
+       allow_close = CLOSE_STATE_NOT;
+       up(&open_lock);
+       return 0;
+}
+
+static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
+                               size_t len, loff_t *ppos)
+{
+       /*
+        *      Refresh the timer.
+        */
+       if(len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       allow_close = CLOSE_STATE_NOT;
+
+                       for (i = 0; i != len; i++) {
+                               char c;
+
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       allow_close = CLOSE_STATE_ALLOW;
+                       }
+               }
+
+               s3c2410wdt_keepalive();
+       }
+       return len;
+}
+
+#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
+
+static struct watchdog_info s3c2410_wdt_ident = {
+       .options          =     OPTIONS,
+       .firmware_version =     0,
+       .identity         =     "S3C2410 Watchdog",
+};
+
+
+static int s3c2410wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_margin;
+
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &s3c2410_wdt_ident,
+                               sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
+
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+
+               case WDIOC_KEEPALIVE:
+                       s3c2410wdt_keepalive();
+                       return 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_margin, p))
+                               return -EFAULT;
+
+                       if (s3c2410wdt_set_heartbeat(new_margin))
+                               return -EINVAL;
+
+                       s3c2410wdt_keepalive();
+                       return put_user(tmr_margin, p);
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(tmr_margin, p);
+       }
+}
+
+/* kernel interface */
+
+static const struct file_operations s3c2410wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = s3c2410wdt_write,
+       .ioctl          = s3c2410wdt_ioctl,
+       .open           = s3c2410wdt_open,
+       .release        = s3c2410wdt_release,
+};
+
+static struct miscdevice s3c2410wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &s3c2410wdt_fops,
+};
+
+/* interrupt handler code */
+
+static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
+{
+       dev_info(wdt_dev, "watchdog timer expired (irq)\n");
+
+       s3c2410wdt_keepalive();
+       return IRQ_HANDLED;
+}
+/* device interface */
+
+static int s3c2410wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct device *dev;
+       unsigned int wtcon;
+       int started = 0;
+       int ret;
+       int size;
+
+       DBG("%s: probe=%p\n", __FUNCTION__, pdev);
+
+       dev = &pdev->dev;
+       wdt_dev = &pdev->dev;
+
+       /* get the memory region for the watchdog timer */
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "no memory resource specified\n");
+               return -ENOENT;
+       }
+
+       size = (res->end-res->start)+1;
+       wdt_mem = request_mem_region(res->start, size, pdev->name);
+       if (wdt_mem == NULL) {
+               dev_err(dev, "failed to get memory region\n");
+               ret = -ENOENT;
+               goto err_req;
+       }
+
+       wdt_base = ioremap(res->start, size);
+       if (wdt_base == 0) {
+               dev_err(dev, "failed to ioremap() region\n");
+               ret = -EINVAL;
+               goto err_req;
+       }
+
+       DBG("probe: mapped wdt_base=%p\n", wdt_base);
+
+       wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (wdt_irq == NULL) {
+               dev_err(dev, "no irq resource specified\n");
+               ret = -ENOENT;
+               goto err_map;
+       }
+
+       ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
+       if (ret != 0) {
+               dev_err(dev, "failed to install irq (%d)\n", ret);
+               goto err_map;
+       }
+
+       wdt_clock = clk_get(&pdev->dev, "watchdog");
+       if (IS_ERR(wdt_clock)) {
+               dev_err(dev, "failed to find watchdog clock source\n");
+               ret = PTR_ERR(wdt_clock);
+               goto err_irq;
+       }
+
+       clk_enable(wdt_clock);
+
+       /* see if we can actually set the requested timer margin, and if
+        * not, try the default value */
+
+       if (s3c2410wdt_set_heartbeat(tmr_margin)) {
+               started = s3c2410wdt_set_heartbeat(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
+
+               if (started == 0) {
+                       dev_info(dev,"tmr_margin value out of range, default %d used\n",
+                              CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
+               } else {
+                       dev_info(dev, "default timer value is out of range, cannot start\n");
+               }
+       }
+
+       ret = misc_register(&s3c2410wdt_miscdev);
+       if (ret) {
+               dev_err(dev, "cannot register miscdev on minor=%d (%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto err_clk;
+       }
+
+       if (tmr_atboot && started == 0) {
+               dev_info(dev, "starting watchdog timer\n");
+               s3c2410wdt_start();
+       } else if (!tmr_atboot) {
+               /* if we're not enabling the watchdog, then ensure it is
+                * disabled if it has been left running from the bootloader
+                * or other source */
+
+               s3c2410wdt_stop();
+       }
+
+       /* print out a statement of readiness */
+
+       wtcon = readl(wdt_base + S3C2410_WTCON);
+
+       dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
+                (wtcon & S3C2410_WTCON_ENABLE) ?  "" : "in",
+                (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
+                (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
+       
+       return 0;
+
+ err_clk:
+       clk_disable(wdt_clock);
+       clk_put(wdt_clock);
+
+ err_irq:
+       free_irq(wdt_irq->start, pdev);
+
+ err_map:
+       iounmap(wdt_base);
+
+ err_req:
+       release_resource(wdt_mem);
+       kfree(wdt_mem);
+
+       return ret;
+}
+
+static int s3c2410wdt_remove(struct platform_device *dev)
+{
+       release_resource(wdt_mem);
+       kfree(wdt_mem);
+       wdt_mem = NULL;
+
+       free_irq(wdt_irq->start, dev);
+       wdt_irq = NULL;
+
+       clk_disable(wdt_clock);
+       clk_put(wdt_clock);
+       wdt_clock = NULL;
+
+       iounmap(wdt_base);
+       misc_deregister(&s3c2410wdt_miscdev);
+       return 0;
+}
+
+static void s3c2410wdt_shutdown(struct platform_device *dev)
+{
+       s3c2410wdt_stop();      
+}
+
+#ifdef CONFIG_PM
+
+static unsigned long wtcon_save;
+static unsigned long wtdat_save;
+
+static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state)
+{
+       /* Save watchdog state, and turn it off. */
+       wtcon_save = readl(wdt_base + S3C2410_WTCON);
+       wtdat_save = readl(wdt_base + S3C2410_WTDAT);
+
+       /* Note that WTCNT doesn't need to be saved. */
+       s3c2410wdt_stop();
+
+       return 0;
+}
+
+static int s3c2410wdt_resume(struct platform_device *dev)
+{
+       /* Restore watchdog state. */
+
+       writel(wtdat_save, wdt_base + S3C2410_WTDAT);
+       writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
+       writel(wtcon_save, wdt_base + S3C2410_WTCON);
+
+       printk(KERN_INFO PFX "watchdog %sabled\n",
+              (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+
+       return 0;
+}
+
+#else
+#define s3c2410wdt_suspend NULL
+#define s3c2410wdt_resume  NULL
+#endif /* CONFIG_PM */
+
+
+static struct platform_driver s3c2410wdt_driver = {
+       .probe          = s3c2410wdt_probe,
+       .remove         = s3c2410wdt_remove,
+       .shutdown       = s3c2410wdt_shutdown,
+       .suspend        = s3c2410wdt_suspend,
+       .resume         = s3c2410wdt_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "s3c2410-wdt",
+       },
+};
+
+
+static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
+
+static int __init watchdog_init(void)
+{
+       printk(banner);
+       return platform_driver_register(&s3c2410wdt_driver);
+}
+
+static void __exit watchdog_exit(void)
+{
+       platform_driver_unregister(&s3c2410wdt_driver);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, "
+             "Dimitry Andric <dimitry.andric@tomtom.com>");
+MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
new file mode 100644 (file)
index 0000000..3475f47
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *     Watchdog driver for the SA11x0/PXA2xx
+ *
+ *      (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *          Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 2000           Oleg Drokin <green@crimea.edu>
+ *
+ *      27/11/2000 Initial release
+ */
+#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>
+
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#define OSCR_FREQ              CLOCK_TICK_RATE
+
+static unsigned long sa1100wdt_users;
+static int pre_margin;
+static int boot_status;
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int sa1100dog_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(1,&sa1100wdt_users))
+               return -EBUSY;
+
+       /* Activate SA1100 Watchdog timer */
+       OSMR3 = OSCR + pre_margin;
+       OSSR = OSSR_M3;
+       OWER = OWER_WME;
+       OIER |= OIER_E3;
+       return nonseekable_open(inode, file);
+}
+
+/*
+ * The watchdog cannot be disabled.
+ *
+ * Previous comments suggested that turning off the interrupt by
+ * clearing OIER[E3] would prevent the watchdog timing out but this
+ * does not appear to be true (at least on the PXA255).
+ */
+static int sa1100dog_release(struct inode *inode, struct file *file)
+{
+       printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
+
+       clear_bit(1, &sa1100wdt_users);
+
+       return 0;
+}
+
+static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
+{
+       if (len)
+               /* Refresh OSMR3 timer. */
+               OSMR3 = OSCR + pre_margin;
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options        = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity       = "SA1100/PXA255 Watchdog",
+};
+
+static int sa1100dog_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int ret = -ENOTTY;
+       int time;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user(argp, &ident,
+                                  sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+               ret = put_user(0, p);
+               break;
+
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(boot_status, p);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, p);
+               if (ret)
+                       break;
+
+               if (time <= 0 || time > 255) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               pre_margin = OSCR_FREQ * time;
+               OSMR3 = OSCR + pre_margin;
+               /*fall through*/
+
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(pre_margin / OSCR_FREQ, p);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               OSMR3 = OSCR + pre_margin;
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+static const struct file_operations sa1100dog_fops =
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = sa1100dog_write,
+       .ioctl          = sa1100dog_ioctl,
+       .open           = sa1100dog_open,
+       .release        = sa1100dog_release,
+};
+
+static struct miscdevice sa1100dog_miscdev =
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &sa1100dog_fops,
+};
+
+static int margin __initdata = 60;             /* (secs) Default is 1 minute */
+
+static int __init sa1100dog_init(void)
+{
+       int ret;
+
+       /*
+        * Read the reset status, and save it for later.  If
+        * we suspend, RCSR will be cleared, and the watchdog
+        * reset reason will be lost.
+        */
+       boot_status = (RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0;
+       pre_margin = OSCR_FREQ * margin;
+
+       ret = misc_register(&sa1100dog_miscdev);
+       if (ret == 0)
+               printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
+                      margin);
+       return ret;
+}
+
+static void __exit sa1100dog_exit(void)
+{
+       misc_deregister(&sa1100dog_miscdev);
+}
+
+module_init(sa1100dog_init);
+module_exit(sa1100dog_exit);
+
+MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
+MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
+
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c
new file mode 100644 (file)
index 0000000..e4f3cb6
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *     60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x
+ *
+ *      Based on acquirewdt.c by Alan Cox.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     The author does NOT admit liability nor provide warranty for
+ *     any of this software. This material is provided "AS-IS" in
+ *     the hope that it may be useful for others.
+ *
+ *     (c) Copyright 2000    Jakob Oestergaard <jakob@unthought.net>
+ *
+ *           12/4 - 2000      [Initial revision]
+ *           25/4 - 2000      Added /dev/watchdog support
+ *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
+ *           12/4 - 2002      [rob@osinvestor.com] eliminate fop_read
+ *                            fix possible wdt_is_open race
+ *                            add CONFIG_WATCHDOG_NOWAYOUT support
+ *                            remove lock_kernel/unlock_kernel pairs
+ *                            added KERN_* to printk's
+ *                            got rid of extraneous comments
+ *                            changed watchdog_info to correctly reflect what the driver offers
+ *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
+ *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
+ *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
+ *                            use module_param
+ *                            made timeout (the emulated heartbeat) a module_param
+ *                            made the keepalive ping an internal subroutine
+ *                            made wdt_stop and wdt_start module params
+ *                            added extra printk's for startup problems
+ *                            added MODULE_AUTHOR and MODULE_DESCRIPTION info
+ *
+ *
+ *  This WDT driver is different from the other Linux WDT
+ *  drivers in the following ways:
+ *  *)  The driver will ping the watchdog by itself, because this
+ *      particular WDT has a very short timeout (one second) and it
+ *      would be insane to count on any userspace daemon always
+ *      getting scheduled within that time frame.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define OUR_NAME "sbc60xxwdt"
+#define PFX OUR_NAME ": "
+
+/*
+ * You must set these - The driver cannot probe for the settings
+ */
+
+static int wdt_stop = 0x45;
+module_param(wdt_stop, int, 0);
+MODULE_PARM_DESC(wdt_stop, "SBC60xx WDT 'stop' io port (default 0x45)");
+
+static int wdt_start = 0x443;
+module_param(wdt_start, int, 0);
+MODULE_PARM_DESC(wdt_start, "SBC60xx WDT 'start' io port (default 0x443)");
+
+/*
+ * The 60xx board can use watchdog timeout values from one second
+ * to several minutes.  The default is one second, so if we reset
+ * the watchdog every ~250ms we should be safe.
+ */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 30 seconds.
+ * If the daemon pulses us every 25 seconds, we can still afford
+ * a 5 second scheduling delay on the (high priority) daemon. That
+ * should be sufficient for a box under any load.
+ */
+
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+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 wdt_timer_ping(unsigned long);
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static char wdt_expect_close;
+
+/*
+ *     Whack the dog
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT
+        */
+       if(time_before(jiffies, next_heartbeat))
+       {
+               /* Ping the WDT by reading from wdt_start */
+               inb_p(wdt_start);
+               /* Re-set the timer interval */
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
+       } else {
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+/*
+ * Utility routines
+ */
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + (timeout * HZ);
+
+       /* Start the timer */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+}
+
+static void wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer(&timer);
+       inb_p(wdt_stop);
+       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+}
+
+static void wdt_keepalive(void)
+{
+       /* user land ping */
+       next_heartbeat = jiffies + (timeout * HZ);
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count)
+       {
+               if (!nowayout)
+               {
+                       size_t ofs;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       wdt_expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for(ofs = 0; ofs != count; ofs++)
+                       {
+                               char c;
+                               if(get_user(c, buf+ofs))
+                                       return -EFAULT;
+                               if(c == 'V')
+                                       wdt_expect_close = 42;
+                       }
+               }
+
+               /* Well, anyhow someone wrote to us, we should return that favour */
+               wdt_keepalive();
+       }
+       return count;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       /* Just in case we're already talking to someone... */
+       if(test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Good, fire up the show */
+       wdt_startup();
+       return nonseekable_open(inode, file);
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(wdt_expect_close == 42)
+               wdt_turnoff();
+       else {
+               del_timer(&timer);
+               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
+       }
+       clear_bit(0, &wdt_is_open);
+       wdt_expect_close = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident=
+       {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "SBC60xx",
+       };
+
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               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:
+                       wdt_keepalive();
+                       return 0;
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if(get_user(new_options, p))
+                               return -EFAULT;
+
+                       if(new_options & WDIOS_DISABLECARD) {
+                               wdt_turnoff();
+                               retval = 0;
+                       }
+
+                       if(new_options & WDIOS_ENABLECARD) {
+                               wdt_startup();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_timeout;
+
+                       if(get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       wdt_keepalive();
+                       /* Fall through */
+               }
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout, p);
+       }
+}
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = fop_write,
+       .open           = fop_open,
+       .release        = fop_close,
+       .ioctl          = fop_ioctl,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &wdt_fops,
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+               wdt_turnoff();
+       return NOTIFY_DONE;
+}
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier=
+{
+       .notifier_call = wdt_notify_sys,
+};
+
+static void __exit sbc60xxwdt_unload(void)
+{
+       wdt_turnoff();
+
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+
+       unregister_reboot_notifier(&wdt_notifier);
+       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
+               release_region(wdt_stop,1);
+       release_region(wdt_start,1);
+}
+
+static int __init sbc60xxwdt_init(void)
+{
+       int rc = -EBUSY;
+
+       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
+       {
+               timeout = WATCHDOG_TIMEOUT;
+               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
+                       timeout);
+       }
+
+       if (!request_region(wdt_start, 1, "SBC 60XX WDT"))
+       {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_start);
+               rc = -EIO;
+               goto err_out;
+       }
+
+       /* We cannot reserve 0x45 - the kernel already has! */
+       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
+       {
+               if (!request_region(wdt_stop, 1, "SBC 60XX WDT"))
+               {
+                       printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                               wdt_stop);
+                       rc = -EIO;
+                       goto err_out_region1;
+               }
+       }
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       wdt_miscdev.minor, rc);
+               goto err_out_region2;
+       }
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_miscdev;
+       }
+
+       printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out_region2:
+       if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
+               release_region(wdt_stop,1);
+err_out_region1:
+       release_region(wdt_start,1);
+err_out:
+       return rc;
+}
+
+module_init(sbc60xxwdt_init);
+module_exit(sbc60xxwdt_unload);
+
+MODULE_AUTHOR("Jakob Oestergaard <jakob@unthought.net>");
+MODULE_DESCRIPTION("60xx Single Board Computer Watchdog Timer driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
new file mode 100644 (file)
index 0000000..285d852
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ *     SBC8360 Watchdog driver
+ *
+ *     (c) Copyright 2005 Webcon, Inc.
+ *
+ *     Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ *      on acquirewdt.c which is based on wdt.c.
+ *
+ *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ *      Based on advantechwdt.c which is based on acquirewdt.c which
+ *       is based on wdt.c.
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     Based on acquirewdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Added timeout module option to override default
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H.  To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H.  To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ *             N
+ *     M |     1       2       3       4
+ *     --|----------------------------------
+ *     0 |     0.5s    5s      50s     100s
+ *     1 |     1s      10s     100s    200s
+ *     2 |     1.5s    15s     150s    300s
+ *     3 |     2s      20s     200s    400s
+ *     4 |     2.5s    25s     250s    500s
+ *     5 |     3s      30s     300s    600s
+ *     6 |     3.5s    35s     350s    700s
+ *     7 |     4s      40s     400s    800s
+ *     8 |     4.5s    45s     450s    900s
+ *     9 |     5s      50s     500s    1000s
+ *     A |     5.5s    55s     550s    1100s
+ *     B |     6s      60s     600s    1200s
+ *     C |     6.5s    65s     650s    1300s
+ *     D |     7s      70s     700s    1400s
+ *     E |     7.5s    75s     750s    1500s
+ *     F |     8s      80s     800s    1600s
+ *
+ * Another way to say the same things is:
+ *  For N=1, Timeout = (M+1) * 0.5s
+ *  For N=2, Timeout = (M+1) * 5s
+ *  For N=3, Timeout = (M+1) * 50s
+ *  For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+       {0, 1},                 /* 0  = 0.5s */
+       {1, 1},                 /* 1  = 1s   */
+       {2, 1},                 /* 2  = 1.5s */
+       {3, 1},                 /* 3  = 2s   */
+       {4, 1},                 /* 4  = 2.5s */
+       {5, 1},                 /* 5  = 3s   */
+       {6, 1},                 /* 6  = 3.5s */
+       {7, 1},                 /* 7  = 4s   */
+       {8, 1},                 /* 8  = 4.5s */
+       {9, 1},                 /* 9  = 5s   */
+       {0xA, 1},               /* 10 = 5.5s */
+       {0xB, 1},               /* 11 = 6s   */
+       {0xC, 1},               /* 12 = 6.5s */
+       {0xD, 1},               /* 13 = 7s   */
+       {0xE, 1},               /* 14 = 7.5s */
+       {0xF, 1},               /* 15 = 8s   */
+       {0, 2},                 /* 16 = 5s  */
+       {1, 2},                 /* 17 = 10s */
+       {2, 2},                 /* 18 = 15s */
+       {3, 2},                 /* 19 = 20s */
+       {4, 2},                 /* 20 = 25s */
+       {5, 2},                 /* 21 = 30s */
+       {6, 2},                 /* 22 = 35s */
+       {7, 2},                 /* 23 = 40s */
+       {8, 2},                 /* 24 = 45s */
+       {9, 2},                 /* 25 = 50s */
+       {0xA, 2},               /* 26 = 55s */
+       {0xB, 2},               /* 27 = 60s */
+       {0xC, 2},               /* 28 = 65s */
+       {0xD, 2},               /* 29 = 70s */
+       {0xE, 2},               /* 30 = 75s */
+       {0xF, 2},               /* 31 = 80s */
+       {0, 3},                 /* 32 = 50s  */
+       {1, 3},                 /* 33 = 100s */
+       {2, 3},                 /* 34 = 150s */
+       {3, 3},                 /* 35 = 200s */
+       {4, 3},                 /* 36 = 250s */
+       {5, 3},                 /* 37 = 300s */
+       {6, 3},                 /* 38 = 350s */
+       {7, 3},                 /* 39 = 400s */
+       {8, 3},                 /* 40 = 450s */
+       {9, 3},                 /* 41 = 500s */
+       {0xA, 3},               /* 42 = 550s */
+       {0xB, 3},               /* 43 = 600s */
+       {0xC, 3},               /* 44 = 650s */
+       {0xD, 3},               /* 45 = 700s */
+       {0xE, 3},               /* 46 = 750s */
+       {0xF, 3},               /* 47 = 800s */
+       {0, 4},                 /* 48 = 100s */
+       {1, 4},                 /* 49 = 200s */
+       {2, 4},                 /* 50 = 300s */
+       {3, 4},                 /* 51 = 400s */
+       {4, 4},                 /* 52 = 500s */
+       {5, 4},                 /* 53 = 600s */
+       {6, 4},                 /* 54 = 700s */
+       {7, 4},                 /* 55 = 800s */
+       {8, 4},                 /* 56 = 900s */
+       {9, 4},                 /* 57 = 1000s */
+       {0xA, 4},               /* 58 = 1100s */
+       {0xB, 4},               /* 59 = 1200s */
+       {0xC, 4},               /* 60 = 1300s */
+       {0xD, 4},               /* 61 = 1400s */
+       {0xE, 4},               /* 62 = 1500s */
+       {0xF, 4}                /* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/*
+ *     Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+       /* Enable the watchdog */
+       outb(0x0A, SBC8360_ENABLE);
+       msleep_interruptible(100);
+       outb(0x0B, SBC8360_ENABLE);
+       msleep_interruptible(100);
+       /* Set timeout multiplier */
+       outb(wd_multiplier, SBC8360_ENABLE);
+       msleep_interruptible(100);
+       /* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+       /* Write the base timer register */
+       outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+                            size_t count, loff_t * ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               sbc8360_ping();
+       }
+       return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+       spin_lock(&sbc8360_lock);
+       if (test_and_set_bit(0, &sbc8360_is_open)) {
+               spin_unlock(&sbc8360_lock);
+               return -EBUSY;
+       }
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate and ping once to start the countdown */
+       spin_unlock(&sbc8360_lock);
+       sbc8360_activate();
+       sbc8360_ping();
+       return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+       spin_lock(&sbc8360_lock);
+       if (expect_close == 42)
+               outb(0, SBC8360_ENABLE);
+       else
+               printk(KERN_CRIT PFX
+                      "SBC8360 device closed unexpectedly.  SBC8360 will not stop!\n");
+
+       clear_bit(0, &sbc8360_is_open);
+       expect_close = 0;
+       spin_unlock(&sbc8360_lock);
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+                             void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Disable the SBC8360 Watchdog */
+               outb(0, SBC8360_ENABLE);
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations sbc8360_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = sbc8360_write,
+       .open = sbc8360_open,
+       .release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &sbc8360_fops,
+};
+
+/*
+ *     The SBC8360 needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+       .notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+       int res;
+       unsigned long int mseconds = 60000;
+
+       if (timeout < 0 || timeout > 63) {
+               printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+               res = -EINVAL;
+               goto out;
+       }
+
+       if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+               printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+                      SBC8360_ENABLE);
+               res = -EIO;
+               goto out;
+       }
+       if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+               printk(KERN_ERR PFX
+                      "BASETIME method I/O %X is not available.\n",
+                      SBC8360_BASETIME);
+               res = -EIO;
+               goto out_nobasetimereg;
+       }
+
+       res = register_reboot_notifier(&sbc8360_notifier);
+       if (res) {
+               printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+               goto out_noreboot;
+       }
+
+       spin_lock_init(&sbc8360_lock);
+       res = misc_register(&sbc8360_miscdev);
+       if (res) {
+               printk(KERN_ERR PFX "failed to register misc device\n");
+               goto out_nomisc;
+       }
+
+       wd_margin = wd_times[timeout][0];
+       wd_multiplier = wd_times[timeout][1];
+
+       if (wd_multiplier == 1)
+               mseconds = (wd_margin + 1) * 500;
+       else if (wd_multiplier == 2)
+               mseconds = (wd_margin + 1) * 5000;
+       else if (wd_multiplier == 3)
+               mseconds = (wd_margin + 1) * 50000;
+       else if (wd_multiplier == 4)
+               mseconds = (wd_margin + 1) * 100000;
+
+       /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+       printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+       return 0;
+
+      out_nomisc:
+       unregister_reboot_notifier(&sbc8360_notifier);
+      out_noreboot:
+       release_region(SBC8360_BASETIME, 1);
+      out_nobasetimereg:
+       release_region(SBC8360_ENABLE, 1);
+      out:
+       return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+       misc_deregister(&sbc8360_miscdev);
+       unregister_reboot_notifier(&sbc8360_notifier);
+       release_region(SBC8360_ENABLE, 1);
+       release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.01");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of sbc8360.c */
diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
new file mode 100644 (file)
index 0000000..82cbd88
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *     SBC EPX C3 0.1  A Hardware Watchdog Device for the Winsystems EPX-C3
+ *     single board computer
+ *
+ *     (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights
+ *     Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     based on softdog.c by Alan Cox <alan@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define PFX "epx_c3: "
+static int epx_c3_alive;
+
+#define WATCHDOG_TIMEOUT 1             /* 1 sec default timeout */
+
+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) ")");
+
+#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
+#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
+
+static void epx_c3_start(void)
+{
+       outb(1, EPXC3_WATCHDOG_CTL_REG);
+}
+
+static void epx_c3_stop(void)
+{
+
+       outb(0, EPXC3_WATCHDOG_CTL_REG);
+
+       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+}
+
+static void epx_c3_pet(void)
+{
+       outb(1, EPXC3_WATCHDOG_PET_REG);
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int epx_c3_open(struct inode *inode, struct file *file)
+{
+       if (epx_c3_alive)
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Activate timer */
+       epx_c3_start();
+       epx_c3_pet();
+
+       epx_c3_alive = 1;
+       printk(KERN_INFO "Started watchdog timer.\n");
+
+       return nonseekable_open(inode, file);
+}
+
+static int epx_c3_release(struct inode *inode, struct file *file)
+{
+       /* Shut off the timer.
+        * Lock it in if it's a module and we defined ...NOWAYOUT */
+       if (!nowayout)
+               epx_c3_stop();          /* Turn the WDT off */
+
+       epx_c3_alive = 0;
+
+       return 0;
+}
+
+static ssize_t epx_c3_write(struct file *file, const char __user *data,
+                       size_t len, loff_t *ppos)
+{
+       /* Refresh the timer. */
+       if (len)
+               epx_c3_pet();
+       return len;
+}
+
+static int epx_c3_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       int options, retval = -EINVAL;
+       int __user *argp = (void __user *)arg;
+       static struct watchdog_info ident = {
+               .options                = WDIOF_KEEPALIVEPING |
+                                         WDIOF_MAGICCLOSE,
+               .firmware_version       = 0,
+               .identity               = "Winsystems EPX-C3 H/W Watchdog",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &ident, sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, argp);
+       case WDIOC_KEEPALIVE:
+               epx_c3_pet();
+               return 0;
+       case WDIOC_GETTIMEOUT:
+               return put_user(WATCHDOG_TIMEOUT, argp);
+       case WDIOC_SETOPTIONS:
+               if (get_user(options, argp))
+                       return -EFAULT;
+
+               if (options & WDIOS_DISABLECARD) {
+                       epx_c3_stop();
+                       retval = 0;
+               }
+
+               if (options & WDIOS_ENABLECARD) {
+                       epx_c3_start();
+                       retval = 0;
+               }
+
+               return retval;
+       default:
+               return -ENOTTY;
+       }
+}
+
+static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
+                               void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+               epx_c3_stop();          /* Turn the WDT off */
+
+       return NOTIFY_DONE;
+}
+
+static const struct file_operations epx_c3_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = epx_c3_write,
+       .ioctl          = epx_c3_ioctl,
+       .open           = epx_c3_open,
+       .release        = epx_c3_release,
+};
+
+static struct miscdevice epx_c3_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &epx_c3_fops,
+};
+
+static struct notifier_block epx_c3_notifier = {
+       .notifier_call = epx_c3_notify_sys,
+};
+
+static const char banner[] __initdata =
+    KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
+
+static int __init watchdog_init(void)
+{
+       int ret;
+
+       if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
+               return -EBUSY;
+
+       ret = register_reboot_notifier(&epx_c3_notifier);
+       if (ret) {
+               printk(KERN_ERR PFX "cannot register reboot notifier "
+                       "(err=%d)\n", ret);
+               goto out;
+       }
+
+       ret = misc_register(&epx_c3_miscdev);
+       if (ret) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
+                       "(err=%d)\n", WATCHDOG_MINOR, ret);
+               unregister_reboot_notifier(&epx_c3_notifier);
+               goto out;
+       }
+
+       printk(banner);
+
+       return 0;
+
+out:
+       release_region(EPXC3_WATCHDOG_CTL_REG, 2);
+       return ret;
+}
+
+static void __exit watchdog_exit(void)
+{
+       misc_deregister(&epx_c3_miscdev);
+       unregister_reboot_notifier(&epx_c3_notifier);
+       release_region(EPXC3_WATCHDOG_CTL_REG, 2);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
+MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC.  Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems!  It writes to IO ports 0x1ee and 0x1ef!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
new file mode 100644 (file)
index 0000000..9670d47
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ *     National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
+ *     (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>,
+ *                     All Rights Reserved.
+ *     Based on wdt.c and wdt977.c by Alan Cox and Woody Suwalski respectively.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     The author(s) of this software shall not be held liable for damages
+ *     of any nature resulting due to the use of this software. This
+ *     software is provided AS-IS with no warranties.
+ *
+ *     Changelog:
+ *     20020220 Zwane Mwaikambo        Code based on datasheet, no hardware.
+ *     20020221 Zwane Mwaikambo        Cleanups as suggested by Jeff Garzik and Alan Cox.
+ *     20020222 Zwane Mwaikambo        Added probing.
+ *     20020225 Zwane Mwaikambo        Added ISAPNP support.
+ *     20020412 Rob Radez              Broke out start/stop functions
+ *              <rob@osinvestor.com>   Return proper status instead of temperature warning
+ *                                     Add WDIOC_GETBOOTSTATUS and WDIOC_SETOPTIONS ioctls
+ *                                     Fix CONFIG_WATCHDOG_NOWAYOUT
+ *     20020530 Joel Becker            Add Matt Domsch's nowayout module option
+ *     20030116 Adam Belay             Updated to the latest pnp code
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pnp.h>
+#include <linux/fs.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define SC1200_MODULE_VER      "build 20020303"
+#define SC1200_MODULE_NAME     "sc1200wdt"
+#define PFX                    SC1200_MODULE_NAME ": "
+
+#define        MAX_TIMEOUT     255     /* 255 minutes */
+#define PMIR           (io)    /* Power Management Index Register */
+#define PMDR           (io+1)  /* Power Management Data Register */
+
+/* Data Register indexes */
+#define FER1           0x00    /* Function enable register 1 */
+#define FER2           0x01    /* Function enable register 2 */
+#define PMC1           0x02    /* Power Management Ctrl 1 */
+#define PMC2           0x03    /* Power Management Ctrl 2 */
+#define PMC3           0x04    /* Power Management Ctrl 3 */
+#define WDTO           0x05    /* Watchdog timeout register */
+#define        WDCF            0x06    /* Watchdog config register */
+#define WDST           0x07    /* Watchdog status register */
+
+/* WDCF bitfields - which devices assert WDO */
+#define KBC_IRQ                0x01    /* Keyboard Controller */
+#define MSE_IRQ                0x02    /* Mouse */
+#define UART1_IRQ      0x03    /* Serial0 */
+#define UART2_IRQ      0x04    /* Serial1 */
+/* 5 -7 are reserved */
+
+static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER;
+static int timeout = 1;
+static int io = -1;
+static int io_len = 2;         /* for non plug and play */
+static struct semaphore open_sem;
+static char expect_close;
+static spinlock_t sc1200wdt_lock;      /* io port access serialisation */
+
+#if defined CONFIG_PNP
+static int isapnp = 1;
+static struct pnp_dev *wdt_dev;
+
+module_param(isapnp, int, 0);
+MODULE_PARM_DESC(isapnp, "When set to 0 driver ISA PnP support will be disabled");
+#endif
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "io port");
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
+
+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) ")");
+
+
+
+/* Read from Data Register */
+static inline void sc1200wdt_read_data(unsigned char index, unsigned char *data)
+{
+       spin_lock(&sc1200wdt_lock);
+       outb_p(index, PMIR);
+       *data = inb(PMDR);
+       spin_unlock(&sc1200wdt_lock);
+}
+
+
+/* Write to Data Register */
+static inline void sc1200wdt_write_data(unsigned char index, unsigned char data)
+{
+       spin_lock(&sc1200wdt_lock);
+       outb_p(index, PMIR);
+       outb(data, PMDR);
+       spin_unlock(&sc1200wdt_lock);
+}
+
+
+static void sc1200wdt_start(void)
+{
+       unsigned char reg;
+
+       sc1200wdt_read_data(WDCF, &reg);
+       /* assert WDO when any of the following interrupts are triggered too */
+       reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ);
+       sc1200wdt_write_data(WDCF, reg);
+       /* set the timeout and get the ball rolling */
+       sc1200wdt_write_data(WDTO, timeout);
+}
+
+
+static void sc1200wdt_stop(void)
+{
+       sc1200wdt_write_data(WDTO, 0);
+}
+
+
+/* This returns the status of the WDO signal, inactive high. */
+static inline int sc1200wdt_status(void)
+{
+       unsigned char ret;
+
+       sc1200wdt_read_data(WDST, &ret);
+       /* If the bit is inactive, the watchdog is enabled, so return
+        * KEEPALIVEPING which is a bit of a kludge because there's nothing
+        * else for enabled/disabled status
+        */
+       return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING;  /* bits 1 - 7 are undefined */
+}
+
+
+static int sc1200wdt_open(struct inode *inode, struct file *file)
+{
+       /* allow one at a time */
+       if (down_trylock(&open_sem))
+               return -EBUSY;
+
+       if (timeout > MAX_TIMEOUT)
+               timeout = MAX_TIMEOUT;
+
+       sc1200wdt_start();
+       printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
+
+       return nonseekable_open(inode, file);
+}
+
+
+static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int new_timeout;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 0,
+               .identity = "PC87307/PC97307",
+       };
+
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user(argp, &ident, sizeof ident))
+                               return -EFAULT;
+                       return 0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user(sc1200wdt_status(), p);
+
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+
+               case WDIOC_KEEPALIVE:
+                       sc1200wdt_write_data(WDTO, timeout);
+                       return 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       /* the API states this is given in secs */
+                       new_timeout /= 60;
+                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       sc1200wdt_write_data(WDTO, timeout);
+                       /* fall through and return the new timeout */
+
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout * 60, p);
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int options, retval = -EINVAL;
+
+                       if (get_user(options, p))
+                               return -EFAULT;
+
+                       if (options & WDIOS_DISABLECARD) {
+                               sc1200wdt_stop();
+                               retval = 0;
+                       }
+
+                       if (options & WDIOS_ENABLECARD) {
+                               sc1200wdt_start();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+       }
+}
+
+
+static int sc1200wdt_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               sc1200wdt_stop();
+               printk(KERN_INFO PFX "Watchdog disabled\n");
+       } else {
+               sc1200wdt_write_data(WDTO, timeout);
+               printk(KERN_CRIT PFX "Unexpected close!, timeout = %d min(s)\n", timeout);
+       }
+       up(&open_sem);
+       expect_close = 0;
+
+       return 0;
+}
+
+
+static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
+{
+       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;
+                       }
+               }
+
+               sc1200wdt_write_data(WDTO, timeout);
+               return len;
+       }
+
+       return 0;
+}
+
+
+static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+               sc1200wdt_stop();
+
+       return NOTIFY_DONE;
+}
+
+
+static struct notifier_block sc1200wdt_notifier =
+{
+       .notifier_call =        sc1200wdt_notify_sys,
+};
+
+static const struct file_operations sc1200wdt_fops =
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = sc1200wdt_write,
+       .ioctl          = sc1200wdt_ioctl,
+       .open           = sc1200wdt_open,
+       .release        = sc1200wdt_release,
+};
+
+static struct miscdevice sc1200wdt_miscdev =
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &sc1200wdt_fops,
+};
+
+
+static int __init sc1200wdt_probe(void)
+{
+       /* The probe works by reading the PMC3 register's default value of 0x0e
+        * there is one caveat, if the device disables the parallel port or any
+        * of the UARTs we won't be able to detect it.
+        * Nb. This could be done with accuracy by reading the SID registers, but
+        * we don't have access to those io regions.
+        */
+
+       unsigned char reg;
+
+       sc1200wdt_read_data(PMC3, &reg);
+       reg &= 0x0f;                            /* we don't want the UART busy bits */
+       return (reg == 0x0e) ? 0 : -ENODEV;
+}
+
+
+#if defined CONFIG_PNP
+
+static struct pnp_device_id scl200wdt_pnp_devices[] = {
+       /* National Semiconductor PC87307/PC97307 watchdog component */
+       {.id = "NSC0800", .driver_data = 0},
+       {.id = ""},
+};
+
+static int scl200wdt_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
+{
+       /* this driver only supports one card at a time */
+       if (wdt_dev || !isapnp)
+               return -EBUSY;
+
+       wdt_dev = dev;
+       io = pnp_port_start(wdt_dev, 0);
+       io_len = pnp_port_len(wdt_dev, 0);
+
+       if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
+               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               return -EBUSY;
+       }
+
+       printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n", io, io_len);
+       return 0;
+}
+
+static void scl200wdt_pnp_remove(struct pnp_dev * dev)
+{
+       if (wdt_dev){
+               release_region(io, io_len);
+               wdt_dev = NULL;
+       }
+}
+
+static struct pnp_driver scl200wdt_pnp_driver = {
+       .name           = "scl200wdt",
+       .id_table       = scl200wdt_pnp_devices,
+       .probe          = scl200wdt_pnp_probe,
+       .remove         = scl200wdt_pnp_remove,
+};
+
+#endif /* CONFIG_PNP */
+
+
+static int __init sc1200wdt_init(void)
+{
+       int ret;
+
+       printk("%s\n", banner);
+
+       spin_lock_init(&sc1200wdt_lock);
+       sema_init(&open_sem, 1);
+
+#if defined CONFIG_PNP
+       if (isapnp) {
+               ret = pnp_register_driver(&scl200wdt_pnp_driver);
+               if (ret)
+                       goto out_clean;
+       }
+#endif
+
+       if (io == -1) {
+               printk(KERN_ERR PFX "io parameter must be specified\n");
+               ret = -EINVAL;
+               goto out_pnp;
+       }
+
+#if defined CONFIG_PNP
+       /* now that the user has specified an IO port and we haven't detected
+        * any devices, disable pnp support */
+       isapnp = 0;
+       pnp_unregister_driver(&scl200wdt_pnp_driver);
+#endif
+
+       if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
+               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               ret = -EBUSY;
+               goto out_pnp;
+       }
+
+       ret = sc1200wdt_probe();
+       if (ret)
+               goto out_io;
+
+       ret = register_reboot_notifier(&sc1200wdt_notifier);
+       if (ret) {
+               printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret);
+               goto out_io;
+       }
+
+       ret = misc_register(&sc1200wdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
+               goto out_rbt;
+       }
+
+       /* ret = 0 */
+
+out_clean:
+       return ret;
+
+out_rbt:
+       unregister_reboot_notifier(&sc1200wdt_notifier);
+
+out_io:
+       release_region(io, io_len);
+
+out_pnp:
+#if defined CONFIG_PNP
+       if (isapnp)
+               pnp_unregister_driver(&scl200wdt_pnp_driver);
+#endif
+       goto out_clean;
+}
+
+
+static void __exit sc1200wdt_exit(void)
+{
+       misc_deregister(&sc1200wdt_miscdev);
+       unregister_reboot_notifier(&sc1200wdt_notifier);
+
+#if defined CONFIG_PNP
+       if(isapnp)
+               pnp_unregister_driver(&scl200wdt_pnp_driver);
+       else
+#endif
+       release_region(io, io_len);
+}
+
+module_init(sc1200wdt_init);
+module_exit(sc1200wdt_exit);
+
+MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
+MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c
new file mode 100644 (file)
index 0000000..e8594c6
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ *     AMD Elan SC520 processor Watchdog Timer driver
+ *
+ *      Based on acquirewdt.c by Alan Cox,
+ *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@unthought.net>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     The authors do NOT admit liability nor provide warranty for
+ *     any of this software. This material is provided "AS-IS" in
+ *      the hope that it may be useful for others.
+ *
+ *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
+ *           9/27 - 2001      [Initial release]
+ *
+ *     Additional fixes Alan Cox
+ *     -       Fixed formatting
+ *     -       Removed debug printks
+ *     -       Fixed SMP built kernel deadlock
+ *     -       Switched to private locks not lock_kernel
+ *     -       Used ioremap/writew/readw
+ *     -       Added NOWAYOUT support
+ *     4/12 - 2002 Changes by Rob Radez <rob@osinvestor.com>
+ *     -       Change comments
+ *     -       Eliminate fop_llseek
+ *     -       Change CONFIG_WATCHDOG_NOWAYOUT semantics
+ *     -       Add KERN_* tags to printks
+ *     -       fix possible wdt_is_open race
+ *     -       Report proper capabilities in watchdog_info
+ *     -       Add WDIOC_{GETSTATUS, GETBOOTSTATUS, SETTIMEOUT,
+ *             GETTIMEOUT, SETOPTIONS} ioctls
+ *     09/8 - 2003 Changes by Wim Van Sebroeck <wim@iguana.be>
+ *     -       cleanup of trailing spaces
+ *     -       added extra printk's for startup problems
+ *     -       use module_param
+ *     -       made timeout (the emulated heartbeat) a module_param
+ *     -       made the keepalive ping an internal subroutine
+ *     3/27 - 2004 Changes by Sean Young <sean@mess.org>
+ *     -       set MMCR_BASE to 0xfffef000
+ *     -       CBAR does not need to be read
+ *     -       removed debugging printks
+ *
+ *  This WDT driver is different from most other Linux WDT
+ *  drivers in that the driver will ping the watchdog by itself,
+ *  because this particular WDT has a very short timeout (1.6
+ *  seconds) and it would be insane to count on any userspace
+ *  daemon always getting scheduled within that time frame.
+ *
+ *  This driver uses memory mapped IO, and spinlock.
+ */
+
+#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/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define OUR_NAME "sc520_wdt"
+#define PFX OUR_NAME ": "
+
+/*
+ * The AMD Elan SC520 timeout value is 492us times a power of 2 (0-7)
+ *
+ *   0: 492us    2: 1.01s    4: 4.03s   6: 16.22s
+ *   1: 503ms    3: 2.01s    5: 8.05s   7: 32.21s
+ *
+ * We will program the SC520 watchdog for a timeout of 2.01s.
+ * If we reset the watchdog every ~250ms we should be safe.
+ */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 30 seconds.
+ */
+
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+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) ")");
+
+/*
+ * AMD Elan SC520 - Watchdog Timer Registers
+ */
+#define MMCR_BASE      0xfffef000      /* The default base address */
+#define OFFS_WDTMRCTL  0xCB0   /* Watchdog Timer Control Register */
+
+/* WDT Control Register bit definitions */
+#define WDT_EXP_SEL_01 0x0001  /* [01] Time-out = 496 us (with 33 Mhz clk). */
+#define WDT_EXP_SEL_02 0x0002  /* [02] Time-out = 508 ms (with 33 Mhz clk). */
+#define WDT_EXP_SEL_03 0x0004  /* [03] Time-out = 1.02 s (with 33 Mhz clk). */
+#define WDT_EXP_SEL_04 0x0008  /* [04] Time-out = 2.03 s (with 33 Mhz clk). */
+#define WDT_EXP_SEL_05 0x0010  /* [05] Time-out = 4.07 s (with 33 Mhz clk). */
+#define WDT_EXP_SEL_06 0x0020  /* [06] Time-out = 8.13 s (with 33 Mhz clk). */
+#define WDT_EXP_SEL_07 0x0040  /* [07] Time-out = 16.27s (with 33 Mhz clk). */
+#define WDT_EXP_SEL_08 0x0080  /* [08] Time-out = 32.54s (with 33 Mhz clk). */
+#define WDT_IRQ_FLG    0x1000  /* [12] Interrupt Request Flag */
+#define WDT_WRST_ENB   0x4000  /* [14] Watchdog Timer Reset Enable */
+#define WDT_ENB                0x8000  /* [15] Watchdog Timer Enable */
+
+static __u16 __iomem *wdtmrctl;
+
+static void wdt_timer_ping(unsigned long);
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static char wdt_expect_close;
+static spinlock_t wdt_spinlock;
+
+/*
+ *     Whack the dog
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT
+        */
+       if(time_before(jiffies, next_heartbeat))
+       {
+               /* Ping the WDT */
+               spin_lock(&wdt_spinlock);
+               writew(0xAAAA, wdtmrctl);
+               writew(0x5555, wdtmrctl);
+               spin_unlock(&wdt_spinlock);
+
+               /* Re-set the timer interval */
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
+       } else {
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+/*
+ *     Utility routines
+ */
+
+static void wdt_config(int writeval)
+{
+       __u16 dummy;
+       unsigned long flags;
+
+       /* buy some time (ping) */
+       spin_lock_irqsave(&wdt_spinlock, flags);
+       dummy=readw(wdtmrctl);  /* ensure write synchronization */
+       writew(0xAAAA, wdtmrctl);
+       writew(0x5555, wdtmrctl);
+       /* unlock WDT = make WDT configuration register writable one time */
+       writew(0x3333, wdtmrctl);
+       writew(0xCCCC, wdtmrctl);
+       /* write WDT configuration register */
+       writew(writeval, wdtmrctl);
+       spin_unlock_irqrestore(&wdt_spinlock, flags);
+}
+
+static int wdt_startup(void)
+{
+       next_heartbeat = jiffies + (timeout * HZ);
+
+       /* Start the timer */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+       /* Start the watchdog */
+       wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
+
+       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       return 0;
+}
+
+static int wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer(&timer);
+
+       /* Stop the watchdog */
+       wdt_config(0);
+
+       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       return 0;
+}
+
+static int wdt_keepalive(void)
+{
+       /* user land ping */
+       next_heartbeat = jiffies + (timeout * HZ);
+       return 0;
+}
+
+static int wdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 3600))      /* arbitrary upper limit */
+               return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count) {
+               if (!nowayout) {
+                       size_t ofs;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       wdt_expect_close = 0;
+
+                       /* now scan */
+                       for(ofs = 0; ofs != count; ofs++) {
+                               char c;
+                               if (get_user(c, buf + ofs))
+                                       return -EFAULT;
+                               if(c == 'V')
+                                       wdt_expect_close = 42;
+                       }
+               }
+
+               /* Well, anyhow someone wrote to us, we should return that favour */
+               wdt_keepalive();
+       }
+       return count;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       /* Just in case we're already talking to someone... */
+       if(test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Good, fire up the show */
+       wdt_startup();
+       return nonseekable_open(inode, file);
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(wdt_expect_close == 42) {
+               wdt_turnoff();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               wdt_keepalive();
+       }
+       clear_bit(0, &wdt_is_open);
+       wdt_expect_close = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "SC520",
+       };
+
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               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:
+                       wdt_keepalive();
+                       return 0;
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if(get_user(new_options, p))
+                               return -EFAULT;
+
+                       if(new_options & WDIOS_DISABLECARD) {
+                               wdt_turnoff();
+                               retval = 0;
+                       }
+
+                       if(new_options & WDIOS_ENABLECARD) {
+                               wdt_startup();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_timeout;
+
+                       if(get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       if(wdt_set_heartbeat(new_timeout))
+                               return -EINVAL;
+
+                       wdt_keepalive();
+                       /* Fall through */
+               }
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout, p);
+       }
+}
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = fop_write,
+       .open           = fop_open,
+       .release        = fop_close,
+       .ioctl          = fop_ioctl,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wdt_fops,
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+               wdt_turnoff();
+       return NOTIFY_DONE;
+}
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+       .notifier_call = wdt_notify_sys,
+};
+
+static void __exit sc520_wdt_unload(void)
+{
+       if (!nowayout)
+               wdt_turnoff();
+
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+       unregister_reboot_notifier(&wdt_notifier);
+       iounmap(wdtmrctl);
+}
+
+static int __init sc520_wdt_init(void)
+{
+       int rc = -EBUSY;
+
+       spin_lock_init(&wdt_spinlock);
+
+       /* Check that the timeout value is within it's range ; if not reset to the default */
+       if (wdt_set_heartbeat(timeout)) {
+               wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n",
+                       WATCHDOG_TIMEOUT);
+       }
+
+       wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
+       if (!wdtmrctl) {
+               printk(KERN_ERR PFX "Unable to remap memory\n");
+               rc = -ENOMEM;
+               goto err_out_region2;
+       }
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc) {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_ioremap;
+       }
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc) {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, rc);
+               goto err_out_notifier;
+       }
+
+       printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout,nowayout);
+
+       return 0;
+
+err_out_notifier:
+       unregister_reboot_notifier(&wdt_notifier);
+err_out_ioremap:
+       iounmap(wdtmrctl);
+err_out_region2:
+       return rc;
+}
+
+module_init(sc520_wdt_init);
+module_exit(sc520_wdt_unload);
+
+MODULE_AUTHOR("Scott and Bill Jennings");
+MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
new file mode 100644 (file)
index 0000000..d4fd0fa
--- /dev/null
@@ -0,0 +1,269 @@
+/* drivers/char/watchdog/scx200_wdt.c
+
+   National Semiconductor SCx200 Watchdog support
+
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+
+   Some code taken from:
+   National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
+   (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The author(s) of this software shall not be held liable for damages
+   of any nature resulting due to the use of this software. This
+   software is provided AS-IS with no warranties. */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/scx200.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define NAME "scx200_wdt"
+
+MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
+MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60;                /* in seconds */
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+static u16 wdto_restart;
+static struct semaphore open_semaphore;
+static char expect_close;
+
+/* Bits of the WDCNFG register */
+#define W_ENABLE 0x00fa                /* Enable watchdog */
+#define W_DISABLE 0x0000       /* Disable watchdog */
+
+/* The scaling factor for the timer, this depends on the value of W_ENABLE */
+#define W_SCALE (32768/1024)
+
+static void scx200_wdt_ping(void)
+{
+       outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
+}
+
+static void scx200_wdt_update_margin(void)
+{
+       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
+       wdto_restart = margin * W_SCALE;
+}
+
+static void scx200_wdt_enable(void)
+{
+       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
+              wdto_restart);
+
+       outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+       outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+       outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
+
+       scx200_wdt_ping();
+}
+
+static void scx200_wdt_disable(void)
+{
+       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+
+       outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+       outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+       outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
+}
+
+static int scx200_wdt_open(struct inode *inode, struct file *file)
+{
+       /* only allow one at a time */
+       if (down_trylock(&open_semaphore))
+               return -EBUSY;
+       scx200_wdt_enable();
+
+       return nonseekable_open(inode, file);
+}
+
+static int scx200_wdt_release(struct inode *inode, struct file *file)
+{
+       if (expect_close != 42) {
+               printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
+       } else if (!nowayout) {
+               scx200_wdt_disable();
+       }
+       expect_close = 0;
+       up(&open_semaphore);
+
+       return 0;
+}
+
+static int scx200_wdt_notify_sys(struct notifier_block *this,
+                                     unsigned long code, void *unused)
+{
+       if (code == SYS_HALT || code == SYS_POWER_OFF)
+               if (!nowayout)
+                       scx200_wdt_disable();
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block scx200_wdt_notifier =
+{
+       .notifier_call = scx200_wdt_notify_sys,
+};
+
+static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
+                                    size_t len, loff_t *ppos)
+{
+       /* check for a magic close character */
+       if (len)
+       {
+               size_t i;
+
+               scx200_wdt_ping();
+
+               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;
+               }
+
+               return len;
+       }
+
+       return 0;
+}
+
+static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .identity = "NatSemi SCx200 Watchdog",
+               .firmware_version = 1,
+               .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
+       };
+       int new_margin;
+
+       switch (cmd) {
+       default:
+               return -ENOTTY;
+       case WDIOC_GETSUPPORT:
+               if(copy_to_user(argp, &ident, sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(0, p))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_KEEPALIVE:
+               scx200_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, p))
+                       return -EFAULT;
+               if (new_margin < 1)
+                       return -EINVAL;
+               margin = new_margin;
+               scx200_wdt_update_margin();
+               scx200_wdt_ping();
+       case WDIOC_GETTIMEOUT:
+               if (put_user(margin, p))
+                       return -EFAULT;
+               return 0;
+       }
+}
+
+static const struct file_operations scx200_wdt_fops = {
+       .owner   = THIS_MODULE,
+       .llseek  = no_llseek,
+       .write   = scx200_wdt_write,
+       .ioctl   = scx200_wdt_ioctl,
+       .open    = scx200_wdt_open,
+       .release = scx200_wdt_release,
+};
+
+static struct miscdevice scx200_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name  = "watchdog",
+       .fops  = &scx200_wdt_fops,
+};
+
+static int __init scx200_wdt_init(void)
+{
+       int r;
+
+       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
+
+       /* check that we have found the configuration block */
+       if (!scx200_cb_present())
+               return -ENODEV;
+
+       if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
+                           SCx200_WDT_SIZE,
+                           "NatSemi SCx200 Watchdog")) {
+               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               return -EBUSY;
+       }
+
+       scx200_wdt_update_margin();
+       scx200_wdt_disable();
+
+       sema_init(&open_semaphore, 1);
+
+       r = misc_register(&scx200_wdt_miscdev);
+       if (r) {
+               release_region(scx200_cb_base + SCx200_WDT_OFFSET,
+                               SCx200_WDT_SIZE);
+               return r;
+       }
+
+       r = register_reboot_notifier(&scx200_wdt_notifier);
+       if (r) {
+               printk(KERN_ERR NAME ": unable to register reboot notifier");
+               misc_deregister(&scx200_wdt_miscdev);
+               release_region(scx200_cb_base + SCx200_WDT_OFFSET,
+                               SCx200_WDT_SIZE);
+               return r;
+       }
+
+       return 0;
+}
+
+static void __exit scx200_wdt_cleanup(void)
+{
+       unregister_reboot_notifier(&scx200_wdt_notifier);
+       misc_deregister(&scx200_wdt_miscdev);
+       release_region(scx200_cb_base + SCx200_WDT_OFFSET,
+                      SCx200_WDT_SIZE);
+}
+
+module_init(scx200_wdt_init);
+module_exit(scx200_wdt_cleanup);
+
+/*
+    Local variables:
+        compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
+        c-basic-offset: 8
+    End:
+*/
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
new file mode 100644 (file)
index 0000000..cecbedd
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * drivers/char/watchdog/shwdt.c
+ *
+ * Watchdog driver for integrated watchdog in the SuperH processors.
+ *
+ * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
+ *     Added expect close support, made emulated timeout runtime changeable
+ *     general cleanups, add some ioctls
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/notifier.h>
+#include <linux/ioport.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/watchdog.h>
+
+#define PFX "shwdt: "
+
+/*
+ * Default clock division ratio is 5.25 msecs. For an additional table of
+ * values, consult the asm-sh/watchdog.h. Overload this at module load
+ * time.
+ *
+ * In order for this to work reliably we need to have HZ set to 1000 or
+ * something quite higher than 100 (or we need a proper high-res timer
+ * implementation that will deal with this properly), otherwise the 10ms
+ * resolution of a jiffy is enough to trigger the overflow. For things like
+ * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
+ * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
+ * necssary.
+ *
+ * As a result of this timing problem, the only modes that are particularly
+ * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms
+ * overflow periods respectively.
+ *
+ * Also, since we can't really expect userspace to be responsive enough
+ * before the overflow happens, we maintain two seperate timers .. One in
+ * the kernel for clearing out WOVF every 2ms or so (again, this depends on
+ * HZ == 1000), and another for monitoring userspace writes to the WDT device.
+ *
+ * As such, we currently use a configurable heartbeat interval which defaults
+ * to 30s. In this case, the userspace daemon is only responsible for periodic
+ * writes to the device before the next heartbeat is scheduled. If the daemon
+ * misses its deadline, the kernel timer will allow the WDT to overflow.
+ */
+static int clock_division_ratio = WTCSR_CKS_4096;
+
+#define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
+
+static void sh_wdt_ping(unsigned long data);
+
+static unsigned long shwdt_is_open;
+static struct watchdog_info sh_wdt_info;
+static char shwdt_expect_close;
+static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
+static unsigned long next_heartbeat;
+
+#define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
+static int heartbeat = WATCHDOG_HEARTBEAT;     /* in seconds */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+/**
+ *     sh_wdt_start - Start the Watchdog
+ *
+ *     Starts the watchdog.
+ */
+static void sh_wdt_start(void)
+{
+       __u8 csr;
+
+       next_heartbeat = jiffies + (heartbeat * HZ);
+       mod_timer(&timer, next_ping_period(clock_division_ratio));
+
+       csr = sh_wdt_read_csr();
+       csr |= WTCSR_WT | clock_division_ratio;
+       sh_wdt_write_csr(csr);
+
+       sh_wdt_write_cnt(0);
+
+       /*
+        * These processors have a bit of an inconsistent initialization
+        * process.. starting with SH-3, RSTS was moved to WTCSR, and the
+        * RSTCSR register was removed.
+        *
+        * On the SH-2 however, in addition with bits being in different
+        * locations, we must deal with RSTCSR outright..
+        */
+       csr = sh_wdt_read_csr();
+       csr |= WTCSR_TME;
+       csr &= ~WTCSR_RSTS;
+       sh_wdt_write_csr(csr);
+
+#ifdef CONFIG_CPU_SH2
+       /*
+        * Whoever came up with the RSTCSR semantics must've been smoking
+        * some of the good stuff, since in addition to the WTCSR/WTCNT write
+        * brain-damage, it's managed to fuck things up one step further..
+        *
+        * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
+        * but if we want to touch RSTE or RSTS, the upper byte has to be
+        * 0x5a..
+        */
+       csr = sh_wdt_read_rstcsr();
+       csr &= ~RSTCSR_RSTS;
+       sh_wdt_write_rstcsr(csr);
+#endif
+}
+
+/**
+ *     sh_wdt_stop - Stop the Watchdog
+ *     Stops the watchdog.
+ */
+static void sh_wdt_stop(void)
+{
+       __u8 csr;
+
+       del_timer(&timer);
+
+       csr = sh_wdt_read_csr();
+       csr &= ~WTCSR_TME;
+       sh_wdt_write_csr(csr);
+}
+
+/**
+ *     sh_wdt_keepalive - Keep the Userspace Watchdog Alive
+ *     The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
+ */
+static inline void sh_wdt_keepalive(void)
+{
+       next_heartbeat = jiffies + (heartbeat * HZ);
+}
+
+/**
+ *     sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
+ *     Set the Userspace Watchdog heartbeat
+ */
+static int sh_wdt_set_heartbeat(int t)
+{
+       if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
+               return -EINVAL;
+
+       heartbeat = t;
+       return 0;
+}
+
+/**
+ *     sh_wdt_ping - Ping the Watchdog
+ *     @data: Unused
+ *
+ *     Clears overflow bit, resets timer counter.
+ */
+static void sh_wdt_ping(unsigned long data)
+{
+       if (time_before(jiffies, next_heartbeat)) {
+               __u8 csr;
+
+               csr = sh_wdt_read_csr();
+               csr &= ~WTCSR_IOVF;
+               sh_wdt_write_csr(csr);
+
+               sh_wdt_write_cnt(0);
+
+               mod_timer(&timer, next_ping_period(clock_division_ratio));
+       } else
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
+                      "the watchdog\n");
+}
+
+/**
+ *     sh_wdt_open - Open the Device
+ *     @inode: inode of device
+ *     @file: file handle of device
+ *
+ *     Watchdog device is opened and started.
+ */
+static int sh_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &shwdt_is_open))
+               return -EBUSY;
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       sh_wdt_start();
+
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     sh_wdt_close - Close the Device
+ *     @inode: inode of device
+ *     @file: file handle of device
+ *
+ *     Watchdog device is closed and stopped.
+ */
+static int sh_wdt_close(struct inode *inode, struct file *file)
+{
+       if (shwdt_expect_close == 42) {
+               sh_wdt_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not "
+                      "stopping watchdog!\n");
+               sh_wdt_keepalive();
+       }
+
+       clear_bit(0, &shwdt_is_open);
+       shwdt_expect_close = 0;
+
+       return 0;
+}
+
+/**
+ *     sh_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 sh_wdt_write(struct file *file, const char *buf,
+                           size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       shwdt_expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       shwdt_expect_close = 42;
+                       }
+               }
+               sh_wdt_keepalive();
+       }
+
+       return count;
+}
+
+/**
+ *     sh_wdt_mmap - map WDT/CPG registers into userspace
+ *     @file: file structure for the device
+ *     @vma: VMA to map the registers into
+ *
+ *     A simple mmap() implementation for the corner cases where the counter
+ *     needs to be mapped in userspace directly. Due to the relatively small
+ *     size of the area, neighbouring registers not necessarily tied to the
+ *     CPG will also be accessible through the register page, so this remains
+ *     configurable for users that really know what they're doing.
+ *
+ *     Additionaly, the register page maps in the CPG register base relative
+ *     to the nearest page-aligned boundary, which requires that userspace do
+ *     the appropriate CPU subtype math for calculating the page offset for
+ *     the counter value.
+ */
+static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int ret = -ENOSYS;
+
+#ifdef CONFIG_SH_WDT_MMAP
+       unsigned long addr;
+
+       /* Only support the simple cases where we map in a register page. */
+       if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
+               return -EINVAL;
+
+       /*
+        * Pick WTCNT as the start, it's usually the first register after the
+        * FRQCR, and neither one are generally page-aligned out of the box.
+        */
+       addr = WTCNT & ~(PAGE_SIZE - 1);
+
+       vma->vm_flags |= VM_IO;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+                              PAGE_SIZE, vma->vm_page_prot)) {
+               printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
+                      __FUNCTION__);
+               return -EAGAIN;
+       }
+
+       ret = 0;
+#endif
+
+       return ret;
+}
+
+/**
+ *     sh_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 sh_wdt_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       int new_heartbeat;
+       int options, retval = -EINVAL;
+
+       switch (cmd) {
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user((struct watchdog_info *)arg,
+                                         &sh_wdt_info,
+                                         sizeof(sh_wdt_info)) ? -EFAULT : 0;
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, (int *)arg);
+               case WDIOC_KEEPALIVE:
+                       sh_wdt_keepalive();
+                       return 0;
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_heartbeat, (int *)arg))
+                               return -EFAULT;
+
+                       if (sh_wdt_set_heartbeat(new_heartbeat))
+                               return -EINVAL;
+
+                       sh_wdt_keepalive();
+                       /* Fall */
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, (int *)arg);
+               case WDIOC_SETOPTIONS:
+                       if (get_user(options, (int *)arg))
+                               return -EFAULT;
+
+                       if (options & WDIOS_DISABLECARD) {
+                               sh_wdt_stop();
+                               retval = 0;
+                       }
+
+                       if (options & WDIOS_ENABLECARD) {
+                               sh_wdt_start();
+                               retval = 0;
+                       }
+
+                       return retval;
+               default:
+                       return -ENOTTY;
+       }
+
+       return 0;
+}
+
+/**
+ *     sh_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 sh_wdt_notify_sys(struct notifier_block *this,
+                            unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+               sh_wdt_stop();
+
+       return NOTIFY_DONE;
+}
+
+static const struct file_operations sh_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = sh_wdt_write,
+       .ioctl          = sh_wdt_ioctl,
+       .open           = sh_wdt_open,
+       .release        = sh_wdt_close,
+       .mmap           = sh_wdt_mmap,
+};
+
+static struct watchdog_info sh_wdt_info = {
+       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+                                 WDIOF_MAGICCLOSE,
+       .firmware_version       = 1,
+       .identity               = "SH WDT",
+};
+
+static struct notifier_block sh_wdt_notifier = {
+       .notifier_call          = sh_wdt_notify_sys,
+};
+
+static struct miscdevice sh_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &sh_wdt_fops,
+};
+
+/**
+ *     sh_wdt_init - Initialize module
+ *     Registers the device and notifier handler. Actual device
+ *     initialization is handled by sh_wdt_open().
+ */
+static int __init sh_wdt_init(void)
+{
+       int rc;
+
+       if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
+               clock_division_ratio = WTCSR_CKS_4096;
+               printk(KERN_INFO PFX "clock_division_ratio value must "
+                      "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
+       }
+
+       rc = sh_wdt_set_heartbeat(heartbeat);
+       if (unlikely(rc)) {
+               heartbeat = WATCHDOG_HEARTBEAT;
+               printk(KERN_INFO PFX "heartbeat value must "
+                      "be 1<=x<=3600, using %d\n", heartbeat);
+       }
+
+       rc = register_reboot_notifier(&sh_wdt_notifier);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
+                      rc);
+               return rc;
+       }
+
+       rc = misc_register(&sh_wdt_miscdev);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register miscdev on "
+                      "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
+               unregister_reboot_notifier(&sh_wdt_notifier);
+               return rc;
+       }
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+
+       return 0;
+}
+
+/**
+ *     sh_wdt_exit - Deinitialize module
+ *     Unregisters the device and notifier handler. Actual device
+ *     deinitialization is handled by sh_wdt_close().
+ */
+static void __exit sh_wdt_exit(void)
+{
+       misc_deregister(&sh_wdt_miscdev);
+       unregister_reboot_notifier(&sh_wdt_notifier);
+}
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("SuperH watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(clock_division_ratio, int, 0);
+MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+module_init(sh_wdt_init);
+module_exit(sh_wdt_exit);
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
new file mode 100644 (file)
index 0000000..d3cb0a7
--- /dev/null
@@ -0,0 +1,627 @@
+/*
+ *     SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x
+ *
+ *      Based on acquirewdt.c by Alan Cox <alan@redhat.com>
+ *       and some other existing drivers
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     The authors do NOT admit liability nor provide warranty for
+ *     any of this software. This material is provided "AS-IS" in
+ *      the hope that it may be useful for others.
+ *
+ *     (C) Copyright 2003-2006  Sven Anders <anders@anduras.de>
+ *
+ *  History:
+ *     2003 - Created version 1.0 for Linux 2.4.x.
+ *     2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE
+ *             features. Released version 1.1
+ *
+ *  Theory of operation:
+ *
+ *      A Watchdog Timer (WDT) is a hardware circuit that can
+ *      reset the computer system in case of a software fault.
+ *      You probably knew that already.
+ *
+ *      Usually a userspace daemon will notify the kernel WDT driver
+ *      via the /dev/watchdog special device file that userspace is
+ *      still alive, at regular intervals.  When such a notification
+ *      occurs, the driver will usually tell the hardware watchdog
+ *      that everything is in order, and that the watchdog should wait
+ *      for yet another little while to reset the system.
+ *      If userspace fails (RAM error, kernel bug, whatever), the
+ *      notifications cease to occur, and the hardware watchdog will
+ *      reset the system (causing a reboot) after the timeout occurs.
+ *
+ * Create device with:
+ *  mknod /dev/watchdog c 10 130
+ *
+ * For an example userspace keep-alive daemon, see:
+ *   Documentation/watchdog/watchdog.txt
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/* enable support for minutes as units? */
+/* (does not always work correctly, so disabled by default!) */
+#define SMSC_SUPPORT_MINUTES
+#undef SMSC_SUPPORT_MINUTES
+
+#define MAX_TIMEOUT     255
+
+#define UNIT_SECOND     0
+#define UNIT_MINUTE     1
+
+#define MODNAME                "smsc37b787_wdt: "
+#define VERSION         "1.1"
+
+#define IOPORT          0x3F0
+#define IOPORT_SIZE     2
+#define IODEV_NO        8
+
+static int unit = UNIT_SECOND;  /* timer's unit */
+static int timeout = 60;        /* timeout value: default is 60 "units" */
+static unsigned long timer_enabled = 0;   /* is the timer enabled? */
+
+static char expect_close;       /* is the close expected? */
+
+static spinlock_t io_lock;     /* to guard the watchdog from io races */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+/* -- Low level function ----------------------------------------*/
+
+/* unlock the IO chip */
+
+static inline void open_io_config(void)
+{
+        outb(0x55, IOPORT);
+       mdelay(1);
+        outb(0x55, IOPORT);
+}
+
+/* lock the IO chip */
+static inline void close_io_config(void)
+{
+        outb(0xAA, IOPORT);
+}
+
+/* select the IO device */
+static inline void select_io_device(unsigned char devno)
+{
+        outb(0x07, IOPORT);
+        outb(devno, IOPORT+1);
+}
+
+/* write to the control register */
+static inline void write_io_cr(unsigned char reg, unsigned char data)
+{
+        outb(reg, IOPORT);
+        outb(data, IOPORT+1);
+}
+
+/* read from the control register */
+static inline char read_io_cr(unsigned char reg)
+{
+        outb(reg, IOPORT);
+        return inb(IOPORT+1);
+}
+
+/* -- Medium level functions ------------------------------------*/
+
+static inline void gpio_bit12(unsigned char reg)
+{
+       // -- General Purpose I/O Bit 1.2 --
+       // Bit 0,   In/Out: 0 = Output, 1 = Input
+       // Bit 1,   Polarity: 0 = No Invert, 1 = Invert
+       // Bit 2,   Group Enable Intr.: 0 = Disable, 1 = Enable
+       // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17,
+       //                           11 = Either Edge Triggered Intr. 2
+        // Bit 5/6  (Reserved)
+       // Bit 7,   Output Type: 0 = Push Pull Bit, 1 = Open Drain
+        write_io_cr(0xE2, reg);
+}
+
+static inline void gpio_bit13(unsigned char reg)
+{
+       // -- General Purpose I/O Bit 1.3 --
+       // Bit 0,  In/Out: 0 = Output, 1 = Input
+       // Bit 1,  Polarity: 0 = No Invert, 1 = Invert
+       // Bit 2,  Group Enable Intr.: 0 = Disable, 1 = Enable
+       // Bit 3,  Function select: 0 = GPI/O, 1 = LED
+        // Bit 4-6 (Reserved)
+       // Bit 7,  Output Type: 0 = Push Pull Bit, 1 = Open Drain
+        write_io_cr(0xE3, reg);
+}
+
+static inline void wdt_timer_units(unsigned char new_units)
+{
+       // -- Watchdog timer units --
+       // Bit 0-6 (Reserved)
+       // Bit 7,  WDT Time-out Value Units Select
+       //         (0 = Minutes, 1 = Seconds)
+        write_io_cr(0xF1, new_units);
+}
+
+static inline void wdt_timeout_value(unsigned char new_timeout)
+{
+       // -- Watchdog Timer Time-out Value --
+       // Bit 0-7 Binary coded units (0=Disabled, 1..255)
+        write_io_cr(0xF2, new_timeout);
+}
+
+static inline void wdt_timer_conf(unsigned char conf)
+{
+       // -- Watchdog timer configuration --
+       // Bit 0   Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O
+       // Bit 1   Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
+       // Bit 2   Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr.
+        // Bit 3   Reset the timer
+        //         (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled)
+       // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
+       //            0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
+        write_io_cr(0xF3, conf);
+}
+
+static inline void wdt_timer_ctrl(unsigned char reg)
+{
+       // -- Watchdog timer control --
+       // Bit 0   Status Bit: 0 = Timer counting, 1 = Timeout occured
+       // Bit 1   Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz
+       // Bit 2   Force Timeout: 1 = Forces WD timeout event (self-cleaning)
+       // Bit 3   P20 Force Timeout enabled:
+       //          0 = P20 activity does not generate the WD timeout event
+       //          1 = P20 Allows rising edge of P20, from the keyboard
+       //              controller, to force the WD timeout event.
+       // Bit 4   (Reserved)
+       // -- Soft power management --
+       // Bit 5   Stop Counter: 1 = Stop software power down counter
+       //            set via register 0xB8, (self-cleaning)
+       //            (Upon read: 0 = Counter running, 1 = Counter stopped)
+       // Bit 6   Restart Counter: 1 = Restart software power down counter
+       //            set via register 0xB8, (self-cleaning)
+       // Bit 7   SPOFF: 1 = Force software power down (self-cleaning)
+
+        write_io_cr(0xF4, reg);
+}
+
+/* -- Higher level functions ------------------------------------*/
+
+/* initialize watchdog */
+
+static void wb_smsc_wdt_initialize(void)
+{
+        unsigned char old;
+
+       spin_lock(&io_lock);
+        open_io_config();
+        select_io_device(IODEV_NO);
+
+       // enable the watchdog
+       gpio_bit13(0x08);  // Select pin 80 = LED not GPIO
+       gpio_bit12(0x0A);  // Set pin 79 = WDT not GPIO/Output/Polarity=Invert
+
+       // disable the timeout
+        wdt_timeout_value(0);
+
+       // reset control register
+        wdt_timer_ctrl(0x00);
+
+       // reset configuration register
+       wdt_timer_conf(0x00);
+
+       // read old (timer units) register
+        old = read_io_cr(0xF1) & 0x7F;
+        if (unit == UNIT_SECOND) old |= 0x80; // set to seconds
+
+       // set the watchdog timer units
+        wdt_timer_units(old);
+
+        close_io_config();
+       spin_unlock(&io_lock);
+}
+
+/* shutdown the watchdog */
+
+static void wb_smsc_wdt_shutdown(void)
+{
+       spin_lock(&io_lock);
+        open_io_config();
+        select_io_device(IODEV_NO);
+
+       // disable the watchdog
+        gpio_bit13(0x09);
+        gpio_bit12(0x09);
+
+       // reset watchdog config register
+       wdt_timer_conf(0x00);
+
+       // reset watchdog control register
+        wdt_timer_ctrl(0x00);
+
+       // disable timeout
+        wdt_timeout_value(0x00);
+
+        close_io_config();
+       spin_unlock(&io_lock);
+}
+
+/* set timeout => enable watchdog */
+
+static void wb_smsc_wdt_set_timeout(unsigned char new_timeout)
+{
+       spin_lock(&io_lock);
+        open_io_config();
+        select_io_device(IODEV_NO);
+
+       // set Power LED to blink, if we enable the timeout
+        wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02);
+
+       // set timeout value
+        wdt_timeout_value(new_timeout);
+
+        close_io_config();
+       spin_unlock(&io_lock);
+}
+
+/* get timeout */
+
+static unsigned char wb_smsc_wdt_get_timeout(void)
+{
+        unsigned char set_timeout;
+
+       spin_lock(&io_lock);
+        open_io_config();
+        select_io_device(IODEV_NO);
+        set_timeout = read_io_cr(0xF2);
+        close_io_config();
+       spin_unlock(&io_lock);
+
+        return set_timeout;
+}
+
+/* disable watchdog */
+
+static void wb_smsc_wdt_disable(void)
+{
+        // set the timeout to 0 to disable the watchdog
+        wb_smsc_wdt_set_timeout(0);
+}
+
+/* enable watchdog by setting the current timeout */
+
+static void wb_smsc_wdt_enable(void)
+{
+        // set the current timeout...
+        wb_smsc_wdt_set_timeout(timeout);
+}
+
+/* reset the timer */
+
+static void wb_smsc_wdt_reset_timer(void)
+{
+       spin_lock(&io_lock);
+        open_io_config();
+        select_io_device(IODEV_NO);
+
+       // reset the timer
+       wdt_timeout_value(timeout);
+       wdt_timer_conf(0x08);
+
+        close_io_config();
+       spin_unlock(&io_lock);
+}
+
+/* return, if the watchdog is enabled (timeout is set...) */
+
+static int wb_smsc_wdt_status(void)
+{
+       return (wb_smsc_wdt_get_timeout() == 0) ? 0 : WDIOF_KEEPALIVEPING;
+}
+
+
+/* -- File operations -------------------------------------------*/
+
+/* open => enable watchdog and set initial timeout */
+
+static int wb_smsc_wdt_open(struct inode *inode, struct file *file)
+{
+       /* /dev/watchdog can only be opened once */
+
+       if (test_and_set_bit(0, &timer_enabled))
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       /* Reload and activate timer */
+       wb_smsc_wdt_enable();
+
+       printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
+
+       return nonseekable_open(inode, file);
+}
+
+/* close => shut off the timer */
+
+static int wb_smsc_wdt_release(struct inode *inode, struct file *file)
+{
+       /* Shut off the timer. */
+
+       if (expect_close == 42) {
+               wb_smsc_wdt_disable();
+               printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n");
+       } else {
+               printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n");
+               wb_smsc_wdt_reset_timer();
+       }
+
+       clear_bit(0, &timer_enabled);
+       expect_close = 0;
+       return 0;
+}
+
+/* write => update the timer to keep the machine alive */
+
+static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data,
+                                size_t len, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* reset expect flag */
+                       expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != len; i++) {
+                               char c;
+                               if (get_user(c, data+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               wb_smsc_wdt_reset_timer();
+       }
+       return len;
+}
+
+/* ioctl => control interface */
+
+static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg)
+{
+       int new_timeout;
+
+       union {
+               struct watchdog_info __user *ident;
+               int __user *i;
+       } uarg;
+
+       static struct watchdog_info ident = {
+               .options =              WDIOF_KEEPALIVEPING |
+                                       WDIOF_SETTIMEOUT |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     0,
+               .identity =             "SMsC 37B787 Watchdog"
+       };
+
+       uarg.i = (int __user *)arg;
+
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(uarg.ident, &ident,
+                               sizeof(ident)) ? -EFAULT : 0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user(wb_smsc_wdt_status(), uarg.i);
+
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, uarg.i);
+
+               case WDIOC_KEEPALIVE:
+                       wb_smsc_wdt_reset_timer();
+                       return 0;
+
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_timeout, uarg.i))
+                               return -EFAULT;
+
+                       // the API states this is given in secs
+                       if (unit == UNIT_MINUTE)
+                         new_timeout /= 60;
+
+                       if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       wb_smsc_wdt_set_timeout(timeout);
+
+                       // fall through and return the new timeout...
+
+               case WDIOC_GETTIMEOUT:
+
+                       new_timeout = timeout;
+
+                       if (unit == UNIT_MINUTE)
+                         new_timeout *= 60;
+
+                       return put_user(new_timeout, uarg.i);
+
+               case WDIOC_SETOPTIONS:
+               {
+                       int options, retval = -EINVAL;
+
+                       if (get_user(options, uarg.i))
+                               return -EFAULT;
+
+                       if (options & WDIOS_DISABLECARD) {
+                               wb_smsc_wdt_disable();
+                               retval = 0;
+                       }
+
+                       if (options & WDIOS_ENABLECARD) {
+                               wb_smsc_wdt_enable();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+       }
+}
+
+/* -- Notifier funtions -----------------------------------------*/
+
+static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT)
+       {
+                // set timeout to 0, to avoid possible race-condition
+               timeout = 0;
+               wb_smsc_wdt_disable();
+       }
+       return NOTIFY_DONE;
+}
+
+/* -- Module's structures ---------------------------------------*/
+
+static const struct file_operations wb_smsc_wdt_fops =
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wb_smsc_wdt_write,
+       .ioctl          = wb_smsc_wdt_ioctl,
+       .open           = wb_smsc_wdt_open,
+       .release        = wb_smsc_wdt_release,
+};
+
+static struct notifier_block wb_smsc_wdt_notifier =
+{
+       .notifier_call  = wb_smsc_wdt_notify_sys,
+};
+
+static struct miscdevice wb_smsc_wdt_miscdev =
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &wb_smsc_wdt_fops,
+};
+
+/* -- Module init functions -------------------------------------*/
+
+/* module's "constructor" */
+
+static int __init wb_smsc_wdt_init(void)
+{
+       int ret;
+
+       spin_lock_init(&io_lock);
+
+       printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n");
+
+       if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
+               printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT);
+               ret = -EBUSY;
+               goto out_pnp;
+       }
+
+        // set new maximum, if it's too big
+        if (timeout > MAX_TIMEOUT)
+               timeout = MAX_TIMEOUT;
+
+        // init the watchdog timer
+        wb_smsc_wdt_initialize();
+
+       ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
+       if (ret) {
+               printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret);
+               goto out_io;
+       }
+
+       ret = misc_register(&wb_smsc_wdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
+               goto out_rbt;
+       }
+
+       // output info
+       printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
+       printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout);
+
+       // ret = 0
+
+out_clean:
+       return ret;
+
+out_rbt:
+       unregister_reboot_notifier(&wb_smsc_wdt_notifier);
+
+out_io:
+       release_region(IOPORT, IOPORT_SIZE);
+
+out_pnp:
+       goto out_clean;
+}
+
+/* module's "destructor" */
+
+static void __exit wb_smsc_wdt_exit(void)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+       {
+               wb_smsc_wdt_shutdown();
+               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+       }
+
+       misc_deregister(&wb_smsc_wdt_miscdev);
+       unregister_reboot_notifier(&wb_smsc_wdt_notifier);
+       release_region(IOPORT, IOPORT_SIZE);
+
+       printk("SMsC 37B787 watchdog component driver removed.\n");
+}
+
+module_init(wb_smsc_wdt_init);
+module_exit(wb_smsc_wdt_exit);
+
+MODULE_AUTHOR("Sven Anders <anders@anduras.de>");
+MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+#ifdef SMSC_SUPPORT_MINUTES
+module_param(unit, int, 0);
+MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0");
+#endif
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
new file mode 100644 (file)
index 0000000..9c36949
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ *     SoftDog 0.07:   A Software Watchdog Device
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Software only watchdog driver. Unlike its big brother the WDT501P
+ *     driver this won't always recover a failed machine.
+ *
+ *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
+ *     Modularised.
+ *     Added soft_margin; use upon insmod to change the timer delay.
+ *     NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
+ *         minors.
+ *
+ *  19980911 Alan Cox
+ *     Made SMP safe for 2.3.x
+ *
+ *  20011127 Joel Becker (jlbec@evilplan.org>
+ *     Added soft_noboot; Allows testing the softdog trigger without
+ *     requiring a recompile.
+ *     Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
+ *
+ *  20020530 Joel Becker <joel.becker@oracle.com>
+ *     Added Matt Domsch's nowayout module option.
+ */
+
+#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/jiffies.h>
+
+#include <asm/uaccess.h>
+
+#define PFX "SoftDog: "
+
+#define TIMER_MARGIN   60              /* Default is 60 seconds */
+static int soft_margin = TIMER_MARGIN; /* in seconds */
+module_param(soft_margin, int, 0);
+MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+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) ")");
+
+#ifdef ONLY_TESTING
+static int soft_noboot = 1;
+#else
+static int soft_noboot = 0;
+#endif  /* ONLY_TESTING */
+
+module_param(soft_noboot, int, 0);
+MODULE_PARM_DESC(soft_noboot, "Softdog action, set to 1 to ignore reboots, 0 to reboot (default depends on ONLY_TESTING)");
+
+/*
+ *     Our timer
+ */
+
+static void watchdog_fire(unsigned long);
+
+static struct timer_list watchdog_ticktock =
+               TIMER_INITIALIZER(watchdog_fire, 0, 0);
+static unsigned long driver_open, orphan_timer;
+static char expect_close;
+
+
+/*
+ *     If the timer expires..
+ */
+
+static void watchdog_fire(unsigned long data)
+{
+       if (test_and_clear_bit(0, &orphan_timer))
+               module_put(THIS_MODULE);
+
+       if (soft_noboot)
+               printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
+       else
+       {
+               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               emergency_restart();
+               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+       }
+}
+
+/*
+ *     Softdog operations
+ */
+
+static int softdog_keepalive(void)
+{
+       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+       return 0;
+}
+
+static int softdog_stop(void)
+{
+       del_timer(&watchdog_ticktock);
+       return 0;
+}
+
+static int softdog_set_heartbeat(int t)
+{
+       if ((t < 0x0001) || (t > 0xFFFF))
+               return -EINVAL;
+
+       soft_margin = t;
+       return 0;
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int softdog_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &driver_open))
+               return -EBUSY;
+       if (!test_and_clear_bit(0, &orphan_timer))
+               __module_get(THIS_MODULE);
+       /*
+        *      Activate timer
+        */
+       softdog_keepalive();
+       return nonseekable_open(inode, file);
+}
+
+static int softdog_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if (expect_close == 42) {
+               softdog_stop();
+               module_put(THIS_MODULE);
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               set_bit(0, &orphan_timer);
+               softdog_keepalive();
+       }
+       clear_bit(0, &driver_open);
+       expect_close = 0;
+       return 0;
+}
+
+static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
+{
+       /*
+        *      Refresh the timer.
+        */
+       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;
+                       }
+               }
+               softdog_keepalive();
+       }
+       return len;
+}
+
+static int softdog_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_margin;
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT |
+                                       WDIOF_KEEPALIVEPING |
+                                       WDIOF_MAGICCLOSE,
+               .firmware_version =     0,
+               .identity =             "Software Watchdog",
+       };
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+               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:
+                       softdog_keepalive();
+                       return 0;
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_margin, p))
+                               return -EFAULT;
+                       if (softdog_set_heartbeat(new_margin))
+                               return -EINVAL;
+                       softdog_keepalive();
+                       /* Fall */
+               case WDIOC_GETTIMEOUT:
+                       return put_user(soft_margin, p);
+       }
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the WDT off */
+               softdog_stop();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations softdog_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = softdog_write,
+       .ioctl          = softdog_ioctl,
+       .open           = softdog_open,
+       .release        = softdog_release,
+};
+
+static struct miscdevice softdog_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &softdog_fops,
+};
+
+static struct notifier_block softdog_notifier = {
+       .notifier_call  = softdog_notify_sys,
+};
+
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n";
+
+static int __init watchdog_init(void)
+{
+       int ret;
+
+       /* Check that the soft_margin value is within it's range ; if not reset to the default */
+       if (softdog_set_heartbeat(soft_margin)) {
+               softdog_set_heartbeat(TIMER_MARGIN);
+               printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n",
+                       TIMER_MARGIN);
+       }
+
+       ret = register_reboot_notifier(&softdog_notifier);
+       if (ret) {
+               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = misc_register(&softdog_miscdev);
+       if (ret) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               unregister_reboot_notifier(&softdog_notifier);
+               return ret;
+       }
+
+       printk(banner, soft_noboot, soft_margin, nowayout);
+
+       return 0;
+}
+
+static void __exit watchdog_exit(void)
+{
+       misc_deregister(&softdog_miscdev);
+       unregister_reboot_notifier(&softdog_notifier);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("Software Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
new file mode 100644 (file)
index 0000000..df33b3b
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *     w83627hf/thf WDT driver
+ *
+ *     (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
+ *             added support for W83627THF.
+ *
+ *     (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com>
+ *
+ *     Based on advantechwdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define WATCHDOG_NAME "w83627hf/thf/hg WDT"
+#define PFX WATCHDOG_NAME ": "
+#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
+
+static unsigned long wdt_is_open;
+static char expect_close;
+static spinlock_t io_lock;
+
+/* You must set this - there is no sane way to probe for this board. */
+static int wdt_io = 0x2E;
+module_param(wdt_io, int, 0);
+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 <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+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) ")");
+
+/*
+ *     Kernel methods.
+ */
+
+#define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
+#define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register (same as EFER) */
+#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
+
+static void
+w83627hf_select_wd_register(void)
+{
+       unsigned char c;
+       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   */
+       c = inb(WDT_EFDR);
+       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);
+               outb_p(c, WDT_EFDR);    /* set GPIO3 to WDT0 */
+       }
+
+       outb_p(0x07, WDT_EFER); /* point to logical device number reg */
+       outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
+       outb_p(0x30, WDT_EFER); /* select CR30 */
+       outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+}
+
+static void
+w83627hf_unselect_wd_register(void)
+{
+       outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
+}
+
+/* tyan motherboards seem to set F5 to 0x4C ?
+ * So explicitly init to appropriate value. */
+static void
+w83627hf_init(void)
+{
+       unsigned char t;
+
+       w83627hf_select_wd_register();
+
+       outb_p(0xF6, WDT_EFER); /* Select CRF6 */
+       t=inb_p(WDT_EFDR);      /* read CRF6 */
+       if (t != 0) {
+               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();
+}
+
+static void
+wdt_ctrl(int timeout)
+{
+       spin_lock(&io_lock);
+
+       w83627hf_select_wd_register();
+
+       outb_p(0xF6, WDT_EFER);    /* Select CRF6 */
+       outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */
+
+       w83627hf_unselect_wd_register();
+
+       spin_unlock(&io_lock);
+}
+
+static int
+wdt_ping(void)
+{
+       wdt_ctrl(timeout);
+       return 0;
+}
+
+static int
+wdt_disable(void)
+{
+       wdt_ctrl(0);
+       return 0;
+}
+
+static int
+wdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 255))
+               return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+static ssize_t
+wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               wdt_ping();
+       }
+       return count;
+}
+
+static int
+wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_timeout;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "W83627HF WDT",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user(argp, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+         return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+         wdt_ping();
+         break;
+
+       case WDIOC_SETTIMEOUT:
+         if (get_user(new_timeout, p))
+                 return -EFAULT;
+         if (wdt_set_heartbeat(new_timeout))
+                 return -EINVAL;
+         wdt_ping();
+         /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+         return put_user(timeout, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+         int options, retval = -EINVAL;
+
+         if (get_user(options, p))
+           return -EFAULT;
+
+         if (options & WDIOS_DISABLECARD) {
+           wdt_disable();
+           retval = 0;
+         }
+
+         if (options & WDIOS_ENABLECARD) {
+           wdt_ping();
+           retval = 0;
+         }
+
+         return retval;
+       }
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+       /*
+        *      Activate
+        */
+
+       wdt_ping();
+       return nonseekable_open(inode, file);
+}
+
+static int
+wdt_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               wdt_disable();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               wdt_ping();
+       }
+       expect_close = 0;
+       clear_bit(0, &wdt_is_open);
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int
+wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the WDT off */
+               wdt_disable();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdt_write,
+       .ioctl          = wdt_ioctl,
+       .open           = wdt_open,
+       .release        = wdt_close,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &wdt_fops,
+};
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+       .notifier_call = wdt_notify_sys,
+};
+
+static int __init
+wdt_init(void)
+{
+       int ret;
+
+       spin_lock_init(&io_lock);
+
+       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<=255, using %d\n",
+                       WATCHDOG_TIMEOUT);
+       }
+
+       if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
+               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_io);
+               ret = -EIO;
+               goto out;
+       }
+
+       w83627hf_init();
+
+       ret = register_reboot_notifier(&wdt_notifier);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               goto unreg_regions;
+       }
+
+       ret = misc_register(&wdt_miscdev);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto unreg_reboot;
+       }
+
+       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+out:
+       return ret;
+unreg_reboot:
+       unregister_reboot_notifier(&wdt_notifier);
+unreg_regions:
+       release_region(wdt_io, 1);
+       goto out;
+}
+
+static void __exit
+wdt_exit(void)
+{
+       misc_deregister(&wdt_miscdev);
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(wdt_io,1);
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
+MODULE_DESCRIPTION("w83627hf/thf WDT driver");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c
new file mode 100644 (file)
index 0000000..d9e821d
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ *     w83697hf/hg WDT driver
+ *
+ *     (c) Copyright 2006 Samuel Tardieu <sam@rfc1149.net>
+ *     (c) Copyright 2006 Marcus Junker <junker@anduras.de>
+ *
+ *     Based on w83627hf_wdt.c which is based on advantechwdt.c
+ *     which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Marcus Junker nor ANDURAS AG admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define WATCHDOG_NAME "w83697hf/hg WDT"
+#define PFX WATCHDOG_NAME ": "
+#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
+
+static unsigned long wdt_is_open;
+static char expect_close;
+static spinlock_t io_lock;
+
+/* You must set this - there is no sane way to probe for this board. */
+static int wdt_io = 0x2e;
+module_param(wdt_io, int, 0);
+MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)");
+
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+module_param(timeout, int, 0);
+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);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/*
+ *     Kernel methods.
+ */
+
+#define W83697HF_EFER (wdt_io+0)       /* Extended Function Enable Register */
+#define W83697HF_EFIR (wdt_io+0)       /* Extended Function Index Register (same as EFER) */
+#define W83697HF_EFDR (wdt_io+1)       /* Extended Function Data Register */
+
+static inline void
+w83697hf_unlock(void)
+{
+       outb_p(0x87, W83697HF_EFER);    /* Enter extended function mode */
+       outb_p(0x87, W83697HF_EFER);    /* Again according to manual */
+}
+
+static inline void
+w83697hf_lock(void)
+{
+       outb_p(0xAA, W83697HF_EFER);    /* Leave extended function mode */
+}
+
+/*
+ *     The three functions w83697hf_get_reg(), w83697hf_set_reg() and
+ *     w83697hf_write_timeout() must be called with the device unlocked.
+ */
+
+static unsigned char
+w83697hf_get_reg(unsigned char reg)
+{
+       outb_p(reg, W83697HF_EFIR);
+       return inb_p(W83697HF_EFDR);
+}
+
+static void
+w83697hf_set_reg(unsigned char reg, unsigned char data)
+{
+       outb_p(reg, W83697HF_EFIR);
+       outb_p(data, W83697HF_EFDR);
+}
+
+static void
+w83697hf_write_timeout(int timeout)
+{
+       w83697hf_set_reg(0xF4, timeout);        /* Write Timeout counter to CRF4 */
+}
+
+static void
+w83697hf_select_wdt(void)
+{
+       w83697hf_unlock();
+       w83697hf_set_reg(0x07, 0x08);   /* Switch to logic device 8 (GPIO2) */
+}
+
+static inline void
+w83697hf_deselect_wdt(void)
+{
+       w83697hf_lock();
+}
+
+static void
+w83697hf_init(void)
+{
+       unsigned char bbuf;
+
+       w83697hf_select_wdt();
+
+       bbuf = w83697hf_get_reg(0x29);
+       bbuf &= ~0x60;
+       bbuf |= 0x20;
+       w83697hf_set_reg(0x29, bbuf);   /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
+
+       bbuf = w83697hf_get_reg(0xF3);
+       bbuf &= ~0x04;
+       w83697hf_set_reg(0xF3, bbuf);   /* Count mode is seconds */
+
+       w83697hf_deselect_wdt();
+}
+
+static int
+wdt_ping(void)
+{
+       spin_lock(&io_lock);
+       w83697hf_select_wdt();
+
+       w83697hf_write_timeout(timeout);
+
+       w83697hf_deselect_wdt();
+       spin_unlock(&io_lock);
+       return 0;
+}
+
+static int
+wdt_enable(void)
+{
+       spin_lock(&io_lock);
+       w83697hf_select_wdt();
+
+       w83697hf_write_timeout(timeout);
+       w83697hf_set_reg(0x30, 1);      /* Enable timer */
+
+       w83697hf_deselect_wdt();
+       spin_unlock(&io_lock);
+       return 0;
+}
+
+static int
+wdt_disable(void)
+{
+       spin_lock(&io_lock);
+       w83697hf_select_wdt();
+
+       w83697hf_set_reg(0x30, 0);      /* Disable timer */
+       w83697hf_write_timeout(0);
+
+       w83697hf_deselect_wdt();
+       spin_unlock(&io_lock);
+       return 0;
+}
+
+static int
+wdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 255))
+               return -EINVAL;
+
+       timeout = t;
+       return 0;
+}
+
+static ssize_t
+wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               wdt_ping();
+       }
+       return count;
+}
+
+static int
+wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_timeout;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "W83697HF WDT",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &ident, sizeof(ident)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+               wdt_ping();
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_timeout, p))
+                       return -EFAULT;
+               if (wdt_set_heartbeat(new_timeout))
+                       return -EINVAL;
+               wdt_ping();
+               /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+               int options, retval = -EINVAL;
+
+               if (get_user(options, p))
+                       return -EFAULT;
+
+               if (options & WDIOS_DISABLECARD) {
+                       wdt_disable();
+                       retval = 0;
+               }
+
+               if (options & WDIOS_ENABLECARD) {
+                       wdt_enable();
+                       retval = 0;
+               }
+
+               return retval;
+       }
+
+       default:
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+       /*
+        *      Activate
+        */
+
+       wdt_enable();
+       return nonseekable_open(inode, file);
+}
+
+static int
+wdt_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               wdt_disable();
+       } else {
+               printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               wdt_ping();
+       }
+       expect_close = 0;
+       clear_bit(0, &wdt_is_open);
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int
+wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the WDT off */
+               wdt_disable();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdt_write,
+       .ioctl          = wdt_ioctl,
+       .open           = wdt_open,
+       .release        = wdt_close,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &wdt_fops,
+};
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+       .notifier_call = wdt_notify_sys,
+};
+
+static int
+w83697hf_check_wdt(void)
+{
+       if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
+               printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io);
+               return -EIO;
+       }
+
+       printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io);
+       w83697hf_unlock();
+       if (w83697hf_get_reg(0x20) == 0x60) {
+               printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io);
+               w83697hf_lock();
+               return 0;
+       }
+       w83697hf_lock();        /* Reprotect in case it was a compatible device */
+
+       printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
+       release_region(wdt_io, 2);
+       return -EIO;
+}
+
+static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 };
+
+static int __init
+wdt_init(void)
+{
+       int ret, i, found = 0;
+
+       spin_lock_init(&io_lock);
+
+       printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
+
+       if (wdt_io == 0) {
+               /* we will autodetect the W83697HF/HG watchdog */
+               for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) {
+                       wdt_io = w83697hf_ioports[i];
+                       if (!w83697hf_check_wdt())
+                               found++;
+               }
+       } else {
+               if (!w83697hf_check_wdt())
+                       found++;
+       }
+
+       if (!found) {
+               printk (KERN_ERR PFX "No W83697HF/HG could be found\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       w83697hf_init();
+       wdt_disable();  /* Disable watchdog until first use */
+
+       if (wdt_set_heartbeat(timeout)) {
+               wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n",
+                       WATCHDOG_TIMEOUT);
+       }
+
+       ret = register_reboot_notifier(&wdt_notifier);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               goto unreg_regions;
+       }
+
+       ret = misc_register(&wdt_miscdev);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto unreg_reboot;
+       }
+
+       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+out:
+       return ret;
+unreg_reboot:
+       unregister_reboot_notifier(&wdt_notifier);
+unreg_regions:
+       release_region(wdt_io, 2);
+       goto out;
+}
+
+static void __exit
+wdt_exit(void)
+{
+       misc_deregister(&wdt_miscdev);
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(wdt_io, 2);
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marcus Junker <junker@anduras.de>, Samuel Tardieu <sam@rfc1149.net>");
+MODULE_DESCRIPTION("w83697hf/hg WDT driver");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c
new file mode 100644 (file)
index 0000000..3c88fe1
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ *     W83877F Computer Watchdog Timer driver
+ *
+ *      Based on acquirewdt.c by Alan Cox,
+ *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@unthought.net>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     The authors do NOT admit liability nor provide warranty for
+ *     any of this software. This material is provided "AS-IS" in
+ *      the hope that it may be useful for others.
+ *
+ *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
+ *
+ *           4/19 - 2001      [Initial revision]
+ *           9/27 - 2001      Added spinlocking
+ *           4/12 - 2002      [rob@osinvestor.com] Eliminate extra comments
+ *                            Eliminate fop_read
+ *                            Eliminate extra spin_unlock
+ *                            Added KERN_* tags to printks
+ *                            add CONFIG_WATCHDOG_NOWAYOUT support
+ *                            fix possible wdt_is_open race
+ *                            changed watchdog_info to correctly reflect what the driver offers
+ *                            added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT,
+ *                            WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls
+ *           09/8 - 2003      [wim@iguana.be] cleanup of trailing spaces
+ *                            added extra printk's for startup problems
+ *                            use module_param
+ *                            made timeout (the emulated heartbeat) a module_param
+ *                            made the keepalive ping an internal subroutine
+ *
+ *  This WDT driver is different from most other Linux WDT
+ *  drivers in that the driver will ping the watchdog by itself,
+ *  because this particular WDT has a very short timeout (1.6
+ *  seconds) and it would be insane to count on any userspace
+ *  daemon always getting scheduled within that time frame.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define OUR_NAME "w83877f_wdt"
+#define PFX OUR_NAME ": "
+
+#define ENABLE_W83877F_PORT 0x3F0
+#define ENABLE_W83877F 0x87
+#define DISABLE_W83877F 0xAA
+#define WDT_PING 0x443
+#define WDT_REGISTER 0x14
+#define WDT_ENABLE 0x9C
+#define WDT_DISABLE 0x8C
+
+/*
+ * The W83877F seems to be fixed at 1.6s timeout (at least on the
+ * EMACS PC-104 board I'm using). If we reset the watchdog every
+ * ~250ms we should be safe.  */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 30 seconds.
+ */
+
+#define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+
+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 wdt_timer_ping(unsigned long);
+static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0);
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static char wdt_expect_close;
+static spinlock_t wdt_spinlock;
+
+/*
+ *     Whack the dog
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT
+        */
+       if(time_before(jiffies, next_heartbeat))
+       {
+               /* Ping the WDT */
+               spin_lock(&wdt_spinlock);
+
+               /* Ping the WDT by reading from WDT_PING */
+               inb_p(WDT_PING);
+
+               /* Re-set the timer interval */
+               mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+               spin_unlock(&wdt_spinlock);
+
+       } else {
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+/*
+ * Utility routines
+ */
+
+static void wdt_change(int writeval)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&wdt_spinlock, flags);
+
+       /* buy some time */
+       inb_p(WDT_PING);
+
+       /* make W83877F available */
+       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
+       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
+
+       /* enable watchdog */
+       outb_p(WDT_REGISTER,    ENABLE_W83877F_PORT);
+       outb_p(writeval,        ENABLE_W83877F_PORT+1);
+
+       /* lock the W8387FF away */
+       outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT);
+
+       spin_unlock_irqrestore(&wdt_spinlock, flags);
+}
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + (timeout * HZ);
+
+       /* Start the timer */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+       wdt_change(WDT_ENABLE);
+
+       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+}
+
+static void wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer(&timer);
+
+       wdt_change(WDT_DISABLE);
+
+       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+}
+
+static void wdt_keepalive(void)
+{
+       /* user land ping */
+       next_heartbeat = jiffies + (timeout * HZ);
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count)
+       {
+               if (!nowayout)
+               {
+                       size_t ofs;
+
+                       /* note: just in case someone wrote the magic character
+                        * five months ago... */
+                       wdt_expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for(ofs = 0; ofs != count; ofs++)
+                       {
+                               char c;
+                               if (get_user(c, buf + ofs))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       wdt_expect_close = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should restart timer */
+               wdt_keepalive();
+       }
+       return count;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       /* Just in case we're already talking to someone... */
+       if(test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+
+       /* Good, fire up the show */
+       wdt_startup();
+       return nonseekable_open(inode, file);
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(wdt_expect_close == 42)
+               wdt_turnoff();
+       else {
+               del_timer(&timer);
+               printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n");
+       }
+       clear_bit(0, &wdt_is_open);
+       wdt_expect_close = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident=
+       {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "W83877F",
+       };
+
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               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:
+                       wdt_keepalive();
+                       return 0;
+               case WDIOC_SETOPTIONS:
+               {
+                       int new_options, retval = -EINVAL;
+
+                       if(get_user(new_options, p))
+                               return -EFAULT;
+
+                       if(new_options & WDIOS_DISABLECARD) {
+                               wdt_turnoff();
+                               retval = 0;
+                       }
+
+                       if(new_options & WDIOS_ENABLECARD) {
+                               wdt_startup();
+                               retval = 0;
+                       }
+
+                       return retval;
+               }
+               case WDIOC_SETTIMEOUT:
+               {
+                       int new_timeout;
+
+                       if(get_user(new_timeout, p))
+                               return -EFAULT;
+
+                       if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
+                               return -EINVAL;
+
+                       timeout = new_timeout;
+                       wdt_keepalive();
+                       /* Fall through */
+               }
+               case WDIOC_GETTIMEOUT:
+                       return put_user(timeout, p);
+       }
+}
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = fop_write,
+       .open           = fop_open,
+       .release        = fop_close,
+       .ioctl          = fop_ioctl,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wdt_fops,
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+               wdt_turnoff();
+       return NOTIFY_DONE;
+}
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier=
+{
+       .notifier_call = wdt_notify_sys,
+};
+
+static void __exit w83877f_wdt_unload(void)
+{
+       wdt_turnoff();
+
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(WDT_PING,1);
+       release_region(ENABLE_W83877F_PORT,2);
+}
+
+static int __init w83877f_wdt_init(void)
+{
+       int rc = -EBUSY;
+
+       spin_lock_init(&wdt_spinlock);
+
+       if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
+       {
+               timeout = WATCHDOG_TIMEOUT;
+               printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
+                       timeout);
+       }
+
+       if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
+       {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       ENABLE_W83877F_PORT);
+               rc = -EIO;
+               goto err_out;
+       }
+
+       if (!request_region(WDT_PING, 1, "W8387FF WDT"))
+       {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       WDT_PING);
+               rc = -EIO;
+               goto err_out_region1;
+       }
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       wdt_miscdev.minor, rc);
+               goto err_out_region2;
+       }
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_miscdev;
+       }
+
+       printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out_region2:
+       release_region(WDT_PING,1);
+err_out_region1:
+       release_region(ENABLE_W83877F_PORT,2);
+err_out:
+       return rc;
+}
+
+module_init(w83877f_wdt_init);
+module_exit(w83877f_wdt_unload);
+
+MODULE_AUTHOR("Scott and Bill Jennings");
+MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
new file mode 100644 (file)
index 0000000..1579684
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ *     W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ *     (c) Copyright 2005  Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ *      Based on w83877f_wdt.c by Scott Jennings,
+ *           and wdt977.c by Woody Suwalski
+ *
+ *                     -----------------------
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ */
+
+#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/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION  "1.00"
+#define WATCHDOG_NAME     "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT     0x3F0
+#define IO_DATA_PORT      (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA       0x87
+#define LOCK_DATA         0xAA
+#define DEVICE_REGISTER   0x07
+
+#define        DEFAULT_TIMEOUT   45            /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutW;                   /* timeout in watchdog counter units */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+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) ")");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* Unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+       /*
+        * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+        * F2 has the timeout in watchdog counter units.
+        * F3 is set to enable watchdog LED blink at timeout.
+        * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+        */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+       outb_p(0xF2,IO_INDEX_PORT);
+       outb_p(timeoutW,IO_DATA_PORT);
+       outb_p(0xF3,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+       outb_p(0xF4,IO_INDEX_PORT);
+       outb_p(0x00,IO_DATA_PORT);
+
+       /* Set device Aux2 active */
+       outb_p(0x30,IO_INDEX_PORT);
+       outb_p(0x01,IO_DATA_PORT);
+
+       /* 
+        * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+        * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+        * Map GP16 at pin 119.
+        * In test mode watch the bit 0 on F4 to indicate "triggered" or
+        * check watchdog LED on SBC.
+        */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x07,IO_DATA_PORT);
+       if (!testmode)
+       {
+               unsigned pin_map;
+
+               outb_p(0xE6,IO_INDEX_PORT);
+               outb_p(0x0A,IO_DATA_PORT);
+               outb_p(0x2C,IO_INDEX_PORT);
+               pin_map = inb_p(IO_DATA_PORT);
+               pin_map |= 0x10;
+               pin_map &= ~(0x20);
+               outb_p(0x2C,IO_INDEX_PORT);
+               outb_p(pin_map,IO_DATA_PORT);
+       }
+       outb_p(0xE3,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+
+       /* Set device Aux1 active */
+       outb_p(0x30,IO_INDEX_PORT);
+       outb_p(0x01,IO_DATA_PORT);
+
+       /* Lock the SuperIO chip */
+       outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       printk(KERN_INFO PFX "activated.\n");
+
+       return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* Unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+       /* 
+        * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+        * F2 is reset to its default value (watchdog timer disabled).
+        * F3 is reset to its default state.
+        * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+        */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+       outb_p(0xF2,IO_INDEX_PORT);
+       outb_p(0xFF,IO_DATA_PORT);
+       outb_p(0xF3,IO_INDEX_PORT);
+       outb_p(0x00,IO_DATA_PORT);
+       outb_p(0xF4,IO_INDEX_PORT);
+       outb_p(0x00,IO_DATA_PORT);
+       outb_p(0xF2,IO_INDEX_PORT);
+       outb_p(0x00,IO_DATA_PORT);
+
+       /*
+        * Select device Aux1 (dev=7) to set GP16 (in reg E6) and 
+        * Gp13 (in reg E3) as inputs.
+        */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x07,IO_DATA_PORT);
+       if (!testmode)
+       {
+               outb_p(0xE6,IO_INDEX_PORT);
+               outb_p(0x01,IO_DATA_PORT);
+       }
+       outb_p(0xE3,IO_INDEX_PORT);
+       outb_p(0x01,IO_DATA_PORT);
+
+       /* Lock the SuperIO chip */
+       outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       printk(KERN_INFO PFX "shutdown.\n");
+
+       return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* Unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+       /* Select device Aux2 (device=8) to kick watchdog reg F2 */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+       outb_p(0xF2,IO_INDEX_PORT);
+       outb_p(timeoutW,IO_DATA_PORT);
+
+       /* Lock the SuperIO chip */
+       outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+       int tmrval;
+
+       /*
+        * Convert seconds to watchdog counter time units, rounding up.
+        * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup 
+        * value. This information is supplied in the PCM-5335 manual and was
+        * checked by me on a real board. This is a bit strange because W83977f
+        * datasheet says counter unit is in minutes!
+        */
+       if (t < 15)
+               return -EINVAL;
+
+       tmrval = ((t + 15) + 29) / 30;
+
+       if (tmrval > 255)
+               return -EINVAL;
+
+       /*
+        * timeout is the timeout in seconds, 
+        * timeoutW is the timeout in watchdog counter units.
+        */
+       timeoutW = tmrval;
+       timeout = (timeoutW * 30) - 15;
+       return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+       int new_status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* Unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+       /* Select device Aux2 (device=8) to read watchdog reg F4 */
+       outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+       outb_p(0x08,IO_DATA_PORT);
+       outb_p(0xF4,IO_INDEX_PORT);
+       new_status = inb_p(IO_DATA_PORT);
+
+       /* Lock the SuperIO chip */
+       outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       *status = 0;
+       if (new_status & 1)
+               *status |= WDIOF_CARDRESET;
+
+       return 0;
+}
+
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+       /* If the watchdog is alive we don't need to start it again */
+       if( test_and_set_bit(0, &timer_alive) )
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+       /*
+        * Shut off the timer.
+        * Lock it in if it's a module and we set nowayout
+        */
+       if (expect_close == 42)
+       {
+               wdt_stop();
+               clear_bit(0, &timer_alive);
+       } else {
+               wdt_keepalive();
+               printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+       }
+       expect_close = 0;
+       return 0;
+}
+
+/*
+ *      wdt_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if(count)
+       {
+               if (!nowayout)
+               {
+                       size_t ofs;
+
+                       /* note: just in case someone wrote the magic character long ago */
+                       expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for(ofs = 0; ofs != count; ofs++)
+                       {
+                               char c;
+                               if (get_user(c, buf + ofs))
+                                       return -EFAULT;
+                               if (c == 'V') {
+                                       expect_close = 42;
+                               }
+                       }
+               }
+
+               /* someone wrote to us, we should restart timer */
+               wdt_keepalive();
+       }
+       return count;
+}
+
+/*
+ *      wdt_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static struct watchdog_info ident = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+       .firmware_version =     1,
+       .identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int status;
+       int new_options, retval = -EINVAL;
+       int new_timeout;
+       union {
+               struct watchdog_info __user *ident;
+               int __user *i;
+       } uarg;
+
+       uarg.i = (int __user *)arg;
+
+       switch(cmd)
+       {
+       default:
+               return -ENOTTY;
+
+       case WDIOC_GETSUPPORT:
+               return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+       case WDIOC_GETSTATUS:
+               wdt_get_status(&status);
+               return put_user(status, uarg.i);
+
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, uarg.i);
+
+       case WDIOC_KEEPALIVE:
+               wdt_keepalive();
+               return 0;
+
+       case WDIOC_SETOPTIONS:
+               if (get_user (new_options, uarg.i))
+                       return -EFAULT;
+
+               if (new_options & WDIOS_DISABLECARD) {
+                       wdt_stop();
+                       retval = 0;
+               }
+
+               if (new_options & WDIOS_ENABLECARD) {
+                       wdt_start();
+                       retval = 0;
+               }
+
+               return retval;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_timeout, uarg.i))
+                       return -EFAULT;
+
+               if (wdt_set_timeout(new_timeout))
+                   return -EINVAL;
+
+               wdt_keepalive();
+               /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout, uarg.i);
+
+       }
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT)
+               wdt_stop();
+       return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt_fops=
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdt_write,
+       .ioctl          = wdt_ioctl,
+       .open           = wdt_open,
+       .release        = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+       .notifier_call = wdt_notify_sys,
+};
+
+static int __init w83977f_wdt_init(void)
+{
+       int rc;
+
+        printk(KERN_INFO PFX DRIVER_VERSION);
+
+       spin_lock_init(&spinlock);
+
+       /*
+        * Check that the timeout value is within it's range ; 
+        * if not reset to the default
+        */
+       if (wdt_set_timeout(timeout)) {
+               wdt_set_timeout(DEFAULT_TIMEOUT);
+               printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+                       DEFAULT_TIMEOUT);
+       }
+
+       if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+       {
+               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       IO_INDEX_PORT);
+               rc = -EIO;
+               goto err_out;
+       }
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       wdt_miscdev.minor, rc);
+               goto err_out_region;
+       }
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_miscdev;
+       }
+
+       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+               timeout, nowayout, testmode);
+
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out_region:
+       release_region(IO_INDEX_PORT,2);
+err_out:
+       return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+       wdt_stop();
+       misc_deregister(&wdt_miscdev);
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c
new file mode 100644 (file)
index 0000000..950905d
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ *     ICP Wafer 5823 Single Board Computer WDT driver
+ *      http://www.icpamerica.com/wafer_5823.php
+ *      May also work on other similar models
+ *
+ *     (c) Copyright 2002 Justin Cormack <justin@street-vision.com>
+ *
+ *      Release 0.02
+ *
+ *     Based on advantechwdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_NAME "Wafer 5823 WDT"
+#define PFX WATCHDOG_NAME ": "
+#define WD_TIMO 60                     /* 60 sec default timeout */
+
+static unsigned long wafwdt_is_open;
+static char expect_close;
+static spinlock_t wafwdt_lock;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ *
+ *      To enable, write the timeout value in seconds (1 to 255) to I/O
+ *      port WDT_START, then read the port to start the watchdog. To pat
+ *      the dog, read port WDT_STOP to stop the timer, then read WDT_START
+ *      to restart it again.
+ */
+
+static int wdt_stop = 0x843;
+static int wdt_start = 0x443;
+
+static int timeout = WD_TIMO;  /* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) ".");
+
+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 wafwdt_ping(void)
+{
+       /* pat watchdog */
+       spin_lock(&wafwdt_lock);
+       inb_p(wdt_stop);
+       inb_p(wdt_start);
+       spin_unlock(&wafwdt_lock);
+}
+
+static void wafwdt_start(void)
+{
+       /* start up watchdog */
+       outb_p(timeout, wdt_start);
+       inb_p(wdt_start);
+}
+
+static void
+wafwdt_stop(void)
+{
+       /* stop watchdog */
+       inb_p(wdt_stop);
+}
+
+static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
+{
+       /* See if we got the magic character 'V' and reload the timer */
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       /* scan to see whether or not we got the magic character */
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               /* Well, anyhow someone wrote to us, we should return that favour */
+               wafwdt_ping();
+       }
+       return count;
+}
+
+static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+            unsigned long arg)
+{
+       int new_timeout;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+               .firmware_version = 1,
+               .identity = "Wafer 5823 WDT",
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &ident, sizeof (ident)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, p);
+
+       case WDIOC_KEEPALIVE:
+               wafwdt_ping();
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_timeout, p))
+                       return -EFAULT;
+               if ((new_timeout < 1) || (new_timeout > 255))
+                       return -EINVAL;
+               timeout = new_timeout;
+               wafwdt_stop();
+               wafwdt_start();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+               int options, retval = -EINVAL;
+
+               if (get_user(options, p))
+                       return -EFAULT;
+
+               if (options & WDIOS_DISABLECARD) {
+                       wafwdt_start();
+                       retval = 0;
+               }
+
+               if (options & WDIOS_ENABLECARD) {
+                       wafwdt_stop();
+                       retval = 0;
+               }
+
+               return retval;
+       }
+
+       default:
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static int wafwdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &wafwdt_is_open))
+               return -EBUSY;
+
+       /*
+        *      Activate
+        */
+       wafwdt_start();
+       return nonseekable_open(inode, file);
+}
+
+static int
+wafwdt_close(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               wafwdt_stop();
+       } else {
+               printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
+               wafwdt_ping();
+       }
+       clear_bit(0, &wafwdt_is_open);
+       expect_close = 0;
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the WDT off */
+               wafwdt_stop();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations wafwdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wafwdt_write,
+       .ioctl          = wafwdt_ioctl,
+       .open           = wafwdt_open,
+       .release        = wafwdt_close,
+};
+
+static struct miscdevice wafwdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wafwdt_fops,
+};
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wafwdt_notifier = {
+       .notifier_call = wafwdt_notify_sys,
+};
+
+static int __init wafwdt_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n");
+
+       spin_lock_init(&wafwdt_lock);
+
+       if (timeout < 1 || timeout > 255) {
+               timeout = WD_TIMO;
+               printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n",
+                       timeout);
+       }
+
+       if (wdt_stop != wdt_start) {
+               if(!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
+                       printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_stop);
+                       ret = -EIO;
+                       goto error;
+               }
+       }
+
+       if(!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
+               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                       wdt_start);
+               ret = -EIO;
+               goto error2;
+       }
+
+       ret = register_reboot_notifier(&wafwdt_notifier);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       ret);
+               goto error3;
+       }
+
+       ret = misc_register(&wafwdt_miscdev);
+       if (ret != 0) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto error4;
+       }
+
+       printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+       return ret;
+error4:
+       unregister_reboot_notifier(&wafwdt_notifier);
+error3:
+       release_region(wdt_start, 1);
+error2:
+       if (wdt_stop != wdt_start)
+               release_region(wdt_stop, 1);
+error:
+       return ret;
+}
+
+static void __exit wafwdt_exit(void)
+{
+       misc_deregister(&wafwdt_miscdev);
+       unregister_reboot_notifier(&wafwdt_notifier);
+       if(wdt_stop != wdt_start)
+               release_region(wdt_stop, 1);
+       release_region(wdt_start, 1);
+}
+
+module_init(wafwdt_init);
+module_exit(wafwdt_exit);
+
+MODULE_AUTHOR("Justin Cormack");
+MODULE_DESCRIPTION("ICP Wafer 5823 Single Board Computer WDT driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of wafer5823wdt.c */
diff --git a/drivers/watchdog/wd501p.h b/drivers/watchdog/wd501p.h
new file mode 100644 (file)
index 0000000..a4504f4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *     Industrial Computer Source WDT500/501 driver
+ *
+ *     (c) Copyright 1995      CymruNET Ltd
+ *                             Innovation Centre
+ *                             Singleton Park
+ *                             Swansea
+ *                             Wales
+ *                             UK
+ *                             SA2 8PP
+ *
+ *     http://www.cymru.net
+ *
+ *     This driver is provided under the GNU General Public License, incorporated
+ *     herein by reference. The driver is provided without warranty or 
+ *     support.
+ *
+ *     Release 0.04.
+ *
+ */
+
+
+#define WDT_COUNT0             (io+0)
+#define WDT_COUNT1             (io+1)
+#define WDT_COUNT2             (io+2)
+#define WDT_CR                 (io+3)
+#define WDT_SR                 (io+4)  /* Start buzzer on PCI write */
+#define WDT_RT                 (io+5)  /* Stop buzzer on PCI write */
+#define WDT_BUZZER             (io+6)  /* PCI only: rd=disable, wr=enable */
+#define WDT_DC                 (io+7)
+
+/* The following are only on the PCI card, they're outside of I/O space on
+ * the ISA card: */
+#define WDT_CLOCK              (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */
+/* inverted opto isolated reset output: */
+#define WDT_OPTONOTRST         (io+13) /* wr=enable, rd=disable */
+/* opto isolated reset output: */
+#define WDT_OPTORST            (io+14) /* wr=enable, rd=disable */
+/* programmable outputs: */
+#define WDT_PROGOUT            (io+15) /* wr=enable, rd=disable */
+
+                                                               /* FAN 501 500 */
+#define WDC_SR_WCCR            1       /* Active low */        /*  X   X   X  */
+#define WDC_SR_TGOOD           2                               /*  X   X   -  */
+#define WDC_SR_ISOI0           4                               /*  X   X   X  */
+#define WDC_SR_ISII1           8                               /*  X   X   X  */
+#define WDC_SR_FANGOOD         16                              /*  X   -   -  */
+#define WDC_SR_PSUOVER         32      /* Active low */        /*  X   X   -  */
+#define WDC_SR_PSUUNDR         64      /* Active low */        /*  X   X   -  */
+#define WDC_SR_IRQ             128     /* Active low */        /*  X   X   X  */
+
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
new file mode 100644 (file)
index 0000000..1d64e27
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
+ * RTAS calls are available
+ */
+
+/*
+ * RTAS watchdog driver
+ *
+ * (C) Copyright IBM Corp. 2005
+ * device driver to exploit watchdog RTAS functions
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#include <asm/rtas.h>
+#include <asm/uaccess.h>
+
+#define WDRTAS_MAGIC_CHAR              42
+#define WDRTAS_SUPPORTED_MASK          (WDIOF_SETTIMEOUT | \
+                                        WDIOF_MAGICCLOSE)
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
+MODULE_DESCRIPTION("RTAS watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int wdrtas_nowayout = 1;
+#else
+static int wdrtas_nowayout = 0;
+#endif
+
+static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
+static char wdrtas_expect_close = 0;
+
+static int wdrtas_interval;
+
+#define WDRTAS_THERMAL_SENSOR          3
+static int wdrtas_token_get_sensor_state;
+#define WDRTAS_SURVEILLANCE_IND                9000
+static int wdrtas_token_set_indicator;
+#define WDRTAS_SP_SPI                  28
+static int wdrtas_token_get_sp;
+static int wdrtas_token_event_scan;
+
+#define WDRTAS_DEFAULT_INTERVAL                300
+
+#define WDRTAS_LOGBUFFER_LEN           128
+static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
+
+
+/*** watchdog access functions */
+
+/**
+ * wdrtas_set_interval - sets the watchdog interval
+ * @interval: new interval
+ *
+ * returns 0 on success, <0 on failures
+ *
+ * wdrtas_set_interval sets the watchdog keepalive interval by calling the
+ * RTAS function set-indicator (surveillance). The unit of interval is
+ * seconds.
+ */
+static int
+wdrtas_set_interval(int interval)
+{
+       long result;
+       static int print_msg = 10;
+
+       /* rtas uses minutes */
+       interval = (interval + 59) / 60;
+
+       result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
+                          WDRTAS_SURVEILLANCE_IND, 0, interval);
+       if ( (result < 0) && (print_msg) ) {
+               printk(KERN_ERR "wdrtas: setting the watchdog to %i "
+                      "timeout failed: %li\n", interval, result);
+               print_msg--;
+       }
+
+       return result;
+}
+
+/**
+ * wdrtas_get_interval - returns the current watchdog interval
+ * @fallback_value: value (in seconds) to use, if the RTAS call fails
+ *
+ * returns the interval
+ *
+ * wdrtas_get_interval returns the current watchdog keepalive interval
+ * as reported by the RTAS function ibm,get-system-parameter. The unit
+ * of the return value is seconds.
+ */
+static int
+wdrtas_get_interval(int fallback_value)
+{
+       long result;
+       char value[4];
+
+       result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
+                          WDRTAS_SP_SPI, (void *)__pa(&value), 4);
+       if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
+            (result < 0) ) {
+               printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
+                      "timeout (%li). Continuing\n", result);
+               return fallback_value;
+       }
+
+       /* rtas uses minutes */
+       return ((int)value[2]) * 60;
+}
+
+/**
+ * wdrtas_timer_start - starts watchdog
+ *
+ * wdrtas_timer_start starts the watchdog by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_start(void)
+{
+       wdrtas_set_interval(wdrtas_interval);
+}
+
+/**
+ * wdrtas_timer_stop - stops watchdog
+ *
+ * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_stop(void)
+{
+       wdrtas_set_interval(0);
+}
+
+/**
+ * wdrtas_log_scanned_event - logs an event we received during keepalive
+ *
+ * wdrtas_log_scanned_event prints a message to the log buffer dumping
+ * the results of the last event-scan call
+ */
+static void
+wdrtas_log_scanned_event(void)
+{
+       int i;
+
+       for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
+               printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
+                      "%02x %02x %02x %02x  %02x %02x %02x %02x   "
+                      "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                      (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
+                      wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], 
+                      wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], 
+                      wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], 
+                      wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], 
+                      wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], 
+                      wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], 
+                      wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], 
+                      wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
+}
+
+/**
+ * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
+ *
+ * wdrtas_timer_keepalive restarts the watchdog timer by calling the
+ * RTAS function event-scan and repeats these calls as long as there are
+ * events available. All events will be dumped.
+ */
+static void
+wdrtas_timer_keepalive(void)
+{
+       long result;
+
+       do {
+               result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
+                                  RTAS_EVENT_SCAN_ALL_EVENTS, 0,
+                                  (void *)__pa(wdrtas_logbuffer),
+                                  WDRTAS_LOGBUFFER_LEN);
+               if (result < 0)
+                       printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
+                              result);
+               if (result == 0)
+                       wdrtas_log_scanned_event();
+       } while (result == 0);
+}
+
+/**
+ * wdrtas_get_temperature - returns current temperature
+ *
+ * returns temperature or <0 on failures
+ *
+ * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
+ * uses the RTAS call get-sensor-state, token 3 to do so
+ */
+static int
+wdrtas_get_temperature(void)
+{
+       long result;
+       int temperature = 0;
+
+       result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
+                          (void *)__pa(&temperature),
+                          WDRTAS_THERMAL_SENSOR, 0);
+
+       if (result < 0)
+               printk(KERN_WARNING "wdrtas: reading the thermal sensor "
+                      "faild: %li\n", result);
+       else
+               temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
+
+       return temperature;
+}
+
+/**
+ * wdrtas_get_status - returns the status of the watchdog
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h
+ */
+static int
+wdrtas_get_status(void)
+{
+       return 0; /* TODO */
+}
+
+/**
+ * wdrtas_get_boot_status - returns the reason for the last boot
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h, indicating why the watchdog rebooted the system
+ */
+static int
+wdrtas_get_boot_status(void)
+{
+       return 0; /* TODO */
+}
+
+/*** watchdog API and operations stuff */
+
+/* wdrtas_write - called when watchdog device is written to
+ * @file: file structure
+ * @buf: user buffer with data
+ * @len: amount to data written
+ * @ppos: position in file
+ *
+ * returns the number of successfully processed characters, which is always
+ * the number of bytes passed to this function
+ *
+ * wdrtas_write processes all the data given to it and looks for the magic
+ * character 'V'. This character allows the watchdog device to be closed
+ * properly.
+ */
+static ssize_t
+wdrtas_write(struct file *file, const char __user *buf,
+            size_t len, loff_t *ppos)
+{
+       int i;
+       char c;
+
+       if (!len)
+               goto out;
+
+       if (!wdrtas_nowayout) {
+               wdrtas_expect_close = 0;
+               /* look for 'V' */
+               for (i = 0; i < len; i++) {
+                       if (get_user(c, buf + i))
+                               return -EFAULT;
+                       /* allow to close device */
+                       if (c == 'V')
+                               wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
+               }
+       }
+
+       wdrtas_timer_keepalive();
+
+out:
+       return len;
+}
+
+/**
+ * wdrtas_ioctl - ioctl function for the watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ * @cmd: command for ioctl
+ * @arg: argument pointer
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * wdrtas_ioctl implements the watchdog API ioctls
+ */
+static int
+wdrtas_ioctl(struct inode *inode, struct file *file,
+            unsigned int cmd, unsigned long arg)
+{
+       int __user *argp = (void __user *)arg;
+       int i;
+       static struct watchdog_info wdinfo = {
+               .options = WDRTAS_SUPPORTED_MASK,
+               .firmware_version = 0,
+               .identity = "wdrtas"
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
+                       return -EFAULT;
+               return 0;
+
+       case WDIOC_GETSTATUS:
+               i = wdrtas_get_status();
+               return put_user(i, argp);
+
+       case WDIOC_GETBOOTSTATUS:
+               i = wdrtas_get_boot_status();
+               return put_user(i, argp);
+
+       case WDIOC_GETTEMP:
+               if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
+                       return -EOPNOTSUPP;
+
+               i = wdrtas_get_temperature();
+               return put_user(i, argp);
+
+       case WDIOC_SETOPTIONS:
+               if (get_user(i, argp))
+                       return -EFAULT;
+               if (i & WDIOS_DISABLECARD)
+                       wdrtas_timer_stop();
+               if (i & WDIOS_ENABLECARD) {
+                       wdrtas_timer_keepalive();
+                       wdrtas_timer_start();
+               }
+               if (i & WDIOS_TEMPPANIC) {
+                       /* not implemented. Done by H8 */
+               }
+               return 0;
+
+       case WDIOC_KEEPALIVE:
+               wdrtas_timer_keepalive();
+               return 0;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(i, argp))
+                       return -EFAULT;
+
+               if (wdrtas_set_interval(i))
+                       return -EINVAL;
+
+               wdrtas_timer_keepalive();
+
+               if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+                       wdrtas_interval = i;
+               else
+                       wdrtas_interval = wdrtas_get_interval(i);
+               /* fallthrough */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(wdrtas_interval, argp);
+
+       default:
+               return -ENOTTY;
+       }
+}
+
+/**
+ * wdrtas_open - open function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, -EBUSY if the file has been opened already, <0 on
+ * other failures
+ *
+ * function called when watchdog device is opened
+ */
+static int
+wdrtas_open(struct inode *inode, struct file *file)
+{
+       /* only open once */
+       if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
+               atomic_dec(&wdrtas_miscdev_open);
+               return -EBUSY;
+       }
+
+       wdrtas_timer_start();
+       wdrtas_timer_keepalive();
+
+       return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_close - close function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_close(struct inode *inode, struct file *file)
+{
+       /* only stop watchdog, if this was announced using 'V' before */
+       if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
+               wdrtas_timer_stop();
+       else {
+               printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
+                      "not stopped.\n");
+               wdrtas_timer_keepalive();
+       }
+
+       wdrtas_expect_close = 0;
+       atomic_dec(&wdrtas_miscdev_open);
+       return 0;
+}
+
+/**
+ * wdrtas_temp_read - gives back the temperature in fahrenheit
+ * @file: file structure
+ * @buf: user buffer
+ * @count: number of bytes to be read
+ * @ppos: position in file
+ *
+ * returns always 1 or -EFAULT in case of user space copy failures, <0 on
+ * other failures
+ *
+ * wdrtas_temp_read gives the temperature to the users by copying this
+ * value as one byte into the user space buffer. The unit is Fahrenheit...
+ */
+static ssize_t
+wdrtas_temp_read(struct file *file, char __user *buf,
+                size_t count, loff_t *ppos)
+{
+       int temperature = 0;
+
+       temperature = wdrtas_get_temperature();
+       if (temperature < 0)
+               return temperature;
+
+       if (copy_to_user(buf, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+/**
+ * wdrtas_temp_open - open function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * function called when temperature device is opened
+ */
+static int
+wdrtas_temp_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_temp_close - close function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_temp_close(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+/**
+ * wdrtas_reboot - reboot notifier function
+ * @nb: notifier block structure
+ * @code: reboot code
+ * @ptr: unused
+ *
+ * returns NOTIFY_DONE
+ *
+ * wdrtas_reboot stops the watchdog in case of a reboot
+ */
+static int
+wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
+{
+       if ( (code==SYS_DOWN) || (code==SYS_HALT) )
+               wdrtas_timer_stop();
+
+       return NOTIFY_DONE;
+}
+
+/*** initialization stuff */
+
+static const struct file_operations wdrtas_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdrtas_write,
+       .ioctl          = wdrtas_ioctl,
+       .open           = wdrtas_open,
+       .release        = wdrtas_close,
+};
+
+static struct miscdevice wdrtas_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &wdrtas_fops,
+};
+
+static const struct file_operations wdrtas_temp_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = wdrtas_temp_read,
+       .open           = wdrtas_temp_open,
+       .release        = wdrtas_temp_close,
+};
+
+static struct miscdevice wdrtas_tempdev = {
+       .minor =        TEMP_MINOR,
+       .name =         "temperature",
+       .fops =         &wdrtas_temp_fops,
+};
+
+static struct notifier_block wdrtas_notifier = {
+       .notifier_call =        wdrtas_reboot,
+};
+
+/**
+ * wdrtas_get_tokens - reads in RTAS tokens
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
+ * this watchdog driver. It tolerates, if "get-sensor-state" and
+ * "ibm,get-system-parameter" are not available.
+ */
+static int
+wdrtas_get_tokens(void)
+{
+       wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
+       if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_WARNING "wdrtas: couldn't get token for "
+                      "get-sensor-state. Trying to continue without "
+                      "temperature support.\n");
+       }
+
+       wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
+       if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_WARNING "wdrtas: couldn't get token for "
+                      "ibm,get-system-parameter. Trying to continue with "
+                      "a default timeout value of %i seconds.\n",
+                      WDRTAS_DEFAULT_INTERVAL);
+       }
+
+       wdrtas_token_set_indicator = rtas_token("set-indicator");
+       if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_ERR "wdrtas: couldn't get token for "
+                      "set-indicator. Terminating watchdog code.\n");
+               return -EIO;
+       }
+
+       wdrtas_token_event_scan = rtas_token("event-scan");
+       if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
+                      "Terminating watchdog code.\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/**
+ * wdrtas_unregister_devs - unregisters the misc dev handlers
+ *
+ * wdrtas_register_devs unregisters the watchdog and temperature watchdog
+ * misc devs
+ */
+static void
+wdrtas_unregister_devs(void)
+{
+       misc_deregister(&wdrtas_miscdev);
+       if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
+               misc_deregister(&wdrtas_tempdev);
+}
+
+/**
+ * wdrtas_register_devs - registers the misc dev handlers
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_register_devs registers the watchdog and temperature watchdog
+ * misc devs
+ */
+static int
+wdrtas_register_devs(void)
+{
+       int result;
+
+       result = misc_register(&wdrtas_miscdev);
+       if (result) {
+               printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
+                      "device. Terminating watchdog code.\n");
+               return result;
+       }
+
+       if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
+               result = misc_register(&wdrtas_tempdev);
+               if (result) {
+                       printk(KERN_WARNING "wdrtas: couldn't register "
+                              "watchdog temperature misc device. Continuing "
+                              "without temperature support.\n");
+                       wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * wdrtas_init - init function of the watchdog driver
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * registers the file handlers and the reboot notifier
+ */
+static int __init
+wdrtas_init(void)
+{
+       if (wdrtas_get_tokens())
+               return -ENODEV;
+
+       if (wdrtas_register_devs())
+               return -ENODEV;
+
+       if (register_reboot_notifier(&wdrtas_notifier)) {
+               printk(KERN_ERR "wdrtas: could not register reboot notifier. "
+                      "Terminating watchdog code.\n");
+               wdrtas_unregister_devs();
+               return -ENODEV;
+       }
+
+       if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+               wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
+       else
+               wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
+
+       return 0;
+}
+
+/**
+ * wdrtas_exit - exit function of the watchdog driver
+ *
+ * unregisters the file handlers and the reboot notifier
+ */
+static void __exit
+wdrtas_exit(void)
+{
+       if (!wdrtas_nowayout)
+               wdrtas_timer_stop();
+
+       wdrtas_unregister_devs();
+
+       unregister_reboot_notifier(&wdrtas_notifier);
+}
+
+module_init(wdrtas_init);
+module_exit(wdrtas_exit);
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
new file mode 100644 (file)
index 0000000..0a3de6a
--- /dev/null
@@ -0,0 +1,640 @@
+/*
+ *     Industrial Computer Source WDT500/501 driver
+ *
+ *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Release 0.10.
+ *
+ *     Fixes
+ *             Dave Gregorich  :       Modularisation and minor bugs
+ *             Alan Cox        :       Added the watchdog ioctl() stuff
+ *             Alan Cox        :       Fixed the reboot problem (as noted by
+ *                                     Matt Crocker).
+ *             Alan Cox        :       Added wdt= boot option
+ *             Alan Cox        :       Cleaned up copy/user stuff
+ *             Tim Hockin      :       Added insmod parameters, comment cleanup
+ *                                     Parameterized timeout
+ *             Tigran Aivazian :       Restructured wdt_init() to handle failures
+ *             Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
+ *             Matt Domsch     :       Added nowayout module option
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include "wd501p.h"
+
+static unsigned long wdt_is_open;
+static char expect_close;
+
+/*
+ *     Module parameters
+ */
+
+#define WD_TIMO 60                     /* Default heartbeat = 60 seconds */
+
+static int heartbeat = WD_TIMO;
+static int wd_heartbeat;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
+
+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) ")");
+
+/* You must set these - there is no sane way to probe for this board. */
+static int io=0x240;
+static int irq=11;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "WDT irq (default=11)");
+
+#ifdef CONFIG_WDT_501
+/* Support for the Fan Tachometer on the WDT501-P */
+static int tachometer;
+
+module_param(tachometer, int, 0);
+MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)");
+#endif /* CONFIG_WDT_501 */
+
+/*
+ *     Programming support
+ */
+
+static void wdt_ctr_mode(int ctr, int mode)
+{
+       ctr<<=6;
+       ctr|=0x30;
+       ctr|=(mode<<1);
+       outb_p(ctr, WDT_CR);
+}
+
+static void wdt_ctr_load(int ctr, int val)
+{
+       outb_p(val&0xFF, WDT_COUNT0+ctr);
+       outb_p(val>>8, WDT_COUNT0+ctr);
+}
+
+/**
+ *     wdt_start:
+ *
+ *     Start the watchdog driver.
+ */
+
+static int wdt_start(void)
+{
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdt_ctr_mode(0,3);              /* Program CTR0 for Mode 3: Square Wave Generator */
+       wdt_ctr_mode(1,2);              /* Program CTR1 for Mode 2: Rate Generator */
+       wdt_ctr_mode(2,0);              /* Program CTR2 for Mode 0: Pulse on Terminal Count */
+       wdt_ctr_load(0, 8948);          /* Count at 100Hz */
+       wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
+       wdt_ctr_load(2,65535);          /* Length of reset pulse */
+       outb_p(0, WDT_DC);              /* Enable watchdog */
+       return 0;
+}
+
+/**
+ *     wdt_stop:
+ *
+ *     Stop the watchdog driver.
+ */
+
+static int wdt_stop (void)
+{
+       /* Turn the card off */
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdt_ctr_load(2,0);              /* 0 length reset pulses now */
+       return 0;
+}
+
+/**
+ *     wdt_ping:
+ *
+ *     Reload counter one with the watchdog heartbeat. We don't bother reloading
+ *     the cascade counter.
+ */
+
+static int wdt_ping(void)
+{
+       /* Write a watchdog value */
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdt_ctr_mode(1,2);              /* Re-Program CTR1 for Mode 2: Rate Generator */
+       wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
+       outb_p(0, WDT_DC);              /* Enable watchdog */
+       return 0;
+}
+
+/**
+ *     wdt_set_heartbeat:
+ *     @t:             the new heartbeat value that needs to be set.
+ *
+ *     Set a new heartbeat value for the watchdog device. If the heartbeat value is
+ *     incorrect we keep the old value and return -EINVAL. If successfull we
+ *     return 0.
+ */
+static int wdt_set_heartbeat(int t)
+{
+       if ((t < 1) || (t > 65535))
+               return -EINVAL;
+
+       heartbeat = t;
+       wd_heartbeat = t * 100;
+       return 0;
+}
+
+/**
+ *     wdt_get_status:
+ *     @status:                the new status.
+ *
+ *     Extract the status information from a WDT watchdog device. There are
+ *     several board variants so we have to know which bits are valid. Some
+ *     bits default to one and some to zero in order to be maximally painful.
+ *
+ *     we then map the bits onto the status ioctl flags.
+ */
+
+static int wdt_get_status(int *status)
+{
+       unsigned char new_status=inb_p(WDT_SR);
+
+       *status=0;
+       if (new_status & WDC_SR_ISOI0)
+               *status |= WDIOF_EXTERN1;
+       if (new_status & WDC_SR_ISII1)
+               *status |= WDIOF_EXTERN2;
+#ifdef CONFIG_WDT_501
+       if (!(new_status & WDC_SR_TGOOD))
+               *status |= WDIOF_OVERHEAT;
+       if (!(new_status & WDC_SR_PSUOVER))
+               *status |= WDIOF_POWEROVER;
+       if (!(new_status & WDC_SR_PSUUNDR))
+               *status |= WDIOF_POWERUNDER;
+       if (tachometer) {
+               if (!(new_status & WDC_SR_FANGOOD))
+                       *status |= WDIOF_FANFAULT;
+       }
+#endif /* CONFIG_WDT_501 */
+       return 0;
+}
+
+#ifdef CONFIG_WDT_501
+/**
+ *     wdt_get_temperature:
+ *
+ *     Reports the temperature in degrees Fahrenheit. The API is in
+ *     farenheit. It was designed by an imperial measurement luddite.
+ */
+
+static int wdt_get_temperature(int *temperature)
+{
+       unsigned short c=inb_p(WDT_RT);
+
+       *temperature = (c * 11 / 15) + 7;
+       return 0;
+}
+#endif /* CONFIG_WDT_501 */
+
+/**
+ *     wdt_interrupt:
+ *     @irq:           Interrupt number
+ *     @dev_id:        Unused as we don't allow multiple devices.
+ *
+ *     Handle an interrupt from the board. These are raised when the status
+ *     map changes in what the board considers an interesting way. That means
+ *     a failure condition occurring.
+ */
+
+static irqreturn_t wdt_interrupt(int irq, void *dev_id)
+{
+       /*
+        *      Read the status register see what is up and
+        *      then printk it.
+        */
+       unsigned char status=inb_p(WDT_SR);
+
+       printk(KERN_CRIT "WDT status %d\n", status);
+
+#ifdef CONFIG_WDT_501
+       if (!(status & WDC_SR_TGOOD))
+               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
+       if (!(status & WDC_SR_PSUOVER))
+               printk(KERN_CRIT "PSU over voltage.\n");
+       if (!(status & WDC_SR_PSUUNDR))
+               printk(KERN_CRIT "PSU under voltage.\n");
+       if (tachometer) {
+               if (!(status & WDC_SR_FANGOOD))
+                       printk(KERN_CRIT "Possible fan fault.\n");
+       }
+#endif /* CONFIG_WDT_501 */
+       if (!(status & WDC_SR_WCCR))
+#ifdef SOFTWARE_REBOOT
+#ifdef ONLY_TESTING
+               printk(KERN_CRIT "Would Reboot.\n");
+#else
+               printk(KERN_CRIT "Initiating system reboot.\n");
+               emergency_restart();
+#endif
+#else
+               printk(KERN_CRIT "Reset in 5ms.\n");
+#endif
+       return IRQ_HANDLED;
+}
+
+
+/**
+ *     wdt_write:
+ *     @file: file handle to the watchdog
+ *     @buf: buffer to write (unused as data does not matter here
+ *     @count: count of bytes
+ *     @ppos: pointer to the position to write. No seeks allowed
+ *
+ *     A write to a watchdog device is defined as a keepalive signal. Any
+ *     write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if(count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               wdt_ping();
+       }
+       return count;
+}
+
+/**
+ *     wdt_ioctl:
+ *     @inode: inode of the device
+ *     @file: file handle to the device
+ *     @cmd: watchdog command
+ *     @arg: argument pointer
+ *
+ *     The watchdog API defines a common set of functions for all watchdogs
+ *     according to their available features. We only actually usefully support
+ *     querying capabilities and current status.
+ */
+
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int new_heartbeat;
+       int status;
+
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT|
+                                       WDIOF_MAGICCLOSE|
+                                       WDIOF_KEEPALIVEPING,
+               .firmware_version =     1,
+               .identity =             "WDT500/501",
+       };
+
+       /* Add options according to the card we have */
+       ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
+#ifdef CONFIG_WDT_501
+       ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER);
+       if (tachometer)
+               ident.options |= WDIOF_FANFAULT;
+#endif /* CONFIG_WDT_501 */
+
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
+
+               case WDIOC_GETSTATUS:
+                       wdt_get_status(&status);
+                       return put_user(status, p);
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+               case WDIOC_KEEPALIVE:
+                       wdt_ping();
+                       return 0;
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_heartbeat, p))
+                               return -EFAULT;
+
+                       if (wdt_set_heartbeat(new_heartbeat))
+                               return -EINVAL;
+
+                       wdt_ping();
+                       /* Fall */
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, p);
+       }
+}
+
+/**
+ *     wdt_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     The watchdog device has been opened. The watchdog device is single
+ *     open and on opening we load the counters. Counter zero is a 100Hz
+ *     cascade, into counter 1 which downcounts to reboot. When the counter
+ *     triggers counter 2 downcounts the length of the reset pulse which
+ *     set set to be as long as possible.
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+       if(test_and_set_bit(0, &wdt_is_open))
+               return -EBUSY;
+       /*
+        *      Activate
+        */
+       wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     wdt_release:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The watchdog has a configurable API. There is a religious dispute
+ *     between people who want their watchdog to be able to shut down and
+ *     those who want to be sure if the watchdog manager dies the machine
+ *     reboots. In the former case we disable the counters, in the latter
+ *     case you have to open it again very soon.
+ */
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               wdt_stop();
+               clear_bit(0, &wdt_is_open);
+       } else {
+               printk(KERN_CRIT "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
+               wdt_ping();
+       }
+       expect_close = 0;
+       return 0;
+}
+
+#ifdef CONFIG_WDT_501
+/**
+ *     wdt_temp_read:
+ *     @file: file handle to the watchdog board
+ *     @buf: buffer to write 1 byte into
+ *     @count: length of buffer
+ *     @ptr: offset (no seek allowed)
+ *
+ *     Temp_read reports the temperature in degrees Fahrenheit. The API is in
+ *     farenheit. It was designed by an imperial measurement luddite.
+ */
+
+static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
+{
+       int temperature;
+
+       if (wdt_get_temperature(&temperature))
+               return -EFAULT;
+
+       if (copy_to_user (buf, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+/**
+ *     wdt_temp_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     The temperature device has been opened.
+ */
+
+static int wdt_temp_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     wdt_temp_release:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The temperature device has been closed.
+ */
+
+static int wdt_temp_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+#endif /* CONFIG_WDT_501 */
+
+/**
+ *     notify_sys:
+ *     @this: our notifier block
+ *     @code: the event being reported
+ *     @unused: unused
+ *
+ *     Our notifier is called on system shutdowns. We want to turn the card
+ *     off at reboot otherwise the machine will reboot again during memory
+ *     test or worse yet during the following fsck. This would suck, in fact
+ *     trust me - if it happens it does suck.
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the card off */
+               wdt_stop();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+
+static const struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdt_write,
+       .ioctl          = wdt_ioctl,
+       .open           = wdt_open,
+       .release        = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wdt_fops,
+};
+
+#ifdef CONFIG_WDT_501
+static const struct file_operations wdt_temp_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = wdt_temp_read,
+       .open           = wdt_temp_open,
+       .release        = wdt_temp_release,
+};
+
+static struct miscdevice temp_miscdev = {
+       .minor  = TEMP_MINOR,
+       .name   = "temperature",
+       .fops   = &wdt_temp_fops,
+};
+#endif /* CONFIG_WDT_501 */
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+       .notifier_call = wdt_notify_sys,
+};
+
+/**
+ *     cleanup_module:
+ *
+ *     Unload the watchdog. You cannot do this with any file handles open.
+ *     If your watchdog is set to continue ticking on close and you unload
+ *     it, well it keeps ticking. We won't get the interrupt but the board
+ *     will not touch PC memory so all is fine. You just have to load a new
+ *     module in 60 seconds or reboot.
+ */
+
+static void __exit wdt_exit(void)
+{
+       misc_deregister(&wdt_miscdev);
+#ifdef CONFIG_WDT_501
+       misc_deregister(&temp_miscdev);
+#endif /* CONFIG_WDT_501 */
+       unregister_reboot_notifier(&wdt_notifier);
+       free_irq(irq, NULL);
+       release_region(io,8);
+}
+
+/**
+ *     wdt_init:
+ *
+ *     Set up the WDT watchdog board. All we have to do is grab the
+ *     resources we require and bitch if anyone beat us to them.
+ *     The open() function will actually kick the board off.
+ */
+
+static int __init wdt_init(void)
+{
+       int ret;
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (wdt_set_heartbeat(heartbeat)) {
+               wdt_set_heartbeat(WD_TIMO);
+               printk(KERN_INFO "wdt: heartbeat value must be 0<heartbeat<65536, using %d\n",
+                       WD_TIMO);
+       }
+
+       if (!request_region(io, 8, "wdt501p")) {
+               printk(KERN_ERR "wdt: I/O address 0x%04x already in use\n", io);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL);
+       if(ret) {
+               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
+               goto outreg;
+       }
+
+       ret = register_reboot_notifier(&wdt_notifier);
+       if(ret) {
+               printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret);
+               goto outirq;
+       }
+
+#ifdef CONFIG_WDT_501
+       ret = misc_register(&temp_miscdev);
+       if (ret) {
+               printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
+                       TEMP_MINOR, ret);
+               goto outrbt;
+       }
+#endif /* CONFIG_WDT_501 */
+
+       ret = misc_register(&wdt_miscdev);
+       if (ret) {
+               printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto outmisc;
+       }
+
+       ret = 0;
+       printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
+               io, irq, heartbeat, nowayout);
+#ifdef CONFIG_WDT_501
+       printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled"));
+#endif /* CONFIG_WDT_501 */
+
+out:
+       return ret;
+
+outmisc:
+#ifdef CONFIG_WDT_501
+       misc_deregister(&temp_miscdev);
+outrbt:
+#endif /* CONFIG_WDT_501 */
+       unregister_reboot_notifier(&wdt_notifier);
+outirq:
+       free_irq(irq, NULL);
+outreg:
+       release_region(io,8);
+       goto out;
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c
new file mode 100644 (file)
index 0000000..e4cf661
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *     Intel 21285 watchdog driver
+ *     Copyright (c) Phil Blundell <pb@nexus.co.uk>, 1998
+ *
+ *     based on
+ *
+ *     SoftDog 0.05:   A Software Watchdog Device
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/dec21285.h>
+
+/*
+ * Define this to stop the watchdog actually rebooting the machine.
+ */
+#undef ONLY_TESTING
+
+static unsigned int soft_margin = 60;          /* in seconds */
+static unsigned int reload;
+static unsigned long timer_alive;
+
+#ifdef ONLY_TESTING
+/*
+ *     If the timer expires..
+ */
+static void watchdog_fire(int irq, void *dev_id)
+{
+       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
+       *CSR_TIMER4_CNTL = 0;
+       *CSR_TIMER4_CLR = 0;
+}
+#endif
+
+/*
+ *     Refresh the timer.
+ */
+static void watchdog_ping(void)
+{
+       *CSR_TIMER4_LOAD = reload;
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int watchdog_open(struct inode *inode, struct file *file)
+{
+       int ret;
+
+       if (*CSR_SA110_CNTL & (1 << 13))
+               return -EBUSY;
+
+       if (test_and_set_bit(1, &timer_alive))
+               return -EBUSY;
+
+       reload = soft_margin * (mem_fclk_21285 / 256);
+
+       *CSR_TIMER4_CLR = 0;
+       watchdog_ping();
+       *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD
+               | TIMER_CNTL_DIV256;
+
+#ifdef ONLY_TESTING
+       ret = request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
+       if (ret) {
+               *CSR_TIMER4_CNTL = 0;
+               clear_bit(1, &timer_alive);
+       }
+#else
+       /*
+        * Setting this bit is irreversible; once enabled, there is
+        * no way to disable the watchdog.
+        */
+       *CSR_SA110_CNTL |= 1 << 13;
+
+       ret = 0;
+#endif
+       nonseekable_open(inode, file);
+       return ret;
+}
+
+/*
+ *     Shut off the timer.
+ *     Note: if we really have enabled the watchdog, there
+ *     is no way to turn off.
+ */
+static int watchdog_release(struct inode *inode, struct file *file)
+{
+#ifdef ONLY_TESTING
+       free_irq(IRQ_TIMER4, NULL);
+       clear_bit(1, &timer_alive);
+#endif
+       return 0;
+}
+
+static ssize_t
+watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       /*
+        *      Refresh the timer.
+        */
+       if (len)
+               watchdog_ping();
+
+       return len;
+}
+
+static struct watchdog_info ident = {
+       .options        = WDIOF_SETTIMEOUT,
+       .identity       = "Footbridge Watchdog",
+};
+
+static int
+watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+              unsigned long arg)
+{
+       unsigned int new_margin;
+       int ret = -ENOTTY;
+
+       switch(cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = 0;
+               if (copy_to_user((void *)arg, &ident, sizeof(ident)))
+                       ret = -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(0,(int *)arg);
+               break;
+
+       case WDIOC_KEEPALIVE:
+               watchdog_ping();
+               ret = 0;
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(new_margin, (int *)arg);
+               if (ret)
+                       break;
+
+               /* Arbitrary, can't find the card's limits */
+               if (new_margin < 0 || new_margin > 60) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               soft_margin = new_margin;
+               reload = soft_margin * (mem_fclk_21285 / 256);
+               watchdog_ping();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               ret = put_user(soft_margin, (int *)arg);
+               break;
+       }
+       return ret;
+}
+
+static const struct file_operations watchdog_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = watchdog_write,
+       .ioctl          = watchdog_ioctl,
+       .open           = watchdog_open,
+       .release        = watchdog_release,
+};
+
+static struct miscdevice watchdog_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &watchdog_fops,
+};
+
+static int __init footbridge_watchdog_init(void)
+{
+       int retval;
+
+       if (machine_is_netwinder())
+               return -ENODEV;
+
+       retval = misc_register(&watchdog_miscdev);
+       if (retval < 0)
+               return retval;
+
+       printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
+              soft_margin);
+
+       if (machine_is_cats())
+               printk("Warning: Watchdog reset may not work on this machine.\n");
+       return 0;
+}
+
+static void __exit footbridge_watchdog_exit(void)
+{
+       misc_deregister(&watchdog_miscdev);
+}
+
+MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
+MODULE_DESCRIPTION("Footbridge watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+module_param(soft_margin, int, 0);
+MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
+
+module_init(footbridge_watchdog_init);
+module_exit(footbridge_watchdog_exit);
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
new file mode 100644 (file)
index 0000000..7d300ff
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *     Wdt977  0.04:   A Watchdog Device for Netwinder W83977AF chip
+ *
+ *     (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
+ *
+ *                     -----------------------
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *                     -----------------------
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *     19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
+ *     06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
+ *                                 from minutes to seconds.
+ *      07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
+ *                                    nwwatchdog_init.
+ *      25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
+ *                                 remove limitiation to be used on Netwinders only
+ */
+
+#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/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION  "0.04"
+#define WATCHDOG_NAME     "Wdt977"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT  0x370           /* on some systems it can be 0x3F0 */
+#define IO_DATA_PORT   (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA    0x87
+#define LOCK_DATA      0xAA
+#define DEVICE_REGISTER        0x07
+
+
+#define        DEFAULT_TIMEOUT 60                      /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutM;                           /* timeout in minutes */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+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) ")");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt977_start(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+
+       /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
+        * F2 has the timeout in minutes
+        * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
+        *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
+        * F4 is used to just clear the TIMEOUT'ed state (bit 0)
+        */
+       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+       outb_p(0x08, IO_DATA_PORT);
+       outb_p(0xF2, IO_INDEX_PORT);
+       outb_p(timeoutM, IO_DATA_PORT);
+       outb_p(0xF3, IO_INDEX_PORT);
+       outb_p(0x00, IO_DATA_PORT);     /* another setting is 0E for kbd/mouse/LED */
+       outb_p(0xF4, IO_INDEX_PORT);
+       outb_p(0x00, IO_DATA_PORT);
+
+       /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+       /* in test mode watch the bit 1 on F4 to indicate "triggered" */
+       if (!testmode)
+       {
+               outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+               outb_p(0x07, IO_DATA_PORT);
+               outb_p(0xE6, IO_INDEX_PORT);
+               outb_p(0x08, IO_DATA_PORT);
+       }
+
+       /* lock the SuperIO chip */
+       outb_p(LOCK_DATA, IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+       printk(KERN_INFO PFX "activated.\n");
+
+       return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt977_stop(void)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+
+       /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
+       * F3 is reset to its default state
+       * F4 can clear the TIMEOUT'ed state (bit 0) - back to default
+       * We can not use GP17 as a PowerLed, as we use its usage as a RedLed
+       */
+       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+       outb_p(0x08, IO_DATA_PORT);
+       outb_p(0xF2, IO_INDEX_PORT);
+       outb_p(0xFF, IO_DATA_PORT);
+       outb_p(0xF3, IO_INDEX_PORT);
+       outb_p(0x00, IO_DATA_PORT);
+       outb_p(0xF4, IO_INDEX_PORT);
+       outb_p(0x00, IO_DATA_PORT);
+       outb_p(0xF2, IO_INDEX_PORT);
+       outb_p(0x00, IO_DATA_PORT);
+
+       /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+       outb_p(0x07, IO_DATA_PORT);
+       outb_p(0xE6, IO_INDEX_PORT);
+       outb_p(0x08, IO_DATA_PORT);
+
+       /* lock the SuperIO chip */
+       outb_p(LOCK_DATA, IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+       printk(KERN_INFO PFX "shutdown.\n");
+
+       return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt977_keepalive(void)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+
+       /* select device Aux2 (device=8) and kicks watchdog reg F2 */
+       /* F2 has the timeout in minutes */
+       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+       outb_p(0x08, IO_DATA_PORT);
+       outb_p(0xF2, IO_INDEX_PORT);
+       outb_p(timeoutM, IO_DATA_PORT);
+
+       /* lock the SuperIO chip */
+       outb_p(LOCK_DATA, IO_INDEX_PORT);
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt977_set_timeout(int t)
+{
+       int tmrval;
+
+       /* convert seconds to minutes, rounding up */
+       tmrval = (t + 59) / 60;
+
+       if (machine_is_netwinder()) {
+               /* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+                *  this limits the max timeout to half of device max of 255 minutes...
+                */
+               tmrval += tmrval;
+       }
+
+       if ((tmrval < 1) || (tmrval > 255))
+               return -EINVAL;
+
+       /* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */
+       timeout = t;
+       timeoutM = tmrval;
+       return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt977_get_status(int *status)
+{
+       int new_status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&spinlock, flags);
+
+       /* unlock the SuperIO chip */
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+       outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+
+       /* select device Aux2 (device=8) and read watchdog reg F4 */
+       outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+       outb_p(0x08, IO_DATA_PORT);
+       outb_p(0xF4, IO_INDEX_PORT);
+       new_status = inb_p(IO_DATA_PORT);
+
+       /* lock the SuperIO chip */
+       outb_p(LOCK_DATA, IO_INDEX_PORT);
+
+       spin_unlock_irqrestore(&spinlock, flags);
+
+       *status=0;
+       if (new_status & 1)
+               *status |= WDIOF_CARDRESET;
+
+       return 0;
+}
+
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static int wdt977_open(struct inode *inode, struct file *file)
+{
+       /* If the watchdog is alive we don't need to start it again */
+       if( test_and_set_bit(0,&timer_alive) )
+               return -EBUSY;
+
+       if (nowayout)
+               __module_get(THIS_MODULE);
+
+       wdt977_start();
+       return nonseekable_open(inode, file);
+}
+
+static int wdt977_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if (expect_close == 42)
+       {
+               wdt977_stop();
+               clear_bit(0,&timer_alive);
+       } else {
+               wdt977_keepalive();
+               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+       }
+       expect_close = 0;
+       return 0;
+}
+
+
+/*
+ *      wdt977_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt977_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
+{
+       if (count)
+       {
+               if (!nowayout)
+               {
+                       size_t i;
+
+                       /* In case it was set long ago */
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++)
+                       {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+
+               /* someone wrote to us, we should restart timer */
+               wdt977_keepalive();
+       }
+       return count;
+}
+
+/*
+ *      wdt977_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static struct watchdog_info ident = {
+       .options =              WDIOF_SETTIMEOUT |
+                               WDIOF_MAGICCLOSE |
+                               WDIOF_KEEPALIVEPING,
+       .firmware_version =     1,
+       .identity =             WATCHDOG_NAME,
+};
+
+static int wdt977_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int status;
+       int new_options, retval = -EINVAL;
+       int new_timeout;
+       union {
+               struct watchdog_info __user *ident;
+               int __user *i;
+       } uarg;
+
+       uarg.i = (int __user *)arg;
+
+       switch(cmd)
+       {
+       default:
+               return -ENOTTY;
+
+       case WDIOC_GETSUPPORT:
+               return copy_to_user(uarg.ident, &ident,
+                       sizeof(ident)) ? -EFAULT : 0;
+
+       case WDIOC_GETSTATUS:
+               wdt977_get_status(&status);
+               return put_user(status, uarg.i);
+
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(0, uarg.i);
+
+       case WDIOC_KEEPALIVE:
+               wdt977_keepalive();
+               return 0;
+
+       case WDIOC_SETOPTIONS:
+               if (get_user (new_options, uarg.i))
+                       return -EFAULT;
+
+               if (new_options & WDIOS_DISABLECARD) {
+                       wdt977_stop();
+                       retval = 0;
+               }
+
+               if (new_options & WDIOS_ENABLECARD) {
+                       wdt977_start();
+                       retval = 0;
+               }
+
+               return retval;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_timeout, uarg.i))
+                       return -EFAULT;
+
+               if (wdt977_set_timeout(new_timeout))
+                   return -EINVAL;
+
+               wdt977_keepalive();
+               /* Fall */
+
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout, uarg.i);
+
+       }
+}
+
+static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+               wdt977_stop();
+       return NOTIFY_DONE;
+}
+
+static const struct file_operations wdt977_fops=
+{
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdt977_write,
+       .ioctl          = wdt977_ioctl,
+       .open           = wdt977_open,
+       .release        = wdt977_release,
+};
+
+static struct miscdevice wdt977_miscdev=
+{
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &wdt977_fops,
+};
+
+static struct notifier_block wdt977_notifier = {
+       .notifier_call = wdt977_notify_sys,
+};
+
+static int __init wd977_init(void)
+{
+       int rc;
+
+       //if (!machine_is_netwinder())
+       //      return -ENODEV;
+
+       printk(KERN_INFO PFX DRIVER_VERSION);
+
+       spin_lock_init(&spinlock);
+
+       /* Check that the timeout value is within it's range ; if not reset to the default */
+       if (wdt977_set_timeout(timeout))
+       {
+               wdt977_set_timeout(DEFAULT_TIMEOUT);
+               printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n",
+                       DEFAULT_TIMEOUT);
+       }
+
+       /* on Netwinder the IOports are already reserved by
+        * arch/arm/mach-footbridge/netwinder-hw.c
+        */
+       if (!machine_is_netwinder())
+       {
+               if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+               {
+                       printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+                               IO_INDEX_PORT);
+                       rc = -EIO;
+                       goto err_out;
+               }
+       }
+
+       rc = misc_register(&wdt977_miscdev);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       wdt977_miscdev.minor, rc);
+               goto err_out_region;
+       }
+
+       rc = register_reboot_notifier(&wdt977_notifier);
+       if (rc)
+       {
+               printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                       rc);
+               goto err_out_miscdev;
+       }
+
+       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
+               timeout, nowayout, testmode);
+
+       return 0;
+
+err_out_miscdev:
+        misc_deregister(&wdt977_miscdev);
+err_out_region:
+       if (!machine_is_netwinder())
+               release_region(IO_INDEX_PORT,2);
+err_out:
+       return rc;
+}
+
+static void __exit wd977_exit(void)
+{
+       wdt977_stop();
+       misc_deregister(&wdt977_miscdev);
+       unregister_reboot_notifier(&wdt977_notifier);
+       release_region(IO_INDEX_PORT,2);
+}
+
+module_init(wd977_init);
+module_exit(wd977_exit);
+
+MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>");
+MODULE_DESCRIPTION("W83977AF Watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
new file mode 100644 (file)
index 0000000..6baf4ae
--- /dev/null
@@ -0,0 +1,756 @@
+/*
+ *     Industrial Computer Source PCI-WDT500/501 driver
+ *
+ *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Release 0.10.
+ *
+ *     Fixes
+ *             Dave Gregorich  :       Modularisation and minor bugs
+ *             Alan Cox        :       Added the watchdog ioctl() stuff
+ *             Alan Cox        :       Fixed the reboot problem (as noted by
+ *                                     Matt Crocker).
+ *             Alan Cox        :       Added wdt= boot option
+ *             Alan Cox        :       Cleaned up copy/user stuff
+ *             Tim Hockin      :       Added insmod parameters, comment cleanup
+ *                                     Parameterized timeout
+ *             JP Nollmann     :       Added support for PCI wdt501p
+ *             Alan Cox        :       Split ISA and PCI cards into two drivers
+ *             Jeff Garzik     :       PCI cleanups
+ *             Tigran Aivazian :       Restructured wdtpci_init_one() to handle failures
+ *             Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
+ *             Zwane Mwaikambo :       Magic char closing, locking changes, cleanups
+ *             Matt Domsch     :       nowayout module option
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define WDT_IS_PCI
+#include "wd501p.h"
+
+#define PFX "wdt_pci: "
+
+/*
+ * Until Access I/O gets their application for a PCI vendor ID approved,
+ * I don't think that it's appropriate to move these constants into the
+ * regular pci_ids.h file. -- JPN 2000/01/18
+ */
+
+#ifndef PCI_VENDOR_ID_ACCESSIO
+#define PCI_VENDOR_ID_ACCESSIO 0x494f
+#endif
+#ifndef PCI_DEVICE_ID_WDG_CSM
+#define PCI_DEVICE_ID_WDG_CSM 0x22c0
+#endif
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int dev_count;
+
+static struct semaphore open_sem;
+static spinlock_t wdtpci_lock;
+static char expect_close;
+
+static int io;
+static int irq;
+
+/* Default timeout */
+#define WD_TIMO 60                     /* Default heartbeat = 60 seconds */
+
+static int heartbeat = WD_TIMO;
+static int wd_heartbeat;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
+
+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) ")");
+
+#ifdef CONFIG_WDT_501_PCI
+/* Support for the Fan Tachometer on the PCI-WDT501 */
+static int tachometer;
+
+module_param(tachometer, int, 0);
+MODULE_PARM_DESC(tachometer, "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
+#endif /* CONFIG_WDT_501_PCI */
+
+/*
+ *     Programming support
+ */
+
+static void wdtpci_ctr_mode(int ctr, int mode)
+{
+       ctr<<=6;
+       ctr|=0x30;
+       ctr|=(mode<<1);
+       outb_p(ctr, WDT_CR);
+}
+
+static void wdtpci_ctr_load(int ctr, int val)
+{
+       outb_p(val&0xFF, WDT_COUNT0+ctr);
+       outb_p(val>>8, WDT_COUNT0+ctr);
+}
+
+/**
+ *     wdtpci_start:
+ *
+ *     Start the watchdog driver.
+ */
+
+static int wdtpci_start(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdtpci_lock, flags);
+
+       /*
+        * "pet" the watchdog, as Access says.
+        * This resets the clock outputs.
+        */
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdtpci_ctr_mode(2,0);           /* Program CTR2 for Mode 0: Pulse on Terminal Count */
+       outb_p(0, WDT_DC);              /* Enable watchdog */
+
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       outb_p(0, WDT_CLOCK);           /* 2.0833MHz clock */
+       inb_p(WDT_BUZZER);              /* disable */
+       inb_p(WDT_OPTONOTRST);          /* disable */
+       inb_p(WDT_OPTORST);             /* disable */
+       inb_p(WDT_PROGOUT);             /* disable */
+       wdtpci_ctr_mode(0,3);           /* Program CTR0 for Mode 3: Square Wave Generator */
+       wdtpci_ctr_mode(1,2);           /* Program CTR1 for Mode 2: Rate Generator */
+       wdtpci_ctr_mode(2,1);           /* Program CTR2 for Mode 1: Retriggerable One-Shot */
+       wdtpci_ctr_load(0,20833);       /* count at 100Hz */
+       wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */
+       /* DO NOT LOAD CTR2 on PCI card! -- JPN */
+       outb_p(0, WDT_DC);              /* Enable watchdog */
+
+       spin_unlock_irqrestore(&wdtpci_lock, flags);
+       return 0;
+}
+
+/**
+ *     wdtpci_stop:
+ *
+ *     Stop the watchdog driver.
+ */
+
+static int wdtpci_stop (void)
+{
+       unsigned long flags;
+
+       /* Turn the card off */
+       spin_lock_irqsave(&wdtpci_lock, flags);
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdtpci_ctr_load(2,0);           /* 0 length reset pulses now */
+       spin_unlock_irqrestore(&wdtpci_lock, flags);
+       return 0;
+}
+
+/**
+ *     wdtpci_ping:
+ *
+ *     Reload counter one with the watchdog heartbeat. We don't bother reloading
+ *     the cascade counter.
+ */
+
+static int wdtpci_ping(void)
+{
+       unsigned long flags;
+
+       /* Write a watchdog value */
+       spin_lock_irqsave(&wdtpci_lock, flags);
+       inb_p(WDT_DC);                  /* Disable watchdog */
+       wdtpci_ctr_mode(1,2);           /* Re-Program CTR1 for Mode 2: Rate Generator */
+       wdtpci_ctr_load(1,wd_heartbeat);/* Heartbeat */
+       outb_p(0, WDT_DC);              /* Enable watchdog */
+       spin_unlock_irqrestore(&wdtpci_lock, flags);
+       return 0;
+}
+
+/**
+ *     wdtpci_set_heartbeat:
+ *     @t:             the new heartbeat value that needs to be set.
+ *
+ *     Set a new heartbeat value for the watchdog device. If the heartbeat value is
+ *     incorrect we keep the old value and return -EINVAL. If successfull we
+ *     return 0.
+ */
+static int wdtpci_set_heartbeat(int t)
+{
+       /* Arbitrary, can't find the card's limits */
+       if ((t < 1) || (t > 65535))
+               return -EINVAL;
+
+       heartbeat = t;
+       wd_heartbeat = t * 100;
+       return 0;
+}
+
+/**
+ *     wdtpci_get_status:
+ *     @status:                the new status.
+ *
+ *     Extract the status information from a WDT watchdog device. There are
+ *     several board variants so we have to know which bits are valid. Some
+ *     bits default to one and some to zero in order to be maximally painful.
+ *
+ *     we then map the bits onto the status ioctl flags.
+ */
+
+static int wdtpci_get_status(int *status)
+{
+       unsigned char new_status=inb_p(WDT_SR);
+
+       *status=0;
+       if (new_status & WDC_SR_ISOI0)
+               *status |= WDIOF_EXTERN1;
+       if (new_status & WDC_SR_ISII1)
+               *status |= WDIOF_EXTERN2;
+#ifdef CONFIG_WDT_501_PCI
+       if (!(new_status & WDC_SR_TGOOD))
+               *status |= WDIOF_OVERHEAT;
+       if (!(new_status & WDC_SR_PSUOVER))
+               *status |= WDIOF_POWEROVER;
+       if (!(new_status & WDC_SR_PSUUNDR))
+               *status |= WDIOF_POWERUNDER;
+       if (tachometer) {
+               if (!(new_status & WDC_SR_FANGOOD))
+                       *status |= WDIOF_FANFAULT;
+       }
+#endif /* CONFIG_WDT_501_PCI */
+       return 0;
+}
+
+#ifdef CONFIG_WDT_501_PCI
+/**
+ *     wdtpci_get_temperature:
+ *
+ *     Reports the temperature in degrees Fahrenheit. The API is in
+ *     farenheit. It was designed by an imperial measurement luddite.
+ */
+
+static int wdtpci_get_temperature(int *temperature)
+{
+       unsigned short c=inb_p(WDT_RT);
+
+       *temperature = (c * 11 / 15) + 7;
+       return 0;
+}
+#endif /* CONFIG_WDT_501_PCI */
+
+/**
+ *     wdtpci_interrupt:
+ *     @irq:           Interrupt number
+ *     @dev_id:        Unused as we don't allow multiple devices.
+ *
+ *     Handle an interrupt from the board. These are raised when the status
+ *     map changes in what the board considers an interesting way. That means
+ *     a failure condition occurring.
+ */
+
+static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
+{
+       /*
+        *      Read the status register see what is up and
+        *      then printk it.
+        */
+       unsigned char status=inb_p(WDT_SR);
+
+       printk(KERN_CRIT PFX "status %d\n", status);
+
+#ifdef CONFIG_WDT_501_PCI
+       if (!(status & WDC_SR_TGOOD))
+               printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",inb_p(WDT_RT));
+       if (!(status & WDC_SR_PSUOVER))
+               printk(KERN_CRIT PFX "PSU over voltage.\n");
+       if (!(status & WDC_SR_PSUUNDR))
+               printk(KERN_CRIT PFX "PSU under voltage.\n");
+       if (tachometer) {
+               if (!(status & WDC_SR_FANGOOD))
+                       printk(KERN_CRIT PFX "Possible fan fault.\n");
+       }
+#endif /* CONFIG_WDT_501_PCI */
+       if (!(status&WDC_SR_WCCR))
+#ifdef SOFTWARE_REBOOT
+#ifdef ONLY_TESTING
+               printk(KERN_CRIT PFX "Would Reboot.\n");
+#else
+               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               emergency_restart(NULL);
+#endif
+#else
+               printk(KERN_CRIT PFX "Reset in 5ms.\n");
+#endif
+       return IRQ_HANDLED;
+}
+
+
+/**
+ *     wdtpci_write:
+ *     @file: file handle to the watchdog
+ *     @buf: buffer to write (unused as data does not matter here
+ *     @count: count of bytes
+ *     @ppos: pointer to the position to write. No seeks allowed
+ *
+ *     A write to a watchdog device is defined as a keepalive signal. Any
+ *     write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if(get_user(c, buf+i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       expect_close = 42;
+                       }
+               }
+               wdtpci_ping();
+       }
+
+       return count;
+}
+
+/**
+ *     wdtpci_ioctl:
+ *     @inode: inode of the device
+ *     @file: file handle to the device
+ *     @cmd: watchdog command
+ *     @arg: argument pointer
+ *
+ *     The watchdog API defines a common set of functions for all watchdogs
+ *     according to their available features. We only actually usefully support
+ *     querying capabilities and current status.
+ */
+
+static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       int new_heartbeat;
+       int status;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT|
+                                       WDIOF_MAGICCLOSE|
+                                       WDIOF_KEEPALIVEPING,
+               .firmware_version =     1,
+               .identity =             "PCI-WDT500/501",
+       };
+
+       /* Add options according to the card we have */
+       ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
+#ifdef CONFIG_WDT_501_PCI
+       ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER);
+       if (tachometer)
+               ident.options |= WDIOF_FANFAULT;
+#endif /* CONFIG_WDT_501_PCI */
+
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
+
+               case WDIOC_GETSTATUS:
+                       wdtpci_get_status(&status);
+                       return put_user(status, p);
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, p);
+               case WDIOC_KEEPALIVE:
+                       wdtpci_ping();
+                       return 0;
+               case WDIOC_SETTIMEOUT:
+                       if (get_user(new_heartbeat, p))
+                               return -EFAULT;
+
+                       if (wdtpci_set_heartbeat(new_heartbeat))
+                               return -EINVAL;
+
+                       wdtpci_ping();
+                       /* Fall */
+               case WDIOC_GETTIMEOUT:
+                       return put_user(heartbeat, p);
+       }
+}
+
+/**
+ *     wdtpci_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     The watchdog device has been opened. The watchdog device is single
+ *     open and on opening we load the counters. Counter zero is a 100Hz
+ *     cascade, into counter 1 which downcounts to reboot. When the counter
+ *     triggers counter 2 downcounts the length of the reset pulse which
+ *     set set to be as long as possible.
+ */
+
+static int wdtpci_open(struct inode *inode, struct file *file)
+{
+       if (down_trylock(&open_sem))
+               return -EBUSY;
+
+       if (nowayout) {
+               __module_get(THIS_MODULE);
+       }
+       /*
+        *      Activate
+        */
+       wdtpci_start();
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     wdtpci_release:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The watchdog has a configurable API. There is a religious dispute
+ *     between people who want their watchdog to be able to shut down and
+ *     those who want to be sure if the watchdog manager dies the machine
+ *     reboots. In the former case we disable the counters, in the latter
+ *     case you have to open it again very soon.
+ */
+
+static int wdtpci_release(struct inode *inode, struct file *file)
+{
+       if (expect_close == 42) {
+               wdtpci_stop();
+       } else {
+               printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
+               wdtpci_ping();
+       }
+       expect_close = 0;
+       up(&open_sem);
+       return 0;
+}
+
+#ifdef CONFIG_WDT_501_PCI
+/**
+ *     wdtpci_temp_read:
+ *     @file: file handle to the watchdog board
+ *     @buf: buffer to write 1 byte into
+ *     @count: length of buffer
+ *     @ptr: offset (no seek allowed)
+ *
+ *     Read reports the temperature in degrees Fahrenheit. The API is in
+ *     fahrenheit. It was designed by an imperial measurement luddite.
+ */
+
+static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
+{
+       int temperature;
+
+       if (wdtpci_get_temperature(&temperature))
+               return -EFAULT;
+
+       if (copy_to_user (buf, &temperature, 1))
+               return -EFAULT;
+
+       return 1;
+}
+
+/**
+ *     wdtpci_temp_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     The temperature device has been opened.
+ */
+
+static int wdtpci_temp_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+/**
+ *     wdtpci_temp_release:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The temperature device has been closed.
+ */
+
+static int wdtpci_temp_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+#endif /* CONFIG_WDT_501_PCI */
+
+/**
+ *     notify_sys:
+ *     @this: our notifier block
+ *     @code: the event being reported
+ *     @unused: unused
+ *
+ *     Our notifier is called on system shutdowns. We want to turn the card
+ *     off at reboot otherwise the machine will reboot again during memory
+ *     test or worse yet during the following fsck. This would suck, in fact
+ *     trust me - if it happens it does suck.
+ */
+
+static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code==SYS_DOWN || code==SYS_HALT) {
+               /* Turn the card off */
+               wdtpci_stop();
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+
+static const struct file_operations wdtpci_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = wdtpci_write,
+       .ioctl          = wdtpci_ioctl,
+       .open           = wdtpci_open,
+       .release        = wdtpci_release,
+};
+
+static struct miscdevice wdtpci_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wdtpci_fops,
+};
+
+#ifdef CONFIG_WDT_501_PCI
+static const struct file_operations wdtpci_temp_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = wdtpci_temp_read,
+       .open           = wdtpci_temp_open,
+       .release        = wdtpci_temp_release,
+};
+
+static struct miscdevice temp_miscdev = {
+       .minor  = TEMP_MINOR,
+       .name   = "temperature",
+       .fops   = &wdtpci_temp_fops,
+};
+#endif /* CONFIG_WDT_501_PCI */
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block wdtpci_notifier = {
+       .notifier_call = wdtpci_notify_sys,
+};
+
+
+static int __devinit wdtpci_init_one (struct pci_dev *dev,
+                                  const struct pci_device_id *ent)
+{
+       int ret = -EIO;
+
+       dev_count++;
+       if (dev_count > 1) {
+               printk (KERN_ERR PFX "this driver only supports 1 device\n");
+               return -ENODEV;
+       }
+
+       if (pci_enable_device (dev)) {
+               printk (KERN_ERR PFX "Not possible to enable PCI Device\n");
+               return -ENODEV;
+       }
+
+       if (pci_resource_start (dev, 2) == 0x0000) {
+               printk (KERN_ERR PFX "No I/O-Address for card detected\n");
+               ret = -ENODEV;
+               goto out_pci;
+       }
+
+       sema_init(&open_sem, 1);
+       spin_lock_init(&wdtpci_lock);
+
+       irq = dev->irq;
+       io = pci_resource_start (dev, 2);
+
+       if (request_region (io, 16, "wdt_pci") == NULL) {
+               printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", io);
+               goto out_pci;
+       }
+
+       if (request_irq (irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED,
+                        "wdt_pci", &wdtpci_miscdev)) {
+               printk (KERN_ERR PFX "IRQ %d is not free\n", irq);
+               goto out_reg;
+       }
+
+       printk ("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%04x (Interrupt %d)\n",
+               io, irq);
+
+       /* Check that the heartbeat value is within it's range ; if not reset to the default */
+       if (wdtpci_set_heartbeat(heartbeat)) {
+               wdtpci_set_heartbeat(WD_TIMO);
+               printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
+                       WD_TIMO);
+       }
+
+       ret = register_reboot_notifier (&wdtpci_notifier);
+       if (ret) {
+               printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret);
+               goto out_irq;
+       }
+
+#ifdef CONFIG_WDT_501_PCI
+       ret = misc_register (&temp_miscdev);
+       if (ret) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       TEMP_MINOR, ret);
+               goto out_rbt;
+       }
+#endif /* CONFIG_WDT_501_PCI */
+
+       ret = misc_register (&wdtpci_miscdev);
+       if (ret) {
+               printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                       WATCHDOG_MINOR, ret);
+               goto out_misc;
+       }
+
+       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
+#ifdef CONFIG_WDT_501_PCI
+       printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled"));
+#endif /* CONFIG_WDT_501_PCI */
+
+       ret = 0;
+out:
+       return ret;
+
+out_misc:
+#ifdef CONFIG_WDT_501_PCI
+       misc_deregister(&temp_miscdev);
+out_rbt:
+#endif /* CONFIG_WDT_501_PCI */
+       unregister_reboot_notifier(&wdtpci_notifier);
+out_irq:
+       free_irq(irq, &wdtpci_miscdev);
+out_reg:
+       release_region (io, 16);
+out_pci:
+       pci_disable_device(dev);
+       goto out;
+}
+
+
+static void __devexit wdtpci_remove_one (struct pci_dev *pdev)
+{
+       /* here we assume only one device will ever have
+        * been picked up and registered by probe function */
+       misc_deregister(&wdtpci_miscdev);
+#ifdef CONFIG_WDT_501_PCI
+       misc_deregister(&temp_miscdev);
+#endif /* CONFIG_WDT_501_PCI */
+       unregister_reboot_notifier(&wdtpci_notifier);
+       free_irq(irq, &wdtpci_miscdev);
+       release_region(io, 16);
+       pci_disable_device(pdev);
+       dev_count--;
+}
+
+
+static struct pci_device_id wdtpci_pci_tbl[] = {
+       {
+               .vendor    = PCI_VENDOR_ID_ACCESSIO,
+               .device    = PCI_DEVICE_ID_WDG_CSM,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_ANY_ID,
+       },
+       { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
+
+
+static struct pci_driver wdtpci_driver = {
+       .name           = "wdt_pci",
+       .id_table       = wdtpci_pci_tbl,
+       .probe          = wdtpci_init_one,
+       .remove         = __devexit_p(wdtpci_remove_one),
+};
+
+
+/**
+ *     wdtpci_cleanup:
+ *
+ *     Unload the watchdog. You cannot do this with any file handles open.
+ *     If your watchdog is set to continue ticking on close and you unload
+ *     it, well it keeps ticking. We won't get the interrupt but the board
+ *     will not touch PC memory so all is fine. You just have to load a new
+ *     module in xx seconds or reboot.
+ */
+
+static void __exit wdtpci_cleanup(void)
+{
+       pci_unregister_driver (&wdtpci_driver);
+}
+
+
+/**
+ *     wdtpci_init:
+ *
+ *     Set up the WDT watchdog board. All we have to do is grab the
+ *     resources we require and bitch if anyone beat us to them.
+ *     The open() function will actually kick the board off.
+ */
+
+static int __init wdtpci_init(void)
+{
+       return pci_register_driver (&wdtpci_driver);
+}
+
+
+module_init(wdtpci_init);
+module_exit(wdtpci_cleanup);
+
+MODULE_AUTHOR("JP Nollmann, Alan Cox");
+MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);