aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/watchdog
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig148
-rw-r--r--drivers/watchdog/Makefile17
-rw-r--r--drivers/watchdog/acquirewdt.c2
-rw-r--r--drivers/watchdog/alim1535_wdt.c10
-rw-r--r--drivers/watchdog/alim7101_wdt.c2
-rw-r--r--drivers/watchdog/ar7_wdt.c1
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c2
-rw-r--r--drivers/watchdog/ath79_wdt.c305
-rw-r--r--drivers/watchdog/bcm47xx_wdt.c4
-rw-r--r--drivers/watchdog/bcm63xx_wdt.c332
-rw-r--r--drivers/watchdog/bfin_wdt.c4
-rw-r--r--drivers/watchdog/booke_wdt.c99
-rw-r--r--drivers/watchdog/cpwd.c63
-rw-r--r--drivers/watchdog/davinci_wdt.c22
-rw-r--r--drivers/watchdog/ep93xx_wdt.c1
-rw-r--r--drivers/watchdog/eurotechwdt.c2
-rw-r--r--drivers/watchdog/f71808e_wdt.c82
-rw-r--r--drivers/watchdog/gef_wdt.c12
-rw-r--r--drivers/watchdog/hpwdt.c19
-rw-r--r--drivers/watchdog/i6300esb.c2
-rw-r--r--drivers/watchdog/iTCO_wdt.c143
-rw-r--r--drivers/watchdog/imx2_wdt.c2
-rw-r--r--drivers/watchdog/intel_scu_watchdog.c571
-rw-r--r--drivers/watchdog/intel_scu_watchdog.h66
-rw-r--r--drivers/watchdog/it8712f_wdt.c27
-rw-r--r--drivers/watchdog/it87_wdt.c114
-rw-r--r--drivers/watchdog/jz4740_wdt.c322
-rw-r--r--drivers/watchdog/ks8695_wdt.c2
-rw-r--r--drivers/watchdog/lantiq_wdt.c261
-rw-r--r--drivers/watchdog/m54xx_wdt.c227
-rw-r--r--drivers/watchdog/machzwd.c6
-rw-r--r--drivers/watchdog/max63xx_wdt.c22
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c24
-rw-r--r--drivers/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/watchdog/mtx-1_wdt.c44
-rw-r--r--drivers/watchdog/nv_tco.c512
-rw-r--r--drivers/watchdog/nv_tco.h64
-rw-r--r--drivers/watchdog/octeon-wdt-main.c5
-rw-r--r--drivers/watchdog/omap_wdt.c68
-rw-r--r--drivers/watchdog/omap_wdt.h2
-rw-r--r--drivers/watchdog/pc87413_wdt.c4
-rw-r--r--drivers/watchdog/pcwd_pci.c2
-rw-r--r--drivers/watchdog/pnx4008_wdt.c30
-rw-r--r--drivers/watchdog/riowd.c9
-rw-r--r--drivers/watchdog/s3c2410_wdt.c21
-rw-r--r--drivers/watchdog/sbc7240_wdt.c2
-rw-r--r--drivers/watchdog/sbc8360.c2
-rw-r--r--drivers/watchdog/sbc_epx_c3.c2
-rw-r--r--drivers/watchdog/sbc_fitpc2_wdt.c9
-rw-r--r--drivers/watchdog/sch311x_wdt.c4
-rw-r--r--drivers/watchdog/shwdt.c367
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c6
-rw-r--r--drivers/watchdog/softdog.c18
-rw-r--r--drivers/watchdog/sp5100_tco.c492
-rw-r--r--drivers/watchdog/sp5100_tco.h41
-rw-r--r--drivers/watchdog/sp805_wdt.c4
-rw-r--r--drivers/watchdog/ts72xx_wdt.c2
-rw-r--r--drivers/watchdog/w83627hf_wdt.c8
-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/wm831x_wdt.c5
-rw-r--r--drivers/watchdog/xen_wdt.c359
64 files changed, 4473 insertions, 543 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 24efd8ea41bb..21d816e9dfa5 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -409,15 +409,26 @@ config ALIM7101_WDT
409 Most people will say N. 409 Most people will say N.
410 410
411config F71808E_WDT 411config F71808E_WDT
412 tristate "Fintek F71808E and F71882FG Watchdog" 412 tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog"
413 depends on X86 && EXPERIMENTAL 413 depends on X86 && EXPERIMENTAL
414 help 414 help
415 This is the driver for the hardware watchdog on the Fintek 415 This is the driver for the hardware watchdog on the Fintek
416 F71808E and F71882FG Super I/O controllers. 416 F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers.
417 417
418 You can compile this driver directly into the kernel, or use 418 You can compile this driver directly into the kernel, or use
419 it as a module. The module will be called f71808e_wdt. 419 it as a module. The module will be called f71808e_wdt.
420 420
421config SP5100_TCO
422 tristate "AMD/ATI SP5100 TCO Timer/Watchdog"
423 depends on X86 && PCI
424 ---help---
425 Hardware watchdog driver for the AMD/ATI SP5100 chipset. The TCO
426 (Total Cost of Ownership) timer is a watchdog timer that will reboot
427 the machine after its expiration. The expiration time can be
428 configured with the "heartbeat" parameter.
429
430 To compile this driver as a module, choose M here: the
431 module will be called sp5100_tco.
421 432
422config GEODE_WDT 433config GEODE_WDT
423 tristate "AMD Geode CS5535/CS5536 Watchdog" 434 tristate "AMD Geode CS5535/CS5536 Watchdog"
@@ -522,6 +533,15 @@ config I6300ESB_WDT
522 To compile this driver as a module, choose M here: the 533 To compile this driver as a module, choose M here: the
523 module will be called i6300esb. 534 module will be called i6300esb.
524 535
536config INTEL_SCU_WATCHDOG
537 bool "Intel SCU Watchdog for Mobile Platforms"
538 depends on X86_MRST
539 ---help---
540 Hardware driver for the watchdog time built into the Intel SCU
541 for Intel Mobile Platforms.
542
543 To compile this driver as a module, choose M here.
544
525config ITCO_WDT 545config ITCO_WDT
526 tristate "Intel TCO Timer/Watchdog" 546 tristate "Intel TCO Timer/Watchdog"
527 depends on (X86 || IA64) && PCI 547 depends on (X86 || IA64) && PCI
@@ -558,6 +578,9 @@ config IT8712F_WDT
558 This is the driver for the built-in watchdog timer on the IT8712F 578 This is the driver for the built-in watchdog timer on the IT8712F
559 Super I/0 chipset used on many motherboards. 579 Super I/0 chipset used on many motherboards.
560 580
581 If the driver does not work, then make sure that the game port in
582 the BIOS is enabled.
583
561 To compile this driver as a module, choose M here: the 584 To compile this driver as a module, choose M here: the
562 module will be called it8712f_wdt. 585 module will be called it8712f_wdt.
563 586
@@ -565,27 +588,29 @@ config IT87_WDT
565 tristate "IT87 Watchdog Timer" 588 tristate "IT87 Watchdog Timer"
566 depends on X86 && EXPERIMENTAL 589 depends on X86 && EXPERIMENTAL
567 ---help--- 590 ---help---
568 This is the driver for the hardware watchdog on the ITE IT8716, 591 This is the driver for the hardware watchdog on the ITE IT8702,
569 IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog 592 IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips.
570 simply watches your kernel to make sure it doesn't freeze, and if 593 This watchdog simply watches your kernel to make sure it doesn't
571 it does, it reboots your computer after a certain amount of time. 594 freeze, and if it does, it reboots your computer after a certain
595 amount of time.
572 596
573 To compile this driver as a module, choose M here: the module will 597 To compile this driver as a module, choose M here: the module will
574 be called it87_wdt. 598 be called it87_wdt.
575 599
576config HP_WATCHDOG 600config HP_WATCHDOG
577 tristate "HP Proliant iLO2+ Hardware Watchdog Timer" 601 tristate "HP ProLiant iLO2+ Hardware Watchdog Timer"
578 depends on X86 602 depends on X86 && PCI
579 help 603 help
580 A software monitoring watchdog and NMI sourcing driver. This driver 604 A software monitoring watchdog and NMI sourcing driver. This driver
581 will detect lockups and provide a stack trace. This is a driver that 605 will detect lockups and provide a stack trace. This is a driver that
582 will only load on a HP ProLiant system with a minimum of iLO2 support. 606 will only load on an HP ProLiant system with a minimum of iLO2 support.
583 To compile this driver as a module, choose M here: the module will be 607 To compile this driver as a module, choose M here: the module will be
584 called hpwdt. 608 called hpwdt.
585 609
586config HPWDT_NMI_DECODING 610config HPWDT_NMI_DECODING
587 bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" 611 bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
588 depends on HP_WATCHDOG 612 depends on HP_WATCHDOG
613 default y
589 help 614 help
590 When an NMI occurs this feature will make the necessary BIOS calls to 615 When an NMI occurs this feature will make the necessary BIOS calls to
591 log the cause of the NMI. 616 log the cause of the NMI.
@@ -627,6 +652,24 @@ config PC87413_WDT
627 652
628 Most people will say N. 653 Most people will say N.
629 654
655config NV_TCO
656 tristate "nVidia TCO Timer/Watchdog"
657 depends on X86 && PCI
658 ---help---
659 Hardware driver for the TCO timer built into the nVidia Hub family
660 (such as the MCP51). The TCO (Total Cost of Ownership) timer is a
661 watchdog timer that will reboot the machine after its second
662 expiration. The expiration time can be configured with the
663 "heartbeat" parameter.
664
665 On some motherboards the driver may fail to reset the chipset's
666 NO_REBOOT flag which prevents the watchdog from rebooting the
667 machine. If this is the case you will get a kernel message like
668 "failed to reset NO_REBOOT flag, reboot disabled by hardware".
669
670 To compile this driver as a module, choose M here: the
671 module will be called nv_tco.
672
630config RDC321X_WDT 673config RDC321X_WDT
631 tristate "RDC R-321x SoC watchdog" 674 tristate "RDC R-321x SoC watchdog"
632 depends on X86_RDC321X 675 depends on X86_RDC321X
@@ -718,14 +761,15 @@ config SMSC37B787_WDT
718 Most people will say N. 761 Most people will say N.
719 762
720config W83627HF_WDT 763config W83627HF_WDT
721 tristate "W83627HF Watchdog Timer" 764 tristate "W83627HF/W83627DHG Watchdog Timer"
722 depends on X86 765 depends on X86
723 ---help--- 766 ---help---
724 This is the driver for the hardware watchdog on the W83627HF chipset 767 This is the driver for the hardware watchdog on the W83627HF chipset
725 as used in Advantech PC-9578 and Tyan S2721-533 motherboards 768 as used in Advantech PC-9578 and Tyan S2721-533 motherboards
726 (and likely others). This watchdog simply watches your kernel to 769 (and likely others). The driver also supports the W83627DHG chip.
727 make sure it doesn't freeze, and if it does, it reboots your computer 770 This watchdog simply watches your kernel to make sure it doesn't
728 after a certain amount of time. 771 freeze, and if it does, it reboots your computer after a certain
772 amount of time.
729 773
730 To compile this driver as a module, choose M here: the 774 To compile this driver as a module, choose M here: the
731 module will be called w83627hf_wdt. 775 module will be called w83627hf_wdt.
@@ -828,10 +872,22 @@ config SBC_EPX_C3_WATCHDOG
828 872
829# M68K Architecture 873# M68K Architecture
830 874
831# M68KNOMMU Architecture 875config M54xx_WATCHDOG
876 tristate "MCF54xx watchdog support"
877 depends on M548x
878 help
879 To compile this driver as a module, choose M here: the
880 module will be called m54xx_wdt.
832 881
833# MIPS Architecture 882# MIPS Architecture
834 883
884config ATH79_WDT
885 tristate "Atheros AR71XX/AR724X/AR913X hardware watchdog"
886 depends on ATH79
887 help
888 Hardware driver for the built-in watchdog timer on the Atheros
889 AR71XX/AR724X/AR913X SoCs.
890
835config BCM47XX_WDT 891config BCM47XX_WDT
836 tristate "Broadcom BCM47xx Watchdog Timer" 892 tristate "Broadcom BCM47xx Watchdog Timer"
837 depends on BCM47XX 893 depends on BCM47XX
@@ -857,6 +913,12 @@ config INDYDOG
857 timer expired and no process has written to /dev/watchdog during 913 timer expired and no process has written to /dev/watchdog during
858 that time. 914 that time.
859 915
916config JZ4740_WDT
917 tristate "Ingenic jz4740 SoC hardware watchdog"
918 depends on MACH_JZ4740
919 help
920 Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
921
860config WDT_MTX1 922config WDT_MTX1
861 tristate "MTX-1 Hardware Watchdog" 923 tristate "MTX-1 Hardware Watchdog"
862 depends on MIPS_MTX1 924 depends on MIPS_MTX1
@@ -869,7 +931,7 @@ config PNX833X_WDT
869 depends on SOC_PNX8335 931 depends on SOC_PNX8335
870 help 932 help
871 Hardware driver for the PNX833x's watchdog. This is a 933 Hardware driver for the PNX833x's watchdog. This is a
872 watchdog timer that will reboot the machine after a programable 934 watchdog timer that will reboot the machine after a programmable
873 timer has expired and no process has written to /dev/watchdog during 935 timer has expired and no process has written to /dev/watchdog during
874 that time. 936 that time.
875 937
@@ -916,6 +978,22 @@ config OCTEON_WDT
916 from the first interrupt, it is then only poked when the 978 from the first interrupt, it is then only poked when the
917 device is written. 979 device is written.
918 980
981config BCM63XX_WDT
982 tristate "Broadcom BCM63xx hardware watchdog"
983 depends on BCM63XX
984 help
985 Watchdog driver for the built in watchdog hardware in Broadcom
986 BCM63xx SoC.
987
988 To compile this driver as a loadable module, choose M here.
989 The module will be called bcm63xx_wdt.
990
991config LANTIQ_WDT
992 tristate "Lantiq SoC watchdog"
993 depends on LANTIQ
994 help
995 Hardware driver for the Lantiq SoC Watchdog Timer.
996
919# PARISC Architecture 997# PARISC Architecture
920 998
921# POWERPC Architecture 999# POWERPC Architecture
@@ -957,12 +1035,32 @@ config PIKA_WDT
957 the Warp platform. 1035 the Warp platform.
958 1036
959config BOOKE_WDT 1037config BOOKE_WDT
960 bool "PowerPC Book-E Watchdog Timer" 1038 tristate "PowerPC Book-E Watchdog Timer"
961 depends on BOOKE || 4xx 1039 depends on BOOKE || 4xx
962 ---help--- 1040 ---help---
1041 Watchdog driver for PowerPC Book-E chips, such as the Freescale
1042 MPC85xx SOCs and the IBM PowerPC 440.
1043
963 Please see Documentation/watchdog/watchdog-api.txt for 1044 Please see Documentation/watchdog/watchdog-api.txt for
964 more information. 1045 more information.
965 1046
1047config BOOKE_WDT_DEFAULT_TIMEOUT
1048 int "PowerPC Book-E Watchdog Timer Default Timeout"
1049 depends on BOOKE_WDT
1050 default 38 if FSL_BOOKE
1051 range 0 63 if FSL_BOOKE
1052 default 3 if !FSL_BOOKE
1053 range 0 3 if !FSL_BOOKE
1054 help
1055 Select the default watchdog timer period to be used by the PowerPC
1056 Book-E watchdog driver. A watchdog "event" occurs when the bit
1057 position represented by this number transitions from zero to one.
1058
1059 For Freescale Book-E processors, this is a number between 0 and 63.
1060 For other Book-E processors, this is a number between 0 and 3.
1061
1062 The value can be overidden by the wdt_period command-line parameter.
1063
966# PPC64 Architecture 1064# PPC64 Architecture
967 1065
968config WATCHDOG_RTAS 1066config WATCHDOG_RTAS
@@ -1007,14 +1105,6 @@ config SH_WDT
1007 To compile this driver as a module, choose M here: the 1105 To compile this driver as a module, choose M here: the
1008 module will be called shwdt. 1106 module will be called shwdt.
1009 1107
1010config SH_WDT_MMAP
1011 bool "Allow mmap of SH WDT"
1012 default n
1013 depends on SH_WDT
1014 help
1015 If you say Y here, user applications will be able to mmap the
1016 WDT/CPG registers.
1017
1018# SPARC Architecture 1108# SPARC Architecture
1019 1109
1020# SPARC64 Architecture 1110# SPARC64 Architecture
@@ -1043,6 +1133,16 @@ config WATCHDOG_RIO
1043 1133
1044# XTENSA Architecture 1134# XTENSA Architecture
1045 1135
1136# Xen Architecture
1137
1138config XEN_WDT
1139 tristate "Xen Watchdog support"
1140 depends on XEN
1141 help
1142 Say Y here to support the hypervisor watchdog capability provided
1143 by Xen 4.0 and newer. The watchdog timeout period is normally one
1144 minute but can be changed with a boot-time parameter.
1145
1046# 1146#
1047# ISA-based Watchdog Cards 1147# ISA-based Watchdog Cards
1048# 1148#
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 8374503fcc6a..ed26f7094e47 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -4,7 +4,7 @@
4 4
5# Only one watchdog can succeed. We probe the ISA/PCI/USB based 5# Only one watchdog can succeed. We probe the ISA/PCI/USB based
6# watchdog-cards first, then the architecture specific watchdog 6# watchdog-cards first, then the architecture specific watchdog
7# drivers and then the architecture independant "softdog" driver. 7# drivers and then the architecture independent "softdog" driver.
8# This means that if your ISA/PCI/USB card isn't detected that 8# This means that if your ISA/PCI/USB card isn't detected that
9# you can fall back to an architecture specific driver and if 9# you can fall back to an architecture specific driver and if
10# that also fails then you can fall back to the software watchdog 10# that also fails then you can fall back to the software watchdog
@@ -68,6 +68,7 @@ obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
68obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o 68obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
69obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o 69obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
70obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o 70obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o
71obj-$(CONFIG_SP5100_TCO) += sp5100_tco.o
71obj-$(CONFIG_GEODE_WDT) += geodewdt.o 72obj-$(CONFIG_GEODE_WDT) += geodewdt.o
72obj-$(CONFIG_SC520_WDT) += sc520_wdt.o 73obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
73obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o 74obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o
@@ -86,6 +87,7 @@ obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
86obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 87obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
87obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 88obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
88obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o 89obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
90obj-$(CONFIG_NV_TCO) += nv_tco.o
89obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o 91obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o
90obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 92obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
91obj-$(CONFIG_SBC8360_WDT) += sbc8360.o 93obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
@@ -100,17 +102,20 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
100obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o 102obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
101obj-$(CONFIG_MACHZ_WDT) += machzwd.o 103obj-$(CONFIG_MACHZ_WDT) += machzwd.o
102obj-$(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
103 106
104# M32R Architecture 107# M32R Architecture
105 108
106# M68K Architecture 109# M68K Architecture
107 110obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
108# M68KNOMMU Architecture
109 111
110# MIPS Architecture 112# MIPS Architecture
113obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
111obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o 114obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
115obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
112obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 116obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
113obj-$(CONFIG_INDYDOG) += indydog.o 117obj-$(CONFIG_INDYDOG) += indydog.o
118obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o
114obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 119obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
115obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o 120obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
116obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o 121obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
@@ -118,6 +123,7 @@ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
118obj-$(CONFIG_TXX9_WDT) += txx9wdt.o 123obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
119obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o 124obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
120octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o 125octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
126obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
121 127
122# PARISC Architecture 128# PARISC Architecture
123 129
@@ -145,7 +151,10 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
145 151
146# XTENSA Architecture 152# XTENSA Architecture
147 153
148# Architecture Independant 154# Xen
155obj-$(CONFIG_XEN_WDT) += xen_wdt.o
156
157# Architecture Independent
149obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 158obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
150obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 159obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
151obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o 160obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 2ffce4d75443..b6a2b58cbe64 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -26,7 +26,7 @@
26 * Theory of Operation: 26 * Theory of Operation:
27 * The Watch-Dog Timer is provided to ensure that standalone 27 * The Watch-Dog Timer is provided to ensure that standalone
28 * Systems can always recover from catastrophic conditions that 28 * Systems can always recover from catastrophic conditions that
29 * caused the CPU to crash. This condition may have occured by 29 * caused the CPU to crash. This condition may have occurred by
30 * external EMI or a software bug. When the CPU stops working 30 * external EMI or a software bug. When the CPU stops working
31 * correctly, hardware on the board will either perform a hardware 31 * correctly, hardware on the board will either perform a hardware
32 * reset (cold boot) or a non-maskable interrupt (NMI) to bring the 32 * reset (cold boot) or a non-maskable interrupt (NMI) to bring the
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index 1e9caea8ff8a..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[] = { 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 d8d4da9a483d..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 = { 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/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index c764c52412e4..b29221783598 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -267,6 +267,7 @@ static const struct file_operations ar7_wdt_fops = {
267 .unlocked_ioctl = ar7_wdt_ioctl, 267 .unlocked_ioctl = ar7_wdt_ioctl,
268 .open = ar7_wdt_open, 268 .open = ar7_wdt_open,
269 .release = ar7_wdt_release, 269 .release = ar7_wdt_release,
270 .llseek = no_llseek,
270}; 271};
271 272
272static struct miscdevice ar7_wdt_miscdev = { 273static struct miscdevice ar7_wdt_miscdev = {
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 750bc5281d79..4ca5d40304b2 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -448,7 +448,7 @@ static void __exit at32_wdt_exit(void)
448} 448}
449module_exit(at32_wdt_exit); 449module_exit(at32_wdt_exit);
450 450
451MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 451MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
452MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); 452MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
453MODULE_LICENSE("GPL"); 453MODULE_LICENSE("GPL");
454MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 454MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
new file mode 100644
index 000000000000..725c84bfdd76
--- /dev/null
+++ b/drivers/watchdog/ath79_wdt.c
@@ -0,0 +1,305 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X built-in hardware watchdog timer.
3 *
4 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This driver was based on: drivers/watchdog/ixp4xx_wdt.c
8 * Author: Deepak Saxena <dsaxena@plexity.net>
9 * Copyright 2004 (c) MontaVista, Software, Inc.
10 *
11 * which again was based on sa1100 driver,
12 * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License version 2 as published
16 * by the Free Software Foundation.
17 *
18 */
19
20#include <linux/bitops.h>
21#include <linux/errno.h>
22#include <linux/fs.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/miscdevice.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/platform_device.h>
29#include <linux/types.h>
30#include <linux/watchdog.h>
31#include <linux/clk.h>
32#include <linux/err.h>
33
34#include <asm/mach-ath79/ath79.h>
35#include <asm/mach-ath79/ar71xx_regs.h>
36
37#define DRIVER_NAME "ath79-wdt"
38
39#define WDT_TIMEOUT 15 /* seconds */
40
41#define WDOG_CTRL_LAST_RESET BIT(31)
42#define WDOG_CTRL_ACTION_MASK 3
43#define WDOG_CTRL_ACTION_NONE 0 /* no action */
44#define WDOG_CTRL_ACTION_GPI 1 /* general purpose interrupt */
45#define WDOG_CTRL_ACTION_NMI 2 /* NMI */
46#define WDOG_CTRL_ACTION_FCR 3 /* full chip reset */
47
48static int nowayout = WATCHDOG_NOWAYOUT;
49module_param(nowayout, int, 0);
50MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
51 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
52
53static int timeout = WDT_TIMEOUT;
54module_param(timeout, int, 0);
55MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds "
56 "(default=" __MODULE_STRING(WDT_TIMEOUT) "s)");
57
58static unsigned long wdt_flags;
59
60#define WDT_FLAGS_BUSY 0
61#define WDT_FLAGS_EXPECT_CLOSE 1
62
63static struct clk *wdt_clk;
64static unsigned long wdt_freq;
65static int boot_status;
66static int max_timeout;
67
68static inline void ath79_wdt_keepalive(void)
69{
70 ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout);
71}
72
73static inline void ath79_wdt_enable(void)
74{
75 ath79_wdt_keepalive();
76 ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR);
77}
78
79static inline void ath79_wdt_disable(void)
80{
81 ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE);
82}
83
84static int ath79_wdt_set_timeout(int val)
85{
86 if (val < 1 || val > max_timeout)
87 return -EINVAL;
88
89 timeout = val;
90 ath79_wdt_keepalive();
91
92 return 0;
93}
94
95static int ath79_wdt_open(struct inode *inode, struct file *file)
96{
97 if (test_and_set_bit(WDT_FLAGS_BUSY, &wdt_flags))
98 return -EBUSY;
99
100 clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
101 ath79_wdt_enable();
102
103 return nonseekable_open(inode, file);
104}
105
106static int ath79_wdt_release(struct inode *inode, struct file *file)
107{
108 if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags))
109 ath79_wdt_disable();
110 else {
111 pr_crit(DRIVER_NAME ": device closed unexpectedly, "
112 "watchdog timer will not stop!\n");
113 ath79_wdt_keepalive();
114 }
115
116 clear_bit(WDT_FLAGS_BUSY, &wdt_flags);
117 clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
118
119 return 0;
120}
121
122static ssize_t ath79_wdt_write(struct file *file, const char *data,
123 size_t len, loff_t *ppos)
124{
125 if (len) {
126 if (!nowayout) {
127 size_t i;
128
129 clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
130
131 for (i = 0; i != len; i++) {
132 char c;
133
134 if (get_user(c, data + i))
135 return -EFAULT;
136
137 if (c == 'V')
138 set_bit(WDT_FLAGS_EXPECT_CLOSE,
139 &wdt_flags);
140 }
141 }
142
143 ath79_wdt_keepalive();
144 }
145
146 return len;
147}
148
149static const struct watchdog_info ath79_wdt_info = {
150 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
151 WDIOF_MAGICCLOSE | WDIOF_CARDRESET,
152 .firmware_version = 0,
153 .identity = "ATH79 watchdog",
154};
155
156static long ath79_wdt_ioctl(struct file *file, unsigned int cmd,
157 unsigned long arg)
158{
159 void __user *argp = (void __user *)arg;
160 int __user *p = argp;
161 int err;
162 int t;
163
164 switch (cmd) {
165 case WDIOC_GETSUPPORT:
166 err = copy_to_user(argp, &ath79_wdt_info,
167 sizeof(ath79_wdt_info)) ? -EFAULT : 0;
168 break;
169
170 case WDIOC_GETSTATUS:
171 err = put_user(0, p);
172 break;
173
174 case WDIOC_GETBOOTSTATUS:
175 err = put_user(boot_status, p);
176 break;
177
178 case WDIOC_KEEPALIVE:
179 ath79_wdt_keepalive();
180 err = 0;
181 break;
182
183 case WDIOC_SETTIMEOUT:
184 err = get_user(t, p);
185 if (err)
186 break;
187
188 err = ath79_wdt_set_timeout(t);
189 if (err)
190 break;
191
192 /* fallthrough */
193 case WDIOC_GETTIMEOUT:
194 err = put_user(timeout, p);
195 break;
196
197 default:
198 err = -ENOTTY;
199 break;
200 }
201
202 return err;
203}
204
205static const struct file_operations ath79_wdt_fops = {
206 .owner = THIS_MODULE,
207 .llseek = no_llseek,
208 .write = ath79_wdt_write,
209 .unlocked_ioctl = ath79_wdt_ioctl,
210 .open = ath79_wdt_open,
211 .release = ath79_wdt_release,
212};
213
214static struct miscdevice ath79_wdt_miscdev = {
215 .minor = WATCHDOG_MINOR,
216 .name = "watchdog",
217 .fops = &ath79_wdt_fops,
218};
219
220static int __devinit ath79_wdt_probe(struct platform_device *pdev)
221{
222 u32 ctrl;
223 int err;
224
225 wdt_clk = clk_get(&pdev->dev, "wdt");
226 if (IS_ERR(wdt_clk))
227 return PTR_ERR(wdt_clk);
228
229 err = clk_enable(wdt_clk);
230 if (err)
231 goto err_clk_put;
232
233 wdt_freq = clk_get_rate(wdt_clk);
234 if (!wdt_freq) {
235 err = -EINVAL;
236 goto err_clk_disable;
237 }
238
239 max_timeout = (0xfffffffful / wdt_freq);
240 if (timeout < 1 || timeout > max_timeout) {
241 timeout = max_timeout;
242 dev_info(&pdev->dev,
243 "timeout value must be 0 < timeout < %d, using %d\n",
244 max_timeout, timeout);
245 }
246
247 ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
248 boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0;
249
250 err = misc_register(&ath79_wdt_miscdev);
251 if (err) {
252 dev_err(&pdev->dev,
253 "unable to register misc device, err=%d\n", err);
254 goto err_clk_disable;
255 }
256
257 return 0;
258
259err_clk_disable:
260 clk_disable(wdt_clk);
261err_clk_put:
262 clk_put(wdt_clk);
263 return err;
264}
265
266static int __devexit ath79_wdt_remove(struct platform_device *pdev)
267{
268 misc_deregister(&ath79_wdt_miscdev);
269 clk_disable(wdt_clk);
270 clk_put(wdt_clk);
271 return 0;
272}
273
274static void ath97_wdt_shutdown(struct platform_device *pdev)
275{
276 ath79_wdt_disable();
277}
278
279static struct platform_driver ath79_wdt_driver = {
280 .remove = __devexit_p(ath79_wdt_remove),
281 .shutdown = ath97_wdt_shutdown,
282 .driver = {
283 .name = DRIVER_NAME,
284 .owner = THIS_MODULE,
285 },
286};
287
288static int __init ath79_wdt_init(void)
289{
290 return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe);
291}
292module_init(ath79_wdt_init);
293
294static void __exit ath79_wdt_exit(void)
295{
296 platform_driver_unregister(&ath79_wdt_driver);
297}
298module_exit(ath79_wdt_exit);
299
300MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver");
301MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
302MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org");
303MODULE_LICENSE("GPL v2");
304MODULE_ALIAS("platform:" DRIVER_NAME);
305MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
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/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
new file mode 100644
index 000000000000..5064e8317521
--- /dev/null
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -0,0 +1,332 @@
1/*
2 * Broadcom BCM63xx SoC watchdog driver
3 *
4 * Copyright (C) 2007, Miguel Gaio <miguel.gaio@efixo.com>
5 * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <linux/bitops.h>
14#include <linux/errno.h>
15#include <linux/fs.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/miscdevice.h>
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/types.h>
22#include <linux/uaccess.h>
23#include <linux/watchdog.h>
24#include <linux/timer.h>
25#include <linux/jiffies.h>
26#include <linux/interrupt.h>
27#include <linux/ptrace.h>
28#include <linux/resource.h>
29#include <linux/platform_device.h>
30
31#include <bcm63xx_cpu.h>
32#include <bcm63xx_io.h>
33#include <bcm63xx_regs.h>
34#include <bcm63xx_timer.h>
35
36#define PFX KBUILD_MODNAME
37
38#define WDT_HZ 50000000 /* Fclk */
39#define WDT_DEFAULT_TIME 30 /* seconds */
40#define WDT_MAX_TIME 256 /* seconds */
41
42static struct {
43 void __iomem *regs;
44 struct timer_list timer;
45 int default_ticks;
46 unsigned long inuse;
47 atomic_t ticks;
48} bcm63xx_wdt_device;
49
50static int expect_close;
51
52static int wdt_time = WDT_DEFAULT_TIME;
53static int nowayout = WATCHDOG_NOWAYOUT;
54module_param(nowayout, int, 0);
55MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
56 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
57
58/* HW functions */
59static void bcm63xx_wdt_hw_start(void)
60{
61 bcm_writel(0xfffffffe, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
62 bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
63 bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
64}
65
66static void bcm63xx_wdt_hw_stop(void)
67{
68 bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
69 bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
70}
71
72static void bcm63xx_wdt_isr(void *data)
73{
74 struct pt_regs *regs = get_irq_regs();
75
76 die(PFX " fire", regs);
77}
78
79static void bcm63xx_timer_tick(unsigned long unused)
80{
81 if (!atomic_dec_and_test(&bcm63xx_wdt_device.ticks)) {
82 bcm63xx_wdt_hw_start();
83 mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
84 } else
85 printk(KERN_CRIT PFX ": watchdog will restart system\n");
86}
87
88static void bcm63xx_wdt_pet(void)
89{
90 atomic_set(&bcm63xx_wdt_device.ticks, wdt_time);
91}
92
93static void bcm63xx_wdt_start(void)
94{
95 bcm63xx_wdt_pet();
96 bcm63xx_timer_tick(0);
97}
98
99static void bcm63xx_wdt_pause(void)
100{
101 del_timer_sync(&bcm63xx_wdt_device.timer);
102 bcm63xx_wdt_hw_stop();
103}
104
105static int bcm63xx_wdt_settimeout(int new_time)
106{
107 if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
108 return -EINVAL;
109
110 wdt_time = new_time;
111
112 return 0;
113}
114
115static int bcm63xx_wdt_open(struct inode *inode, struct file *file)
116{
117 if (test_and_set_bit(0, &bcm63xx_wdt_device.inuse))
118 return -EBUSY;
119
120 bcm63xx_wdt_start();
121 return nonseekable_open(inode, file);
122}
123
124static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
125{
126 if (expect_close == 42)
127 bcm63xx_wdt_pause();
128 else {
129 printk(KERN_CRIT PFX
130 ": Unexpected close, not stopping watchdog!\n");
131 bcm63xx_wdt_start();
132 }
133 clear_bit(0, &bcm63xx_wdt_device.inuse);
134 expect_close = 0;
135 return 0;
136}
137
138static ssize_t bcm63xx_wdt_write(struct file *file, const char *data,
139 size_t len, loff_t *ppos)
140{
141 if (len) {
142 if (!nowayout) {
143 size_t i;
144
145 /* In case it was set long ago */
146 expect_close = 0;
147
148 for (i = 0; i != len; i++) {
149 char c;
150 if (get_user(c, data + i))
151 return -EFAULT;
152 if (c == 'V')
153 expect_close = 42;
154 }
155 }
156 bcm63xx_wdt_pet();
157 }
158 return len;
159}
160
161static struct watchdog_info bcm63xx_wdt_info = {
162 .identity = PFX,
163 .options = WDIOF_SETTIMEOUT |
164 WDIOF_KEEPALIVEPING |
165 WDIOF_MAGICCLOSE,
166};
167
168
169static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd,
170 unsigned long arg)
171{
172 void __user *argp = (void __user *)arg;
173 int __user *p = argp;
174 int new_value, retval = -EINVAL;
175
176 switch (cmd) {
177 case WDIOC_GETSUPPORT:
178 return copy_to_user(argp, &bcm63xx_wdt_info,
179 sizeof(bcm63xx_wdt_info)) ? -EFAULT : 0;
180
181 case WDIOC_GETSTATUS:
182 case WDIOC_GETBOOTSTATUS:
183 return put_user(0, p);
184
185 case WDIOC_SETOPTIONS:
186 if (get_user(new_value, p))
187 return -EFAULT;
188
189 if (new_value & WDIOS_DISABLECARD) {
190 bcm63xx_wdt_pause();
191 retval = 0;
192 }
193 if (new_value & WDIOS_ENABLECARD) {
194 bcm63xx_wdt_start();
195 retval = 0;
196 }
197
198 return retval;
199
200 case WDIOC_KEEPALIVE:
201 bcm63xx_wdt_pet();
202 return 0;
203
204 case WDIOC_SETTIMEOUT:
205 if (get_user(new_value, p))
206 return -EFAULT;
207
208 if (bcm63xx_wdt_settimeout(new_value))
209 return -EINVAL;
210
211 bcm63xx_wdt_pet();
212
213 case WDIOC_GETTIMEOUT:
214 return put_user(wdt_time, p);
215
216 default:
217 return -ENOTTY;
218
219 }
220}
221
222static const struct file_operations bcm63xx_wdt_fops = {
223 .owner = THIS_MODULE,
224 .llseek = no_llseek,
225 .write = bcm63xx_wdt_write,
226 .unlocked_ioctl = bcm63xx_wdt_ioctl,
227 .open = bcm63xx_wdt_open,
228 .release = bcm63xx_wdt_release,
229};
230
231static struct miscdevice bcm63xx_wdt_miscdev = {
232 .minor = WATCHDOG_MINOR,
233 .name = "watchdog",
234 .fops = &bcm63xx_wdt_fops,
235};
236
237
238static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev)
239{
240 int ret;
241 struct resource *r;
242
243 setup_timer(&bcm63xx_wdt_device.timer, bcm63xx_timer_tick, 0L);
244
245 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
246 if (!r) {
247 dev_err(&pdev->dev, "failed to get resources\n");
248 return -ENODEV;
249 }
250
251 bcm63xx_wdt_device.regs = ioremap_nocache(r->start, resource_size(r));
252 if (!bcm63xx_wdt_device.regs) {
253 dev_err(&pdev->dev, "failed to remap I/O resources\n");
254 return -ENXIO;
255 }
256
257 ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL);
258 if (ret < 0) {
259 dev_err(&pdev->dev, "failed to register wdt timer isr\n");
260 goto unmap;
261 }
262
263 if (bcm63xx_wdt_settimeout(wdt_time)) {
264 bcm63xx_wdt_settimeout(WDT_DEFAULT_TIME);
265 dev_info(&pdev->dev,
266 ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
267 wdt_time);
268 }
269
270 ret = misc_register(&bcm63xx_wdt_miscdev);
271 if (ret < 0) {
272 dev_err(&pdev->dev, "failed to register watchdog device\n");
273 goto unregister_timer;
274 }
275
276 dev_info(&pdev->dev, " started, timer margin: %d sec\n",
277 WDT_DEFAULT_TIME);
278
279 return 0;
280
281unregister_timer:
282 bcm63xx_timer_unregister(TIMER_WDT_ID);
283unmap:
284 iounmap(bcm63xx_wdt_device.regs);
285 return ret;
286}
287
288static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev)
289{
290 if (!nowayout)
291 bcm63xx_wdt_pause();
292
293 misc_deregister(&bcm63xx_wdt_miscdev);
294 bcm63xx_timer_unregister(TIMER_WDT_ID);
295 iounmap(bcm63xx_wdt_device.regs);
296 return 0;
297}
298
299static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
300{
301 bcm63xx_wdt_pause();
302}
303
304static struct platform_driver bcm63xx_wdt = {
305 .probe = bcm63xx_wdt_probe,
306 .remove = __devexit_p(bcm63xx_wdt_remove),
307 .shutdown = bcm63xx_wdt_shutdown,
308 .driver = {
309 .owner = THIS_MODULE,
310 .name = "bcm63xx-wdt",
311 }
312};
313
314static int __init bcm63xx_wdt_init(void)
315{
316 return platform_driver_register(&bcm63xx_wdt);
317}
318
319static void __exit bcm63xx_wdt_exit(void)
320{
321 platform_driver_unregister(&bcm63xx_wdt);
322}
323
324module_init(bcm63xx_wdt_init);
325module_exit(bcm63xx_wdt_exit);
326
327MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
328MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
329MODULE_DESCRIPTION("Driver for the Broadcom BCM63xx SoC watchdog");
330MODULE_LICENSE("GPL");
331MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
332MODULE_ALIAS("platform:bcm63xx-wdt");
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 3d49671cdf5a..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 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
@@ -33,14 +33,8 @@
33 * occur, and the final time the board will reset. 33 * occur, and the final time the board will reset.
34 */ 34 */
35 35
36#ifdef CONFIG_FSL_BOOKE
37#define WDT_PERIOD_DEFAULT 38 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
38#else
39#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
40#endif /* for timing information */
41
42u32 booke_wdt_enabled; 36u32 booke_wdt_enabled;
43u32 booke_wdt_period = WDT_PERIOD_DEFAULT; 37u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
44 38
45#ifdef CONFIG_FSL_BOOKE 39#ifdef CONFIG_FSL_BOOKE
46#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) 40#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
@@ -91,6 +85,22 @@ static unsigned int sec_to_period(unsigned int secs)
91 return 0; 85 return 0;
92} 86}
93 87
88static void __booke_wdt_set(void *data)
89{
90 u32 val;
91
92 val = mfspr(SPRN_TCR);
93 val &= ~WDTP_MASK;
94 val |= WDTP(booke_wdt_period);
95
96 mtspr(SPRN_TCR, val);
97}
98
99static void booke_wdt_set(void)
100{
101 on_each_cpu(__booke_wdt_set, NULL, 0);
102}
103
94static void __booke_wdt_ping(void *data) 104static void __booke_wdt_ping(void *data)
95{ 105{
96 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); 106 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
@@ -114,6 +124,27 @@ static void __booke_wdt_enable(void *data)
114 mtspr(SPRN_TCR, val); 124 mtspr(SPRN_TCR, val);
115} 125}
116 126
127/**
128 * booke_wdt_disable - disable the watchdog on the given CPU
129 *
130 * This function is called on each CPU. It disables the watchdog on that CPU.
131 *
132 * TCR[WRC] cannot be changed once it has been set to non-zero, but we can
133 * effectively disable the watchdog by setting its period to the maximum value.
134 */
135static void __booke_wdt_disable(void *data)
136{
137 u32 val;
138
139 val = mfspr(SPRN_TCR);
140 val &= ~(TCR_WIE | WDTP_MASK);
141 mtspr(SPRN_TCR, val);
142
143 /* clear status to make sure nothing is pending */
144 __booke_wdt_ping(NULL);
145
146}
147
117static ssize_t booke_wdt_write(struct file *file, const char __user *buf, 148static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
118 size_t count, loff_t *ppos) 149 size_t count, loff_t *ppos)
119{ 150{
@@ -166,8 +197,7 @@ static long booke_wdt_ioctl(struct file *file,
166#else 197#else
167 booke_wdt_period = tmp; 198 booke_wdt_period = tmp;
168#endif 199#endif
169 mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) | 200 booke_wdt_set();
170 WDTP(booke_wdt_period));
171 return 0; 201 return 0;
172 case WDIOC_GETTIMEOUT: 202 case WDIOC_GETTIMEOUT:
173 return put_user(booke_wdt_period, p); 203 return put_user(booke_wdt_period, p);
@@ -178,27 +208,52 @@ static long booke_wdt_ioctl(struct file *file,
178 return 0; 208 return 0;
179} 209}
180 210
211/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
212static unsigned long wdt_is_active;
213
181static int booke_wdt_open(struct inode *inode, struct file *file) 214static int booke_wdt_open(struct inode *inode, struct file *file)
182{ 215{
216 /* /dev/watchdog can only be opened once */
217 if (test_and_set_bit(0, &wdt_is_active))
218 return -EBUSY;
219
183 spin_lock(&booke_wdt_lock); 220 spin_lock(&booke_wdt_lock);
184 if (booke_wdt_enabled == 0) { 221 if (booke_wdt_enabled == 0) {
185 booke_wdt_enabled = 1; 222 booke_wdt_enabled = 1;
186 on_each_cpu(__booke_wdt_enable, NULL, 0); 223 on_each_cpu(__booke_wdt_enable, NULL, 0);
187 printk(KERN_INFO 224 pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
188 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 225 period_to_sec(booke_wdt_period));
189 booke_wdt_period);
190 } 226 }
191 spin_unlock(&booke_wdt_lock); 227 spin_unlock(&booke_wdt_lock);
192 228
193 return nonseekable_open(inode, file); 229 return nonseekable_open(inode, file);
194} 230}
195 231
232static int booke_wdt_release(struct inode *inode, struct file *file)
233{
234#ifndef CONFIG_WATCHDOG_NOWAYOUT
235 /* Normally, the watchdog is disabled when /dev/watchdog is closed, but
236 * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the
237 * watchdog should remain enabled. So we disable it only if
238 * CONFIG_WATCHDOG_NOWAYOUT is not defined.
239 */
240 on_each_cpu(__booke_wdt_disable, NULL, 0);
241 booke_wdt_enabled = 0;
242 pr_debug("booke_wdt: watchdog disabled\n");
243#endif
244
245 clear_bit(0, &wdt_is_active);
246
247 return 0;
248}
249
196static const struct file_operations booke_wdt_fops = { 250static const struct file_operations booke_wdt_fops = {
197 .owner = THIS_MODULE, 251 .owner = THIS_MODULE,
198 .llseek = no_llseek, 252 .llseek = no_llseek,
199 .write = booke_wdt_write, 253 .write = booke_wdt_write,
200 .unlocked_ioctl = booke_wdt_ioctl, 254 .unlocked_ioctl = booke_wdt_ioctl,
201 .open = booke_wdt_open, 255 .open = booke_wdt_open,
256 .release = booke_wdt_release,
202}; 257};
203 258
204static struct miscdevice booke_wdt_miscdev = { 259static struct miscdevice booke_wdt_miscdev = {
@@ -216,25 +271,29 @@ static int __init booke_wdt_init(void)
216{ 271{
217 int ret = 0; 272 int ret = 0;
218 273
219 printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); 274 pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
220 ident.firmware_version = cur_cpu_spec->pvr_value; 275 ident.firmware_version = cur_cpu_spec->pvr_value;
221 276
222 ret = misc_register(&booke_wdt_miscdev); 277 ret = misc_register(&booke_wdt_miscdev);
223 if (ret) { 278 if (ret) {
224 printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n", 279 pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
225 WATCHDOG_MINOR, ret); 280 WATCHDOG_MINOR, ret);
226 return ret; 281 return ret;
227 } 282 }
228 283
229 spin_lock(&booke_wdt_lock); 284 spin_lock(&booke_wdt_lock);
230 if (booke_wdt_enabled == 1) { 285 if (booke_wdt_enabled == 1) {
231 printk(KERN_INFO 286 pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
232 "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 287 period_to_sec(booke_wdt_period));
233 booke_wdt_period);
234 on_each_cpu(__booke_wdt_enable, NULL, 0); 288 on_each_cpu(__booke_wdt_enable, NULL, 0);
235 } 289 }
236 spin_unlock(&booke_wdt_lock); 290 spin_unlock(&booke_wdt_lock);
237 291
238 return ret; 292 return ret;
239} 293}
240device_initcall(booke_wdt_init); 294
295module_init(booke_wdt_init);
296module_exit(booke_wdt_exit);
297
298MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
299MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 566343b3c131..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>
@@ -25,7 +25,7 @@
25#include <linux/ioport.h> 25#include <linux/ioport.h>
26#include <linux/timer.h> 26#include <linux/timer.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/smp_lock.h> 28#include <linux/mutex.h>
29#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/of.h> 30#include <linux/of.h>
31#include <linux/of_device.h> 31#include <linux/of_device.h>
@@ -89,6 +89,7 @@ struct cpwd {
89 } devs[WD_NUMDEVS]; 89 } devs[WD_NUMDEVS];
90}; 90};
91 91
92static DEFINE_MUTEX(cpwd_mutex);
92static struct cpwd *cpwd_device; 93static struct cpwd *cpwd_device;
93 94
94/* Sun uses Altera PLD EPF8820ATC144-4 95/* Sun uses Altera PLD EPF8820ATC144-4
@@ -106,13 +107,13 @@ static struct cpwd *cpwd_device;
106 * ------------------- 107 * -------------------
107 * |- counter val -| 108 * |- counter val -|
108 * ------------------- 109 * -------------------
109 * dcntr - Current 16-bit downcounter value. 110 * dcntr - Current 16-bit downcounter value.
110 * When downcounter reaches '0' watchdog expires. 111 * When downcounter reaches '0' watchdog expires.
111 * Reading this register resets downcounter with 112 * Reading this register resets downcounter with
112 * 'limit' value. 113 * 'limit' value.
113 * limit - 16-bit countdown value in 1/10th second increments. 114 * limit - 16-bit countdown value in 1/10th second increments.
114 * Writing this register begins countdown with input value. 115 * Writing this register begins countdown with input value.
115 * Reading from this register does not affect counter. 116 * Reading from this register does not affect counter.
116 * NOTES: After watchdog reset, dcntr and limit contain '1' 117 * NOTES: After watchdog reset, dcntr and limit contain '1'
117 * 118 *
118 * status register (byte access): 119 * status register (byte access):
@@ -122,7 +123,7 @@ static struct cpwd *cpwd_device;
122 * |- UNUSED -| EXP | RUN | 123 * |- UNUSED -| EXP | RUN |
123 * --------------------------- 124 * ---------------------------
124 * status- Bit 0 - Watchdog is running 125 * status- Bit 0 - Watchdog is running
125 * Bit 1 - Watchdog has expired 126 * Bit 1 - Watchdog has expired
126 * 127 *
127 *** PLD register block definition (struct wd_pld_regblk) 128 *** PLD register block definition (struct wd_pld_regblk)
128 * 129 *
@@ -196,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr)
196 * Because of the CP1400 defect this should only be 197 * Because of the CP1400 defect this should only be
197 * called during initialzation or by wd_[start|stop]timer() 198 * called during initialzation or by wd_[start|stop]timer()
198 * 199 *
199 * index - sub-device index, or -1 for 'all' 200 * index - sub-device index, or -1 for 'all'
200 * enable - non-zero to enable interrupts, zero to disable 201 * enable - non-zero to enable interrupts, zero to disable
201 */ 202 */
202static void cpwd_toggleintr(struct cpwd *p, int index, int enable) 203static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
@@ -316,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index)
316 } else { 317 } else {
317 /* Fudge WD_EXPIRED status for defective CP1400-- 318 /* Fudge WD_EXPIRED status for defective CP1400--
318 * IF timer is running 319 * IF timer is running
319 * AND brokenstop is set 320 * AND brokenstop is set
320 * AND an interrupt has been serviced 321 * AND an interrupt has been serviced
321 * we are WD_EXPIRED. 322 * we are WD_EXPIRED.
322 * 323 *
323 * IF timer is running 324 * IF timer is running
324 * AND brokenstop is set 325 * AND brokenstop is set
325 * AND no interrupt has been serviced 326 * AND no interrupt has been serviced
326 * we are WD_FREERUN. 327 * we are WD_FREERUN.
327 */ 328 */
328 if (p->broken && 329 if (p->broken &&
@@ -368,7 +369,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
368{ 369{
369 struct cpwd *p = cpwd_device; 370 struct cpwd *p = cpwd_device;
370 371
371 lock_kernel(); 372 mutex_lock(&cpwd_mutex);
372 switch (iminor(inode)) { 373 switch (iminor(inode)) {
373 case WD0_MINOR: 374 case WD0_MINOR:
374 case WD1_MINOR: 375 case WD1_MINOR:
@@ -376,7 +377,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
376 break; 377 break;
377 378
378 default: 379 default:
379 unlock_kernel(); 380 mutex_unlock(&cpwd_mutex);
380 return -ENODEV; 381 return -ENODEV;
381 } 382 }
382 383
@@ -386,13 +387,13 @@ static int cpwd_open(struct inode *inode, struct file *f)
386 IRQF_SHARED, DRIVER_NAME, p)) { 387 IRQF_SHARED, DRIVER_NAME, p)) {
387 printk(KERN_ERR PFX "Cannot register IRQ %d\n", 388 printk(KERN_ERR PFX "Cannot register IRQ %d\n",
388 p->irq); 389 p->irq);
389 unlock_kernel(); 390 mutex_unlock(&cpwd_mutex);
390 return -EBUSY; 391 return -EBUSY;
391 } 392 }
392 p->initialized = true; 393 p->initialized = true;
393 } 394 }
394 395
395 unlock_kernel(); 396 mutex_unlock(&cpwd_mutex);
396 397
397 return nonseekable_open(inode, f); 398 return nonseekable_open(inode, f);
398} 399}
@@ -482,9 +483,9 @@ static long cpwd_compat_ioctl(struct file *file, unsigned int cmd,
482 case WIOCSTART: 483 case WIOCSTART:
483 case WIOCSTOP: 484 case WIOCSTOP:
484 case WIOCGSTAT: 485 case WIOCGSTAT:
485 lock_kernel(); 486 mutex_lock(&cpwd_mutex);
486 rval = cpwd_ioctl(file, cmd, arg); 487 rval = cpwd_ioctl(file, cmd, arg);
487 unlock_kernel(); 488 mutex_unlock(&cpwd_mutex);
488 break; 489 break;
489 490
490 /* everything else is handled by the generic compat layer */ 491 /* everything else is handled by the generic compat layer */
@@ -524,10 +525,10 @@ static const struct file_operations cpwd_fops = {
524 .write = cpwd_write, 525 .write = cpwd_write,
525 .read = cpwd_read, 526 .read = cpwd_read,
526 .release = cpwd_release, 527 .release = cpwd_release,
528 .llseek = no_llseek,
527}; 529};
528 530
529static int __devinit cpwd_probe(struct platform_device *op, 531static int __devinit cpwd_probe(struct platform_device *op)
530 const struct of_device_id *match)
531{ 532{
532 struct device_node *options; 533 struct device_node *options;
533 const char *str_prop; 534 const char *str_prop;
@@ -612,7 +613,7 @@ static int __devinit cpwd_probe(struct platform_device *op,
612 613
613 if (p->broken) { 614 if (p->broken) {
614 init_timer(&cpwd_timer); 615 init_timer(&cpwd_timer);
615 cpwd_timer.function = cpwd_brokentimer; 616 cpwd_timer.function = cpwd_brokentimer;
616 cpwd_timer.data = (unsigned long) p; 617 cpwd_timer.data = (unsigned long) p;
617 cpwd_timer.expires = WD_BTIMEOUT; 618 cpwd_timer.expires = WD_BTIMEOUT;
618 619
@@ -644,7 +645,7 @@ static int __devexit cpwd_remove(struct platform_device *op)
644 struct cpwd *p = dev_get_drvdata(&op->dev); 645 struct cpwd *p = dev_get_drvdata(&op->dev);
645 int i; 646 int i;
646 647
647 for (i = 0; i < 4; i++) { 648 for (i = 0; i < WD_NUMDEVS; i++) {
648 misc_deregister(&p->devs[i].misc); 649 misc_deregister(&p->devs[i].misc);
649 650
650 if (!p->enabled) { 651 if (!p->enabled) {
@@ -676,7 +677,7 @@ static const struct of_device_id cpwd_match[] = {
676}; 677};
677MODULE_DEVICE_TABLE(of, cpwd_match); 678MODULE_DEVICE_TABLE(of, cpwd_match);
678 679
679static struct of_platform_driver cpwd_driver = { 680static struct platform_driver cpwd_driver = {
680 .driver = { 681 .driver = {
681 .name = DRIVER_NAME, 682 .name = DRIVER_NAME,
682 .owner = THIS_MODULE, 683 .owner = THIS_MODULE,
@@ -688,12 +689,12 @@ static struct of_platform_driver cpwd_driver = {
688 689
689static int __init cpwd_init(void) 690static int __init cpwd_init(void)
690{ 691{
691 return of_register_platform_driver(&cpwd_driver); 692 return platform_driver_register(&cpwd_driver);
692} 693}
693 694
694static void __exit cpwd_exit(void) 695static void __exit cpwd_exit(void)
695{ 696{
696 of_unregister_platform_driver(&cpwd_driver); 697 platform_driver_unregister(&cpwd_driver);
697} 698}
698 699
699module_init(cpwd_init); 700module_init(cpwd_init);
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 596ba604e78d..51b5551b4e3f 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -202,7 +202,6 @@ static struct miscdevice davinci_wdt_miscdev = {
202static int __devinit davinci_wdt_probe(struct platform_device *pdev) 202static int __devinit davinci_wdt_probe(struct platform_device *pdev)
203{ 203{
204 int ret = 0, size; 204 int ret = 0, size;
205 struct resource *res;
206 struct device *dev = &pdev->dev; 205 struct device *dev = &pdev->dev;
207 206
208 wdt_clk = clk_get(dev, NULL); 207 wdt_clk = clk_get(dev, NULL);
@@ -216,31 +215,31 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
216 215
217 dev_info(dev, "heartbeat %d sec\n", heartbeat); 216 dev_info(dev, "heartbeat %d sec\n", heartbeat);
218 217
219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 218 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
220 if (res == NULL) { 219 if (wdt_mem == NULL) {
221 dev_err(dev, "failed to get memory region resource\n"); 220 dev_err(dev, "failed to get memory region resource\n");
222 return -ENOENT; 221 return -ENOENT;
223 } 222 }
224 223
225 size = resource_size(res); 224 size = resource_size(wdt_mem);
226 wdt_mem = request_mem_region(res->start, size, pdev->name); 225 if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
227
228 if (wdt_mem == NULL) {
229 dev_err(dev, "failed to get memory region\n"); 226 dev_err(dev, "failed to get memory region\n");
230 return -ENOENT; 227 return -ENOENT;
231 } 228 }
232 229
233 wdt_base = ioremap(res->start, size); 230 wdt_base = ioremap(wdt_mem->start, size);
234 if (!wdt_base) { 231 if (!wdt_base) {
235 dev_err(dev, "failed to map memory region\n"); 232 dev_err(dev, "failed to map memory region\n");
233 release_mem_region(wdt_mem->start, size);
234 wdt_mem = NULL;
236 return -ENOMEM; 235 return -ENOMEM;
237 } 236 }
238 237
239 ret = misc_register(&davinci_wdt_miscdev); 238 ret = misc_register(&davinci_wdt_miscdev);
240 if (ret < 0) { 239 if (ret < 0) {
241 dev_err(dev, "cannot register misc device\n"); 240 dev_err(dev, "cannot register misc device\n");
242 release_resource(wdt_mem); 241 release_mem_region(wdt_mem->start, size);
243 kfree(wdt_mem); 242 wdt_mem = NULL;
244 } else { 243 } else {
245 set_bit(WDT_DEVICE_INITED, &wdt_status); 244 set_bit(WDT_DEVICE_INITED, &wdt_status);
246 } 245 }
@@ -253,8 +252,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev)
253{ 252{
254 misc_deregister(&davinci_wdt_miscdev); 253 misc_deregister(&davinci_wdt_miscdev);
255 if (wdt_mem) { 254 if (wdt_mem) {
256 release_resource(wdt_mem); 255 release_mem_region(wdt_mem->start, resource_size(wdt_mem));
257 kfree(wdt_mem);
258 wdt_mem = NULL; 256 wdt_mem = NULL;
259 } 257 }
260 258
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 59359c9a5e01..726b7df61fd0 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -188,6 +188,7 @@ static const struct file_operations ep93xx_wdt_fops = {
188 .unlocked_ioctl = ep93xx_wdt_ioctl, 188 .unlocked_ioctl = ep93xx_wdt_ioctl,
189 .open = ep93xx_wdt_open, 189 .open = ep93xx_wdt_open,
190 .release = ep93xx_wdt_release, 190 .release = ep93xx_wdt_release,
191 .llseek = no_llseek,
191}; 192};
192 193
193static struct miscdevice ep93xx_wdt_miscdev = { 194static struct miscdevice ep93xx_wdt_miscdev = {
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/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index 7e5c266cda48..d4d8d1fdccc4 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -42,18 +42,21 @@
42#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ 42#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
43#define SIO_REG_DEVREV 0x22 /* Device revision */ 43#define SIO_REG_DEVREV 0x22 /* Device revision */
44#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ 44#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
45#define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */
46#define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */
47#define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */
48#define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */
45#define SIO_REG_ENABLE 0x30 /* Logical device enable */ 49#define SIO_REG_ENABLE 0x30 /* Logical device enable */
46#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ 50#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
47 51
48#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ 52#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
49#define SIO_F71808_ID 0x0901 /* Chipset ID */ 53#define SIO_F71808_ID 0x0901 /* Chipset ID */
50#define SIO_F71858_ID 0x0507 /* Chipset ID */ 54#define SIO_F71858_ID 0x0507 /* Chipset ID */
51#define SIO_F71862_ID 0x0601 /* Chipset ID */ 55#define SIO_F71862_ID 0x0601 /* Chipset ID */
56#define SIO_F71869_ID 0x0814 /* Chipset ID */
52#define SIO_F71882_ID 0x0541 /* Chipset ID */ 57#define SIO_F71882_ID 0x0541 /* Chipset ID */
53#define SIO_F71889_ID 0x0723 /* Chipset ID */ 58#define SIO_F71889_ID 0x0723 /* Chipset ID */
54 59
55#define F71882FG_REG_START 0x01
56
57#define F71808FG_REG_WDO_CONF 0xf0 60#define F71808FG_REG_WDO_CONF 0xf0
58#define F71808FG_REG_WDT_CONF 0xf5 61#define F71808FG_REG_WDT_CONF 0xf5
59#define F71808FG_REG_WD_TIME 0xf6 62#define F71808FG_REG_WD_TIME 0xf6
@@ -70,13 +73,15 @@
70#define WATCHDOG_MAX_TIMEOUT (60 * 255) 73#define WATCHDOG_MAX_TIMEOUT (60 * 255)
71#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for 74#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for
72 watchdog signal */ 75 watchdog signal */
76#define WATCHDOG_F71862FG_PIN 63 /* default watchdog reset output
77 pin number 63 */
73 78
74static unsigned short force_id; 79static unsigned short force_id;
75module_param(force_id, ushort, 0); 80module_param(force_id, ushort, 0);
76MODULE_PARM_DESC(force_id, "Override the detected device ID"); 81MODULE_PARM_DESC(force_id, "Override the detected device ID");
77 82
78static const int max_timeout = WATCHDOG_MAX_TIMEOUT; 83static const int max_timeout = WATCHDOG_MAX_TIMEOUT;
79static int timeout = 60; /* default timeout in seconds */ 84static int timeout = WATCHDOG_TIMEOUT; /* default timeout in seconds */
80module_param(timeout, int, 0); 85module_param(timeout, int, 0);
81MODULE_PARM_DESC(timeout, 86MODULE_PARM_DESC(timeout,
82 "Watchdog timeout in seconds. 1<= timeout <=" 87 "Watchdog timeout in seconds. 1<= timeout <="
@@ -89,6 +94,12 @@ MODULE_PARM_DESC(pulse_width,
89 "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" 94 "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms"
90 " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); 95 " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")");
91 96
97static unsigned int f71862fg_pin = WATCHDOG_F71862FG_PIN;
98module_param(f71862fg_pin, uint, 0);
99MODULE_PARM_DESC(f71862fg_pin,
100 "Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63"
101 " (default=" __MODULE_STRING(WATCHDOG_F71862FG_PIN)")");
102
92static int nowayout = WATCHDOG_NOWAYOUT; 103static int nowayout = WATCHDOG_NOWAYOUT;
93module_param(nowayout, bool, 0444); 104module_param(nowayout, bool, 0444);
94MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); 105MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
@@ -98,12 +109,13 @@ module_param(start_withtimeout, uint, 0);
98MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" 109MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with"
99 " given initial timeout. Zero (default) disables this feature."); 110 " given initial timeout. Zero (default) disables this feature.");
100 111
101enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; 112enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg };
102 113
103static const char *f71808e_names[] = { 114static const char *f71808e_names[] = {
104 "f71808fg", 115 "f71808fg",
105 "f71858fg", 116 "f71858fg",
106 "f71862fg", 117 "f71862fg",
118 "f71869",
107 "f71882fg", 119 "f71882fg",
108 "f71889fg", 120 "f71889fg",
109}; 121};
@@ -282,6 +294,28 @@ exit_unlock:
282 return err; 294 return err;
283} 295}
284 296
297static int f71862fg_pin_configure(unsigned short ioaddr)
298{
299 /* When ioaddr is non-zero the calling function has to take care of
300 mutex handling and superio preparation! */
301
302 if (f71862fg_pin == 63) {
303 if (ioaddr) {
304 /* SPI must be disabled first to use this pin! */
305 superio_clear_bit(ioaddr, SIO_REG_ROM_ADDR_SEL, 6);
306 superio_set_bit(ioaddr, SIO_REG_MFUNCT3, 4);
307 }
308 } else if (f71862fg_pin == 56) {
309 if (ioaddr)
310 superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1);
311 } else {
312 printk(KERN_ERR DRVNAME ": Invalid argument f71862fg_pin=%d\n",
313 f71862fg_pin);
314 return -EINVAL;
315 }
316 return 0;
317}
318
285static int watchdog_start(void) 319static int watchdog_start(void)
286{ 320{
287 /* Make sure we don't die as soon as the watchdog is enabled below */ 321 /* Make sure we don't die as soon as the watchdog is enabled below */
@@ -299,13 +333,30 @@ static int watchdog_start(void)
299 switch (watchdog.type) { 333 switch (watchdog.type) {
300 case f71808fg: 334 case f71808fg:
301 /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ 335 /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */
302 superio_clear_bit(watchdog.sioaddr, 0x2a, 3); 336 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT2, 3);
303 superio_clear_bit(watchdog.sioaddr, 0x2b, 3); 337 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 3);
338 break;
339
340 case f71862fg:
341 err = f71862fg_pin_configure(watchdog.sioaddr);
342 if (err)
343 goto exit_superio;
344 break;
345
346 case f71869:
347 /* GPIO14 --> WDTRST# */
348 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 4);
304 break; 349 break;
305 350
306 case f71882fg: 351 case f71882fg:
307 /* Set pin 56 to WDTRST# */ 352 /* Set pin 56 to WDTRST# */
308 superio_set_bit(watchdog.sioaddr, 0x29, 1); 353 superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1);
354 break;
355
356 case f71889fg:
357 /* set pin 40 to WDTRST# */
358 superio_outb(watchdog.sioaddr, SIO_REG_MFUNCT3,
359 superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf);
309 break; 360 break;
310 361
311 default: 362 default:
@@ -705,14 +756,19 @@ static int __init f71808e_find(int sioaddr)
705 case SIO_F71808_ID: 756 case SIO_F71808_ID:
706 watchdog.type = f71808fg; 757 watchdog.type = f71808fg;
707 break; 758 break;
759 case SIO_F71862_ID:
760 watchdog.type = f71862fg;
761 err = f71862fg_pin_configure(0); /* validate module parameter */
762 break;
763 case SIO_F71869_ID:
764 watchdog.type = f71869;
765 break;
708 case SIO_F71882_ID: 766 case SIO_F71882_ID:
709 watchdog.type = f71882fg; 767 watchdog.type = f71882fg;
710 break; 768 break;
711 case SIO_F71862_ID:
712 case SIO_F71889_ID: 769 case SIO_F71889_ID:
713 /* These have a watchdog, though it isn't implemented (yet). */ 770 watchdog.type = f71889fg;
714 err = -ENOSYS; 771 break;
715 goto exit;
716 case SIO_F71858_ID: 772 case SIO_F71858_ID:
717 /* Confirmed (by datasheet) not to have a watchdog. */ 773 /* Confirmed (by datasheet) not to have a watchdog. */
718 err = -ENODEV; 774 err = -ENODEV;
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 9c21d19043a6..b146082bd85a 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -30,6 +30,7 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/miscdevice.h> 31#include <linux/miscdevice.h>
32#include <linux/watchdog.h> 32#include <linux/watchdog.h>
33#include <linux/fs.h>
33#include <linux/of.h> 34#include <linux/of.h>
34#include <linux/of_platform.h> 35#include <linux/of_platform.h>
35#include <linux/io.h> 36#include <linux/io.h>
@@ -260,8 +261,7 @@ static struct miscdevice gef_wdt_miscdev = {
260}; 261};
261 262
262 263
263static int __devinit gef_wdt_probe(struct platform_device *dev, 264static int __devinit gef_wdt_probe(struct platform_device *dev)
264 const struct of_device_id *match)
265{ 265{
266 int timeout = 10; 266 int timeout = 10;
267 u32 freq; 267 u32 freq;
@@ -302,7 +302,7 @@ static const struct of_device_id gef_wdt_ids[] = {
302 {}, 302 {},
303}; 303};
304 304
305static struct of_platform_driver gef_wdt_driver = { 305static struct platform_driver gef_wdt_driver = {
306 .driver = { 306 .driver = {
307 .name = "gef_wdt", 307 .name = "gef_wdt",
308 .owner = THIS_MODULE, 308 .owner = THIS_MODULE,
@@ -314,12 +314,12 @@ static struct of_platform_driver gef_wdt_driver = {
314static int __init gef_wdt_init(void) 314static int __init gef_wdt_init(void)
315{ 315{
316 printk(KERN_INFO "GE watchdog driver\n"); 316 printk(KERN_INFO "GE watchdog driver\n");
317 return of_register_platform_driver(&gef_wdt_driver); 317 return platform_driver_register(&gef_wdt_driver);
318} 318}
319 319
320static void __exit gef_wdt_exit(void) 320static void __exit gef_wdt_exit(void)
321{ 321{
322 of_unregister_platform_driver(&gef_wdt_driver); 322 platform_driver_unregister(&gef_wdt_driver);
323} 323}
324 324
325module_init(gef_wdt_init); 325module_init(gef_wdt_init);
@@ -329,4 +329,4 @@ MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>");
329MODULE_DESCRIPTION("GE watchdog driver"); 329MODULE_DESCRIPTION("GE watchdog driver");
330MODULE_LICENSE("GPL"); 330MODULE_LICENSE("GPL");
331MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 331MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
332MODULE_ALIAS("platform: gef_wdt"); 332MODULE_ALIAS("platform:gef_wdt");
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 3d77116e4634..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 */
@@ -469,7 +469,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
469 unsigned long rom_pl; 469 unsigned long rom_pl;
470 static int die_nmi_called; 470 static int die_nmi_called;
471 471
472 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 472 if (ulReason != DIE_NMIUNKNOWN)
473 goto out; 473 goto out;
474 474
475 if (!hpwdt_nmi_decoding) 475 if (!hpwdt_nmi_decoding)
@@ -642,19 +642,14 @@ static struct notifier_block die_notifier = {
642 */ 642 */
643 643
644#ifdef CONFIG_HPWDT_NMI_DECODING 644#ifdef CONFIG_HPWDT_NMI_DECODING
645#ifdef ARCH_HAS_NMI_WATCHDOG 645#ifdef CONFIG_X86_LOCAL_APIC
646static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) 646static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
647{ 647{
648 /* 648 /*
649 * If nmi_watchdog is turned off then we can turn on 649 * If nmi_watchdog is turned off then we can turn on
650 * our nmi decoding capability. 650 * our nmi decoding capability.
651 */ 651 */
652 if (!nmi_watchdog_active()) 652 hpwdt_nmi_decoding = 1;
653 hpwdt_nmi_decoding = 1;
654 else
655 dev_warn(&dev->dev, "NMI decoding is disabled. To enable this "
656 "functionality you must reboot with nmi_watchdog=0 "
657 "and load the hpwdt driver with priority=1.\n");
658} 653}
659#else 654#else
660static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev) 655static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
@@ -662,7 +657,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
662 dev_warn(&dev->dev, "NMI decoding is disabled. " 657 dev_warn(&dev->dev, "NMI decoding is disabled. "
663 "Your kernel does not support a NMI Watchdog.\n"); 658 "Your kernel does not support a NMI Watchdog.\n");
664} 659}
665#endif /* ARCH_HAS_NMI_WATCHDOG */ 660#endif /* CONFIG_X86_LOCAL_APIC */
666 661
667static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) 662static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
668{ 663{
@@ -715,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
715 return 0; 710 return 0;
716} 711}
717 712
718static void __devexit hpwdt_exit_nmi_decoding(void) 713static void hpwdt_exit_nmi_decoding(void)
719{ 714{
720 unregister_die_notifier(&die_notifier); 715 unregister_die_notifier(&die_notifier);
721 if (cru_rom_addr) 716 if (cru_rom_addr)
@@ -731,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
731 return 0; 726 return 0;
732} 727}
733 728
734static void __devexit hpwdt_exit_nmi_decoding(void) 729static void hpwdt_exit_nmi_decoding(void)
735{ 730{
736} 731}
737#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 69de8713b8e4..5fd020da7c55 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * intel TCO Watchdog Driver 2 * intel TCO Watchdog Driver
3 * 3 *
4 * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. 4 * (c) Copyright 2006-2010 Wim Van Sebroeck <wim@iguana.be>.
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
@@ -26,12 +26,16 @@
26 * document number 301473-002, 301474-026: 82801F (ICH6) 26 * document number 301473-002, 301474-026: 82801F (ICH6)
27 * document number 313082-001, 313075-006: 631xESB, 632xESB 27 * document number 313082-001, 313075-006: 631xESB, 632xESB
28 * document number 307013-003, 307014-024: 82801G (ICH7) 28 * document number 307013-003, 307014-024: 82801G (ICH7)
29 * document number 322896-001, 322897-001: NM10
29 * document number 313056-003, 313057-017: 82801H (ICH8) 30 * document number 313056-003, 313057-017: 82801H (ICH8)
30 * document number 316972-004, 316973-012: 82801I (ICH9) 31 * document number 316972-004, 316973-012: 82801I (ICH9)
31 * document number 319973-002, 319974-002: 82801J (ICH10) 32 * document number 319973-002, 319974-002: 82801J (ICH10)
32 * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) 33 * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
33 * document number 320066-003, 320257-008: EP80597 (IICH) 34 * document number 320066-003, 320257-008: EP80597 (IICH)
34 * document number TBD : Cougar Point (CPT) 35 * document number 324645-001, 324646-001: Cougar Point (CPT)
36 * document number TBD : Patsburg (PBG)
37 * document number TBD : DH89xxCC
38 * document number TBD : Panther Point
35 */ 39 */
36 40
37/* 41/*
@@ -84,6 +88,7 @@ enum iTCO_chipsets {
84 TCO_ICH7DH, /* ICH7DH */ 88 TCO_ICH7DH, /* ICH7DH */
85 TCO_ICH7M, /* ICH7-M & ICH7-U */ 89 TCO_ICH7M, /* ICH7-M & ICH7-U */
86 TCO_ICH7MDH, /* ICH7-M DH */ 90 TCO_ICH7MDH, /* ICH7-M DH */
91 TCO_NM10, /* NM10 */
87 TCO_ICH8, /* ICH8 & ICH8R */ 92 TCO_ICH8, /* ICH8 & ICH8R */
88 TCO_ICH8DH, /* ICH8DH */ 93 TCO_ICH8DH, /* ICH8DH */
89 TCO_ICH8DO, /* ICH8DO */ 94 TCO_ICH8DO, /* ICH8DO */
@@ -146,6 +151,41 @@ enum iTCO_chipsets {
146 TCO_CPT29, /* Cougar Point */ 151 TCO_CPT29, /* Cougar Point */
147 TCO_CPT30, /* Cougar Point */ 152 TCO_CPT30, /* Cougar Point */
148 TCO_CPT31, /* Cougar Point */ 153 TCO_CPT31, /* Cougar Point */
154 TCO_PBG1, /* Patsburg */
155 TCO_PBG2, /* Patsburg */
156 TCO_DH89XXCC, /* DH89xxCC */
157 TCO_PPT0, /* Panther Point */
158 TCO_PPT1, /* Panther Point */
159 TCO_PPT2, /* Panther Point */
160 TCO_PPT3, /* Panther Point */
161 TCO_PPT4, /* Panther Point */
162 TCO_PPT5, /* Panther Point */
163 TCO_PPT6, /* Panther Point */
164 TCO_PPT7, /* Panther Point */
165 TCO_PPT8, /* Panther Point */
166 TCO_PPT9, /* Panther Point */
167 TCO_PPT10, /* Panther Point */
168 TCO_PPT11, /* Panther Point */
169 TCO_PPT12, /* Panther Point */
170 TCO_PPT13, /* Panther Point */
171 TCO_PPT14, /* Panther Point */
172 TCO_PPT15, /* Panther Point */
173 TCO_PPT16, /* Panther Point */
174 TCO_PPT17, /* Panther Point */
175 TCO_PPT18, /* Panther Point */
176 TCO_PPT19, /* Panther Point */
177 TCO_PPT20, /* Panther Point */
178 TCO_PPT21, /* Panther Point */
179 TCO_PPT22, /* Panther Point */
180 TCO_PPT23, /* Panther Point */
181 TCO_PPT24, /* Panther Point */
182 TCO_PPT25, /* Panther Point */
183 TCO_PPT26, /* Panther Point */
184 TCO_PPT27, /* Panther Point */
185 TCO_PPT28, /* Panther Point */
186 TCO_PPT29, /* Panther Point */
187 TCO_PPT30, /* Panther Point */
188 TCO_PPT31, /* Panther Point */
149}; 189};
150 190
151static struct { 191static struct {
@@ -171,6 +211,7 @@ static struct {
171 {"ICH7DH", 2}, 211 {"ICH7DH", 2},
172 {"ICH7-M or ICH7-U", 2}, 212 {"ICH7-M or ICH7-U", 2},
173 {"ICH7-M DH", 2}, 213 {"ICH7-M DH", 2},
214 {"NM10", 2},
174 {"ICH8 or ICH8R", 2}, 215 {"ICH8 or ICH8R", 2},
175 {"ICH8DH", 2}, 216 {"ICH8DH", 2},
176 {"ICH8DO", 2}, 217 {"ICH8DO", 2},
@@ -233,10 +274,45 @@ static struct {
233 {"Cougar Point", 2}, 274 {"Cougar Point", 2},
234 {"Cougar Point", 2}, 275 {"Cougar Point", 2},
235 {"Cougar Point", 2}, 276 {"Cougar Point", 2},
277 {"Patsburg", 2},
278 {"Patsburg", 2},
279 {"DH89xxCC", 2},
280 {"Panther Point", 2},
281 {"Panther Point", 2},
282 {"Panther Point", 2},
283 {"Panther Point", 2},
284 {"Panther Point", 2},
285 {"Panther Point", 2},
286 {"Panther Point", 2},
287 {"Panther Point", 2},
288 {"Panther Point", 2},
289 {"Panther Point", 2},
290 {"Panther Point", 2},
291 {"Panther Point", 2},
292 {"Panther Point", 2},
293 {"Panther Point", 2},
294 {"Panther Point", 2},
295 {"Panther Point", 2},
296 {"Panther Point", 2},
297 {"Panther Point", 2},
298 {"Panther Point", 2},
299 {"Panther Point", 2},
300 {"Panther Point", 2},
301 {"Panther Point", 2},
302 {"Panther Point", 2},
303 {"Panther Point", 2},
304 {"Panther Point", 2},
305 {"Panther Point", 2},
306 {"Panther Point", 2},
307 {"Panther Point", 2},
308 {"Panther Point", 2},
309 {"Panther Point", 2},
310 {"Panther Point", 2},
311 {"Panther Point", 2},
236 {NULL, 0} 312 {NULL, 0}
237}; 313};
238 314
239#define ITCO_PCI_DEVICE(dev, data) \ 315#define ITCO_PCI_DEVICE(dev, data) \
240 .vendor = PCI_VENDOR_ID_INTEL, \ 316 .vendor = PCI_VENDOR_ID_INTEL, \
241 .device = dev, \ 317 .device = dev, \
242 .subvendor = PCI_ANY_ID, \ 318 .subvendor = PCI_ANY_ID, \
@@ -251,7 +327,7 @@ static struct {
251 * pci_driver, because the I/O Controller Hub has also other 327 * pci_driver, because the I/O Controller Hub has also other
252 * functions that probably will be registered by other drivers. 328 * functions that probably will be registered by other drivers.
253 */ 329 */
254static struct pci_device_id iTCO_wdt_pci_tbl[] = { 330static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
255 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)}, 331 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)},
256 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)}, 332 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)},
257 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)}, 333 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)},
@@ -286,6 +362,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
286 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, 362 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)},
287 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, 363 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
288 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, 364 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
365 { ITCO_PCI_DEVICE(0x27bc, TCO_NM10)},
289 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, 366 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
290 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, 367 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
291 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, 368 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
@@ -348,6 +425,41 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
348 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, 425 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)},
349 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, 426 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)},
350 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, 427 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)},
428 { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)},
429 { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)},
430 { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)},
431 { ITCO_PCI_DEVICE(0x1e40, TCO_PPT0)},
432 { ITCO_PCI_DEVICE(0x1e41, TCO_PPT1)},
433 { ITCO_PCI_DEVICE(0x1e42, TCO_PPT2)},
434 { ITCO_PCI_DEVICE(0x1e43, TCO_PPT3)},
435 { ITCO_PCI_DEVICE(0x1e44, TCO_PPT4)},
436 { ITCO_PCI_DEVICE(0x1e45, TCO_PPT5)},
437 { ITCO_PCI_DEVICE(0x1e46, TCO_PPT6)},
438 { ITCO_PCI_DEVICE(0x1e47, TCO_PPT7)},
439 { ITCO_PCI_DEVICE(0x1e48, TCO_PPT8)},
440 { ITCO_PCI_DEVICE(0x1e49, TCO_PPT9)},
441 { ITCO_PCI_DEVICE(0x1e4a, TCO_PPT10)},
442 { ITCO_PCI_DEVICE(0x1e4b, TCO_PPT11)},
443 { ITCO_PCI_DEVICE(0x1e4c, TCO_PPT12)},
444 { ITCO_PCI_DEVICE(0x1e4d, TCO_PPT13)},
445 { ITCO_PCI_DEVICE(0x1e4e, TCO_PPT14)},
446 { ITCO_PCI_DEVICE(0x1e4f, TCO_PPT15)},
447 { ITCO_PCI_DEVICE(0x1e50, TCO_PPT16)},
448 { ITCO_PCI_DEVICE(0x1e51, TCO_PPT17)},
449 { ITCO_PCI_DEVICE(0x1e52, TCO_PPT18)},
450 { ITCO_PCI_DEVICE(0x1e53, TCO_PPT19)},
451 { ITCO_PCI_DEVICE(0x1e54, TCO_PPT20)},
452 { ITCO_PCI_DEVICE(0x1e55, TCO_PPT21)},
453 { ITCO_PCI_DEVICE(0x1e56, TCO_PPT22)},
454 { ITCO_PCI_DEVICE(0x1e57, TCO_PPT23)},
455 { ITCO_PCI_DEVICE(0x1e58, TCO_PPT24)},
456 { ITCO_PCI_DEVICE(0x1e59, TCO_PPT25)},
457 { ITCO_PCI_DEVICE(0x1e5a, TCO_PPT26)},
458 { ITCO_PCI_DEVICE(0x1e5b, TCO_PPT27)},
459 { ITCO_PCI_DEVICE(0x1e5c, TCO_PPT28)},
460 { ITCO_PCI_DEVICE(0x1e5d, TCO_PPT29)},
461 { ITCO_PCI_DEVICE(0x1e5e, TCO_PPT30)},
462 { ITCO_PCI_DEVICE(0x1e5f, TCO_PPT31)},
351 { 0, }, /* End of list */ 463 { 0, }, /* End of list */
352}; 464};
353MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 465MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -374,7 +486,7 @@ static char expect_release;
374static struct { /* this is private data for the iTCO_wdt device */ 486static struct { /* this is private data for the iTCO_wdt device */
375 /* TCO version/generation */ 487 /* TCO version/generation */
376 unsigned int iTCO_version; 488 unsigned int iTCO_version;
377 /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 489 /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
378 unsigned long ACPIBASE; 490 unsigned long ACPIBASE;
379 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ 491 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
380 unsigned long __iomem *gcs; 492 unsigned long __iomem *gcs;
@@ -467,7 +579,7 @@ static int iTCO_wdt_start(void)
467 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 579 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
468 spin_unlock(&iTCO_wdt_private.io_lock); 580 spin_unlock(&iTCO_wdt_private.io_lock);
469 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " 581 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
470 "reboot disabled by hardware\n"); 582 "reboot disabled by hardware/BIOS\n");
471 return -EIO; 583 return -EIO;
472 } 584 }
473 585
@@ -781,8 +893,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
781 base_address &= 0x0000ff80; 893 base_address &= 0x0000ff80;
782 if (base_address == 0x00000000) { 894 if (base_address == 0x00000000) {
783 /* Something's wrong here, ACPIBASE has to be set */ 895 /* Something's wrong here, ACPIBASE has to be set */
784 printk(KERN_ERR PFX "failed to get TCOBASE address\n"); 896 printk(KERN_ERR PFX "failed to get TCOBASE address, "
785 pci_dev_put(pdev); 897 "device disabled by hardware/BIOS\n");
786 return -ENODEV; 898 return -ENODEV;
787 } 899 }
788 iTCO_wdt_private.iTCO_version = 900 iTCO_wdt_private.iTCO_version =
@@ -797,7 +909,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
797 if (iTCO_wdt_private.iTCO_version == 2) { 909 if (iTCO_wdt_private.iTCO_version == 2) {
798 pci_read_config_dword(pdev, 0xf0, &base_address); 910 pci_read_config_dword(pdev, 0xf0, &base_address);
799 if ((base_address & 1) == 0) { 911 if ((base_address & 1) == 0) {
800 printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); 912 printk(KERN_ERR PFX "RCBA is disabled by hardware"
913 "/BIOS, device disabled\n");
801 ret = -ENODEV; 914 ret = -ENODEV;
802 goto out; 915 goto out;
803 } 916 }
@@ -808,7 +921,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
808 /* Check chipset's NO_REBOOT bit */ 921 /* Check chipset's NO_REBOOT bit */
809 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { 922 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
810 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " 923 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
811 "platform may have disabled it\n"); 924 "device disabled by hardware/BIOS\n");
812 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 925 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
813 goto out_unmap; 926 goto out_unmap;
814 } 927 }
@@ -819,7 +932,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
819 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 932 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
820 if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 933 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
821 printk(KERN_ERR PFX 934 printk(KERN_ERR PFX
822 "I/O address 0x%04lx already in use\n", SMI_EN); 935 "I/O address 0x%04lx already in use, "
936 "device disabled\n", SMI_EN);
823 ret = -EIO; 937 ret = -EIO;
824 goto out_unmap; 938 goto out_unmap;
825 } 939 }
@@ -831,8 +945,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
831 /* The TCO I/O registers reside in a 32-byte range pointed to 945 /* The TCO I/O registers reside in a 32-byte range pointed to
832 by the TCOBASE value */ 946 by the TCOBASE value */
833 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { 947 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
834 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", 948 printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
835 TCOBASE); 949 "device disabled\n", TCOBASE);
836 ret = -EIO; 950 ret = -EIO;
837 goto unreg_smi_en; 951 goto unreg_smi_en;
838 } 952 }
@@ -880,7 +994,6 @@ out_unmap:
880 if (iTCO_wdt_private.iTCO_version == 2) 994 if (iTCO_wdt_private.iTCO_version == 2)
881 iounmap(iTCO_wdt_private.gcs); 995 iounmap(iTCO_wdt_private.gcs);
882out: 996out:
883 pci_dev_put(iTCO_wdt_private.pdev);
884 iTCO_wdt_private.ACPIBASE = 0; 997 iTCO_wdt_private.ACPIBASE = 0;
885 return ret; 998 return ret;
886} 999}
@@ -921,7 +1034,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
921 } 1034 }
922 1035
923 if (!found) 1036 if (!found)
924 printk(KERN_INFO PFX "No card detected\n"); 1037 printk(KERN_INFO PFX "No device detected.\n");
925 1038
926 return ret; 1039 return ret;
927} 1040}
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 2ee7dac55a3c..86f7cac1026c 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -270,7 +270,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
270 return -ENOMEM; 270 return -ENOMEM;
271 } 271 }
272 272
273 imx2_wdt.clk = clk_get_sys("imx-wdt.0", NULL); 273 imx2_wdt.clk = clk_get(&pdev->dev, NULL);
274 if (IS_ERR(imx2_wdt.clk)) { 274 if (IS_ERR(imx2_wdt.clk)) {
275 dev_err(&pdev->dev, "can't get Watchdog clock\n"); 275 dev_err(&pdev->dev, "can't get Watchdog clock\n");
276 return PTR_ERR(imx2_wdt.clk); 276 return PTR_ERR(imx2_wdt.clk);
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
new file mode 100644
index 000000000000..ba4386066a42
--- /dev/null
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -0,0 +1,571 @@
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 <asm/irq.h>
46#include <asm/atomic.h>
47#include <asm/intel_scu_ipc.h>
48#include <asm/apb_timer.h>
49#include <asm/mrst.h>
50
51#include "intel_scu_watchdog.h"
52
53/* Bounds number of times we will retry loading time count */
54/* This retry is a work around for a silicon bug. */
55#define MAX_RETRY 16
56
57#define IPC_SET_WATCHDOG_TIMER 0xF8
58
59static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN;
60module_param(timer_margin, int, 0);
61MODULE_PARM_DESC(timer_margin,
62 "Watchdog timer margin"
63 "Time between interrupt and resetting the system"
64 "The range is from 1 to 160"
65 "This is the time for all keep alives to arrive");
66
67static int timer_set = DEFAULT_TIME;
68module_param(timer_set, int, 0);
69MODULE_PARM_DESC(timer_set,
70 "Default Watchdog timer setting"
71 "Complete cycle time"
72 "The range is from 1 to 170"
73 "This is the time for all keep alives to arrive");
74
75/* After watchdog device is closed, check force_boot. If:
76 * force_boot == 0, then force boot on next watchdog interrupt after close,
77 * force_boot == 1, then force boot immediately when device is closed.
78 */
79static int force_boot;
80module_param(force_boot, int, 0);
81MODULE_PARM_DESC(force_boot,
82 "A value of 1 means that the driver will reboot"
83 "the system immediately if the /dev/watchdog device is closed"
84 "A value of 0 means that when /dev/watchdog device is closed"
85 "the watchdog timer will be refreshed for one more interval"
86 "of length: timer_set. At the end of this interval, the"
87 "watchdog timer will reset the system."
88 );
89
90/* there is only one device in the system now; this can be made into
91 * an array in the future if we have more than one device */
92
93static struct intel_scu_watchdog_dev watchdog_device;
94
95/* Forces restart, if force_reboot is set */
96static void watchdog_fire(void)
97{
98 if (force_boot) {
99 printk(KERN_CRIT PFX "Initiating system reboot.\n");
100 emergency_restart();
101 printk(KERN_CRIT PFX "Reboot didn't ?????\n");
102 }
103
104 else {
105 printk(KERN_CRIT PFX "Immediate Reboot Disabled\n");
106 printk(KERN_CRIT PFX
107 "System will reset when watchdog timer times out!\n");
108 }
109}
110
111static int check_timer_margin(int new_margin)
112{
113 if ((new_margin < MIN_TIME_CYCLE) ||
114 (new_margin > MAX_TIME - timer_set)) {
115 pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n",
116 new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
117 return -EINVAL;
118 }
119 return 0;
120}
121
122/*
123 * IPC operations
124 */
125static int watchdog_set_ipc(int soft_threshold, int threshold)
126{
127 u32 *ipc_wbuf;
128 u8 cbuf[16] = { '\0' };
129 int ipc_ret = 0;
130
131 ipc_wbuf = (u32 *)&cbuf;
132 ipc_wbuf[0] = soft_threshold;
133 ipc_wbuf[1] = threshold;
134
135 ipc_ret = intel_scu_ipc_command(
136 IPC_SET_WATCHDOG_TIMER,
137 0,
138 ipc_wbuf,
139 2,
140 NULL,
141 0);
142
143 if (ipc_ret != 0)
144 pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);
145
146 return ipc_ret;
147};
148
149/*
150 * Intel_SCU operations
151 */
152
153/* timer interrupt handler */
154static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
155{
156 int int_status;
157 int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
158
159 pr_debug("Watchdog timer: irq, int_status: %x\n", int_status);
160
161 if (int_status != 0)
162 return IRQ_NONE;
163
164 /* has the timer been started? If not, then this is spurious */
165 if (watchdog_device.timer_started == 0) {
166 pr_debug("Watchdog timer: spurious interrupt received\n");
167 return IRQ_HANDLED;
168 }
169
170 /* temporarily disable the timer */
171 iowrite32(0x00000002, watchdog_device.timer_control_addr);
172
173 /* set the timer to the threshold */
174 iowrite32(watchdog_device.threshold,
175 watchdog_device.timer_load_count_addr);
176
177 /* allow the timer to run */
178 iowrite32(0x00000003, watchdog_device.timer_control_addr);
179
180 return IRQ_HANDLED;
181}
182
183static int intel_scu_keepalive(void)
184{
185
186 /* read eoi register - clears interrupt */
187 ioread32(watchdog_device.timer_clear_interrupt_addr);
188
189 /* temporarily disable the timer */
190 iowrite32(0x00000002, watchdog_device.timer_control_addr);
191
192 /* set the timer to the soft_threshold */
193 iowrite32(watchdog_device.soft_threshold,
194 watchdog_device.timer_load_count_addr);
195
196 /* allow the timer to run */
197 iowrite32(0x00000003, watchdog_device.timer_control_addr);
198
199 return 0;
200}
201
202static int intel_scu_stop(void)
203{
204 iowrite32(0, watchdog_device.timer_control_addr);
205 return 0;
206}
207
208static int intel_scu_set_heartbeat(u32 t)
209{
210 int ipc_ret;
211 int retry_count;
212 u32 soft_value;
213 u32 hw_pre_value;
214 u32 hw_value;
215
216 watchdog_device.timer_set = t;
217 watchdog_device.threshold =
218 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
219 watchdog_device.soft_threshold =
220 (watchdog_device.timer_set - timer_margin)
221 * watchdog_device.timer_tbl_ptr->freq_hz;
222
223 pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n",
224 watchdog_device.timer_tbl_ptr->freq_hz);
225 pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n",
226 watchdog_device.timer_set);
227 pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n",
228 timer_margin);
229 pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n",
230 watchdog_device.threshold);
231 pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n",
232 watchdog_device.soft_threshold);
233
234 /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
235 /* watchdog timing come out right. */
236 watchdog_device.threshold =
237 watchdog_device.threshold / FREQ_ADJUSTMENT;
238 watchdog_device.soft_threshold =
239 watchdog_device.soft_threshold / FREQ_ADJUSTMENT;
240
241 /* temporarily disable the timer */
242 iowrite32(0x00000002, watchdog_device.timer_control_addr);
243
244 /* send the threshold and soft_threshold via IPC to the processor */
245 ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold,
246 watchdog_device.threshold);
247
248 if (ipc_ret != 0) {
249 /* Make sure the watchdog timer is stopped */
250 intel_scu_stop();
251 return ipc_ret;
252 }
253
254 /* Soft Threshold set loop. Early versions of silicon did */
255 /* not always set this count correctly. This loop checks */
256 /* the value and retries if it was not set correctly. */
257
258 retry_count = 0;
259 soft_value = watchdog_device.soft_threshold & 0xFFFF0000;
260 do {
261
262 /* Make sure timer is stopped */
263 intel_scu_stop();
264
265 if (MAX_RETRY < retry_count++) {
266 /* Unable to set timer value */
267 pr_err("Watchdog timer: Unable to set timer\n");
268 return -ENODEV;
269 }
270
271 /* set the timer to the soft threshold */
272 iowrite32(watchdog_device.soft_threshold,
273 watchdog_device.timer_load_count_addr);
274
275 /* read count value before starting timer */
276 hw_pre_value = ioread32(watchdog_device.timer_load_count_addr);
277 hw_pre_value = hw_pre_value & 0xFFFF0000;
278
279 /* Start the timer */
280 iowrite32(0x00000003, watchdog_device.timer_control_addr);
281
282 /* read the value the time loaded into its count reg */
283 hw_value = ioread32(watchdog_device.timer_load_count_addr);
284 hw_value = hw_value & 0xFFFF0000;
285
286
287 } while (soft_value != hw_value);
288
289 watchdog_device.timer_started = 1;
290
291 return 0;
292}
293
294/*
295 * /dev/watchdog handling
296 */
297
298static int intel_scu_open(struct inode *inode, struct file *file)
299{
300
301 /* Set flag to indicate that watchdog device is open */
302 if (test_and_set_bit(0, &watchdog_device.driver_open))
303 return -EBUSY;
304
305 /* Check for reopen of driver. Reopens are not allowed */
306 if (watchdog_device.driver_closed)
307 return -EPERM;
308
309 return nonseekable_open(inode, file);
310}
311
312static int intel_scu_release(struct inode *inode, struct file *file)
313{
314 /*
315 * This watchdog should not be closed, after the timer
316 * is started with the WDIPC_SETTIMEOUT ioctl
317 * If force_boot is set watchdog_fire() will cause an
318 * immediate reset. If force_boot is not set, the watchdog
319 * timer is refreshed for one more interval. At the end
320 * of that interval, the watchdog timer will reset the system.
321 */
322
323 if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
324 pr_debug("Watchdog timer: intel_scu_release, without open\n");
325 return -ENOTTY;
326 }
327
328 if (!watchdog_device.timer_started) {
329 /* Just close, since timer has not been started */
330 pr_debug("Watchdog timer: closed, without starting timer\n");
331 return 0;
332 }
333
334 printk(KERN_CRIT PFX
335 "Unexpected close of /dev/watchdog!\n");
336
337 /* Since the timer was started, prevent future reopens */
338 watchdog_device.driver_closed = 1;
339
340 /* Refresh the timer for one more interval */
341 intel_scu_keepalive();
342
343 /* Reboot system (if force_boot is set) */
344 watchdog_fire();
345
346 /* We should only reach this point if force_boot is not set */
347 return 0;
348}
349
350static ssize_t intel_scu_write(struct file *file,
351 char const *data,
352 size_t len,
353 loff_t *ppos)
354{
355
356 if (watchdog_device.timer_started)
357 /* Watchdog already started, keep it alive */
358 intel_scu_keepalive();
359 else
360 /* Start watchdog with timer value set by init */
361 intel_scu_set_heartbeat(watchdog_device.timer_set);
362
363 return len;
364}
365
366static long intel_scu_ioctl(struct file *file,
367 unsigned int cmd,
368 unsigned long arg)
369{
370 void __user *argp = (void __user *)arg;
371 u32 __user *p = argp;
372 u32 new_margin;
373
374
375 static const struct watchdog_info ident = {
376 .options = WDIOF_SETTIMEOUT
377 | WDIOF_KEEPALIVEPING,
378 .firmware_version = 0, /* @todo Get from SCU via
379 ipc_get_scu_fw_version()? */
380 .identity = "Intel_SCU IOH Watchdog" /* len < 32 */
381 };
382
383 switch (cmd) {
384 case WDIOC_GETSUPPORT:
385 return copy_to_user(argp,
386 &ident,
387 sizeof(ident)) ? -EFAULT : 0;
388 case WDIOC_GETSTATUS:
389 case WDIOC_GETBOOTSTATUS:
390 return put_user(0, p);
391 case WDIOC_KEEPALIVE:
392 intel_scu_keepalive();
393
394 return 0;
395 case WDIOC_SETTIMEOUT:
396 if (get_user(new_margin, p))
397 return -EFAULT;
398
399 if (check_timer_margin(new_margin))
400 return -EINVAL;
401
402 if (intel_scu_set_heartbeat(new_margin))
403 return -EINVAL;
404 return 0;
405 case WDIOC_GETTIMEOUT:
406 return put_user(watchdog_device.soft_threshold, p);
407
408 default:
409 return -ENOTTY;
410 }
411}
412
413/*
414 * Notifier for system down
415 */
416static int intel_scu_notify_sys(struct notifier_block *this,
417 unsigned long code,
418 void *another_unused)
419{
420 if (code == SYS_DOWN || code == SYS_HALT)
421 /* Turn off the watchdog timer. */
422 intel_scu_stop();
423 return NOTIFY_DONE;
424}
425
426/*
427 * Kernel Interfaces
428 */
429static const struct file_operations intel_scu_fops = {
430 .owner = THIS_MODULE,
431 .llseek = no_llseek,
432 .write = intel_scu_write,
433 .unlocked_ioctl = intel_scu_ioctl,
434 .open = intel_scu_open,
435 .release = intel_scu_release,
436};
437
438static int __init intel_scu_watchdog_init(void)
439{
440 int ret;
441 u32 __iomem *tmp_addr;
442
443 /*
444 * We don't really need to check this as the SFI timer get will fail
445 * but if we do so we can exit with a clearer reason and no noise.
446 *
447 * If it isn't an intel MID device then it doesn't have this watchdog
448 */
449 if (!mrst_identify_cpu())
450 return -ENODEV;
451
452 /* Check boot parameters to verify that their initial values */
453 /* are in range. */
454 /* Check value of timer_set boot parameter */
455 if ((timer_set < MIN_TIME_CYCLE) ||
456 (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
457 pr_err("Watchdog timer: value of timer_set %x (hex) "
458 "is out of range from %x to %x (hex)\n",
459 timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
460 return -EINVAL;
461 }
462
463 /* Check value of timer_margin boot parameter */
464 if (check_timer_margin(timer_margin))
465 return -EINVAL;
466
467 watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
468
469 if (watchdog_device.timer_tbl_ptr == NULL) {
470 pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
471 return -ENODEV;
472 }
473 /* make sure the timer exists */
474 if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
475 pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
476 sfi_mtimer_num);
477 return -ENODEV;
478 }
479
480 if (watchdog_device.timer_tbl_ptr->irq == 0) {
481 pr_debug("Watchdog timer: timer %d invalid irq\n",
482 sfi_mtimer_num);
483 return -ENODEV;
484 }
485
486 tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr,
487 20);
488
489 if (tmp_addr == NULL) {
490 pr_debug("Watchdog timer: timer unable to ioremap\n");
491 return -ENOMEM;
492 }
493
494 watchdog_device.timer_load_count_addr = tmp_addr++;
495 watchdog_device.timer_current_value_addr = tmp_addr++;
496 watchdog_device.timer_control_addr = tmp_addr++;
497 watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
498 watchdog_device.timer_interrupt_status_addr = tmp_addr++;
499
500 /* Set the default time values in device structure */
501
502 watchdog_device.timer_set = timer_set;
503 watchdog_device.threshold =
504 timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
505 watchdog_device.soft_threshold =
506 (watchdog_device.timer_set - timer_margin)
507 * watchdog_device.timer_tbl_ptr->freq_hz;
508
509
510 watchdog_device.intel_scu_notifier.notifier_call =
511 intel_scu_notify_sys;
512
513 ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
514 if (ret) {
515 pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
516 goto register_reboot_error;
517 }
518
519 watchdog_device.miscdev.minor = WATCHDOG_MINOR;
520 watchdog_device.miscdev.name = "watchdog";
521 watchdog_device.miscdev.fops = &intel_scu_fops;
522
523 ret = misc_register(&watchdog_device.miscdev);
524 if (ret) {
525 pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
526 WATCHDOG_MINOR, ret);
527 goto misc_register_error;
528 }
529
530 ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
531 watchdog_timer_interrupt,
532 IRQF_SHARED, "watchdog",
533 &watchdog_device.timer_load_count_addr);
534 if (ret) {
535 pr_err("Watchdog timer: error requesting irq %d\n", ret);
536 goto request_irq_error;
537 }
538 /* Make sure timer is disabled before returning */
539 intel_scu_stop();
540 return 0;
541
542/* error cleanup */
543
544request_irq_error:
545 misc_deregister(&watchdog_device.miscdev);
546misc_register_error:
547 unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
548register_reboot_error:
549 intel_scu_stop();
550 iounmap(watchdog_device.timer_load_count_addr);
551 return ret;
552}
553
554static void __exit intel_scu_watchdog_exit(void)
555{
556
557 misc_deregister(&watchdog_device.miscdev);
558 unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
559 /* disable the timer */
560 iowrite32(0x00000002, watchdog_device.timer_control_addr);
561 iounmap(watchdog_device.timer_load_count_addr);
562}
563
564late_initcall(intel_scu_watchdog_init);
565module_exit(intel_scu_watchdog_exit);
566
567MODULE_AUTHOR("Intel Corporation");
568MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver");
569MODULE_LICENSE("GPL");
570MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
571MODULE_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 f52c162b1bea..6143f52ba6b8 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -69,21 +69,29 @@ 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 */
76#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */ 76#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */
77 77
78#define WDT_RESET_GAME 0x10 78#define WDT_RESET_GAME 0x10 /* Reset timer on read or write to game port */
79#define WDT_RESET_KBD 0x20 79#define WDT_RESET_KBD 0x20 /* Reset timer on keyboard interrupt */
80#define WDT_RESET_MOUSE 0x40 80#define WDT_RESET_MOUSE 0x40 /* Reset timer on mouse interrupt */
81#define WDT_RESET_CIR 0x80 81#define WDT_RESET_CIR 0x80 /* Reset timer on consumer IR interrupt */
82 82
83#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */ 83#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */
84 84
85#define WDT_OUT_PWROK 0x10 85#define WDT_OUT_PWROK 0x10 /* Pulse PWROK on timeout */
86#define WDT_OUT_KRST 0x40 86#define WDT_OUT_KRST 0x40 /* Pulse reset on timeout */
87
88static int wdt_control_reg = WDT_RESET_GAME;
89module_param(wdt_control_reg, int, 0);
90MODULE_PARM_DESC(wdt_control_reg, "Value to write to watchdog control "
91 "register. The default WDT_RESET_GAME resets the timer on "
92 "game port reads that this driver generates. You can also "
93 "use KBD, MOUSE or CIR if you have some external way to "
94 "generate those interrupts.");
87 95
88static int superio_inb(int reg) 96static int superio_inb(int reg)
89{ 97{
@@ -131,7 +139,8 @@ static inline void superio_exit(void)
131 139
132static inline void it8712f_wdt_ping(void) 140static inline void it8712f_wdt_ping(void)
133{ 141{
134 inb(address); 142 if (wdt_control_reg & WDT_RESET_GAME)
143 inb(address);
135} 144}
136 145
137static void it8712f_wdt_update_margin(void) 146static void it8712f_wdt_update_margin(void)
@@ -170,7 +179,7 @@ static void it8712f_wdt_enable(void)
170 superio_enter(); 179 superio_enter();
171 superio_select(LDN_GPIO); 180 superio_select(LDN_GPIO);
172 181
173 superio_outb(WDT_RESET_GAME, WDT_CONTROL); 182 superio_outb(wdt_control_reg, WDT_CONTROL);
174 183
175 it8712f_wdt_update_margin(); 184 it8712f_wdt_update_margin();
176 185
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index b709b3b2d1ef..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 * IT8716, IT8718, IT8726 and IT8712 (J,K version). 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.12" 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,20 +70,23 @@
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
79#define IT8702_ID 0x8702
79#define IT8705_ID 0x8705 80#define IT8705_ID 0x8705
80#define IT8712_ID 0x8712 81#define IT8712_ID 0x8712
81#define IT8716_ID 0x8716 82#define IT8716_ID 0x8716
82#define IT8718_ID 0x8718 83#define IT8718_ID 0x8718
84#define IT8720_ID 0x8720
85#define IT8721_ID 0x8721
83#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 86#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
84 87
85/* GPIO Configuration Registers LDN=0x07 */ 88/* GPIO Configuration Registers LDN=0x07 */
86#define WDTCTRL 0x71 89#define WDTCTRL 0x71
87#define WDTCFG 0x72 90#define WDTCFG 0x72
88#define WDTVALLSB 0x73 91#define WDTVALLSB 0x73
89#define WDTVALMSB 0x74 92#define WDTVALMSB 0x74
@@ -92,7 +95,7 @@
92#define WDT_CIRINT 0x80 95#define WDT_CIRINT 0x80
93#define WDT_MOUSEINT 0x40 96#define WDT_MOUSEINT 0x40
94#define WDT_KYBINT 0x20 97#define WDT_KYBINT 0x20
95#define WDT_GAMEPORT 0x10 /* not it8718 */ 98#define WDT_GAMEPORT 0x10 /* not in it8718, it8720, it8721 */
96#define WDT_FORCE 0x02 99#define WDT_FORCE 0x02
97#define WDT_ZERO 0x01 100#define WDT_ZERO 0x01
98 101
@@ -100,11 +103,11 @@
100#define WDT_TOV1 0x80 103#define WDT_TOV1 0x80
101#define WDT_KRST 0x40 104#define WDT_KRST 0x40
102#define WDT_TOVE 0x20 105#define WDT_TOVE 0x20
103#define WDT_PWROK 0x10 106#define WDT_PWROK 0x10 /* not in it8721 */
104#define WDT_INT_MASK 0x0f 107#define WDT_INT_MASK 0x0f
105 108
106/* CIR Configuration Register LDN=0x0a */ 109/* CIR Configuration Register LDN=0x0a */
107#define CIR_ILS 0x70 110#define CIR_ILS 0x70
108 111
109/* The default Base address is not always available, we use this */ 112/* The default Base address is not always available, we use this */
110#define CIR_BASE 0x0208 113#define CIR_BASE 0x0208
@@ -132,7 +135,7 @@
132#define WDTS_USE_GP 4 135#define WDTS_USE_GP 4
133#define WDTS_EXPECTED 5 136#define WDTS_EXPECTED 5
134 137
135static unsigned int base, gpact, ciract; 138static unsigned int base, gpact, ciract, max_units, chip_type;
136static unsigned long wdt_status; 139static unsigned long wdt_status;
137static DEFINE_SPINLOCK(spinlock); 140static DEFINE_SPINLOCK(spinlock);
138 141
@@ -210,6 +213,36 @@ static inline void superio_outw(int val, int reg)
210 outb(val, VAL); 213 outb(val, VAL);
211} 214}
212 215
216/* Internal function, should be called after superio_select(GPIO) */
217static void wdt_update_timeout(void)
218{
219 unsigned char cfg = WDT_KRST;
220 int tm = timeout;
221
222 if (testmode)
223 cfg = 0;
224
225 if (tm <= max_units)
226 cfg |= WDT_TOV1;
227 else
228 tm /= 60;
229
230 if (chip_type != IT8721_ID)
231 cfg |= WDT_PWROK;
232
233 superio_outb(cfg, WDTCFG);
234 superio_outb(tm, WDTVALLSB);
235 if (max_units > 255)
236 superio_outb(tm>>8, WDTVALMSB);
237}
238
239static int wdt_round_time(int t)
240{
241 t += 59;
242 t -= t % 60;
243 return t;
244}
245
213/* watchdog timer handling */ 246/* watchdog timer handling */
214 247
215static void wdt_keepalive(void) 248static void wdt_keepalive(void)
@@ -234,12 +267,7 @@ static void wdt_start(void)
234 superio_outb(WDT_GAMEPORT, WDTCTRL); 267 superio_outb(WDT_GAMEPORT, WDTCTRL);
235 else 268 else
236 superio_outb(WDT_CIRINT, WDTCTRL); 269 superio_outb(WDT_CIRINT, WDTCTRL);
237 if (!testmode) 270 wdt_update_timeout();
238 superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG);
239 else
240 superio_outb(WDT_TOV1, WDTCFG);
241 superio_outb(timeout>>8, WDTVALMSB);
242 superio_outb(timeout, WDTVALLSB);
243 271
244 superio_exit(); 272 superio_exit();
245 spin_unlock_irqrestore(&spinlock, flags); 273 spin_unlock_irqrestore(&spinlock, flags);
@@ -255,8 +283,9 @@ static void wdt_stop(void)
255 superio_select(GPIO); 283 superio_select(GPIO);
256 superio_outb(0x00, WDTCTRL); 284 superio_outb(0x00, WDTCTRL);
257 superio_outb(WDT_TOV1, WDTCFG); 285 superio_outb(WDT_TOV1, WDTCFG);
258 superio_outb(0x00, WDTVALMSB);
259 superio_outb(0x00, WDTVALLSB); 286 superio_outb(0x00, WDTVALLSB);
287 if (max_units > 255)
288 superio_outb(0x00, WDTVALMSB);
260 289
261 superio_exit(); 290 superio_exit();
262 spin_unlock_irqrestore(&spinlock, flags); 291 spin_unlock_irqrestore(&spinlock, flags);
@@ -266,8 +295,8 @@ static void wdt_stop(void)
266 * wdt_set_timeout - set a new timeout value with watchdog ioctl 295 * wdt_set_timeout - set a new timeout value with watchdog ioctl
267 * @t: timeout value in seconds 296 * @t: timeout value in seconds
268 * 297 *
269 * The hardware device has a 16 bit watchdog timer, thus the 298 * The hardware device has a 8 or 16 bit watchdog timer (depends on
270 * timeout time ranges between 1 and 65535 seconds. 299 * chip version) that can be configured to count seconds or minutes.
271 * 300 *
272 * Used within WDIOC_SETTIMEOUT watchdog device ioctl. 301 * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
273 */ 302 */
@@ -276,19 +305,19 @@ static int wdt_set_timeout(int t)
276{ 305{
277 unsigned long flags; 306 unsigned long flags;
278 307
279 if (t < 1 || t > 65535) 308 if (t < 1 || t > max_units * 60)
280 return -EINVAL; 309 return -EINVAL;
281 310
282 timeout = t; 311 if (t > max_units)
312 timeout = wdt_round_time(t);
313 else
314 timeout = t;
283 315
284 spin_lock_irqsave(&spinlock, flags); 316 spin_lock_irqsave(&spinlock, flags);
285 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 317 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
286 superio_enter(); 318 superio_enter();
287
288 superio_select(GPIO); 319 superio_select(GPIO);
289 superio_outb(t>>8, WDTVALMSB); 320 wdt_update_timeout();
290 superio_outb(t, WDTVALLSB);
291
292 superio_exit(); 321 superio_exit();
293 } 322 }
294 spin_unlock_irqrestore(&spinlock, flags); 323 spin_unlock_irqrestore(&spinlock, flags);
@@ -529,10 +558,12 @@ static struct notifier_block wdt_notifier = {
529static int __init it87_wdt_init(void) 558static int __init it87_wdt_init(void)
530{ 559{
531 int rc = 0; 560 int rc = 0;
532 u16 chip_type; 561 int try_gameport = !nogameport;
533 u8 chip_rev; 562 u8 chip_rev;
534 unsigned long flags; 563 unsigned long flags;
535 564
565 wdt_status = 0;
566
536 spin_lock_irqsave(&spinlock, flags); 567 spin_lock_irqsave(&spinlock, flags);
537 superio_enter(); 568 superio_enter();
538 chip_type = superio_inw(CHIPID); 569 chip_type = superio_inw(CHIPID);
@@ -541,13 +572,22 @@ static int __init it87_wdt_init(void)
541 spin_unlock_irqrestore(&spinlock, flags); 572 spin_unlock_irqrestore(&spinlock, flags);
542 573
543 switch (chip_type) { 574 switch (chip_type) {
575 case IT8702_ID:
576 max_units = 255;
577 break;
578 case IT8712_ID:
579 max_units = (chip_rev < 8) ? 255 : 65535;
580 break;
544 case IT8716_ID: 581 case IT8716_ID:
545 case IT8718_ID:
546 case IT8726_ID: 582 case IT8726_ID:
583 max_units = 65535;
584 break;
585 case IT8718_ID:
586 case IT8720_ID:
587 case IT8721_ID:
588 max_units = 65535;
589 try_gameport = 0;
547 break; 590 break;
548 case IT8712_ID:
549 if (chip_rev > 7)
550 break;
551 case IT8705_ID: 591 case IT8705_ID:
552 printk(KERN_ERR PFX 592 printk(KERN_ERR PFX
553 "Unsupported Chip found, Chip %04x Revision %02x\n", 593 "Unsupported Chip found, Chip %04x Revision %02x\n",
@@ -571,7 +611,7 @@ static int __init it87_wdt_init(void)
571 superio_outb(0x00, WDTCTRL); 611 superio_outb(0x00, WDTCTRL);
572 612
573 /* First try to get Gameport support */ 613 /* First try to get Gameport support */
574 if (chip_type != IT8718_ID && !nogameport) { 614 if (try_gameport) {
575 superio_select(GAMEPORT); 615 superio_select(GAMEPORT);
576 base = superio_inw(BASEREG); 616 base = superio_inw(BASEREG);
577 if (!base) { 617 if (!base) {
@@ -623,13 +663,16 @@ static int __init it87_wdt_init(void)
623 spin_unlock_irqrestore(&spinlock, flags); 663 spin_unlock_irqrestore(&spinlock, flags);
624 } 664 }
625 665
626 if (timeout < 1 || timeout > 65535) { 666 if (timeout < 1 || timeout > max_units * 60) {
627 timeout = DEFAULT_TIMEOUT; 667 timeout = DEFAULT_TIMEOUT;
628 printk(KERN_WARNING PFX 668 printk(KERN_WARNING PFX
629 "Timeout value out of range, use default %d sec\n", 669 "Timeout value out of range, use default %d sec\n",
630 DEFAULT_TIMEOUT); 670 DEFAULT_TIMEOUT);
631 } 671 }
632 672
673 if (timeout > max_units)
674 timeout = wdt_round_time(timeout);
675
633 rc = register_reboot_notifier(&wdt_notifier); 676 rc = register_reboot_notifier(&wdt_notifier);
634 if (rc) { 677 if (rc) {
635 printk(KERN_ERR PFX 678 printk(KERN_ERR PFX
@@ -656,7 +699,7 @@ static int __init it87_wdt_init(void)
656 outb(0x09, CIR_IER(base)); 699 outb(0x09, CIR_IER(base));
657 } 700 }
658 701
659 printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " 702 printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
660 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " 703 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
661 "nogameport=%d)\n", chip_type, chip_rev, timeout, 704 "nogameport=%d)\n", chip_type, chip_rev, timeout,
662 nowayout, testmode, exclusive, nogameport); 705 nowayout, testmode, exclusive, nogameport);
@@ -676,7 +719,7 @@ err_out_region:
676 spin_unlock_irqrestore(&spinlock, flags); 719 spin_unlock_irqrestore(&spinlock, flags);
677 } 720 }
678err_out: 721err_out:
679 if (chip_type != IT8718_ID && !nogameport) { 722 if (try_gameport) {
680 spin_lock_irqsave(&spinlock, flags); 723 spin_lock_irqsave(&spinlock, flags);
681 superio_enter(); 724 superio_enter();
682 superio_select(GAMEPORT); 725 superio_select(GAMEPORT);
@@ -698,8 +741,9 @@ static void __exit it87_wdt_exit(void)
698 superio_select(GPIO); 741 superio_select(GPIO);
699 superio_outb(0x00, WDTCTRL); 742 superio_outb(0x00, WDTCTRL);
700 superio_outb(0x00, WDTCFG); 743 superio_outb(0x00, WDTCFG);
701 superio_outb(0x00, WDTVALMSB);
702 superio_outb(0x00, WDTVALLSB); 744 superio_outb(0x00, WDTVALLSB);
745 if (max_units > 255)
746 superio_outb(0x00, WDTVALMSB);
703 if (test_bit(WDTS_USE_GP, &wdt_status)) { 747 if (test_bit(WDTS_USE_GP, &wdt_status)) {
704 superio_select(GAMEPORT); 748 superio_select(GAMEPORT);
705 superio_outb(gpact, ACTREG); 749 superio_outb(gpact, ACTREG);
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/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index 2852bb2e3fd9..811471903e8a 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -21,7 +21,7 @@
21#include <linux/watchdog.h> 21#include <linux/watchdog.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/uaccess.h> 23#include <linux/uaccess.h>
24#include <mach/timex.h> 24#include <mach/hardware.h>
25#include <mach/regs-timer.h> 25#include <mach/regs-timer.h>
26 26
27#define WDT_DEFAULT_TIME 5 /* seconds */ 27#define WDT_DEFAULT_TIME 5 /* seconds */
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
new file mode 100644
index 000000000000..7d82adac1cb2
--- /dev/null
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -0,0 +1,261 @@
1/*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License version 2 as published
4 * by the Free Software Foundation.
5 *
6 * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
7 * Based on EP93xx wdt driver
8 */
9
10#include <linux/module.h>
11#include <linux/fs.h>
12#include <linux/miscdevice.h>
13#include <linux/watchdog.h>
14#include <linux/platform_device.h>
15#include <linux/uaccess.h>
16#include <linux/clk.h>
17#include <linux/io.h>
18
19#include <lantiq.h>
20
21/* Section 3.4 of the datasheet
22 * The password sequence protects the WDT control register from unintended
23 * write actions, which might cause malfunction of the WDT.
24 *
25 * essentially the following two magic passwords need to be written to allow
26 * IO access to the WDT core
27 */
28#define LTQ_WDT_PW1 0x00BE0000
29#define LTQ_WDT_PW2 0x00DC0000
30
31#define LTQ_WDT_CR 0x0 /* watchdog control register */
32#define LTQ_WDT_SR 0x8 /* watchdog status register */
33
34#define LTQ_WDT_SR_EN (0x1 << 31) /* enable bit */
35#define LTQ_WDT_SR_PWD (0x3 << 26) /* turn on power */
36#define LTQ_WDT_SR_CLKDIV (0x3 << 24) /* turn on clock and set */
37 /* divider to 0x40000 */
38#define LTQ_WDT_DIVIDER 0x40000
39#define LTQ_MAX_TIMEOUT ((1 << 16) - 1) /* the reload field is 16 bit */
40
41static int nowayout = WATCHDOG_NOWAYOUT;
42
43static void __iomem *ltq_wdt_membase;
44static unsigned long ltq_io_region_clk_rate;
45
46static unsigned long ltq_wdt_bootstatus;
47static unsigned long ltq_wdt_in_use;
48static int ltq_wdt_timeout = 30;
49static int ltq_wdt_ok_to_close;
50
51static void
52ltq_wdt_enable(void)
53{
54 ltq_wdt_timeout = ltq_wdt_timeout *
55 (ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
56 if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
57 ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
58
59 /* write the first password magic */
60 ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
61 /* write the second magic plus the configuration and new timeout */
62 ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
63 LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
64}
65
66static void
67ltq_wdt_disable(void)
68{
69 /* write the first password magic */
70 ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
71 /* write the second password magic with no config
72 * this turns the watchdog off
73 */
74 ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
75}
76
77static ssize_t
78ltq_wdt_write(struct file *file, const char __user *data,
79 size_t len, loff_t *ppos)
80{
81 if (len) {
82 if (!nowayout) {
83 size_t i;
84
85 ltq_wdt_ok_to_close = 0;
86 for (i = 0; i != len; i++) {
87 char c;
88
89 if (get_user(c, data + i))
90 return -EFAULT;
91 if (c == 'V')
92 ltq_wdt_ok_to_close = 1;
93 else
94 ltq_wdt_ok_to_close = 0;
95 }
96 }
97 ltq_wdt_enable();
98 }
99
100 return len;
101}
102
103static struct watchdog_info ident = {
104 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
105 WDIOF_CARDRESET,
106 .identity = "ltq_wdt",
107};
108
109static long
110ltq_wdt_ioctl(struct file *file,
111 unsigned int cmd, unsigned long arg)
112{
113 int ret = -ENOTTY;
114
115 switch (cmd) {
116 case WDIOC_GETSUPPORT:
117 ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
118 sizeof(ident)) ? -EFAULT : 0;
119 break;
120
121 case WDIOC_GETBOOTSTATUS:
122 ret = put_user(ltq_wdt_bootstatus, (int __user *)arg);
123 break;
124
125 case WDIOC_GETSTATUS:
126 ret = put_user(0, (int __user *)arg);
127 break;
128
129 case WDIOC_SETTIMEOUT:
130 ret = get_user(ltq_wdt_timeout, (int __user *)arg);
131 if (!ret)
132 ltq_wdt_enable();
133 /* intentional drop through */
134 case WDIOC_GETTIMEOUT:
135 ret = put_user(ltq_wdt_timeout, (int __user *)arg);
136 break;
137
138 case WDIOC_KEEPALIVE:
139 ltq_wdt_enable();
140 ret = 0;
141 break;
142 }
143 return ret;
144}
145
146static int
147ltq_wdt_open(struct inode *inode, struct file *file)
148{
149 if (test_and_set_bit(0, &ltq_wdt_in_use))
150 return -EBUSY;
151 ltq_wdt_in_use = 1;
152 ltq_wdt_enable();
153
154 return nonseekable_open(inode, file);
155}
156
157static int
158ltq_wdt_release(struct inode *inode, struct file *file)
159{
160 if (ltq_wdt_ok_to_close)
161 ltq_wdt_disable();
162 else
163 pr_err("ltq_wdt: watchdog closed without warning\n");
164 ltq_wdt_ok_to_close = 0;
165 clear_bit(0, &ltq_wdt_in_use);
166
167 return 0;
168}
169
170static const struct file_operations ltq_wdt_fops = {
171 .owner = THIS_MODULE,
172 .write = ltq_wdt_write,
173 .unlocked_ioctl = ltq_wdt_ioctl,
174 .open = ltq_wdt_open,
175 .release = ltq_wdt_release,
176 .llseek = no_llseek,
177};
178
179static struct miscdevice ltq_wdt_miscdev = {
180 .minor = WATCHDOG_MINOR,
181 .name = "watchdog",
182 .fops = &ltq_wdt_fops,
183};
184
185static int __init
186ltq_wdt_probe(struct platform_device *pdev)
187{
188 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
189 struct clk *clk;
190
191 if (!res) {
192 dev_err(&pdev->dev, "cannot obtain I/O memory region");
193 return -ENOENT;
194 }
195 res = devm_request_mem_region(&pdev->dev, res->start,
196 resource_size(res), dev_name(&pdev->dev));
197 if (!res) {
198 dev_err(&pdev->dev, "cannot request I/O memory region");
199 return -EBUSY;
200 }
201 ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
202 resource_size(res));
203 if (!ltq_wdt_membase) {
204 dev_err(&pdev->dev, "cannot remap I/O memory region\n");
205 return -ENOMEM;
206 }
207
208 /* we do not need to enable the clock as it is always running */
209 clk = clk_get(&pdev->dev, "io");
210 WARN_ON(!clk);
211 ltq_io_region_clk_rate = clk_get_rate(clk);
212 clk_put(clk);
213
214 if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
215 ltq_wdt_bootstatus = WDIOF_CARDRESET;
216
217 return misc_register(&ltq_wdt_miscdev);
218}
219
220static int __devexit
221ltq_wdt_remove(struct platform_device *pdev)
222{
223 misc_deregister(&ltq_wdt_miscdev);
224
225 if (ltq_wdt_membase)
226 iounmap(ltq_wdt_membase);
227
228 return 0;
229}
230
231
232static struct platform_driver ltq_wdt_driver = {
233 .remove = __devexit_p(ltq_wdt_remove),
234 .driver = {
235 .name = "ltq_wdt",
236 .owner = THIS_MODULE,
237 },
238};
239
240static int __init
241init_ltq_wdt(void)
242{
243 return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
244}
245
246static void __exit
247exit_ltq_wdt(void)
248{
249 return platform_driver_unregister(&ltq_wdt_driver);
250}
251
252module_init(init_ltq_wdt);
253module_exit(exit_ltq_wdt);
254
255module_param(nowayout, int, 0);
256MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
257
258MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
259MODULE_DESCRIPTION("Lantiq SoC Watchdog");
260MODULE_LICENSE("GPL");
261MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/m54xx_wdt.c b/drivers/watchdog/m54xx_wdt.c
new file mode 100644
index 000000000000..4d43286074aa
--- /dev/null
+++ b/drivers/watchdog/m54xx_wdt.c
@@ -0,0 +1,227 @@
1/*
2 * drivers/watchdog/m54xx_wdt.c
3 *
4 * Watchdog driver for ColdFire MCF547x & MCF548x processors
5 * Copyright 2010 (c) Philippe De Muyter <phdm@macqel.be>
6 *
7 * Adapted from the IXP4xx watchdog driver, which carries these notices:
8 *
9 * Author: Deepak Saxena <dsaxena@plexity.net>
10 *
11 * Copyright 2004 (c) MontaVista, Software, Inc.
12 * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
13 *
14 * This file is licensed under the terms of the GNU General Public
15 * License version 2. This program is licensed "as is" without any
16 * warranty of any kind, whether express or implied.
17 */
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/fs.h>
24#include <linux/miscdevice.h>
25#include <linux/watchdog.h>
26#include <linux/init.h>
27#include <linux/bitops.h>
28#include <linux/ioport.h>
29#include <linux/uaccess.h>
30
31#include <asm/coldfire.h>
32#include <asm/m54xxsim.h>
33#include <asm/m54xxgpt.h>
34
35static int nowayout = WATCHDOG_NOWAYOUT;
36static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */
37static unsigned long wdt_status;
38
39#define WDT_IN_USE 0
40#define WDT_OK_TO_CLOSE 1
41
42static void wdt_enable(void)
43{
44 unsigned int gms0;
45
46 /* preserve GPIO usage, if any */
47 gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
48 if (gms0 & MCF_GPT_GMS_TMS_GPIO)
49 gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK
50 | MCF_GPT_GMS_OD);
51 else
52 gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD;
53 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
54 __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) |
55 MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0);
56 gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE;
57 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
58}
59
60static void wdt_disable(void)
61{
62 unsigned int gms0;
63
64 /* disable watchdog */
65 gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
66 gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE);
67 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
68}
69
70static void wdt_keepalive(void)
71{
72 unsigned int gms0;
73
74 gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
75 gms0 |= MCF_GPT_GMS_OCPW(0xA5);
76 __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
77}
78
79static int m54xx_wdt_open(struct inode *inode, struct file *file)
80{
81 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
82 return -EBUSY;
83
84 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
85 wdt_enable();
86 return nonseekable_open(inode, file);
87}
88
89static ssize_t m54xx_wdt_write(struct file *file, const char *data,
90 size_t len, loff_t *ppos)
91{
92 if (len) {
93 if (!nowayout) {
94 size_t i;
95
96 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
97
98 for (i = 0; i != len; i++) {
99 char c;
100
101 if (get_user(c, data + i))
102 return -EFAULT;
103 if (c == 'V')
104 set_bit(WDT_OK_TO_CLOSE, &wdt_status);
105 }
106 }
107 wdt_keepalive();
108 }
109 return len;
110}
111
112static const struct watchdog_info ident = {
113 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
114 WDIOF_KEEPALIVEPING,
115 .identity = "Coldfire M54xx Watchdog",
116};
117
118static long m54xx_wdt_ioctl(struct file *file, unsigned int cmd,
119 unsigned long arg)
120{
121 int ret = -ENOTTY;
122 int time;
123
124 switch (cmd) {
125 case WDIOC_GETSUPPORT:
126 ret = copy_to_user((struct watchdog_info *)arg, &ident,
127 sizeof(ident)) ? -EFAULT : 0;
128 break;
129
130 case WDIOC_GETSTATUS:
131 ret = put_user(0, (int *)arg);
132 break;
133
134 case WDIOC_GETBOOTSTATUS:
135 ret = put_user(0, (int *)arg);
136 break;
137
138 case WDIOC_KEEPALIVE:
139 wdt_keepalive();
140 ret = 0;
141 break;
142
143 case WDIOC_SETTIMEOUT:
144 ret = get_user(time, (int *)arg);
145 if (ret)
146 break;
147
148 if (time <= 0 || time > 30) {
149 ret = -EINVAL;
150 break;
151 }
152
153 heartbeat = time;
154 wdt_enable();
155 /* Fall through */
156
157 case WDIOC_GETTIMEOUT:
158 ret = put_user(heartbeat, (int *)arg);
159 break;
160 }
161 return ret;
162}
163
164static int m54xx_wdt_release(struct inode *inode, struct file *file)
165{
166 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
167 wdt_disable();
168 else {
169 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
170 "timer will not stop\n");
171 wdt_keepalive();
172 }
173 clear_bit(WDT_IN_USE, &wdt_status);
174 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
175
176 return 0;
177}
178
179
180static const struct file_operations m54xx_wdt_fops = {
181 .owner = THIS_MODULE,
182 .llseek = no_llseek,
183 .write = m54xx_wdt_write,
184 .unlocked_ioctl = m54xx_wdt_ioctl,
185 .open = m54xx_wdt_open,
186 .release = m54xx_wdt_release,
187};
188
189static struct miscdevice m54xx_wdt_miscdev = {
190 .minor = WATCHDOG_MINOR,
191 .name = "watchdog",
192 .fops = &m54xx_wdt_fops,
193};
194
195static int __init m54xx_wdt_init(void)
196{
197 if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
198 "Coldfire M54xx Watchdog")) {
199 printk(KERN_WARNING
200 "Coldfire M54xx Watchdog : I/O region busy\n");
201 return -EBUSY;
202 }
203 printk(KERN_INFO "ColdFire watchdog driver is loaded.\n");
204
205 return misc_register(&m54xx_wdt_miscdev);
206}
207
208static void __exit m54xx_wdt_exit(void)
209{
210 misc_deregister(&m54xx_wdt_miscdev);
211 release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4);
212}
213
214module_init(m54xx_wdt_init);
215module_exit(m54xx_wdt_exit);
216
217MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
218MODULE_DESCRIPTION("Coldfire M54xx Watchdog");
219
220module_param(heartbeat, int, 0);
221MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)");
222
223module_param(nowayout, int, 0);
224MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
225
226MODULE_LICENSE("GPL");
227MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 2d118cf022fc..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 */
@@ -143,7 +143,7 @@ static unsigned long next_heartbeat;
143#ifndef ZF_DEBUG 143#ifndef ZF_DEBUG
144# define dprintk(format, args...) 144# define dprintk(format, args...)
145#else 145#else
146# define dprintk(format, args...) printk(KERN_DEBUG PFX 146# define dprintk(format, args...) printk(KERN_DEBUG PFX \
147 ":%s:%d: " format, __func__, __LINE__ , ## args) 147 ":%s:%d: " format, __func__, __LINE__ , ## args)
148#endif 148#endif
149 149
@@ -388,7 +388,7 @@ static struct notifier_block zf_notifier = {
388 388
389static void __init zf_show_action(int act) 389static void __init zf_show_action(int act)
390{ 390{
391 char *str[] = { "RESET", "SMI", "NMI", "SCI" }; 391 static const char * const str[] = { "RESET", "SMI", "NMI", "SCI" };
392 392
393 printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]); 393 printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
394} 394}
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 3053ff05ca41..73ba2fd8e591 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
@@ -270,7 +270,6 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
270{ 270{
271 int ret = 0; 271 int ret = 0;
272 int size; 272 int size;
273 struct resource *res;
274 struct device *dev = &pdev->dev; 273 struct device *dev = &pdev->dev;
275 struct max63xx_timeout *table; 274 struct max63xx_timeout *table;
276 275
@@ -294,21 +293,19 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
294 293
295 max63xx_pdev = pdev; 294 max63xx_pdev = pdev;
296 295
297 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 296 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
298 if (res == NULL) { 297 if (wdt_mem == NULL) {
299 dev_err(dev, "failed to get memory region resource\n"); 298 dev_err(dev, "failed to get memory region resource\n");
300 return -ENOENT; 299 return -ENOENT;
301 } 300 }
302 301
303 size = resource_size(res); 302 size = resource_size(wdt_mem);
304 wdt_mem = request_mem_region(res->start, size, pdev->name); 303 if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
305
306 if (wdt_mem == NULL) {
307 dev_err(dev, "failed to get memory region\n"); 304 dev_err(dev, "failed to get memory region\n");
308 return -ENOENT; 305 return -ENOENT;
309 } 306 }
310 307
311 wdt_base = ioremap(res->start, size); 308 wdt_base = ioremap(wdt_mem->start, size);
312 if (!wdt_base) { 309 if (!wdt_base) {
313 dev_err(dev, "failed to map memory region\n"); 310 dev_err(dev, "failed to map memory region\n");
314 ret = -ENOMEM; 311 ret = -ENOMEM;
@@ -326,8 +323,8 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
326out_unmap: 323out_unmap:
327 iounmap(wdt_base); 324 iounmap(wdt_base);
328out_request: 325out_request:
329 release_resource(wdt_mem); 326 release_mem_region(wdt_mem->start, size);
330 kfree(wdt_mem); 327 wdt_mem = NULL;
331 328
332 return ret; 329 return ret;
333} 330}
@@ -336,8 +333,7 @@ static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
336{ 333{
337 misc_deregister(&max63xx_wdt_miscdev); 334 misc_deregister(&max63xx_wdt_miscdev);
338 if (wdt_mem) { 335 if (wdt_mem) {
339 release_resource(wdt_mem); 336 release_mem_region(wdt_mem->start, resource_size(wdt_mem));
340 kfree(wdt_mem);
341 wdt_mem = NULL; 337 wdt_mem = NULL;
342 } 338 }
343 339
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 8fa213cdb499..eed5436ffb51 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,21 @@ 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 const struct of_device_id mpc8xxx_wdt_match[];
189 const struct of_device_id *match) 189static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
190{ 190{
191 int ret; 191 int ret;
192 const struct of_device_id *match;
192 struct device_node *np = ofdev->dev.of_node; 193 struct device_node *np = ofdev->dev.of_node;
193 struct mpc8xxx_wdt_type *wdt_type = match->data; 194 struct mpc8xxx_wdt_type *wdt_type;
194 u32 freq = fsl_get_sys_freq(); 195 u32 freq = fsl_get_sys_freq();
195 bool enabled; 196 bool enabled;
196 197
198 match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev);
199 if (!match)
200 return -EINVAL;
201 wdt_type = match->data;
202
197 if (!freq || freq == -1) 203 if (!freq || freq == -1)
198 return -EINVAL; 204 return -EINVAL;
199 205
@@ -272,7 +278,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
272}; 278};
273MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); 279MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
274 280
275static struct of_platform_driver mpc8xxx_wdt_driver = { 281static struct platform_driver mpc8xxx_wdt_driver = {
276 .probe = mpc8xxx_wdt_probe, 282 .probe = mpc8xxx_wdt_probe,
277 .remove = __devexit_p(mpc8xxx_wdt_remove), 283 .remove = __devexit_p(mpc8xxx_wdt_remove),
278 .driver = { 284 .driver = {
@@ -308,13 +314,13 @@ module_init(mpc8xxx_wdt_init_late);
308 314
309static int __init mpc8xxx_wdt_init(void) 315static int __init mpc8xxx_wdt_init(void)
310{ 316{
311 return of_register_platform_driver(&mpc8xxx_wdt_driver); 317 return platform_driver_register(&mpc8xxx_wdt_driver);
312} 318}
313arch_initcall(mpc8xxx_wdt_init); 319arch_initcall(mpc8xxx_wdt_init);
314 320
315static void __exit mpc8xxx_wdt_exit(void) 321static void __exit mpc8xxx_wdt_exit(void)
316{ 322{
317 of_unregister_platform_driver(&mpc8xxx_wdt_driver); 323 platform_driver_unregister(&mpc8xxx_wdt_driver);
318} 324}
319module_exit(mpc8xxx_wdt_exit); 325module_exit(mpc8xxx_wdt_exit);
320 326
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..0430e093b1a0 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -66,22 +66,18 @@ static struct {
66 int default_ticks; 66 int default_ticks;
67 unsigned long inuse; 67 unsigned long inuse;
68 unsigned gpio; 68 unsigned gpio;
69 unsigned int gstate;
69} mtx1_wdt_device; 70} mtx1_wdt_device;
70 71
71static void mtx1_wdt_trigger(unsigned long unused) 72static void mtx1_wdt_trigger(unsigned long unused)
72{ 73{
73 u32 tmp;
74
75 spin_lock(&mtx1_wdt_device.lock); 74 spin_lock(&mtx1_wdt_device.lock);
76 if (mtx1_wdt_device.running) 75 if (mtx1_wdt_device.running)
77 ticks--; 76 ticks--;
78 /* 77
79 * toggle GPIO2_15 78 /* toggle wdt gpio */
80 */ 79 mtx1_wdt_device.gstate = !mtx1_wdt_device.gstate;
81 tmp = au_readl(GPIO2_DIR); 80 gpio_set_value(mtx1_wdt_device.gpio, mtx1_wdt_device.gstate);
82 tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) |
83 ((~tmp) & (1 << mtx1_wdt_device.gpio));
84 au_writel(tmp, GPIO2_DIR);
85 81
86 if (mtx1_wdt_device.queue && ticks) 82 if (mtx1_wdt_device.queue && ticks)
87 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); 83 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
@@ -103,6 +99,7 @@ static void mtx1_wdt_start(void)
103 spin_lock_irqsave(&mtx1_wdt_device.lock, flags); 99 spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
104 if (!mtx1_wdt_device.queue) { 100 if (!mtx1_wdt_device.queue) {
105 mtx1_wdt_device.queue = 1; 101 mtx1_wdt_device.queue = 1;
102 mtx1_wdt_device.gstate = 1;
106 gpio_set_value(mtx1_wdt_device.gpio, 1); 103 gpio_set_value(mtx1_wdt_device.gpio, 1);
107 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); 104 mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
108 } 105 }
@@ -117,6 +114,7 @@ static int mtx1_wdt_stop(void)
117 spin_lock_irqsave(&mtx1_wdt_device.lock, flags); 114 spin_lock_irqsave(&mtx1_wdt_device.lock, flags);
118 if (mtx1_wdt_device.queue) { 115 if (mtx1_wdt_device.queue) {
119 mtx1_wdt_device.queue = 0; 116 mtx1_wdt_device.queue = 0;
117 mtx1_wdt_device.gstate = 0;
120 gpio_set_value(mtx1_wdt_device.gpio, 0); 118 gpio_set_value(mtx1_wdt_device.gpio, 0);
121 } 119 }
122 ticks = mtx1_wdt_device.default_ticks; 120 ticks = mtx1_wdt_device.default_ticks;
@@ -190,19 +188,19 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
190} 188}
191 189
192static const struct file_operations mtx1_wdt_fops = { 190static const struct file_operations mtx1_wdt_fops = {
193 .owner = THIS_MODULE, 191 .owner = THIS_MODULE,
194 .llseek = no_llseek, 192 .llseek = no_llseek,
195 .unlocked_ioctl = mtx1_wdt_ioctl, 193 .unlocked_ioctl = mtx1_wdt_ioctl,
196 .open = mtx1_wdt_open, 194 .open = mtx1_wdt_open,
197 .write = mtx1_wdt_write, 195 .write = mtx1_wdt_write,
198 .release = mtx1_wdt_release, 196 .release = mtx1_wdt_release,
199}; 197};
200 198
201 199
202static struct miscdevice mtx1_wdt_misc = { 200static struct miscdevice mtx1_wdt_misc = {
203 .minor = WATCHDOG_MINOR, 201 .minor = WATCHDOG_MINOR,
204 .name = "watchdog", 202 .name = "watchdog",
205 .fops = &mtx1_wdt_fops, 203 .fops = &mtx1_wdt_fops,
206}; 204};
207 205
208 206
@@ -211,6 +209,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
211 int ret; 209 int ret;
212 210
213 mtx1_wdt_device.gpio = pdev->resource[0].start; 211 mtx1_wdt_device.gpio = pdev->resource[0].start;
212 ret = gpio_request_one(mtx1_wdt_device.gpio,
213 GPIOF_OUT_INIT_HIGH, "mtx1-wdt");
214 if (ret < 0) {
215 dev_err(&pdev->dev, "failed to request gpio");
216 return ret;
217 }
214 218
215 spin_lock_init(&mtx1_wdt_device.lock); 219 spin_lock_init(&mtx1_wdt_device.lock);
216 init_completion(&mtx1_wdt_device.stop); 220 init_completion(&mtx1_wdt_device.stop);
@@ -236,11 +240,13 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
236 mtx1_wdt_device.queue = 0; 240 mtx1_wdt_device.queue = 0;
237 wait_for_completion(&mtx1_wdt_device.stop); 241 wait_for_completion(&mtx1_wdt_device.stop);
238 } 242 }
243
244 gpio_free(mtx1_wdt_device.gpio);
239 misc_deregister(&mtx1_wdt_misc); 245 misc_deregister(&mtx1_wdt_misc);
240 return 0; 246 return 0;
241} 247}
242 248
243static struct platform_driver mtx1_wdt = { 249static struct platform_driver mtx1_wdt_driver = {
244 .probe = mtx1_wdt_probe, 250 .probe = mtx1_wdt_probe,
245 .remove = __devexit_p(mtx1_wdt_remove), 251 .remove = __devexit_p(mtx1_wdt_remove),
246 .driver.name = "mtx1-wdt", 252 .driver.name = "mtx1-wdt",
@@ -249,12 +255,12 @@ static struct platform_driver mtx1_wdt = {
249 255
250static int __init mtx1_wdt_init(void) 256static int __init mtx1_wdt_init(void)
251{ 257{
252 return platform_driver_register(&mtx1_wdt); 258 return platform_driver_register(&mtx1_wdt_driver);
253} 259}
254 260
255static void __exit mtx1_wdt_exit(void) 261static void __exit mtx1_wdt_exit(void)
256{ 262{
257 platform_driver_unregister(&mtx1_wdt); 263 platform_driver_unregister(&mtx1_wdt_driver);
258} 264}
259 265
260module_init(mtx1_wdt_init); 266module_init(mtx1_wdt_init);
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
new file mode 100644
index 000000000000..afa78a54711e
--- /dev/null
+++ b/drivers/watchdog/nv_tco.c
@@ -0,0 +1,512 @@
1/*
2 * nv_tco 0.01: TCO timer driver for NV chipsets
3 *
4 * (c) Copyright 2005 Google Inc., All Rights Reserved.
5 *
6 * Based off i8xx_tco.c:
7 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights
8 * Reserved.
9 * http://www.kernelconcepts.de
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 *
16 * TCO timer driver for NV chipsets
17 * based on softdog.c by Alan Cox <alan@redhat.com>
18 */
19
20/*
21 * Includes, defines, variables, module parameters, ...
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/types.h>
27#include <linux/miscdevice.h>
28#include <linux/watchdog.h>
29#include <linux/init.h>
30#include <linux/fs.h>
31#include <linux/pci.h>
32#include <linux/ioport.h>
33#include <linux/jiffies.h>
34#include <linux/platform_device.h>
35#include <linux/uaccess.h>
36#include <linux/io.h>
37
38#include "nv_tco.h"
39
40/* Module and version information */
41#define TCO_VERSION "0.01"
42#define TCO_MODULE_NAME "NV_TCO"
43#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
44#define PFX TCO_MODULE_NAME ": "
45
46/* internal variables */
47static unsigned int tcobase;
48static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */
49static unsigned long timer_alive;
50static char tco_expect_close;
51static struct pci_dev *tco_pci;
52
53/* the watchdog platform device */
54static struct platform_device *nv_tco_platform_device;
55
56/* module parameters */
57#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2<heartbeat<39) */
58static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
59module_param(heartbeat, int, 0);
60MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, "
61 "default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
62
63static int nowayout = WATCHDOG_NOWAYOUT;
64module_param(nowayout, int, 0);
65MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
66 " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
67
68/*
69 * Some TCO specific functions
70 */
71static inline unsigned char seconds_to_ticks(int seconds)
72{
73 /* the internal timer is stored as ticks which decrement
74 * every 0.6 seconds */
75 return (seconds * 10) / 6;
76}
77
78static void tco_timer_start(void)
79{
80 u32 val;
81 unsigned long flags;
82
83 spin_lock_irqsave(&tco_lock, flags);
84 val = inl(TCO_CNT(tcobase));
85 val &= ~TCO_CNT_TCOHALT;
86 outl(val, TCO_CNT(tcobase));
87 spin_unlock_irqrestore(&tco_lock, flags);
88}
89
90static void tco_timer_stop(void)
91{
92 u32 val;
93 unsigned long flags;
94
95 spin_lock_irqsave(&tco_lock, flags);
96 val = inl(TCO_CNT(tcobase));
97 val |= TCO_CNT_TCOHALT;
98 outl(val, TCO_CNT(tcobase));
99 spin_unlock_irqrestore(&tco_lock, flags);
100}
101
102static void tco_timer_keepalive(void)
103{
104 unsigned long flags;
105
106 spin_lock_irqsave(&tco_lock, flags);
107 outb(0x01, TCO_RLD(tcobase));
108 spin_unlock_irqrestore(&tco_lock, flags);
109}
110
111static int tco_timer_set_heartbeat(int t)
112{
113 int ret = 0;
114 unsigned char tmrval;
115 unsigned long flags;
116 u8 val;
117
118 /*
119 * note seconds_to_ticks(t) > t, so if t > 0x3f, so is
120 * tmrval=seconds_to_ticks(t). Check that the count in seconds isn't
121 * out of range on it's own (to avoid overflow in tmrval).
122 */
123 if (t < 0 || t > 0x3f)
124 return -EINVAL;
125 tmrval = seconds_to_ticks(t);
126
127 /* "Values of 0h-3h are ignored and should not be attempted" */
128 if (tmrval > 0x3f || tmrval < 0x04)
129 return -EINVAL;
130
131 /* Write new heartbeat to watchdog */
132 spin_lock_irqsave(&tco_lock, flags);
133 val = inb(TCO_TMR(tcobase));
134 val &= 0xc0;
135 val |= tmrval;
136 outb(val, TCO_TMR(tcobase));
137 val = inb(TCO_TMR(tcobase));
138
139 if ((val & 0x3f) != tmrval)
140 ret = -EINVAL;
141 spin_unlock_irqrestore(&tco_lock, flags);
142
143 if (ret)
144 return ret;
145
146 heartbeat = t;
147 return 0;
148}
149
150/*
151 * /dev/watchdog handling
152 */
153
154static int nv_tco_open(struct inode *inode, struct file *file)
155{
156 /* /dev/watchdog can only be opened once */
157 if (test_and_set_bit(0, &timer_alive))
158 return -EBUSY;
159
160 /* Reload and activate timer */
161 tco_timer_keepalive();
162 tco_timer_start();
163 return nonseekable_open(inode, file);
164}
165
166static int nv_tco_release(struct inode *inode, struct file *file)
167{
168 /* Shut off the timer */
169 if (tco_expect_close == 42) {
170 tco_timer_stop();
171 } else {
172 printk(KERN_CRIT PFX "Unexpected close, not stopping "
173 "watchdog!\n");
174 tco_timer_keepalive();
175 }
176 clear_bit(0, &timer_alive);
177 tco_expect_close = 0;
178 return 0;
179}
180
181static ssize_t nv_tco_write(struct file *file, const char __user *data,
182 size_t len, loff_t *ppos)
183{
184 /* See if we got the magic character 'V' and reload the timer */
185 if (len) {
186 if (!nowayout) {
187 size_t i;
188
189 /*
190 * note: just in case someone wrote the magic character
191 * five months ago...
192 */
193 tco_expect_close = 0;
194
195 /*
196 * scan to see whether or not we got the magic
197 * character
198 */
199 for (i = 0; i != len; i++) {
200 char c;
201 if (get_user(c, data + i))
202 return -EFAULT;
203 if (c == 'V')
204 tco_expect_close = 42;
205 }
206 }
207
208 /* someone wrote to us, we should reload the timer */
209 tco_timer_keepalive();
210 }
211 return len;
212}
213
214static long nv_tco_ioctl(struct file *file, unsigned int cmd,
215 unsigned long arg)
216{
217 int new_options, retval = -EINVAL;
218 int new_heartbeat;
219 void __user *argp = (void __user *)arg;
220 int __user *p = argp;
221 static const struct watchdog_info ident = {
222 .options = WDIOF_SETTIMEOUT |
223 WDIOF_KEEPALIVEPING |
224 WDIOF_MAGICCLOSE,
225 .firmware_version = 0,
226 .identity = TCO_MODULE_NAME,
227 };
228
229 switch (cmd) {
230 case WDIOC_GETSUPPORT:
231 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
232 case WDIOC_GETSTATUS:
233 case WDIOC_GETBOOTSTATUS:
234 return put_user(0, p);
235 case WDIOC_SETOPTIONS:
236 if (get_user(new_options, p))
237 return -EFAULT;
238 if (new_options & WDIOS_DISABLECARD) {
239 tco_timer_stop();
240 retval = 0;
241 }
242 if (new_options & WDIOS_ENABLECARD) {
243 tco_timer_keepalive();
244 tco_timer_start();
245 retval = 0;
246 }
247 return retval;
248 case WDIOC_KEEPALIVE:
249 tco_timer_keepalive();
250 return 0;
251 case WDIOC_SETTIMEOUT:
252 if (get_user(new_heartbeat, p))
253 return -EFAULT;
254 if (tco_timer_set_heartbeat(new_heartbeat))
255 return -EINVAL;
256 tco_timer_keepalive();
257 /* Fall through */
258 case WDIOC_GETTIMEOUT:
259 return put_user(heartbeat, p);
260 default:
261 return -ENOTTY;
262 }
263}
264
265/*
266 * Kernel Interfaces
267 */
268
269static const struct file_operations nv_tco_fops = {
270 .owner = THIS_MODULE,
271 .llseek = no_llseek,
272 .write = nv_tco_write,
273 .unlocked_ioctl = nv_tco_ioctl,
274 .open = nv_tco_open,
275 .release = nv_tco_release,
276};
277
278static struct miscdevice nv_tco_miscdev = {
279 .minor = WATCHDOG_MINOR,
280 .name = "watchdog",
281 .fops = &nv_tco_fops,
282};
283
284/*
285 * Data for PCI driver interface
286 *
287 * This data only exists for exporting the supported
288 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
289 * register a pci_driver, because someone else might one day
290 * want to register another driver on the same PCI id.
291 */
292static DEFINE_PCI_DEVICE_TABLE(tco_pci_tbl) = {
293 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
294 PCI_ANY_ID, PCI_ANY_ID, },
295 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
296 PCI_ANY_ID, PCI_ANY_ID, },
297 { 0, }, /* End of list */
298};
299MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
300
301/*
302 * Init & exit routines
303 */
304
305static unsigned char __devinit nv_tco_getdevice(void)
306{
307 struct pci_dev *dev = NULL;
308 u32 val;
309
310 /* Find the PCI device */
311 for_each_pci_dev(dev) {
312 if (pci_match_id(tco_pci_tbl, dev) != NULL) {
313 tco_pci = dev;
314 break;
315 }
316 }
317
318 if (!tco_pci)
319 return 0;
320
321 /* Find the base io port */
322 pci_read_config_dword(tco_pci, 0x64, &val);
323 val &= 0xffff;
324 if (val == 0x0001 || val == 0x0000) {
325 /* Something is wrong here, bar isn't setup */
326 printk(KERN_ERR PFX "failed to get tcobase address\n");
327 return 0;
328 }
329 val &= 0xff00;
330 tcobase = val + 0x40;
331
332 if (!request_region(tcobase, 0x10, "NV TCO")) {
333 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
334 tcobase);
335 return 0;
336 }
337
338 /* Set a reasonable heartbeat before we stop the timer */
339 tco_timer_set_heartbeat(30);
340
341 /*
342 * Stop the TCO before we change anything so we don't race with
343 * a zeroed timer.
344 */
345 tco_timer_keepalive();
346 tco_timer_stop();
347
348 /* Disable SMI caused by TCO */
349 if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) {
350 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
351 MCP51_SMI_EN(tcobase));
352 goto out;
353 }
354 val = inl(MCP51_SMI_EN(tcobase));
355 val &= ~MCP51_SMI_EN_TCO;
356 outl(val, MCP51_SMI_EN(tcobase));
357 val = inl(MCP51_SMI_EN(tcobase));
358 release_region(MCP51_SMI_EN(tcobase), 4);
359 if (val & MCP51_SMI_EN_TCO) {
360 printk(KERN_ERR PFX "Could not disable SMI caused by TCO\n");
361 goto out;
362 }
363
364 /* Check chipset's NO_REBOOT bit */
365 pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
366 val |= MCP51_SMBUS_SETUP_B_TCO_REBOOT;
367 pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
368 pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
369 if (!(val & MCP51_SMBUS_SETUP_B_TCO_REBOOT)) {
370 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot "
371 "disabled by hardware\n");
372 goto out;
373 }
374
375 return 1;
376out:
377 release_region(tcobase, 0x10);
378 return 0;
379}
380
381static int __devinit nv_tco_init(struct platform_device *dev)
382{
383 int ret;
384
385 /* Check whether or not the hardware watchdog is there */
386 if (!nv_tco_getdevice())
387 return -ENODEV;
388
389 /* Check to see if last reboot was due to watchdog timeout */
390 printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
391 inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not ");
392
393 /* Clear out the old status */
394 outl(TCO_STS_RESET, TCO_STS(tcobase));
395
396 /*
397 * Check that the heartbeat value is within it's range.
398 * If not, reset to the default.
399 */
400 if (tco_timer_set_heartbeat(heartbeat)) {
401 heartbeat = WATCHDOG_HEARTBEAT;
402 tco_timer_set_heartbeat(heartbeat);
403 printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, "
404 "using %d\n", heartbeat);
405 }
406
407 ret = misc_register(&nv_tco_miscdev);
408 if (ret != 0) {
409 printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
410 "(err=%d)\n", WATCHDOG_MINOR, ret);
411 goto unreg_region;
412 }
413
414 clear_bit(0, &timer_alive);
415
416 tco_timer_stop();
417
418 printk(KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec "
419 "(nowayout=%d)\n", tcobase, heartbeat, nowayout);
420
421 return 0;
422
423unreg_region:
424 release_region(tcobase, 0x10);
425 return ret;
426}
427
428static void __devexit nv_tco_cleanup(void)
429{
430 u32 val;
431
432 /* Stop the timer before we leave */
433 if (!nowayout)
434 tco_timer_stop();
435
436 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
437 pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
438 val &= ~MCP51_SMBUS_SETUP_B_TCO_REBOOT;
439 pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
440 pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
441 if (val & MCP51_SMBUS_SETUP_B_TCO_REBOOT) {
442 printk(KERN_CRIT PFX "Couldn't unset REBOOT bit. Machine may "
443 "soon reset\n");
444 }
445
446 /* Deregister */
447 misc_deregister(&nv_tco_miscdev);
448 release_region(tcobase, 0x10);
449}
450
451static int __devexit nv_tco_remove(struct platform_device *dev)
452{
453 if (tcobase)
454 nv_tco_cleanup();
455
456 return 0;
457}
458
459static void nv_tco_shutdown(struct platform_device *dev)
460{
461 tco_timer_stop();
462}
463
464static struct platform_driver nv_tco_driver = {
465 .probe = nv_tco_init,
466 .remove = __devexit_p(nv_tco_remove),
467 .shutdown = nv_tco_shutdown,
468 .driver = {
469 .owner = THIS_MODULE,
470 .name = TCO_MODULE_NAME,
471 },
472};
473
474static int __init nv_tco_init_module(void)
475{
476 int err;
477
478 printk(KERN_INFO PFX "NV TCO WatchDog Timer Driver v%s\n",
479 TCO_VERSION);
480
481 err = platform_driver_register(&nv_tco_driver);
482 if (err)
483 return err;
484
485 nv_tco_platform_device = platform_device_register_simple(
486 TCO_MODULE_NAME, -1, NULL, 0);
487 if (IS_ERR(nv_tco_platform_device)) {
488 err = PTR_ERR(nv_tco_platform_device);
489 goto unreg_platform_driver;
490 }
491
492 return 0;
493
494unreg_platform_driver:
495 platform_driver_unregister(&nv_tco_driver);
496 return err;
497}
498
499static void __exit nv_tco_cleanup_module(void)
500{
501 platform_device_unregister(nv_tco_platform_device);
502 platform_driver_unregister(&nv_tco_driver);
503 printk(KERN_INFO PFX "NV TCO Watchdog Module Unloaded.\n");
504}
505
506module_init(nv_tco_init_module);
507module_exit(nv_tco_cleanup_module);
508
509MODULE_AUTHOR("Mike Waychison");
510MODULE_DESCRIPTION("TCO timer driver for NV chipsets");
511MODULE_LICENSE("GPL");
512MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/nv_tco.h b/drivers/watchdog/nv_tco.h
new file mode 100644
index 000000000000..c2d1d04e055b
--- /dev/null
+++ b/drivers/watchdog/nv_tco.h
@@ -0,0 +1,64 @@
1/*
2 * nv_tco: TCO timer driver for nVidia chipsets.
3 *
4 * (c) Copyright 2005 Google Inc., All Rights Reserved.
5 *
6 * Supported Chipsets:
7 * - MCP51/MCP55
8 *
9 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights
10 * Reserved.
11 * http://www.kernelconcepts.de
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 *
18 * Neither kernel concepts nor Nils Faerber admit liability nor provide
19 * warranty for any of this software. This material is provided
20 * "AS-IS" and at no charge.
21 *
22 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>
23 * developed for
24 * Jentro AG, Haar/Munich (Germany)
25 *
26 * TCO timer driver for NV chipsets
27 * based on softdog.c by Alan Cox <alan@redhat.com>
28 */
29
30/*
31 * Some address definitions for the TCO
32 */
33
34#define TCO_RLD(base) ((base) + 0x00) /* TCO Timer Reload and Current Value */
35#define TCO_TMR(base) ((base) + 0x01) /* TCO Timer Initial Value */
36
37#define TCO_STS(base) ((base) + 0x04) /* TCO Status Register */
38/*
39 * TCO Boot Status bit: set on TCO reset, reset by software or standby
40 * power-good (survives reboots), unfortunately this bit is never
41 * set.
42 */
43# define TCO_STS_BOOT_STS (1 << 9)
44/*
45 * first and 2nd timeout status bits, these also survive a warm boot,
46 * and they work, so we use them.
47 */
48# define TCO_STS_TCO_INT_STS (1 << 1)
49# define TCO_STS_TCO2TO_STS (1 << 10)
50# define TCO_STS_RESET (TCO_STS_BOOT_STS | TCO_STS_TCO2TO_STS | \
51 TCO_STS_TCO_INT_STS)
52
53#define TCO_CNT(base) ((base) + 0x08) /* TCO Control Register */
54# define TCO_CNT_TCOHALT (1 << 12)
55
56#define MCP51_SMBUS_SETUP_B 0xe8
57# define MCP51_SMBUS_SETUP_B_TCO_REBOOT (1 << 25)
58
59/*
60 * The SMI_EN register is at the base io address + 0x04,
61 * while TCOBASE is + 0x40.
62 */
63#define MCP51_SMI_EN(base) ((base) - 0x40 + 0x04)
64# define MCP51_SMI_EN_TCO ((1 << 4) | (1 << 5))
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 2a410170eca6..945ee8300306 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -64,6 +64,7 @@
64#include <linux/cpu.h> 64#include <linux/cpu.h>
65#include <linux/smp.h> 65#include <linux/smp.h>
66#include <linux/fs.h> 66#include <linux/fs.h>
67#include <linux/irq.h>
67 68
68#include <asm/mipsregs.h> 69#include <asm/mipsregs.h>
69#include <asm/uasm.h> 70#include <asm/uasm.h>
@@ -477,7 +478,7 @@ static void octeon_wdt_calc_parameters(int t)
477 478
478 countdown_reset = periods > 2 ? periods - 2 : 0; 479 countdown_reset = periods > 2 ? periods - 2 : 0;
479 heartbeat = t; 480 heartbeat = t;
480 timeout_cnt = ((octeon_get_clock_rate() >> 8) * timeout_sec) >> 8; 481 timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
481} 482}
482 483
483static int octeon_wdt_set_heartbeat(int t) 484static int octeon_wdt_set_heartbeat(int t)
@@ -676,7 +677,7 @@ static int __init octeon_wdt_init(void)
676 max_timeout_sec = 6; 677 max_timeout_sec = 6;
677 do { 678 do {
678 max_timeout_sec--; 679 max_timeout_sec--;
679 timeout_cnt = ((octeon_get_clock_rate() >> 8) * max_timeout_sec) >> 8; 680 timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8;
680 } while (timeout_cnt > 65535); 681 } while (timeout_cnt > 65535);
681 682
682 BUG_ON(timeout_cnt == 0); 683 BUG_ON(timeout_cnt == 0);
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 76b58abf4451..2b4acb86c191 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -38,11 +38,11 @@
38#include <linux/err.h> 38#include <linux/err.h>
39#include <linux/platform_device.h> 39#include <linux/platform_device.h>
40#include <linux/moduleparam.h> 40#include <linux/moduleparam.h>
41#include <linux/clk.h>
42#include <linux/bitops.h> 41#include <linux/bitops.h>
43#include <linux/io.h> 42#include <linux/io.h>
44#include <linux/uaccess.h> 43#include <linux/uaccess.h>
45#include <linux/slab.h> 44#include <linux/slab.h>
45#include <linux/pm_runtime.h>
46#include <mach/hardware.h> 46#include <mach/hardware.h>
47#include <plat/prcm.h> 47#include <plat/prcm.h>
48 48
@@ -61,8 +61,6 @@ struct omap_wdt_dev {
61 void __iomem *base; /* physical */ 61 void __iomem *base; /* physical */
62 struct device *dev; 62 struct device *dev;
63 int omap_wdt_users; 63 int omap_wdt_users;
64 struct clk *ick;
65 struct clk *fck;
66 struct resource *mem; 64 struct resource *mem;
67 struct miscdevice omap_wdt_miscdev; 65 struct miscdevice omap_wdt_miscdev;
68}; 66};
@@ -126,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
126 u32 pre_margin = GET_WLDR_VAL(timer_margin); 124 u32 pre_margin = GET_WLDR_VAL(timer_margin);
127 void __iomem *base = wdev->base; 125 void __iomem *base = wdev->base;
128 126
127 pm_runtime_get_sync(wdev->dev);
128
129 /* just count up at 32 KHz */ 129 /* just count up at 32 KHz */
130 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 130 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
131 cpu_relax(); 131 cpu_relax();
@@ -133,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
133 __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); 133 __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
134 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) 134 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
135 cpu_relax(); 135 cpu_relax();
136
137 pm_runtime_put_sync(wdev->dev);
136} 138}
137 139
138/* 140/*
@@ -146,8 +148,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
146 if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) 148 if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
147 return -EBUSY; 149 return -EBUSY;
148 150
149 clk_enable(wdev->ick); /* Enable the interface clock */ 151 pm_runtime_get_sync(wdev->dev);
150 clk_enable(wdev->fck); /* Enable the functional clock */
151 152
152 /* initialize prescaler */ 153 /* initialize prescaler */
153 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) 154 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -163,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
163 omap_wdt_ping(wdev); /* trigger loading of new timeout value */ 164 omap_wdt_ping(wdev); /* trigger loading of new timeout value */
164 omap_wdt_enable(wdev); 165 omap_wdt_enable(wdev);
165 166
167 pm_runtime_put_sync(wdev->dev);
168
166 return nonseekable_open(inode, file); 169 return nonseekable_open(inode, file);
167} 170}
168 171
@@ -174,11 +177,11 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
174 * Shut off the timer unless NOWAYOUT is defined. 177 * Shut off the timer unless NOWAYOUT is defined.
175 */ 178 */
176#ifndef CONFIG_WATCHDOG_NOWAYOUT 179#ifndef CONFIG_WATCHDOG_NOWAYOUT
180 pm_runtime_get_sync(wdev->dev);
177 181
178 omap_wdt_disable(wdev); 182 omap_wdt_disable(wdev);
179 183
180 clk_disable(wdev->ick); 184 pm_runtime_put_sync(wdev->dev);
181 clk_disable(wdev->fck);
182#else 185#else
183 printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); 186 printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
184#endif 187#endif
@@ -194,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
194 197
195 /* Refresh LOAD_TIME. */ 198 /* Refresh LOAD_TIME. */
196 if (len) { 199 if (len) {
200 pm_runtime_get_sync(wdev->dev);
197 spin_lock(&wdt_lock); 201 spin_lock(&wdt_lock);
198 omap_wdt_ping(wdev); 202 omap_wdt_ping(wdev);
199 spin_unlock(&wdt_lock); 203 spin_unlock(&wdt_lock);
204 pm_runtime_put_sync(wdev->dev);
200 } 205 }
201 return len; 206 return len;
202} 207}
@@ -228,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
228 return put_user(omap_prcm_get_reset_sources(), 233 return put_user(omap_prcm_get_reset_sources(),
229 (int __user *)arg); 234 (int __user *)arg);
230 case WDIOC_KEEPALIVE: 235 case WDIOC_KEEPALIVE:
236 pm_runtime_get_sync(wdev->dev);
231 spin_lock(&wdt_lock); 237 spin_lock(&wdt_lock);
232 omap_wdt_ping(wdev); 238 omap_wdt_ping(wdev);
233 spin_unlock(&wdt_lock); 239 spin_unlock(&wdt_lock);
240 pm_runtime_put_sync(wdev->dev);
234 return 0; 241 return 0;
235 case WDIOC_SETTIMEOUT: 242 case WDIOC_SETTIMEOUT:
236 if (get_user(new_margin, (int __user *)arg)) 243 if (get_user(new_margin, (int __user *)arg))
237 return -EFAULT; 244 return -EFAULT;
238 omap_wdt_adjust_timeout(new_margin); 245 omap_wdt_adjust_timeout(new_margin);
239 246
247 pm_runtime_get_sync(wdev->dev);
240 spin_lock(&wdt_lock); 248 spin_lock(&wdt_lock);
241 omap_wdt_disable(wdev); 249 omap_wdt_disable(wdev);
242 omap_wdt_set_timeout(wdev); 250 omap_wdt_set_timeout(wdev);
@@ -244,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
244 252
245 omap_wdt_ping(wdev); 253 omap_wdt_ping(wdev);
246 spin_unlock(&wdt_lock); 254 spin_unlock(&wdt_lock);
255 pm_runtime_put_sync(wdev->dev);
247 /* Fall */ 256 /* Fall */
248 case WDIOC_GETTIMEOUT: 257 case WDIOC_GETTIMEOUT:
249 return put_user(timer_margin, (int __user *)arg); 258 return put_user(timer_margin, (int __user *)arg);
@@ -258,6 +267,7 @@ static const struct file_operations omap_wdt_fops = {
258 .unlocked_ioctl = omap_wdt_ioctl, 267 .unlocked_ioctl = omap_wdt_ioctl,
259 .open = omap_wdt_open, 268 .open = omap_wdt_open,
260 .release = omap_wdt_release, 269 .release = omap_wdt_release,
270 .llseek = no_llseek,
261}; 271};
262 272
263static int __devinit omap_wdt_probe(struct platform_device *pdev) 273static int __devinit omap_wdt_probe(struct platform_device *pdev)
@@ -292,19 +302,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
292 302
293 wdev->omap_wdt_users = 0; 303 wdev->omap_wdt_users = 0;
294 wdev->mem = mem; 304 wdev->mem = mem;
295 305 wdev->dev = &pdev->dev;
296 wdev->ick = clk_get(&pdev->dev, "ick");
297 if (IS_ERR(wdev->ick)) {
298 ret = PTR_ERR(wdev->ick);
299 wdev->ick = NULL;
300 goto err_clk;
301 }
302 wdev->fck = clk_get(&pdev->dev, "fck");
303 if (IS_ERR(wdev->fck)) {
304 ret = PTR_ERR(wdev->fck);
305 wdev->fck = NULL;
306 goto err_clk;
307 }
308 306
309 wdev->base = ioremap(res->start, resource_size(res)); 307 wdev->base = ioremap(res->start, resource_size(res));
310 if (!wdev->base) { 308 if (!wdev->base) {
@@ -314,8 +312,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
314 312
315 platform_set_drvdata(pdev, wdev); 313 platform_set_drvdata(pdev, wdev);
316 314
317 clk_enable(wdev->ick); 315 pm_runtime_enable(wdev->dev);
318 clk_enable(wdev->fck); 316 pm_runtime_get_sync(wdev->dev);
319 317
320 omap_wdt_disable(wdev); 318 omap_wdt_disable(wdev);
321 omap_wdt_adjust_timeout(timer_margin); 319 omap_wdt_adjust_timeout(timer_margin);
@@ -333,11 +331,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
333 __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 331 __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
334 timer_margin); 332 timer_margin);
335 333
336 /* autogate OCP interface clock */ 334 pm_runtime_put_sync(wdev->dev);
337 __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG);
338
339 clk_disable(wdev->ick);
340 clk_disable(wdev->fck);
341 335
342 omap_wdt_dev = pdev; 336 omap_wdt_dev = pdev;
343 337
@@ -349,12 +343,6 @@ err_misc:
349 343
350err_ioremap: 344err_ioremap:
351 wdev->base = NULL; 345 wdev->base = NULL;
352
353err_clk:
354 if (wdev->ick)
355 clk_put(wdev->ick);
356 if (wdev->fck)
357 clk_put(wdev->fck);
358 kfree(wdev); 346 kfree(wdev);
359 347
360err_kzalloc: 348err_kzalloc:
@@ -370,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
370{ 358{
371 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 359 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
372 360
373 if (wdev->omap_wdt_users) 361 if (wdev->omap_wdt_users) {
362 pm_runtime_get_sync(wdev->dev);
374 omap_wdt_disable(wdev); 363 omap_wdt_disable(wdev);
364 pm_runtime_put_sync(wdev->dev);
365 }
375} 366}
376 367
377static int __devexit omap_wdt_remove(struct platform_device *pdev) 368static int __devexit omap_wdt_remove(struct platform_device *pdev)
@@ -386,8 +377,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
386 release_mem_region(res->start, resource_size(res)); 377 release_mem_region(res->start, resource_size(res));
387 platform_set_drvdata(pdev, NULL); 378 platform_set_drvdata(pdev, NULL);
388 379
389 clk_put(wdev->ick);
390 clk_put(wdev->fck);
391 iounmap(wdev->base); 380 iounmap(wdev->base);
392 381
393 kfree(wdev); 382 kfree(wdev);
@@ -408,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
408{ 397{
409 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 398 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
410 399
411 if (wdev->omap_wdt_users) 400 if (wdev->omap_wdt_users) {
401 pm_runtime_get_sync(wdev->dev);
412 omap_wdt_disable(wdev); 402 omap_wdt_disable(wdev);
403 pm_runtime_put_sync(wdev->dev);
404 }
413 405
414 return 0; 406 return 0;
415} 407}
@@ -419,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev)
419 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 411 struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
420 412
421 if (wdev->omap_wdt_users) { 413 if (wdev->omap_wdt_users) {
414 pm_runtime_get_sync(wdev->dev);
422 omap_wdt_enable(wdev); 415 omap_wdt_enable(wdev);
423 omap_wdt_ping(wdev); 416 omap_wdt_ping(wdev);
417 pm_runtime_put_sync(wdev->dev);
424 } 418 }
425 419
426 return 0; 420 return 0;
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..b7c139051575 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -49,7 +49,7 @@
49#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) 49#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1)
50#define SWC_LDN 0x04 50#define SWC_LDN 0x04
51#define SIOCFG2 0x22 /* Serial IO register */ 51#define SIOCFG2 0x22 /* Serial IO register */
52#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ 52#define WDCTL 0x10 /* Watchdog-Timer-Control-Register */
53#define WDTO 0x11 /* Watchdog timeout register */ 53#define WDTO 0x11 /* Watchdog timeout register */
54#define WDCFG 0x12 /* Watchdog config register */ 54#define WDCFG 0x12 /* Watchdog config register */
55 55
@@ -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..614933225560 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 *
@@ -254,7 +254,6 @@ static struct miscdevice pnx4008_wdt_miscdev = {
254static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) 254static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
255{ 255{
256 int ret = 0, size; 256 int ret = 0, size;
257 struct resource *res;
258 257
259 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 258 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
260 heartbeat = DEFAULT_HEARTBEAT; 259 heartbeat = DEFAULT_HEARTBEAT;
@@ -262,42 +261,42 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
262 printk(KERN_INFO MODULE_NAME 261 printk(KERN_INFO MODULE_NAME
263 "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat); 262 "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
264 263
265 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 264 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
266 if (res == NULL) { 265 if (wdt_mem == NULL) {
267 printk(KERN_INFO MODULE_NAME 266 printk(KERN_INFO MODULE_NAME
268 "failed to get memory region resouce\n"); 267 "failed to get memory region resouce\n");
269 return -ENOENT; 268 return -ENOENT;
270 } 269 }
271 270
272 size = resource_size(res); 271 size = resource_size(wdt_mem);
273 wdt_mem = request_mem_region(res->start, size, pdev->name);
274 272
275 if (wdt_mem == NULL) { 273 if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
276 printk(KERN_INFO MODULE_NAME "failed to get memory region\n"); 274 printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
277 return -ENOENT; 275 return -ENOENT;
278 } 276 }
279 wdt_base = (void __iomem *)IO_ADDRESS(res->start); 277 wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
280 278
281 wdt_clk = clk_get(&pdev->dev, NULL); 279 wdt_clk = clk_get(&pdev->dev, NULL);
282 if (IS_ERR(wdt_clk)) { 280 if (IS_ERR(wdt_clk)) {
283 ret = PTR_ERR(wdt_clk); 281 ret = PTR_ERR(wdt_clk);
284 release_resource(wdt_mem); 282 release_mem_region(wdt_mem->start, size);
285 kfree(wdt_mem); 283 wdt_mem = NULL;
286 goto out; 284 goto out;
287 } 285 }
288 286
289 ret = clk_enable(wdt_clk); 287 ret = clk_enable(wdt_clk);
290 if (ret) { 288 if (ret) {
291 release_resource(wdt_mem); 289 release_mem_region(wdt_mem->start, size);
292 kfree(wdt_mem); 290 wdt_mem = NULL;
291 clk_put(wdt_clk);
293 goto out; 292 goto out;
294 } 293 }
295 294
296 ret = misc_register(&pnx4008_wdt_miscdev); 295 ret = misc_register(&pnx4008_wdt_miscdev);
297 if (ret < 0) { 296 if (ret < 0) {
298 printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); 297 printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
299 release_resource(wdt_mem); 298 release_mem_region(wdt_mem->start, size);
300 kfree(wdt_mem); 299 wdt_mem = NULL;
301 clk_disable(wdt_clk); 300 clk_disable(wdt_clk);
302 clk_put(wdt_clk); 301 clk_put(wdt_clk);
303 } else { 302 } else {
@@ -320,8 +319,7 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
320 clk_put(wdt_clk); 319 clk_put(wdt_clk);
321 320
322 if (wdt_mem) { 321 if (wdt_mem) {
323 release_resource(wdt_mem); 322 release_mem_region(wdt_mem->start, resource_size(wdt_mem));
324 kfree(wdt_mem);
325 wdt_mem = NULL; 323 wdt_mem = NULL;
326 } 324 }
327 return 0; 325 return 0;
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..f7f5aa00df60 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)
@@ -402,7 +402,6 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
402 402
403static int __devinit s3c2410wdt_probe(struct platform_device *pdev) 403static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
404{ 404{
405 struct resource *res;
406 struct device *dev; 405 struct device *dev;
407 unsigned int wtcon; 406 unsigned int wtcon;
408 int started = 0; 407 int started = 0;
@@ -416,20 +415,19 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
416 415
417 /* get the memory region for the watchdog timer */ 416 /* get the memory region for the watchdog timer */
418 417
419 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 418 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
420 if (res == NULL) { 419 if (wdt_mem == NULL) {
421 dev_err(dev, "no memory resource specified\n"); 420 dev_err(dev, "no memory resource specified\n");
422 return -ENOENT; 421 return -ENOENT;
423 } 422 }
424 423
425 size = resource_size(res); 424 size = resource_size(wdt_mem);
426 wdt_mem = request_mem_region(res->start, size, pdev->name); 425 if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
427 if (wdt_mem == NULL) {
428 dev_err(dev, "failed to get memory region\n"); 426 dev_err(dev, "failed to get memory region\n");
429 return -EBUSY; 427 return -EBUSY;
430 } 428 }
431 429
432 wdt_base = ioremap(res->start, size); 430 wdt_base = ioremap(wdt_mem->start, size);
433 if (wdt_base == NULL) { 431 if (wdt_base == NULL) {
434 dev_err(dev, "failed to ioremap() region\n"); 432 dev_err(dev, "failed to ioremap() region\n");
435 ret = -EINVAL; 433 ret = -EINVAL;
@@ -524,8 +522,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
524 iounmap(wdt_base); 522 iounmap(wdt_base);
525 523
526 err_req: 524 err_req:
527 release_resource(wdt_mem); 525 release_mem_region(wdt_mem->start, size);
528 kfree(wdt_mem); 526 wdt_mem = NULL;
529 527
530 return ret; 528 return ret;
531} 529}
@@ -545,8 +543,7 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
545 543
546 iounmap(wdt_base); 544 iounmap(wdt_base);
547 545
548 release_resource(wdt_mem); 546 release_mem_region(wdt_mem->start, resource_size(wdt_mem));
549 kfree(wdt_mem);
550 wdt_mem = NULL; 547 wdt_mem = NULL;
551 return 0; 548 return 0;
552} 549}
diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c
index 67ddeb1c830a..ff11504c376e 100644
--- a/drivers/watchdog/sbc7240_wdt.c
+++ b/drivers/watchdog/sbc7240_wdt.c
@@ -273,7 +273,7 @@ static int __init sbc7240_wdt_init(void)
273 273
274 /* The IO port 0x043 used to disable the watchdog 274 /* The IO port 0x043 used to disable the watchdog
275 * is already claimed by the system timer, so we 275 * is already claimed by the system timer, so we
276 * cant request_region() it ...*/ 276 * can't request_region() it ...*/
277 277
278 if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) { 278 if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) {
279 timeout = SBC7240_TIMEOUT; 279 timeout = SBC7240_TIMEOUT;
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_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
index 28f1214457bd..3066a5127ca8 100644
--- a/drivers/watchdog/sbc_epx_c3.c
+++ b/drivers/watchdog/sbc_epx_c3.c
@@ -220,7 +220,7 @@ module_exit(watchdog_exit);
220MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>"); 220MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
221MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. " 221MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. "
222 "Note that there is no way to probe for this device -- " 222 "Note that there is no way to probe for this device -- "
223 "so only use it if you are *sure* you are runnning on this specific " 223 "so only use it if you are *sure* you are running on this specific "
224 "SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"); 224 "SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
225MODULE_LICENSE("GPL"); 225MODULE_LICENSE("GPL");
226MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 226MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
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..c7cf4b01f58d 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -201,7 +201,7 @@ static void sch311x_wdt_get_status(int *status)
201 spin_lock(&sch311x_wdt_data.io_lock); 201 spin_lock(&sch311x_wdt_data.io_lock);
202 202
203 /* -- Watchdog timer control -- 203 /* -- Watchdog timer control --
204 * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured 204 * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred
205 * Bit 1 Reserved 205 * Bit 1 Reserved
206 * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) 206 * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning)
207 * Bit 3 P20 Force Timeout enabled: 207 * Bit 3 P20 Force Timeout enabled:
@@ -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..db84f2322d1a 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
@@ -48,7 +50,7 @@
48 * necssary. 50 * necssary.
49 * 51 *
50 * As a result of this timing problem, the only modes that are particularly 52 * As a result of this timing problem, the only modes that are particularly
51 * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms 53 * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms
52 * overflow periods respectively. 54 * overflow periods respectively.
53 * 55 *
54 * Also, since we can't really expect userspace to be responsive enough 56 * Also, since we can't really expect userspace to be responsive enough
@@ -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..e97b0499bd0d 100644
--- a/drivers/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -191,7 +191,7 @@ static inline void wdt_timer_conf(unsigned char conf)
191static inline void wdt_timer_ctrl(unsigned char reg) 191static inline void wdt_timer_ctrl(unsigned char reg)
192{ 192{
193 /* -- Watchdog timer control -- 193 /* -- Watchdog timer control --
194 * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured 194 * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occurred
195 * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz 195 * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz
196 * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) 196 * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning)
197 * Bit 3 P20 Force Timeout enabled: 197 * Bit 3 P20 Force Timeout enabled:
@@ -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..bf16ffb4d21e 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -48,6 +48,7 @@
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/jiffies.h> 49#include <linux/jiffies.h>
50#include <linux/uaccess.h> 50#include <linux/uaccess.h>
51#include <linux/kernel.h>
51 52
52#define PFX "SoftDog: " 53#define PFX "SoftDog: "
53 54
@@ -75,6 +76,11 @@ MODULE_PARM_DESC(soft_noboot,
75 "Softdog action, set to 1 to ignore reboots, 0 to reboot " 76 "Softdog action, set to 1 to ignore reboots, 0 to reboot "
76 "(default depends on ONLY_TESTING)"); 77 "(default depends on ONLY_TESTING)");
77 78
79static int soft_panic;
80module_param(soft_panic, int, 0);
81MODULE_PARM_DESC(soft_panic,
82 "Softdog action, set to 1 to panic, 0 to reboot (default=0)");
83
78/* 84/*
79 * Our timer 85 * Our timer
80 */ 86 */
@@ -98,7 +104,10 @@ static void watchdog_fire(unsigned long data)
98 104
99 if (soft_noboot) 105 if (soft_noboot)
100 printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); 106 printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
101 else { 107 else if (soft_panic) {
108 printk(KERN_CRIT PFX "Initiating panic.\n");
109 panic("Software Watchdog Timer expired.");
110 } else {
102 printk(KERN_CRIT PFX "Initiating system reboot.\n"); 111 printk(KERN_CRIT PFX "Initiating system reboot.\n");
103 emergency_restart(); 112 emergency_restart();
104 printk(KERN_CRIT PFX "Reboot didn't ?????\n"); 113 printk(KERN_CRIT PFX "Reboot didn't ?????\n");
@@ -151,7 +160,7 @@ static int softdog_release(struct inode *inode, struct file *file)
151{ 160{
152 /* 161 /*
153 * Shut off the timer. 162 * Shut off the timer.
154 * Lock it in if it's a module and we set nowayout 163 * Lock it in if it's a module and we set nowayout
155 */ 164 */
156 if (expect_close == 42) { 165 if (expect_close == 42) {
157 softdog_stop(); 166 softdog_stop();
@@ -267,7 +276,8 @@ static struct notifier_block softdog_notifier = {
267}; 276};
268 277
269static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 " 278static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 "
270 "initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n"; 279 "initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d "
280 "(nowayout= %d)\n";
271 281
272static int __init watchdog_init(void) 282static int __init watchdog_init(void)
273{ 283{
@@ -298,7 +308,7 @@ static int __init watchdog_init(void)
298 return ret; 308 return ret;
299 } 309 }
300 310
301 printk(banner, soft_noboot, soft_margin, nowayout); 311 printk(banner, soft_noboot, soft_margin, soft_panic, nowayout);
302 312
303 return 0; 313 return 0;
304} 314}
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
new file mode 100644
index 000000000000..87e0527669d8
--- /dev/null
+++ b/drivers/watchdog/sp5100_tco.c
@@ -0,0 +1,492 @@
1/*
2 * sp5100_tco : TCO timer driver for sp5100 chipsets
3 *
4 * (c) Copyright 2009 Google Inc., All Rights Reserved.
5 *
6 * Based on i8xx_tco.c:
7 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights
8 * Reserved.
9 * http://www.kernelconcepts.de
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 *
16 * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide"
17 */
18
19/*
20 * Includes, defines, variables, module parameters, ...
21 */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/types.h>
26#include <linux/miscdevice.h>
27#include <linux/watchdog.h>
28#include <linux/init.h>
29#include <linux/fs.h>
30#include <linux/pci.h>
31#include <linux/ioport.h>
32#include <linux/platform_device.h>
33#include <linux/uaccess.h>
34#include <linux/io.h>
35
36#include "sp5100_tco.h"
37
38/* Module and version information */
39#define TCO_VERSION "0.01"
40#define TCO_MODULE_NAME "SP5100 TCO timer"
41#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
42#define PFX TCO_MODULE_NAME ": "
43
44/* internal variables */
45static u32 tcobase_phys;
46static void __iomem *tcobase;
47static unsigned int pm_iobase;
48static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */
49static unsigned long timer_alive;
50static char tco_expect_close;
51static struct pci_dev *sp5100_tco_pci;
52
53/* the watchdog platform device */
54static struct platform_device *sp5100_tco_platform_device;
55
56/* module parameters */
57
58#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */
59static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
60module_param(heartbeat, int, 0);
61MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
62 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
63
64static int nowayout = WATCHDOG_NOWAYOUT;
65module_param(nowayout, int, 0);
66MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
67 " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
68
69/*
70 * Some TCO specific functions
71 */
72static void tco_timer_start(void)
73{
74 u32 val;
75 unsigned long flags;
76
77 spin_lock_irqsave(&tco_lock, flags);
78 val = readl(SP5100_WDT_CONTROL(tcobase));
79 val |= SP5100_WDT_START_STOP_BIT;
80 writel(val, SP5100_WDT_CONTROL(tcobase));
81 spin_unlock_irqrestore(&tco_lock, flags);
82}
83
84static void tco_timer_stop(void)
85{
86 u32 val;
87 unsigned long flags;
88
89 spin_lock_irqsave(&tco_lock, flags);
90 val = readl(SP5100_WDT_CONTROL(tcobase));
91 val &= ~SP5100_WDT_START_STOP_BIT;
92 writel(val, SP5100_WDT_CONTROL(tcobase));
93 spin_unlock_irqrestore(&tco_lock, flags);
94}
95
96static void tco_timer_keepalive(void)
97{
98 u32 val;
99 unsigned long flags;
100
101 spin_lock_irqsave(&tco_lock, flags);
102 val = readl(SP5100_WDT_CONTROL(tcobase));
103 val |= SP5100_WDT_TRIGGER_BIT;
104 writel(val, SP5100_WDT_CONTROL(tcobase));
105 spin_unlock_irqrestore(&tco_lock, flags);
106}
107
108static int tco_timer_set_heartbeat(int t)
109{
110 unsigned long flags;
111
112 if (t < 0 || t > 0xffff)
113 return -EINVAL;
114
115 /* Write new heartbeat to watchdog */
116 spin_lock_irqsave(&tco_lock, flags);
117 writel(t, SP5100_WDT_COUNT(tcobase));
118 spin_unlock_irqrestore(&tco_lock, flags);
119
120 heartbeat = t;
121 return 0;
122}
123
124/*
125 * /dev/watchdog handling
126 */
127
128static int sp5100_tco_open(struct inode *inode, struct file *file)
129{
130 /* /dev/watchdog can only be opened once */
131 if (test_and_set_bit(0, &timer_alive))
132 return -EBUSY;
133
134 /* Reload and activate timer */
135 tco_timer_start();
136 tco_timer_keepalive();
137 return nonseekable_open(inode, file);
138}
139
140static int sp5100_tco_release(struct inode *inode, struct file *file)
141{
142 /* Shut off the timer. */
143 if (tco_expect_close == 42) {
144 tco_timer_stop();
145 } else {
146 printk(KERN_CRIT PFX
147 "Unexpected close, not stopping watchdog!\n");
148 tco_timer_keepalive();
149 }
150 clear_bit(0, &timer_alive);
151 tco_expect_close = 0;
152 return 0;
153}
154
155static ssize_t sp5100_tco_write(struct file *file, const char __user *data,
156 size_t len, loff_t *ppos)
157{
158 /* See if we got the magic character 'V' and reload the timer */
159 if (len) {
160 if (!nowayout) {
161 size_t i;
162
163 /* note: just in case someone wrote the magic character
164 * five months ago... */
165 tco_expect_close = 0;
166
167 /* scan to see whether or not we got the magic character
168 */
169 for (i = 0; i != len; i++) {
170 char c;
171 if (get_user(c, data + i))
172 return -EFAULT;
173 if (c == 'V')
174 tco_expect_close = 42;
175 }
176 }
177
178 /* someone wrote to us, we should reload the timer */
179 tco_timer_keepalive();
180 }
181 return len;
182}
183
184static long sp5100_tco_ioctl(struct file *file, unsigned int cmd,
185 unsigned long arg)
186{
187 int new_options, retval = -EINVAL;
188 int new_heartbeat;
189 void __user *argp = (void __user *)arg;
190 int __user *p = argp;
191 static const struct watchdog_info ident = {
192 .options = WDIOF_SETTIMEOUT |
193 WDIOF_KEEPALIVEPING |
194 WDIOF_MAGICCLOSE,
195 .firmware_version = 0,
196 .identity = TCO_MODULE_NAME,
197 };
198
199 switch (cmd) {
200 case WDIOC_GETSUPPORT:
201 return copy_to_user(argp, &ident,
202 sizeof(ident)) ? -EFAULT : 0;
203 case WDIOC_GETSTATUS:
204 case WDIOC_GETBOOTSTATUS:
205 return put_user(0, p);
206 case WDIOC_SETOPTIONS:
207 if (get_user(new_options, p))
208 return -EFAULT;
209 if (new_options & WDIOS_DISABLECARD) {
210 tco_timer_stop();
211 retval = 0;
212 }
213 if (new_options & WDIOS_ENABLECARD) {
214 tco_timer_start();
215 tco_timer_keepalive();
216 retval = 0;
217 }
218 return retval;
219 case WDIOC_KEEPALIVE:
220 tco_timer_keepalive();
221 return 0;
222 case WDIOC_SETTIMEOUT:
223 if (get_user(new_heartbeat, p))
224 return -EFAULT;
225 if (tco_timer_set_heartbeat(new_heartbeat))
226 return -EINVAL;
227 tco_timer_keepalive();
228 /* Fall through */
229 case WDIOC_GETTIMEOUT:
230 return put_user(heartbeat, p);
231 default:
232 return -ENOTTY;
233 }
234}
235
236/*
237 * Kernel Interfaces
238 */
239
240static const struct file_operations sp5100_tco_fops = {
241 .owner = THIS_MODULE,
242 .llseek = no_llseek,
243 .write = sp5100_tco_write,
244 .unlocked_ioctl = sp5100_tco_ioctl,
245 .open = sp5100_tco_open,
246 .release = sp5100_tco_release,
247};
248
249static struct miscdevice sp5100_tco_miscdev = {
250 .minor = WATCHDOG_MINOR,
251 .name = "watchdog",
252 .fops = &sp5100_tco_fops,
253};
254
255/*
256 * Data for PCI driver interface
257 *
258 * This data only exists for exporting the supported
259 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
260 * register a pci_driver, because someone else might
261 * want to register another driver on the same PCI id.
262 */
263static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
264 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
265 PCI_ANY_ID, },
266 { 0, }, /* End of list */
267};
268MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
269
270/*
271 * Init & exit routines
272 */
273
274static unsigned char __devinit sp5100_tco_setupdevice(void)
275{
276 struct pci_dev *dev = NULL;
277 u32 val;
278
279 /* Match the PCI device */
280 for_each_pci_dev(dev) {
281 if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) {
282 sp5100_tco_pci = dev;
283 break;
284 }
285 }
286
287 if (!sp5100_tco_pci)
288 return 0;
289
290 /* Request the IO ports used by this driver */
291 pm_iobase = SP5100_IO_PM_INDEX_REG;
292 if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
293 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
294 pm_iobase);
295 goto exit;
296 }
297
298 /* Find the watchdog base address. */
299 outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG);
300 val = inb(SP5100_IO_PM_DATA_REG);
301 outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG);
302 val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
303 outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG);
304 val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
305 outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG);
306 /* Low three bits of BASE0 are reserved. */
307 val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
308
309 if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
310 "SP5100 TCO")) {
311 printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
312 val);
313 goto unreg_region;
314 }
315 tcobase_phys = val;
316
317 tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
318 if (tcobase == 0) {
319 printk(KERN_ERR PFX "failed to get tcobase address\n");
320 goto unreg_mem_region;
321 }
322
323 /* Enable watchdog decode bit */
324 pci_read_config_dword(sp5100_tco_pci,
325 SP5100_PCI_WATCHDOG_MISC_REG,
326 &val);
327
328 val |= SP5100_PCI_WATCHDOG_DECODE_EN;
329
330 pci_write_config_dword(sp5100_tco_pci,
331 SP5100_PCI_WATCHDOG_MISC_REG,
332 val);
333
334 /* Enable Watchdog timer and set the resolution to 1 sec. */
335 outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
336 val = inb(SP5100_IO_PM_DATA_REG);
337 val |= SP5100_PM_WATCHDOG_SECOND_RES;
338 val &= ~SP5100_PM_WATCHDOG_DISABLE;
339 outb(val, SP5100_IO_PM_DATA_REG);
340
341 /* Check that the watchdog action is set to reset the system. */
342 val = readl(SP5100_WDT_CONTROL(tcobase));
343 val &= ~SP5100_PM_WATCHDOG_ACTION_RESET;
344 writel(val, SP5100_WDT_CONTROL(tcobase));
345
346 /* Set a reasonable heartbeat before we stop the timer */
347 tco_timer_set_heartbeat(heartbeat);
348
349 /*
350 * Stop the TCO before we change anything so we don't race with
351 * a zeroed timer.
352 */
353 tco_timer_stop();
354
355 /* Done */
356 return 1;
357
358unreg_mem_region:
359 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
360unreg_region:
361 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
362exit:
363 return 0;
364}
365
366static int __devinit sp5100_tco_init(struct platform_device *dev)
367{
368 int ret;
369 u32 val;
370
371 /* Check whether or not the hardware watchdog is there. If found, then
372 * set it up.
373 */
374 if (!sp5100_tco_setupdevice())
375 return -ENODEV;
376
377 /* Check to see if last reboot was due to watchdog timeout */
378 printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
379 readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
380 "" : "not ");
381
382 /* Clear out the old status */
383 val = readl(SP5100_WDT_CONTROL(tcobase));
384 val &= ~SP5100_PM_WATCHDOG_FIRED;
385 writel(val, SP5100_WDT_CONTROL(tcobase));
386
387 /*
388 * Check that the heartbeat value is within it's range.
389 * If not, reset to the default.
390 */
391 if (tco_timer_set_heartbeat(heartbeat)) {
392 heartbeat = WATCHDOG_HEARTBEAT;
393 tco_timer_set_heartbeat(heartbeat);
394 }
395
396 ret = misc_register(&sp5100_tco_miscdev);
397 if (ret != 0) {
398 printk(KERN_ERR PFX "cannot register miscdev on minor="
399 "%d (err=%d)\n",
400 WATCHDOG_MINOR, ret);
401 goto exit;
402 }
403
404 clear_bit(0, &timer_alive);
405
406 printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec"
407 " (nowayout=%d)\n",
408 tcobase, heartbeat, nowayout);
409
410 return 0;
411
412exit:
413 iounmap(tcobase);
414 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
415 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
416 return ret;
417}
418
419static void __devexit sp5100_tco_cleanup(void)
420{
421 /* Stop the timer before we leave */
422 if (!nowayout)
423 tco_timer_stop();
424
425 /* Deregister */
426 misc_deregister(&sp5100_tco_miscdev);
427 iounmap(tcobase);
428 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
429 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
430}
431
432static int __devexit sp5100_tco_remove(struct platform_device *dev)
433{
434 if (tcobase)
435 sp5100_tco_cleanup();
436 return 0;
437}
438
439static void sp5100_tco_shutdown(struct platform_device *dev)
440{
441 tco_timer_stop();
442}
443
444static struct platform_driver sp5100_tco_driver = {
445 .probe = sp5100_tco_init,
446 .remove = __devexit_p(sp5100_tco_remove),
447 .shutdown = sp5100_tco_shutdown,
448 .driver = {
449 .owner = THIS_MODULE,
450 .name = TCO_MODULE_NAME,
451 },
452};
453
454static int __init sp5100_tco_init_module(void)
455{
456 int err;
457
458 printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n",
459 TCO_VERSION);
460
461 err = platform_driver_register(&sp5100_tco_driver);
462 if (err)
463 return err;
464
465 sp5100_tco_platform_device = platform_device_register_simple(
466 TCO_MODULE_NAME, -1, NULL, 0);
467 if (IS_ERR(sp5100_tco_platform_device)) {
468 err = PTR_ERR(sp5100_tco_platform_device);
469 goto unreg_platform_driver;
470 }
471
472 return 0;
473
474unreg_platform_driver:
475 platform_driver_unregister(&sp5100_tco_driver);
476 return err;
477}
478
479static void __exit sp5100_tco_cleanup_module(void)
480{
481 platform_device_unregister(sp5100_tco_platform_device);
482 platform_driver_unregister(&sp5100_tco_driver);
483 printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n");
484}
485
486module_init(sp5100_tco_init_module);
487module_exit(sp5100_tco_cleanup_module);
488
489MODULE_AUTHOR("Priyanka Gupta");
490MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset");
491MODULE_LICENSE("GPL");
492MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sp5100_tco.h b/drivers/watchdog/sp5100_tco.h
new file mode 100644
index 000000000000..a5a16cc90a34
--- /dev/null
+++ b/drivers/watchdog/sp5100_tco.h
@@ -0,0 +1,41 @@
1/*
2 * sp5100_tco: TCO timer driver for sp5100 chipsets.
3 *
4 * (c) Copyright 2009 Google Inc., All Rights Reserved.
5 *
6 * TCO timer driver for sp5100 chipsets
7 */
8
9/*
10 * Some address definitions for the Watchdog
11 */
12
13#define SP5100_WDT_MEM_MAP_SIZE 0x08
14#define SP5100_WDT_CONTROL(base) ((base) + 0x00) /* Watchdog Control */
15#define SP5100_WDT_COUNT(base) ((base) + 0x04) /* Watchdog Count */
16
17#define SP5100_WDT_START_STOP_BIT 1
18#define SP5100_WDT_TRIGGER_BIT (1 << 7)
19
20#define SP5100_PCI_WATCHDOG_MISC_REG 0x41
21#define SP5100_PCI_WATCHDOG_DECODE_EN (1 << 3)
22
23#define SP5100_PM_IOPORTS_SIZE 0x02
24
25/* These two IO registers are hardcoded and there doesn't seem to be a way to
26 * read them from a register.
27 */
28#define SP5100_IO_PM_INDEX_REG 0xCD6
29#define SP5100_IO_PM_DATA_REG 0xCD7
30
31#define SP5100_PM_WATCHDOG_CONTROL 0x69
32#define SP5100_PM_WATCHDOG_BASE0 0x6C
33#define SP5100_PM_WATCHDOG_BASE1 0x6D
34#define SP5100_PM_WATCHDOG_BASE2 0x6E
35#define SP5100_PM_WATCHDOG_BASE3 0x6F
36
37#define SP5100_PM_WATCHDOG_FIRED (1 << 1)
38#define SP5100_PM_WATCHDOG_ACTION_RESET (1 << 2)
39
40#define SP5100_PM_WATCHDOG_DISABLE 1
41#define SP5100_PM_WATCHDOG_SECOND_RES (3 << 1)
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 9127eda2145b..0d80e08b6439 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -90,7 +90,7 @@ static void wdt_setload(unsigned int timeout)
90 /* 90 /*
91 * sp805 runs counter with given value twice, after the end of first 91 * sp805 runs counter with given value twice, after the end of first
92 * counter it gives an interrupt and then starts counter again. If 92 * counter it gives an interrupt and then starts counter again. If
93 * interrupt already occured then it resets the system. This is why 93 * interrupt already occurred then it resets the system. This is why
94 * load is half of what should be required. 94 * load is half of what should be required.
95 */ 95 */
96 load = div_u64(rate, 2) * timeout - 1; 96 load = div_u64(rate, 2) * timeout - 1;
@@ -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/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index 0f5288df0091..e5c91d4404ed 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -42,7 +42,7 @@
42 42
43#include <asm/system.h> 43#include <asm/system.h>
44 44
45#define WATCHDOG_NAME "w83627hf/thf/hg WDT" 45#define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
46#define PFX WATCHDOG_NAME ": " 46#define PFX WATCHDOG_NAME ": "
47#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ 47#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
48 48
@@ -89,7 +89,7 @@ static void w83627hf_select_wd_register(void)
89 c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ 89 c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
90 outb_p(0x2b, WDT_EFER); 90 outb_p(0x2b, WDT_EFER);
91 outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ 91 outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */
92 } else if (c == 0x88) { /* W83627EHF */ 92 } else if (c == 0x88 || c == 0xa0) { /* W83627EHF / W83627DHG */
93 outb_p(0x2d, WDT_EFER); /* select GPIO5 */ 93 outb_p(0x2d, WDT_EFER); /* select GPIO5 */
94 c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ 94 c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */
95 outb_p(0x2d, WDT_EFER); 95 outb_p(0x2d, WDT_EFER);
@@ -129,6 +129,8 @@ static void w83627hf_init(void)
129 t = inb_p(WDT_EFDR); /* read CRF5 */ 129 t = inb_p(WDT_EFDR); /* read CRF5 */
130 t &= ~0x0C; /* set second mode & disable keyboard 130 t &= ~0x0C; /* set second mode & disable keyboard
131 turning off watchdog */ 131 turning off watchdog */
132 t |= 0x02; /* enable the WDTO# output low pulse
133 to the KBRST# pin (PIN60) */
132 outb_p(t, WDT_EFDR); /* Write back to CRF5 */ 134 outb_p(t, WDT_EFDR); /* Write back to CRF5 */
133 135
134 outb_p(0xF7, WDT_EFER); /* Select CRF7 */ 136 outb_p(0xF7, WDT_EFER); /* Select CRF7 */
@@ -321,7 +323,7 @@ static int __init wdt_init(void)
321{ 323{
322 int ret; 324 int ret;
323 325
324 printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); 326 printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising.\n");
325 327
326 if (wdt_set_heartbeat(timeout)) { 328 if (wdt_set_heartbeat(timeout)) {
327 wdt_set_heartbeat(WATCHDOG_TIMEOUT); 329 wdt_set_heartbeat(WATCHDOG_TIMEOUT);
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/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index 8c4b2d5bb7da..871caea4e1c6 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -320,6 +320,11 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
320 struct wm831x_watchdog_pdata *pdata; 320 struct wm831x_watchdog_pdata *pdata;
321 int reg, ret; 321 int reg, ret;
322 322
323 if (wm831x) {
324 dev_err(&pdev->dev, "wm831x watchdog already registered\n");
325 return -EBUSY;
326 }
327
323 wm831x = dev_get_drvdata(pdev->dev.parent); 328 wm831x = dev_get_drvdata(pdev->dev.parent);
324 329
325 ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG); 330 ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
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);