aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig48
-rw-r--r--drivers/watchdog/Makefile7
-rw-r--r--drivers/watchdog/alim1535_wdt.c10
-rw-r--r--drivers/watchdog/alim7101_wdt.c2
-rw-r--r--drivers/watchdog/bcm47xx_wdt.c4
-rw-r--r--drivers/watchdog/bfin_wdt.c4
-rw-r--r--drivers/watchdog/booke_wdt.c19
-rw-r--r--drivers/watchdog/cpwd.c47
-rw-r--r--drivers/watchdog/eurotechwdt.c2
-rw-r--r--drivers/watchdog/gef_wdt.c9
-rw-r--r--drivers/watchdog/hpwdt.c6
-rw-r--r--drivers/watchdog/i6300esb.c2
-rw-r--r--drivers/watchdog/iTCO_wdt.c4
-rw-r--r--drivers/watchdog/intel_scu_watchdog.c572
-rw-r--r--drivers/watchdog/intel_scu_watchdog.h66
-rw-r--r--drivers/watchdog/it8712f_wdt.c2
-rw-r--r--drivers/watchdog/it87_wdt.c28
-rw-r--r--drivers/watchdog/jz4740_wdt.c322
-rw-r--r--drivers/watchdog/m54xx_wdt.c (renamed from drivers/watchdog/m548x_wdt.c)50
-rw-r--r--drivers/watchdog/machzwd.c2
-rw-r--r--drivers/watchdog/max63xx_wdt.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c21
-rw-r--r--drivers/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/watchdog/mtx-1_wdt.c14
-rw-r--r--drivers/watchdog/nv_tco.c2
-rw-r--r--drivers/watchdog/omap_wdt.h2
-rw-r--r--drivers/watchdog/pc87413_wdt.c2
-rw-r--r--drivers/watchdog/pcwd_pci.c2
-rw-r--r--drivers/watchdog/pnx4008_wdt.c2
-rw-r--r--drivers/watchdog/riowd.c9
-rw-r--r--drivers/watchdog/s3c2410_wdt.c2
-rw-r--r--drivers/watchdog/sbc8360.c2
-rw-r--r--drivers/watchdog/sbc_fitpc2_wdt.c9
-rw-r--r--drivers/watchdog/sch311x_wdt.c2
-rw-r--r--drivers/watchdog/shwdt.c365
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c4
-rw-r--r--drivers/watchdog/softdog.c2
-rw-r--r--drivers/watchdog/sp5100_tco.c2
-rw-r--r--drivers/watchdog/sp805_wdt.c2
-rw-r--r--drivers/watchdog/ts72xx_wdt.c2
-rw-r--r--drivers/watchdog/w83697ug_wdt.c6
-rw-r--r--drivers/watchdog/wdt.c2
-rw-r--r--drivers/watchdog/wdt977.c2
-rw-r--r--drivers/watchdog/wdt_pci.c6
-rw-r--r--drivers/watchdog/xen_wdt.c359
45 files changed, 1678 insertions, 353 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 2e2400e7322e..b69d71482554 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -533,6 +533,16 @@ config I6300ESB_WDT
533 To compile this driver as a module, choose M here: the 533 To compile this driver as a module, choose M here: the
534 module will be called i6300esb. 534 module will be called i6300esb.
535 535
536config INTEL_SCU_WATCHDOG
537 bool "Intel SCU Watchdog for Mobile Platforms"
538 depends on WATCHDOG
539 depends on INTEL_SCU_IPC
540 ---help---
541 Hardware driver for the watchdog time built into the Intel SCU
542 for Intel Mobile Platforms.
543
544 To compile this driver as a module, choose M here.
545
536config ITCO_WDT 546config ITCO_WDT
537 tristate "Intel TCO Timer/Watchdog" 547 tristate "Intel TCO Timer/Watchdog"
538 depends on (X86 || IA64) && PCI 548 depends on (X86 || IA64) && PCI
@@ -580,7 +590,7 @@ config IT87_WDT
580 depends on X86 && EXPERIMENTAL 590 depends on X86 && EXPERIMENTAL
581 ---help--- 591 ---help---
582 This is the driver for the hardware watchdog on the ITE IT8702, 592 This is the driver for the hardware watchdog on the ITE IT8702,
583 IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips. 593 IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips.
584 This watchdog simply watches your kernel to make sure it doesn't 594 This watchdog simply watches your kernel to make sure it doesn't
585 freeze, and if it does, it reboots your computer after a certain 595 freeze, and if it does, it reboots your computer after a certain
586 amount of time. 596 amount of time.
@@ -589,18 +599,20 @@ config IT87_WDT
589 be called it87_wdt. 599 be called it87_wdt.
590 600
591config HP_WATCHDOG 601config HP_WATCHDOG
592 tristate "HP Proliant iLO2+ Hardware Watchdog Timer" 602 tristate "HP ProLiant iLO2+ Hardware Watchdog Timer"
593 depends on X86 603 depends on X86
604 default m
594 help 605 help
595 A software monitoring watchdog and NMI sourcing driver. This driver 606 A software monitoring watchdog and NMI sourcing driver. This driver
596 will detect lockups and provide a stack trace. This is a driver that 607 will detect lockups and provide a stack trace. This is a driver that
597 will only load on a HP ProLiant system with a minimum of iLO2 support. 608 will only load on an HP ProLiant system with a minimum of iLO2 support.
598 To compile this driver as a module, choose M here: the module will be 609 To compile this driver as a module, choose M here: the module will be
599 called hpwdt. 610 called hpwdt.
600 611
601config HPWDT_NMI_DECODING 612config HPWDT_NMI_DECODING
602 bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" 613 bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
603 depends on HP_WATCHDOG 614 depends on HP_WATCHDOG
615 default y
604 help 616 help
605 When an NMI occurs this feature will make the necessary BIOS calls to 617 When an NMI occurs this feature will make the necessary BIOS calls to
606 log the cause of the NMI. 618 log the cause of the NMI.
@@ -862,12 +874,12 @@ config SBC_EPX_C3_WATCHDOG
862 874
863# M68K Architecture 875# M68K Architecture
864 876
865config M548x_WATCHDOG 877config M54xx_WATCHDOG
866 tristate "MCF548x watchdog support" 878 tristate "MCF54xx watchdog support"
867 depends on M548x 879 depends on M548x
868 help 880 help
869 To compile this driver as a module, choose M here: the 881 To compile this driver as a module, choose M here: the
870 module will be called m548x_wdt. 882 module will be called m54xx_wdt.
871 883
872# MIPS Architecture 884# MIPS Architecture
873 885
@@ -903,6 +915,12 @@ config INDYDOG
903 timer expired and no process has written to /dev/watchdog during 915 timer expired and no process has written to /dev/watchdog during
904 that time. 916 that time.
905 917
918config JZ4740_WDT
919 tristate "Ingenic jz4740 SoC hardware watchdog"
920 depends on MACH_JZ4740
921 help
922 Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
923
906config WDT_MTX1 924config WDT_MTX1
907 tristate "MTX-1 Hardware Watchdog" 925 tristate "MTX-1 Hardware Watchdog"
908 depends on MIPS_MTX1 926 depends on MIPS_MTX1
@@ -1083,14 +1101,6 @@ config SH_WDT
1083 To compile this driver as a module, choose M here: the 1101 To compile this driver as a module, choose M here: the
1084 module will be called shwdt. 1102 module will be called shwdt.
1085 1103
1086config SH_WDT_MMAP
1087 bool "Allow mmap of SH WDT"
1088 default n
1089 depends on SH_WDT
1090 help
1091 If you say Y here, user applications will be able to mmap the
1092 WDT/CPG registers.
1093
1094# SPARC Architecture 1104# SPARC Architecture
1095 1105
1096# SPARC64 Architecture 1106# SPARC64 Architecture
@@ -1119,6 +1129,16 @@ config WATCHDOG_RIO
1119 1129
1120# XTENSA Architecture 1130# XTENSA Architecture
1121 1131
1132# Xen Architecture
1133
1134config XEN_WDT
1135 tristate "Xen Watchdog support"
1136 depends on XEN
1137 help
1138 Say Y here to support the hypervisor watchdog capability provided
1139 by Xen 4.0 and newer. The watchdog timeout period is normally one
1140 minute but can be changed with a boot-time parameter.
1141
1122# 1142#
1123# ISA-based Watchdog Cards 1143# ISA-based Watchdog Cards
1124# 1144#
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index dd776651917c..d520bf9c3355 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -102,11 +102,12 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
102obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o 102obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
103obj-$(CONFIG_MACHZ_WDT) += machzwd.o 103obj-$(CONFIG_MACHZ_WDT) += machzwd.o
104obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o 104obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
105obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
105 106
106# M32R Architecture 107# M32R Architecture
107 108
108# M68K Architecture 109# M68K Architecture
109obj-$(CONFIG_M548x_WATCHDOG) += m548x_wdt.o 110obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
110 111
111# MIPS Architecture 112# MIPS Architecture
112obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o 113obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
@@ -114,6 +115,7 @@ obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
114obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o 115obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
115obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 116obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
116obj-$(CONFIG_INDYDOG) += indydog.o 117obj-$(CONFIG_INDYDOG) += indydog.o
118obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o
117obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 119obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
118obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o 120obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
119obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o 121obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
@@ -148,6 +150,9 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
148 150
149# XTENSA Architecture 151# XTENSA Architecture
150 152
153# Xen
154obj-$(CONFIG_XEN_WDT) += xen_wdt.o
155
151# Architecture Independant 156# Architecture Independant
152obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 157obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
153obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 158obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index fa4d36033552..f16dcbd475fb 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this,
301 * want to register another driver on the same PCI id. 301 * want to register another driver on the same PCI id.
302 */ 302 */
303 303
304static struct pci_device_id ali_pci_tbl[] __used = { 304static DEFINE_PCI_DEVICE_TABLE(ali_pci_tbl) __used = {
305 { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, 305 { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
306 { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, 306 { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
307 { 0, }, 307 { 0, },
@@ -362,12 +362,12 @@ static int __init ali_find_watchdog(void)
362 */ 362 */
363 363
364static const struct file_operations ali_fops = { 364static const struct file_operations ali_fops = {
365 .owner = THIS_MODULE, 365 .owner = THIS_MODULE,
366 .llseek = no_llseek, 366 .llseek = no_llseek,
367 .write = ali_write, 367 .write = ali_write,
368 .unlocked_ioctl = ali_ioctl, 368 .unlocked_ioctl = ali_ioctl,
369 .open = ali_open, 369 .open = ali_open,
370 .release = ali_release, 370 .release = ali_release,
371}; 371};
372 372
373static struct miscdevice ali_miscdev = { 373static struct miscdevice ali_miscdev = {
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 4b7a2b4138ed..46f4b85b46de 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -430,7 +430,7 @@ err_out:
430module_init(alim7101_wdt_init); 430module_init(alim7101_wdt_init);
431module_exit(alim7101_wdt_unload); 431module_exit(alim7101_wdt_unload);
432 432
433static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = { 433static DEFINE_PCI_DEVICE_TABLE(alim7101_pci_tbl) __used = {
434 { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, 434 { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
435 { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, 435 { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
436 { } 436 { }
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 5f245522397b..bd44417c84d4 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -150,8 +150,8 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
150} 150}
151 151
152static const struct watchdog_info bcm47xx_wdt_info = { 152static const struct watchdog_info bcm47xx_wdt_info = {
153 .identity = DRV_NAME, 153 .identity = DRV_NAME,
154 .options = WDIOF_SETTIMEOUT | 154 .options = WDIOF_SETTIMEOUT |
155 WDIOF_KEEPALIVEPING | 155 WDIOF_KEEPALIVEPING |
156 WDIOF_MAGICCLOSE, 156 WDIOF_MAGICCLOSE,
157}; 157};
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 9042a95fc98c..b9fa9b71583a 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -63,7 +63,7 @@ static DEFINE_SPINLOCK(bfin_wdt_spinlock);
63/** 63/**
64 * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive 64 * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
65 * 65 *
66 * The Userspace watchdog got a KeepAlive: schedule the next timeout. 66 * The Userspace watchdog got a KeepAlive: schedule the next timeout.
67 */ 67 */
68static int bfin_wdt_keepalive(void) 68static int bfin_wdt_keepalive(void)
69{ 69{
@@ -337,7 +337,7 @@ static int bfin_wdt_resume(struct platform_device *pdev)
337static const struct file_operations bfin_wdt_fops = { 337static const struct file_operations bfin_wdt_fops = {
338 .owner = THIS_MODULE, 338 .owner = THIS_MODULE,
339 .llseek = no_llseek, 339 .llseek = no_llseek,
340 .write = bfin_wdt_write, 340 .write = bfin_wdt_write,
341 .unlocked_ioctl = bfin_wdt_ioctl, 341 .unlocked_ioctl = bfin_wdt_ioctl,
342 .open = bfin_wdt_open, 342 .open = bfin_wdt_open,
343 .release = bfin_wdt_release, 343 .release = bfin_wdt_release,
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 7e7ec9c35b6a..337265b47305 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -4,7 +4,7 @@
4 * Author: Matthew McClintock 4 * Author: Matthew McClintock
5 * Maintainer: Kumar Gala <galak@kernel.crashing.org> 5 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
6 * 6 *
7 * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc. 7 * Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc.
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
@@ -221,9 +221,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
221 if (booke_wdt_enabled == 0) { 221 if (booke_wdt_enabled == 0) {
222 booke_wdt_enabled = 1; 222 booke_wdt_enabled = 1;
223 on_each_cpu(__booke_wdt_enable, NULL, 0); 223 on_each_cpu(__booke_wdt_enable, NULL, 0);
224 printk(KERN_INFO 224 pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
225 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 225 period_to_sec(booke_wdt_period));
226 booke_wdt_period);
227 } 226 }
228 spin_unlock(&booke_wdt_lock); 227 spin_unlock(&booke_wdt_lock);
229 228
@@ -240,6 +239,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file)
240 */ 239 */
241 on_each_cpu(__booke_wdt_disable, NULL, 0); 240 on_each_cpu(__booke_wdt_disable, NULL, 0);
242 booke_wdt_enabled = 0; 241 booke_wdt_enabled = 0;
242 pr_debug("booke_wdt: watchdog disabled\n");
243#endif 243#endif
244 244
245 clear_bit(0, &wdt_is_active); 245 clear_bit(0, &wdt_is_active);
@@ -271,21 +271,20 @@ static int __init booke_wdt_init(void)
271{ 271{
272 int ret = 0; 272 int ret = 0;
273 273
274 printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); 274 pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
275 ident.firmware_version = cur_cpu_spec->pvr_value; 275 ident.firmware_version = cur_cpu_spec->pvr_value;
276 276
277 ret = misc_register(&booke_wdt_miscdev); 277 ret = misc_register(&booke_wdt_miscdev);
278 if (ret) { 278 if (ret) {
279 printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n", 279 pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
280 WATCHDOG_MINOR, ret); 280 WATCHDOG_MINOR, ret);
281 return ret; 281 return ret;
282 } 282 }
283 283
284 spin_lock(&booke_wdt_lock); 284 spin_lock(&booke_wdt_lock);
285 if (booke_wdt_enabled == 1) { 285 if (booke_wdt_enabled == 1) {
286 printk(KERN_INFO 286 pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
287 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 287 period_to_sec(booke_wdt_period));
288 booke_wdt_period);
289 on_each_cpu(__booke_wdt_enable, NULL, 0); 288 on_each_cpu(__booke_wdt_enable, NULL, 0);
290 } 289 }
291 spin_unlock(&booke_wdt_lock); 290 spin_unlock(&booke_wdt_lock);
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index eca855a55c0d..1e013e8457b7 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -5,10 +5,10 @@
5 * interface and Solaris-compatible ioctls as best it is 5 * interface and Solaris-compatible ioctls as best it is
6 * able. 6 * able.
7 * 7 *
8 * NOTE: CP1400 systems appear to have a defective intr_mask 8 * NOTE: CP1400 systems appear to have a defective intr_mask
9 * register on the PLD, preventing the disabling of 9 * register on the PLD, preventing the disabling of
10 * timer interrupts. We use a timer to periodically 10 * timer interrupts. We use a timer to periodically
11 * reset 'stopped' watchdogs on affected platforms. 11 * reset 'stopped' watchdogs on affected platforms.
12 * 12 *
13 * Copyright (c) 2000 Eric Brower (ebrower@usa.net) 13 * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
14 * Copyright (C) 2008 David S. Miller <davem@davemloft.net> 14 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
@@ -107,13 +107,13 @@ static struct cpwd *cpwd_device;
107 * ------------------- 107 * -------------------
108 * |- counter val -| 108 * |- counter val -|
109 * ------------------- 109 * -------------------
110 * dcntr - Current 16-bit downcounter value. 110 * dcntr - Current 16-bit downcounter value.
111 * When downcounter reaches '0' watchdog expires. 111 * When downcounter reaches '0' watchdog expires.
112 * Reading this register resets downcounter with 112 * Reading this register resets downcounter with
113 * 'limit' value. 113 * 'limit' value.
114 * limit - 16-bit countdown value in 1/10th second increments. 114 * limit - 16-bit countdown value in 1/10th second increments.
115 * Writing this register begins countdown with input value. 115 * Writing this register begins countdown with input value.
116 * Reading from this register does not affect counter. 116 * Reading from this register does not affect counter.
117 * NOTES: After watchdog reset, dcntr and limit contain '1' 117 * NOTES: After watchdog reset, dcntr and limit contain '1'
118 * 118 *
119 * status register (byte access): 119 * status register (byte access):
@@ -123,7 +123,7 @@ static struct cpwd *cpwd_device;
123 * |- UNUSED -| EXP | RUN | 123 * |- UNUSED -| EXP | RUN |
124 * --------------------------- 124 * ---------------------------
125 * status- Bit 0 - Watchdog is running 125 * status- Bit 0 - Watchdog is running
126 * Bit 1 - Watchdog has expired 126 * Bit 1 - Watchdog has expired
127 * 127 *
128 *** PLD register block definition (struct wd_pld_regblk) 128 *** PLD register block definition (struct wd_pld_regblk)
129 * 129 *
@@ -197,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr)
197 * Because of the CP1400 defect this should only be 197 * Because of the CP1400 defect this should only be
198 * called during initialzation or by wd_[start|stop]timer() 198 * called during initialzation or by wd_[start|stop]timer()
199 * 199 *
200 * index - sub-device index, or -1 for 'all' 200 * index - sub-device index, or -1 for 'all'
201 * enable - non-zero to enable interrupts, zero to disable 201 * enable - non-zero to enable interrupts, zero to disable
202 */ 202 */
203static void cpwd_toggleintr(struct cpwd *p, int index, int enable) 203static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
@@ -317,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index)
317 } else { 317 } else {
318 /* Fudge WD_EXPIRED status for defective CP1400-- 318 /* Fudge WD_EXPIRED status for defective CP1400--
319 * IF timer is running 319 * IF timer is running
320 * AND brokenstop is set 320 * AND brokenstop is set
321 * AND an interrupt has been serviced 321 * AND an interrupt has been serviced
322 * we are WD_EXPIRED. 322 * we are WD_EXPIRED.
323 * 323 *
324 * IF timer is running 324 * IF timer is running
325 * AND brokenstop is set 325 * AND brokenstop is set
326 * AND no interrupt has been serviced 326 * AND no interrupt has been serviced
327 * we are WD_FREERUN. 327 * we are WD_FREERUN.
328 */ 328 */
329 if (p->broken && 329 if (p->broken &&
@@ -528,8 +528,7 @@ static const struct file_operations cpwd_fops = {
528 .llseek = no_llseek, 528 .llseek = no_llseek,
529}; 529};
530 530
531static int __devinit cpwd_probe(struct platform_device *op, 531static int __devinit cpwd_probe(struct platform_device *op)
532 const struct of_device_id *match)
533{ 532{
534 struct device_node *options; 533 struct device_node *options;
535 const char *str_prop; 534 const char *str_prop;
@@ -614,7 +613,7 @@ static int __devinit cpwd_probe(struct platform_device *op,
614 613
615 if (p->broken) { 614 if (p->broken) {
616 init_timer(&cpwd_timer); 615 init_timer(&cpwd_timer);
617 cpwd_timer.function = cpwd_brokentimer; 616 cpwd_timer.function = cpwd_brokentimer;
618 cpwd_timer.data = (unsigned long) p; 617 cpwd_timer.data = (unsigned long) p;
619 cpwd_timer.expires = WD_BTIMEOUT; 618 cpwd_timer.expires = WD_BTIMEOUT;
620 619
@@ -646,7 +645,7 @@ static int __devexit cpwd_remove(struct platform_device *op)
646 struct cpwd *p = dev_get_drvdata(&op->dev); 645 struct cpwd *p = dev_get_drvdata(&op->dev);
647 int i; 646 int i;
648 647
649 for (i = 0; i < 4; i++) { 648 for (i = 0; i < WD_NUMDEVS; i++) {
650 misc_deregister(&p->devs[i].misc); 649 misc_deregister(&p->devs[i].misc);
651 650
652 if (!p->enabled) { 651 if (!p->enabled) {
@@ -678,7 +677,7 @@ static const struct of_device_id cpwd_match[] = {
678}; 677};
679MODULE_DEVICE_TABLE(of, cpwd_match); 678MODULE_DEVICE_TABLE(of, cpwd_match);
680 679
681static struct of_platform_driver cpwd_driver = { 680static struct platform_driver cpwd_driver = {
682 .driver = { 681 .driver = {
683 .name = DRIVER_NAME, 682 .name = DRIVER_NAME,
684 .owner = THIS_MODULE, 683 .owner = THIS_MODULE,
@@ -690,12 +689,12 @@ static struct of_platform_driver cpwd_driver = {
690 689
691static int __init cpwd_init(void) 690static int __init cpwd_init(void)
692{ 691{
693 return of_register_platform_driver(&cpwd_driver); 692 return platform_driver_register(&cpwd_driver);
694} 693}
695 694
696static void __exit cpwd_exit(void) 695static void __exit cpwd_exit(void)
697{ 696{
698 of_unregister_platform_driver(&cpwd_driver); 697 platform_driver_unregister(&cpwd_driver);
699} 698}
700 699
701module_init(cpwd_init); 700module_init(cpwd_init);
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index 3f3dc093ad68..f1d1da662fbe 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -201,7 +201,7 @@ static void eurwdt_ping(void)
201static ssize_t eurwdt_write(struct file *file, const char __user *buf, 201static ssize_t eurwdt_write(struct file *file, const char __user *buf,
202size_t count, loff_t *ppos) 202size_t count, loff_t *ppos)
203{ 203{
204 if (count) { 204 if (count) {
205 if (!nowayout) { 205 if (!nowayout) {
206 size_t i; 206 size_t i;
207 207
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index f6bd6f10fcec..29a7cd4b90c8 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -261,8 +261,7 @@ static struct miscdevice gef_wdt_miscdev = {
261}; 261};
262 262
263 263
264static int __devinit gef_wdt_probe(struct platform_device *dev, 264static int __devinit gef_wdt_probe(struct platform_device *dev)
265 const struct of_device_id *match)
266{ 265{
267 int timeout = 10; 266 int timeout = 10;
268 u32 freq; 267 u32 freq;
@@ -303,7 +302,7 @@ static const struct of_device_id gef_wdt_ids[] = {
303 {}, 302 {},
304}; 303};
305 304
306static struct of_platform_driver gef_wdt_driver = { 305static struct platform_driver gef_wdt_driver = {
307 .driver = { 306 .driver = {
308 .name = "gef_wdt", 307 .name = "gef_wdt",
309 .owner = THIS_MODULE, 308 .owner = THIS_MODULE,
@@ -315,12 +314,12 @@ static struct of_platform_driver gef_wdt_driver = {
315static int __init gef_wdt_init(void) 314static int __init gef_wdt_init(void)
316{ 315{
317 printk(KERN_INFO "GE watchdog driver\n"); 316 printk(KERN_INFO "GE watchdog driver\n");
318 return of_register_platform_driver(&gef_wdt_driver); 317 return platform_driver_register(&gef_wdt_driver);
319} 318}
320 319
321static void __exit gef_wdt_exit(void) 320static void __exit gef_wdt_exit(void)
322{ 321{
323 of_unregister_platform_driver(&gef_wdt_driver); 322 platform_driver_unregister(&gef_wdt_driver);
324} 323}
325 324
326module_init(gef_wdt_init); 325module_init(gef_wdt_init);
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 24b966d5061a..8cb26855bfed 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -52,7 +52,7 @@ static void __iomem *pci_mem_addr; /* the PCI-memory address */
52static unsigned long __iomem *hpwdt_timer_reg; 52static unsigned long __iomem *hpwdt_timer_reg;
53static unsigned long __iomem *hpwdt_timer_con; 53static unsigned long __iomem *hpwdt_timer_con;
54 54
55static struct pci_device_id hpwdt_devices[] = { 55static DEFINE_PCI_DEVICE_TABLE(hpwdt_devices) = {
56 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */ 56 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */
57 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */ 57 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */
58 {0}, /* terminate list */ 58 {0}, /* terminate list */
@@ -710,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
710 return 0; 710 return 0;
711} 711}
712 712
713static void __devexit hpwdt_exit_nmi_decoding(void) 713static void hpwdt_exit_nmi_decoding(void)
714{ 714{
715 unregister_die_notifier(&die_notifier); 715 unregister_die_notifier(&die_notifier);
716 if (cru_rom_addr) 716 if (cru_rom_addr)
@@ -726,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
726 return 0; 726 return 0;
727} 727}
728 728
729static void __devexit hpwdt_exit_nmi_decoding(void) 729static void hpwdt_exit_nmi_decoding(void)
730{ 730{
731} 731}
732#endif /* CONFIG_HPWDT_NMI_DECODING */ 732#endif /* CONFIG_HPWDT_NMI_DECODING */
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index bb9750a03942..db45091ef434 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -334,7 +334,7 @@ static struct miscdevice esb_miscdev = {
334/* 334/*
335 * Data for PCI driver interface 335 * Data for PCI driver interface
336 */ 336 */
337static struct pci_device_id esb_pci_tbl[] = { 337static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = {
338 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, 338 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
339 { 0, }, /* End of list */ 339 { 0, }, /* End of list */
340}; 340};
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 2c6c2b4ad8bf..35a0d12dad73 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -247,7 +247,7 @@ static struct {
247 {NULL, 0} 247 {NULL, 0}
248}; 248};
249 249
250#define ITCO_PCI_DEVICE(dev, data) \ 250#define ITCO_PCI_DEVICE(dev, data) \
251 .vendor = PCI_VENDOR_ID_INTEL, \ 251 .vendor = PCI_VENDOR_ID_INTEL, \
252 .device = dev, \ 252 .device = dev, \
253 .subvendor = PCI_ANY_ID, \ 253 .subvendor = PCI_ANY_ID, \
@@ -262,7 +262,7 @@ static struct {
262 * pci_driver, because the I/O Controller Hub has also other 262 * pci_driver, because the I/O Controller Hub has also other
263 * functions that probably will be registered by other drivers. 263 * functions that probably will be registered by other drivers.
264 */ 264 */
265static struct pci_device_id iTCO_wdt_pci_tbl[] = { 265static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
266 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)}, 266 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)},
267 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)}, 267 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)},
268 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)}, 268 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)},
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
new file mode 100644
index 000000000000..919bdd16136f
--- /dev/null
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -0,0 +1,572 @@
1/*
2 * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
3 * for Intel part #(s):
4 * - AF82MP20 PCH
5 *
6 * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General
10 * Public License as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be
13 * useful, but WITHOUT ANY WARRANTY; without even the implied
14 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 * The full GNU General Public License is included in this
21 * distribution in the file called COPYING.
22 *
23 */
24
25#include <linux/compiler.h>
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/moduleparam.h>
29#include <linux/types.h>
30#include <linux/miscdevice.h>
31#include <linux/watchdog.h>
32#include <linux/fs.h>
33#include <linux/notifier.h>
34#include <linux/reboot.h>
35#include <linux/init.h>
36#include <linux/jiffies.h>
37#include <linux/uaccess.h>
38#include <linux/slab.h>
39#include <linux/io.h>
40#include <linux/interrupt.h>
41#include <linux/delay.h>
42#include <linux/sched.h>
43#include <linux/signal.h>
44#include <linux/sfi.h>
45#include <linux/types.h>
46#include <asm/irq.h>
47#include <asm/atomic.h>
48#include <asm/intel_scu_ipc.h>
49#include <asm/apb_timer.h>
50#include <asm/mrst.h>
51
52#include "intel_scu_watchdog.h"
53
54/* Bounds number of times we will retry loading time count */
55/* This retry is a work around for a silicon bug. */
56#define MAX_RETRY 16
57
58#define IPC_SET_WATCHDOG_TIMER 0xF8
59
60static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN;
61module_param(timer_margin, int, 0);
62MODULE_PARM_DESC(timer_margin,
63 "Watchdog timer margin"
64 "Time between interrupt and resetting the system"
65 "The range is from 1 to 160"
66 "This is the time for all keep alives to arrive");
67
68static int timer_set = DEFAULT_TIME;
69module_param(timer_set, int, 0);
70MODULE_PARM_DESC(timer_set,
71 "Default Watchdog timer setting"
72 "Complete cycle time"
73 "The range is from 1 to 170"
74 "This is the time for all keep alives to arrive");
75
76/* After watchdog device is closed, check force_boot. If:
77 * force_boot == 0, then force boot on next watchdog interrupt after close,
78 * force_boot == 1, then force boot immediately when device is closed.
79 */
80static int force_boot;
81module_param(force_boot, int, 0);
82MODULE_PARM_DESC(force_boot,
83 "A value of 1 means that the driver will reboot"
84 "the system immediately if the /dev/watchdog device is closed"
85 "A value of 0 means that when /dev/watchdog device is closed"
86 "the watchdog timer will be refreshed for one more interval"
87 "of length: timer_set. At the end of this interval, the"
88 "watchdog timer will reset the system."
89 );
90
91/* there is only one device in the system now; this can be made into
92 * an array in the future if we have more than one device */
93
94static struct intel_scu_watchdog_dev watchdog_device;
95
96/* Forces restart, if force_reboot is set */
97static void watchdog_fire(void)
98{
99 if (force_boot) {
100 printk(KERN_CRIT PFX "Initiating system reboot.\n");
101 emergency_restart();
102 printk(KERN_CRIT PFX "Reboot didn't ?????\n");
103 }
104
105 else {
106 printk(KERN_CRIT PFX "Immediate Reboot Disabled\n");
107 printk(KERN_CRIT PFX
108 "System will reset when watchdog timer times out!\n");
109 }
110}
111
112static int check_timer_margin(int new_margin)
113{
114 if ((new_margin < MIN_TIME_CYCLE) ||
115 (new_margin > MAX_TIME - timer_set)) {
116 pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n",
117 new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
118 return -EINVAL;
119 }
120 return 0;
121}
122
123/*
124 * IPC operations
125 */
126static int watchdog_set_ipc(int soft_threshold, int threshold)
127{
128 u32 *ipc_wbuf;
129 u8 cbuf[16] = { '\0' };
130 int ipc_ret = 0;
131
132 ipc_wbuf = (u32 *)&cbuf;
133 ipc_wbuf[0] = soft_threshold;
134 ipc_wbuf[1] = threshold;
135
136 ipc_ret = intel_scu_ipc_command(
137 IPC_SET_WATCHDOG_TIMER,
138 0,
139 ipc_wbuf,
140 2,
141 NULL,
142 0);
143
144 if (ipc_ret != 0)
145 pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);
146
147 return ipc_ret;
148};
149
150/*
151 * Intel_SCU operations
152 */
153
154/* timer interrupt handler */
155static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
156{
157 int int_status;
158 int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
159
160 pr_debug("Watchdog timer: irq, int_status: %x\n", int_status);
161
162 if (int_status != 0)
163 return IRQ_NONE;
164
165 /* has the timer been started? If not, then this is spurious */
166 if (watchdog_device.timer_started == 0) {
167 pr_debug("Watchdog timer: spurious interrupt received\n");
168 return IRQ_HANDLED;
169 }
170
171 /* temporarily disable the timer */
172 iowrite32(0x00000002, watchdog_device.timer_control_addr);
173
174 /* set the timer to the threshold */
175 iowrite32(watchdog_device.threshold,
176 watchdog_device.timer_load_count_addr);
177
178 /* allow the timer to run */
179 iowrite32(0x00000003, watchdog_device.timer_control_addr);
180
181 return IRQ_HANDLED;
182}
183
184static int intel_scu_keepalive(void)
185{
186
187 /* read eoi register - clears interrupt */
188 ioread32(watchdog_device.timer_clear_interrupt_addr);
189
190 /* temporarily disable the timer */
191 iowrite32(0x00000002, watchdog_device.timer_control_addr);
192
193 /* set the timer to the soft_threshold */
194 iowrite32(watchdog_device.soft_threshold,
195 watchdog_device.timer_load_count_addr);
196
197 /* allow the timer to run */
198 iowrite32(0x00000003, watchdog_device.timer_control_addr);
199
200 return 0;
201}
202
203static int intel_scu_stop(void)
204{
205 iowrite32(0, watchdog_device.timer_control_addr);
206 return 0;
207}
208
209static int intel_scu_set_heartbeat(u32 t)
210{
211 int ipc_ret;
212 int retry_count;
213 u32 soft_value;
214 u32 hw_pre_value;
215 u32 hw_value;
216
217 watchdog_device.timer_set = t;
218 watchdog_device.threshold =
219 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
220 watchdog_device.soft_threshold =
221 (watchdog_device.timer_set - timer_margin)
222 * watchdog_device.timer_tbl_ptr->freq_hz;
223
224 pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n",
225 watchdog_device.timer_tbl_ptr->freq_hz);
226 pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n",
227 watchdog_device.timer_set);
228 pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n",
229 timer_margin);
230 pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n",
231 watchdog_device.threshold);
232 pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n",
233 watchdog_device.soft_threshold);
234
235 /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
236 /* watchdog timing come out right. */
237 watchdog_device.threshold =
238 watchdog_device.threshold / FREQ_ADJUSTMENT;
239 watchdog_device.soft_threshold =
240 watchdog_device.soft_threshold / FREQ_ADJUSTMENT;
241
242 /* temporarily disable the timer */
243 iowrite32(0x00000002, watchdog_device.timer_control_addr);
244
245 /* send the threshold and soft_threshold via IPC to the processor */
246 ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold,
247 watchdog_device.threshold);
248
249 if (ipc_ret != 0) {
250 /* Make sure the watchdog timer is stopped */
251 intel_scu_stop();
252 return ipc_ret;
253 }
254
255 /* Soft Threshold set loop. Early versions of silicon did */
256 /* not always set this count correctly. This loop checks */
257 /* the value and retries if it was not set correctly. */
258
259 retry_count = 0;
260 soft_value = watchdog_device.soft_threshold & 0xFFFF0000;
261 do {
262
263 /* Make sure timer is stopped */
264 intel_scu_stop();
265
266 if (MAX_RETRY < retry_count++) {
267 /* Unable to set timer value */
268 pr_err("Watchdog timer: Unable to set timer\n");
269 return -ENODEV;
270 }
271
272 /* set the timer to the soft threshold */
273 iowrite32(watchdog_device.soft_threshold,
274 watchdog_device.timer_load_count_addr);
275
276 /* read count value before starting timer */
277 hw_pre_value = ioread32(watchdog_device.timer_load_count_addr);
278 hw_pre_value = hw_pre_value & 0xFFFF0000;
279
280 /* Start the timer */
281 iowrite32(0x00000003, watchdog_device.timer_control_addr);
282
283 /* read the value the time loaded into its count reg */
284 hw_value = ioread32(watchdog_device.timer_load_count_addr);
285 hw_value = hw_value & 0xFFFF0000;
286
287
288 } while (soft_value != hw_value);
289
290 watchdog_device.timer_started = 1;
291
292 return 0;
293}
294
295/*
296 * /dev/watchdog handling
297 */
298
299static int intel_scu_open(struct inode *inode, struct file *file)
300{
301
302 /* Set flag to indicate that watchdog device is open */
303 if (test_and_set_bit(0, &watchdog_device.driver_open))
304 return -EBUSY;
305
306 /* Check for reopen of driver. Reopens are not allowed */
307 if (watchdog_device.driver_closed)
308 return -EPERM;
309
310 return nonseekable_open(inode, file);
311}
312
313static int intel_scu_release(struct inode *inode, struct file *file)
314{
315 /*
316 * This watchdog should not be closed, after the timer
317 * is started with the WDIPC_SETTIMEOUT ioctl
318 * If force_boot is set watchdog_fire() will cause an
319 * immediate reset. If force_boot is not set, the watchdog
320 * timer is refreshed for one more interval. At the end
321 * of that interval, the watchdog timer will reset the system.
322 */
323
324 if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
325 pr_debug("Watchdog timer: intel_scu_release, without open\n");
326 return -ENOTTY;
327 }
328
329 if (!watchdog_device.timer_started) {
330 /* Just close, since timer has not been started */
331 pr_debug("Watchdog timer: closed, without starting timer\n");
332 return 0;
333 }
334
335 printk(KERN_CRIT PFX
336 "Unexpected close of /dev/watchdog!\n");
337
338 /* Since the timer was started, prevent future reopens */
339 watchdog_device.driver_closed = 1;
340
341 /* Refresh the timer for one more interval */
342 intel_scu_keepalive();
343
344 /* Reboot system (if force_boot is set) */
345 watchdog_fire();
346
347 /* We should only reach this point if force_boot is not set */
348 return 0;
349}
350
351static ssize_t intel_scu_write(struct file *file,
352 char const *data,
353 size_t len,
354 loff_t *ppos)
355{
356
357 if (watchdog_device.timer_started)
358 /* Watchdog already started, keep it alive */
359 intel_scu_keepalive();
360 else
361 /* Start watchdog with timer value set by init */
362 intel_scu_set_heartbeat(watchdog_device.timer_set);
363
364 return len;
365}
366
367static long intel_scu_ioctl(struct file *file,
368 unsigned int cmd,
369 unsigned long arg)
370{
371 void __user *argp = (void __user *)arg;
372 u32 __user *p = argp;
373 u32 new_margin;
374
375
376 static const struct watchdog_info ident = {
377 .options = WDIOF_SETTIMEOUT
378 | WDIOF_KEEPALIVEPING,
379 .firmware_version = 0, /* @todo Get from SCU via
380 ipc_get_scu_fw_version()? */
381 .identity = "Intel_SCU IOH Watchdog" /* len < 32 */
382 };
383
384 switch (cmd) {
385 case WDIOC_GETSUPPORT:
386 return copy_to_user(argp,
387 &ident,
388 sizeof(ident)) ? -EFAULT : 0;
389 case WDIOC_GETSTATUS:
390 case WDIOC_GETBOOTSTATUS:
391 return put_user(0, p);
392 case WDIOC_KEEPALIVE:
393 intel_scu_keepalive();
394
395 return 0;
396 case WDIOC_SETTIMEOUT:
397 if (get_user(new_margin, p))
398 return -EFAULT;
399
400 if (check_timer_margin(new_margin))
401 return -EINVAL;
402
403 if (intel_scu_set_heartbeat(new_margin))
404 return -EINVAL;
405 return 0;
406 case WDIOC_GETTIMEOUT:
407 return put_user(watchdog_device.soft_threshold, p);
408
409 default:
410 return -ENOTTY;
411 }
412}
413
414/*
415 * Notifier for system down
416 */
417static int intel_scu_notify_sys(struct notifier_block *this,
418 unsigned long code,
419 void *another_unused)
420{
421 if (code == SYS_DOWN || code == SYS_HALT)
422 /* Turn off the watchdog timer. */
423 intel_scu_stop();
424 return NOTIFY_DONE;
425}
426
427/*
428 * Kernel Interfaces
429 */
430static const struct file_operations intel_scu_fops = {
431 .owner = THIS_MODULE,
432 .llseek = no_llseek,
433 .write = intel_scu_write,
434 .unlocked_ioctl = intel_scu_ioctl,
435 .open = intel_scu_open,
436 .release = intel_scu_release,
437};
438
439static int __init intel_scu_watchdog_init(void)
440{
441 int ret;
442 u32 __iomem *tmp_addr;
443
444 /*
445 * We don't really need to check this as the SFI timer get will fail
446 * but if we do so we can exit with a clearer reason and no noise.
447 *
448 * If it isn't an intel MID device then it doesn't have this watchdog
449 */
450 if (!mrst_identify_cpu())
451 return -ENODEV;
452
453 /* Check boot parameters to verify that their initial values */
454 /* are in range. */
455 /* Check value of timer_set boot parameter */
456 if ((timer_set < MIN_TIME_CYCLE) ||
457 (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
458 pr_err("Watchdog timer: value of timer_set %x (hex) "
459 "is out of range from %x to %x (hex)\n",
460 timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
461 return -EINVAL;
462 }
463
464 /* Check value of timer_margin boot parameter */
465 if (check_timer_margin(timer_margin))
466 return -EINVAL;
467
468 watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
469
470 if (watchdog_device.timer_tbl_ptr == NULL) {
471 pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
472 return -ENODEV;
473 }
474 /* make sure the timer exists */
475 if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
476 pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
477 sfi_mtimer_num);
478 return -ENODEV;
479 }
480
481 if (watchdog_device.timer_tbl_ptr->irq == 0) {
482 pr_debug("Watchdog timer: timer %d invalid irq\n",
483 sfi_mtimer_num);
484 return -ENODEV;
485 }
486
487 tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr,
488 20);
489
490 if (tmp_addr == NULL) {
491 pr_debug("Watchdog timer: timer unable to ioremap\n");
492 return -ENOMEM;
493 }
494
495 watchdog_device.timer_load_count_addr = tmp_addr++;
496 watchdog_device.timer_current_value_addr = tmp_addr++;
497 watchdog_device.timer_control_addr = tmp_addr++;
498 watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
499 watchdog_device.timer_interrupt_status_addr = tmp_addr++;
500
501 /* Set the default time values in device structure */
502
503 watchdog_device.timer_set = timer_set;
504 watchdog_device.threshold =
505 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
506 watchdog_device.soft_threshold =
507 (watchdog_device.timer_set - timer_margin)
508 * watchdog_device.timer_tbl_ptr->freq_hz;
509
510
511 watchdog_device.intel_scu_notifier.notifier_call =
512 intel_scu_notify_sys;
513
514 ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
515 if (ret) {
516 pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
517 goto register_reboot_error;
518 }
519
520 watchdog_device.miscdev.minor = WATCHDOG_MINOR;
521 watchdog_device.miscdev.name = "watchdog";
522 watchdog_device.miscdev.fops = &intel_scu_fops;
523
524 ret = misc_register(&watchdog_device.miscdev);
525 if (ret) {
526 pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
527 WATCHDOG_MINOR, ret);
528 goto misc_register_error;
529 }
530
531 ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
532 watchdog_timer_interrupt,
533 IRQF_SHARED, "watchdog",
534 &watchdog_device.timer_load_count_addr);
535 if (ret) {
536 pr_err("Watchdog timer: error requesting irq %d\n", ret);
537 goto request_irq_error;
538 }
539 /* Make sure timer is disabled before returning */
540 intel_scu_stop();
541 return 0;
542
543/* error cleanup */
544
545request_irq_error:
546 misc_deregister(&watchdog_device.miscdev);
547misc_register_error:
548 unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
549register_reboot_error:
550 intel_scu_stop();
551 iounmap(watchdog_device.timer_load_count_addr);
552 return ret;
553}
554
555static void __exit intel_scu_watchdog_exit(void)
556{
557
558 misc_deregister(&watchdog_device.miscdev);
559 unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
560 /* disable the timer */
561 iowrite32(0x00000002, watchdog_device.timer_control_addr);
562 iounmap(watchdog_device.timer_load_count_addr);
563}
564
565late_initcall(intel_scu_watchdog_init);
566module_exit(intel_scu_watchdog_exit);
567
568MODULE_AUTHOR("Intel Corporation");
569MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver");
570MODULE_LICENSE("GPL");
571MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
572MODULE_VERSION(WDT_VER);
diff --git a/drivers/watchdog/intel_scu_watchdog.h b/drivers/watchdog/intel_scu_watchdog.h
new file mode 100644
index 000000000000..d2b074a82db6
--- /dev/null
+++ b/drivers/watchdog/intel_scu_watchdog.h
@@ -0,0 +1,66 @@
1/*
2 * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device
3 * for Intel part #(s):
4 * - AF82MP20 PCH
5 *
6 * Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General
10 * Public License as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be
13 * useful, but WITHOUT ANY WARRANTY; without even the implied
14 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 * The full GNU General Public License is included in this
21 * distribution in the file called COPYING.
22 *
23 */
24
25#ifndef __INTEL_SCU_WATCHDOG_H
26#define __INTEL_SCU_WATCHDOG_H
27
28#define PFX "Intel_SCU: "
29#define WDT_VER "0.3"
30
31/* minimum time between interrupts */
32#define MIN_TIME_CYCLE 1
33
34/* Time from warning to reboot is 2 seconds */
35#define DEFAULT_SOFT_TO_HARD_MARGIN 2
36
37#define MAX_TIME 170
38
39#define DEFAULT_TIME 5
40
41#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE)
42
43/* Ajustment to clock tick frequency to make timing come out right */
44#define FREQ_ADJUSTMENT 8
45
46struct intel_scu_watchdog_dev {
47 ulong driver_open;
48 ulong driver_closed;
49 u32 timer_started;
50 u32 timer_set;
51 u32 threshold;
52 u32 soft_threshold;
53 u32 __iomem *timer_load_count_addr;
54 u32 __iomem *timer_current_value_addr;
55 u32 __iomem *timer_control_addr;
56 u32 __iomem *timer_clear_interrupt_addr;
57 u32 __iomem *timer_interrupt_status_addr;
58 struct sfi_timer_table_entry *timer_tbl_ptr;
59 struct notifier_block intel_scu_notifier;
60 struct miscdevice miscdev;
61};
62
63extern int sfi_mtimer_num;
64
65/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */
66#endif /* __INTEL_SCU_WATCHDOG_H */
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index b32c6c045b1a..6143f52ba6b8 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -69,7 +69,7 @@ static unsigned short address;
69#define IT8712F_DEVID 0x8712 69#define IT8712F_DEVID 0x8712
70 70
71#define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */ 71#define LDN_GPIO 0x07 /* GPIO and Watch Dog Timer */
72#define LDN_GAME 0x09 /* Game Port */ 72#define LDN_GAME 0x09 /* Game Port */
73 73
74#define WDT_CONTROL 0x71 /* WDT Register: Control */ 74#define WDT_CONTROL 0x71 /* WDT Register: Control */
75#define WDT_CONFIG 0x72 /* WDT Register: Configuration */ 75#define WDT_CONFIG 0x72 /* WDT Register: Configuration */
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index dad29245a6a7..b1bc72f9a209 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -12,7 +12,7 @@
12 * http://www.ite.com.tw/ 12 * http://www.ite.com.tw/
13 * 13 *
14 * Support of the watchdog timers, which are available on 14 * Support of the watchdog timers, which are available on
15 * IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726. 15 * IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726.
16 * 16 *
17 * This program is free software; you can redistribute it and/or 17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License 18 * modify it under the terms of the GNU General Public License
@@ -45,7 +45,7 @@
45 45
46#include <asm/system.h> 46#include <asm/system.h>
47 47
48#define WATCHDOG_VERSION "1.13" 48#define WATCHDOG_VERSION "1.14"
49#define WATCHDOG_NAME "IT87 WDT" 49#define WATCHDOG_NAME "IT87 WDT"
50#define PFX WATCHDOG_NAME ": " 50#define PFX WATCHDOG_NAME ": "
51#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" 51#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
@@ -54,7 +54,7 @@
54/* Defaults for Module Parameter */ 54/* Defaults for Module Parameter */
55#define DEFAULT_NOGAMEPORT 0 55#define DEFAULT_NOGAMEPORT 0
56#define DEFAULT_EXCLUSIVE 1 56#define DEFAULT_EXCLUSIVE 1
57#define DEFAULT_TIMEOUT 60 57#define DEFAULT_TIMEOUT 60
58#define DEFAULT_TESTMODE 0 58#define DEFAULT_TESTMODE 0
59#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT 59#define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT
60 60
@@ -70,9 +70,9 @@
70/* Configuration Registers and Functions */ 70/* Configuration Registers and Functions */
71#define LDNREG 0x07 71#define LDNREG 0x07
72#define CHIPID 0x20 72#define CHIPID 0x20
73#define CHIPREV 0x22 73#define CHIPREV 0x22
74#define ACTREG 0x30 74#define ACTREG 0x30
75#define BASEREG 0x60 75#define BASEREG 0x60
76 76
77/* Chip Id numbers */ 77/* Chip Id numbers */
78#define NO_DEV_ID 0xffff 78#define NO_DEV_ID 0xffff
@@ -82,10 +82,11 @@
82#define IT8716_ID 0x8716 82#define IT8716_ID 0x8716
83#define IT8718_ID 0x8718 83#define IT8718_ID 0x8718
84#define IT8720_ID 0x8720 84#define IT8720_ID 0x8720
85#define IT8721_ID 0x8721
85#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 86#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
86 87
87/* GPIO Configuration Registers LDN=0x07 */ 88/* GPIO Configuration Registers LDN=0x07 */
88#define WDTCTRL 0x71 89#define WDTCTRL 0x71
89#define WDTCFG 0x72 90#define WDTCFG 0x72
90#define WDTVALLSB 0x73 91#define WDTVALLSB 0x73
91#define WDTVALMSB 0x74 92#define WDTVALMSB 0x74
@@ -94,7 +95,7 @@
94#define WDT_CIRINT 0x80 95#define WDT_CIRINT 0x80
95#define WDT_MOUSEINT 0x40 96#define WDT_MOUSEINT 0x40
96#define WDT_KYBINT 0x20 97#define WDT_KYBINT 0x20
97#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */ 98#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */
98#define WDT_FORCE 0x02 99#define WDT_FORCE 0x02
99#define WDT_ZERO 0x01 100#define WDT_ZERO 0x01
100 101
@@ -102,11 +103,11 @@
102#define WDT_TOV1 0x80 103#define WDT_TOV1 0x80
103#define WDT_KRST 0x40 104#define WDT_KRST 0x40
104#define WDT_TOVE 0x20 105#define WDT_TOVE 0x20
105#define WDT_PWROK 0x10 106#define WDT_PWROK 0x10 /* not in it8721 */
106#define WDT_INT_MASK 0x0f 107#define WDT_INT_MASK 0x0f
107 108
108/* CIR Configuration Register LDN=0x0a */ 109/* CIR Configuration Register LDN=0x0a */
109#define CIR_ILS 0x70 110#define CIR_ILS 0x70
110 111
111/* The default Base address is not always available, we use this */ 112/* The default Base address is not always available, we use this */
112#define CIR_BASE 0x0208 113#define CIR_BASE 0x0208
@@ -134,7 +135,7 @@
134#define WDTS_USE_GP 4 135#define WDTS_USE_GP 4
135#define WDTS_EXPECTED 5 136#define WDTS_EXPECTED 5
136 137
137static unsigned int base, gpact, ciract, max_units; 138static unsigned int base, gpact, ciract, max_units, chip_type;
138static unsigned long wdt_status; 139static unsigned long wdt_status;
139static DEFINE_SPINLOCK(spinlock); 140static DEFINE_SPINLOCK(spinlock);
140 141
@@ -215,7 +216,7 @@ static inline void superio_outw(int val, int reg)
215/* Internal function, should be called after superio_select(GPIO) */ 216/* Internal function, should be called after superio_select(GPIO) */
216static void wdt_update_timeout(void) 217static void wdt_update_timeout(void)
217{ 218{
218 unsigned char cfg = WDT_KRST | WDT_PWROK; 219 unsigned char cfg = WDT_KRST;
219 int tm = timeout; 220 int tm = timeout;
220 221
221 if (testmode) 222 if (testmode)
@@ -226,6 +227,9 @@ static void wdt_update_timeout(void)
226 else 227 else
227 tm /= 60; 228 tm /= 60;
228 229
230 if (chip_type != IT8721_ID)
231 cfg |= WDT_PWROK;
232
229 superio_outb(cfg, WDTCFG); 233 superio_outb(cfg, WDTCFG);
230 superio_outb(tm, WDTVALLSB); 234 superio_outb(tm, WDTVALLSB);
231 if (max_units > 255) 235 if (max_units > 255)
@@ -555,7 +559,6 @@ static int __init it87_wdt_init(void)
555{ 559{
556 int rc = 0; 560 int rc = 0;
557 int try_gameport = !nogameport; 561 int try_gameport = !nogameport;
558 u16 chip_type;
559 u8 chip_rev; 562 u8 chip_rev;
560 unsigned long flags; 563 unsigned long flags;
561 564
@@ -581,6 +584,7 @@ static int __init it87_wdt_init(void)
581 break; 584 break;
582 case IT8718_ID: 585 case IT8718_ID:
583 case IT8720_ID: 586 case IT8720_ID:
587 case IT8721_ID:
584 max_units = 65535; 588 max_units = 65535;
585 try_gameport = 0; 589 try_gameport = 0;
586 break; 590 break;
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
new file mode 100644
index 000000000000..684ba01fb540
--- /dev/null
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -0,0 +1,322 @@
1/*
2 * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net>
3 * JZ4740 Watchdog driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/watchdog.h>
23#include <linux/init.h>
24#include <linux/bitops.h>
25#include <linux/platform_device.h>
26#include <linux/spinlock.h>
27#include <linux/uaccess.h>
28#include <linux/io.h>
29#include <linux/device.h>
30#include <linux/clk.h>
31#include <linux/slab.h>
32
33#include <asm/mach-jz4740/timer.h>
34
35#define JZ_REG_WDT_TIMER_DATA 0x0
36#define JZ_REG_WDT_COUNTER_ENABLE 0x4
37#define JZ_REG_WDT_TIMER_COUNTER 0x8
38#define JZ_REG_WDT_TIMER_CONTROL 0xC
39
40#define JZ_WDT_CLOCK_PCLK 0x1
41#define JZ_WDT_CLOCK_RTC 0x2
42#define JZ_WDT_CLOCK_EXT 0x4
43
44#define WDT_IN_USE 0
45#define WDT_OK_TO_CLOSE 1
46
47#define JZ_WDT_CLOCK_DIV_SHIFT 3
48
49#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT)
50#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT)
51#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT)
52#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT)
53#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT)
54#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
55
56#define DEFAULT_HEARTBEAT 5
57#define MAX_HEARTBEAT 2048
58
59static struct {
60 void __iomem *base;
61 struct resource *mem;
62 struct clk *rtc_clk;
63 unsigned long status;
64} jz4740_wdt;
65
66static int heartbeat = DEFAULT_HEARTBEAT;
67
68
69static void jz4740_wdt_service(void)
70{
71 writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
72}
73
74static void jz4740_wdt_set_heartbeat(int new_heartbeat)
75{
76 unsigned int rtc_clk_rate;
77 unsigned int timeout_value;
78 unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
79
80 heartbeat = new_heartbeat;
81
82 rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk);
83
84 timeout_value = rtc_clk_rate * heartbeat;
85 while (timeout_value > 0xffff) {
86 if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
87 /* Requested timeout too high;
88 * use highest possible value. */
89 timeout_value = 0xffff;
90 break;
91 }
92 timeout_value >>= 2;
93 clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
94 }
95
96 writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
97 writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
98
99 writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA);
100 writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
101 writew(clock_div | JZ_WDT_CLOCK_RTC,
102 jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
103
104 writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
105}
106
107static void jz4740_wdt_enable(void)
108{
109 jz4740_timer_enable_watchdog();
110 jz4740_wdt_set_heartbeat(heartbeat);
111}
112
113static void jz4740_wdt_disable(void)
114{
115 jz4740_timer_disable_watchdog();
116 writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
117}
118
119static int jz4740_wdt_open(struct inode *inode, struct file *file)
120{
121 if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status))
122 return -EBUSY;
123
124 jz4740_wdt_enable();
125
126 return nonseekable_open(inode, file);
127}
128
129static ssize_t jz4740_wdt_write(struct file *file, const char *data,
130 size_t len, loff_t *ppos)
131{
132 if (len) {
133 size_t i;
134
135 clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
136 for (i = 0; i != len; i++) {
137 char c;
138
139 if (get_user(c, data + i))
140 return -EFAULT;
141
142 if (c == 'V')
143 set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
144 }
145 jz4740_wdt_service();
146 }
147
148 return len;
149}
150
151static const struct watchdog_info ident = {
152 .options = WDIOF_KEEPALIVEPING,
153 .identity = "jz4740 Watchdog",
154};
155
156static long jz4740_wdt_ioctl(struct file *file,
157 unsigned int cmd, unsigned long arg)
158{
159 int ret = -ENOTTY;
160 int heartbeat_seconds;
161
162 switch (cmd) {
163 case WDIOC_GETSUPPORT:
164 ret = copy_to_user((struct watchdog_info *)arg, &ident,
165 sizeof(ident)) ? -EFAULT : 0;
166 break;
167
168 case WDIOC_GETSTATUS:
169 case WDIOC_GETBOOTSTATUS:
170 ret = put_user(0, (int *)arg);
171 break;
172
173 case WDIOC_KEEPALIVE:
174 jz4740_wdt_service();
175 return 0;
176
177 case WDIOC_SETTIMEOUT:
178 if (get_user(heartbeat_seconds, (int __user *)arg))
179 return -EFAULT;
180
181 jz4740_wdt_set_heartbeat(heartbeat_seconds);
182 return 0;
183
184 case WDIOC_GETTIMEOUT:
185 return put_user(heartbeat, (int *)arg);
186
187 default:
188 break;
189 }
190
191 return ret;
192}
193
194static int jz4740_wdt_release(struct inode *inode, struct file *file)
195{
196 jz4740_wdt_service();
197
198 if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status))
199 jz4740_wdt_disable();
200
201 clear_bit(WDT_IN_USE, &jz4740_wdt.status);
202 return 0;
203}
204
205static const struct file_operations jz4740_wdt_fops = {
206 .owner = THIS_MODULE,
207 .llseek = no_llseek,
208 .write = jz4740_wdt_write,
209 .unlocked_ioctl = jz4740_wdt_ioctl,
210 .open = jz4740_wdt_open,
211 .release = jz4740_wdt_release,
212};
213
214static struct miscdevice jz4740_wdt_miscdev = {
215 .minor = WATCHDOG_MINOR,
216 .name = "watchdog",
217 .fops = &jz4740_wdt_fops,
218};
219
220static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
221{
222 int ret = 0, size;
223 struct resource *res;
224 struct device *dev = &pdev->dev;
225
226 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
227 if (res == NULL) {
228 dev_err(dev, "failed to get memory region resource\n");
229 return -ENXIO;
230 }
231
232 size = resource_size(res);
233 jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name);
234 if (jz4740_wdt.mem == NULL) {
235 dev_err(dev, "failed to get memory region\n");
236 return -EBUSY;
237 }
238
239 jz4740_wdt.base = ioremap_nocache(res->start, size);
240 if (jz4740_wdt.base == NULL) {
241 dev_err(dev, "failed to map memory region\n");
242 ret = -EBUSY;
243 goto err_release_region;
244 }
245
246 jz4740_wdt.rtc_clk = clk_get(NULL, "rtc");
247 if (IS_ERR(jz4740_wdt.rtc_clk)) {
248 dev_err(dev, "cannot find RTC clock\n");
249 ret = PTR_ERR(jz4740_wdt.rtc_clk);
250 goto err_iounmap;
251 }
252
253 ret = misc_register(&jz4740_wdt_miscdev);
254 if (ret < 0) {
255 dev_err(dev, "cannot register misc device\n");
256 goto err_disable_clk;
257 }
258
259 return 0;
260
261err_disable_clk:
262 clk_put(jz4740_wdt.rtc_clk);
263err_iounmap:
264 iounmap(jz4740_wdt.base);
265err_release_region:
266 release_mem_region(jz4740_wdt.mem->start,
267 resource_size(jz4740_wdt.mem));
268 return ret;
269}
270
271
272static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
273{
274 jz4740_wdt_disable();
275 misc_deregister(&jz4740_wdt_miscdev);
276 clk_put(jz4740_wdt.rtc_clk);
277
278 iounmap(jz4740_wdt.base);
279 jz4740_wdt.base = NULL;
280
281 release_mem_region(jz4740_wdt.mem->start,
282 resource_size(jz4740_wdt.mem));
283 jz4740_wdt.mem = NULL;
284
285 return 0;
286}
287
288
289static struct platform_driver jz4740_wdt_driver = {
290 .probe = jz4740_wdt_probe,
291 .remove = __devexit_p(jz4740_wdt_remove),
292 .driver = {
293 .name = "jz4740-wdt",
294 .owner = THIS_MODULE,
295 },
296};
297
298
299static int __init jz4740_wdt_init(void)
300{
301 return platform_driver_register(&jz4740_wdt_driver);
302}
303module_init(jz4740_wdt_init);
304
305static void __exit jz4740_wdt_exit(void)
306{
307 platform_driver_unregister(&jz4740_wdt_driver);
308}
309module_exit(jz4740_wdt_exit);
310
311MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
312MODULE_DESCRIPTION("jz4740 Watchdog Driver");
313
314module_param(heartbeat, int, 0);
315MODULE_PARM_DESC(heartbeat,
316 "Watchdog heartbeat period in seconds from 1 to "
317 __MODULE_STRING(MAX_HEARTBEAT) ", default "
318 __MODULE_STRING(DEFAULT_HEARTBEAT));
319
320MODULE_LICENSE("GPL");
321MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
322MODULE_ALIAS("platform:jz4740-wdt");
diff --git a/drivers/watchdog/m548x_wdt.c b/drivers/watchdog/m54xx_wdt.c
index cabbcfe1c847..4d43286074aa 100644
--- a/drivers/watchdog/m548x_wdt.c
+++ b/drivers/watchdog/m54xx_wdt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/watchdog/m548x_wdt.c 2 * drivers/watchdog/m54xx_wdt.c
3 * 3 *
4 * Watchdog driver for ColdFire MCF548x processors 4 * Watchdog driver for ColdFire MCF547x & MCF548x processors
5 * Copyright 2010 (c) Philippe De Muyter <phdm@macqel.be> 5 * Copyright 2010 (c) Philippe De Muyter <phdm@macqel.be>
6 * 6 *
7 * Adapted from the IXP4xx watchdog driver, which carries these notices: 7 * Adapted from the IXP4xx watchdog driver, which carries these notices:
@@ -29,8 +29,8 @@
29#include <linux/uaccess.h> 29#include <linux/uaccess.h>
30 30
31#include <asm/coldfire.h> 31#include <asm/coldfire.h>
32#include <asm/m548xsim.h> 32#include <asm/m54xxsim.h>
33#include <asm/m548xgpt.h> 33#include <asm/m54xxgpt.h>
34 34
35static int nowayout = WATCHDOG_NOWAYOUT; 35static int nowayout = WATCHDOG_NOWAYOUT;
36static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ 36static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */
@@ -76,7 +76,7 @@ static void wdt_keepalive(void)
76 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); 76 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
77} 77}
78 78
79static int m548x_wdt_open(struct inode *inode, struct file *file) 79static int m54xx_wdt_open(struct inode *inode, struct file *file)
80{ 80{
81 if (test_and_set_bit(WDT_IN_USE, &wdt_status)) 81 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
82 return -EBUSY; 82 return -EBUSY;
@@ -86,7 +86,7 @@ static int m548x_wdt_open(struct inode *inode, struct file *file)
86 return nonseekable_open(inode, file); 86 return nonseekable_open(inode, file);
87} 87}
88 88
89static ssize_t m548x_wdt_write(struct file *file, const char *data, 89static ssize_t m54xx_wdt_write(struct file *file, const char *data,
90 size_t len, loff_t *ppos) 90 size_t len, loff_t *ppos)
91{ 91{
92 if (len) { 92 if (len) {
@@ -112,10 +112,10 @@ static ssize_t m548x_wdt_write(struct file *file, const char *data,
112static const struct watchdog_info ident = { 112static const struct watchdog_info ident = {
113 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | 113 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
114 WDIOF_KEEPALIVEPING, 114 WDIOF_KEEPALIVEPING,
115 .identity = "Coldfire M548x Watchdog", 115 .identity = "Coldfire M54xx Watchdog",
116}; 116};
117 117
118static long m548x_wdt_ioctl(struct file *file, unsigned int cmd, 118static long m54xx_wdt_ioctl(struct file *file, unsigned int cmd,
119 unsigned long arg) 119 unsigned long arg)
120{ 120{
121 int ret = -ENOTTY; 121 int ret = -ENOTTY;
@@ -161,7 +161,7 @@ static long m548x_wdt_ioctl(struct file *file, unsigned int cmd,
161 return ret; 161 return ret;
162} 162}
163 163
164static int m548x_wdt_release(struct inode *inode, struct file *file) 164static int m54xx_wdt_release(struct inode *inode, struct file *file)
165{ 165{
166 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) 166 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
167 wdt_disable(); 167 wdt_disable();
@@ -177,45 +177,45 @@ static int m548x_wdt_release(struct inode *inode, struct file *file)
177} 177}
178 178
179 179
180static const struct file_operations m548x_wdt_fops = { 180static const struct file_operations m54xx_wdt_fops = {
181 .owner = THIS_MODULE, 181 .owner = THIS_MODULE,
182 .llseek = no_llseek, 182 .llseek = no_llseek,
183 .write = m548x_wdt_write, 183 .write = m54xx_wdt_write,
184 .unlocked_ioctl = m548x_wdt_ioctl, 184 .unlocked_ioctl = m54xx_wdt_ioctl,
185 .open = m548x_wdt_open, 185 .open = m54xx_wdt_open,
186 .release = m548x_wdt_release, 186 .release = m54xx_wdt_release,
187}; 187};
188 188
189static struct miscdevice m548x_wdt_miscdev = { 189static struct miscdevice m54xx_wdt_miscdev = {
190 .minor = WATCHDOG_MINOR, 190 .minor = WATCHDOG_MINOR,
191 .name = "watchdog", 191 .name = "watchdog",
192 .fops = &m548x_wdt_fops, 192 .fops = &m54xx_wdt_fops,
193}; 193};
194 194
195static int __init m548x_wdt_init(void) 195static int __init m54xx_wdt_init(void)
196{ 196{
197 if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, 197 if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
198 "Coldfire M548x Watchdog")) { 198 "Coldfire M54xx Watchdog")) {
199 printk(KERN_WARNING 199 printk(KERN_WARNING
200 "Coldfire M548x Watchdog : I/O region busy\n"); 200 "Coldfire M54xx Watchdog : I/O region busy\n");
201 return -EBUSY; 201 return -EBUSY;
202 } 202 }
203 printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); 203 printk(KERN_INFO "ColdFire watchdog driver is loaded.\n");
204 204
205 return misc_register(&m548x_wdt_miscdev); 205 return misc_register(&m54xx_wdt_miscdev);
206} 206}
207 207
208static void __exit m548x_wdt_exit(void) 208static void __exit m54xx_wdt_exit(void)
209{ 209{
210 misc_deregister(&m548x_wdt_miscdev); 210 misc_deregister(&m54xx_wdt_miscdev);
211 release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); 211 release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4);
212} 212}
213 213
214module_init(m548x_wdt_init); 214module_init(m54xx_wdt_init);
215module_exit(m548x_wdt_exit); 215module_exit(m54xx_wdt_exit);
216 216
217MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>"); 217MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
218MODULE_DESCRIPTION("Coldfire M548x Watchdog"); 218MODULE_DESCRIPTION("Coldfire M54xx Watchdog");
219 219
220module_param(heartbeat, int, 0); 220module_param(heartbeat, int, 0);
221MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); 221MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)");
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 928035069396..1332b838cc58 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -54,7 +54,7 @@
54 54
55/* indexes */ /* size */ 55/* indexes */ /* size */
56#define ZFL_VERSION 0x02 /* 16 */ 56#define ZFL_VERSION 0x02 /* 16 */
57#define CONTROL 0x10 /* 16 */ 57#define CONTROL 0x10 /* 16 */
58#define STATUS 0x12 /* 8 */ 58#define STATUS 0x12 /* 8 */
59#define COUNTER_1 0x0C /* 16 */ 59#define COUNTER_1 0x0C /* 16 */
60#define COUNTER_2 0x0E /* 8 */ 60#define COUNTER_2 0x0E /* 8 */
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 3053ff05ca41..7a82ce5a6337 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -41,7 +41,7 @@ static int nowayout = WATCHDOG_NOWAYOUT;
41 * to ping the watchdog. 41 * to ping the watchdog.
42 */ 42 */
43#define MAX6369_WDSET (7 << 0) 43#define MAX6369_WDSET (7 << 0)
44#define MAX6369_WDI (1 << 3) 44#define MAX6369_WDI (1 << 3)
45 45
46static DEFINE_SPINLOCK(io_lock); 46static DEFINE_SPINLOCK(io_lock);
47 47
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 8fa213cdb499..6709d723e017 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -2,9 +2,9 @@
2 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface 2 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface
3 * 3 *
4 * Authors: Dave Updegraff <dave@cray.org> 4 * Authors: Dave Updegraff <dave@cray.org>
5 * Kumar Gala <galak@kernel.crashing.org> 5 * Kumar Gala <galak@kernel.crashing.org>
6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> 6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
7 * ..and from sc520_wdt 7 * ..and from sc520_wdt
8 * Copyright (c) 2008 MontaVista Software, Inc. 8 * Copyright (c) 2008 MontaVista Software, Inc.
9 * Anton Vorontsov <avorontsov@ru.mvista.com> 9 * Anton Vorontsov <avorontsov@ru.mvista.com>
10 * 10 *
@@ -185,15 +185,18 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
185 .fops = &mpc8xxx_wdt_fops, 185 .fops = &mpc8xxx_wdt_fops,
186}; 186};
187 187
188static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, 188static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
189 const struct of_device_id *match)
190{ 189{
191 int ret; 190 int ret;
192 struct device_node *np = ofdev->dev.of_node; 191 struct device_node *np = ofdev->dev.of_node;
193 struct mpc8xxx_wdt_type *wdt_type = match->data; 192 struct mpc8xxx_wdt_type *wdt_type;
194 u32 freq = fsl_get_sys_freq(); 193 u32 freq = fsl_get_sys_freq();
195 bool enabled; 194 bool enabled;
196 195
196 if (!ofdev->dev.of_match)
197 return -EINVAL;
198 wdt_type = match->data;
199
197 if (!freq || freq == -1) 200 if (!freq || freq == -1)
198 return -EINVAL; 201 return -EINVAL;
199 202
@@ -272,7 +275,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
272}; 275};
273MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); 276MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
274 277
275static struct of_platform_driver mpc8xxx_wdt_driver = { 278static struct platform_driver mpc8xxx_wdt_driver = {
276 .probe = mpc8xxx_wdt_probe, 279 .probe = mpc8xxx_wdt_probe,
277 .remove = __devexit_p(mpc8xxx_wdt_remove), 280 .remove = __devexit_p(mpc8xxx_wdt_remove),
278 .driver = { 281 .driver = {
@@ -308,13 +311,13 @@ module_init(mpc8xxx_wdt_init_late);
308 311
309static int __init mpc8xxx_wdt_init(void) 312static int __init mpc8xxx_wdt_init(void)
310{ 313{
311 return of_register_platform_driver(&mpc8xxx_wdt_driver); 314 return platform_driver_register(&mpc8xxx_wdt_driver);
312} 315}
313arch_initcall(mpc8xxx_wdt_init); 316arch_initcall(mpc8xxx_wdt_init);
314 317
315static void __exit mpc8xxx_wdt_exit(void) 318static void __exit mpc8xxx_wdt_exit(void)
316{ 319{
317 of_unregister_platform_driver(&mpc8xxx_wdt_driver); 320 platform_driver_unregister(&mpc8xxx_wdt_driver);
318} 321}
319module_exit(mpc8xxx_wdt_exit); 322module_exit(mpc8xxx_wdt_exit);
320 323
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index b8ec7aca3c8e..2b4af222b5f2 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -172,7 +172,7 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file)
172 172
173 /* 173 /*
174 * Shut off the timer. 174 * Shut off the timer.
175 * Lock it in if it's a module and we set nowayout 175 * Lock it in if it's a module and we set nowayout
176 */ 176 */
177 if (wdt->expect_close == 42) 177 if (wdt->expect_close == 42)
178 mpcore_wdt_stop(wdt); 178 mpcore_wdt_stop(wdt);
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index 08e8a6ab74e1..5ec5ac1f7878 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -190,19 +190,19 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
190} 190}
191 191
192static const struct file_operations mtx1_wdt_fops = { 192static const struct file_operations mtx1_wdt_fops = {
193 .owner = THIS_MODULE, 193 .owner = THIS_MODULE,
194 .llseek = no_llseek, 194 .llseek = no_llseek,
195 .unlocked_ioctl = mtx1_wdt_ioctl, 195 .unlocked_ioctl = mtx1_wdt_ioctl,
196 .open = mtx1_wdt_open, 196 .open = mtx1_wdt_open,
197 .write = mtx1_wdt_write, 197 .write = mtx1_wdt_write,
198 .release = mtx1_wdt_release, 198 .release = mtx1_wdt_release,
199}; 199};
200 200
201 201
202static struct miscdevice mtx1_wdt_misc = { 202static struct miscdevice mtx1_wdt_misc = {
203 .minor = WATCHDOG_MINOR, 203 .minor = WATCHDOG_MINOR,
204 .name = "watchdog", 204 .name = "watchdog",
205 .fops = &mtx1_wdt_fops, 205 .fops = &mtx1_wdt_fops,
206}; 206};
207 207
208 208
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
index 1a50aa7079bf..267377a5a83e 100644
--- a/drivers/watchdog/nv_tco.c
+++ b/drivers/watchdog/nv_tco.c
@@ -289,7 +289,7 @@ static struct miscdevice nv_tco_miscdev = {
289 * register a pci_driver, because someone else might one day 289 * register a pci_driver, because someone else might one day
290 * want to register another driver on the same PCI id. 290 * want to register another driver on the same PCI id.
291 */ 291 */
292static struct pci_device_id tco_pci_tbl[] = { 292static DEFINE_PCI_DEVICE_TABLE(tco_pci_tbl) = {
293 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS, 293 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
294 PCI_ANY_ID, PCI_ANY_ID, }, 294 PCI_ANY_ID, PCI_ANY_ID, },
295 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, 295 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index fc02ec6a0386..09b774cf75b9 100644
--- a/drivers/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
@@ -44,7 +44,7 @@
44 * months before firing. These limits work without scaling, 44 * months before firing. These limits work without scaling,
45 * with the 60 second default assumed by most tools and docs. 45 * with the 60 second default assumed by most tools and docs.
46 */ 46 */
47#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */ 47#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */
48#define TIMER_MARGIN_DEFAULT 60 /* 60 secs */ 48#define TIMER_MARGIN_DEFAULT 60 /* 60 secs */
49#define TIMER_MARGIN_MIN 1 49#define TIMER_MARGIN_MIN 1
50 50
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 3a56bc360924..139d773300c6 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -514,7 +514,7 @@ static struct miscdevice pc87413_miscdev = {
514/* -- Module init functions -------------------------------------*/ 514/* -- Module init functions -------------------------------------*/
515 515
516/** 516/**
517 * pc87413_init: module's "constructor" 517 * pc87413_init: module's "constructor"
518 * 518 *
519 * Set up the WDT watchdog board. All we have to do is grab the 519 * Set up the WDT watchdog board. All we have to do is grab the
520 * resources we require and bitch if anyone beat us to them. 520 * resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 64374d636f09..b8d14f88f0b5 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -817,7 +817,7 @@ static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
817 cards_found--; 817 cards_found--;
818} 818}
819 819
820static struct pci_device_id pcipcwd_pci_tbl[] = { 820static DEFINE_PCI_DEVICE_TABLE(pcipcwd_pci_tbl) = {
821 { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD, 821 { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD,
822 PCI_ANY_ID, PCI_ANY_ID, }, 822 PCI_ANY_ID, PCI_ANY_ID, },
823 { 0 }, /* End of list */ 823 { 0 }, /* End of list */
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index bf5b97c546eb..c7cf4cbf8ab3 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -4,7 +4,7 @@
4 * Watchdog driver for PNX4008 board 4 * Watchdog driver for PNX4008 board
5 * 5 *
6 * Authors: Dmitry Chigirev <source@mvista.com>, 6 * Authors: Dmitry Chigirev <source@mvista.com>,
7 * Vitaly Wool <vitalywool@gmail.com> 7 * Vitaly Wool <vitalywool@gmail.com>
8 * Based on sa1100 driver, 8 * Based on sa1100 driver,
9 * Copyright (C) 2000 Oleg Drokin <green@crimea.edu> 9 * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
10 * 10 *
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 3faee1ae64bd..109b533896b7 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -172,8 +172,7 @@ static struct miscdevice riowd_miscdev = {
172 .fops = &riowd_fops 172 .fops = &riowd_fops
173}; 173};
174 174
175static int __devinit riowd_probe(struct platform_device *op, 175static int __devinit riowd_probe(struct platform_device *op)
176 const struct of_device_id *match)
177{ 176{
178 struct riowd *p; 177 struct riowd *p;
179 int err = -EINVAL; 178 int err = -EINVAL;
@@ -238,7 +237,7 @@ static const struct of_device_id riowd_match[] = {
238}; 237};
239MODULE_DEVICE_TABLE(of, riowd_match); 238MODULE_DEVICE_TABLE(of, riowd_match);
240 239
241static struct of_platform_driver riowd_driver = { 240static struct platform_driver riowd_driver = {
242 .driver = { 241 .driver = {
243 .name = DRIVER_NAME, 242 .name = DRIVER_NAME,
244 .owner = THIS_MODULE, 243 .owner = THIS_MODULE,
@@ -250,12 +249,12 @@ static struct of_platform_driver riowd_driver = {
250 249
251static int __init riowd_init(void) 250static int __init riowd_init(void)
252{ 251{
253 return of_register_platform_driver(&riowd_driver); 252 return platform_driver_register(&riowd_driver);
254} 253}
255 254
256static void __exit riowd_exit(void) 255static void __exit riowd_exit(void)
257{ 256{
258 of_unregister_platform_driver(&riowd_driver); 257 platform_driver_unregister(&riowd_driver);
259} 258}
260 259
261module_init(riowd_init); 260module_init(riowd_init);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index ae53662c29bc..25b39bf35925 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -224,7 +224,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
224{ 224{
225 /* 225 /*
226 * Shut off the timer. 226 * Shut off the timer.
227 * Lock it in if it's a module and we set nowayout 227 * Lock it in if it's a module and we set nowayout
228 */ 228 */
229 229
230 if (expect_close == 42) 230 if (expect_close == 42)
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
index 68e2e2d6f73d..514ec23050f7 100644
--- a/drivers/watchdog/sbc8360.c
+++ b/drivers/watchdog/sbc8360.c
@@ -114,7 +114,7 @@ static char expect_close;
114 * C | 6.5s 65s 650s 1300s 114 * C | 6.5s 65s 650s 1300s
115 * D | 7s 70s 700s 1400s 115 * D | 7s 70s 700s 1400s
116 * E | 7.5s 75s 750s 1500s 116 * E | 7.5s 75s 750s 1500s
117 * F | 8s 80s 800s 1600s 117 * F | 8s 80s 800s 1600s
118 * 118 *
119 * Another way to say the same things is: 119 * Another way to say the same things is:
120 * For N=1, Timeout = (M+1) * 0.5s 120 * For N=1, Timeout = (M+1) * 0.5s
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c
index c7d67e9a7465..d5d399464599 100644
--- a/drivers/watchdog/sbc_fitpc2_wdt.c
+++ b/drivers/watchdog/sbc_fitpc2_wdt.c
@@ -41,7 +41,7 @@ static DEFINE_MUTEX(wdt_lock);
41#define IFACE_ON_COMMAND 1 41#define IFACE_ON_COMMAND 1
42#define REBOOT_COMMAND 2 42#define REBOOT_COMMAND 2
43 43
44#define WATCHDOG_NAME "SBC-FITPC2 Watchdog" 44#define WATCHDOG_NAME "SBC-FITPC2 Watchdog"
45 45
46static void wdt_send_data(unsigned char command, unsigned char data) 46static void wdt_send_data(unsigned char command, unsigned char data)
47{ 47{
@@ -201,11 +201,14 @@ static struct miscdevice fitpc2_wdt_miscdev = {
201static int __init fitpc2_wdt_init(void) 201static int __init fitpc2_wdt_init(void)
202{ 202{
203 int err; 203 int err;
204 const char *brd_name;
204 205
205 if (!strstr(dmi_get_system_info(DMI_BOARD_NAME), "SBC-FITPC2")) 206 brd_name = dmi_get_system_info(DMI_BOARD_NAME);
207
208 if (!brd_name || !strstr(brd_name, "SBC-FITPC2"))
206 return -ENODEV; 209 return -ENODEV;
207 210
208 pr_info("%s found\n", dmi_get_system_info(DMI_BOARD_NAME)); 211 pr_info("%s found\n", brd_name);
209 212
210 if (!request_region(COMMAND_PORT, 1, WATCHDOG_NAME)) { 213 if (!request_region(COMMAND_PORT, 1, WATCHDOG_NAME)) {
211 pr_err("I/O address 0x%04x already in use\n", COMMAND_PORT); 214 pr_err("I/O address 0x%04x already in use\n", COMMAND_PORT);
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 0461858e07d0..b61ab1c54293 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
508 sch311x_sio_outb(sio_config_port, 0x07, 0x0a); 508 sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
509 509
510 /* Check if Logical Device Register is currently active */ 510 /* Check if Logical Device Register is currently active */
511 if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) 511 if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
512 printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); 512 printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n");
513 513
514 /* Get the base address of the runtime registers */ 514 /* Get the base address of the runtime registers */
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 6fc74065abee..4e3e7eb5919c 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * drivers/char/watchdog/shwdt.c 2 * drivers/watchdog/shwdt.c
3 * 3 *
4 * Watchdog driver for integrated watchdog in the SuperH processors. 4 * Watchdog driver for integrated watchdog in the SuperH processors.
5 * 5 *
6 * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org> 6 * Copyright (C) 2001 - 2010 Paul Mundt <lethal@linux-sh.org>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -19,6 +19,7 @@
19 */ 19 */
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/moduleparam.h> 21#include <linux/moduleparam.h>
22#include <linux/platform_device.h>
22#include <linux/init.h> 23#include <linux/init.h>
23#include <linux/types.h> 24#include <linux/types.h>
24#include <linux/miscdevice.h> 25#include <linux/miscdevice.h>
@@ -28,11 +29,12 @@
28#include <linux/ioport.h> 29#include <linux/ioport.h>
29#include <linux/fs.h> 30#include <linux/fs.h>
30#include <linux/mm.h> 31#include <linux/mm.h>
32#include <linux/slab.h>
31#include <linux/io.h> 33#include <linux/io.h>
32#include <linux/uaccess.h> 34#include <linux/uaccess.h>
33#include <asm/watchdog.h> 35#include <asm/watchdog.h>
34 36
35#define PFX "shwdt: " 37#define DRV_NAME "sh-wdt"
36 38
37/* 39/*
38 * Default clock division ratio is 5.25 msecs. For an additional table of 40 * Default clock division ratio is 5.25 msecs. For an additional table of
@@ -62,37 +64,36 @@
62 * misses its deadline, the kernel timer will allow the WDT to overflow. 64 * misses its deadline, the kernel timer will allow the WDT to overflow.
63 */ 65 */
64static int clock_division_ratio = WTCSR_CKS_4096; 66static int clock_division_ratio = WTCSR_CKS_4096;
65
66#define next_ping_period(cks) msecs_to_jiffies(cks - 4) 67#define next_ping_period(cks) msecs_to_jiffies(cks - 4)
67 68
68static void sh_wdt_ping(unsigned long data);
69
70static unsigned long shwdt_is_open;
71static const struct watchdog_info sh_wdt_info; 69static const struct watchdog_info sh_wdt_info;
72static char shwdt_expect_close; 70static struct platform_device *sh_wdt_dev;
73static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
74static unsigned long next_heartbeat;
75static DEFINE_SPINLOCK(shwdt_lock); 71static DEFINE_SPINLOCK(shwdt_lock);
76 72
77#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 73#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
78static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 74static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
79
80static int nowayout = WATCHDOG_NOWAYOUT; 75static int nowayout = WATCHDOG_NOWAYOUT;
76static unsigned long next_heartbeat;
81 77
82/** 78struct sh_wdt {
83 * sh_wdt_start - Start the Watchdog 79 void __iomem *base;
84 * 80 struct device *dev;
85 * Starts the watchdog. 81
86 */ 82 struct timer_list timer;
87static void sh_wdt_start(void) 83
84 unsigned long enabled;
85 char expect_close;
86};
87
88static void sh_wdt_start(struct sh_wdt *wdt)
88{ 89{
89 __u8 csr;
90 unsigned long flags; 90 unsigned long flags;
91 u8 csr;
91 92
92 spin_lock_irqsave(&shwdt_lock, flags); 93 spin_lock_irqsave(&shwdt_lock, flags);
93 94
94 next_heartbeat = jiffies + (heartbeat * HZ); 95 next_heartbeat = jiffies + (heartbeat * HZ);
95 mod_timer(&timer, next_ping_period(clock_division_ratio)); 96 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
96 97
97 csr = sh_wdt_read_csr(); 98 csr = sh_wdt_read_csr();
98 csr |= WTCSR_WT | clock_division_ratio; 99 csr |= WTCSR_WT | clock_division_ratio;
@@ -114,15 +115,6 @@ static void sh_wdt_start(void)
114 sh_wdt_write_csr(csr); 115 sh_wdt_write_csr(csr);
115 116
116#ifdef CONFIG_CPU_SH2 117#ifdef CONFIG_CPU_SH2
117 /*
118 * Whoever came up with the RSTCSR semantics must've been smoking
119 * some of the good stuff, since in addition to the WTCSR/WTCNT write
120 * brain-damage, it's managed to fuck things up one step further..
121 *
122 * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
123 * but if we want to touch RSTE or RSTS, the upper byte has to be
124 * 0x5a..
125 */
126 csr = sh_wdt_read_rstcsr(); 118 csr = sh_wdt_read_rstcsr();
127 csr &= ~RSTCSR_RSTS; 119 csr &= ~RSTCSR_RSTS;
128 sh_wdt_write_rstcsr(csr); 120 sh_wdt_write_rstcsr(csr);
@@ -130,30 +122,23 @@ static void sh_wdt_start(void)
130 spin_unlock_irqrestore(&shwdt_lock, flags); 122 spin_unlock_irqrestore(&shwdt_lock, flags);
131} 123}
132 124
133/** 125static void sh_wdt_stop(struct sh_wdt *wdt)
134 * sh_wdt_stop - Stop the Watchdog
135 * Stops the watchdog.
136 */
137static void sh_wdt_stop(void)
138{ 126{
139 __u8 csr;
140 unsigned long flags; 127 unsigned long flags;
128 u8 csr;
141 129
142 spin_lock_irqsave(&shwdt_lock, flags); 130 spin_lock_irqsave(&shwdt_lock, flags);
143 131
144 del_timer(&timer); 132 del_timer(&wdt->timer);
145 133
146 csr = sh_wdt_read_csr(); 134 csr = sh_wdt_read_csr();
147 csr &= ~WTCSR_TME; 135 csr &= ~WTCSR_TME;
148 sh_wdt_write_csr(csr); 136 sh_wdt_write_csr(csr);
137
149 spin_unlock_irqrestore(&shwdt_lock, flags); 138 spin_unlock_irqrestore(&shwdt_lock, flags);
150} 139}
151 140
152/** 141static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
153 * sh_wdt_keepalive - Keep the Userspace Watchdog Alive
154 * The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
155 */
156static inline void sh_wdt_keepalive(void)
157{ 142{
158 unsigned long flags; 143 unsigned long flags;
159 144
@@ -162,10 +147,6 @@ static inline void sh_wdt_keepalive(void)
162 spin_unlock_irqrestore(&shwdt_lock, flags); 147 spin_unlock_irqrestore(&shwdt_lock, flags);
163} 148}
164 149
165/**
166 * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
167 * Set the Userspace Watchdog heartbeat
168 */
169static int sh_wdt_set_heartbeat(int t) 150static int sh_wdt_set_heartbeat(int t)
170{ 151{
171 unsigned long flags; 152 unsigned long flags;
@@ -179,19 +160,14 @@ static int sh_wdt_set_heartbeat(int t)
179 return 0; 160 return 0;
180} 161}
181 162
182/**
183 * sh_wdt_ping - Ping the Watchdog
184 * @data: Unused
185 *
186 * Clears overflow bit, resets timer counter.
187 */
188static void sh_wdt_ping(unsigned long data) 163static void sh_wdt_ping(unsigned long data)
189{ 164{
165 struct sh_wdt *wdt = (struct sh_wdt *)data;
190 unsigned long flags; 166 unsigned long flags;
191 167
192 spin_lock_irqsave(&shwdt_lock, flags); 168 spin_lock_irqsave(&shwdt_lock, flags);
193 if (time_before(jiffies, next_heartbeat)) { 169 if (time_before(jiffies, next_heartbeat)) {
194 __u8 csr; 170 u8 csr;
195 171
196 csr = sh_wdt_read_csr(); 172 csr = sh_wdt_read_csr();
197 csr &= ~WTCSR_IOVF; 173 csr &= ~WTCSR_IOVF;
@@ -199,148 +175,76 @@ static void sh_wdt_ping(unsigned long data)
199 175
200 sh_wdt_write_cnt(0); 176 sh_wdt_write_cnt(0);
201 177
202 mod_timer(&timer, next_ping_period(clock_division_ratio)); 178 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
203 } else 179 } else
204 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " 180 dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
205 "the watchdog\n"); 181 "the watchdog\n");
206 spin_unlock_irqrestore(&shwdt_lock, flags); 182 spin_unlock_irqrestore(&shwdt_lock, flags);
207} 183}
208 184
209/**
210 * sh_wdt_open - Open the Device
211 * @inode: inode of device
212 * @file: file handle of device
213 *
214 * Watchdog device is opened and started.
215 */
216static int sh_wdt_open(struct inode *inode, struct file *file) 185static int sh_wdt_open(struct inode *inode, struct file *file)
217{ 186{
218 if (test_and_set_bit(0, &shwdt_is_open)) 187 struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
188
189 if (test_and_set_bit(0, &wdt->enabled))
219 return -EBUSY; 190 return -EBUSY;
220 if (nowayout) 191 if (nowayout)
221 __module_get(THIS_MODULE); 192 __module_get(THIS_MODULE);
222 193
223 sh_wdt_start(); 194 file->private_data = wdt;
195
196 sh_wdt_start(wdt);
224 197
225 return nonseekable_open(inode, file); 198 return nonseekable_open(inode, file);
226} 199}
227 200
228/**
229 * sh_wdt_close - Close the Device
230 * @inode: inode of device
231 * @file: file handle of device
232 *
233 * Watchdog device is closed and stopped.
234 */
235static int sh_wdt_close(struct inode *inode, struct file *file) 201static int sh_wdt_close(struct inode *inode, struct file *file)
236{ 202{
237 if (shwdt_expect_close == 42) { 203 struct sh_wdt *wdt = file->private_data;
238 sh_wdt_stop(); 204
205 if (wdt->expect_close == 42) {
206 sh_wdt_stop(wdt);
239 } else { 207 } else {
240 printk(KERN_CRIT PFX "Unexpected close, not " 208 dev_crit(wdt->dev, "Unexpected close, not "
241 "stopping watchdog!\n"); 209 "stopping watchdog!\n");
242 sh_wdt_keepalive(); 210 sh_wdt_keepalive(wdt);
243 } 211 }
244 212
245 clear_bit(0, &shwdt_is_open); 213 clear_bit(0, &wdt->enabled);
246 shwdt_expect_close = 0; 214 wdt->expect_close = 0;
247 215
248 return 0; 216 return 0;
249} 217}
250 218
251/**
252 * sh_wdt_write - Write to Device
253 * @file: file handle of device
254 * @buf: buffer to write
255 * @count: length of buffer
256 * @ppos: offset
257 *
258 * Pings the watchdog on write.
259 */
260static ssize_t sh_wdt_write(struct file *file, const char *buf, 219static ssize_t sh_wdt_write(struct file *file, const char *buf,
261 size_t count, loff_t *ppos) 220 size_t count, loff_t *ppos)
262{ 221{
222 struct sh_wdt *wdt = file->private_data;
223
263 if (count) { 224 if (count) {
264 if (!nowayout) { 225 if (!nowayout) {
265 size_t i; 226 size_t i;
266 227
267 shwdt_expect_close = 0; 228 wdt->expect_close = 0;
268 229
269 for (i = 0; i != count; i++) { 230 for (i = 0; i != count; i++) {
270 char c; 231 char c;
271 if (get_user(c, buf + i)) 232 if (get_user(c, buf + i))
272 return -EFAULT; 233 return -EFAULT;
273 if (c == 'V') 234 if (c == 'V')
274 shwdt_expect_close = 42; 235 wdt->expect_close = 42;
275 } 236 }
276 } 237 }
277 sh_wdt_keepalive(); 238 sh_wdt_keepalive(wdt);
278 } 239 }
279 240
280 return count; 241 return count;
281} 242}
282 243
283/**
284 * sh_wdt_mmap - map WDT/CPG registers into userspace
285 * @file: file structure for the device
286 * @vma: VMA to map the registers into
287 *
288 * A simple mmap() implementation for the corner cases where the counter
289 * needs to be mapped in userspace directly. Due to the relatively small
290 * size of the area, neighbouring registers not necessarily tied to the
291 * CPG will also be accessible through the register page, so this remains
292 * configurable for users that really know what they're doing.
293 *
294 * Additionaly, the register page maps in the CPG register base relative
295 * to the nearest page-aligned boundary, which requires that userspace do
296 * the appropriate CPU subtype math for calculating the page offset for
297 * the counter value.
298 */
299static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
300{
301 int ret = -ENOSYS;
302
303#ifdef CONFIG_SH_WDT_MMAP
304 unsigned long addr;
305
306 /* Only support the simple cases where we map in a register page. */
307 if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
308 return -EINVAL;
309
310 /*
311 * Pick WTCNT as the start, it's usually the first register after the
312 * FRQCR, and neither one are generally page-aligned out of the box.
313 */
314 addr = WTCNT & ~(PAGE_SIZE - 1);
315
316 vma->vm_flags |= VM_IO;
317 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
318
319 if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
320 PAGE_SIZE, vma->vm_page_prot)) {
321 printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
322 __func__);
323 return -EAGAIN;
324 }
325
326 ret = 0;
327#endif
328
329 return ret;
330}
331
332/**
333 * sh_wdt_ioctl - Query Device
334 * @file: file handle of device
335 * @cmd: watchdog command
336 * @arg: argument
337 *
338 * Query basic information from the device or ping it, as outlined by the
339 * watchdog API.
340 */
341static long sh_wdt_ioctl(struct file *file, unsigned int cmd, 244static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
342 unsigned long arg) 245 unsigned long arg)
343{ 246{
247 struct sh_wdt *wdt = file->private_data;
344 int new_heartbeat; 248 int new_heartbeat;
345 int options, retval = -EINVAL; 249 int options, retval = -EINVAL;
346 250
@@ -356,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
356 return -EFAULT; 260 return -EFAULT;
357 261
358 if (options & WDIOS_DISABLECARD) { 262 if (options & WDIOS_DISABLECARD) {
359 sh_wdt_stop(); 263 sh_wdt_stop(wdt);
360 retval = 0; 264 retval = 0;
361 } 265 }
362 266
363 if (options & WDIOS_ENABLECARD) { 267 if (options & WDIOS_ENABLECARD) {
364 sh_wdt_start(); 268 sh_wdt_start(wdt);
365 retval = 0; 269 retval = 0;
366 } 270 }
367 271
368 return retval; 272 return retval;
369 case WDIOC_KEEPALIVE: 273 case WDIOC_KEEPALIVE:
370 sh_wdt_keepalive(); 274 sh_wdt_keepalive(wdt);
371 return 0; 275 return 0;
372 case WDIOC_SETTIMEOUT: 276 case WDIOC_SETTIMEOUT:
373 if (get_user(new_heartbeat, (int *)arg)) 277 if (get_user(new_heartbeat, (int *)arg))
@@ -376,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
376 if (sh_wdt_set_heartbeat(new_heartbeat)) 280 if (sh_wdt_set_heartbeat(new_heartbeat))
377 return -EINVAL; 281 return -EINVAL;
378 282
379 sh_wdt_keepalive(); 283 sh_wdt_keepalive(wdt);
380 /* Fall */ 284 /* Fall */
381 case WDIOC_GETTIMEOUT: 285 case WDIOC_GETTIMEOUT:
382 return put_user(heartbeat, (int *)arg); 286 return put_user(heartbeat, (int *)arg);
@@ -386,20 +290,13 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
386 return 0; 290 return 0;
387} 291}
388 292
389/**
390 * sh_wdt_notify_sys - Notifier Handler
391 * @this: notifier block
392 * @code: notifier event
393 * @unused: unused
394 *
395 * Handles specific events, such as turning off the watchdog during a
396 * shutdown event.
397 */
398static int sh_wdt_notify_sys(struct notifier_block *this, 293static int sh_wdt_notify_sys(struct notifier_block *this,
399 unsigned long code, void *unused) 294 unsigned long code, void *unused)
400{ 295{
296 struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
297
401 if (code == SYS_DOWN || code == SYS_HALT) 298 if (code == SYS_DOWN || code == SYS_HALT)
402 sh_wdt_stop(); 299 sh_wdt_stop(wdt);
403 300
404 return NOTIFY_DONE; 301 return NOTIFY_DONE;
405} 302}
@@ -411,7 +308,6 @@ static const struct file_operations sh_wdt_fops = {
411 .unlocked_ioctl = sh_wdt_ioctl, 308 .unlocked_ioctl = sh_wdt_ioctl,
412 .open = sh_wdt_open, 309 .open = sh_wdt_open,
413 .release = sh_wdt_close, 310 .release = sh_wdt_close,
414 .mmap = sh_wdt_mmap,
415}; 311};
416 312
417static const struct watchdog_info sh_wdt_info = { 313static const struct watchdog_info sh_wdt_info = {
@@ -431,66 +327,148 @@ static struct miscdevice sh_wdt_miscdev = {
431 .fops = &sh_wdt_fops, 327 .fops = &sh_wdt_fops,
432}; 328};
433 329
434/** 330static int __devinit sh_wdt_probe(struct platform_device *pdev)
435 * sh_wdt_init - Initialize module
436 * Registers the device and notifier handler. Actual device
437 * initialization is handled by sh_wdt_open().
438 */
439static int __init sh_wdt_init(void)
440{ 331{
332 struct sh_wdt *wdt;
333 struct resource *res;
441 int rc; 334 int rc;
442 335
443 if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) { 336 /*
444 clock_division_ratio = WTCSR_CKS_4096; 337 * As this driver only covers the global watchdog case, reject
445 printk(KERN_INFO PFX 338 * any attempts to register per-CPU watchdogs.
446 "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", 339 */
447 clock_division_ratio); 340 if (pdev->id != -1)
341 return -EINVAL;
342
343 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
344 if (unlikely(!res))
345 return -EINVAL;
346
347 if (!devm_request_mem_region(&pdev->dev, res->start,
348 resource_size(res), DRV_NAME))
349 return -EBUSY;
350
351 wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
352 if (unlikely(!wdt)) {
353 rc = -ENOMEM;
354 goto out_release;
448 } 355 }
449 356
450 rc = sh_wdt_set_heartbeat(heartbeat); 357 wdt->dev = &pdev->dev;
451 if (unlikely(rc)) { 358
452 heartbeat = WATCHDOG_HEARTBEAT; 359 wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
453 printk(KERN_INFO PFX 360 if (unlikely(!wdt->base)) {
454 "heartbeat value must be 1<=x<=3600, using %d\n", 361 rc = -ENXIO;
455 heartbeat); 362 goto out_err;
456 } 363 }
457 364
458 rc = register_reboot_notifier(&sh_wdt_notifier); 365 rc = register_reboot_notifier(&sh_wdt_notifier);
459 if (unlikely(rc)) { 366 if (unlikely(rc)) {
460 printk(KERN_ERR PFX 367 dev_err(&pdev->dev,
461 "Can't register reboot notifier (err=%d)\n", rc); 368 "Can't register reboot notifier (err=%d)\n", rc);
462 return rc; 369 goto out_unmap;
463 } 370 }
464 371
372 sh_wdt_miscdev.parent = wdt->dev;
373
465 rc = misc_register(&sh_wdt_miscdev); 374 rc = misc_register(&sh_wdt_miscdev);
466 if (unlikely(rc)) { 375 if (unlikely(rc)) {
467 printk(KERN_ERR PFX 376 dev_err(&pdev->dev,
468 "Can't register miscdev on minor=%d (err=%d)\n", 377 "Can't register miscdev on minor=%d (err=%d)\n",
469 sh_wdt_miscdev.minor, rc); 378 sh_wdt_miscdev.minor, rc);
470 unregister_reboot_notifier(&sh_wdt_notifier); 379 goto out_unreg;
471 return rc;
472 } 380 }
473 381
474 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 382 init_timer(&wdt->timer);
475 heartbeat, nowayout); 383 wdt->timer.function = sh_wdt_ping;
384 wdt->timer.data = (unsigned long)wdt;
385 wdt->timer.expires = next_ping_period(clock_division_ratio);
386
387 platform_set_drvdata(pdev, wdt);
388 sh_wdt_dev = pdev;
389
390 dev_info(&pdev->dev, "initialized.\n");
476 391
477 return 0; 392 return 0;
393
394out_unreg:
395 unregister_reboot_notifier(&sh_wdt_notifier);
396out_unmap:
397 devm_iounmap(&pdev->dev, wdt->base);
398out_err:
399 devm_kfree(&pdev->dev, wdt);
400out_release:
401 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
402
403 return rc;
478} 404}
479 405
480/** 406static int __devexit sh_wdt_remove(struct platform_device *pdev)
481 * sh_wdt_exit - Deinitialize module
482 * Unregisters the device and notifier handler. Actual device
483 * deinitialization is handled by sh_wdt_close().
484 */
485static void __exit sh_wdt_exit(void)
486{ 407{
408 struct sh_wdt *wdt = platform_get_drvdata(pdev);
409 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
410
411 platform_set_drvdata(pdev, NULL);
412
487 misc_deregister(&sh_wdt_miscdev); 413 misc_deregister(&sh_wdt_miscdev);
414
415 sh_wdt_dev = NULL;
416
488 unregister_reboot_notifier(&sh_wdt_notifier); 417 unregister_reboot_notifier(&sh_wdt_notifier);
418 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
419 devm_iounmap(&pdev->dev, wdt->base);
420 devm_kfree(&pdev->dev, wdt);
421
422 return 0;
489} 423}
490 424
425static struct platform_driver sh_wdt_driver = {
426 .driver = {
427 .name = DRV_NAME,
428 .owner = THIS_MODULE,
429 },
430
431 .probe = sh_wdt_probe,
432 .remove = __devexit_p(sh_wdt_remove),
433};
434
435static int __init sh_wdt_init(void)
436{
437 int rc;
438
439 if (unlikely(clock_division_ratio < 0x5 ||
440 clock_division_ratio > 0x7)) {
441 clock_division_ratio = WTCSR_CKS_4096;
442
443 pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
444 DRV_NAME, clock_division_ratio);
445 }
446
447 rc = sh_wdt_set_heartbeat(heartbeat);
448 if (unlikely(rc)) {
449 heartbeat = WATCHDOG_HEARTBEAT;
450
451 pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
452 DRV_NAME, heartbeat);
453 }
454
455 pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
456 DRV_NAME, heartbeat, nowayout);
457
458 return platform_driver_register(&sh_wdt_driver);
459}
460
461static void __exit sh_wdt_exit(void)
462{
463 platform_driver_unregister(&sh_wdt_driver);
464}
465module_init(sh_wdt_init);
466module_exit(sh_wdt_exit);
467
491MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); 468MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
492MODULE_DESCRIPTION("SuperH watchdog driver"); 469MODULE_DESCRIPTION("SuperH watchdog driver");
493MODULE_LICENSE("GPL"); 470MODULE_LICENSE("GPL");
471MODULE_ALIAS("platform:" DRV_NAME);
494MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 472MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
495 473
496module_param(clock_division_ratio, int, 0); 474module_param(clock_division_ratio, int, 0);
@@ -507,6 +485,3 @@ module_param(nowayout, int, 0);
507MODULE_PARM_DESC(nowayout, 485MODULE_PARM_DESC(nowayout,
508 "Watchdog cannot be stopped once started (default=" 486 "Watchdog cannot be stopped once started (default="
509 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 487 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
510
511module_init(sh_wdt_init);
512module_exit(sh_wdt_exit);
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
index 8a1f0bc3e271..df88cfa05f35 100644
--- a/drivers/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -434,11 +434,11 @@ static long wb_smsc_wdt_ioctl(struct file *file,
434 } uarg; 434 } uarg;
435 435
436 static const struct watchdog_info ident = { 436 static const struct watchdog_info ident = {
437 .options = WDIOF_KEEPALIVEPING | 437 .options = WDIOF_KEEPALIVEPING |
438 WDIOF_SETTIMEOUT | 438 WDIOF_SETTIMEOUT |
439 WDIOF_MAGICCLOSE, 439 WDIOF_MAGICCLOSE,
440 .firmware_version = 0, 440 .firmware_version = 0,
441 .identity = "SMsC 37B787 Watchdog", 441 .identity = "SMsC 37B787 Watchdog",
442 }; 442 };
443 443
444 uarg.i = (int __user *)arg; 444 uarg.i = (int __user *)arg;
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 833f49f43d43..100b114e3c3c 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -151,7 +151,7 @@ static int softdog_release(struct inode *inode, struct file *file)
151{ 151{
152 /* 152 /*
153 * Shut off the timer. 153 * Shut off the timer.
154 * Lock it in if it's a module and we set nowayout 154 * Lock it in if it's a module and we set nowayout
155 */ 155 */
156 if (expect_close == 42) { 156 if (expect_close == 42) {
157 softdog_stop(); 157 softdog_stop();
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 808372883e88..1bc493848ed4 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -259,7 +259,7 @@ static struct miscdevice sp5100_tco_miscdev = {
259 * register a pci_driver, because someone else might 259 * register a pci_driver, because someone else might
260 * want to register another driver on the same PCI id. 260 * want to register another driver on the same PCI id.
261 */ 261 */
262static struct pci_device_id sp5100_tco_pci_tbl[] = { 262static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
263 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, 263 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
264 PCI_ANY_ID, }, 264 PCI_ANY_ID, },
265 { 0, }, /* End of list */ 265 { 0, }, /* End of list */
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 9127eda2145b..0a0efe713bc8 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -278,7 +278,7 @@ static struct miscdevice sp805_wdt_miscdev = {
278}; 278};
279 279
280static int __devinit 280static int __devinit
281sp805_wdt_probe(struct amba_device *adev, struct amba_id *id) 281sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
282{ 282{
283 int ret = 0; 283 int ret = 0;
284 284
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 18cdeb4c4258..5a90a4a871dd 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -68,7 +68,7 @@ struct platform_device *ts72xx_wdt_pdev;
68 * to control register): 68 * to control register):
69 * value description 69 * value description
70 * ------------------------- 70 * -------------------------
71 * 0x00 watchdog disabled 71 * 0x00 watchdog disabled
72 * 0x01 250ms 72 * 0x01 250ms
73 * 0x02 500ms 73 * 0x02 500ms
74 * 0x03 1s 74 * 0x03 1s
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c
index a6c12dec91a1..be9c4d839e15 100644
--- a/drivers/watchdog/w83697ug_wdt.c
+++ b/drivers/watchdog/w83697ug_wdt.c
@@ -87,10 +87,10 @@ static int w83697ug_select_wd_register(void)
87 outb_p(0x87, WDT_EFER); /* Enter extended function mode */ 87 outb_p(0x87, WDT_EFER); /* Enter extended function mode */
88 outb_p(0x87, WDT_EFER); /* Again according to manual */ 88 outb_p(0x87, WDT_EFER); /* Again according to manual */
89 89
90 outb(0x20, WDT_EFER); /* check chip version */ 90 outb(0x20, WDT_EFER); /* check chip version */
91 version = inb(WDT_EFDR); 91 version = inb(WDT_EFDR);
92 92
93 if (version == 0x68) { /* W83697UG */ 93 if (version == 0x68) { /* W83697UG */
94 printk(KERN_INFO PFX "Watchdog chip version 0x%02x = " 94 printk(KERN_INFO PFX "Watchdog chip version 0x%02x = "
95 "W83697UG/UF found at 0x%04x\n", version, wdt_io); 95 "W83697UG/UF found at 0x%04x\n", version, wdt_io);
96 96
@@ -109,7 +109,7 @@ static int w83697ug_select_wd_register(void)
109 outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ 109 outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
110 outb_p(0x30, WDT_EFER); /* select CR30 */ 110 outb_p(0x30, WDT_EFER); /* select CR30 */
111 c = inb_p(WDT_EFDR); 111 c = inb_p(WDT_EFDR);
112 outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ 112 outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
113 113
114 return 0; 114 return 0;
115} 115}
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 552a4381e78f..bb03e151a1d0 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -581,7 +581,7 @@ static void __exit wdt_exit(void)
581} 581}
582 582
583/** 583/**
584 * wdt_init: 584 * wdt_init:
585 * 585 *
586 * Set up the WDT watchdog board. All we have to do is grab the 586 * Set up the WDT watchdog board. All we have to do is grab the
587 * resources we require and bitch if anyone beat us to them. 587 * resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 5c2521fc836c..a2f01c9f5c34 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -281,7 +281,7 @@ static int wdt977_release(struct inode *inode, struct file *file)
281{ 281{
282 /* 282 /*
283 * Shut off the timer. 283 * Shut off the timer.
284 * Lock it in if it's a module and we set nowayout 284 * Lock it in if it's a module and we set nowayout
285 */ 285 */
286 if (expect_close == 42) { 286 if (expect_close == 42) {
287 wdt977_stop(); 287 wdt977_stop();
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 6130c88fa5ac..172dad6c7693 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -31,7 +31,7 @@
31 * Jeff Garzik : PCI cleanups 31 * Jeff Garzik : PCI cleanups
32 * Tigran Aivazian : Restructured wdtpci_init_one() to handle 32 * Tigran Aivazian : Restructured wdtpci_init_one() to handle
33 * failures 33 * failures
34 * Joel Becker : Added WDIOC_GET/SETTIMEOUT 34 * Joel Becker : Added WDIOC_GET/SETTIMEOUT
35 * Zwane Mwaikambo : Magic char closing, locking changes, 35 * Zwane Mwaikambo : Magic char closing, locking changes,
36 * cleanups 36 * cleanups
37 * Matt Domsch : nowayout module option 37 * Matt Domsch : nowayout module option
@@ -727,7 +727,7 @@ static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
727} 727}
728 728
729 729
730static struct pci_device_id wdtpci_pci_tbl[] = { 730static DEFINE_PCI_DEVICE_TABLE(wdtpci_pci_tbl) = {
731 { 731 {
732 .vendor = PCI_VENDOR_ID_ACCESSIO, 732 .vendor = PCI_VENDOR_ID_ACCESSIO,
733 .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM, 733 .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
@@ -764,7 +764,7 @@ static void __exit wdtpci_cleanup(void)
764 764
765 765
766/** 766/**
767 * wdtpci_init: 767 * wdtpci_init:
768 * 768 *
769 * Set up the WDT watchdog board. All we have to do is grab the 769 * Set up the WDT watchdog board. All we have to do is grab the
770 * resources we require and bitch if anyone beat us to them. 770 * resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
new file mode 100644
index 000000000000..49bd9d395562
--- /dev/null
+++ b/drivers/watchdog/xen_wdt.c
@@ -0,0 +1,359 @@
1/*
2 * Xen Watchdog Driver
3 *
4 * (c) Copyright 2010 Novell, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#define DRV_NAME "wdt"
13#define DRV_VERSION "0.01"
14#define PFX DRV_NAME ": "
15
16#include <linux/bug.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/hrtimer.h>
20#include <linux/kernel.h>
21#include <linux/ktime.h>
22#include <linux/init.h>
23#include <linux/miscdevice.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/platform_device.h>
27#include <linux/spinlock.h>
28#include <linux/uaccess.h>
29#include <linux/watchdog.h>
30#include <xen/xen.h>
31#include <asm/xen/hypercall.h>
32#include <xen/interface/sched.h>
33
34static struct platform_device *platform_device;
35static DEFINE_SPINLOCK(wdt_lock);
36static struct sched_watchdog wdt;
37static __kernel_time_t wdt_expires;
38static bool is_active, expect_release;
39
40#define WATCHDOG_TIMEOUT 60 /* in seconds */
41static unsigned int timeout = WATCHDOG_TIMEOUT;
42module_param(timeout, uint, S_IRUGO);
43MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds "
44 "(default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
45
46static bool nowayout = WATCHDOG_NOWAYOUT;
47module_param(nowayout, bool, S_IRUGO);
48MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
49 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
50
51static inline __kernel_time_t set_timeout(void)
52{
53 wdt.timeout = timeout;
54 return ktime_to_timespec(ktime_get()).tv_sec + timeout;
55}
56
57static int xen_wdt_start(void)
58{
59 __kernel_time_t expires;
60 int err;
61
62 spin_lock(&wdt_lock);
63
64 expires = set_timeout();
65 if (!wdt.id)
66 err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
67 else
68 err = -EBUSY;
69 if (err > 0) {
70 wdt.id = err;
71 wdt_expires = expires;
72 err = 0;
73 } else
74 BUG_ON(!err);
75
76 spin_unlock(&wdt_lock);
77
78 return err;
79}
80
81static int xen_wdt_stop(void)
82{
83 int err = 0;
84
85 spin_lock(&wdt_lock);
86
87 wdt.timeout = 0;
88 if (wdt.id)
89 err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
90 if (!err)
91 wdt.id = 0;
92
93 spin_unlock(&wdt_lock);
94
95 return err;
96}
97
98static int xen_wdt_kick(void)
99{
100 __kernel_time_t expires;
101 int err;
102
103 spin_lock(&wdt_lock);
104
105 expires = set_timeout();
106 if (wdt.id)
107 err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
108 else
109 err = -ENXIO;
110 if (!err)
111 wdt_expires = expires;
112
113 spin_unlock(&wdt_lock);
114
115 return err;
116}
117
118static int xen_wdt_open(struct inode *inode, struct file *file)
119{
120 int err;
121
122 /* /dev/watchdog can only be opened once */
123 if (xchg(&is_active, true))
124 return -EBUSY;
125
126 err = xen_wdt_start();
127 if (err == -EBUSY)
128 err = xen_wdt_kick();
129 return err ?: nonseekable_open(inode, file);
130}
131
132static int xen_wdt_release(struct inode *inode, struct file *file)
133{
134 if (expect_release)
135 xen_wdt_stop();
136 else {
137 printk(KERN_CRIT PFX
138 "unexpected close, not stopping watchdog!\n");
139 xen_wdt_kick();
140 }
141 is_active = false;
142 expect_release = false;
143 return 0;
144}
145
146static ssize_t xen_wdt_write(struct file *file, const char __user *data,
147 size_t len, loff_t *ppos)
148{
149 /* See if we got the magic character 'V' and reload the timer */
150 if (len) {
151 if (!nowayout) {
152 size_t i;
153
154 /* in case it was set long ago */
155 expect_release = false;
156
157 /* scan to see whether or not we got the magic
158 character */
159 for (i = 0; i != len; i++) {
160 char c;
161 if (get_user(c, data + i))
162 return -EFAULT;
163 if (c == 'V')
164 expect_release = true;
165 }
166 }
167
168 /* someone wrote to us, we should reload the timer */
169 xen_wdt_kick();
170 }
171 return len;
172}
173
174static long xen_wdt_ioctl(struct file *file, unsigned int cmd,
175 unsigned long arg)
176{
177 int new_options, retval = -EINVAL;
178 int new_timeout;
179 int __user *argp = (void __user *)arg;
180 static const struct watchdog_info ident = {
181 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
182 .firmware_version = 0,
183 .identity = DRV_NAME,
184 };
185
186 switch (cmd) {
187 case WDIOC_GETSUPPORT:
188 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
189
190 case WDIOC_GETSTATUS:
191 case WDIOC_GETBOOTSTATUS:
192 return put_user(0, argp);
193
194 case WDIOC_SETOPTIONS:
195 if (get_user(new_options, argp))
196 return -EFAULT;
197
198 if (new_options & WDIOS_DISABLECARD)
199 retval = xen_wdt_stop();
200 if (new_options & WDIOS_ENABLECARD) {
201 retval = xen_wdt_start();
202 if (retval == -EBUSY)
203 retval = xen_wdt_kick();
204 }
205 return retval;
206
207 case WDIOC_KEEPALIVE:
208 xen_wdt_kick();
209 return 0;
210
211 case WDIOC_SETTIMEOUT:
212 if (get_user(new_timeout, argp))
213 return -EFAULT;
214 if (!new_timeout)
215 return -EINVAL;
216 timeout = new_timeout;
217 xen_wdt_kick();
218 /* fall through */
219 case WDIOC_GETTIMEOUT:
220 return put_user(timeout, argp);
221
222 case WDIOC_GETTIMELEFT:
223 retval = wdt_expires - ktime_to_timespec(ktime_get()).tv_sec;
224 return put_user(retval, argp);
225 }
226
227 return -ENOTTY;
228}
229
230static const struct file_operations xen_wdt_fops = {
231 .owner = THIS_MODULE,
232 .llseek = no_llseek,
233 .write = xen_wdt_write,
234 .unlocked_ioctl = xen_wdt_ioctl,
235 .open = xen_wdt_open,
236 .release = xen_wdt_release,
237};
238
239static struct miscdevice xen_wdt_miscdev = {
240 .minor = WATCHDOG_MINOR,
241 .name = "watchdog",
242 .fops = &xen_wdt_fops,
243};
244
245static int __devinit xen_wdt_probe(struct platform_device *dev)
246{
247 struct sched_watchdog wd = { .id = ~0 };
248 int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd);
249
250 switch (ret) {
251 case -EINVAL:
252 if (!timeout) {
253 timeout = WATCHDOG_TIMEOUT;
254 printk(KERN_INFO PFX
255 "timeout value invalid, using %d\n", timeout);
256 }
257
258 ret = misc_register(&xen_wdt_miscdev);
259 if (ret) {
260 printk(KERN_ERR PFX
261 "cannot register miscdev on minor=%d (%d)\n",
262 WATCHDOG_MINOR, ret);
263 break;
264 }
265
266 printk(KERN_INFO PFX
267 "initialized (timeout=%ds, nowayout=%d)\n",
268 timeout, nowayout);
269 break;
270
271 case -ENOSYS:
272 printk(KERN_INFO PFX "not supported\n");
273 ret = -ENODEV;
274 break;
275
276 default:
277 printk(KERN_INFO PFX "bogus return value %d\n", ret);
278 break;
279 }
280
281 return ret;
282}
283
284static int __devexit xen_wdt_remove(struct platform_device *dev)
285{
286 /* Stop the timer before we leave */
287 if (!nowayout)
288 xen_wdt_stop();
289
290 misc_deregister(&xen_wdt_miscdev);
291
292 return 0;
293}
294
295static void xen_wdt_shutdown(struct platform_device *dev)
296{
297 xen_wdt_stop();
298}
299
300static int xen_wdt_suspend(struct platform_device *dev, pm_message_t state)
301{
302 return xen_wdt_stop();
303}
304
305static int xen_wdt_resume(struct platform_device *dev)
306{
307 return xen_wdt_start();
308}
309
310static struct platform_driver xen_wdt_driver = {
311 .probe = xen_wdt_probe,
312 .remove = __devexit_p(xen_wdt_remove),
313 .shutdown = xen_wdt_shutdown,
314 .suspend = xen_wdt_suspend,
315 .resume = xen_wdt_resume,
316 .driver = {
317 .owner = THIS_MODULE,
318 .name = DRV_NAME,
319 },
320};
321
322static int __init xen_wdt_init_module(void)
323{
324 int err;
325
326 if (!xen_domain())
327 return -ENODEV;
328
329 printk(KERN_INFO PFX "Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
330
331 err = platform_driver_register(&xen_wdt_driver);
332 if (err)
333 return err;
334
335 platform_device = platform_device_register_simple(DRV_NAME,
336 -1, NULL, 0);
337 if (IS_ERR(platform_device)) {
338 err = PTR_ERR(platform_device);
339 platform_driver_unregister(&xen_wdt_driver);
340 }
341
342 return err;
343}
344
345static void __exit xen_wdt_cleanup_module(void)
346{
347 platform_device_unregister(platform_device);
348 platform_driver_unregister(&xen_wdt_driver);
349 printk(KERN_INFO PFX "module unloaded\n");
350}
351
352module_init(xen_wdt_init_module);
353module_exit(xen_wdt_cleanup_module);
354
355MODULE_AUTHOR("Jan Beulich <jbeulich@novell.com>");
356MODULE_DESCRIPTION("Xen WatchDog Timer Driver");
357MODULE_VERSION(DRV_VERSION);
358MODULE_LICENSE("GPL");
359MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);