diff options
Diffstat (limited to 'drivers/char/watchdog')
24 files changed, 484 insertions, 228 deletions
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 9789e27b361a..8a296fdcaa73 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -55,6 +55,8 @@ config SOFT_WATCHDOG To compile this driver as a module, choose M here: the module will be called softdog. +# ALPHA Architecture + # ARM Architecture config AT91RM9200_WATCHDOG @@ -187,6 +189,64 @@ config PNX4008_WATCHDOG Say N if you are unsure. +config IOP_WATCHDOG + tristate "IOP Watchdog" + depends on PLAT_IOP + select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X) + help + Say Y here if to include support for the watchdog timer + in the Intel IOP3XX & IOP13XX I/O Processors. This driver can + be built as a module by choosing M. The module will + be called iop_wdt. + + Note: The IOP13XX watchdog does an Internal Bus Reset which will + affect both cores and the peripherals of the IOP. The ATU-X + and/or ATUe configuration registers will remain intact, but if + operating as an Root Complex and/or Central Resource, the PCI-X + and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER. + +config DAVINCI_WATCHDOG + tristate "DaVinci watchdog" + depends on ARCH_DAVINCI + help + Say Y here if to include support for the watchdog timer + in the DaVinci DM644x/DM646x processors. + To compile this driver as a module, choose M here: the + module will be called davinci_wdt. + + NOTE: once enabled, this timer cannot be disabled. + Say N if you are unsure. + +# ARM26 Architecture + +# AVR32 Architecture + +config AT32AP700X_WDT + tristate "AT32AP700x watchdog" + depends on CPU_AT32AP7000 + help + Watchdog timer embedded into AT32AP700x devices. This will reboot + your system when the timeout is reached. + +# BLACKFIN Architecture + +config BFIN_WDT + tristate "Blackfin On-Chip Watchdog Timer" + depends on BLACKFIN + ---help--- + If you say yes here you will get support for the Blackfin On-Chip + Watchdog Timer. If you have one of these processors and wish to + have watchdog support enabled, say Y, otherwise say N. + + To compile this driver as a module, choose M here: the + module will be called bfin_wdt. + +# CRIS Architecture + +# FRV Architecture + +# H8300 Architecture + config MXC_WATCHDOG tristate "MXC watchdog" depends on WATCHDOG && WATCHDOG_NOWAYOUT @@ -528,37 +588,11 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. -# PowerPC Architecture - -config 8xx_WDT - tristate "MPC8xx Watchdog Timer" - depends on 8xx - -config 83xx_WDT - tristate "MPC83xx Watchdog Timer" - depends on PPC_83xx - -config MV64X60_WDT - tristate "MV64X60 (Marvell Discovery) Watchdog Timer" - depends on MV64X60 +# M32R Architecture -config BOOKE_WDT - bool "PowerPC Book-E Watchdog Timer" - depends on BOOKE || 4xx - ---help--- - Please see Documentation/watchdog/watchdog-api.txt for - more information. +# M68K Architecture -# PPC64 Architecture - -config WATCHDOG_RTAS - tristate "RTAS watchdog" - depends on PPC_RTAS - help - This driver adds watchdog support for the RTAS watchdog. - - To compile this driver as a module, choose M here. The module - will be called wdrtas. +# M68KNOMMU Architecture # MIPS Architecture @@ -588,6 +622,44 @@ config WDT_RM9K_GPI To compile this driver as a module, choose M here: the module will be called rm9k_wdt. +# PARISC Architecture + +# POWERPC Architecture + +config MPC5200_WDT + tristate "MPC5200 Watchdog Timer" + depends on PPC_MPC52xx + +config 8xx_WDT + tristate "MPC8xx Watchdog Timer" + depends on 8xx + +config 83xx_WDT + tristate "MPC83xx Watchdog Timer" + depends on PPC_83xx + +config MV64X60_WDT + tristate "MV64X60 (Marvell Discovery) Watchdog Timer" + depends on MV64X60 + +config BOOKE_WDT + bool "PowerPC Book-E Watchdog Timer" + depends on BOOKE || 4xx + ---help--- + Please see Documentation/watchdog/watchdog-api.txt for + more information. + +# PPC64 Architecture + +config WATCHDOG_RTAS + tristate "RTAS watchdog" + depends on PPC_RTAS + help + This driver adds watchdog support for the RTAS watchdog. + + To compile this driver as a module, choose M here. The module + will be called wdrtas. + # S390 Architecture config ZVM_WATCHDOG @@ -602,11 +674,11 @@ config ZVM_WATCHDOG To compile this driver as a module, choose M here. The module will be called vmwatchdog. -# SUPERH Architecture +# SUPERH (sh + sh64) Architecture config SH_WDT tristate "SuperH Watchdog" - depends on SUPERH + depends on SUPERH && (CPU_SH3 || CPU_SH4) help This driver adds watchdog support for the integrated watchdog in the SuperH processors. If you have one of these processors and wish @@ -629,6 +701,8 @@ config SH_WDT_MMAP If you say Y here, user applications will be able to mmap the WDT/CPG registers. +# SPARC Architecture + # SPARC64 Architecture config WATCHDOG_CP1XXX @@ -653,6 +727,10 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. +# V850 Architecture + +# XTENSA Architecture + # # ISA-based Watchdog Cards # diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 1fc37393b77e..c95dc01d32f7 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -22,6 +22,8 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o # USB-based Watchdog Cards obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o +# ALPHA Architecture + # ARM Architecture obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o @@ -36,6 +38,22 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o obj-$(CONFIG_MXC_WATCHDOG) += mxc_wdt.o obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o +obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o +obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o + +# ARM26 Architecture + +# AVR32 Architecture +obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o + +# BLACKFIN Architecture +obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o + +# CRIS Architecture + +# FRV Architecture + +# H8300 Architecture # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o @@ -63,8 +81,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o -# PowerPC Architecture +# M32R Architecture + +# M68K Architecture + +# M68KNOMMU Architecture + +# MIPS Architecture +obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o +obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o + +# PARISC Architecture + +# POWERPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o +obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o @@ -72,17 +104,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o # PPC64 Architecture obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o -# MIPS Architecture -obj-$(CONFIG_INDYDOG) += indydog.o -obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o -obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o - # S390 Architecture -# SUPERH Architecture +# SUPERH (sh + sh64) Architecture obj-$(CONFIG_SH_WDT) += shwdt.o +# SPARC Architecture + # SPARC64 Architecture +# V850 Architecture + +# XTENSA Architecture + # Architecture Independant obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c index e3f6a7d0c83d..c404fc69e7e6 100644 --- a/drivers/char/watchdog/alim1535_wdt.c +++ b/drivers/char/watchdog/alim1535_wdt.c @@ -312,6 +312,7 @@ static int ali_notify_sys(struct notifier_block *this, unsigned long code, void */ static struct pci_device_id ali_pci_tbl[] = { + { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, }; @@ -329,9 +330,11 @@ static int __init ali_find_watchdog(void) struct pci_dev *pdev; u32 wdog; - /* Check for a 1535 series bridge */ + /* Check for a 1533/1535 series bridge */ pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL); - if(pdev == NULL) + if (pdev == NULL) + pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL); + if (pdev == NULL) return -ENODEV; pci_dev_put(pdev); diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 0f5c77ddd39d..d362f5bf658a 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c @@ -144,7 +144,7 @@ static int booke_wdt_open (struct inode *inode, struct file *file) booke_wdt_period); } - return 0; + return nonseekable_open(inode, file); } static const struct file_operations booke_wdt_fops = { diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index d0d45a8b09f0..5941ca601a3a 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c @@ -162,6 +162,10 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm if ( copy_to_user(argp, &value, sizeof(int)) ) return -EFAULT; break; + case WDIOC_GETBOOTSTATUS: + if ( copy_to_user(argp, &value, sizeof(int)) ) + return -EFAULT; + break; case WDIOC_GETSUPPORT: if ( copy_to_user(argp, &ident, sizeof(ident)) ) return -EFAULT; diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c index 01cf123b1616..0e4787a0bb87 100644 --- a/drivers/char/watchdog/ep93xx_wdt.c +++ b/drivers/char/watchdog/ep93xx_wdt.c @@ -107,10 +107,6 @@ static ssize_t ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ - if (*ppos != file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c index b070324e27a6..b14e9d1f164d 100644 --- a/drivers/char/watchdog/eurotechwdt.c +++ b/drivers/char/watchdog/eurotechwdt.c @@ -1,5 +1,5 @@ /* - * Eurotech CPU-1220/1410 on board WDT driver + * Eurotech CPU-1220/1410/1420 on board WDT driver * * (c) Copyright 2001 Ascensit <support@ascensit.com> * (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com> @@ -25,6 +25,9 @@ /* Changelog: * + * 2001 - Rodolfo Giometti + * Initial release + * * 2002/04/25 - Rob Radez * clean up #includes * clean up locking @@ -33,13 +36,15 @@ * 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. */ +/* + * The eurotech CPU-1220/1410/1420's watchdog is a part + * of the on-board SUPER I/O device SMSC FDC 37B782. + */ + #include <linux/interrupt.h> #include <linux/module.h> #include <linux/moduleparam.h> diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index eac4f9b9f007..cd5a565bc3a0 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -39,7 +39,12 @@ * 82801HR (ICH8R) : document number 313056-002, 313057-004, * 82801HH (ICH8DH) : document number 313056-002, 313057-004, * 82801HO (ICH8DO) : document number 313056-002, 313057-004, - * 6300ESB (6300ESB) : document number 300641-003 + * 82801IB (ICH9) : document number 316972-001, 316973-001, + * 82801IR (ICH9R) : document number 316972-001, 316973-001, + * 82801IH (ICH9DH) : document number 316972-001, 316973-001, + * 6300ESB (6300ESB) : document number 300641-003, 300884-010, + * 631xESB (631xESB) : document number 313082-001, 313075-005, + * 632xESB (632xESB) : document number 313082-001, 313075-005 */ /* @@ -48,8 +53,8 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" -#define DRV_VERSION "1.01" -#define DRV_RELDATE "21-Jan-2007" +#define DRV_VERSION "1.02" +#define DRV_RELDATE "26-Jul-2007" #define PFX DRV_NAME ": " /* Includes */ @@ -92,6 +97,10 @@ enum iTCO_chipsets { TCO_ICH8, /* ICH8 & ICH8R */ TCO_ICH8DH, /* ICH8DH */ TCO_ICH8DO, /* ICH8DO */ + TCO_ICH9, /* ICH9 */ + TCO_ICH9R, /* ICH9R */ + TCO_ICH9DH, /* ICH9DH */ + TCO_631XESB, /* 631xESB/632xESB */ }; static struct { @@ -118,6 +127,10 @@ static struct { {"ICH8 or ICH8R", 2}, {"ICH8DH", 2}, {"ICH8DO", 2}, + {"ICH9", 2}, + {"ICH9R", 2}, + {"ICH9DH", 2}, + {"631xESB/632xESB", 2}, {NULL,0} }; @@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, + { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 }, + { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index a0d27160c80e..6d35bb112a5f 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index f35e2848aa3e..1adf1d56027d 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -29,11 +29,18 @@ * - 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 + * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * + * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com> + * - make mixcomwd_opened unsigned, + * removed lock_kernel/unlock_kernel from mixcomwd_release, + * modified ioctl a bit to conform to API * */ -#define VERSION "0.5" +#define VERSION "0.6" +#define WATCHDOG_NAME "mixcomwd" +#define PFX WATCHDOG_NAME ": " #include <linux/module.h> #include <linux/moduleparam.h> @@ -49,12 +56,46 @@ #include <asm/uaccess.h> #include <asm/io.h> -static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 }; - -#define MIXCOM_WATCHDOG_OFFSET 0xc10 +/* + * We have two types of cards that can be probed: + * 1) The Mixcom cards: these cards can be found at addresses + * 0x180, 0x280, 0x380 with an additional offset of 0xc10. + * (Or 0xd90, 0xe90, 0xf90). + * 2) The FlashCOM cards: these cards can be set up at + * 0x300 -> 0x378, in 0x8 jumps with an offset of 0x04. + * (Or 0x304 -> 0x37c in 0x8 jumps). + * Each card has it's own ID. + */ #define MIXCOM_ID 0x11 -#define FLASHCOM_WATCHDOG_OFFSET 0x4 #define FLASHCOM_ID 0x18 +static struct { + int ioport; + int id; +} mixcomwd_io_info[] __devinitdata = { + /* The Mixcom cards */ + {0x0d90, MIXCOM_ID}, + {0x0e90, MIXCOM_ID}, + {0x0f90, MIXCOM_ID}, + /* The FlashCOM cards */ + {0x0304, FLASHCOM_ID}, + {0x030c, FLASHCOM_ID}, + {0x0314, FLASHCOM_ID}, + {0x031c, FLASHCOM_ID}, + {0x0324, FLASHCOM_ID}, + {0x032c, FLASHCOM_ID}, + {0x0334, FLASHCOM_ID}, + {0x033c, FLASHCOM_ID}, + {0x0344, FLASHCOM_ID}, + {0x034c, FLASHCOM_ID}, + {0x0354, FLASHCOM_ID}, + {0x035c, FLASHCOM_ID}, + {0x0364, FLASHCOM_ID}, + {0x036c, FLASHCOM_ID}, + {0x0374, FLASHCOM_ID}, + {0x037c, FLASHCOM_ID}, + /* The end of the list */ + {0x0000, 0}, +}; static void mixcomwd_timerfun(unsigned long d); @@ -113,13 +154,13 @@ 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"); + printk(KERN_ERR PFX "release called while internal timer alive"); return -EBUSY; } mixcomwd_timer_alive=1; mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); } else { - printk(KERN_CRIT "mixcomwd: WDT device closed unexpectedly. WDT will not stop!\n"); + printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); } clear_bit(0,&mixcomwd_opened); @@ -174,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, return -EFAULT; } break; + case WDIOC_GETBOOTSTATUS: + if (copy_to_user(p, &status, sizeof(int))) { + return -EFAULT; + } + break; case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) { return -EFAULT; @@ -188,8 +234,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, return 0; } -static const struct file_operations mixcomwd_fops= -{ +static const struct file_operations mixcomwd_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = mixcomwd_write, @@ -198,46 +243,30 @@ static const struct file_operations mixcomwd_fops= .release = mixcomwd_release, }; -static struct miscdevice mixcomwd_miscdev= -{ +static struct miscdevice mixcomwd_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &mixcomwd_fops, }; -static int __init mixcomwd_checkcard(int port) +static int __init checkcard(int port, int card_id) { 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) { + if (card_id==MIXCOM_ID) + id &= 0x3f; + + if (id!=card_id) { release_region(port, 1); return 0; } - return port; - } + return 1; +} static int __init mixcomwd_init(void) { @@ -245,50 +274,50 @@ static int __init mixcomwd_init(void) 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) { + for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) { + if (checkcard(mixcomwd_io_info[i].ioport, + mixcomwd_io_info[i].id)) { found = 1; + watchdog_port = mixcomwd_io_info[i].ioport; } } if (!found) { - printk("mixcomwd: No card detected, or port not available.\n"); + printk(KERN_ERR PFX "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_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto error_misc_register_watchdog; } - printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port); + printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n", + VERSION, watchdog_port); return 0; + +error_misc_register_watchdog: + release_region(watchdog_port, 1); + watchdog_port = 0x0000; + return ret; } static void __exit mixcomwd_exit(void) { if (!nowayout) { if(mixcomwd_timer_alive) { - printk(KERN_WARNING "mixcomwd: I quit now, hardware will" + printk(KERN_WARNING PFX "I quit now, hardware will" " probably reboot!\n"); del_timer_sync(&mixcomwd_timer); mixcomwd_timer_alive=0; } } - release_region(watchdog_port,1); misc_deregister(&mixcomwd_miscdev); + release_region(watchdog_port,1); } module_init(mixcomwd_init); @@ -296,5 +325,6 @@ module_exit(mixcomwd_exit); MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>"); MODULE_DESCRIPTION("MixCom Watchdog driver"); +MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c index 18ca752e2f90..a0bf95fb9763 100644 --- a/drivers/char/watchdog/mpc83xx_wdt.c +++ b/drivers/char/watchdog/mpc83xx_wdt.c @@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); case WDIOC_KEEPALIVE: mpc83xx_wdt_keepalive(); return 0; diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c index 8aaed10dd499..85b5734403a5 100644 --- a/drivers/char/watchdog/mpc8xx_wdt.c +++ b/drivers/char/watchdog/mpc8xx_wdt.c @@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file) m8xx_wdt_reset(); mpc8xx_wdt_handler_disable(); - return 0; + return nonseekable_open(inode, file); } static int mpc8xx_wdt_release(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c index e88947f8fe53..0d2b27735419 100644 --- a/drivers/char/watchdog/mpcore_wdt.c +++ b/drivers/char/watchdog/mpcore_wdt.c @@ -328,12 +328,11 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) goto err_out; } - wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL); + wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL); if (!wdt) { ret = -ENOMEM; goto err_out; } - memset(wdt, 0, sizeof(struct mpcore_wdt)); wdt->dev = &dev->dev; wdt->irq = platform_get_irq(dev, 0); diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c index 419ab445c944..dcfd401a7ad7 100644 --- a/drivers/char/watchdog/mtx-1_wdt.c +++ b/drivers/char/watchdog/mtx-1_wdt.c @@ -143,6 +143,7 @@ static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int c mtx1_wdt_reset(); break; case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: if ( copy_to_user(argp, &value, sizeof(int)) ) return -EFAULT; break; diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index b887cdb01334..0365c317f7e1 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c @@ -23,61 +23,101 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> -#include <asm/mv64x60.h> +#include <linux/mv643xx.h> #include <asm/uaccess.h> #include <asm/io.h> -/* MV64x60 WDC (config) register access definitions */ -#define MV64x60_WDC_CTL1_MASK (3 << 24) -#define MV64x60_WDC_CTL1(val) ((val & 3) << 24) -#define MV64x60_WDC_CTL2_MASK (3 << 26) -#define MV64x60_WDC_CTL2(val) ((val & 3) << 26) +#define MV64x60_WDT_WDC_OFFSET 0 + +/* + * The watchdog configuration register contains a pair of 2-bit fields, + * 1. a reload field, bits 27-26, which triggers a reload of + * the countdown register, and + * 2. an enable field, bits 25-24, which toggles between + * enabling and disabling the watchdog timer. + * Bit 31 is a read-only field which indicates whether the + * watchdog timer is currently enabled. + * + * The low 24 bits contain the timer reload value. + */ +#define MV64x60_WDC_ENABLE_SHIFT 24 +#define MV64x60_WDC_SERVICE_SHIFT 26 +#define MV64x60_WDC_ENABLED_SHIFT 31 + +#define MV64x60_WDC_ENABLED_TRUE 1 +#define MV64x60_WDC_ENABLED_FALSE 0 /* Flags bits */ #define MV64x60_WDOG_FLAG_OPENED 0 -#define MV64x60_WDOG_FLAG_ENABLED 1 static unsigned long wdt_flags; static int wdt_status; -static void __iomem *mv64x60_regs; +static void __iomem *mv64x60_wdt_regs; static int mv64x60_wdt_timeout; +static int mv64x60_wdt_count; +static unsigned int bus_clk; +static char expect_close; +static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static void mv64x60_wdt_reg_write(u32 val) +static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) { - /* Allow write only to CTL1 / CTL2 fields, retaining values in - * other fields. - */ - u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); - data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); - data |= val; - writel(data, mv64x60_regs + MV64x60_WDT_WDC); + u32 data; + u32 enabled; + int ret = 0; + + spin_lock(&mv64x60_wdt_spinlock); + data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1; + + /* only toggle the requested field if enabled state matches predicate */ + if ((enabled ^ enabled_predicate) == 0) { + /* We write a 1, then a 2 -- to the appropriate field */ + data = (1 << field_shift) | mv64x60_wdt_count; + writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + + data = (2 << field_shift) | mv64x60_wdt_count; + writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + ret = 1; + } + spin_unlock(&mv64x60_wdt_spinlock); + + return ret; } static void mv64x60_wdt_service(void) { - /* Write 01 followed by 10 to CTL2 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); + mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, + MV64x60_WDC_SERVICE_SHIFT); +} + +static void mv64x60_wdt_handler_enable(void) +{ + if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE, + MV64x60_WDC_ENABLE_SHIFT)) { + mv64x60_wdt_service(); + printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); + } } static void mv64x60_wdt_handler_disable(void) { - if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { - /* Write 01 followed by 10 to CTL1 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); + if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, + MV64x60_WDC_ENABLE_SHIFT)) printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); - } } -static void mv64x60_wdt_handler_enable(void) +static void mv64x60_wdt_set_timeout(unsigned int timeout) { - if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { - /* Write 01 followed by 10 to CTL1 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); - printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); - } + /* maximum bus cycle count is 0xFFFFFFFF */ + if (timeout > 0xFFFFFFFF / bus_clk) + timeout = 0xFFFFFFFF / bus_clk; + + mv64x60_wdt_count = timeout * bus_clk >> 8; + mv64x60_wdt_timeout = timeout; } static int mv64x60_wdt_open(struct inode *inode, struct file *file) @@ -85,21 +125,24 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) return -EBUSY; - mv64x60_wdt_service(); - mv64x60_wdt_handler_enable(); + if (nowayout) + __module_get(THIS_MODULE); - nonseekable_open(inode, file); + mv64x60_wdt_handler_enable(); - return 0; + return nonseekable_open(inode, file); } static int mv64x60_wdt_release(struct inode *inode, struct file *file) { - mv64x60_wdt_service(); - -#if !defined(CONFIG_WATCHDOG_NOWAYOUT) - mv64x60_wdt_handler_disable(); -#endif + if (expect_close == 42) + mv64x60_wdt_handler_disable(); + else { + printk(KERN_CRIT + "mv64x60_wdt: unexpected close, not stopping timer!\n"); + mv64x60_wdt_service(); + } + expect_close = 0; clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); @@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { - if (len) + if (len) { + if (!nowayout) { + size_t i; + + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } mv64x60_wdt_service(); + } return len; } @@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int timeout; + int options; void __user *argp = (void __user *)arg; static struct watchdog_info info = { - .options = WDIOF_KEEPALIVEPING, + .options = WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, .firmware_version = 0, .identity = "MV64x60 watchdog", }; @@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, return -EOPNOTSUPP; case WDIOC_SETOPTIONS: - return -EOPNOTSUPP; + if (get_user(options, (int __user *)argp)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) + mv64x60_wdt_handler_disable(); + + if (options & WDIOS_ENABLECARD) + mv64x60_wdt_handler_enable(); + break; case WDIOC_KEEPALIVE: mv64x60_wdt_service(); @@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, break; case WDIOC_SETTIMEOUT: - return -EOPNOTSUPP; + if (get_user(timeout, (int __user *)argp)) + return -EFAULT; + mv64x60_wdt_set_timeout(timeout); + /* Fall through */ case WDIOC_GETTIMEOUT: - timeout = mv64x60_wdt_timeout * HZ; - if (put_user(timeout, (int __user *)argp)) + if (put_user(mv64x60_wdt_timeout, (int __user *)argp)) return -EFAULT; break; @@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = { static int __devinit mv64x60_wdt_probe(struct platform_device *dev) { struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data; - int bus_clk = 133; + struct resource *r; + int timeout = 10; - mv64x60_wdt_timeout = 10; + bus_clk = 133; /* in MHz */ if (pdata) { - mv64x60_wdt_timeout = pdata->timeout; + timeout = pdata->timeout; bus_clk = pdata->bus_clk; } - mv64x60_regs = mv64x60_get_bridge_vbase(); + /* Since bus_clk is truncated MHz, actual frequency could be + * up to 1MHz higher. Round up, since it's better to time out + * too late than too soon. + */ + bus_clk++; + bus_clk *= 1000000; /* convert to Hz */ + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; - writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, - mv64x60_regs + MV64x60_WDT_WDC); + mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1); + if (mv64x60_wdt_regs == NULL) + return -ENOMEM; + + mv64x60_wdt_set_timeout(timeout); + + mv64x60_wdt_handler_disable(); /* in case timer was already running */ return misc_register(&mv64x60_wdt_miscdev); } @@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev) { misc_deregister(&mv64x60_wdt_miscdev); - mv64x60_wdt_service(); mv64x60_wdt_handler_disable(); + iounmap(mv64x60_wdt_regs); + return 0; } @@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = { }, }; -static struct platform_device *mv64x60_wdt_dev; - static int __init mv64x60_wdt_init(void) { - int ret; - printk(KERN_INFO "MV64x60 watchdog driver\n"); - mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1); - if (!mv64x60_wdt_dev) { - ret = -ENOMEM; - goto out; - } - - ret = platform_device_add(mv64x60_wdt_dev); - if (ret) { - platform_device_put(mv64x60_wdt_dev); - goto out; - } - - ret = platform_driver_register(&mv64x60_wdt_driver); - if (ret) { - platform_device_unregister(mv64x60_wdt_dev); - goto out; - } - - out: - return ret; + return platform_driver_register(&mv64x60_wdt_driver); } static void __exit mv64x60_wdt_exit(void) { platform_driver_unregister(&mv64x60_wdt_driver); - platform_device_unregister(mv64x60_wdt_dev); } module_init(mv64x60_wdt_init); diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index b36fa8de2131..719b066f73c4 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c @@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_set_timeout(); omap_wdt_enable(); - return 0; + return nonseekable_open(inode, file); } static int omap_wdt_release(struct inode *inode, struct file *file) @@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { default: - return -ENOIOCTLCMD; + return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)); diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 1e7a6719d5ba..0f3fd6c9c354 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c @@ -626,12 +626,11 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi 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); + usb_pcwd = kzalloc (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; diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c index 5991add702b0..22f8873dd092 100644 --- a/drivers/char/watchdog/pnx4008_wdt.c +++ b/drivers/char/watchdog/pnx4008_wdt.c @@ -148,10 +148,6 @@ static ssize_t pnx4008_wdt_write(struct file *file, const char *data, size_t len, loff_t * ppos) { - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - if (len) { if (!nowayout) { size_t i; diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 20fa29ca7404..5d1c15f83d23 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -52,10 +52,10 @@ #include <asm/arch/map.h> -#undef S3C24XX_VA_WATCHDOG -#define S3C24XX_VA_WATCHDOG (0) +#undef S3C_VA_WATCHDOG +#define S3C_VA_WATCHDOG (0) -#include <asm/arch/regs-watchdog.h> +#include <asm/plat-s3c/regs-watchdog.h> #define PFX "s3c2410-wdt: " @@ -92,6 +92,7 @@ typedef enum close_state { static DECLARE_MUTEX(open_lock); +static struct device *wdt_dev; /* platform device attached to */ static struct resource *wdt_mem; static struct resource *wdt_irq; static struct clk *wdt_clock; @@ -180,7 +181,7 @@ static int s3c2410wdt_set_heartbeat(int timeout) } if ((count / divisor) >= 0x10000) { - printk(KERN_ERR PFX "timeout %d too big\n", timeout); + dev_err(wdt_dev, "timeout %d too big\n", timeout); return -EINVAL; } } @@ -233,7 +234,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file) if (allow_close == CLOSE_STATE_ALLOW) { s3c2410wdt_stop(); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n"); s3c2410wdt_keepalive(); } @@ -338,7 +339,7 @@ static struct miscdevice s3c2410wdt_miscdev = { static irqreturn_t s3c2410wdt_irq(int irqno, void *param) { - printk(KERN_INFO PFX "Watchdog timer expired!\n"); + dev_info(wdt_dev, "watchdog timer expired (irq)\n"); s3c2410wdt_keepalive(); return IRQ_HANDLED; @@ -348,31 +349,36 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param) static int s3c2410wdt_probe(struct platform_device *pdev) { struct resource *res; + struct device *dev; + unsigned int wtcon; int started = 0; int ret; int size; DBG("%s: probe=%p\n", __FUNCTION__, pdev); + dev = &pdev->dev; + wdt_dev = &pdev->dev; + /* get the memory region for the watchdog timer */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { - printk(KERN_INFO PFX "failed to get memory region resouce\n"); + dev_err(dev, "no memory resource specified\n"); return -ENOENT; } size = (res->end-res->start)+1; wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { - printk(KERN_INFO PFX "failed to get memory region\n"); + dev_err(dev, "failed to get memory region\n"); ret = -ENOENT; goto err_req; } wdt_base = ioremap(res->start, size); if (wdt_base == 0) { - printk(KERN_INFO PFX "failed to ioremap() region\n"); + dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; goto err_req; } @@ -381,20 +387,20 @@ static int s3c2410wdt_probe(struct platform_device *pdev) wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (wdt_irq == NULL) { - printk(KERN_INFO PFX "failed to get irq resource\n"); + dev_err(dev, "no irq resource specified\n"); ret = -ENOENT; goto err_map; } ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev); if (ret != 0) { - printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); + dev_err(dev, "failed to install irq (%d)\n", ret); goto err_map; } wdt_clock = clk_get(&pdev->dev, "watchdog"); if (IS_ERR(wdt_clock)) { - printk(KERN_INFO PFX "failed to find watchdog clock source\n"); + dev_err(dev, "failed to find watchdog clock source\n"); ret = PTR_ERR(wdt_clock); goto err_irq; } @@ -408,22 +414,22 @@ static int s3c2410wdt_probe(struct platform_device *pdev) 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", + dev_info(dev,"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"); + dev_info(dev, "default timer value is out of range, cannot start\n"); } } ret = misc_register(&s3c2410wdt_miscdev); if (ret) { - printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", + dev_err(dev, "cannot register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); goto err_clk; } if (tmr_atboot && started == 0) { - printk(KERN_INFO PFX "Starting Watchdog Timer\n"); + dev_info(dev, "starting watchdog timer\n"); s3c2410wdt_start(); } else if (!tmr_atboot) { /* if we're not enabling the watchdog, then ensure it is @@ -433,6 +439,15 @@ static int s3c2410wdt_probe(struct platform_device *pdev) s3c2410wdt_stop(); } + /* print out a statement of readiness */ + + wtcon = readl(wdt_base + S3C2410_WTCON); + + dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n", + (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", + (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", + (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); + return 0; err_clk: diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 33c1137f17d6..3475f47aaa45 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -45,7 +45,6 @@ static int boot_status; */ static int sa1100dog_open(struct inode *inode, struct file *file) { - nonseekable_open(inode, file); if (test_and_set_bit(1,&sa1100wdt_users)) return -EBUSY; @@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file) OSSR = OSSR_M3; OWER = OWER_WME; OIER |= OIER_E3; - return 0; + return nonseekable_open(inode, file); } /* diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c index b6282039198c..e4f3cb6090bc 100644 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ b/drivers/char/watchdog/sbc60xxwdt.c @@ -191,8 +191,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { - nonseekable_open(inode, file); - /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; @@ -202,7 +200,7 @@ static int fop_open(struct inode * inode, struct file * file) /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 2f7ba7a514fe..9670d47190d0 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -150,8 +150,6 @@ static inline int sc1200wdt_status(void) static int sc1200wdt_open(struct inode *inode, struct file *file) { - nonseekable_open(inode, file); - /* allow one at a time */ if (down_trylock(&open_sem)) return -EBUSY; @@ -162,7 +160,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file) sc1200wdt_start(); printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout); - return 0; + return nonseekable_open(inode, file); } diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 2676a43895a7..e8594c64d1e6 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -248,8 +248,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { - nonseekable_open(inode, file); - /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; @@ -258,7 +256,7 @@ static int fop_open(struct inode * inode, struct file * file) /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b46e7f47d705..df33b3b5a53c 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c @@ -4,7 +4,7 @@ * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> * added support for W83627THF. * - * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> + * (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com> * * Based on advantechwdt.c which is based on wdt.c. * Original copyright messages: @@ -42,7 +42,7 @@ #include <asm/uaccess.h> #include <asm/system.h> -#define WATCHDOG_NAME "w83627hf/thf WDT" +#define WATCHDOG_NAME "w83627hf/thf/hg WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ @@ -57,7 +57,7 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)"); static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); @@ -78,9 +78,9 @@ w83627hf_select_wd_register(void) outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Again according to manual */ - outb(0x20, WDT_EFER); /* check chip version */ + outb(0x20, WDT_EFER); /* check chip version */ c = inb(WDT_EFDR); - if (c == 0x82) { /* W83627THF */ + if (c == 0x82) { /* W83627THF */ outb_p(0x2b, WDT_EFER); /* select GPIO3 */ c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ outb_p(0x2b, WDT_EFER); @@ -114,11 +114,17 @@ w83627hf_init(void) printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ } + outb_p(0xF5, WDT_EFER); /* Select CRF5 */ t=inb_p(WDT_EFDR); /* read CRF5 */ t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ outb_p(t, WDT_EFDR); /* Write back to CRF5 */ + outb_p(0xF7, WDT_EFER); /* Select CRF7 */ + t=inb_p(WDT_EFDR); /* read CRF7 */ + t&=~0xC0; /* disable keyboard & mouse turning off watchdog */ + outb_p(t, WDT_EFDR); /* Write back to CRF7 */ + w83627hf_unselect_wd_register(); } @@ -126,7 +132,7 @@ static void wdt_ctrl(int timeout) { spin_lock(&io_lock); - + w83627hf_select_wd_register(); outb_p(0xF6, WDT_EFER); /* Select CRF6 */ @@ -154,7 +160,7 @@ wdt_disable(void) static int wdt_set_heartbeat(int t) { - if ((t < 1) || (t > 63)) + if ((t < 1) || (t > 255)) return -EINVAL; timeout = t; @@ -324,11 +330,11 @@ wdt_init(void) spin_lock_init(&io_lock); - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n"); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); - printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", + printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", WATCHDOG_TIMEOUT); } |