diff options
Diffstat (limited to 'drivers/char/watchdog')
37 files changed, 0 insertions, 14828 deletions
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig deleted file mode 100644 index b53e2e2b5ae..00000000000 --- a/drivers/char/watchdog/Kconfig +++ /dev/null @@ -1,559 +0,0 @@ -# -# Watchdog device configuration -# - -menu "Watchdog Cards" - -config 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 - online 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. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - 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" - depends on WATCHDOG - -# Architecture Independant - -config SOFT_WATCHDOG - tristate "Software watchdog" - depends on 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. - -# ARM Architecture - -config 21285_WATCHDOG - tristate "DC21285 watchdog" - depends on WATCHDOG && FOOTBRIDGE - help - The Intel Footbridge chip contains a builtin 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 WATCHDOG && 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 IXP4XX_WATCHDOG - tristate "IXP4xx Watchdog" - depends on WATCHDOG && 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 IXP2000_WATCHDOG - tristate "IXP2000 Watchdog" - depends on WATCHDOG && 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 S3C2410_WATCHDOG - tristate "S3C2410 Watchdog" - depends on WATCHDOG && 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 reasonbaly 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 WATCHDOG && ( 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. - -# X86 (i386 + ia64 + x86_64) Architecture - -config ACQUIRE_WDT - tristate "Acquire SBC Watchdog Timer" - depends on WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WAFER_WDT - tristate "ICP Wafer 5823 Single Board Computer Watchdog" - depends on WATCHDOG && 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 I8XX_TCO - tristate "Intel i8xx TCO Timer/Watchdog" - depends on WATCHDOG && (X86 || IA64) && PCI - ---help--- - Hardware driver for the TCO timer built into the Intel 82801 - I/O Controller Hub family. 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 i8xx_tco. - -config SC1200_WDT - tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" - depends on WATCHDOG && 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 WATCHDOG && 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 60XX_WDT - tristate "SBC-60XX Watchdog Timer" - depends on WATCHDOG && 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 CPU5_WDT - tristate "SMA CPU5 Watchdog" - depends on WATCHDOG && X86 - ---help--- - TBD. - To compile this driver as a module, choose M here: the - module will be called cpu5wdt. - -config W83627HF_WDT - tristate "W83627HF Watchdog Timer" - depends on WATCHDOG && 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 W83877F_WDT - tristate "W83877F (EMACS) Watchdog Timer" - depends on WATCHDOG && 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 MACHZ_WDT - tristate "ZF MachZ Watchdog" - depends on WATCHDOG && X86 - ---help--- - If you are using a ZF Micro MachZ processor, say Y here, otherwise - N. This is the driver for the watchdog timer builtin 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. - -# PowerPC Architecture - -config 8xx_WDT - tristate "MPC8xx Watchdog Timer" - depends on WATCHDOG && 8xx - -# MIPS Architecture - -config INDYDOG - tristate "Indy/I2 Hardware Watchdog" - depends on WATCHDOG && SGI_IP22 - help - Hardwaredriver 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. - -# S390 Architecture - -config ZVM_WATCHDOG - tristate "z/VM Watchdog Timer" - depends on WATCHDOG && ARCH_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 Architecture - -config SH_WDT - tristate "SuperH Watchdog" - depends on WATCHDOG && SUPERH - 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. - -# SPARC64 Architecture - -config WATCHDOG_CP1XXX - tristate "CP1XXX Hardware Watchdog support" - depends on WATCHDOG && 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 WATCHDOG && 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. - -# ppc64 RTAS watchdog -config WATCHDOG_RTAS - tristate "RTAS watchdog" - depends on WATCHDOG && 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. - -# -# ISA-based Watchdog Cards -# - -comment "ISA-based Watchdog Cards" - depends on WATCHDOG && ISA - -config PCWATCHDOG - tristate "Berkshire Products ISA-PC Watchdog" - depends on WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && PCI - -config PCIPCWATCHDOG - tristate "Berkshire Products PCI-PC Watchdog" - depends on WATCHDOG && 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 WATCHDOG && 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 WATCHDOG && USB - -config USBPCWATCHDOG - tristate "Berkshire Products USB-PC Watchdog" - depends on WATCHDOG && 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. - -endmenu diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile deleted file mode 100644 index c1838834ea7..00000000000 --- a/drivers/char/watchdog/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Makefile for the WatchDog device drivers. -# - -obj-$(CONFIG_PCWATCHDOG) += pcwd.o -obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o -obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o -obj-$(CONFIG_IB700_WDT) += ib700wdt.o -obj-$(CONFIG_MIXCOMWD) += mixcomwd.o -obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o -obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o -obj-$(CONFIG_WDT) += wdt.o -obj-$(CONFIG_WDTPCI) += wdt_pci.o -obj-$(CONFIG_21285_WATCHDOG) += wdt285.o -obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o -obj-$(CONFIG_MACHZ_WDT) += machzwd.o -obj-$(CONFIG_SH_WDT) += shwdt.o -obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o -obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o -obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o -obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o -obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o -obj-$(CONFIG_SC520_WDT) += sc520_wdt.o -obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o -obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o -obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o -obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o -obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o -obj-$(CONFIG_INDYDOG) += indydog.o -obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o -obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o -obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o -obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o -obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o -obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o - -# Only one watchdog can succeed. We probe the hardware watchdog -# drivers first, then the softdog driver. This means if your hardware -# watchdog dies or is 'borrowed' for some reason the software watchdog -# still gives you some cover. - -obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c deleted file mode 100644 index 7289f4af93d..00000000000 --- a/drivers/char/watchdog/acquirewdt.c +++ /dev/null @@ -1,327 +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. - */ - -#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> - -#define WATCHDOG_NAME "Acquire WDT" -#define PFX WATCHDOG_NAME ": " -#define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ - -static unsigned long acq_is_open; -static char expect_close; - -/* - * You must set these - there is no sane way to probe for this board. - */ - -static int wdt_stop = 0x43; -module_param(wdt_stop, int, 0); -MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)"); - -static int wdt_start = 0x443; -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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Kernel methods. - */ - -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 = "Acquire WDT", - }; - - 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 -ENOIOCTLCMD; - } -} - -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; -} - -/* - * Notifier for system down - */ - -static int acq_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - acq_stop(); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static 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, -}; - -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block acq_notifier = -{ - .notifier_call = acq_notify_sys, -}; - -static int __init acq_init(void) -{ - int ret; - - printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n"); - - 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 = register_reboot_notifier(&acq_notifier); - if (ret != 0) { - printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - ret); - goto unreg_regions; - } - - 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_reboot; - } - - printk (KERN_INFO PFX "initialized. (nowayout=%d)\n", - nowayout); - - return 0; - -unreg_reboot: - unregister_reboot_notifier(&acq_notifier); -unreg_regions: - release_region(wdt_start, 1); -unreg_stop: - if (wdt_stop != wdt_start) - release_region(wdt_stop, 1); -out: - return ret; -} - -static void __exit acq_exit(void) -{ - misc_deregister(&acq_miscdev); - unregister_reboot_notifier(&acq_notifier); - if(wdt_stop != wdt_start) - release_region(wdt_stop,1); - release_region(wdt_start,1); -} - -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 index 194a3fd36b9..00000000000 --- a/drivers/char/watchdog/advantechwdt.c +++ /dev/null @@ -1,328 +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/notifier.h> -#include <linux/reboot.h> -#include <linux/init.h> - -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#define WATCHDOG_NAME "Advantech WDT" -#define PFX WATCHDOG_NAME ": " -#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ - -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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Kernel methods. - */ - -static void -advwdt_ping(void) -{ - /* Write a watchdog value */ - outb_p(timeout, wdt_start); -} - -static void -advwdt_disable(void) -{ - inb_p(wdt_stop); -} - -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 = "Advantech 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: - advwdt_ping(); - break; - - case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, p)) - return -EFAULT; - if ((new_timeout < 1) || (new_timeout > 63)) - return -EINVAL; - timeout = new_timeout; - 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 -ENOIOCTLCMD; - } - 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; -} - -/* - * Notifier for system down - */ - -static int -advwdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - /* Turn the WDT off */ - advwdt_disable(); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static 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, -}; - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block advwdt_notifier = { - .notifier_call = advwdt_notify_sys, -}; - -static int __init -advwdt_init(void) -{ - int ret; - - printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); - - if (timeout < 1 || timeout > 63) { - timeout = WATCHDOG_TIMEOUT; - printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n", - timeout); - } - - 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 = register_reboot_notifier(&advwdt_notifier); - if (ret != 0) { - printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - ret); - goto unreg_regions; - } - - 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_reboot; - } - - printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", - timeout, nowayout); - -out: - return ret; -unreg_reboot: - unregister_reboot_notifier(&advwdt_notifier); -unreg_regions: - release_region(wdt_start, 1); -unreg_stop: - if (wdt_stop != wdt_start) - release_region(wdt_stop, 1); - goto out; -} - -static void __exit -advwdt_exit(void) -{ - misc_deregister(&advwdt_miscdev); - unregister_reboot_notifier(&advwdt_notifier); - if(wdt_stop != wdt_start) - release_region(wdt_stop,1); - release_region(wdt_start,1); -} - -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 index 8338ca300e2..00000000000 --- a/drivers/char/watchdog/alim1535_wdt.c +++ /dev/null @@ -1,458 +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=CONFIG_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 -ENOIOCTLCMD; - } -} - -/* - * 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, 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 1535 series bridge */ - pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x1535, NULL); - if(pdev == NULL) - return -ENODEV; - - /* Check for the a 7101 PMU */ - pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x7101, NULL); - if(pdev == NULL) - return -ENODEV; - - if(pci_enable_device(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 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); -} - -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 index c05ac188a4d..00000000000 --- a/drivers/char/watchdog/alim7101_wdt.c +++ /dev/null @@ -1,416 +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 struct timer_list timer; -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=CONFIG_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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); -} - -/* - * 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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - - 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 -ENOIOCTLCMD; - } -} - -static 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); -} - -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_find_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_find_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"); - return -EBUSY; - } - pci_read_config_byte(ali1543_south, 0x5e, &tmp); - 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"); - return -EBUSY; - } - 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"); - return -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); - } - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 1; - - 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: - return rc; -} - -module_init(alim7101_wdt_init); -module_exit(alim7101_wdt_unload); - -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/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c deleted file mode 100644 index 2865dac0a81..00000000000 --- a/drivers/char/watchdog/cpu5wdt.c +++ /dev/null @@ -1,303 +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 <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 semaphore 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 ) { - cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL; - add_timer(&cpu5wdt_device.timer); - } - else { - /* ticks doesn't matter anyway */ - up(&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); - cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL; - add_timer(&cpu5wdt_device.timer); - } - /* 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_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 -ENOIOCTLCMD; - } - 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 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 ( (err = misc_register(&cpu5wdt_misc)) < 0 ) { - printk(KERN_ERR PFX "misc_register failed\n"); - goto no_misc; - } - - if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { - printk(KERN_ERR PFX "request_region failed\n"); - err = -EBUSY; - goto no_port; - } - - /* watchdog reboot? */ - val = inb(port + CPU5WDT_STATUS_REG); - val = (val >> 2) & 1; - if ( !val ) - printk(KERN_INFO PFX "sorry, was my fault\n"); - - init_MUTEX_LOCKED(&cpu5wdt_device.stop); - cpu5wdt_device.queue = 0; - - clear_bit(0, &cpu5wdt_device.inuse); - - init_timer(&cpu5wdt_device.timer); - cpu5wdt_device.timer.function = cpu5wdt_trigger; - cpu5wdt_device.timer.data = 0; - - cpu5wdt_device.default_ticks = ticks; - - printk(KERN_INFO PFX "init success\n"); - - return 0; - -no_port: - misc_deregister(&cpu5wdt_misc); -no_misc: - 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; - down(&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/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c deleted file mode 100644 index 25c2f257561..00000000000 --- a/drivers/char/watchdog/eurotechwdt.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Eurotech CPU-1220/1410 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: - * - * 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 - * - * 2001 - Rodolfo Giometti - * Initial release - * - * 2002.05.30 - Joel Becker <joel.becker@oracle.com> - * Added Matt Domsch's nowayout module option. - */ - -#include <linux/config.h> -#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=CONFIG_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, struct pt_regs *regs) -{ - 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 -ENOIOCTLCMD; - - 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 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 = misc_register(&eurwdt_miscdev); - if (ret) { - printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto out; - } - - ret = request_irq(irq, eurwdt_interrupt, SA_INTERRUPT, "eurwdt", NULL); - if(ret) { - printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); - goto outmisc; - } - - 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; - } - - 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; - -outreg: - release_region(io, 2); - -outirq: - free_irq(irq, NULL); - -outmisc: - misc_deregister(&eurwdt_miscdev); - 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/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c deleted file mode 100644 index f975dab1ddf..00000000000 --- a/drivers/char/watchdog/i8xx_tco.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * i8xx_tco 0.07: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. - * http://www.kernelconcepts.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 kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de> - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox <alan@redhat.com> - * - * The TCO timer 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 - * - * 20000710 Nils Faerber - * Initial Version 0.01 - * 20000728 Nils Faerber - * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups - * 20011214 Matt Domsch <Matt_Domsch@dell.com> - * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option as i810_margin already exists. - * 20020224 Joel Becker, Wim Van Sebroeck - * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, - * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. - * 20020412 Rob Radez <rob@osinvestor.com>, Wim Van Sebroeck - * 0.05 Fix possible timer_alive race, add expect close support, - * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and - * WDIOC_SETOPTIONS), made i810tco_getdevice __init, - * removed boot_status, removed tco_timer_read, - * added support for 82801DB and 82801E chipset, - * added support for 82801EB and 8280ER chipset, - * general cleanup. - * 20030921 Wim Van Sebroeck <wim@iguana.be> - * 0.06 change i810_margin to heartbeat, use module_param, - * added notify system support, renamed module to i8xx_tco. - * 20050128 Wim Van Sebroeck <wim@iguana.be> - * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW - * chipsets. Also added support for the "undocumented" ICH7 chipset. - */ - -/* - * Includes, defines, variables, module parameters, ... - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/pci.h> -#include <linux/ioport.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#include "i8xx_tco.h" - -/* Module and version information */ -#define TCO_VERSION "0.07" -#define TCO_MODULE_NAME "i8xx TCO timer" -#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION -#define PFX TCO_MODULE_NAME ": " - -/* internal variables */ -static unsigned int ACPIBASE; -static spinlock_t tco_lock; /* Guards the hardware */ -static unsigned long timer_alive; -static char tco_expect_close; -static struct pci_dev *i8xx_tco_pci; - -/* module parameters */ -#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2<heartbeat<39) */ -static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, 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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Some TCO specific functions - */ - -static inline unsigned char seconds_to_ticks(int seconds) -{ - /* the internal timer is stored as ticks which decrement - * every 0.6 seconds */ - return (seconds * 10) / 6; -} - -static int tco_timer_start (void) -{ - unsigned char val; - - spin_lock(&tco_lock); - val = inb (TCO1_CNT + 1); - val &= 0xf7; - outb (val, TCO1_CNT + 1); - val = inb (TCO1_CNT + 1); - spin_unlock(&tco_lock); - - if (val & 0x08) - return -1; - return 0; -} - -static int tco_timer_stop (void) -{ - unsigned char val; - - spin_lock(&tco_lock); - val = inb (TCO1_CNT + 1); - val |= 0x08; - outb (val, TCO1_CNT + 1); - val = inb (TCO1_CNT + 1); - spin_unlock(&tco_lock); - - if ((val & 0x08) == 0) - return -1; - return 0; -} - -static int tco_timer_keepalive (void) -{ - spin_lock(&tco_lock); - outb (0x01, TCO1_RLD); - spin_unlock(&tco_lock); - return 0; -} - -static int tco_timer_set_heartbeat (int t) -{ - unsigned char val; - unsigned char tmrval; - - tmrval = seconds_to_ticks(t); - /* from the specs: */ - /* "Values of 0h-3h are ignored and should not be attempted" */ - if (tmrval > 0x3f || tmrval < 0x04) - return -EINVAL; - - /* Write new heartbeat to watchdog */ - spin_lock(&tco_lock); - val = inb (TCO1_TMR); - val &= 0xc0; - val |= tmrval; - outb (val, TCO1_TMR); - val = inb (TCO1_TMR); - spin_unlock(&tco_lock); - - if ((val & 0x3f) != tmrval) - return -EINVAL; - - heartbeat = t; - return 0; -} - -/* - * /dev/watchdog handling - */ - -static int i8xx_tco_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 - */ - tco_timer_keepalive (); - tco_timer_start (); - return nonseekable_open(inode, file); -} - -static int i8xx_tco_release (struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - */ - if (tco_expect_close == 42) { - tco_timer_stop (); - } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); - tco_timer_keepalive (); - } - clear_bit(0, &timer_alive); - tco_expect_close = 0; - return 0; -} - -static ssize_t i8xx_tco_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... */ - tco_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') - tco_expect_close = 42; - } - } - - /* someone wrote to us, we should reload the timer */ - tco_timer_keepalive (); - } - return len; -} - -static int i8xx_tco_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 = TCO_MODULE_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: - tco_timer_keepalive (); - return 0; - - case WDIOC_SETOPTIONS: - { - if (get_user (new_options, p)) - return -EFAULT; - - if (new_options & WDIOS_DISABLECARD) { - tco_timer_stop (); - retval = 0; - } - - if (new_options & WDIOS_ENABLECARD) { - tco_timer_keepalive (); - tco_timer_start (); - retval = 0; - } - - return retval; - } - - case WDIOC_SETTIMEOUT: - { - if (get_user(new_heartbeat, p)) - return -EFAULT; - - if (tco_timer_set_heartbeat(new_heartbeat)) - return -EINVAL; - - tco_timer_keepalive (); - /* Fall */ - } - - case WDIOC_GETTIMEOUT: - return put_user(heartbeat, p); - - default: - return -ENOIOCTLCMD; - } -} - -/* - * Notify system - */ - -static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, void *unused) -{ - if (code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - tco_timer_stop (); - } - - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static struct file_operations i8xx_tco_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = i8xx_tco_write, - .ioctl = i8xx_tco_ioctl, - .open = i8xx_tco_open, - .release = i8xx_tco_release, -}; - -static struct miscdevice i8xx_tco_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &i8xx_tco_fops, -}; - -static struct notifier_block i8xx_tco_notifier = { - .notifier_call = i8xx_tco_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 i8xx_tco_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, /* End of list */ -}; -MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); - -/* - * Init & exit routines - */ - -static unsigned char __init i8xx_tco_getdevice (void) -{ - struct pci_dev *dev = NULL; - u8 val1, val2; - u16 badr; - /* - * Find the PCI device - */ - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_match_id(i8xx_tco_pci_tbl, dev)) { - i8xx_tco_pci = dev; - break; - } - } - - if (i8xx_tco_pci) { - /* - * Find the ACPI 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_byte (i8xx_tco_pci, 0x40, &val1); - pci_read_config_byte (i8xx_tco_pci, 0x41, &val2); - badr = ((val2 << 1) | (val1 >> 7)) << 7; - ACPIBASE = badr; - /* Something's wrong here, ACPIBASE has to be set */ - if (badr == 0x0001 || badr == 0x0000) { - printk (KERN_ERR PFX "failed to get TCOBASE address\n"); - return 0; - } - /* - * Check chipset's NO_REBOOT bit - */ - pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - val1 &= 0xfd; - pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); - pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); - return 0; /* Cannot reset NO_REBOOT bit */ - } - } - /* Set the TCO_EN bit in SMI_EN register */ - if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { - printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", - SMI_EN + 1); - return 0; - } - val1 = inb (SMI_EN + 1); - val1 &= 0xdf; - outb (val1, SMI_EN + 1); - release_region (SMI_EN + 1, 1); - return 1; - } - return 0; -} - -static int __init watchdog_init (void) -{ - int ret; - - spin_lock_init(&tco_lock); - - /* Check whether or not the hardware watchdog is there */ - if (!i8xx_tco_getdevice () || i8xx_tco_pci == NULL) - return -ENODEV; - - if (!request_region (TCOBASE, 0x10, "i8xx TCO")) { - printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", - TCOBASE); - ret = -EIO; - goto out; - } - - /* Clear out the (probably old) status */ - outb (0, TCO1_STS); - outb (3, TCO2_STS); - - /* Check that the heartbeat value is within it's range ; if not reset to the default */ - if (tco_timer_set_heartbeat (heartbeat)) { - heartbeat = WATCHDOG_HEARTBEAT; - tco_timer_set_heartbeat (heartbeat); - printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, using %d\n", - heartbeat); - } - - ret = register_reboot_notifier(&i8xx_tco_notifier); - if (ret != 0) { - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - ret); - goto unreg_region; - } - - ret = misc_register(&i8xx_tco_miscdev); - if (ret != 0) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - goto unreg_notifier; - } - - tco_timer_stop (); - - printk (KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n", - TCOBASE, heartbeat, nowayout); - - return 0; - -unreg_notifier: - unregister_reboot_notifier(&i8xx_tco_notifier); -unreg_region: - release_region (TCOBASE, 0x10); -out: - return ret; -} - -static void __exit watchdog_cleanup (void) -{ - u8 val; - - /* Stop the timer before we leave */ - if (!nowayout) - tco_timer_stop (); - - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i8xx_tco_pci, 0xd4, val); - - /* Deregister */ - misc_deregister (&i8xx_tco_miscdev); - unregister_reboot_notifier(&i8xx_tco_notifier); - release_region (TCOBASE, 0x10); -} - -module_init(watchdog_init); -module_exit(watchdog_cleanup); - -MODULE_AUTHOR("Nils Faerber"); -MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/i8xx_tco.h b/drivers/char/watchdog/i8xx_tco.h deleted file mode 100644 index cc14eb8ac3d..00000000000 --- a/drivers/char/watchdog/i8xx_tco.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * i8xx_tco: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. - * http://www.kernelconcepts.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 kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de> - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox <alan@redhat.com> - * - * For history and the complete list of supported I/O Controller Hub's - * see i8xx_tco.c - */ - - -/* - * Some address definitions for the TCO - */ - -#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ -#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ -#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ -#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ -#define TCO1_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 SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c deleted file mode 100644 index cf60329eec8..00000000000 --- a/drivers/char/watchdog/ib700wdt.c +++ /dev/null @@ -1,347 +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/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/ioport.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 ibwdt_is_open; -static spinlock_t ibwdt_lock; -static char expect_close; - -#define PFX "ib700wdt: " - -/* - * - * 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=CONFIG_WATCHDOG_NOWAYOUT)"); - - -/* - * Kernel methods. - */ - -static void -ibwdt_ping(void) -{ - /* Write a watchdog value */ - outb_p(wd_margin, WDT_START); -} - -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 i, 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: - return put_user(0, p); - - case WDIOC_KEEPALIVE: - ibwdt_ping(); - break; - - case WDIOC_SETTIMEOUT: - if (get_user(new_margin, p)) - return -EFAULT; - if ((new_margin < 0) || (new_margin > 30)) - return -EINVAL; - for (i = 0x0F; i > -1; i--) - if (wd_times[i] > new_margin) - break; - wd_margin = i; - ibwdt_ping(); - /* Fall */ - - case WDIOC_GETTIMEOUT: - return put_user(wd_times[wd_margin], p); - break; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int -ibwdt_open(struct inode *inode, struct file *file) -{ - spin_lock(&ibwdt_lock); - if (test_and_set_bit(0, &ibwdt_is_open)) { - spin_unlock(&ibwdt_lock); - return -EBUSY; - } - if (nowayout) - __module_get(THIS_MODULE); - - /* Activate */ - ibwdt_ping(); - spin_unlock(&ibwdt_lock); - return nonseekable_open(inode, file); -} - -static int -ibwdt_close(struct inode *inode, struct file *file) -{ - spin_lock(&ibwdt_lock); - if (expect_close == 42) - outb_p(0, WDT_STOP); - else - printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); - - clear_bit(0, &ibwdt_is_open); - expect_close = 0; - spin_unlock(&ibwdt_lock); - return 0; -} - -/* - * Notifier for system down - */ - -static int -ibwdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) { - /* Turn the WDT off */ - outb_p(0, WDT_STOP); - } - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static 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, -}; - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block ibwdt_notifier = { - .notifier_call = ibwdt_notify_sys, -}; - -static int __init ibwdt_init(void) -{ - int res; - - printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n"); - - spin_lock_init(&ibwdt_lock); - res = misc_register(&ibwdt_miscdev); - if (res) { - printk (KERN_ERR PFX "failed to register misc device\n"); - goto out_nomisc; - } - -#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 = register_reboot_notifier(&ibwdt_notifier); - if (res) { - printk (KERN_ERR PFX "Failed to register reboot notifier.\n"); - goto out_noreboot; - } - return 0; - -out_noreboot: - release_region(WDT_START, 1); -out_nostartreg: -#if WDT_START != WDT_STOP - release_region(WDT_STOP, 1); -#endif -out_nostopreg: - misc_deregister(&ibwdt_miscdev); -out_nomisc: - return res; -} - -static void __exit -ibwdt_exit(void) -{ - misc_deregister(&ibwdt_miscdev); - unregister_reboot_notifier(&ibwdt_notifier); -#if WDT_START != WDT_STOP - release_region(WDT_STOP,1); -#endif - release_region(WDT_START,1); -} - -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/indydog.c b/drivers/char/watchdog/indydog.c deleted file mode 100644 index b4b94daba67..00000000000 --- a/drivers/char/watchdog/indydog.c +++ /dev/null @@ -1,216 +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/config.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=CONFIG_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 -ENOIOCTLCMD; - 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 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/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c deleted file mode 100644 index e7640bc4904..00000000000 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * drivers/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/config.h> -#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 = -ENOIOCTLCMD; - 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 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 = "IXP2000 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 index 8d916afbf4f..00000000000 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * drivers/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/config.h> -#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 = -ENOIOCTLCMD; - 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 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 = "IXP4xx 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)) { - printk("IXP4XXX Watchdog: Rev. A0 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/machzwd.c b/drivers/char/watchdog/machzwd.c deleted file mode 100644 index a9a20aad61e..00000000000 --- a/drivers/char/watchdog/machzwd.c +++ /dev/null @@ -1,496 +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/config.h> -#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=CONFIG_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 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 struct timer_list zf_timer; -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 */ - zf_timer.expires = jiffies + ZF_HW_TIMEO; - - add_timer(&zf_timer); - - /* 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); - - zf_timer.expires = jiffies + ZF_HW_TIMEO; - add_timer(&zf_timer); - }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: - return put_user(0, p); - - case WDIOC_KEEPALIVE: - zf_ping(0); - break; - - default: - return -ENOIOCTLCMD; - } - - 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 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(); - printk("%#x\n", ret); - 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); - - ret = misc_register(&zf_miscdev); - if (ret){ - printk(KERN_ERR "can't misc_register on minor=%d\n", - WATCHDOG_MINOR); - goto out; - } - - 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; - } - - zf_set_status(0); - zf_set_control(0); - - /* this is the timer that will do the hard work */ - init_timer(&zf_timer); - zf_timer.function = zf_ping; - zf_timer.data = 0; - - return 0; - -no_reboot: - release_region(ZF_IOBASE, 3); -no_region: - misc_deregister(&zf_miscdev); -out: - 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 index c9b301dccec..00000000000 --- a/drivers/char/watchdog/mixcomwd.c +++ /dev/null @@ -1,301 +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 - * - */ - -#define VERSION "0.5" - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/config.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 <asm/uaccess.h> -#include <asm/io.h> - -static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 }; - -#define MIXCOM_WATCHDOG_OFFSET 0xc10 -#define MIXCOM_ID 0x11 -#define FLASHCOM_WATCHDOG_OFFSET 0x4 -#define FLASHCOM_ID 0x18 - -static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */ - -static int watchdog_port; -static int mixcomwd_timer_alive; -static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 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=CONFIG_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 "mixcomwd: release called while internal timer alive"); - return -EBUSY; - } - init_timer(&mixcomwd_timer); - mixcomwd_timer.expires=jiffies + 5 * HZ; - mixcomwd_timer.function=mixcomwd_timerfun; - mixcomwd_timer.data=0; - mixcomwd_timer_alive=1; - add_timer(&mixcomwd_timer); - } else { - printk(KERN_CRIT "mixcomwd: 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_GETSUPPORT: - if (copy_to_user(argp, &ident, sizeof(ident))) { - return -EFAULT; - } - break; - case WDIOC_KEEPALIVE: - mixcomwd_ping(); - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static 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 mixcomwd_checkcard(int port) -{ - int id; - - port += MIXCOM_WATCHDOG_OFFSET; - if (!request_region(port, 1, "MixCOM watchdog")) { - return 0; - } - - id=inb_p(port) & 0x3f; - if(id!=MIXCOM_ID) { - release_region(port, 1); - return 0; - } - return port; -} - -static int __init flashcom_checkcard(int port) -{ - int id; - - port += FLASHCOM_WATCHDOG_OFFSET; - if (!request_region(port, 1, "MixCOM watchdog")) { - return 0; - } - - id=inb_p(port); - if(id!=FLASHCOM_ID) { - release_region(port, 1); - return 0; - } - return port; - } - -static int __init mixcomwd_init(void) -{ - int i; - int ret; - int found=0; - - for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) { - watchdog_port = mixcomwd_checkcard(mixcomwd_ioports[i]); - if (watchdog_port) { - found = 1; - } - } - - /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */ - for (i = 0x300; !found && i < 0x380; i+=0x8) { - watchdog_port = flashcom_checkcard(i); - if (watchdog_port) { - found = 1; - } - } - - if (!found) { - printk("mixcomwd: No card detected, or port not available.\n"); - return -ENODEV; - } - - ret = misc_register(&mixcomwd_miscdev); - if (ret) - { - release_region(watchdog_port, 1); - return ret; - } - - printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port); - - return 0; -} - -static void __exit mixcomwd_exit(void) -{ - if (!nowayout) { - if(mixcomwd_timer_alive) { - printk(KERN_WARNING "mixcomwd: I quit now, hardware will" - " probably reboot!\n"); - del_timer(&mixcomwd_timer); - mixcomwd_timer_alive=0; - } - } - release_region(watchdog_port,1); - misc_deregister(&mixcomwd_miscdev); -} - -module_init(mixcomwd_init); -module_exit(mixcomwd_exit); - -MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>"); -MODULE_DESCRIPTION("MixCom Watchdog driver"); -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 index 56d62ba7c6c..00000000000 --- a/drivers/char/watchdog/mpc8xx_wdt.c +++ /dev/null @@ -1,164 +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/config.h> -#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 <syslib/m8xx_wdt.h> - -static unsigned long wdt_opened; -static int wdt_status; - -static void mpc8xx_wdt_handler_disable(void) -{ - volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; - - imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE); - - printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); -} - -static void mpc8xx_wdt_handler_enable(void) -{ - volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; - - imap->im_sit.sit_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 0; -} - -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 (ppos != &file->f_pos) - return -ESPIPE; - - 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 -ENOIOCTLCMD; - } - - return 0; -} - -static 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/pcwd.c b/drivers/char/watchdog/pcwd.c deleted file mode 100644 index 427ad51b7a3..00000000000 --- a/drivers/char/watchdog/pcwd.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * PC Watchdog Driver - * by Ken Hollis (khollis@bitgate.com) - * - * Permission granted from Simon Machell (73244.1270@compuserve.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> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/timer.h> -#include <linux/jiffies.h> -#include <linux/config.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/reboot.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#define WD_VER "1.16 (06/12/2004)" -#define PFX "pcwd: " - -/* - * 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 defines that describe the control status bits 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 */ - -/* - * These are the defines that describe the control status bits 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 */ - -/* 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_DELAY_TIME_2SECS 0x0A -#define CMD_ISA_DELAY_TIME_4SECS 0x0B -#define CMD_ISA_DELAY_TIME_8SECS 0x0C - -/* - * 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 struct timer_list timer; -static unsigned long next_heartbeat; -static int temp_panic; -static int revision; /* The card's revision */ -static int supports_temp; /* Wether or not the card has a temperature device */ -static int command_mode; /* Wether or not the card is in command mode */ -static int initial_status; /* The card's boot status */ -static int current_readport; /* The cards I/O address */ -static spinlock_t io_lock; - -/* module parameters */ -#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ -static int heartbeat = WATCHDOG_HEARTBEAT; -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, 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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Internal functions - */ - -static int send_isa_command(int cmd) -{ - int i; - int control_status; - int port0, last_port0; /* Double read for stabilising */ - - /* The WCMD bit must be 1 and the command is only 4 bits in size */ - control_status = (cmd & 0x0F) | 0x80; - outb_p(control_status, current_readport + 2); - udelay(ISA_COMMAND_TIMEOUT); - - port0 = inb_p(current_readport); - for (i = 0; i < 25; ++i) { - last_port0 = port0; - port0 = inb_p(current_readport); - - if (port0 == last_port0) - break; /* Data is stable */ - - udelay (250); - } - - return port0; -} - -static int set_command_mode(void) -{ - int i, found=0, count=0; - - /* Set the card into command mode */ - spin_lock(&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, current_readport + 2); - udelay(1200); /* Spec says wait 1ms */ - outb_p(0x00, current_readport + 2); - udelay(ISA_COMMAND_TIMEOUT); - } - count++; - } - spin_unlock(&io_lock); - command_mode = found; - - return(found); -} - -static void unset_command_mode(void) -{ - /* Set the card into normal mode */ - spin_lock(&io_lock); - outb_p(0x00, current_readport + 2); - udelay(ISA_COMMAND_TIMEOUT); - spin_unlock(&io_lock); - - command_mode = 0; -} - -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, next_heartbeat)) { - /* Ping the watchdog */ - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) { - /* Rev A cards are reset by setting the WD_WDRST bit in register 1 */ - wdrst_stat = inb_p(current_readport); - wdrst_stat &= 0x0F; - wdrst_stat |= WD_WDRST; - - outb_p(wdrst_stat, current_readport + 1); - } else { - /* Re-trigger watchdog by writing to port 0 */ - outb_p(0x00, current_readport); - } - - /* Re-set the timer interval */ - mod_timer(&timer, jiffies + WDT_INTERVAL); - - spin_unlock(&io_lock); - } else { - printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); - } -} - -static int pcwd_start(void) -{ - int stat_reg; - - next_heartbeat = jiffies + (heartbeat * HZ); - - /* Start the timer */ - mod_timer(&timer, jiffies + WDT_INTERVAL); - - /* Enable the port */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 3); - udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if (stat_reg & 0x10) { - printk(KERN_INFO PFX "Could not start watchdog\n"); - return -EIO; - } - } - return 0; -} - -static int pcwd_stop(void) -{ - int stat_reg; - - /* Stop the timer */ - del_timer(&timer); - - /* Disable the board */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0xA5, current_readport + 3); - udelay(ISA_COMMAND_TIMEOUT); - outb_p(0xA5, current_readport + 3); - udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); - if ((stat_reg & 0x10) == 0) { - printk(KERN_INFO PFX "Could not stop watchdog\n"); - return -EIO; - } - } - return 0; -} - -static int pcwd_keepalive(void) -{ - /* user land ping */ - next_heartbeat = jiffies + (heartbeat * HZ); - return 0; -} - -static int pcwd_set_heartbeat(int t) -{ - if ((t < 2) || (t > 7200)) /* arbitrary upper limit */ - return -EINVAL; - - heartbeat = t; - return 0; -} - -static int pcwd_get_status(int *status) -{ - int card_status; - - *status=0; - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) - /* Rev A cards return status information from - * the base register, which is used for the - * temperature in other cards. */ - card_status = inb(current_readport); - 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. */ - card_status = inb(current_readport + 1); - } - spin_unlock(&io_lock); - - if (revision == PCWD_REVISION_A) { - if (card_status & WD_WDRST) - *status |= WDIOF_CARDRESET; - - if (card_status & WD_T110) { - *status |= WDIOF_OVERHEAT; - if (temp_panic) { - printk (KERN_INFO PFX "Temperature overheat trip!\n"); - kernel_power_off(); - } - } - } else { - if (card_status & WD_REVC_WTRP) - *status |= WDIOF_CARDRESET; - - if (card_status & WD_REVC_TTRP) { - *status |= WDIOF_OVERHEAT; - if (temp_panic) { - printk (KERN_INFO PFX "Temperature overheat trip!\n"); - kernel_power_off(); - } - } - } - - return 0; -} - -static int pcwd_clear_status(void) -{ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 1); /* clear reset status */ - spin_unlock(&io_lock); - } - return 0; -} - -static int pcwd_get_temperature(int *temperature) -{ - /* check that port 0 gives temperature info and no command results */ - if (command_mode) - return -1; - - *temperature = 0; - if (!supports_temp) - return -ENODEV; - - /* - * Convert celsius to fahrenheit, since this was - * the decided 'standard' for this return value. - */ - spin_lock(&io_lock); - *temperature = ((inb(current_readport)) * 9 / 5) + 32; - spin_unlock(&io_lock); - - 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 -ENOIOCTLCMD; - - 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(initial_status, argp); - - case WDIOC_GETTEMP: - if (pcwd_get_temperature(&temperature)) - return -EFAULT; - - return put_user(temperature, argp); - - case WDIOC_SETOPTIONS: - if (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) ) { - 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 (!supports_temp) - return -ENODEV; - - return nonseekable_open(inode, file); -} - -static int pcwd_temp_close(struct inode *inode, struct file *file) -{ - return 0; -} - -/* - * Notify system - */ - -static int pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) -{ - if (code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - pcwd_stop(); - } - - return NOTIFY_DONE; -} - -/* - * Kernel Interfaces - */ - -static 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 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, -}; - -static struct notifier_block pcwd_notifier = { - .notifier_call = pcwd_notify_sys, -}; - -/* - * Init & exit routines - */ - -static inline void get_support(void) -{ - if (inb(current_readport) != 0xF0) - supports_temp = 1; -} - -static inline int get_revision(void) -{ - int r = PCWD_REVISION_C; - - spin_lock(&io_lock); - /* REV A cards use only 2 io ports; test - * presumes a floating bus reads as 0xff. */ - if ((inb(current_readport + 2) == 0xFF) || - (inb(current_readport + 3) == 0xFF)) - r=PCWD_REVISION_A; - spin_unlock(&io_lock); - - return r; -} - -static inline char *get_firmware(void) -{ - int one, ten, hund, minor; - char *ret; - - ret = kmalloc(6, GFP_KERNEL); - if(ret == NULL) - return NULL; - - 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(ret, "%c.%c%c%c", one, ten, hund, minor); - } - else - sprintf(ret, "ERROR"); - - unset_command_mode(); - return(ret); -} - -static inline int get_option_switches(void) -{ - int rv=0; - - if (set_command_mode()) { - /* Get switch settings */ - rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS); - } - - unset_command_mode(); - return(rv); -} - -static int __devinit pcwatchdog_init(int base_addr) -{ - int ret; - char *firmware; - int option_switches; - - 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 (base_addr == 0x0000) { - printk(KERN_ERR PFX "No I/O-Address for card detected\n"); - return -ENODEV; - } - current_readport = base_addr; - - /* Check card's revision */ - revision = get_revision(); - - if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { - printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", - current_readport); - current_readport = 0x0000; - return -EIO; - } - - /* Initial variables */ - supports_temp = 0; - temp_panic = 0; - initial_status = 0x0000; - - /* get the boot_status */ - pcwd_get_status(&initial_status); - - /* clear the "card caused reboot" flag */ - pcwd_clear_status(); - - init_timer(&timer); - timer.function = pcwd_timer_ping; - timer.data = 0; - - /* Disable the board */ - pcwd_stop(); - - /* Check whether or not the card supports the temperature device */ - get_support(); - - /* Get some extra info from the hardware (in command/debug/diag mode) */ - if (revision == PCWD_REVISION_A) - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport); - else if (revision == PCWD_REVISION_C) { - firmware = get_firmware(); - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", - current_readport, firmware); - kfree(firmware); - option_switches = 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(); - } - } else { - /* Should NEVER happen, unless get_revision() fails. */ - printk(KERN_INFO PFX "Unable to get revision\n"); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; - return -1; - } - - if (supports_temp) - printk(KERN_INFO PFX "Temperature Option Detected\n"); - - if (initial_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); - - if (initial_status & WDIOF_OVERHEAT) { - printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); - printk(KERN_EMERG PFX "CPU Overheat\n"); - } - - if (initial_status == 0) - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); - - /* 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); - } - - ret = register_reboot_notifier(&pcwd_notifier); - if (ret) { - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - ret); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; - return ret; - } - - if (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); - unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; - return ret; - } - } - - ret = misc_register(&pcwd_miscdev); - if (ret) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - if (supports_temp) - misc_deregister(&temp_miscdev); - unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; - return ret; - } - - printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", - heartbeat, nowayout); - - return 0; -} - -static void __devexit pcwatchdog_exit(void) -{ - /* Disable the board */ - if (!nowayout) - pcwd_stop(); - - /* Deregister */ - misc_deregister(&pcwd_miscdev); - if (supports_temp) - misc_deregister(&temp_miscdev); - unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; -} - -/* - * 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 __init pcwd_checkcard(int base_addr) -{ - 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 (!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; -} - -/* - * 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. - */ -static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; - -static int __init pcwd_init_module(void) -{ - int i, found = 0; - - spin_lock_init(&io_lock); - - for (i = 0; pcwd_ioports[i] != 0; i++) { - if (pcwd_checkcard(pcwd_ioports[i])) { - if (!(pcwatchdog_init(pcwd_ioports[i]))) - found++; - } - } - - if (!found) { - printk (KERN_INFO PFX "No card detected, or port not available\n"); - return -ENODEV; - } - - return 0; -} - -static void __exit pcwd_cleanup_module(void) -{ - if (current_readport) - pcwatchdog_exit(); - return; -} - -module_init(pcwd_init_module); -module_exit(pcwd_cleanup_module); - -MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>"); -MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver"); -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 index 2b13afb09c5..00000000000 --- a/drivers/char/watchdog/pcwd_pci.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Berkshire PCI-PC Watchdog Card Driver - * - * (c) Copyright 2003 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.pcwd.de/ - * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ - */ - -/* - * Includes, defines, variables, module parameters, ... - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/spinlock.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -/* Module and version information */ -#define WATCHDOG_VERSION "1.01" -#define WATCHDOG_DATE "15 Mar 2005" -#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. - */ -#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ -#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ -#define WD_PCI_TTRP 0x04 /* Temperature Trip status */ - -/* 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 - -/* 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 { - 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; - struct pci_dev *pdev; -} pcipcwd_private; - -/* module parameters */ -#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ -static int heartbeat = WATCHDOG_HEARTBEAT; -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, 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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Internal functions - */ - -static int send_command(int cmd, int *msb, int *lsb) -{ - int got_response, count; - - 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) & 0x40; - for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { - mdelay(1); - got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; - } - - 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); - } - spin_unlock(&pcipcwd_private.io_lock); - - return got_response; -} - -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 & 0x10) { - printk(KERN_ERR PFX "Card timer not enabled\n"); - return -1; - } - - 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 & 0x10)) { - printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); - return -1; - } - - return 0; -} - -static int pcipcwd_keepalive(void) -{ - /* Re-trigger watchdog by writing to port 0 */ - outb_p(0x42, pcipcwd_private.io_addr); - 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; - return 0; -} - -static int pcipcwd_get_status(int *status) -{ - int new_status; - - *status=0; - new_status = inb_p(pcipcwd_private.io_addr + 1); - if (new_status & WD_PCI_WTRP) - *status |= WDIOF_CARDRESET; - if (new_status & WD_PCI_TTRP) { - *status |= WDIOF_OVERHEAT; - if (temp_panic) - panic(PFX "Temperature overheat trip!\n"); - } - - return 0; -} - -static int pcipcwd_clear_status(void) -{ - outb_p(0x01, pcipcwd_private.io_addr + 1); - return 0; -} - -static int pcipcwd_get_temperature(int *temperature) -{ - *temperature = 0; - if (!pcipcwd_private.supports_temp) - return -ENODEV; - - /* - * Convert celsius to fahrenheit, since this was - * the decided 'standard' for this return value. - */ - *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; - - 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) { - pcipcwd_stop(); - retval = 0; - } - - if (new_options & WDIOS_ENABLECARD) { - pcipcwd_start(); - 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); - - default: - return -ENOIOCTLCMD; - } -} - -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)) - 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 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 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 inline void check_temperature_support(void) -{ - if (inb_p(pcipcwd_private.io_addr) != 0xF0) - pcipcwd_private.supports_temp = 1; -} - -static int __devinit pcipcwd_card_init(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int ret = -EIO; - int got_fw_rev, fw_rev_major, fw_rev_minor; - char fw_ver_str[20]; - char option_switches; - - 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 */ - check_temperature_support(); - - /* Get the Firmware Version */ - 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 = inb_p(pcipcwd_private.io_addr + 3); - - 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"); - - /* 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); -} - -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 index 092e9b13375..00000000000 --- a/drivers/char/watchdog/pcwd_usb.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Berkshire USB-PC Watchdog Card Driver - * - * (c) Copyright 2004 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/config.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/notifier.h> -#include <linux/reboot.h> -#include <linux/fs.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#include <asm/uaccess.h> -#include <linux/usb.h> - - -#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.01" -#define DRIVER_DATE "15 Mar 2005" -#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 2 /* 2 sec default heartbeat */ -static int heartbeat = WATCHDOG_HEARTBEAT; -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, 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=CONFIG_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 - -/* Some defines that I like to be somewhere else like include/linux/usb_hid.h */ -#define HID_REQ_SET_REPORT 0x09 -#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) - -/* 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 semaphore sem; /* locks this structure */ -}; -static struct usb_pcwd_private *usb_pcwd_device; - -/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); - -/* 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 = { - .owner = THIS_MODULE, - .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 pt_regs *regs) -{ - 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; -} - -/* - * /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); - - default: - return -ENOIOCTLCMD; - } -} - -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 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 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) -{ - if (usb_pcwd->intr_urb != NULL) - 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 = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); - if (usb_pcwd == NULL) { - printk(KERN_ERR PFX "Out of memory\n"); - goto error; - } - memset (usb_pcwd, 0x00, sizeof (*usb_pcwd)); - - usb_pcwd_device = usb_pcwd; - - init_MUTEX (&usb_pcwd->sem); - 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, SLAB_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")); - - /* 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: - 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() */ - down (&disconnect_sem); - - usb_pcwd = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); - - down (&usb_pcwd->sem); - - /* 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); - - up (&usb_pcwd->sem); - - /* Delete the USB PCWD device */ - usb_pcwd_delete(usb_pcwd); - - cards_found--; - - up (&disconnect_sem); - - 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/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c deleted file mode 100644 index f85ac898a49..00000000000 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ /dev/null @@ -1,511 +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-2004 BJD Fixed divide-by-2 in timeout code - * - * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA -*/ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/config.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/device.h> -#include <linux/interrupt.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#include <asm/arch/map.h> -#include <asm/hardware/clock.h> - -#undef S3C24XX_VA_WATCHDOG -#define S3C24XX_VA_WATCHDOG (0) - -#include <asm/arch/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=CONFIG_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 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) { - printk(KERN_ERR PFX "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); - } else { - allow_close = CLOSE_STATE_ALLOW; - } - - /* 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 { - printk(KERN_CRIT PFX "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 -ENOIOCTLCMD; - - 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); - } -} - -/* - * Notifier for system down - */ - -static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if(code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - s3c2410wdt_stop(); - } - return NOTIFY_DONE; -} - -/* kernel interface */ - -static 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, -}; - -static struct notifier_block s3c2410wdt_notifier = { - .notifier_call = s3c2410wdt_notify_sys, -}; - -/* interrupt handler code */ - -static irqreturn_t s3c2410wdt_irq(int irqno, void *param, - struct pt_regs *regs) -{ - printk(KERN_INFO PFX "Watchdog timer expired!\n"); - - s3c2410wdt_keepalive(); - return IRQ_HANDLED; -} -/* device interface */ - -static int s3c2410wdt_probe(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct resource *res; - int started = 0; - int ret; - int size; - - DBG("%s: probe=%p, device=%p\n", __FUNCTION__, pdev, dev); - - /* get the memory region for the watchdog timer */ - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - printk(KERN_INFO PFX "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 PFX "failed to get memory region\n"); - return -ENOENT; - } - - wdt_base = ioremap(res->start, size); - if (wdt_base == 0) { - printk(KERN_INFO PFX "failed to ioremap() region\n"); - return -EINVAL; - } - - DBG("probe: mapped wdt_base=%p\n", wdt_base); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - printk(KERN_INFO PFX "failed to get irq resource\n"); - return -ENOENT; - } - - ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, dev); - if (ret != 0) { - printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); - return ret; - } - - wdt_clock = clk_get(dev, "watchdog"); - if (wdt_clock == NULL) { - printk(KERN_INFO PFX "failed to find watchdog clock source\n"); - return -ENOENT; - } - - clk_use(wdt_clock); - 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) { - printk(KERN_INFO PFX "tmr_margin value out of range, default %d used\n", - CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); - } else { - printk(KERN_INFO PFX "default timer value is out of range, cannot start\n"); - } - } - - ret = register_reboot_notifier(&s3c2410wdt_notifier); - if (ret) { - printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n", - ret); - return ret; - } - - ret = misc_register(&s3c2410wdt_miscdev); - if (ret) { - printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", - WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&s3c2410wdt_notifier); - return ret; - } - - if (tmr_atboot && started == 0) { - printk(KERN_INFO PFX "Starting Watchdog Timer\n"); - s3c2410wdt_start(); - } - - return 0; -} - -static int s3c2410wdt_remove(struct device *dev) -{ - if (wdt_mem != NULL) { - release_resource(wdt_mem); - kfree(wdt_mem); - wdt_mem = NULL; - } - - if (wdt_irq != NULL) { - free_irq(wdt_irq->start, dev); - wdt_irq = NULL; - } - - if (wdt_clock != NULL) { - clk_disable(wdt_clock); - clk_unuse(wdt_clock); - clk_put(wdt_clock); - wdt_clock = NULL; - } - - misc_deregister(&s3c2410wdt_miscdev); - return 0; -} - -static struct device_driver s3c2410wdt_driver = { - .name = "s3c2410-wdt", - .bus = &platform_bus_type, - .probe = s3c2410wdt_probe, - .remove = s3c2410wdt_remove, -}; - - - -static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; - -static int __init watchdog_init(void) -{ - printk(banner); - return driver_register(&s3c2410wdt_driver); -} - -static void __exit watchdog_exit(void) -{ - driver_unregister(&s3c2410wdt_driver); - unregister_reboot_notifier(&s3c2410wdt_notifier); -} - -module_init(watchdog_init); -module_exit(watchdog_exit); - -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -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 index 1b2132617dc..00000000000 --- a/drivers/char/watchdog/sa1100_wdt.c +++ /dev/null @@ -1,219 +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/config.h> -#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 -#define SA1100_CLOSE_MAGIC (0x5afc4453) - -static unsigned long sa1100wdt_users; -static int expect_close; -static int pre_margin; -static int boot_status; -static int nowayout = WATCHDOG_NOWAYOUT; - -/* - * Allow only one person to hold it open - */ -static int sa1100dog_open(struct inode *inode, struct file *file) -{ - nonseekable_open(inode, 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 0; -} - -/* - * Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT - * Oddly, the watchdog can only be enabled, but we can turn off - * the interrupt, which appears to prevent the watchdog timing out. - */ -static int sa1100dog_release(struct inode *inode, struct file *file) -{ - OSMR3 = OSCR + pre_margin; - - if (expect_close == SA1100_CLOSE_MAGIC) { - OIER &= ~OIER_E3; - } else { - printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); - } - - clear_bit(1, &sa1100wdt_users); - expect_close = 0; - - return 0; -} - -static ssize_t sa1100dog_write(struct file *file, const char *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 = SA1100_CLOSE_MAGIC; - } - } - /* Refresh OSMR3 timer. */ - OSMR3 = OSCR + pre_margin; - } - - return len; -} - -static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | - WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "SA1100 Watchdog", -}; - -static int sa1100dog_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ret = -ENOIOCTLCMD; - 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 > 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, (int *)arg); - break; - - case WDIOC_KEEPALIVE: - OSMR3 = OSCR + pre_margin; - ret = 0; - break; - } - return ret; -} - -static 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 = "SA1100/PXA2xx 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_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/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c deleted file mode 100644 index ed0bd55fbfc..00000000000 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ /dev/null @@ -1,408 +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=CONFIG_WATCHDOG_NOWAYOUT)"); - -static void wdt_timer_ping(unsigned long); -static struct timer_list timer; -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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - } 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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - 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) -{ - nonseekable_open(inode, 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 0; -} - -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 -ENOIOCTLCMD; - 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 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; - } - } - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 0; - - 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/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c deleted file mode 100644 index 515ce757204..00000000000 --- a/drivers/char/watchdog/sc1200wdt.c +++ /dev/null @@ -1,462 +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/config.h> -#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 <linux/pci.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=CONFIG_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, ®); - /* 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) -{ - nonseekable_open(inode, 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 0; -} - - -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 -ENOIOCTLCMD; /* Keep Pavel Machek amused ;) */ - - 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 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 &= 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(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_clean; - } - -#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_clean; - } - - 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); - - 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 index 72501be79b0..00000000000 --- a/drivers/char/watchdog/sc520_wdt.c +++ /dev/null @@ -1,442 +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 <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=CONFIG_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 struct timer_list timer; -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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - } 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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - /* 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) -{ - nonseekable_open(inode, 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 0; -} - -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 -ENOIOCTLCMD; - 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 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); - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 0; - - /* 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 index c4568569f3a..00000000000 --- a/drivers/char/watchdog/scx200_wdt.c +++ /dev/null @@ -1,270 +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/config.h> -#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/pci.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 -ENOIOCTLCMD; - 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 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 = NAME, - .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 index 1f4cab55b2e..00000000000 --- a/drivers/char/watchdog/shwdt.c +++ /dev/null @@ -1,448 +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/config.h> -#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 <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 unsigned long shwdt_is_open; -static struct watchdog_info sh_wdt_info; -static char shwdt_expect_close; -static struct timer_list timer; -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 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 ((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_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 -ENOIOCTLCMD; - } - - 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 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, -}; - -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); - } - - if (sh_wdt_set_heartbeat(heartbeat)) - { - heartbeat = WATCHDOG_HEARTBEAT; - printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n", - heartbeat); - } - - init_timer(&timer); - timer.function = sh_wdt_ping; - timer.data = 0; - - rc = register_reboot_notifier(&sh_wdt_notifier); - if (rc) { - printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc); - return rc; - } - - rc = misc_register(&sh_wdt_miscdev); - if (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). Defaults to 0x7."); - -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=CONFIG_WATCHDOG_NOWAYOUT)"); - -module_init(sh_wdt_init); -module_exit(sh_wdt_exit); - diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c deleted file mode 100644 index 4d7ed931f5c..00000000000 --- a/drivers/char/watchdog/softdog.c +++ /dev/null @@ -1,304 +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/config.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 <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=CONFIG_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 timer_alive; -static char expect_close; - - -/* - * If the timer expires.. - */ - -static void watchdog_fire(unsigned long data) -{ - 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, &timer_alive)) - return -EBUSY; - if (nowayout) - __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(); - } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); - softdog_keepalive(); - } - clear_bit(0, &timer_alive); - 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 -ENOIOCTLCMD; - 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 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 index 465e0fd0423..00000000000 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * w83627hf WDT driver - * - * (c) Copyright 2003 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 <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#define WATCHDOG_NAME "w83627hf WDT" -#define PFX WATCHDOG_NAME ": " -#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ - -static unsigned long wdt_is_open; -static char expect_close; - -/* 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 WDT io port (default 0x2E)"); - -static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_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) -{ - outb_p(0x87, WDT_EFER); /* Enter extended function mode */ - outb_p(0x87, WDT_EFER); /* Again according to manual */ - - 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(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 */ - - w83627hf_unselect_wd_register(); -} - -static void -wdt_ctrl(int timeout) -{ - 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(); -} - -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 > 63)) - 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 -ENOIOCTLCMD; - } - 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 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; - - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); - - if (wdt_set_heartbeat(timeout)) { - wdt_set_heartbeat(WATCHDOG_TIMEOUT); - printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", - 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("w38627hf 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 index 52a8bd0a598..00000000000 --- a/drivers/char/watchdog/w83877f_wdt.c +++ /dev/null @@ -1,421 +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=CONFIG_WATCHDOG_NOWAYOUT)"); - -static void wdt_timer_ping(unsigned long); -static struct timer_list timer; -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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - 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 */ - timer.expires = jiffies + WDT_INTERVAL; - add_timer(&timer); - - 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 -ENOIOCTLCMD; - 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 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; - } - - init_timer(&timer); - timer.function = wdt_timer_ping; - timer.data = 0; - - 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/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c deleted file mode 100644 index 7cf6c9bbf48..00000000000 --- a/drivers/char/watchdog/wafer5823wdt.c +++ /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=CONFIG_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 -ENOIOCTLCMD; - } - 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 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 index 84e60eb7433..00000000000 --- a/drivers/char/watchdog/wd501p.h +++ /dev/null @@ -1,52 +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. - * - */ - -#include <linux/config.h> - -#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 index 619e2ffca33..00000000000 --- a/drivers/char/watchdog/wdrtas.c +++ /dev/null @@ -1,696 +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/config.h> -#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 *)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 -ENOIOCTLCMD; - } -} - -/** - * 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 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 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 index ec7e401228e..00000000000 --- a/drivers/char/watchdog/wdt.c +++ /dev/null @@ -1,642 +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/config.h> -#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=CONFIG_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. - * @regs: Unused. - * - * 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, struct pt_regs *regs) -{ - /* - * 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 -ENOIOCTLCMD; - 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 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 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, SA_INTERRUPT, "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 index 52825a1f177..00000000000 --- a/drivers/char/watchdog/wdt285.c +++ /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, struct pt_regs *regs) -{ - 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 = -ENOIOCTLCMD; - - 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 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 index 44d49dfacbb..00000000000 --- a/drivers/char/watchdog/wdt977.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Wdt977 0.03: 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. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/init.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 PFX "Wdt977: " -#define WATCHDOG_MINOR 130 - -#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; - -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=CONFIG_WATCHDOG_NOWAYOUT)"); - -/* - * Start the watchdog - */ - -static int wdt977_start(void) -{ - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* 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(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ - outb(0xF4,0x370); - outb(0x00,0x371); - - /* 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(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); - } - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - printk(KERN_INFO PFX "activated.\n"); - - return 0; -} - -/* - * Stop the watchdog - */ - -static int wdt977_stop(void) -{ - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* 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(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(0xFF,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); - outb(0xF4,0x370); - outb(0x00,0x371); - outb(0xF2,0x370); - outb(0x00,0x371); - - /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ - outb(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - 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) -{ - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and kicks watchdog reg F2 */ - /* F2 has the timeout in minutes */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - 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; - - *status=0; - - /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); - - /* select device Aux2 (device=8) and read watchdog reg F4 */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF4,0x370); - new_status = inb(0x371); - - /* lock the SuperIO chip */ - outb(0xAA,0x370); - - 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 { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); - wdt977_keepalive(); - } - 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; - } - } - - 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 = "Winbond 83977", -}; - -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 -ENOIOCTLCMD; - - 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 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 nwwatchdog_init(void) -{ - int retval; - if (!machine_is_netwinder()) - return -ENODEV; - - /* 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); - } - - retval = register_reboot_notifier(&wdt977_notifier); - if (retval) { - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - retval); - return retval; - } - - retval = misc_register(&wdt977_miscdev); - if (retval) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, retval); - unregister_reboot_notifier(&wdt977_notifier); - return retval; - } - - printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode = %i)\n", - timeout, nowayout, testmode); - - return 0; -} - -static void __exit nwwatchdog_exit(void) -{ - misc_deregister(&wdt977_miscdev); - unregister_reboot_notifier(&wdt977_notifier); -} - -module_init(nwwatchdog_init); -module_exit(nwwatchdog_exit); - -MODULE_AUTHOR("Woody Suwalski <woody@netwinder.org>"); -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 index 4b3311993d4..00000000000 --- a/drivers/char/watchdog/wdt_pci.c +++ /dev/null @@ -1,758 +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/config.h> -#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=CONFIG_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. - * @regs: Unused. - * - * 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, struct pt_regs *regs) -{ - /* - * 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 -ENOIOCTLCMD; - 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 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 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, SA_INTERRUPT | SA_SHIRQ, - "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); |
