aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig183
-rw-r--r--drivers/watchdog/Makefile12
-rw-r--r--drivers/watchdog/alim1535_wdt.c2
-rw-r--r--drivers/watchdog/alim7101_wdt.c2
-rw-r--r--drivers/watchdog/ar7_wdt.c1
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c16
-rw-r--r--drivers/watchdog/ath79_wdt.c305
-rw-r--r--drivers/watchdog/bcm63xx_wdt.c332
-rw-r--r--drivers/watchdog/bfin_wdt.c19
-rw-r--r--drivers/watchdog/booke_wdt.c88
-rw-r--r--drivers/watchdog/cpwd.c26
-rw-r--r--drivers/watchdog/ep93xx_wdt.c1
-rw-r--r--drivers/watchdog/eurotechwdt.c1
-rw-r--r--drivers/watchdog/f71808e_wdt.c824
-rw-r--r--drivers/watchdog/gef_wdt.c5
-rw-r--r--drivers/watchdog/hpwdt.c317
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c11
-rw-r--r--drivers/watchdog/iTCO_wdt.c71
-rw-r--r--drivers/watchdog/imx2_wdt.c357
-rw-r--r--drivers/watchdog/it8712f_wdt.c25
-rw-r--r--drivers/watchdog/it87_wdt.c96
-rw-r--r--drivers/watchdog/ks8695_wdt.c2
-rw-r--r--drivers/watchdog/m548x_wdt.c227
-rw-r--r--drivers/watchdog/machzwd.c4
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c8
-rw-r--r--drivers/watchdog/nv_tco.c512
-rw-r--r--drivers/watchdog/nv_tco.h64
-rw-r--r--drivers/watchdog/octeon-wdt-main.c746
-rw-r--r--drivers/watchdog/octeon-wdt-nmi.S64
-rw-r--r--drivers/watchdog/omap_wdt.c43
-rw-r--r--drivers/watchdog/pc87413_wdt.c9
-rw-r--r--drivers/watchdog/pnx833x_wdt.c11
-rw-r--r--drivers/watchdog/rdc321x_wdt.c53
-rw-r--r--drivers/watchdog/riowd.c8
-rw-r--r--drivers/watchdog/s3c2410_wdt.c26
-rw-r--r--drivers/watchdog/sb_wdog.c12
-rw-r--r--drivers/watchdog/sch311x_wdt.c4
-rw-r--r--drivers/watchdog/shwdt.c2
-rw-r--r--drivers/watchdog/sp5100_tco.c480
-rw-r--r--drivers/watchdog/sp5100_tco.h41
-rw-r--r--drivers/watchdog/sp805_wdt.c387
-rw-r--r--drivers/watchdog/ts72xx_wdt.c3
-rw-r--r--drivers/watchdog/twl4030_wdt.c2
-rw-r--r--drivers/watchdog/w83627hf_wdt.c8
-rw-r--r--drivers/watchdog/wdt.c2
-rw-r--r--drivers/watchdog/wdt977.c2
-rw-r--r--drivers/watchdog/wdt_pci.c15
-rw-r--r--drivers/watchdog/wm8350_wdt.c2
48 files changed, 5037 insertions, 394 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8828d8ffd353..faa9127aecaa 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -73,6 +73,13 @@ config WM8350_WATCHDOG
73 73
74# ARM Architecture 74# ARM Architecture
75 75
76config ARM_SP805_WATCHDOG
77 tristate "ARM SP805 Watchdog"
78 depends on ARM_AMBA
79 help
80 ARM Primecell SP805 Watchdog timer. This will reboot your system when
81 the timeout is reached.
82
76config AT91RM9200_WATCHDOG 83config AT91RM9200_WATCHDOG
77 tristate "AT91RM9200 watchdog" 84 tristate "AT91RM9200 watchdog"
78 depends on ARCH_AT91RM9200 85 depends on ARCH_AT91RM9200
@@ -145,13 +152,19 @@ config KS8695_WATCHDOG
145 Watchdog timer embedded into KS8695 processor. This will reboot your 152 Watchdog timer embedded into KS8695 processor. This will reboot your
146 system when the timeout is reached. 153 system when the timeout is reached.
147 154
155config HAVE_S3C2410_WATCHDOG
156 bool
157 help
158 This will include watchdog timer support for Samsung SoCs. If
159 you want to include watchdog support for any machine, kindly
160 select this in the respective mach-XXXX/Kconfig file.
161
148config S3C2410_WATCHDOG 162config S3C2410_WATCHDOG
149 tristate "S3C2410 Watchdog" 163 tristate "S3C2410 Watchdog"
150 depends on ARCH_S3C2410 164 depends on ARCH_S3C2410 || HAVE_S3C2410_WATCHDOG
151 help 165 help
152 Watchdog timer block in the Samsung S3C2410 chips. This will 166 Watchdog timer block in the Samsung SoCs. This will reboot
153 reboot the system when the timer expires with the watchdog 167 the system when the timer expires with the watchdog enabled.
154 enabled.
155 168
156 The driver is limited by the speed of the system's PCLK 169 The driver is limited by the speed of the system's PCLK
157 signal, so with reasonably fast systems (PCLK around 50-66MHz) 170 signal, so with reasonably fast systems (PCLK around 50-66MHz)
@@ -200,11 +213,11 @@ config OMAP_WATCHDOG
200 here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. 213 here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer.
201 214
202config PNX4008_WATCHDOG 215config PNX4008_WATCHDOG
203 tristate "PNX4008 Watchdog" 216 tristate "PNX4008 and LPC32XX Watchdog"
204 depends on ARCH_PNX4008 217 depends on ARCH_PNX4008 || ARCH_LPC32XX
205 help 218 help
206 Say Y here if to include support for the watchdog timer 219 Say Y here if to include support for the watchdog timer
207 in the PNX4008 processor. 220 in the PNX4008 or LPC32XX processor.
208 This driver can be built as a module by choosing M. The module 221 This driver can be built as a module by choosing M. The module
209 will be called pnx4008_wdt. 222 will be called pnx4008_wdt.
210 223
@@ -306,6 +319,18 @@ config MAX63XX_WATCHDOG
306 help 319 help
307 Support for memory mapped max63{69,70,71,72,73,74} watchdog timer. 320 Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
308 321
322config IMX2_WDT
323 tristate "IMX2+ Watchdog"
324 depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX5
325 help
326 This is the driver for the hardware watchdog
327 on the Freescale IMX2 and later processors.
328 If you have one of these processors and wish to have
329 watchdog support enabled, say Y, otherwise say N.
330
331 To compile this driver as a module, choose M here: the
332 module will be called imx2_wdt.
333
309# AVR32 Architecture 334# AVR32 Architecture
310 335
311config AT32AP700X_WDT 336config AT32AP700X_WDT
@@ -383,6 +408,28 @@ config ALIM7101_WDT
383 408
384 Most people will say N. 409 Most people will say N.
385 410
411config F71808E_WDT
412 tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog"
413 depends on X86 && EXPERIMENTAL
414 help
415 This is the driver for the hardware watchdog on the Fintek
416 F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers.
417
418 You can compile this driver directly into the kernel, or use
419 it as a module. The module will be called f71808e_wdt.
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.
432
386config GEODE_WDT 433config GEODE_WDT
387 tristate "AMD Geode CS5535/CS5536 Watchdog" 434 tristate "AMD Geode CS5535/CS5536 Watchdog"
388 depends on CS5535_MFGPT 435 depends on CS5535_MFGPT
@@ -522,6 +569,9 @@ config IT8712F_WDT
522 This is the driver for the built-in watchdog timer on the IT8712F 569 This is the driver for the built-in watchdog timer on the IT8712F
523 Super I/0 chipset used on many motherboards. 570 Super I/0 chipset used on many motherboards.
524 571
572 If the driver does not work, then make sure that the game port in
573 the BIOS is enabled.
574
525 To compile this driver as a module, choose M here: the 575 To compile this driver as a module, choose M here: the
526 module will be called it8712f_wdt. 576 module will be called it8712f_wdt.
527 577
@@ -529,25 +579,31 @@ config IT87_WDT
529 tristate "IT87 Watchdog Timer" 579 tristate "IT87 Watchdog Timer"
530 depends on X86 && EXPERIMENTAL 580 depends on X86 && EXPERIMENTAL
531 ---help--- 581 ---help---
532 This is the driver for the hardware watchdog on the ITE IT8716, 582 This is the driver for the hardware watchdog on the ITE IT8702,
533 IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog 583 IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips.
534 simply watches your kernel to make sure it doesn't freeze, and if 584 This watchdog simply watches your kernel to make sure it doesn't
535 it does, it reboots your computer after a certain amount of time. 585 freeze, and if it does, it reboots your computer after a certain
586 amount of time.
536 587
537 To compile this driver as a module, choose M here: the module will 588 To compile this driver as a module, choose M here: the module will
538 be called it87_wdt. 589 be called it87_wdt.
539 590
540config HP_WATCHDOG 591config HP_WATCHDOG
541 tristate "HP Proliant iLO 2 Hardware Watchdog Timer" 592 tristate "HP Proliant iLO2+ Hardware Watchdog Timer"
542 depends on X86 593 depends on X86
543 help 594 help
544 A software monitoring watchdog and NMI sourcing driver. This driver 595 A software monitoring watchdog and NMI sourcing driver. This driver
545 will detect lockups and provide stack trace. Also, when an NMI 596 will detect lockups and provide a stack trace. This is a driver that
546 occurs this driver will make the necessary BIOS calls to log 597 will only load on a HP ProLiant system with a minimum of iLO2 support.
547 the cause of the NMI. This is a driver that will only load on a 598 To compile this driver as a module, choose M here: the module will be
548 HP ProLiant system with a minimum of iLO2 support. 599 called hpwdt.
549 To compile this driver as a module, choose M here: the 600
550 module will be called hpwdt. 601config HPWDT_NMI_DECODING
602 bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
603 depends on HP_WATCHDOG
604 help
605 When an NMI occurs this feature will make the necessary BIOS calls to
606 log the cause of the NMI.
551 607
552config SC1200_WDT 608config SC1200_WDT
553 tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" 609 tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
@@ -586,6 +642,24 @@ config PC87413_WDT
586 642
587 Most people will say N. 643 Most people will say N.
588 644
645config NV_TCO
646 tristate "nVidia TCO Timer/Watchdog"
647 depends on X86 && PCI
648 ---help---
649 Hardware driver for the TCO timer built into the nVidia Hub family
650 (such as the MCP51). The TCO (Total Cost of Ownership) timer is a
651 watchdog timer that will reboot the machine after its second
652 expiration. The expiration time can be configured with the
653 "heartbeat" parameter.
654
655 On some motherboards the driver may fail to reset the chipset's
656 NO_REBOOT flag which prevents the watchdog from rebooting the
657 machine. If this is the case you will get a kernel message like
658 "failed to reset NO_REBOOT flag, reboot disabled by hardware".
659
660 To compile this driver as a module, choose M here: the
661 module will be called nv_tco.
662
589config RDC321X_WDT 663config RDC321X_WDT
590 tristate "RDC R-321x SoC watchdog" 664 tristate "RDC R-321x SoC watchdog"
591 depends on X86_RDC321X 665 depends on X86_RDC321X
@@ -677,14 +751,15 @@ config SMSC37B787_WDT
677 Most people will say N. 751 Most people will say N.
678 752
679config W83627HF_WDT 753config W83627HF_WDT
680 tristate "W83627HF Watchdog Timer" 754 tristate "W83627HF/W83627DHG Watchdog Timer"
681 depends on X86 755 depends on X86
682 ---help--- 756 ---help---
683 This is the driver for the hardware watchdog on the W83627HF chipset 757 This is the driver for the hardware watchdog on the W83627HF chipset
684 as used in Advantech PC-9578 and Tyan S2721-533 motherboards 758 as used in Advantech PC-9578 and Tyan S2721-533 motherboards
685 (and likely others). This watchdog simply watches your kernel to 759 (and likely others). The driver also supports the W83627DHG chip.
686 make sure it doesn't freeze, and if it does, it reboots your computer 760 This watchdog simply watches your kernel to make sure it doesn't
687 after a certain amount of time. 761 freeze, and if it does, it reboots your computer after a certain
762 amount of time.
688 763
689 To compile this driver as a module, choose M here: the 764 To compile this driver as a module, choose M here: the
690 module will be called w83627hf_wdt. 765 module will be called w83627hf_wdt.
@@ -787,10 +862,22 @@ config SBC_EPX_C3_WATCHDOG
787 862
788# M68K Architecture 863# M68K Architecture
789 864
790# M68KNOMMU Architecture 865config M548x_WATCHDOG
866 tristate "MCF548x watchdog support"
867 depends on M548x
868 help
869 To compile this driver as a module, choose M here: the
870 module will be called m548x_wdt.
791 871
792# MIPS Architecture 872# MIPS Architecture
793 873
874config ATH79_WDT
875 tristate "Atheros AR71XX/AR724X/AR913X hardware watchdog"
876 depends on ATH79
877 help
878 Hardware driver for the built-in watchdog timer on the Atheros
879 AR71XX/AR724X/AR913X SoCs.
880
794config BCM47XX_WDT 881config BCM47XX_WDT
795 tristate "Broadcom BCM47xx Watchdog Timer" 882 tristate "Broadcom BCM47xx Watchdog Timer"
796 depends on BCM47XX 883 depends on BCM47XX
@@ -857,6 +944,34 @@ config TXX9_WDT
857 help 944 help
858 Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. 945 Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
859 946
947config OCTEON_WDT
948 tristate "Cavium OCTEON SOC family Watchdog Timer"
949 depends on CPU_CAVIUM_OCTEON
950 default y
951 select EXPORT_UASM if OCTEON_WDT = m
952 help
953 Hardware driver for OCTEON's on chip watchdog timer.
954 Enables the watchdog for all cores running Linux. It
955 installs a NMI handler and pokes the watchdog based on an
956 interrupt. On first expiration of the watchdog, the
957 interrupt handler pokes it. The second expiration causes an
958 NMI that prints a message. The third expiration causes a
959 global soft reset.
960
961 When userspace has /dev/watchdog open, no poking is done
962 from the first interrupt, it is then only poked when the
963 device is written.
964
965config BCM63XX_WDT
966 tristate "Broadcom BCM63xx hardware watchdog"
967 depends on BCM63XX
968 help
969 Watchdog driver for the built in watchdog hardware in Broadcom
970 BCM63xx SoC.
971
972 To compile this driver as a loadable module, choose M here.
973 The module will be called bcm63xx_wdt.
974
860# PARISC Architecture 975# PARISC Architecture
861 976
862# POWERPC Architecture 977# POWERPC Architecture
@@ -898,12 +1013,32 @@ config PIKA_WDT
898 the Warp platform. 1013 the Warp platform.
899 1014
900config BOOKE_WDT 1015config BOOKE_WDT
901 bool "PowerPC Book-E Watchdog Timer" 1016 tristate "PowerPC Book-E Watchdog Timer"
902 depends on BOOKE || 4xx 1017 depends on BOOKE || 4xx
903 ---help--- 1018 ---help---
1019 Watchdog driver for PowerPC Book-E chips, such as the Freescale
1020 MPC85xx SOCs and the IBM PowerPC 440.
1021
904 Please see Documentation/watchdog/watchdog-api.txt for 1022 Please see Documentation/watchdog/watchdog-api.txt for
905 more information. 1023 more information.
906 1024
1025config BOOKE_WDT_DEFAULT_TIMEOUT
1026 int "PowerPC Book-E Watchdog Timer Default Timeout"
1027 depends on BOOKE_WDT
1028 default 38 if FSL_BOOKE
1029 range 0 63 if FSL_BOOKE
1030 default 3 if !FSL_BOOKE
1031 range 0 3 if !FSL_BOOKE
1032 help
1033 Select the default watchdog timer period to be used by the PowerPC
1034 Book-E watchdog driver. A watchdog "event" occurs when the bit
1035 position represented by this number transitions from zero to one.
1036
1037 For Freescale Book-E processors, this is a number between 0 and 63.
1038 For other Book-E processors, this is a number between 0 and 3.
1039
1040 The value can be overidden by the wdt_period command-line parameter.
1041
907# PPC64 Architecture 1042# PPC64 Architecture
908 1043
909config WATCHDOG_RTAS 1044config WATCHDOG_RTAS
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 5e3cb95bb0e9..dd776651917c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
25# ALPHA Architecture 25# ALPHA Architecture
26 26
27# ARM Architecture 27# ARM Architecture
28obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
28obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o 29obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
29obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o 30obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
30obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o 31obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
47obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o 48obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
48obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o 49obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
49obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o 50obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
51obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
50 52
51# AVR32 Architecture 53# AVR32 Architecture
52obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o 54obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -65,6 +67,8 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
65obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o 67obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
66obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o 68obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
67obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o 69obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
70obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o
71obj-$(CONFIG_SP5100_TCO) += sp5100_tco.o
68obj-$(CONFIG_GEODE_WDT) += geodewdt.o 72obj-$(CONFIG_GEODE_WDT) += geodewdt.o
69obj-$(CONFIG_SC520_WDT) += sc520_wdt.o 73obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
70obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o 74obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o
@@ -83,6 +87,7 @@ obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o
83obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 87obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
84obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 88obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
85obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o 89obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o
90obj-$(CONFIG_NV_TCO) += nv_tco.o
86obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o 91obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o
87obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 92obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
88obj-$(CONFIG_SBC8360_WDT) += sbc8360.o 93obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
@@ -101,11 +106,12 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
101# M32R Architecture 106# M32R Architecture
102 107
103# M68K Architecture 108# M68K Architecture
104 109obj-$(CONFIG_M548x_WATCHDOG) += m548x_wdt.o
105# M68KNOMMU Architecture
106 110
107# MIPS Architecture 111# MIPS Architecture
112obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
108obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o 113obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
114obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
109obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 115obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
110obj-$(CONFIG_INDYDOG) += indydog.o 116obj-$(CONFIG_INDYDOG) += indydog.o
111obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 117obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
@@ -113,6 +119,8 @@ obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
113obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o 119obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
114obj-$(CONFIG_AR7_WDT) += ar7_wdt.o 120obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
115obj-$(CONFIG_TXX9_WDT) += txx9wdt.o 121obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
122obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
123octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
116 124
117# PARISC Architecture 125# PARISC Architecture
118 126
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index 1e9caea8ff8a..fa4d36033552 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 struct pci_device_id 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, },
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index d8d4da9a483d..4b7a2b4138ed 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 struct pci_device_id alim7101_pci_tbl[] __devinitdata __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 1cddf92cb9a6..750bc5281d79 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
346 } else { 346 } else {
347 wdt->users = 0; 347 wdt->users = 0;
348 } 348 }
349 wdt->miscdev.minor = WATCHDOG_MINOR; 349
350 wdt->miscdev.name = "watchdog"; 350 wdt->miscdev.minor = WATCHDOG_MINOR;
351 wdt->miscdev.fops = &at32_wdt_fops; 351 wdt->miscdev.name = "watchdog";
352 wdt->miscdev.fops = &at32_wdt_fops;
353 wdt->miscdev.parent = &pdev->dev;
354
355 platform_set_drvdata(pdev, wdt);
352 356
353 if (at32_wdt_settimeout(timeout)) { 357 if (at32_wdt_settimeout(timeout)) {
354 at32_wdt_settimeout(TIMEOUT_DEFAULT); 358 at32_wdt_settimeout(TIMEOUT_DEFAULT);
@@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev)
360 ret = misc_register(&wdt->miscdev); 364 ret = misc_register(&wdt->miscdev);
361 if (ret) { 365 if (ret) {
362 dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); 366 dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
363 goto err_iounmap; 367 goto err_register;
364 } 368 }
365 369
366 platform_set_drvdata(pdev, wdt);
367 wdt->miscdev.parent = &pdev->dev;
368 dev_info(&pdev->dev, 370 dev_info(&pdev->dev,
369 "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n", 371 "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
370 wdt->regs, wdt->timeout, nowayout); 372 wdt->regs, wdt->timeout, nowayout);
371 373
372 return 0; 374 return 0;
373 375
376err_register:
377 platform_set_drvdata(pdev, NULL);
374err_iounmap: 378err_iounmap:
375 iounmap(wdt->regs); 379 iounmap(wdt->regs);
376err_free: 380err_free:
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/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
new file mode 100644
index 000000000000..3c5045a206dd
--- /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, r->end - r->start);
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 9c7ccd1e9088..9042a95fc98c 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -23,6 +23,7 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <asm/blackfin.h> 25#include <asm/blackfin.h>
26#include <asm/bfin_watchdog.h>
26 27
27#define stamp(fmt, args...) \ 28#define stamp(fmt, args...) \
28 pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) 29 pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
@@ -49,24 +50,6 @@
49# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x) 50# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x)
50#endif 51#endif
51 52
52/* Bit in SWRST that indicates boot caused by watchdog */
53#define SWRST_RESET_WDOG 0x4000
54
55/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */
56#define WDOG_EXPIRED 0x8000
57
58/* Masks for WDEV field in WDOG_CTL register */
59#define ICTL_RESET 0x0
60#define ICTL_NMI 0x2
61#define ICTL_GPI 0x4
62#define ICTL_NONE 0x6
63#define ICTL_MASK 0x6
64
65/* Masks for WDEN field in WDOG_CTL register */
66#define WDEN_MASK 0x0FF0
67#define WDEN_ENABLE 0x0000
68#define WDEN_DISABLE 0x0AD0
69
70/* some defaults */ 53/* some defaults */
71#define WATCHDOG_TIMEOUT 20 54#define WATCHDOG_TIMEOUT 20
72 55
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 801ead191499..7e7ec9c35b6a 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 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{
@@ -137,12 +168,12 @@ static long booke_wdt_ioctl(struct file *file,
137 if (copy_to_user((void *)arg, &ident, sizeof(ident))) 168 if (copy_to_user((void *)arg, &ident, sizeof(ident)))
138 return -EFAULT; 169 return -EFAULT;
139 case WDIOC_GETSTATUS: 170 case WDIOC_GETSTATUS:
140 return put_user(ident.options, p); 171 return put_user(0, p);
141 case WDIOC_GETBOOTSTATUS: 172 case WDIOC_GETBOOTSTATUS:
142 /* XXX: something is clearing TSR */ 173 /* XXX: something is clearing TSR */
143 tmp = mfspr(SPRN_TSR) & TSR_WRS(3); 174 tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
144 /* returns 1 if last reset was caused by the WDT */ 175 /* returns CARDRESET if last reset was caused by the WDT */
145 return (tmp ? 1 : 0); 176 return (tmp ? WDIOF_CARDRESET : 0);
146 case WDIOC_SETOPTIONS: 177 case WDIOC_SETOPTIONS:
147 if (get_user(tmp, p)) 178 if (get_user(tmp, p))
148 return -EINVAL; 179 return -EINVAL;
@@ -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,8 +208,15 @@ 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;
@@ -193,12 +230,30 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
193 return nonseekable_open(inode, file); 230 return nonseekable_open(inode, file);
194} 231}
195 232
233static int booke_wdt_release(struct inode *inode, struct file *file)
234{
235#ifndef CONFIG_WATCHDOG_NOWAYOUT
236 /* Normally, the watchdog is disabled when /dev/watchdog is closed, but
237 * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the
238 * watchdog should remain enabled. So we disable it only if
239 * CONFIG_WATCHDOG_NOWAYOUT is not defined.
240 */
241 on_each_cpu(__booke_wdt_disable, NULL, 0);
242 booke_wdt_enabled = 0;
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 = {
@@ -237,4 +292,9 @@ static int __init booke_wdt_init(void)
237 292
238 return ret; 293 return ret;
239} 294}
240device_initcall(booke_wdt_init); 295
296module_init(booke_wdt_init);
297module_exit(booke_wdt_exit);
298
299MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
300MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index d62b9ce8f773..eca855a55c0d 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -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
@@ -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,9 +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 of_device *op, 531static int __devinit cpwd_probe(struct platform_device *op,
530 const struct of_device_id *match) 532 const struct of_device_id *match)
531{ 533{
532 struct device_node *options; 534 struct device_node *options;
@@ -545,7 +547,7 @@ static int __devinit cpwd_probe(struct of_device *op,
545 goto out; 547 goto out;
546 } 548 }
547 549
548 p->irq = op->irqs[0]; 550 p->irq = op->archdata.irqs[0];
549 551
550 spin_lock_init(&p->lock); 552 spin_lock_init(&p->lock);
551 553
@@ -639,7 +641,7 @@ out_free:
639 goto out; 641 goto out;
640} 642}
641 643
642static int __devexit cpwd_remove(struct of_device *op) 644static int __devexit cpwd_remove(struct platform_device *op)
643{ 645{
644 struct cpwd *p = dev_get_drvdata(&op->dev); 646 struct cpwd *p = dev_get_drvdata(&op->dev);
645 int i; 647 int i;
@@ -688,12 +690,12 @@ static struct of_platform_driver cpwd_driver = {
688 690
689static int __init cpwd_init(void) 691static int __init cpwd_init(void)
690{ 692{
691 return of_register_driver(&cpwd_driver, &of_bus_type); 693 return of_register_platform_driver(&cpwd_driver);
692} 694}
693 695
694static void __exit cpwd_exit(void) 696static void __exit cpwd_exit(void)
695{ 697{
696 of_unregister_driver(&cpwd_driver); 698 of_unregister_platform_driver(&cpwd_driver);
697} 699}
698 700
699module_init(cpwd_init); 701module_init(cpwd_init);
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 d1c4e55b1db0..3f3dc093ad68 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -68,7 +68,6 @@ static spinlock_t eurwdt_lock;
68 68
69/* 69/*
70 * You must set these - there is no sane way to probe for this board. 70 * You must set these - there is no sane way to probe for this board.
71 * You can use eurwdt=x,y to set these now.
72 */ 71 */
73 72
74static int io = 0x3f0; 73static int io = 0x3f0;
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
new file mode 100644
index 000000000000..d4d8d1fdccc4
--- /dev/null
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -0,0 +1,824 @@
1/***************************************************************************
2 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
3 * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> *
4 * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
21
22#include <linux/err.h>
23#include <linux/fs.h>
24#include <linux/init.h>
25#include <linux/io.h>
26#include <linux/ioport.h>
27#include <linux/miscdevice.h>
28#include <linux/module.h>
29#include <linux/mutex.h>
30#include <linux/notifier.h>
31#include <linux/reboot.h>
32#include <linux/uaccess.h>
33#include <linux/watchdog.h>
34
35#define DRVNAME "f71808e_wdt"
36
37#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */
38#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
39#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */
40
41#define SIO_REG_LDSEL 0x07 /* Logical device select */
42#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
43#define SIO_REG_DEVREV 0x22 /* Device revision */
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 */
49#define SIO_REG_ENABLE 0x30 /* Logical device enable */
50#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
51
52#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
53#define SIO_F71808_ID 0x0901 /* Chipset ID */
54#define SIO_F71858_ID 0x0507 /* Chipset ID */
55#define SIO_F71862_ID 0x0601 /* Chipset ID */
56#define SIO_F71869_ID 0x0814 /* Chipset ID */
57#define SIO_F71882_ID 0x0541 /* Chipset ID */
58#define SIO_F71889_ID 0x0723 /* Chipset ID */
59
60#define F71808FG_REG_WDO_CONF 0xf0
61#define F71808FG_REG_WDT_CONF 0xf5
62#define F71808FG_REG_WD_TIME 0xf6
63
64#define F71808FG_FLAG_WDOUT_EN 7
65
66#define F71808FG_FLAG_WDTMOUT_STS 5
67#define F71808FG_FLAG_WD_EN 5
68#define F71808FG_FLAG_WD_PULSE 4
69#define F71808FG_FLAG_WD_UNIT 3
70
71/* Default values */
72#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */
73#define WATCHDOG_MAX_TIMEOUT (60 * 255)
74#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for
75 watchdog signal */
76#define WATCHDOG_F71862FG_PIN 63 /* default watchdog reset output
77 pin number 63 */
78
79static unsigned short force_id;
80module_param(force_id, ushort, 0);
81MODULE_PARM_DESC(force_id, "Override the detected device ID");
82
83static const int max_timeout = WATCHDOG_MAX_TIMEOUT;
84static int timeout = WATCHDOG_TIMEOUT; /* default timeout in seconds */
85module_param(timeout, int, 0);
86MODULE_PARM_DESC(timeout,
87 "Watchdog timeout in seconds. 1<= timeout <="
88 __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default="
89 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
90
91static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH;
92module_param(pulse_width, uint, 0);
93MODULE_PARM_DESC(pulse_width,
94 "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms"
95 " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")");
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
103static int nowayout = WATCHDOG_NOWAYOUT;
104module_param(nowayout, bool, 0444);
105MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
106
107static unsigned int start_withtimeout;
108module_param(start_withtimeout, uint, 0);
109MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with"
110 " given initial timeout. Zero (default) disables this feature.");
111
112enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg };
113
114static const char *f71808e_names[] = {
115 "f71808fg",
116 "f71858fg",
117 "f71862fg",
118 "f71869",
119 "f71882fg",
120 "f71889fg",
121};
122
123/* Super-I/O Function prototypes */
124static inline int superio_inb(int base, int reg);
125static inline int superio_inw(int base, int reg);
126static inline void superio_outb(int base, int reg, u8 val);
127static inline void superio_set_bit(int base, int reg, int bit);
128static inline void superio_clear_bit(int base, int reg, int bit);
129static inline int superio_enter(int base);
130static inline void superio_select(int base, int ld);
131static inline void superio_exit(int base);
132
133struct watchdog_data {
134 unsigned short sioaddr;
135 enum chips type;
136 unsigned long opened;
137 struct mutex lock;
138 char expect_close;
139 struct watchdog_info ident;
140
141 unsigned short timeout;
142 u8 timer_val; /* content for the wd_time register */
143 char minutes_mode;
144 u8 pulse_val; /* pulse width flag */
145 char pulse_mode; /* enable pulse output mode? */
146 char caused_reboot; /* last reboot was by the watchdog */
147};
148
149static struct watchdog_data watchdog = {
150 .lock = __MUTEX_INITIALIZER(watchdog.lock),
151};
152
153/* Super I/O functions */
154static inline int superio_inb(int base, int reg)
155{
156 outb(reg, base);
157 return inb(base + 1);
158}
159
160static int superio_inw(int base, int reg)
161{
162 int val;
163 val = superio_inb(base, reg) << 8;
164 val |= superio_inb(base, reg + 1);
165 return val;
166}
167
168static inline void superio_outb(int base, int reg, u8 val)
169{
170 outb(reg, base);
171 outb(val, base + 1);
172}
173
174static inline void superio_set_bit(int base, int reg, int bit)
175{
176 unsigned long val = superio_inb(base, reg);
177 __set_bit(bit, &val);
178 superio_outb(base, reg, val);
179}
180
181static inline void superio_clear_bit(int base, int reg, int bit)
182{
183 unsigned long val = superio_inb(base, reg);
184 __clear_bit(bit, &val);
185 superio_outb(base, reg, val);
186}
187
188static inline int superio_enter(int base)
189{
190 /* Don't step on other drivers' I/O space by accident */
191 if (!request_muxed_region(base, 2, DRVNAME)) {
192 printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
193 (int)base);
194 return -EBUSY;
195 }
196
197 /* according to the datasheet the key must be send twice! */
198 outb(SIO_UNLOCK_KEY, base);
199 outb(SIO_UNLOCK_KEY, base);
200
201 return 0;
202}
203
204static inline void superio_select(int base, int ld)
205{
206 outb(SIO_REG_LDSEL, base);
207 outb(ld, base + 1);
208}
209
210static inline void superio_exit(int base)
211{
212 outb(SIO_LOCK_KEY, base);
213 release_region(base, 2);
214}
215
216static int watchdog_set_timeout(int timeout)
217{
218 if (timeout <= 0
219 || timeout > max_timeout) {
220 printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n");
221 return -EINVAL;
222 }
223
224 mutex_lock(&watchdog.lock);
225
226 watchdog.timeout = timeout;
227 if (timeout > 0xff) {
228 watchdog.timer_val = DIV_ROUND_UP(timeout, 60);
229 watchdog.minutes_mode = true;
230 } else {
231 watchdog.timer_val = timeout;
232 watchdog.minutes_mode = false;
233 }
234
235 mutex_unlock(&watchdog.lock);
236
237 return 0;
238}
239
240static int watchdog_set_pulse_width(unsigned int pw)
241{
242 int err = 0;
243
244 mutex_lock(&watchdog.lock);
245
246 if (pw <= 1) {
247 watchdog.pulse_val = 0;
248 } else if (pw <= 25) {
249 watchdog.pulse_val = 1;
250 } else if (pw <= 125) {
251 watchdog.pulse_val = 2;
252 } else if (pw <= 5000) {
253 watchdog.pulse_val = 3;
254 } else {
255 printk(KERN_ERR DRVNAME ": pulse width out of range\n");
256 err = -EINVAL;
257 goto exit_unlock;
258 }
259
260 watchdog.pulse_mode = pw;
261
262exit_unlock:
263 mutex_unlock(&watchdog.lock);
264 return err;
265}
266
267static int watchdog_keepalive(void)
268{
269 int err = 0;
270
271 mutex_lock(&watchdog.lock);
272 err = superio_enter(watchdog.sioaddr);
273 if (err)
274 goto exit_unlock;
275 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
276
277 if (watchdog.minutes_mode)
278 /* select minutes for timer units */
279 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
280 F71808FG_FLAG_WD_UNIT);
281 else
282 /* select seconds for timer units */
283 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
284 F71808FG_FLAG_WD_UNIT);
285
286 /* Set timer value */
287 superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME,
288 watchdog.timer_val);
289
290 superio_exit(watchdog.sioaddr);
291
292exit_unlock:
293 mutex_unlock(&watchdog.lock);
294 return err;
295}
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
319static int watchdog_start(void)
320{
321 /* Make sure we don't die as soon as the watchdog is enabled below */
322 int err = watchdog_keepalive();
323 if (err)
324 return err;
325
326 mutex_lock(&watchdog.lock);
327 err = superio_enter(watchdog.sioaddr);
328 if (err)
329 goto exit_unlock;
330 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
331
332 /* Watchdog pin configuration */
333 switch (watchdog.type) {
334 case f71808fg:
335 /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */
336 superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT2, 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);
349 break;
350
351 case f71882fg:
352 /* Set pin 56 to WDTRST# */
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);
360 break;
361
362 default:
363 /*
364 * 'default' label to shut up the compiler and catch
365 * programmer errors
366 */
367 err = -ENODEV;
368 goto exit_superio;
369 }
370
371 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
372 superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0);
373 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF,
374 F71808FG_FLAG_WDOUT_EN);
375
376 superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
377 F71808FG_FLAG_WD_EN);
378
379 if (watchdog.pulse_mode) {
380 /* Select "pulse" output mode with given duration */
381 u8 wdt_conf = superio_inb(watchdog.sioaddr,
382 F71808FG_REG_WDT_CONF);
383
384 /* Set WD_PSWIDTH bits (1:0) */
385 wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03);
386 /* Set WD_PULSE to "pulse" mode */
387 wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE);
388
389 superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
390 wdt_conf);
391 } else {
392 /* Select "level" output mode */
393 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
394 F71808FG_FLAG_WD_PULSE);
395 }
396
397exit_superio:
398 superio_exit(watchdog.sioaddr);
399exit_unlock:
400 mutex_unlock(&watchdog.lock);
401
402 return err;
403}
404
405static int watchdog_stop(void)
406{
407 int err = 0;
408
409 mutex_lock(&watchdog.lock);
410 err = superio_enter(watchdog.sioaddr);
411 if (err)
412 goto exit_unlock;
413 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
414
415 superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF,
416 F71808FG_FLAG_WD_EN);
417
418 superio_exit(watchdog.sioaddr);
419
420exit_unlock:
421 mutex_unlock(&watchdog.lock);
422
423 return err;
424}
425
426static int watchdog_get_status(void)
427{
428 int status = 0;
429
430 mutex_lock(&watchdog.lock);
431 status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0;
432 mutex_unlock(&watchdog.lock);
433
434 return status;
435}
436
437static bool watchdog_is_running(void)
438{
439 /*
440 * if we fail to determine the watchdog's status assume it to be
441 * running to be on the safe side
442 */
443 bool is_running = true;
444
445 mutex_lock(&watchdog.lock);
446 if (superio_enter(watchdog.sioaddr))
447 goto exit_unlock;
448 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
449
450 is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0))
451 && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF)
452 & F71808FG_FLAG_WD_EN);
453
454 superio_exit(watchdog.sioaddr);
455
456exit_unlock:
457 mutex_unlock(&watchdog.lock);
458 return is_running;
459}
460
461/* /dev/watchdog api */
462
463static int watchdog_open(struct inode *inode, struct file *file)
464{
465 int err;
466
467 /* If the watchdog is alive we don't need to start it again */
468 if (test_and_set_bit(0, &watchdog.opened))
469 return -EBUSY;
470
471 err = watchdog_start();
472 if (err) {
473 clear_bit(0, &watchdog.opened);
474 return err;
475 }
476
477 if (nowayout)
478 __module_get(THIS_MODULE);
479
480 watchdog.expect_close = 0;
481 return nonseekable_open(inode, file);
482}
483
484static int watchdog_release(struct inode *inode, struct file *file)
485{
486 clear_bit(0, &watchdog.opened);
487
488 if (!watchdog.expect_close) {
489 watchdog_keepalive();
490 printk(KERN_CRIT DRVNAME
491 ": Unexpected close, not stopping watchdog!\n");
492 } else if (!nowayout) {
493 watchdog_stop();
494 }
495 return 0;
496}
497
498/*
499 * watchdog_write:
500 * @file: file handle to the watchdog
501 * @buf: buffer to write
502 * @count: count of bytes
503 * @ppos: pointer to the position to write. No seeks allowed
504 *
505 * A write to a watchdog device is defined as a keepalive signal. Any
506 * write of data will do, as we we don't define content meaning.
507 */
508
509static ssize_t watchdog_write(struct file *file, const char __user *buf,
510 size_t count, loff_t *ppos)
511{
512 if (count) {
513 if (!nowayout) {
514 size_t i;
515
516 /* In case it was set long ago */
517 bool expect_close = false;
518
519 for (i = 0; i != count; i++) {
520 char c;
521 if (get_user(c, buf + i))
522 return -EFAULT;
523 expect_close = (c == 'V');
524 }
525
526 /* Properly order writes across fork()ed processes */
527 mutex_lock(&watchdog.lock);
528 watchdog.expect_close = expect_close;
529 mutex_unlock(&watchdog.lock);
530 }
531
532 /* someone wrote to us, we should restart timer */
533 watchdog_keepalive();
534 }
535 return count;
536}
537
538/*
539 * watchdog_ioctl:
540 * @inode: inode of the device
541 * @file: file handle to the device
542 * @cmd: watchdog command
543 * @arg: argument pointer
544 *
545 * The watchdog API defines a common set of functions for all watchdogs
546 * according to their available features.
547 */
548static long watchdog_ioctl(struct file *file, unsigned int cmd,
549 unsigned long arg)
550{
551 int status;
552 int new_options;
553 int new_timeout;
554 union {
555 struct watchdog_info __user *ident;
556 int __user *i;
557 } uarg;
558
559 uarg.i = (int __user *)arg;
560
561 switch (cmd) {
562 case WDIOC_GETSUPPORT:
563 return copy_to_user(uarg.ident, &watchdog.ident,
564 sizeof(watchdog.ident)) ? -EFAULT : 0;
565
566 case WDIOC_GETSTATUS:
567 status = watchdog_get_status();
568 if (status < 0)
569 return status;
570 return put_user(status, uarg.i);
571
572 case WDIOC_GETBOOTSTATUS:
573 return put_user(0, uarg.i);
574
575 case WDIOC_SETOPTIONS:
576 if (get_user(new_options, uarg.i))
577 return -EFAULT;
578
579 if (new_options & WDIOS_DISABLECARD)
580 watchdog_stop();
581
582 if (new_options & WDIOS_ENABLECARD)
583 return watchdog_start();
584
585
586 case WDIOC_KEEPALIVE:
587 watchdog_keepalive();
588 return 0;
589
590 case WDIOC_SETTIMEOUT:
591 if (get_user(new_timeout, uarg.i))
592 return -EFAULT;
593
594 if (watchdog_set_timeout(new_timeout))
595 return -EINVAL;
596
597 watchdog_keepalive();
598 /* Fall */
599
600 case WDIOC_GETTIMEOUT:
601 return put_user(watchdog.timeout, uarg.i);
602
603 default:
604 return -ENOTTY;
605
606 }
607}
608
609static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
610 void *unused)
611{
612 if (code == SYS_DOWN || code == SYS_HALT)
613 watchdog_stop();
614 return NOTIFY_DONE;
615}
616
617static const struct file_operations watchdog_fops = {
618 .owner = THIS_MODULE,
619 .llseek = no_llseek,
620 .open = watchdog_open,
621 .release = watchdog_release,
622 .write = watchdog_write,
623 .unlocked_ioctl = watchdog_ioctl,
624};
625
626static struct miscdevice watchdog_miscdev = {
627 .minor = WATCHDOG_MINOR,
628 .name = "watchdog",
629 .fops = &watchdog_fops,
630};
631
632static struct notifier_block watchdog_notifier = {
633 .notifier_call = watchdog_notify_sys,
634};
635
636static int __init watchdog_init(int sioaddr)
637{
638 int wdt_conf, err = 0;
639
640 /* No need to lock watchdog.lock here because no entry points
641 * into the module have been registered yet.
642 */
643 watchdog.sioaddr = sioaddr;
644 watchdog.ident.options = WDIOC_SETTIMEOUT
645 | WDIOF_MAGICCLOSE
646 | WDIOF_KEEPALIVEPING;
647
648 snprintf(watchdog.ident.identity,
649 sizeof(watchdog.ident.identity), "%s watchdog",
650 f71808e_names[watchdog.type]);
651
652 err = superio_enter(sioaddr);
653 if (err)
654 return err;
655 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
656
657 wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF);
658 watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS;
659
660 superio_exit(sioaddr);
661
662 err = watchdog_set_timeout(timeout);
663 if (err)
664 return err;
665 err = watchdog_set_pulse_width(pulse_width);
666 if (err)
667 return err;
668
669 err = register_reboot_notifier(&watchdog_notifier);
670 if (err)
671 return err;
672
673 err = misc_register(&watchdog_miscdev);
674 if (err) {
675 printk(KERN_ERR DRVNAME
676 ": cannot register miscdev on minor=%d\n",
677 watchdog_miscdev.minor);
678 goto exit_reboot;
679 }
680
681 if (start_withtimeout) {
682 if (start_withtimeout <= 0
683 || start_withtimeout > max_timeout) {
684 printk(KERN_ERR DRVNAME
685 ": starting timeout out of range\n");
686 err = -EINVAL;
687 goto exit_miscdev;
688 }
689
690 err = watchdog_start();
691 if (err) {
692 printk(KERN_ERR DRVNAME
693 ": cannot start watchdog timer\n");
694 goto exit_miscdev;
695 }
696
697 mutex_lock(&watchdog.lock);
698 err = superio_enter(sioaddr);
699 if (err)
700 goto exit_unlock;
701 superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
702
703 if (start_withtimeout > 0xff) {
704 /* select minutes for timer units */
705 superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF,
706 F71808FG_FLAG_WD_UNIT);
707 superio_outb(sioaddr, F71808FG_REG_WD_TIME,
708 DIV_ROUND_UP(start_withtimeout, 60));
709 } else {
710 /* select seconds for timer units */
711 superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF,
712 F71808FG_FLAG_WD_UNIT);
713 superio_outb(sioaddr, F71808FG_REG_WD_TIME,
714 start_withtimeout);
715 }
716
717 superio_exit(sioaddr);
718 mutex_unlock(&watchdog.lock);
719
720 if (nowayout)
721 __module_get(THIS_MODULE);
722
723 printk(KERN_INFO DRVNAME
724 ": watchdog started with initial timeout of %u sec\n",
725 start_withtimeout);
726 }
727
728 return 0;
729
730exit_unlock:
731 mutex_unlock(&watchdog.lock);
732exit_miscdev:
733 misc_deregister(&watchdog_miscdev);
734exit_reboot:
735 unregister_reboot_notifier(&watchdog_notifier);
736
737 return err;
738}
739
740static int __init f71808e_find(int sioaddr)
741{
742 u16 devid;
743 int err = superio_enter(sioaddr);
744 if (err)
745 return err;
746
747 devid = superio_inw(sioaddr, SIO_REG_MANID);
748 if (devid != SIO_FINTEK_ID) {
749 pr_debug(DRVNAME ": Not a Fintek device\n");
750 err = -ENODEV;
751 goto exit;
752 }
753
754 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
755 switch (devid) {
756 case SIO_F71808_ID:
757 watchdog.type = f71808fg;
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;
766 case SIO_F71882_ID:
767 watchdog.type = f71882fg;
768 break;
769 case SIO_F71889_ID:
770 watchdog.type = f71889fg;
771 break;
772 case SIO_F71858_ID:
773 /* Confirmed (by datasheet) not to have a watchdog. */
774 err = -ENODEV;
775 goto exit;
776 default:
777 printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n",
778 (unsigned int)devid);
779 err = -ENODEV;
780 goto exit;
781 }
782
783 printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n",
784 f71808e_names[watchdog.type],
785 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
786exit:
787 superio_exit(sioaddr);
788 return err;
789}
790
791static int __init f71808e_init(void)
792{
793 static const unsigned short addrs[] = { 0x2e, 0x4e };
794 int err = -ENODEV;
795 int i;
796
797 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
798 err = f71808e_find(addrs[i]);
799 if (err == 0)
800 break;
801 }
802 if (i == ARRAY_SIZE(addrs))
803 return err;
804
805 return watchdog_init(addrs[i]);
806}
807
808static void __exit f71808e_exit(void)
809{
810 if (watchdog_is_running()) {
811 printk(KERN_WARNING DRVNAME
812 ": Watchdog timer still running, stopping it\n");
813 watchdog_stop();
814 }
815 misc_deregister(&watchdog_miscdev);
816 unregister_reboot_notifier(&watchdog_notifier);
817}
818
819MODULE_DESCRIPTION("F71808E Watchdog Driver");
820MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>");
821MODULE_LICENSE("GPL");
822
823module_init(f71808e_init);
824module_exit(f71808e_exit);
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index ca0f4c6cf5ab..f6bd6f10fcec 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,7 +261,7 @@ static struct miscdevice gef_wdt_miscdev = {
260}; 261};
261 262
262 263
263static int __devinit gef_wdt_probe(struct of_device *dev, 264static int __devinit gef_wdt_probe(struct platform_device *dev,
264 const struct of_device_id *match) 265 const struct of_device_id *match)
265{ 266{
266 int timeout = 10; 267 int timeout = 10;
@@ -273,7 +274,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev,
273 bus_clk = freq; 274 bus_clk = freq;
274 275
275 /* Map devices registers into memory */ 276 /* Map devices registers into memory */
276 gef_wdt_regs = of_iomap(dev->node, 0); 277 gef_wdt_regs = of_iomap(dev->dev.of_node, 0);
277 if (gef_wdt_regs == NULL) 278 if (gef_wdt_regs == NULL)
278 return -ENOMEM; 279 return -ENOMEM;
279 280
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 809e7167a624..24b966d5061a 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -16,38 +16,55 @@
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/io.h> 19#include <linux/io.h>
21#include <linux/irq.h> 20#include <linux/bitops.h>
22#include <linux/nmi.h>
23#include <linux/kernel.h> 21#include <linux/kernel.h>
24#include <linux/miscdevice.h> 22#include <linux/miscdevice.h>
25#include <linux/mm.h>
26#include <linux/module.h> 23#include <linux/module.h>
27#include <linux/kdebug.h>
28#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
29#include <linux/notifier.h>
30#include <linux/pci.h> 25#include <linux/pci.h>
31#include <linux/pci_ids.h> 26#include <linux/pci_ids.h>
32#include <linux/reboot.h>
33#include <linux/sched.h>
34#include <linux/timer.h>
35#include <linux/types.h> 27#include <linux/types.h>
36#include <linux/uaccess.h> 28#include <linux/uaccess.h>
37#include <linux/watchdog.h> 29#include <linux/watchdog.h>
30#ifdef CONFIG_HPWDT_NMI_DECODING
38#include <linux/dmi.h> 31#include <linux/dmi.h>
39#include <linux/efi.h> 32#include <linux/spinlock.h>
40#include <linux/string.h> 33#include <linux/nmi.h>
41#include <linux/bootmem.h> 34#include <linux/kdebug.h>
42#include <asm/desc.h> 35#include <linux/notifier.h>
43#include <asm/cacheflush.h> 36#include <asm/cacheflush.h>
37#endif /* CONFIG_HPWDT_NMI_DECODING */
38
39#define HPWDT_VERSION "1.2.0"
40#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
41#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
42#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
43#define DEFAULT_MARGIN 30
44
45static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */
46static unsigned int reload; /* the computed soft_margin */
47static int nowayout = WATCHDOG_NOWAYOUT;
48static char expect_release;
49static unsigned long hpwdt_is_open;
50
51static void __iomem *pci_mem_addr; /* the PCI-memory address */
52static unsigned long __iomem *hpwdt_timer_reg;
53static unsigned long __iomem *hpwdt_timer_con;
54
55static struct pci_device_id hpwdt_devices[] = {
56 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */
57 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */
58 {0}, /* terminate list */
59};
60MODULE_DEVICE_TABLE(pci, hpwdt_devices);
44 61
62#ifdef CONFIG_HPWDT_NMI_DECODING
45#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ 63#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */
46#define CRU_BIOS_SIGNATURE_VALUE 0x55524324 64#define CRU_BIOS_SIGNATURE_VALUE 0x55524324
47#define PCI_BIOS32_PARAGRAPH_LEN 16 65#define PCI_BIOS32_PARAGRAPH_LEN 16
48#define PCI_ROM_BASE1 0x000F0000 66#define PCI_ROM_BASE1 0x000F0000
49#define ROM_SIZE 0x10000 67#define ROM_SIZE 0x10000
50#define HPWDT_VERSION "1.1.1"
51 68
52struct bios32_service_dir { 69struct bios32_service_dir {
53 u32 signature; 70 u32 signature;
@@ -112,37 +129,17 @@ struct cmn_registers {
112 u32 reflags; 129 u32 reflags;
113} __attribute__((packed)); 130} __attribute__((packed));
114 131
115#define DEFAULT_MARGIN 30 132static unsigned int hpwdt_nmi_decoding;
116static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */
117static unsigned int reload; /* the computed soft_margin */
118static int nowayout = WATCHDOG_NOWAYOUT;
119static char expect_release;
120static unsigned long hpwdt_is_open;
121static unsigned int allow_kdump; 133static unsigned int allow_kdump;
122static unsigned int hpwdt_nmi_sourcing;
123static unsigned int priority; /* hpwdt at end of die_notify list */ 134static unsigned int priority; /* hpwdt at end of die_notify list */
124
125static void __iomem *pci_mem_addr; /* the PCI-memory address */
126static unsigned long __iomem *hpwdt_timer_reg;
127static unsigned long __iomem *hpwdt_timer_con;
128
129static DEFINE_SPINLOCK(rom_lock); 135static DEFINE_SPINLOCK(rom_lock);
130
131static void *cru_rom_addr; 136static void *cru_rom_addr;
132
133static struct cmn_registers cmn_regs; 137static struct cmn_registers cmn_regs;
134 138
135static struct pci_device_id hpwdt_devices[] = {
136 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },
137 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },
138 {0}, /* terminate list */
139};
140MODULE_DEVICE_TABLE(pci, hpwdt_devices);
141
142extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs, 139extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
143 unsigned long *pRomEntry); 140 unsigned long *pRomEntry);
144 141
145#ifndef CONFIG_X86_64 142#ifdef CONFIG_X86_32
146/* --32 Bit Bios------------------------------------------------------------ */ 143/* --32 Bit Bios------------------------------------------------------------ */
147 144
148#define HPWDT_ARCH 32 145#define HPWDT_ARCH 32
@@ -246,8 +243,8 @@ static int __devinit cru_detect(unsigned long map_entry,
246 physical_bios_offset); 243 physical_bios_offset);
247 printk(KERN_DEBUG "hpwdt: CRU Length: 0x%lx\n", 244 printk(KERN_DEBUG "hpwdt: CRU Length: 0x%lx\n",
248 cru_length); 245 cru_length);
249 printk(KERN_DEBUG "hpwdt: CRU Mapped Address: 0x%x\n", 246 printk(KERN_DEBUG "hpwdt: CRU Mapped Address: %p\n",
250 (unsigned int)&cru_rom_addr); 247 &cru_rom_addr);
251 } 248 }
252 iounmap(bios32_map); 249 iounmap(bios32_map);
253 return retval; 250 return retval;
@@ -331,8 +328,9 @@ static int __devinit detect_cru_service(void)
331 iounmap(p); 328 iounmap(p);
332 return rc; 329 return rc;
333} 330}
334 331/* ------------------------------------------------------------------------- */
335#else 332#endif /* CONFIG_X86_32 */
333#ifdef CONFIG_X86_64
336/* --64 Bit Bios------------------------------------------------------------ */ 334/* --64 Bit Bios------------------------------------------------------------ */
337 335
338#define HPWDT_ARCH 64 336#define HPWDT_ARCH 64
@@ -410,17 +408,16 @@ static int __devinit detect_cru_service(void)
410 /* if cru_rom_addr has been set then we found a CRU service */ 408 /* if cru_rom_addr has been set then we found a CRU service */
411 return ((cru_rom_addr != NULL) ? 0 : -ENODEV); 409 return ((cru_rom_addr != NULL) ? 0 : -ENODEV);
412} 410}
413
414/* ------------------------------------------------------------------------- */ 411/* ------------------------------------------------------------------------- */
415 412#endif /* CONFIG_X86_64 */
416#endif 413#endif /* CONFIG_HPWDT_NMI_DECODING */
417 414
418/* 415/*
419 * Watchdog operations 416 * Watchdog operations
420 */ 417 */
421static void hpwdt_start(void) 418static void hpwdt_start(void)
422{ 419{
423 reload = (soft_margin * 1000) / 128; 420 reload = SECS_TO_TICKS(soft_margin);
424 iowrite16(reload, hpwdt_timer_reg); 421 iowrite16(reload, hpwdt_timer_reg);
425 iowrite16(0x85, hpwdt_timer_con); 422 iowrite16(0x85, hpwdt_timer_con);
426} 423}
@@ -441,8 +438,7 @@ static void hpwdt_ping(void)
441 438
442static int hpwdt_change_timer(int new_margin) 439static int hpwdt_change_timer(int new_margin)
443{ 440{
444 /* Arbitrary, can't find the card's limits */ 441 if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) {
445 if (new_margin < 5 || new_margin > 600) {
446 printk(KERN_WARNING 442 printk(KERN_WARNING
447 "hpwdt: New value passed in is invalid: %d seconds.\n", 443 "hpwdt: New value passed in is invalid: %d seconds.\n",
448 new_margin); 444 new_margin);
@@ -453,11 +449,17 @@ static int hpwdt_change_timer(int new_margin)
453 printk(KERN_DEBUG 449 printk(KERN_DEBUG
454 "hpwdt: New timer passed in is %d seconds.\n", 450 "hpwdt: New timer passed in is %d seconds.\n",
455 new_margin); 451 new_margin);
456 reload = (soft_margin * 1000) / 128; 452 reload = SECS_TO_TICKS(soft_margin);
457 453
458 return 0; 454 return 0;
459} 455}
460 456
457static int hpwdt_time_left(void)
458{
459 return TICKS_TO_SECS(ioread16(hpwdt_timer_reg));
460}
461
462#ifdef CONFIG_HPWDT_NMI_DECODING
461/* 463/*
462 * NMI Handler 464 * NMI Handler
463 */ 465 */
@@ -467,27 +469,30 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
467 unsigned long rom_pl; 469 unsigned long rom_pl;
468 static int die_nmi_called; 470 static int die_nmi_called;
469 471
470 if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 472 if (ulReason != DIE_NMIUNKNOWN)
471 return NOTIFY_OK; 473 goto out;
472 474
473 if (hpwdt_nmi_sourcing) { 475 if (!hpwdt_nmi_decoding)
474 spin_lock_irqsave(&rom_lock, rom_pl); 476 goto out;
475 if (!die_nmi_called) 477
476 asminline_call(&cmn_regs, cru_rom_addr); 478 spin_lock_irqsave(&rom_lock, rom_pl);
477 die_nmi_called = 1; 479 if (!die_nmi_called)
478 spin_unlock_irqrestore(&rom_lock, rom_pl); 480 asminline_call(&cmn_regs, cru_rom_addr);
479 if (cmn_regs.u1.ral == 0) { 481 die_nmi_called = 1;
480 printk(KERN_WARNING "hpwdt: An NMI occurred, " 482 spin_unlock_irqrestore(&rom_lock, rom_pl);
481 "but unable to determine source.\n"); 483 if (cmn_regs.u1.ral == 0) {
482 } else { 484 printk(KERN_WARNING "hpwdt: An NMI occurred, "
483 if (allow_kdump) 485 "but unable to determine source.\n");
484 hpwdt_stop(); 486 } else {
485 panic("An NMI occurred, please see the Integrated " 487 if (allow_kdump)
486 "Management Log for details.\n"); 488 hpwdt_stop();
487 } 489 panic("An NMI occurred, please see the Integrated "
490 "Management Log for details.\n");
488 } 491 }
492out:
489 return NOTIFY_OK; 493 return NOTIFY_OK;
490} 494}
495#endif /* CONFIG_HPWDT_NMI_DECODING */
491 496
492/* 497/*
493 * /dev/watchdog handling 498 * /dev/watchdog handling
@@ -557,7 +562,7 @@ static const struct watchdog_info ident = {
557 .options = WDIOF_SETTIMEOUT | 562 .options = WDIOF_SETTIMEOUT |
558 WDIOF_KEEPALIVEPING | 563 WDIOF_KEEPALIVEPING |
559 WDIOF_MAGICCLOSE, 564 WDIOF_MAGICCLOSE,
560 .identity = "HP iLO2 HW Watchdog Timer", 565 .identity = "HP iLO2+ HW Watchdog Timer",
561}; 566};
562 567
563static long hpwdt_ioctl(struct file *file, unsigned int cmd, 568static long hpwdt_ioctl(struct file *file, unsigned int cmd,
@@ -599,6 +604,10 @@ static long hpwdt_ioctl(struct file *file, unsigned int cmd,
599 case WDIOC_GETTIMEOUT: 604 case WDIOC_GETTIMEOUT:
600 ret = put_user(soft_margin, p); 605 ret = put_user(soft_margin, p);
601 break; 606 break;
607
608 case WDIOC_GETTIMELEFT:
609 ret = put_user(hpwdt_time_left(), p);
610 break;
602 } 611 }
603 return ret; 612 return ret;
604} 613}
@@ -621,80 +630,40 @@ static struct miscdevice hpwdt_miscdev = {
621 .fops = &hpwdt_fops, 630 .fops = &hpwdt_fops,
622}; 631};
623 632
633#ifdef CONFIG_HPWDT_NMI_DECODING
624static struct notifier_block die_notifier = { 634static struct notifier_block die_notifier = {
625 .notifier_call = hpwdt_pretimeout, 635 .notifier_call = hpwdt_pretimeout,
626 .priority = 0, 636 .priority = 0,
627}; 637};
638#endif /* CONFIG_HPWDT_NMI_DECODING */
628 639
629/* 640/*
630 * Init & Exit 641 * Init & Exit
631 */ 642 */
632 643
633#ifdef ARCH_HAS_NMI_WATCHDOG 644#ifdef CONFIG_HPWDT_NMI_DECODING
634static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) 645#ifdef CONFIG_X86_LOCAL_APIC
646static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
635{ 647{
636 /* 648 /*
637 * If nmi_watchdog is turned off then we can turn on 649 * If nmi_watchdog is turned off then we can turn on
638 * our nmi sourcing capability. 650 * our nmi decoding capability.
639 */ 651 */
640 if (!nmi_watchdog_active()) 652 hpwdt_nmi_decoding = 1;
641 hpwdt_nmi_sourcing = 1;
642 else
643 dev_warn(&dev->dev, "NMI sourcing is disabled. To enable this "
644 "functionality you must reboot with nmi_watchdog=0 "
645 "and load the hpwdt driver with priority=1.\n");
646} 653}
647#else 654#else
648static void __devinit hpwdt_check_nmi_sourcing(struct pci_dev *dev) 655static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
649{ 656{
650 dev_warn(&dev->dev, "NMI sourcing is disabled. " 657 dev_warn(&dev->dev, "NMI decoding is disabled. "
651 "Your kernel does not support a NMI Watchdog.\n"); 658 "Your kernel does not support a NMI Watchdog.\n");
652} 659}
653#endif 660#endif /* CONFIG_X86_LOCAL_APIC */
654 661
655static int __devinit hpwdt_init_one(struct pci_dev *dev, 662static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
656 const struct pci_device_id *ent)
657{ 663{
658 int retval; 664 int retval;
659 665
660 /* 666 /*
661 * Check if we can do NMI sourcing or not
662 */
663 hpwdt_check_nmi_sourcing(dev);
664
665 /*
666 * First let's find out if we are on an iLO2 server. We will
667 * not run on a legacy ASM box.
668 * So we only support the G5 ProLiant servers and higher.
669 */
670 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
671 dev_warn(&dev->dev,
672 "This server does not have an iLO2 ASIC.\n");
673 return -ENODEV;
674 }
675
676 if (pci_enable_device(dev)) {
677 dev_warn(&dev->dev,
678 "Not possible to enable PCI Device: 0x%x:0x%x.\n",
679 ent->vendor, ent->device);
680 return -ENODEV;
681 }
682
683 pci_mem_addr = pci_iomap(dev, 1, 0x80);
684 if (!pci_mem_addr) {
685 dev_warn(&dev->dev,
686 "Unable to detect the iLO2 server memory.\n");
687 retval = -ENOMEM;
688 goto error_pci_iomap;
689 }
690 hpwdt_timer_reg = pci_mem_addr + 0x70;
691 hpwdt_timer_con = pci_mem_addr + 0x72;
692
693 /* Make sure that we have a valid soft_margin */
694 if (hpwdt_change_timer(soft_margin))
695 hpwdt_change_timer(DEFAULT_MARGIN);
696
697 /*
698 * We need to map the ROM to get the CRU service. 667 * We need to map the ROM to get the CRU service.
699 * For 32 bit Operating Systems we need to go through the 32 Bit 668 * For 32 bit Operating Systems we need to go through the 32 Bit
700 * BIOS Service Directory 669 * BIOS Service Directory
@@ -705,7 +674,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
705 dev_warn(&dev->dev, 674 dev_warn(&dev->dev,
706 "Unable to detect the %d Bit CRU Service.\n", 675 "Unable to detect the %d Bit CRU Service.\n",
707 HPWDT_ARCH); 676 HPWDT_ARCH);
708 goto error_get_cru; 677 return retval;
709 } 678 }
710 679
711 /* 680 /*
@@ -728,8 +697,86 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
728 dev_warn(&dev->dev, 697 dev_warn(&dev->dev,
729 "Unable to register a die notifier (err=%d).\n", 698 "Unable to register a die notifier (err=%d).\n",
730 retval); 699 retval);
731 goto error_die_notifier; 700 if (cru_rom_addr)
701 iounmap(cru_rom_addr);
702 }
703
704 dev_info(&dev->dev,
705 "HP Watchdog Timer Driver: NMI decoding initialized"
706 ", allow kernel dump: %s (default = 0/OFF)"
707 ", priority: %s (default = 0/LAST).\n",
708 (allow_kdump == 0) ? "OFF" : "ON",
709 (priority == 0) ? "LAST" : "FIRST");
710 return 0;
711}
712
713static void __devexit hpwdt_exit_nmi_decoding(void)
714{
715 unregister_die_notifier(&die_notifier);
716 if (cru_rom_addr)
717 iounmap(cru_rom_addr);
718}
719#else /* !CONFIG_HPWDT_NMI_DECODING */
720static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
721{
722}
723
724static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
725{
726 return 0;
727}
728
729static void __devexit hpwdt_exit_nmi_decoding(void)
730{
731}
732#endif /* CONFIG_HPWDT_NMI_DECODING */
733
734static int __devinit hpwdt_init_one(struct pci_dev *dev,
735 const struct pci_device_id *ent)
736{
737 int retval;
738
739 /*
740 * Check if we can do NMI decoding or not
741 */
742 hpwdt_check_nmi_decoding(dev);
743
744 /*
745 * First let's find out if we are on an iLO2+ server. We will
746 * not run on a legacy ASM box.
747 * So we only support the G5 ProLiant servers and higher.
748 */
749 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
750 dev_warn(&dev->dev,
751 "This server does not have an iLO2+ ASIC.\n");
752 return -ENODEV;
753 }
754
755 if (pci_enable_device(dev)) {
756 dev_warn(&dev->dev,
757 "Not possible to enable PCI Device: 0x%x:0x%x.\n",
758 ent->vendor, ent->device);
759 return -ENODEV;
760 }
761
762 pci_mem_addr = pci_iomap(dev, 1, 0x80);
763 if (!pci_mem_addr) {
764 dev_warn(&dev->dev,
765 "Unable to detect the iLO2+ server memory.\n");
766 retval = -ENOMEM;
767 goto error_pci_iomap;
732 } 768 }
769 hpwdt_timer_reg = pci_mem_addr + 0x70;
770 hpwdt_timer_con = pci_mem_addr + 0x72;
771
772 /* Make sure that we have a valid soft_margin */
773 if (hpwdt_change_timer(soft_margin))
774 hpwdt_change_timer(DEFAULT_MARGIN);
775
776 /* Initialize NMI Decoding functionality */
777 retval = hpwdt_init_nmi_decoding(dev);
778 if (retval != 0)
779 goto error_init_nmi_decoding;
733 780
734 retval = misc_register(&hpwdt_miscdev); 781 retval = misc_register(&hpwdt_miscdev);
735 if (retval < 0) { 782 if (retval < 0) {
@@ -739,23 +786,14 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
739 goto error_misc_register; 786 goto error_misc_register;
740 } 787 }
741 788
742 printk(KERN_INFO 789 dev_info(&dev->dev, "HP Watchdog Timer Driver: %s"
743 "hp Watchdog Timer Driver: %s" 790 ", timer margin: %d seconds (nowayout=%d).\n",
744 ", timer margin: %d seconds (nowayout=%d)" 791 HPWDT_VERSION, soft_margin, nowayout);
745 ", allow kernel dump: %s (default = 0/OFF)"
746 ", priority: %s (default = 0/LAST).\n",
747 HPWDT_VERSION, soft_margin, nowayout,
748 (allow_kdump == 0) ? "OFF" : "ON",
749 (priority == 0) ? "LAST" : "FIRST");
750
751 return 0; 792 return 0;
752 793
753error_misc_register: 794error_misc_register:
754 unregister_die_notifier(&die_notifier); 795 hpwdt_exit_nmi_decoding();
755error_die_notifier: 796error_init_nmi_decoding:
756 if (cru_rom_addr)
757 iounmap(cru_rom_addr);
758error_get_cru:
759 pci_iounmap(dev, pci_mem_addr); 797 pci_iounmap(dev, pci_mem_addr);
760error_pci_iomap: 798error_pci_iomap:
761 pci_disable_device(dev); 799 pci_disable_device(dev);
@@ -768,10 +806,7 @@ static void __devexit hpwdt_exit(struct pci_dev *dev)
768 hpwdt_stop(); 806 hpwdt_stop();
769 807
770 misc_deregister(&hpwdt_miscdev); 808 misc_deregister(&hpwdt_miscdev);
771 unregister_die_notifier(&die_notifier); 809 hpwdt_exit_nmi_decoding();
772
773 if (cru_rom_addr)
774 iounmap(cru_rom_addr);
775 pci_iounmap(dev, pci_mem_addr); 810 pci_iounmap(dev, pci_mem_addr);
776 pci_disable_device(dev); 811 pci_disable_device(dev);
777} 812}
@@ -802,16 +837,18 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
802module_param(soft_margin, int, 0); 837module_param(soft_margin, int, 0);
803MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); 838MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
804 839
805module_param(allow_kdump, int, 0);
806MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
807
808module_param(nowayout, int, 0); 840module_param(nowayout, int, 0);
809MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 841MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
810 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 842 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
811 843
844#ifdef CONFIG_HPWDT_NMI_DECODING
845module_param(allow_kdump, int, 0);
846MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs");
847
812module_param(priority, int, 0); 848module_param(priority, int, 0);
813MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last" 849MODULE_PARM_DESC(priority, "The hpwdt driver handles NMIs first or last"
814 " (default = 0/Last)\n"); 850 " (default = 0/Last)\n");
851#endif /* !CONFIG_HPWDT_NMI_DECODING */
815 852
816module_init(hpwdt_init); 853module_init(hpwdt_init);
817module_exit(hpwdt_cleanup); 854module_exit(hpwdt_cleanup);
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index 5133bca5ccbe..481d1ad43464 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -101,13 +101,6 @@ static void supermicro_old_pre_stop(unsigned long acpibase)
101 outl(val32, SMI_EN); /* Needed to deactivate watchdog */ 101 outl(val32, SMI_EN); /* Needed to deactivate watchdog */
102} 102}
103 103
104static void supermicro_old_pre_keepalive(unsigned long acpibase)
105{
106 /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
107 /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */
108 outb(0x08, TCO1_STS);
109}
110
111/* 104/*
112 * Vendor Support: 2 105 * Vendor Support: 2
113 * Board: Super Micro Computer Inc. P4SBx, P4DPx 106 * Board: Super Micro Computer Inc. P4SBx, P4DPx
@@ -337,9 +330,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_stop);
337 330
338void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) 331void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
339{ 332{
340 if (vendorsupport == SUPERMICRO_OLD_BOARD) 333 if (vendorsupport == SUPERMICRO_NEW_BOARD)
341 supermicro_old_pre_keepalive(acpibase);
342 else if (vendorsupport == SUPERMICRO_NEW_BOARD)
343 supermicro_new_pre_set_heartbeat(heartbeat); 334 supermicro_new_pre_set_heartbeat(heartbeat);
344} 335}
345EXPORT_SYMBOL(iTCO_vendor_pre_keepalive); 336EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 8da886035374..2c6c2b4ad8bf 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,15 @@
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
35 */ 38 */
36 39
37/* 40/*
@@ -40,7 +43,7 @@
40 43
41/* Module and version information */ 44/* Module and version information */
42#define DRV_NAME "iTCO_wdt" 45#define DRV_NAME "iTCO_wdt"
43#define DRV_VERSION "1.05" 46#define DRV_VERSION "1.06"
44#define PFX DRV_NAME ": " 47#define PFX DRV_NAME ": "
45 48
46/* Includes */ 49/* Includes */
@@ -84,6 +87,7 @@ enum iTCO_chipsets {
84 TCO_ICH7DH, /* ICH7DH */ 87 TCO_ICH7DH, /* ICH7DH */
85 TCO_ICH7M, /* ICH7-M & ICH7-U */ 88 TCO_ICH7M, /* ICH7-M & ICH7-U */
86 TCO_ICH7MDH, /* ICH7-M DH */ 89 TCO_ICH7MDH, /* ICH7-M DH */
90 TCO_NM10, /* NM10 */
87 TCO_ICH8, /* ICH8 & ICH8R */ 91 TCO_ICH8, /* ICH8 & ICH8R */
88 TCO_ICH8DH, /* ICH8DH */ 92 TCO_ICH8DH, /* ICH8DH */
89 TCO_ICH8DO, /* ICH8DO */ 93 TCO_ICH8DO, /* ICH8DO */
@@ -146,6 +150,9 @@ enum iTCO_chipsets {
146 TCO_CPT29, /* Cougar Point */ 150 TCO_CPT29, /* Cougar Point */
147 TCO_CPT30, /* Cougar Point */ 151 TCO_CPT30, /* Cougar Point */
148 TCO_CPT31, /* Cougar Point */ 152 TCO_CPT31, /* Cougar Point */
153 TCO_PBG1, /* Patsburg */
154 TCO_PBG2, /* Patsburg */
155 TCO_DH89XXCC, /* DH89xxCC */
149}; 156};
150 157
151static struct { 158static struct {
@@ -171,6 +178,7 @@ static struct {
171 {"ICH7DH", 2}, 178 {"ICH7DH", 2},
172 {"ICH7-M or ICH7-U", 2}, 179 {"ICH7-M or ICH7-U", 2},
173 {"ICH7-M DH", 2}, 180 {"ICH7-M DH", 2},
181 {"NM10", 2},
174 {"ICH8 or ICH8R", 2}, 182 {"ICH8 or ICH8R", 2},
175 {"ICH8DH", 2}, 183 {"ICH8DH", 2},
176 {"ICH8DO", 2}, 184 {"ICH8DO", 2},
@@ -233,6 +241,9 @@ static struct {
233 {"Cougar Point", 2}, 241 {"Cougar Point", 2},
234 {"Cougar Point", 2}, 242 {"Cougar Point", 2},
235 {"Cougar Point", 2}, 243 {"Cougar Point", 2},
244 {"Patsburg", 2},
245 {"Patsburg", 2},
246 {"DH89xxCC", 2},
236 {NULL, 0} 247 {NULL, 0}
237}; 248};
238 249
@@ -286,6 +297,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
286 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, 297 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)},
287 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, 298 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
288 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, 299 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
300 { ITCO_PCI_DEVICE(0x27bc, TCO_NM10)},
289 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, 301 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
290 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, 302 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
291 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, 303 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
@@ -348,6 +360,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
348 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, 360 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)},
349 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, 361 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)},
350 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, 362 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)},
363 { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)},
364 { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)},
365 { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)},
351 { 0, }, /* End of list */ 366 { 0, }, /* End of list */
352}; 367};
353MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 368MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -374,7 +389,7 @@ static char expect_release;
374static struct { /* this is private data for the iTCO_wdt device */ 389static struct { /* this is private data for the iTCO_wdt device */
375 /* TCO version/generation */ 390 /* TCO version/generation */
376 unsigned int iTCO_version; 391 unsigned int iTCO_version;
377 /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 392 /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
378 unsigned long ACPIBASE; 393 unsigned long ACPIBASE;
379 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ 394 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
380 unsigned long __iomem *gcs; 395 unsigned long __iomem *gcs;
@@ -391,8 +406,8 @@ static struct platform_device *iTCO_wdt_platform_device;
391#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 406#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
392static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 407static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
393module_param(heartbeat, int, 0); 408module_param(heartbeat, int, 0);
394MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " 409MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
395 "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" 410 "5..76 (TCO v1) or 3..614 (TCO v2), default="
396 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 411 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
397 412
398static int nowayout = WATCHDOG_NOWAYOUT; 413static int nowayout = WATCHDOG_NOWAYOUT;
@@ -467,7 +482,7 @@ static int iTCO_wdt_start(void)
467 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 482 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
468 spin_unlock(&iTCO_wdt_private.io_lock); 483 spin_unlock(&iTCO_wdt_private.io_lock);
469 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " 484 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
470 "reboot disabled by hardware\n"); 485 "reboot disabled by hardware/BIOS\n");
471 return -EIO; 486 return -EIO;
472 } 487 }
473 488
@@ -523,8 +538,13 @@ static int iTCO_wdt_keepalive(void)
523 /* Reload the timer by writing to the TCO Timer Counter register */ 538 /* Reload the timer by writing to the TCO Timer Counter register */
524 if (iTCO_wdt_private.iTCO_version == 2) 539 if (iTCO_wdt_private.iTCO_version == 2)
525 outw(0x01, TCO_RLD); 540 outw(0x01, TCO_RLD);
526 else if (iTCO_wdt_private.iTCO_version == 1) 541 else if (iTCO_wdt_private.iTCO_version == 1) {
542 /* Reset the timeout status bit so that the timer
543 * needs to count down twice again before rebooting */
544 outw(0x0008, TCO1_STS); /* write 1 to clear bit */
545
527 outb(0x01, TCO_RLD); 546 outb(0x01, TCO_RLD);
547 }
528 548
529 spin_unlock(&iTCO_wdt_private.io_lock); 549 spin_unlock(&iTCO_wdt_private.io_lock);
530 return 0; 550 return 0;
@@ -537,6 +557,11 @@ static int iTCO_wdt_set_heartbeat(int t)
537 unsigned int tmrval; 557 unsigned int tmrval;
538 558
539 tmrval = seconds_to_ticks(t); 559 tmrval = seconds_to_ticks(t);
560
561 /* For TCO v1 the timer counts down twice before rebooting */
562 if (iTCO_wdt_private.iTCO_version == 1)
563 tmrval /= 2;
564
540 /* from the specs: */ 565 /* from the specs: */
541 /* "Values of 0h-3h are ignored and should not be attempted" */ 566 /* "Values of 0h-3h are ignored and should not be attempted" */
542 if (tmrval < 0x04) 567 if (tmrval < 0x04)
@@ -593,6 +618,8 @@ static int iTCO_wdt_get_timeleft(int *time_left)
593 spin_lock(&iTCO_wdt_private.io_lock); 618 spin_lock(&iTCO_wdt_private.io_lock);
594 val8 = inb(TCO_RLD); 619 val8 = inb(TCO_RLD);
595 val8 &= 0x3f; 620 val8 &= 0x3f;
621 if (!(inw(TCO1_STS) & 0x0008))
622 val8 += (inb(TCOv1_TMR) & 0x3f);
596 spin_unlock(&iTCO_wdt_private.io_lock); 623 spin_unlock(&iTCO_wdt_private.io_lock);
597 624
598 *time_left = (val8 * 6) / 10; 625 *time_left = (val8 * 6) / 10;
@@ -769,8 +796,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
769 base_address &= 0x0000ff80; 796 base_address &= 0x0000ff80;
770 if (base_address == 0x00000000) { 797 if (base_address == 0x00000000) {
771 /* Something's wrong here, ACPIBASE has to be set */ 798 /* Something's wrong here, ACPIBASE has to be set */
772 printk(KERN_ERR PFX "failed to get TCOBASE address\n"); 799 printk(KERN_ERR PFX "failed to get TCOBASE address, "
773 pci_dev_put(pdev); 800 "device disabled by hardware/BIOS\n");
774 return -ENODEV; 801 return -ENODEV;
775 } 802 }
776 iTCO_wdt_private.iTCO_version = 803 iTCO_wdt_private.iTCO_version =
@@ -785,7 +812,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
785 if (iTCO_wdt_private.iTCO_version == 2) { 812 if (iTCO_wdt_private.iTCO_version == 2) {
786 pci_read_config_dword(pdev, 0xf0, &base_address); 813 pci_read_config_dword(pdev, 0xf0, &base_address);
787 if ((base_address & 1) == 0) { 814 if ((base_address & 1) == 0) {
788 printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); 815 printk(KERN_ERR PFX "RCBA is disabled by hardware"
816 "/BIOS, device disabled\n");
789 ret = -ENODEV; 817 ret = -ENODEV;
790 goto out; 818 goto out;
791 } 819 }
@@ -796,7 +824,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
796 /* Check chipset's NO_REBOOT bit */ 824 /* Check chipset's NO_REBOOT bit */
797 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { 825 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
798 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " 826 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
799 "platform may have disabled it\n"); 827 "device disabled by hardware/BIOS\n");
800 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 828 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
801 goto out_unmap; 829 goto out_unmap;
802 } 830 }
@@ -807,7 +835,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
807 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 835 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
808 if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 836 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
809 printk(KERN_ERR PFX 837 printk(KERN_ERR PFX
810 "I/O address 0x%04lx already in use\n", SMI_EN); 838 "I/O address 0x%04lx already in use, "
839 "device disabled\n", SMI_EN);
811 ret = -EIO; 840 ret = -EIO;
812 goto out_unmap; 841 goto out_unmap;
813 } 842 }
@@ -819,8 +848,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
819 /* The TCO I/O registers reside in a 32-byte range pointed to 848 /* The TCO I/O registers reside in a 32-byte range pointed to
820 by the TCOBASE value */ 849 by the TCOBASE value */
821 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { 850 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
822 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", 851 printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
823 TCOBASE); 852 "device disabled\n", TCOBASE);
824 ret = -EIO; 853 ret = -EIO;
825 goto unreg_smi_en; 854 goto unreg_smi_en;
826 } 855 }
@@ -832,9 +861,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
832 TCOBASE); 861 TCOBASE);
833 862
834 /* Clear out the (probably old) status */ 863 /* Clear out the (probably old) status */
835 outb(8, TCO1_STS); /* Clear the Time Out Status bit */ 864 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
836 outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */ 865 outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
837 outb(4, TCO2_STS); /* Clear BOOT_STS bit */ 866 outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
838 867
839 /* Make sure the watchdog is not running */ 868 /* Make sure the watchdog is not running */
840 iTCO_wdt_stop(); 869 iTCO_wdt_stop();
@@ -844,8 +873,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
844 if (iTCO_wdt_set_heartbeat(heartbeat)) { 873 if (iTCO_wdt_set_heartbeat(heartbeat)) {
845 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); 874 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
846 printk(KERN_INFO PFX 875 printk(KERN_INFO PFX
847 "heartbeat value must be 2 < heartbeat < 39 (TCO v1) " 876 "timeout value out of range, using %d\n", heartbeat);
848 "or 613 (TCO v2), using %d\n", heartbeat);
849 } 877 }
850 878
851 ret = misc_register(&iTCO_wdt_miscdev); 879 ret = misc_register(&iTCO_wdt_miscdev);
@@ -869,7 +897,6 @@ out_unmap:
869 if (iTCO_wdt_private.iTCO_version == 2) 897 if (iTCO_wdt_private.iTCO_version == 2)
870 iounmap(iTCO_wdt_private.gcs); 898 iounmap(iTCO_wdt_private.gcs);
871out: 899out:
872 pci_dev_put(iTCO_wdt_private.pdev);
873 iTCO_wdt_private.ACPIBASE = 0; 900 iTCO_wdt_private.ACPIBASE = 0;
874 return ret; 901 return ret;
875} 902}
@@ -910,7 +937,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
910 } 937 }
911 938
912 if (!found) 939 if (!found)
913 printk(KERN_INFO PFX "No card detected\n"); 940 printk(KERN_INFO PFX "No device detected.\n");
914 941
915 return ret; 942 return ret;
916} 943}
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
new file mode 100644
index 000000000000..86f7cac1026c
--- /dev/null
+++ b/drivers/watchdog/imx2_wdt.c
@@ -0,0 +1,357 @@
1/*
2 * Watchdog driver for IMX2 and later processors
3 *
4 * Copyright (C) 2010 Wolfram Sang, Pengutronix e.K. <w.sang@pengutronix.de>
5 *
6 * some parts adapted by similar drivers from Darius Augulis and Vladimir
7 * Zapolskiy, additional improvements by Wim Van Sebroeck.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * NOTE: MX1 has a slightly different Watchdog than MX2 and later:
14 *
15 * MX1: MX2+:
16 * ---- -----
17 * Registers: 32-bit 16-bit
18 * Stopable timer: Yes No
19 * Need to enable clk: No Yes
20 * Halt on suspend: Manual Can be automatic
21 */
22
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/watchdog.h>
30#include <linux/clk.h>
31#include <linux/fs.h>
32#include <linux/io.h>
33#include <linux/uaccess.h>
34#include <linux/timer.h>
35#include <linux/jiffies.h>
36#include <mach/hardware.h>
37
38#define DRIVER_NAME "imx2-wdt"
39
40#define IMX2_WDT_WCR 0x00 /* Control Register */
41#define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */
42#define IMX2_WDT_WCR_WRE (1 << 3) /* -> WDOG Reset Enable */
43#define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */
44
45#define IMX2_WDT_WSR 0x02 /* Service Register */
46#define IMX2_WDT_SEQ1 0x5555 /* -> service sequence 1 */
47#define IMX2_WDT_SEQ2 0xAAAA /* -> service sequence 2 */
48
49#define IMX2_WDT_MAX_TIME 128
50#define IMX2_WDT_DEFAULT_TIME 60 /* in seconds */
51
52#define WDOG_SEC_TO_COUNT(s) ((s * 2 - 1) << 8)
53
54#define IMX2_WDT_STATUS_OPEN 0
55#define IMX2_WDT_STATUS_STARTED 1
56#define IMX2_WDT_EXPECT_CLOSE 2
57
58static struct {
59 struct clk *clk;
60 void __iomem *base;
61 unsigned timeout;
62 unsigned long status;
63 struct timer_list timer; /* Pings the watchdog when closed */
64} imx2_wdt;
65
66static struct miscdevice imx2_wdt_miscdev;
67
68static int nowayout = WATCHDOG_NOWAYOUT;
69module_param(nowayout, int, 0);
70MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
71 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
72
73
74static unsigned timeout = IMX2_WDT_DEFAULT_TIME;
75module_param(timeout, uint, 0);
76MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
77 __MODULE_STRING(IMX2_WDT_DEFAULT_TIME) ")");
78
79static const struct watchdog_info imx2_wdt_info = {
80 .identity = "imx2+ watchdog",
81 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
82};
83
84static inline void imx2_wdt_setup(void)
85{
86 u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WCR);
87
88 /* Strip the old watchdog Time-Out value */
89 val &= ~IMX2_WDT_WCR_WT;
90 /* Generate reset if WDOG times out */
91 val &= ~IMX2_WDT_WCR_WRE;
92 /* Keep Watchdog Disabled */
93 val &= ~IMX2_WDT_WCR_WDE;
94 /* Set the watchdog's Time-Out value */
95 val |= WDOG_SEC_TO_COUNT(imx2_wdt.timeout);
96
97 __raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR);
98
99 /* enable the watchdog */
100 val |= IMX2_WDT_WCR_WDE;
101 __raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR);
102}
103
104static inline void imx2_wdt_ping(void)
105{
106 __raw_writew(IMX2_WDT_SEQ1, imx2_wdt.base + IMX2_WDT_WSR);
107 __raw_writew(IMX2_WDT_SEQ2, imx2_wdt.base + IMX2_WDT_WSR);
108}
109
110static void imx2_wdt_timer_ping(unsigned long arg)
111{
112 /* ping it every imx2_wdt.timeout / 2 seconds to prevent reboot */
113 imx2_wdt_ping();
114 mod_timer(&imx2_wdt.timer, jiffies + imx2_wdt.timeout * HZ / 2);
115}
116
117static void imx2_wdt_start(void)
118{
119 if (!test_and_set_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) {
120 /* at our first start we enable clock and do initialisations */
121 clk_enable(imx2_wdt.clk);
122
123 imx2_wdt_setup();
124 } else /* delete the timer that pings the watchdog after close */
125 del_timer_sync(&imx2_wdt.timer);
126
127 /* Watchdog is enabled - time to reload the timeout value */
128 imx2_wdt_ping();
129}
130
131static void imx2_wdt_stop(void)
132{
133 /* we don't need a clk_disable, it cannot be disabled once started.
134 * We use a timer to ping the watchdog while /dev/watchdog is closed */
135 imx2_wdt_timer_ping(0);
136}
137
138static void imx2_wdt_set_timeout(int new_timeout)
139{
140 u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WCR);
141
142 /* set the new timeout value in the WSR */
143 val &= ~IMX2_WDT_WCR_WT;
144 val |= WDOG_SEC_TO_COUNT(new_timeout);
145 __raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR);
146}
147
148static int imx2_wdt_open(struct inode *inode, struct file *file)
149{
150 if (test_and_set_bit(IMX2_WDT_STATUS_OPEN, &imx2_wdt.status))
151 return -EBUSY;
152
153 imx2_wdt_start();
154 return nonseekable_open(inode, file);
155}
156
157static int imx2_wdt_close(struct inode *inode, struct file *file)
158{
159 if (test_bit(IMX2_WDT_EXPECT_CLOSE, &imx2_wdt.status) && !nowayout)
160 imx2_wdt_stop();
161 else {
162 dev_crit(imx2_wdt_miscdev.parent,
163 "Unexpected close: Expect reboot!\n");
164 imx2_wdt_ping();
165 }
166
167 clear_bit(IMX2_WDT_EXPECT_CLOSE, &imx2_wdt.status);
168 clear_bit(IMX2_WDT_STATUS_OPEN, &imx2_wdt.status);
169 return 0;
170}
171
172static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
173 unsigned long arg)
174{
175 void __user *argp = (void __user *)arg;
176 int __user *p = argp;
177 int new_value;
178
179 switch (cmd) {
180 case WDIOC_GETSUPPORT:
181 return copy_to_user(argp, &imx2_wdt_info,
182 sizeof(struct watchdog_info)) ? -EFAULT : 0;
183
184 case WDIOC_GETSTATUS:
185 case WDIOC_GETBOOTSTATUS:
186 return put_user(0, p);
187
188 case WDIOC_KEEPALIVE:
189 imx2_wdt_ping();
190 return 0;
191
192 case WDIOC_SETTIMEOUT:
193 if (get_user(new_value, p))
194 return -EFAULT;
195 if ((new_value < 1) || (new_value > IMX2_WDT_MAX_TIME))
196 return -EINVAL;
197 imx2_wdt_set_timeout(new_value);
198 imx2_wdt.timeout = new_value;
199 imx2_wdt_ping();
200
201 /* Fallthrough to return current value */
202 case WDIOC_GETTIMEOUT:
203 return put_user(imx2_wdt.timeout, p);
204
205 default:
206 return -ENOTTY;
207 }
208}
209
210static ssize_t imx2_wdt_write(struct file *file, const char __user *data,
211 size_t len, loff_t *ppos)
212{
213 size_t i;
214 char c;
215
216 if (len == 0) /* Can we see this even ? */
217 return 0;
218
219 clear_bit(IMX2_WDT_EXPECT_CLOSE, &imx2_wdt.status);
220 /* scan to see whether or not we got the magic character */
221 for (i = 0; i != len; i++) {
222 if (get_user(c, data + i))
223 return -EFAULT;
224 if (c == 'V')
225 set_bit(IMX2_WDT_EXPECT_CLOSE, &imx2_wdt.status);
226 }
227
228 imx2_wdt_ping();
229 return len;
230}
231
232static const struct file_operations imx2_wdt_fops = {
233 .owner = THIS_MODULE,
234 .llseek = no_llseek,
235 .unlocked_ioctl = imx2_wdt_ioctl,
236 .open = imx2_wdt_open,
237 .release = imx2_wdt_close,
238 .write = imx2_wdt_write,
239};
240
241static struct miscdevice imx2_wdt_miscdev = {
242 .minor = WATCHDOG_MINOR,
243 .name = "watchdog",
244 .fops = &imx2_wdt_fops,
245};
246
247static int __init imx2_wdt_probe(struct platform_device *pdev)
248{
249 int ret;
250 int res_size;
251 struct resource *res;
252
253 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254 if (!res) {
255 dev_err(&pdev->dev, "can't get device resources\n");
256 return -ENODEV;
257 }
258
259 res_size = resource_size(res);
260 if (!devm_request_mem_region(&pdev->dev, res->start, res_size,
261 res->name)) {
262 dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
263 res_size, res->start);
264 return -ENOMEM;
265 }
266
267 imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size);
268 if (!imx2_wdt.base) {
269 dev_err(&pdev->dev, "ioremap failed\n");
270 return -ENOMEM;
271 }
272
273 imx2_wdt.clk = clk_get(&pdev->dev, NULL);
274 if (IS_ERR(imx2_wdt.clk)) {
275 dev_err(&pdev->dev, "can't get Watchdog clock\n");
276 return PTR_ERR(imx2_wdt.clk);
277 }
278
279 imx2_wdt.timeout = clamp_t(unsigned, timeout, 1, IMX2_WDT_MAX_TIME);
280 if (imx2_wdt.timeout != timeout)
281 dev_warn(&pdev->dev, "Initial timeout out of range! "
282 "Clamped from %u to %u\n", timeout, imx2_wdt.timeout);
283
284 setup_timer(&imx2_wdt.timer, imx2_wdt_timer_ping, 0);
285
286 imx2_wdt_miscdev.parent = &pdev->dev;
287 ret = misc_register(&imx2_wdt_miscdev);
288 if (ret)
289 goto fail;
290
291 dev_info(&pdev->dev,
292 "IMX2+ Watchdog Timer enabled. timeout=%ds (nowayout=%d)\n",
293 imx2_wdt.timeout, nowayout);
294 return 0;
295
296fail:
297 imx2_wdt_miscdev.parent = NULL;
298 clk_put(imx2_wdt.clk);
299 return ret;
300}
301
302static int __exit imx2_wdt_remove(struct platform_device *pdev)
303{
304 misc_deregister(&imx2_wdt_miscdev);
305
306 if (test_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) {
307 del_timer_sync(&imx2_wdt.timer);
308
309 dev_crit(imx2_wdt_miscdev.parent,
310 "Device removed: Expect reboot!\n");
311 } else
312 clk_put(imx2_wdt.clk);
313
314 imx2_wdt_miscdev.parent = NULL;
315 return 0;
316}
317
318static void imx2_wdt_shutdown(struct platform_device *pdev)
319{
320 if (test_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) {
321 /* we are running, we need to delete the timer but will give
322 * max timeout before reboot will take place */
323 del_timer_sync(&imx2_wdt.timer);
324 imx2_wdt_set_timeout(IMX2_WDT_MAX_TIME);
325 imx2_wdt_ping();
326
327 dev_crit(imx2_wdt_miscdev.parent,
328 "Device shutdown: Expect reboot!\n");
329 }
330}
331
332static struct platform_driver imx2_wdt_driver = {
333 .remove = __exit_p(imx2_wdt_remove),
334 .shutdown = imx2_wdt_shutdown,
335 .driver = {
336 .name = DRIVER_NAME,
337 .owner = THIS_MODULE,
338 },
339};
340
341static int __init imx2_wdt_init(void)
342{
343 return platform_driver_probe(&imx2_wdt_driver, imx2_wdt_probe);
344}
345module_init(imx2_wdt_init);
346
347static void __exit imx2_wdt_exit(void)
348{
349 platform_driver_unregister(&imx2_wdt_driver);
350}
351module_exit(imx2_wdt_exit);
352
353MODULE_AUTHOR("Wolfram Sang");
354MODULE_DESCRIPTION("Watchdog driver for IMX2 and later");
355MODULE_LICENSE("GPL v2");
356MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
357MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index f52c162b1bea..b32c6c045b1a 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -75,15 +75,23 @@ static unsigned short address;
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..dad29245a6a7 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 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.13"
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"
@@ -76,10 +76,12 @@
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
83#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 85#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
84 86
85/* GPIO Configuration Registers LDN=0x07 */ 87/* GPIO Configuration Registers LDN=0x07 */
@@ -92,7 +94,7 @@
92#define WDT_CIRINT 0x80 94#define WDT_CIRINT 0x80
93#define WDT_MOUSEINT 0x40 95#define WDT_MOUSEINT 0x40
94#define WDT_KYBINT 0x20 96#define WDT_KYBINT 0x20
95#define WDT_GAMEPORT 0x10 /* not it8718 */ 97#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */
96#define WDT_FORCE 0x02 98#define WDT_FORCE 0x02
97#define WDT_ZERO 0x01 99#define WDT_ZERO 0x01
98 100
@@ -132,7 +134,7 @@
132#define WDTS_USE_GP 4 134#define WDTS_USE_GP 4
133#define WDTS_EXPECTED 5 135#define WDTS_EXPECTED 5
134 136
135static unsigned int base, gpact, ciract; 137static unsigned int base, gpact, ciract, max_units;
136static unsigned long wdt_status; 138static unsigned long wdt_status;
137static DEFINE_SPINLOCK(spinlock); 139static DEFINE_SPINLOCK(spinlock);
138 140
@@ -210,6 +212,33 @@ static inline void superio_outw(int val, int reg)
210 outb(val, VAL); 212 outb(val, VAL);
211} 213}
212 214
215/* Internal function, should be called after superio_select(GPIO) */
216static void wdt_update_timeout(void)
217{
218 unsigned char cfg = WDT_KRST | WDT_PWROK;
219 int tm = timeout;
220
221 if (testmode)
222 cfg = 0;
223
224 if (tm <= max_units)
225 cfg |= WDT_TOV1;
226 else
227 tm /= 60;
228
229 superio_outb(cfg, WDTCFG);
230 superio_outb(tm, WDTVALLSB);
231 if (max_units > 255)
232 superio_outb(tm>>8, WDTVALMSB);
233}
234
235static int wdt_round_time(int t)
236{
237 t += 59;
238 t -= t % 60;
239 return t;
240}
241
213/* watchdog timer handling */ 242/* watchdog timer handling */
214 243
215static void wdt_keepalive(void) 244static void wdt_keepalive(void)
@@ -234,12 +263,7 @@ static void wdt_start(void)
234 superio_outb(WDT_GAMEPORT, WDTCTRL); 263 superio_outb(WDT_GAMEPORT, WDTCTRL);
235 else 264 else
236 superio_outb(WDT_CIRINT, WDTCTRL); 265 superio_outb(WDT_CIRINT, WDTCTRL);
237 if (!testmode) 266 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 267
244 superio_exit(); 268 superio_exit();
245 spin_unlock_irqrestore(&spinlock, flags); 269 spin_unlock_irqrestore(&spinlock, flags);
@@ -255,8 +279,9 @@ static void wdt_stop(void)
255 superio_select(GPIO); 279 superio_select(GPIO);
256 superio_outb(0x00, WDTCTRL); 280 superio_outb(0x00, WDTCTRL);
257 superio_outb(WDT_TOV1, WDTCFG); 281 superio_outb(WDT_TOV1, WDTCFG);
258 superio_outb(0x00, WDTVALMSB);
259 superio_outb(0x00, WDTVALLSB); 282 superio_outb(0x00, WDTVALLSB);
283 if (max_units > 255)
284 superio_outb(0x00, WDTVALMSB);
260 285
261 superio_exit(); 286 superio_exit();
262 spin_unlock_irqrestore(&spinlock, flags); 287 spin_unlock_irqrestore(&spinlock, flags);
@@ -266,8 +291,8 @@ static void wdt_stop(void)
266 * wdt_set_timeout - set a new timeout value with watchdog ioctl 291 * wdt_set_timeout - set a new timeout value with watchdog ioctl
267 * @t: timeout value in seconds 292 * @t: timeout value in seconds
268 * 293 *
269 * The hardware device has a 16 bit watchdog timer, thus the 294 * The hardware device has a 8 or 16 bit watchdog timer (depends on
270 * timeout time ranges between 1 and 65535 seconds. 295 * chip version) that can be configured to count seconds or minutes.
271 * 296 *
272 * Used within WDIOC_SETTIMEOUT watchdog device ioctl. 297 * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
273 */ 298 */
@@ -276,19 +301,19 @@ static int wdt_set_timeout(int t)
276{ 301{
277 unsigned long flags; 302 unsigned long flags;
278 303
279 if (t < 1 || t > 65535) 304 if (t < 1 || t > max_units * 60)
280 return -EINVAL; 305 return -EINVAL;
281 306
282 timeout = t; 307 if (t > max_units)
308 timeout = wdt_round_time(t);
309 else
310 timeout = t;
283 311
284 spin_lock_irqsave(&spinlock, flags); 312 spin_lock_irqsave(&spinlock, flags);
285 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 313 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
286 superio_enter(); 314 superio_enter();
287
288 superio_select(GPIO); 315 superio_select(GPIO);
289 superio_outb(t>>8, WDTVALMSB); 316 wdt_update_timeout();
290 superio_outb(t, WDTVALLSB);
291
292 superio_exit(); 317 superio_exit();
293 } 318 }
294 spin_unlock_irqrestore(&spinlock, flags); 319 spin_unlock_irqrestore(&spinlock, flags);
@@ -529,10 +554,13 @@ static struct notifier_block wdt_notifier = {
529static int __init it87_wdt_init(void) 554static int __init it87_wdt_init(void)
530{ 555{
531 int rc = 0; 556 int rc = 0;
557 int try_gameport = !nogameport;
532 u16 chip_type; 558 u16 chip_type;
533 u8 chip_rev; 559 u8 chip_rev;
534 unsigned long flags; 560 unsigned long flags;
535 561
562 wdt_status = 0;
563
536 spin_lock_irqsave(&spinlock, flags); 564 spin_lock_irqsave(&spinlock, flags);
537 superio_enter(); 565 superio_enter();
538 chip_type = superio_inw(CHIPID); 566 chip_type = superio_inw(CHIPID);
@@ -541,13 +569,21 @@ static int __init it87_wdt_init(void)
541 spin_unlock_irqrestore(&spinlock, flags); 569 spin_unlock_irqrestore(&spinlock, flags);
542 570
543 switch (chip_type) { 571 switch (chip_type) {
572 case IT8702_ID:
573 max_units = 255;
574 break;
575 case IT8712_ID:
576 max_units = (chip_rev < 8) ? 255 : 65535;
577 break;
544 case IT8716_ID: 578 case IT8716_ID:
545 case IT8718_ID:
546 case IT8726_ID: 579 case IT8726_ID:
580 max_units = 65535;
581 break;
582 case IT8718_ID:
583 case IT8720_ID:
584 max_units = 65535;
585 try_gameport = 0;
547 break; 586 break;
548 case IT8712_ID:
549 if (chip_rev > 7)
550 break;
551 case IT8705_ID: 587 case IT8705_ID:
552 printk(KERN_ERR PFX 588 printk(KERN_ERR PFX
553 "Unsupported Chip found, Chip %04x Revision %02x\n", 589 "Unsupported Chip found, Chip %04x Revision %02x\n",
@@ -571,7 +607,7 @@ static int __init it87_wdt_init(void)
571 superio_outb(0x00, WDTCTRL); 607 superio_outb(0x00, WDTCTRL);
572 608
573 /* First try to get Gameport support */ 609 /* First try to get Gameport support */
574 if (chip_type != IT8718_ID && !nogameport) { 610 if (try_gameport) {
575 superio_select(GAMEPORT); 611 superio_select(GAMEPORT);
576 base = superio_inw(BASEREG); 612 base = superio_inw(BASEREG);
577 if (!base) { 613 if (!base) {
@@ -623,13 +659,16 @@ static int __init it87_wdt_init(void)
623 spin_unlock_irqrestore(&spinlock, flags); 659 spin_unlock_irqrestore(&spinlock, flags);
624 } 660 }
625 661
626 if (timeout < 1 || timeout > 65535) { 662 if (timeout < 1 || timeout > max_units * 60) {
627 timeout = DEFAULT_TIMEOUT; 663 timeout = DEFAULT_TIMEOUT;
628 printk(KERN_WARNING PFX 664 printk(KERN_WARNING PFX
629 "Timeout value out of range, use default %d sec\n", 665 "Timeout value out of range, use default %d sec\n",
630 DEFAULT_TIMEOUT); 666 DEFAULT_TIMEOUT);
631 } 667 }
632 668
669 if (timeout > max_units)
670 timeout = wdt_round_time(timeout);
671
633 rc = register_reboot_notifier(&wdt_notifier); 672 rc = register_reboot_notifier(&wdt_notifier);
634 if (rc) { 673 if (rc) {
635 printk(KERN_ERR PFX 674 printk(KERN_ERR PFX
@@ -656,7 +695,7 @@ static int __init it87_wdt_init(void)
656 outb(0x09, CIR_IER(base)); 695 outb(0x09, CIR_IER(base));
657 } 696 }
658 697
659 printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " 698 printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
660 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " 699 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
661 "nogameport=%d)\n", chip_type, chip_rev, timeout, 700 "nogameport=%d)\n", chip_type, chip_rev, timeout,
662 nowayout, testmode, exclusive, nogameport); 701 nowayout, testmode, exclusive, nogameport);
@@ -676,7 +715,7 @@ err_out_region:
676 spin_unlock_irqrestore(&spinlock, flags); 715 spin_unlock_irqrestore(&spinlock, flags);
677 } 716 }
678err_out: 717err_out:
679 if (chip_type != IT8718_ID && !nogameport) { 718 if (try_gameport) {
680 spin_lock_irqsave(&spinlock, flags); 719 spin_lock_irqsave(&spinlock, flags);
681 superio_enter(); 720 superio_enter();
682 superio_select(GAMEPORT); 721 superio_select(GAMEPORT);
@@ -698,8 +737,9 @@ static void __exit it87_wdt_exit(void)
698 superio_select(GPIO); 737 superio_select(GPIO);
699 superio_outb(0x00, WDTCTRL); 738 superio_outb(0x00, WDTCTRL);
700 superio_outb(0x00, WDTCFG); 739 superio_outb(0x00, WDTCFG);
701 superio_outb(0x00, WDTVALMSB);
702 superio_outb(0x00, WDTVALLSB); 740 superio_outb(0x00, WDTVALLSB);
741 if (max_units > 255)
742 superio_outb(0x00, WDTVALMSB);
703 if (test_bit(WDTS_USE_GP, &wdt_status)) { 743 if (test_bit(WDTS_USE_GP, &wdt_status)) {
704 superio_select(GAMEPORT); 744 superio_select(GAMEPORT);
705 superio_outb(gpact, ACTREG); 745 superio_outb(gpact, ACTREG);
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/m548x_wdt.c b/drivers/watchdog/m548x_wdt.c
new file mode 100644
index 000000000000..cabbcfe1c847
--- /dev/null
+++ b/drivers/watchdog/m548x_wdt.c
@@ -0,0 +1,227 @@
1/*
2 * drivers/watchdog/m548x_wdt.c
3 *
4 * Watchdog driver for ColdFire 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/m548xsim.h>
33#include <asm/m548xgpt.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 m548x_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 m548x_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 M548x Watchdog",
116};
117
118static long m548x_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 m548x_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 m548x_wdt_fops = {
181 .owner = THIS_MODULE,
182 .llseek = no_llseek,
183 .write = m548x_wdt_write,
184 .unlocked_ioctl = m548x_wdt_ioctl,
185 .open = m548x_wdt_open,
186 .release = m548x_wdt_release,
187};
188
189static struct miscdevice m548x_wdt_miscdev = {
190 .minor = WATCHDOG_MINOR,
191 .name = "watchdog",
192 .fops = &m548x_wdt_fops,
193};
194
195static int __init m548x_wdt_init(void)
196{
197 if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
198 "Coldfire M548x Watchdog")) {
199 printk(KERN_WARNING
200 "Coldfire M548x 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(&m548x_wdt_miscdev);
206}
207
208static void __exit m548x_wdt_exit(void)
209{
210 misc_deregister(&m548x_wdt_miscdev);
211 release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4);
212}
213
214module_init(m548x_wdt_init);
215module_exit(m548x_wdt_exit);
216
217MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
218MODULE_DESCRIPTION("Coldfire M548x 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..928035069396 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -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/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 7b55974191dd..8fa213cdb499 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -53,7 +53,7 @@ static int mpc8xxx_wdt_init_late(void);
53static u16 timeout = 0xffff; 53static u16 timeout = 0xffff;
54module_param(timeout, ushort, 0); 54module_param(timeout, ushort, 0);
55MODULE_PARM_DESC(timeout, 55MODULE_PARM_DESC(timeout,
56 "Watchdog timeout in ticks. (0<timeout<65536, default=65535"); 56 "Watchdog timeout in ticks. (0<timeout<65536, default=65535)");
57 57
58static int reset = 1; 58static int reset = 1;
59module_param(reset, bool, 0); 59module_param(reset, bool, 0);
@@ -185,11 +185,11 @@ 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 of_device *ofdev, 188static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev,
189 const struct of_device_id *match) 189 const struct of_device_id *match)
190{ 190{
191 int ret; 191 int ret;
192 struct device_node *np = ofdev->node; 192 struct device_node *np = ofdev->dev.of_node;
193 struct mpc8xxx_wdt_type *wdt_type = match->data; 193 struct mpc8xxx_wdt_type *wdt_type = match->data;
194 u32 freq = fsl_get_sys_freq(); 194 u32 freq = fsl_get_sys_freq();
195 bool enabled; 195 bool enabled;
@@ -238,7 +238,7 @@ err_unmap:
238 return ret; 238 return ret;
239} 239}
240 240
241static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) 241static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev)
242{ 242{
243 mpc8xxx_wdt_pr_warn("watchdog removed"); 243 mpc8xxx_wdt_pr_warn("watchdog removed");
244 del_timer_sync(&wdt_timer); 244 del_timer_sync(&wdt_timer);
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
new file mode 100644
index 000000000000..1a50aa7079bf
--- /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 struct pci_device_id 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 __init 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
new file mode 100644
index 000000000000..945ee8300306
--- /dev/null
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -0,0 +1,746 @@
1/*
2 * Octeon Watchdog driver
3 *
4 * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks
5 *
6 * Some parts derived from wdt.c
7 *
8 * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>,
9 * All Rights Reserved.
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 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
17 * warranty for any of this software. This material is provided
18 * "AS-IS" and at no charge.
19 *
20 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
21 *
22 * This file is subject to the terms and conditions of the GNU General Public
23 * License. See the file "COPYING" in the main directory of this archive
24 * for more details.
25 *
26 *
27 * The OCTEON watchdog has a maximum timeout of 2^32 * io_clock.
28 * For most systems this is less than 10 seconds, so to allow for
29 * software to request longer watchdog heartbeats, we maintain software
30 * counters to count multiples of the base rate. If the system locks
31 * up in such a manner that we can not run the software counters, the
32 * only result is a watchdog reset sooner than was requested. But
33 * that is OK, because in this case userspace would likely not be able
34 * to do anything anyhow.
35 *
36 * The hardware watchdog interval we call the period. The OCTEON
37 * watchdog goes through several stages, after the first period an
38 * irq is asserted, then if it is not reset, after the next period NMI
39 * is asserted, then after an additional period a chip wide soft reset.
40 * So for the software counters, we reset watchdog after each period
41 * and decrement the counter. But for the last two periods we need to
42 * let the watchdog progress to the NMI stage so we disable the irq
43 * and let it proceed. Once in the NMI, we print the register state
44 * to the serial port and then wait for the reset.
45 *
46 * A watchdog is maintained for each CPU in the system, that way if
47 * one CPU suffers a lockup, we also get a register dump and reset.
48 * The userspace ping resets the watchdog on all CPUs.
49 *
50 * Before userspace opens the watchdog device, we still run the
51 * watchdogs to catch any lockups that may be kernel related.
52 *
53 */
54
55#include <linux/miscdevice.h>
56#include <linux/interrupt.h>
57#include <linux/watchdog.h>
58#include <linux/cpumask.h>
59#include <linux/bitops.h>
60#include <linux/kernel.h>
61#include <linux/module.h>
62#include <linux/string.h>
63#include <linux/delay.h>
64#include <linux/cpu.h>
65#include <linux/smp.h>
66#include <linux/fs.h>
67#include <linux/irq.h>
68
69#include <asm/mipsregs.h>
70#include <asm/uasm.h>
71
72#include <asm/octeon/octeon.h>
73
74/* The count needed to achieve timeout_sec. */
75static unsigned int timeout_cnt;
76
77/* The maximum period supported. */
78static unsigned int max_timeout_sec;
79
80/* The current period. */
81static unsigned int timeout_sec;
82
83/* Set to non-zero when userspace countdown mode active */
84static int do_coundown;
85static unsigned int countdown_reset;
86static unsigned int per_cpu_countdown[NR_CPUS];
87
88static cpumask_t irq_enabled_cpus;
89
90#define WD_TIMO 60 /* Default heartbeat = 60 seconds */
91
92static int heartbeat = WD_TIMO;
93module_param(heartbeat, int, S_IRUGO);
94MODULE_PARM_DESC(heartbeat,
95 "Watchdog heartbeat in seconds. (0 < heartbeat, default="
96 __MODULE_STRING(WD_TIMO) ")");
97
98static int nowayout = WATCHDOG_NOWAYOUT;
99module_param(nowayout, int, S_IRUGO);
100MODULE_PARM_DESC(nowayout,
101 "Watchdog cannot be stopped once started (default="
102 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
103
104static unsigned long octeon_wdt_is_open;
105static char expect_close;
106
107static u32 __initdata nmi_stage1_insns[64];
108/* We need one branch and therefore one relocation per target label. */
109static struct uasm_label __initdata labels[5];
110static struct uasm_reloc __initdata relocs[5];
111
112enum lable_id {
113 label_enter_bootloader = 1
114};
115
116/* Some CP0 registers */
117#define K0 26
118#define C0_CVMMEMCTL 11, 7
119#define C0_STATUS 12, 0
120#define C0_EBASE 15, 1
121#define C0_DESAVE 31, 0
122
123void octeon_wdt_nmi_stage2(void);
124
125static void __init octeon_wdt_build_stage1(void)
126{
127 int i;
128 int len;
129 u32 *p = nmi_stage1_insns;
130#ifdef CONFIG_HOTPLUG_CPU
131 struct uasm_label *l = labels;
132 struct uasm_reloc *r = relocs;
133#endif
134
135 /*
136 * For the next few instructions running the debugger may
137 * cause corruption of k0 in the saved registers. Since we're
138 * about to crash, nobody probably cares.
139 *
140 * Save K0 into the debug scratch register
141 */
142 uasm_i_dmtc0(&p, K0, C0_DESAVE);
143
144 uasm_i_mfc0(&p, K0, C0_STATUS);
145#ifdef CONFIG_HOTPLUG_CPU
146 uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
147#endif
148 /* Force 64-bit addressing enabled */
149 uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
150 uasm_i_mtc0(&p, K0, C0_STATUS);
151
152#ifdef CONFIG_HOTPLUG_CPU
153 uasm_i_mfc0(&p, K0, C0_EBASE);
154 /* Coreid number in K0 */
155 uasm_i_andi(&p, K0, K0, 0xf);
156 /* 8 * coreid in bits 16-31 */
157 uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
158 uasm_i_ori(&p, K0, K0, 0x8001);
159 uasm_i_dsll_safe(&p, K0, K0, 16);
160 uasm_i_ori(&p, K0, K0, 0x0700);
161 uasm_i_drotr_safe(&p, K0, K0, 32);
162 /*
163 * Should result in: 0x8001,0700,0000,8*coreid which is
164 * CVMX_CIU_WDOGX(coreid) - 0x0500
165 *
166 * Now ld K0, CVMX_CIU_WDOGX(coreid)
167 */
168 uasm_i_ld(&p, K0, 0x500, K0);
169 /*
170 * If bit one set handle the NMI as a watchdog event.
171 * otherwise transfer control to bootloader.
172 */
173 uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
174 uasm_i_nop(&p);
175#endif
176
177 /* Clear Dcache so cvmseg works right. */
178 uasm_i_cache(&p, 1, 0, 0);
179
180 /* Use K0 to do a read/modify/write of CVMMEMCTL */
181 uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL);
182 /* Clear out the size of CVMSEG */
183 uasm_i_dins(&p, K0, 0, 0, 6);
184 /* Set CVMSEG to its largest value */
185 uasm_i_ori(&p, K0, K0, 0x1c0 | 54);
186 /* Store the CVMMEMCTL value */
187 uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL);
188
189 /* Load the address of the second stage handler */
190 UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2);
191 uasm_i_jr(&p, K0);
192 uasm_i_dmfc0(&p, K0, C0_DESAVE);
193
194#ifdef CONFIG_HOTPLUG_CPU
195 uasm_build_label(&l, p, label_enter_bootloader);
196 /* Jump to the bootloader and restore K0 */
197 UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
198 uasm_i_jr(&p, K0);
199 uasm_i_dmfc0(&p, K0, C0_DESAVE);
200#endif
201 uasm_resolve_relocs(relocs, labels);
202
203 len = (int)(p - nmi_stage1_insns);
204 pr_debug("Synthesized NMI stage 1 handler (%d instructions).\n", len);
205
206 pr_debug("\t.set push\n");
207 pr_debug("\t.set noreorder\n");
208 for (i = 0; i < len; i++)
209 pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]);
210 pr_debug("\t.set pop\n");
211
212 if (len > 32)
213 panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len);
214}
215
216static int cpu2core(int cpu)
217{
218#ifdef CONFIG_SMP
219 return cpu_logical_map(cpu);
220#else
221 return cvmx_get_core_num();
222#endif
223}
224
225static int core2cpu(int coreid)
226{
227#ifdef CONFIG_SMP
228 return cpu_number_map(coreid);
229#else
230 return 0;
231#endif
232}
233
234/**
235 * Poke the watchdog when an interrupt is received
236 *
237 * @cpl:
238 * @dev_id:
239 *
240 * Returns
241 */
242static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
243{
244 unsigned int core = cvmx_get_core_num();
245 int cpu = core2cpu(core);
246
247 if (do_coundown) {
248 if (per_cpu_countdown[cpu] > 0) {
249 /* We're alive, poke the watchdog */
250 cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
251 per_cpu_countdown[cpu]--;
252 } else {
253 /* Bad news, you are about to reboot. */
254 disable_irq_nosync(cpl);
255 cpumask_clear_cpu(cpu, &irq_enabled_cpus);
256 }
257 } else {
258 /* Not open, just ping away... */
259 cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
260 }
261 return IRQ_HANDLED;
262}
263
264/* From setup.c */
265extern int prom_putchar(char c);
266
267/**
268 * Write a string to the uart
269 *
270 * @str: String to write
271 */
272static void octeon_wdt_write_string(const char *str)
273{
274 /* Just loop writing one byte at a time */
275 while (*str)
276 prom_putchar(*str++);
277}
278
279/**
280 * Write a hex number out of the uart
281 *
282 * @value: Number to display
283 * @digits: Number of digits to print (1 to 16)
284 */
285static void octeon_wdt_write_hex(u64 value, int digits)
286{
287 int d;
288 int v;
289 for (d = 0; d < digits; d++) {
290 v = (value >> ((digits - d - 1) * 4)) & 0xf;
291 if (v >= 10)
292 prom_putchar('a' + v - 10);
293 else
294 prom_putchar('0' + v);
295 }
296}
297
298const char *reg_name[] = {
299 "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
300 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
301 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
302 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
303};
304
305/**
306 * NMI stage 3 handler. NMIs are handled in the following manner:
307 * 1) The first NMI handler enables CVMSEG and transfers from
308 * the bootbus region into normal memory. It is careful to not
309 * destroy any registers.
310 * 2) The second stage handler uses CVMSEG to save the registers
311 * and create a stack for C code. It then calls the third level
312 * handler with one argument, a pointer to the register values.
313 * 3) The third, and final, level handler is the following C
314 * function that prints out some useful infomration.
315 *
316 * @reg: Pointer to register state before the NMI
317 */
318void octeon_wdt_nmi_stage3(u64 reg[32])
319{
320 u64 i;
321
322 unsigned int coreid = cvmx_get_core_num();
323 /*
324 * Save status and cause early to get them before any changes
325 * might happen.
326 */
327 u64 cp0_cause = read_c0_cause();
328 u64 cp0_status = read_c0_status();
329 u64 cp0_error_epc = read_c0_errorepc();
330 u64 cp0_epc = read_c0_epc();
331
332 /* Delay so output from all cores output is not jumbled together. */
333 __delay(100000000ull * coreid);
334
335 octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x");
336 octeon_wdt_write_hex(coreid, 1);
337 octeon_wdt_write_string(" ***\r\n");
338 for (i = 0; i < 32; i++) {
339 octeon_wdt_write_string("\t");
340 octeon_wdt_write_string(reg_name[i]);
341 octeon_wdt_write_string("\t0x");
342 octeon_wdt_write_hex(reg[i], 16);
343 if (i & 1)
344 octeon_wdt_write_string("\r\n");
345 }
346 octeon_wdt_write_string("\terr_epc\t0x");
347 octeon_wdt_write_hex(cp0_error_epc, 16);
348
349 octeon_wdt_write_string("\tepc\t0x");
350 octeon_wdt_write_hex(cp0_epc, 16);
351 octeon_wdt_write_string("\r\n");
352
353 octeon_wdt_write_string("\tstatus\t0x");
354 octeon_wdt_write_hex(cp0_status, 16);
355 octeon_wdt_write_string("\tcause\t0x");
356 octeon_wdt_write_hex(cp0_cause, 16);
357 octeon_wdt_write_string("\r\n");
358
359 octeon_wdt_write_string("\tsum0\t0x");
360 octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
361 octeon_wdt_write_string("\ten0\t0x");
362 octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
363 octeon_wdt_write_string("\r\n");
364
365 octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
366}
367
368static void octeon_wdt_disable_interrupt(int cpu)
369{
370 unsigned int core;
371 unsigned int irq;
372 union cvmx_ciu_wdogx ciu_wdog;
373
374 core = cpu2core(cpu);
375
376 irq = OCTEON_IRQ_WDOG0 + core;
377
378 /* Poke the watchdog to clear out its state */
379 cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
380
381 /* Disable the hardware. */
382 ciu_wdog.u64 = 0;
383 cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
384
385 free_irq(irq, octeon_wdt_poke_irq);
386}
387
388static void octeon_wdt_setup_interrupt(int cpu)
389{
390 unsigned int core;
391 unsigned int irq;
392 union cvmx_ciu_wdogx ciu_wdog;
393
394 core = cpu2core(cpu);
395
396 /* Disable it before doing anything with the interrupts. */
397 ciu_wdog.u64 = 0;
398 cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
399
400 per_cpu_countdown[cpu] = countdown_reset;
401
402 irq = OCTEON_IRQ_WDOG0 + core;
403
404 if (request_irq(irq, octeon_wdt_poke_irq,
405 IRQF_DISABLED, "octeon_wdt", octeon_wdt_poke_irq))
406 panic("octeon_wdt: Couldn't obtain irq %d", irq);
407
408 cpumask_set_cpu(cpu, &irq_enabled_cpus);
409
410 /* Poke the watchdog to clear out its state */
411 cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
412
413 /* Finally enable the watchdog now that all handlers are installed */
414 ciu_wdog.u64 = 0;
415 ciu_wdog.s.len = timeout_cnt;
416 ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
417 cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
418}
419
420static int octeon_wdt_cpu_callback(struct notifier_block *nfb,
421 unsigned long action, void *hcpu)
422{
423 unsigned int cpu = (unsigned long)hcpu;
424
425 switch (action) {
426 case CPU_DOWN_PREPARE:
427 octeon_wdt_disable_interrupt(cpu);
428 break;
429 case CPU_ONLINE:
430 case CPU_DOWN_FAILED:
431 octeon_wdt_setup_interrupt(cpu);
432 break;
433 default:
434 break;
435 }
436 return NOTIFY_OK;
437}
438
439static void octeon_wdt_ping(void)
440{
441 int cpu;
442 int coreid;
443
444 for_each_online_cpu(cpu) {
445 coreid = cpu2core(cpu);
446 cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
447 per_cpu_countdown[cpu] = countdown_reset;
448 if ((countdown_reset || !do_coundown) &&
449 !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
450 /* We have to enable the irq */
451 int irq = OCTEON_IRQ_WDOG0 + coreid;
452 enable_irq(irq);
453 cpumask_set_cpu(cpu, &irq_enabled_cpus);
454 }
455 }
456}
457
458static void octeon_wdt_calc_parameters(int t)
459{
460 unsigned int periods;
461
462 timeout_sec = max_timeout_sec;
463
464
465 /*
466 * Find the largest interrupt period, that can evenly divide
467 * the requested heartbeat time.
468 */
469 while ((t % timeout_sec) != 0)
470 timeout_sec--;
471
472 periods = t / timeout_sec;
473
474 /*
475 * The last two periods are after the irq is disabled, and
476 * then to the nmi, so we subtract them off.
477 */
478
479 countdown_reset = periods > 2 ? periods - 2 : 0;
480 heartbeat = t;
481 timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
482}
483
484static int octeon_wdt_set_heartbeat(int t)
485{
486 int cpu;
487 int coreid;
488 union cvmx_ciu_wdogx ciu_wdog;
489
490 if (t <= 0)
491 return -1;
492
493 octeon_wdt_calc_parameters(t);
494
495 for_each_online_cpu(cpu) {
496 coreid = cpu2core(cpu);
497 cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
498 ciu_wdog.u64 = 0;
499 ciu_wdog.s.len = timeout_cnt;
500 ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */
501 cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
502 cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
503 }
504 octeon_wdt_ping(); /* Get the irqs back on. */
505 return 0;
506}
507
508/**
509 * octeon_wdt_write:
510 * @file: file handle to the watchdog
511 * @buf: buffer to write (unused as data does not matter here
512 * @count: count of bytes
513 * @ppos: pointer to the position to write. No seeks allowed
514 *
515 * A write to a watchdog device is defined as a keepalive signal. Any
516 * write of data will do, as we we don't define content meaning.
517 */
518
519static ssize_t octeon_wdt_write(struct file *file, const char __user *buf,
520 size_t count, loff_t *ppos)
521{
522 if (count) {
523 if (!nowayout) {
524 size_t i;
525
526 /* In case it was set long ago */
527 expect_close = 0;
528
529 for (i = 0; i != count; i++) {
530 char c;
531 if (get_user(c, buf + i))
532 return -EFAULT;
533 if (c == 'V')
534 expect_close = 1;
535 }
536 }
537 octeon_wdt_ping();
538 }
539 return count;
540}
541
542/**
543 * octeon_wdt_ioctl:
544 * @file: file handle to the device
545 * @cmd: watchdog command
546 * @arg: argument pointer
547 *
548 * The watchdog API defines a common set of functions for all
549 * watchdogs according to their available features. We only
550 * actually usefully support querying capabilities and setting
551 * the timeout.
552 */
553
554static long octeon_wdt_ioctl(struct file *file, unsigned int cmd,
555 unsigned long arg)
556{
557 void __user *argp = (void __user *)arg;
558 int __user *p = argp;
559 int new_heartbeat;
560
561 static struct watchdog_info ident = {
562 .options = WDIOF_SETTIMEOUT|
563 WDIOF_MAGICCLOSE|
564 WDIOF_KEEPALIVEPING,
565 .firmware_version = 1,
566 .identity = "OCTEON",
567 };
568
569 switch (cmd) {
570 case WDIOC_GETSUPPORT:
571 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
572 case WDIOC_GETSTATUS:
573 case WDIOC_GETBOOTSTATUS:
574 return put_user(0, p);
575 case WDIOC_KEEPALIVE:
576 octeon_wdt_ping();
577 return 0;
578 case WDIOC_SETTIMEOUT:
579 if (get_user(new_heartbeat, p))
580 return -EFAULT;
581 if (octeon_wdt_set_heartbeat(new_heartbeat))
582 return -EINVAL;
583 /* Fall through. */
584 case WDIOC_GETTIMEOUT:
585 return put_user(heartbeat, p);
586 default:
587 return -ENOTTY;
588 }
589}
590
591/**
592 * octeon_wdt_open:
593 * @inode: inode of device
594 * @file: file handle to device
595 *
596 * The watchdog device has been opened. The watchdog device is single
597 * open and on opening we do a ping to reset the counters.
598 */
599
600static int octeon_wdt_open(struct inode *inode, struct file *file)
601{
602 if (test_and_set_bit(0, &octeon_wdt_is_open))
603 return -EBUSY;
604 /*
605 * Activate
606 */
607 octeon_wdt_ping();
608 do_coundown = 1;
609 return nonseekable_open(inode, file);
610}
611
612/**
613 * octeon_wdt_release:
614 * @inode: inode to board
615 * @file: file handle to board
616 *
617 * The watchdog has a configurable API. There is a religious dispute
618 * between people who want their watchdog to be able to shut down and
619 * those who want to be sure if the watchdog manager dies the machine
620 * reboots. In the former case we disable the counters, in the latter
621 * case you have to open it again very soon.
622 */
623
624static int octeon_wdt_release(struct inode *inode, struct file *file)
625{
626 if (expect_close) {
627 do_coundown = 0;
628 octeon_wdt_ping();
629 } else {
630 pr_crit("octeon_wdt: WDT device closed unexpectedly. WDT will not stop!\n");
631 }
632 clear_bit(0, &octeon_wdt_is_open);
633 expect_close = 0;
634 return 0;
635}
636
637static const struct file_operations octeon_wdt_fops = {
638 .owner = THIS_MODULE,
639 .llseek = no_llseek,
640 .write = octeon_wdt_write,
641 .unlocked_ioctl = octeon_wdt_ioctl,
642 .open = octeon_wdt_open,
643 .release = octeon_wdt_release,
644};
645
646static struct miscdevice octeon_wdt_miscdev = {
647 .minor = WATCHDOG_MINOR,
648 .name = "watchdog",
649 .fops = &octeon_wdt_fops,
650};
651
652static struct notifier_block octeon_wdt_cpu_notifier = {
653 .notifier_call = octeon_wdt_cpu_callback,
654};
655
656
657/**
658 * Module/ driver initialization.
659 *
660 * Returns Zero on success
661 */
662static int __init octeon_wdt_init(void)
663{
664 int i;
665 int ret;
666 int cpu;
667 u64 *ptr;
668
669 /*
670 * Watchdog time expiration length = The 16 bits of LEN
671 * represent the most significant bits of a 24 bit decrementer
672 * that decrements every 256 cycles.
673 *
674 * Try for a timeout of 5 sec, if that fails a smaller number
675 * of even seconds,
676 */
677 max_timeout_sec = 6;
678 do {
679 max_timeout_sec--;
680 timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8;
681 } while (timeout_cnt > 65535);
682
683 BUG_ON(timeout_cnt == 0);
684
685 octeon_wdt_calc_parameters(heartbeat);
686
687 pr_info("octeon_wdt: Initial granularity %d Sec.\n", timeout_sec);
688
689 ret = misc_register(&octeon_wdt_miscdev);
690 if (ret) {
691 pr_err("octeon_wdt: cannot register miscdev on minor=%d (err=%d)\n",
692 WATCHDOG_MINOR, ret);
693 goto out;
694 }
695
696 /* Build the NMI handler ... */
697 octeon_wdt_build_stage1();
698
699 /* ... and install it. */
700 ptr = (u64 *) nmi_stage1_insns;
701 for (i = 0; i < 16; i++) {
702 cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
703 cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]);
704 }
705 cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
706
707 cpumask_clear(&irq_enabled_cpus);
708
709 for_each_online_cpu(cpu)
710 octeon_wdt_setup_interrupt(cpu);
711
712 register_hotcpu_notifier(&octeon_wdt_cpu_notifier);
713out:
714 return ret;
715}
716
717/**
718 * Module / driver shutdown
719 */
720static void __exit octeon_wdt_cleanup(void)
721{
722 int cpu;
723
724 misc_deregister(&octeon_wdt_miscdev);
725
726 unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier);
727
728 for_each_online_cpu(cpu) {
729 int core = cpu2core(cpu);
730 /* Disable the watchdog */
731 cvmx_write_csr(CVMX_CIU_WDOGX(core), 0);
732 /* Free the interrupt handler */
733 free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq);
734 }
735 /*
736 * Disable the boot-bus memory, the code it points to is soon
737 * to go missing.
738 */
739 cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0);
740}
741
742MODULE_LICENSE("GPL");
743MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
744MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver.");
745module_init(octeon_wdt_init);
746module_exit(octeon_wdt_cleanup);
diff --git a/drivers/watchdog/octeon-wdt-nmi.S b/drivers/watchdog/octeon-wdt-nmi.S
new file mode 100644
index 000000000000..8a900a5e3233
--- /dev/null
+++ b/drivers/watchdog/octeon-wdt-nmi.S
@@ -0,0 +1,64 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2007 Cavium Networks
7 */
8#include <asm/asm.h>
9#include <asm/regdef.h>
10
11#define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0)
12
13 NESTED(octeon_wdt_nmi_stage2, 0, sp)
14 .set push
15 .set noreorder
16 .set noat
17 /* Save all registers to the top CVMSEG. This shouldn't
18 * corrupt any state used by the kernel. Also all registers
19 * should have the value right before the NMI. */
20 SAVE_REG(0)
21 SAVE_REG(1)
22 SAVE_REG(2)
23 SAVE_REG(3)
24 SAVE_REG(4)
25 SAVE_REG(5)
26 SAVE_REG(6)
27 SAVE_REG(7)
28 SAVE_REG(8)
29 SAVE_REG(9)
30 SAVE_REG(10)
31 SAVE_REG(11)
32 SAVE_REG(12)
33 SAVE_REG(13)
34 SAVE_REG(14)
35 SAVE_REG(15)
36 SAVE_REG(16)
37 SAVE_REG(17)
38 SAVE_REG(18)
39 SAVE_REG(19)
40 SAVE_REG(20)
41 SAVE_REG(21)
42 SAVE_REG(22)
43 SAVE_REG(23)
44 SAVE_REG(24)
45 SAVE_REG(25)
46 SAVE_REG(26)
47 SAVE_REG(27)
48 SAVE_REG(28)
49 SAVE_REG(29)
50 SAVE_REG(30)
51 SAVE_REG(31)
52 /* Set the stack to begin right below the registers */
53 li sp, -32768+6912-32*8
54 /* Load the address of the third stage handler */
55 dla a0, octeon_wdt_nmi_stage3
56 /* Call the third stage handler */
57 jal a0
58 /* a0 is the address of the saved registers */
59 move a0, sp
60 /* Loop forvever if we get here. */
611: b 1b
62 nop
63 .set pop
64 END(octeon_wdt_nmi_stage2)
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 76b58abf4451..3dd4971160ef 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};
@@ -146,8 +144,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))) 144 if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
147 return -EBUSY; 145 return -EBUSY;
148 146
149 clk_enable(wdev->ick); /* Enable the interface clock */ 147 pm_runtime_get_sync(wdev->dev);
150 clk_enable(wdev->fck); /* Enable the functional clock */
151 148
152 /* initialize prescaler */ 149 /* initialize prescaler */
153 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) 150 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -177,8 +174,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
177 174
178 omap_wdt_disable(wdev); 175 omap_wdt_disable(wdev);
179 176
180 clk_disable(wdev->ick); 177 pm_runtime_put_sync(wdev->dev);
181 clk_disable(wdev->fck);
182#else 178#else
183 printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); 179 printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
184#endif 180#endif
@@ -258,6 +254,7 @@ static const struct file_operations omap_wdt_fops = {
258 .unlocked_ioctl = omap_wdt_ioctl, 254 .unlocked_ioctl = omap_wdt_ioctl,
259 .open = omap_wdt_open, 255 .open = omap_wdt_open,
260 .release = omap_wdt_release, 256 .release = omap_wdt_release,
257 .llseek = no_llseek,
261}; 258};
262 259
263static int __devinit omap_wdt_probe(struct platform_device *pdev) 260static int __devinit omap_wdt_probe(struct platform_device *pdev)
@@ -292,19 +289,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
292 289
293 wdev->omap_wdt_users = 0; 290 wdev->omap_wdt_users = 0;
294 wdev->mem = mem; 291 wdev->mem = mem;
295 292 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 293
309 wdev->base = ioremap(res->start, resource_size(res)); 294 wdev->base = ioremap(res->start, resource_size(res));
310 if (!wdev->base) { 295 if (!wdev->base) {
@@ -314,8 +299,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
314 299
315 platform_set_drvdata(pdev, wdev); 300 platform_set_drvdata(pdev, wdev);
316 301
317 clk_enable(wdev->ick); 302 pm_runtime_enable(wdev->dev);
318 clk_enable(wdev->fck); 303 pm_runtime_get_sync(wdev->dev);
319 304
320 omap_wdt_disable(wdev); 305 omap_wdt_disable(wdev);
321 omap_wdt_adjust_timeout(timer_margin); 306 omap_wdt_adjust_timeout(timer_margin);
@@ -333,11 +318,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
333 __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 318 __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
334 timer_margin); 319 timer_margin);
335 320
336 /* autogate OCP interface clock */ 321 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 322
342 omap_wdt_dev = pdev; 323 omap_wdt_dev = pdev;
343 324
@@ -349,12 +330,6 @@ err_misc:
349 330
350err_ioremap: 331err_ioremap:
351 wdev->base = NULL; 332 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); 333 kfree(wdev);
359 334
360err_kzalloc: 335err_kzalloc:
@@ -386,8 +361,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
386 release_mem_region(res->start, resource_size(res)); 361 release_mem_region(res->start, resource_size(res));
387 platform_set_drvdata(pdev, NULL); 362 platform_set_drvdata(pdev, NULL);
388 363
389 clk_put(wdev->ick);
390 clk_put(wdev->fck);
391 iounmap(wdev->base); 364 iounmap(wdev->base);
392 365
393 kfree(wdev); 366 kfree(wdev);
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index d3aa2f1fe61d..3a56bc360924 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -53,7 +53,9 @@
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
56static int io = 0x2E; /* Address used on Portwell Boards */ 56#define IO_DEFAULT 0x2E /* Address used on Portwell Boards */
57
58static int io = IO_DEFAULT;
57 59
58static int timeout = DEFAULT_TIMEOUT; /* timeout value */ 60static int timeout = DEFAULT_TIMEOUT; /* timeout value */
59static unsigned long timer_enabled; /* is the timer enabled? */ 61static unsigned long timer_enabled; /* is the timer enabled? */
@@ -583,12 +585,13 @@ MODULE_LICENSE("GPL");
583MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 585MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
584 586
585module_param(io, int, 0); 587module_param(io, int, 0);
586MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); 588MODULE_PARM_DESC(io, MODNAME " I/O port (default: "
589 __MODULE_STRING(IO_DEFAULT) ").");
587 590
588module_param(timeout, int, 0); 591module_param(timeout, int, 0);
589MODULE_PARM_DESC(timeout, 592MODULE_PARM_DESC(timeout,
590 "Watchdog timeout in minutes (default=" 593 "Watchdog timeout in minutes (default="
591 __MODULE_STRING(timeout) ")."); 594 __MODULE_STRING(DEFAULT_TIMEOUT) ").");
592 595
593module_param(nowayout, int, 0); 596module_param(nowayout, int, 0);
594MODULE_PARM_DESC(nowayout, 597MODULE_PARM_DESC(nowayout,
diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c
index 09102f09e681..a7b5ad2a98bd 100644
--- a/drivers/watchdog/pnx833x_wdt.c
+++ b/drivers/watchdog/pnx833x_wdt.c
@@ -33,6 +33,8 @@
33#define PFX "pnx833x: " 33#define PFX "pnx833x: "
34#define WATCHDOG_TIMEOUT 30 /* 30 sec Maximum timeout */ 34#define WATCHDOG_TIMEOUT 30 /* 30 sec Maximum timeout */
35#define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */ 35#define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */
36#define PNX_WATCHDOG_TIMEOUT (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY)
37#define PNX_TIMEOUT_VALUE 2040000000U
36 38
37/** CONFIG block */ 39/** CONFIG block */
38#define PNX833X_CONFIG (0x07000U) 40#define PNX833X_CONFIG (0x07000U)
@@ -47,20 +49,21 @@
47static int pnx833x_wdt_alive; 49static int pnx833x_wdt_alive;
48 50
49/* Set default timeout in MHZ.*/ 51/* Set default timeout in MHZ.*/
50static int pnx833x_wdt_timeout = (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY); 52static int pnx833x_wdt_timeout = PNX_WATCHDOG_TIMEOUT;
51module_param(pnx833x_wdt_timeout, int, 0); 53module_param(pnx833x_wdt_timeout, int, 0);
52MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default=" 54MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default="
53 __MODULE_STRING(pnx833x_wdt_timeout) "(30 seconds)."); 55 __MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds).");
54 56
55static int nowayout = WATCHDOG_NOWAYOUT; 57static int nowayout = WATCHDOG_NOWAYOUT;
56module_param(nowayout, int, 0); 58module_param(nowayout, int, 0);
57MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 59MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
58 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 60 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
59 61
60static int start_enabled = 1; 62#define START_DEFAULT 1
63static int start_enabled = START_DEFAULT;
61module_param(start_enabled, int, 0); 64module_param(start_enabled, int, 0);
62MODULE_PARM_DESC(start_enabled, "Watchdog is started on module insertion " 65MODULE_PARM_DESC(start_enabled, "Watchdog is started on module insertion "
63 "(default=" __MODULE_STRING(start_enabled) ")"); 66 "(default=" __MODULE_STRING(START_DEFAULT) ")");
64 67
65static void pnx833x_wdt_start(void) 68static void pnx833x_wdt_start(void)
66{ 69{
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 69c6adbd8205..3939e53f5f98 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * RDC321x watchdog driver 2 * RDC321x watchdog driver
3 * 3 *
4 * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> 4 * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
5 * 5 *
6 * This driver is highly inspired from the cpu5_wdt driver 6 * This driver is highly inspired from the cpu5_wdt driver
7 * 7 *
@@ -36,8 +36,7 @@
36#include <linux/watchdog.h> 36#include <linux/watchdog.h>
37#include <linux/io.h> 37#include <linux/io.h>
38#include <linux/uaccess.h> 38#include <linux/uaccess.h>
39 39#include <linux/mfd/rdc321x.h>
40#include <asm/rdc321x_defs.h>
41 40
42#define RDC_WDT_MASK 0x80000000 /* Mask */ 41#define RDC_WDT_MASK 0x80000000 /* Mask */
43#define RDC_WDT_EN 0x00800000 /* Enable bit */ 42#define RDC_WDT_EN 0x00800000 /* Enable bit */
@@ -63,6 +62,8 @@ static struct {
63 int default_ticks; 62 int default_ticks;
64 unsigned long inuse; 63 unsigned long inuse;
65 spinlock_t lock; 64 spinlock_t lock;
65 struct pci_dev *sb_pdev;
66 int base_reg;
66} rdc321x_wdt_device; 67} rdc321x_wdt_device;
67 68
68/* generic helper functions */ 69/* generic helper functions */
@@ -70,14 +71,18 @@ static struct {
70static void rdc321x_wdt_trigger(unsigned long unused) 71static void rdc321x_wdt_trigger(unsigned long unused)
71{ 72{
72 unsigned long flags; 73 unsigned long flags;
74 u32 val;
73 75
74 if (rdc321x_wdt_device.running) 76 if (rdc321x_wdt_device.running)
75 ticks--; 77 ticks--;
76 78
77 /* keep watchdog alive */ 79 /* keep watchdog alive */
78 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 80 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
79 outl(RDC_WDT_EN | inl(RDC3210_CFGREG_DATA), 81 pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
80 RDC3210_CFGREG_DATA); 82 rdc321x_wdt_device.base_reg, &val);
83 val |= RDC_WDT_EN;
84 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
85 rdc321x_wdt_device.base_reg, val);
81 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 86 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
82 87
83 /* requeue?? */ 88 /* requeue?? */
@@ -105,10 +110,13 @@ static void rdc321x_wdt_start(void)
105 110
106 /* Clear the timer */ 111 /* Clear the timer */
107 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 112 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
108 outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); 113 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
114 rdc321x_wdt_device.base_reg, RDC_CLS_TMR);
109 115
110 /* Enable watchdog and set the timeout to 81.92 us */ 116 /* Enable watchdog and set the timeout to 81.92 us */
111 outl(RDC_WDT_EN | RDC_WDT_CNT, RDC3210_CFGREG_DATA); 117 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
118 rdc321x_wdt_device.base_reg,
119 RDC_WDT_EN | RDC_WDT_CNT);
112 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 120 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
113 121
114 mod_timer(&rdc321x_wdt_device.timer, 122 mod_timer(&rdc321x_wdt_device.timer,
@@ -148,7 +156,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
148 unsigned long arg) 156 unsigned long arg)
149{ 157{
150 void __user *argp = (void __user *)arg; 158 void __user *argp = (void __user *)arg;
151 unsigned int value; 159 u32 value;
152 static const struct watchdog_info ident = { 160 static const struct watchdog_info ident = {
153 .options = WDIOF_CARDRESET, 161 .options = WDIOF_CARDRESET,
154 .identity = "RDC321x WDT", 162 .identity = "RDC321x WDT",
@@ -162,9 +170,10 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
162 case WDIOC_GETSTATUS: 170 case WDIOC_GETSTATUS:
163 /* Read the value from the DATA register */ 171 /* Read the value from the DATA register */
164 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 172 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
165 value = inl(RDC3210_CFGREG_DATA); 173 pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
174 rdc321x_wdt_device.base_reg, &value);
166 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 175 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
167 if (copy_to_user(argp, &value, sizeof(int))) 176 if (copy_to_user(argp, &value, sizeof(u32)))
168 return -EFAULT; 177 return -EFAULT;
169 break; 178 break;
170 case WDIOC_GETSUPPORT: 179 case WDIOC_GETSUPPORT:
@@ -219,17 +228,35 @@ static struct miscdevice rdc321x_wdt_misc = {
219static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) 228static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
220{ 229{
221 int err; 230 int err;
231 struct resource *r;
232 struct rdc321x_wdt_pdata *pdata;
233
234 pdata = platform_get_drvdata(pdev);
235 if (!pdata) {
236 dev_err(&pdev->dev, "no platform data supplied\n");
237 return -ENODEV;
238 }
239
240 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "wdt-reg");
241 if (!r) {
242 dev_err(&pdev->dev, "failed to get wdt-reg resource\n");
243 return -ENODEV;
244 }
245
246 rdc321x_wdt_device.sb_pdev = pdata->sb_pdev;
247 rdc321x_wdt_device.base_reg = r->start;
222 248
223 err = misc_register(&rdc321x_wdt_misc); 249 err = misc_register(&rdc321x_wdt_misc);
224 if (err < 0) { 250 if (err < 0) {
225 printk(KERN_ERR PFX "watchdog misc_register failed\n"); 251 dev_err(&pdev->dev, "misc_register failed\n");
226 return err; 252 return err;
227 } 253 }
228 254
229 spin_lock_init(&rdc321x_wdt_device.lock); 255 spin_lock_init(&rdc321x_wdt_device.lock);
230 256
231 /* Reset the watchdog */ 257 /* Reset the watchdog */
232 outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); 258 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
259 rdc321x_wdt_device.base_reg, RDC_WDT_RST);
233 260
234 init_completion(&rdc321x_wdt_device.stop); 261 init_completion(&rdc321x_wdt_device.stop);
235 rdc321x_wdt_device.queue = 0; 262 rdc321x_wdt_device.queue = 0;
@@ -240,7 +267,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
240 267
241 rdc321x_wdt_device.default_ticks = ticks; 268 rdc321x_wdt_device.default_ticks = ticks;
242 269
243 printk(KERN_INFO PFX "watchdog init success\n"); 270 dev_info(&pdev->dev, "watchdog init success\n");
244 271
245 return 0; 272 return 0;
246} 273}
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 5dceeddc8859..3faee1ae64bd 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -172,7 +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 of_device *op, 175static int __devinit riowd_probe(struct platform_device *op,
176 const struct of_device_id *match) 176 const struct of_device_id *match)
177{ 177{
178 struct riowd *p; 178 struct riowd *p;
@@ -219,7 +219,7 @@ out:
219 return err; 219 return err;
220} 220}
221 221
222static int __devexit riowd_remove(struct of_device *op) 222static int __devexit riowd_remove(struct platform_device *op)
223{ 223{
224 struct riowd *p = dev_get_drvdata(&op->dev); 224 struct riowd *p = dev_get_drvdata(&op->dev);
225 225
@@ -250,12 +250,12 @@ static struct of_platform_driver riowd_driver = {
250 250
251static int __init riowd_init(void) 251static int __init riowd_init(void)
252{ 252{
253 return of_register_driver(&riowd_driver, &of_bus_type); 253 return of_register_platform_driver(&riowd_driver);
254} 254}
255 255
256static void __exit riowd_exit(void) 256static void __exit riowd_exit(void)
257{ 257{
258 of_unregister_driver(&riowd_driver); 258 of_unregister_platform_driver(&riowd_driver);
259} 259}
260 260
261module_init(riowd_init); 261module_init(riowd_init);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index e4cebef55177..ae53662c29bc 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -63,7 +63,7 @@ module_param(nowayout, int, 0);
63module_param(soft_noboot, int, 0); 63module_param(soft_noboot, int, 0);
64module_param(debug, int, 0); 64module_param(debug, int, 0);
65 65
66MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. default=" 66MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. (default="
67 __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")"); 67 __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME) ")");
68MODULE_PARM_DESC(tmr_atboot, 68MODULE_PARM_DESC(tmr_atboot,
69 "Watchdog is started at boot time if set to 1, default=" 69 "Watchdog is started at boot time if set to 1, default="
@@ -71,8 +71,8 @@ MODULE_PARM_DESC(tmr_atboot,
71MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 71MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
72 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 72 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
73MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, " 73MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, "
74 "0 to reboot (default depends on ONLY_TESTING)"); 74 "0 to reboot (default 0)");
75MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug, (default 0)"); 75MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug (default 0)");
76 76
77static unsigned long open_lock; 77static unsigned long open_lock;
78static struct device *wdt_dev; /* platform device attached to */ 78static struct device *wdt_dev; /* platform device attached to */
@@ -426,8 +426,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
426 wdt_mem = request_mem_region(res->start, size, pdev->name); 426 wdt_mem = request_mem_region(res->start, size, pdev->name);
427 if (wdt_mem == NULL) { 427 if (wdt_mem == NULL) {
428 dev_err(dev, "failed to get memory region\n"); 428 dev_err(dev, "failed to get memory region\n");
429 ret = -ENOENT; 429 return -EBUSY;
430 goto err_req;
431 } 430 }
432 431
433 wdt_base = ioremap(res->start, size); 432 wdt_base = ioremap(res->start, size);
@@ -533,21 +532,22 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
533 532
534static int __devexit s3c2410wdt_remove(struct platform_device *dev) 533static int __devexit s3c2410wdt_remove(struct platform_device *dev)
535{ 534{
536 s3c2410wdt_cpufreq_deregister(); 535 misc_deregister(&s3c2410wdt_miscdev);
537
538 release_resource(wdt_mem);
539 kfree(wdt_mem);
540 wdt_mem = NULL;
541 536
542 free_irq(wdt_irq->start, dev); 537 s3c2410wdt_cpufreq_deregister();
543 wdt_irq = NULL;
544 538
545 clk_disable(wdt_clock); 539 clk_disable(wdt_clock);
546 clk_put(wdt_clock); 540 clk_put(wdt_clock);
547 wdt_clock = NULL; 541 wdt_clock = NULL;
548 542
543 free_irq(wdt_irq->start, dev);
544 wdt_irq = NULL;
545
549 iounmap(wdt_base); 546 iounmap(wdt_base);
550 misc_deregister(&s3c2410wdt_miscdev); 547
548 release_resource(wdt_mem);
549 kfree(wdt_mem);
550 wdt_mem = NULL;
551 return 0; 551 return 0;
552} 552}
553 553
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c
index 88c83aa57303..f31493e65b38 100644
--- a/drivers/watchdog/sb_wdog.c
+++ b/drivers/watchdog/sb_wdog.c
@@ -305,7 +305,7 @@ static int __init sbwdog_init(void)
305 if (ret) { 305 if (ret) {
306 printk(KERN_ERR "%s: failed to request irq 1 - %d\n", 306 printk(KERN_ERR "%s: failed to request irq 1 - %d\n",
307 ident.identity, ret); 307 ident.identity, ret);
308 return ret; 308 goto out;
309 } 309 }
310 310
311 ret = misc_register(&sbwdog_miscdev); 311 ret = misc_register(&sbwdog_miscdev);
@@ -313,14 +313,20 @@ static int __init sbwdog_init(void)
313 printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", 313 printk(KERN_INFO "%s: timeout is %ld.%ld secs\n",
314 ident.identity, 314 ident.identity,
315 timeout / 1000000, (timeout / 100000) % 10); 315 timeout / 1000000, (timeout / 100000) % 10);
316 } else 316 return 0;
317 free_irq(1, (void *)user_dog); 317 }
318 free_irq(1, (void *)user_dog);
319out:
320 unregister_reboot_notifier(&sbwdog_notifier);
321
318 return ret; 322 return ret;
319} 323}
320 324
321static void __exit sbwdog_exit(void) 325static void __exit sbwdog_exit(void)
322{ 326{
323 misc_deregister(&sbwdog_miscdev); 327 misc_deregister(&sbwdog_miscdev);
328 free_irq(1, (void *)user_dog);
329 unregister_reboot_notifier(&sbwdog_notifier);
324} 330}
325 331
326module_init(sbwdog_init); 332module_init(sbwdog_init);
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 9c40f48804f5..0461858e07d0 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -425,6 +425,8 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
425 val = therm_trip ? 0x06 : 0x04; 425 val = therm_trip ? 0x06 : 0x04;
426 outb(val, sch311x_wdt_data.runtime_reg + RESGEN); 426 outb(val, sch311x_wdt_data.runtime_reg + RESGEN);
427 427
428 sch311x_wdt_miscdev.parent = dev;
429
428 err = misc_register(&sch311x_wdt_miscdev); 430 err = misc_register(&sch311x_wdt_miscdev);
429 if (err != 0) { 431 if (err != 0) {
430 dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", 432 dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n",
@@ -432,8 +434,6 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
432 goto exit_release_region3; 434 goto exit_release_region3;
433 } 435 }
434 436
435 sch311x_wdt_miscdev.parent = dev;
436
437 dev_info(dev, 437 dev_info(dev,
438 "SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n", 438 "SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n",
439 timeout, nowayout); 439 timeout, nowayout);
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index b7d2f8a0422b..4e3e7eb5919c 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -474,7 +474,7 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
474module_param(clock_division_ratio, int, 0); 474module_param(clock_division_ratio, int, 0);
475MODULE_PARM_DESC(clock_division_ratio, 475MODULE_PARM_DESC(clock_division_ratio,
476 "Clock division ratio. Valid ranges are from 0x5 (1.31ms) " 476 "Clock division ratio. Valid ranges are from 0x5 (1.31ms) "
477 "to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")"); 477 "to 0x7 (5.25ms). (default=" __MODULE_STRING(WTCSR_CKS_4096) ")");
478 478
479module_param(heartbeat, int, 0); 479module_param(heartbeat, int, 0);
480MODULE_PARM_DESC(heartbeat, 480MODULE_PARM_DESC(heartbeat,
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
new file mode 100644
index 000000000000..808372883e88
--- /dev/null
+++ b/drivers/watchdog/sp5100_tco.c
@@ -0,0 +1,480 @@
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 void __iomem *tcobase;
46static unsigned int pm_iobase;
47static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */
48static unsigned long timer_alive;
49static char tco_expect_close;
50static struct pci_dev *sp5100_tco_pci;
51
52/* the watchdog platform device */
53static struct platform_device *sp5100_tco_platform_device;
54
55/* module parameters */
56
57#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */
58static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
59module_param(heartbeat, int, 0);
60MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
61 __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 void tco_timer_start(void)
72{
73 u32 val;
74 unsigned long flags;
75
76 spin_lock_irqsave(&tco_lock, flags);
77 val = readl(SP5100_WDT_CONTROL(tcobase));
78 val |= SP5100_WDT_START_STOP_BIT;
79 writel(val, SP5100_WDT_CONTROL(tcobase));
80 spin_unlock_irqrestore(&tco_lock, flags);
81}
82
83static void tco_timer_stop(void)
84{
85 u32 val;
86 unsigned long flags;
87
88 spin_lock_irqsave(&tco_lock, flags);
89 val = readl(SP5100_WDT_CONTROL(tcobase));
90 val &= ~SP5100_WDT_START_STOP_BIT;
91 writel(val, SP5100_WDT_CONTROL(tcobase));
92 spin_unlock_irqrestore(&tco_lock, flags);
93}
94
95static void tco_timer_keepalive(void)
96{
97 u32 val;
98 unsigned long flags;
99
100 spin_lock_irqsave(&tco_lock, flags);
101 val = readl(SP5100_WDT_CONTROL(tcobase));
102 val |= SP5100_WDT_TRIGGER_BIT;
103 writel(val, SP5100_WDT_CONTROL(tcobase));
104 spin_unlock_irqrestore(&tco_lock, flags);
105}
106
107static int tco_timer_set_heartbeat(int t)
108{
109 unsigned long flags;
110
111 if (t < 0 || t > 0xffff)
112 return -EINVAL;
113
114 /* Write new heartbeat to watchdog */
115 spin_lock_irqsave(&tco_lock, flags);
116 writel(t, SP5100_WDT_COUNT(tcobase));
117 spin_unlock_irqrestore(&tco_lock, flags);
118
119 heartbeat = t;
120 return 0;
121}
122
123/*
124 * /dev/watchdog handling
125 */
126
127static int sp5100_tco_open(struct inode *inode, struct file *file)
128{
129 /* /dev/watchdog can only be opened once */
130 if (test_and_set_bit(0, &timer_alive))
131 return -EBUSY;
132
133 /* Reload and activate timer */
134 tco_timer_start();
135 tco_timer_keepalive();
136 return nonseekable_open(inode, file);
137}
138
139static int sp5100_tco_release(struct inode *inode, struct file *file)
140{
141 /* Shut off the timer. */
142 if (tco_expect_close == 42) {
143 tco_timer_stop();
144 } else {
145 printk(KERN_CRIT PFX
146 "Unexpected close, not stopping watchdog!\n");
147 tco_timer_keepalive();
148 }
149 clear_bit(0, &timer_alive);
150 tco_expect_close = 0;
151 return 0;
152}
153
154static ssize_t sp5100_tco_write(struct file *file, const char __user *data,
155 size_t len, loff_t *ppos)
156{
157 /* See if we got the magic character 'V' and reload the timer */
158 if (len) {
159 if (!nowayout) {
160 size_t i;
161
162 /* note: just in case someone wrote the magic character
163 * five months ago... */
164 tco_expect_close = 0;
165
166 /* scan to see whether or not we got the magic character
167 */
168 for (i = 0; i != len; i++) {
169 char c;
170 if (get_user(c, data + i))
171 return -EFAULT;
172 if (c == 'V')
173 tco_expect_close = 42;
174 }
175 }
176
177 /* someone wrote to us, we should reload the timer */
178 tco_timer_keepalive();
179 }
180 return len;
181}
182
183static long sp5100_tco_ioctl(struct file *file, unsigned int cmd,
184 unsigned long arg)
185{
186 int new_options, retval = -EINVAL;
187 int new_heartbeat;
188 void __user *argp = (void __user *)arg;
189 int __user *p = argp;
190 static const struct watchdog_info ident = {
191 .options = WDIOF_SETTIMEOUT |
192 WDIOF_KEEPALIVEPING |
193 WDIOF_MAGICCLOSE,
194 .firmware_version = 0,
195 .identity = TCO_MODULE_NAME,
196 };
197
198 switch (cmd) {
199 case WDIOC_GETSUPPORT:
200 return copy_to_user(argp, &ident,
201 sizeof(ident)) ? -EFAULT : 0;
202 case WDIOC_GETSTATUS:
203 case WDIOC_GETBOOTSTATUS:
204 return put_user(0, p);
205 case WDIOC_SETOPTIONS:
206 if (get_user(new_options, p))
207 return -EFAULT;
208 if (new_options & WDIOS_DISABLECARD) {
209 tco_timer_stop();
210 retval = 0;
211 }
212 if (new_options & WDIOS_ENABLECARD) {
213 tco_timer_start();
214 tco_timer_keepalive();
215 retval = 0;
216 }
217 return retval;
218 case WDIOC_KEEPALIVE:
219 tco_timer_keepalive();
220 return 0;
221 case WDIOC_SETTIMEOUT:
222 if (get_user(new_heartbeat, p))
223 return -EFAULT;
224 if (tco_timer_set_heartbeat(new_heartbeat))
225 return -EINVAL;
226 tco_timer_keepalive();
227 /* Fall through */
228 case WDIOC_GETTIMEOUT:
229 return put_user(heartbeat, p);
230 default:
231 return -ENOTTY;
232 }
233}
234
235/*
236 * Kernel Interfaces
237 */
238
239static const struct file_operations sp5100_tco_fops = {
240 .owner = THIS_MODULE,
241 .llseek = no_llseek,
242 .write = sp5100_tco_write,
243 .unlocked_ioctl = sp5100_tco_ioctl,
244 .open = sp5100_tco_open,
245 .release = sp5100_tco_release,
246};
247
248static struct miscdevice sp5100_tco_miscdev = {
249 .minor = WATCHDOG_MINOR,
250 .name = "watchdog",
251 .fops = &sp5100_tco_fops,
252};
253
254/*
255 * Data for PCI driver interface
256 *
257 * This data only exists for exporting the supported
258 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
259 * register a pci_driver, because someone else might
260 * want to register another driver on the same PCI id.
261 */
262static struct pci_device_id sp5100_tco_pci_tbl[] = {
263 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
264 PCI_ANY_ID, },
265 { 0, }, /* End of list */
266};
267MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
268
269/*
270 * Init & exit routines
271 */
272
273static unsigned char __devinit sp5100_tco_setupdevice(void)
274{
275 struct pci_dev *dev = NULL;
276 u32 val;
277
278 /* Match the PCI device */
279 for_each_pci_dev(dev) {
280 if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) {
281 sp5100_tco_pci = dev;
282 break;
283 }
284 }
285
286 if (!sp5100_tco_pci)
287 return 0;
288
289 /* Request the IO ports used by this driver */
290 pm_iobase = SP5100_IO_PM_INDEX_REG;
291 if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
292 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
293 pm_iobase);
294 goto exit;
295 }
296
297 /* Find the watchdog base address. */
298 outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG);
299 val = inb(SP5100_IO_PM_DATA_REG);
300 outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG);
301 val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
302 outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG);
303 val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
304 outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG);
305 /* Low three bits of BASE0 are reserved. */
306 val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
307
308 tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
309 if (tcobase == 0) {
310 printk(KERN_ERR PFX "failed to get tcobase address\n");
311 goto unreg_region;
312 }
313
314 /* Enable watchdog decode bit */
315 pci_read_config_dword(sp5100_tco_pci,
316 SP5100_PCI_WATCHDOG_MISC_REG,
317 &val);
318
319 val |= SP5100_PCI_WATCHDOG_DECODE_EN;
320
321 pci_write_config_dword(sp5100_tco_pci,
322 SP5100_PCI_WATCHDOG_MISC_REG,
323 val);
324
325 /* Enable Watchdog timer and set the resolution to 1 sec. */
326 outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
327 val = inb(SP5100_IO_PM_DATA_REG);
328 val |= SP5100_PM_WATCHDOG_SECOND_RES;
329 val &= ~SP5100_PM_WATCHDOG_DISABLE;
330 outb(val, SP5100_IO_PM_DATA_REG);
331
332 /* Check that the watchdog action is set to reset the system. */
333 val = readl(SP5100_WDT_CONTROL(tcobase));
334 val &= ~SP5100_PM_WATCHDOG_ACTION_RESET;
335 writel(val, SP5100_WDT_CONTROL(tcobase));
336
337 /* Set a reasonable heartbeat before we stop the timer */
338 tco_timer_set_heartbeat(heartbeat);
339
340 /*
341 * Stop the TCO before we change anything so we don't race with
342 * a zeroed timer.
343 */
344 tco_timer_stop();
345
346 /* Done */
347 return 1;
348
349 iounmap(tcobase);
350unreg_region:
351 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
352exit:
353 return 0;
354}
355
356static int __devinit sp5100_tco_init(struct platform_device *dev)
357{
358 int ret;
359 u32 val;
360
361 /* Check whether or not the hardware watchdog is there. If found, then
362 * set it up.
363 */
364 if (!sp5100_tco_setupdevice())
365 return -ENODEV;
366
367 /* Check to see if last reboot was due to watchdog timeout */
368 printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
369 readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
370 "" : "not ");
371
372 /* Clear out the old status */
373 val = readl(SP5100_WDT_CONTROL(tcobase));
374 val &= ~SP5100_PM_WATCHDOG_FIRED;
375 writel(val, SP5100_WDT_CONTROL(tcobase));
376
377 /*
378 * Check that the heartbeat value is within it's range.
379 * If not, reset to the default.
380 */
381 if (tco_timer_set_heartbeat(heartbeat)) {
382 heartbeat = WATCHDOG_HEARTBEAT;
383 tco_timer_set_heartbeat(heartbeat);
384 }
385
386 ret = misc_register(&sp5100_tco_miscdev);
387 if (ret != 0) {
388 printk(KERN_ERR PFX "cannot register miscdev on minor="
389 "%d (err=%d)\n",
390 WATCHDOG_MINOR, ret);
391 goto exit;
392 }
393
394 clear_bit(0, &timer_alive);
395
396 printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec"
397 " (nowayout=%d)\n",
398 tcobase, heartbeat, nowayout);
399
400 return 0;
401
402exit:
403 iounmap(tcobase);
404 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
405 return ret;
406}
407
408static void __devexit sp5100_tco_cleanup(void)
409{
410 /* Stop the timer before we leave */
411 if (!nowayout)
412 tco_timer_stop();
413
414 /* Deregister */
415 misc_deregister(&sp5100_tco_miscdev);
416 iounmap(tcobase);
417 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
418}
419
420static int __devexit sp5100_tco_remove(struct platform_device *dev)
421{
422 if (tcobase)
423 sp5100_tco_cleanup();
424 return 0;
425}
426
427static void sp5100_tco_shutdown(struct platform_device *dev)
428{
429 tco_timer_stop();
430}
431
432static struct platform_driver sp5100_tco_driver = {
433 .probe = sp5100_tco_init,
434 .remove = __devexit_p(sp5100_tco_remove),
435 .shutdown = sp5100_tco_shutdown,
436 .driver = {
437 .owner = THIS_MODULE,
438 .name = TCO_MODULE_NAME,
439 },
440};
441
442static int __init sp5100_tco_init_module(void)
443{
444 int err;
445
446 printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n",
447 TCO_VERSION);
448
449 err = platform_driver_register(&sp5100_tco_driver);
450 if (err)
451 return err;
452
453 sp5100_tco_platform_device = platform_device_register_simple(
454 TCO_MODULE_NAME, -1, NULL, 0);
455 if (IS_ERR(sp5100_tco_platform_device)) {
456 err = PTR_ERR(sp5100_tco_platform_device);
457 goto unreg_platform_driver;
458 }
459
460 return 0;
461
462unreg_platform_driver:
463 platform_driver_unregister(&sp5100_tco_driver);
464 return err;
465}
466
467static void __exit sp5100_tco_cleanup_module(void)
468{
469 platform_device_unregister(sp5100_tco_platform_device);
470 platform_driver_unregister(&sp5100_tco_driver);
471 printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n");
472}
473
474module_init(sp5100_tco_init_module);
475module_exit(sp5100_tco_cleanup_module);
476
477MODULE_AUTHOR("Priyanka Gupta");
478MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset");
479MODULE_LICENSE("GPL");
480MODULE_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
new file mode 100644
index 000000000000..9127eda2145b
--- /dev/null
+++ b/drivers/watchdog/sp805_wdt.c
@@ -0,0 +1,387 @@
1/*
2 * drivers/char/watchdog/sp805-wdt.c
3 *
4 * Watchdog driver for ARM SP805 watchdog module
5 *
6 * Copyright (C) 2010 ST Microelectronics
7 * Viresh Kumar<viresh.kumar@st.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2 or later. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/device.h>
15#include <linux/resource.h>
16#include <linux/amba/bus.h>
17#include <linux/bitops.h>
18#include <linux/clk.h>
19#include <linux/fs.h>
20#include <linux/init.h>
21#include <linux/io.h>
22#include <linux/ioport.h>
23#include <linux/kernel.h>
24#include <linux/math64.h>
25#include <linux/miscdevice.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/slab.h>
29#include <linux/spinlock.h>
30#include <linux/types.h>
31#include <linux/uaccess.h>
32#include <linux/watchdog.h>
33
34/* default timeout in seconds */
35#define DEFAULT_TIMEOUT 60
36
37#define MODULE_NAME "sp805-wdt"
38
39/* watchdog register offsets and masks */
40#define WDTLOAD 0x000
41 #define LOAD_MIN 0x00000001
42 #define LOAD_MAX 0xFFFFFFFF
43#define WDTVALUE 0x004
44#define WDTCONTROL 0x008
45 /* control register masks */
46 #define INT_ENABLE (1 << 0)
47 #define RESET_ENABLE (1 << 1)
48#define WDTINTCLR 0x00C
49#define WDTRIS 0x010
50#define WDTMIS 0x014
51 #define INT_MASK (1 << 0)
52#define WDTLOCK 0xC00
53 #define UNLOCK 0x1ACCE551
54 #define LOCK 0x00000001
55
56/**
57 * struct sp805_wdt: sp805 wdt device structure
58 *
59 * lock: spin lock protecting dev structure and io access
60 * base: base address of wdt
61 * clk: clock structure of wdt
62 * dev: amba device structure of wdt
63 * status: current status of wdt
64 * load_val: load value to be set for current timeout
65 * timeout: current programmed timeout
66 */
67struct sp805_wdt {
68 spinlock_t lock;
69 void __iomem *base;
70 struct clk *clk;
71 struct amba_device *adev;
72 unsigned long status;
73 #define WDT_BUSY 0
74 #define WDT_CAN_BE_CLOSED 1
75 unsigned int load_val;
76 unsigned int timeout;
77};
78
79/* local variables */
80static struct sp805_wdt *wdt;
81static int nowayout = WATCHDOG_NOWAYOUT;
82
83/* This routine finds load value that will reset system in required timout */
84static void wdt_setload(unsigned int timeout)
85{
86 u64 load, rate;
87
88 rate = clk_get_rate(wdt->clk);
89
90 /*
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
93 * interrupt already occured then it resets the system. This is why
94 * load is half of what should be required.
95 */
96 load = div_u64(rate, 2) * timeout - 1;
97
98 load = (load > LOAD_MAX) ? LOAD_MAX : load;
99 load = (load < LOAD_MIN) ? LOAD_MIN : load;
100
101 spin_lock(&wdt->lock);
102 wdt->load_val = load;
103 /* roundup timeout to closest positive integer value */
104 wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate);
105 spin_unlock(&wdt->lock);
106}
107
108/* returns number of seconds left for reset to occur */
109static u32 wdt_timeleft(void)
110{
111 u64 load, rate;
112
113 rate = clk_get_rate(wdt->clk);
114
115 spin_lock(&wdt->lock);
116 load = readl(wdt->base + WDTVALUE);
117
118 /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
119 if (!(readl(wdt->base + WDTRIS) & INT_MASK))
120 load += wdt->load_val + 1;
121 spin_unlock(&wdt->lock);
122
123 return div_u64(load, rate);
124}
125
126/* enables watchdog timers reset */
127static void wdt_enable(void)
128{
129 spin_lock(&wdt->lock);
130
131 writel(UNLOCK, wdt->base + WDTLOCK);
132 writel(wdt->load_val, wdt->base + WDTLOAD);
133 writel(INT_MASK, wdt->base + WDTINTCLR);
134 writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
135 writel(LOCK, wdt->base + WDTLOCK);
136
137 spin_unlock(&wdt->lock);
138}
139
140/* disables watchdog timers reset */
141static void wdt_disable(void)
142{
143 spin_lock(&wdt->lock);
144
145 writel(UNLOCK, wdt->base + WDTLOCK);
146 writel(0, wdt->base + WDTCONTROL);
147 writel(0, wdt->base + WDTLOAD);
148 writel(LOCK, wdt->base + WDTLOCK);
149
150 spin_unlock(&wdt->lock);
151}
152
153static ssize_t sp805_wdt_write(struct file *file, const char *data,
154 size_t len, loff_t *ppos)
155{
156 if (len) {
157 if (!nowayout) {
158 size_t i;
159
160 clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
161
162 for (i = 0; i != len; i++) {
163 char c;
164
165 if (get_user(c, data + i))
166 return -EFAULT;
167 /* Check for Magic Close character */
168 if (c == 'V') {
169 set_bit(WDT_CAN_BE_CLOSED,
170 &wdt->status);
171 break;
172 }
173 }
174 }
175 wdt_enable();
176 }
177 return len;
178}
179
180static const struct watchdog_info ident = {
181 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
182 .identity = MODULE_NAME,
183};
184
185static long sp805_wdt_ioctl(struct file *file, unsigned int cmd,
186 unsigned long arg)
187{
188 int ret = -ENOTTY;
189 unsigned int timeout;
190
191 switch (cmd) {
192 case WDIOC_GETSUPPORT:
193 ret = copy_to_user((struct watchdog_info *)arg, &ident,
194 sizeof(ident)) ? -EFAULT : 0;
195 break;
196
197 case WDIOC_GETSTATUS:
198 ret = put_user(0, (int *)arg);
199 break;
200
201 case WDIOC_KEEPALIVE:
202 wdt_enable();
203 ret = 0;
204 break;
205
206 case WDIOC_SETTIMEOUT:
207 ret = get_user(timeout, (unsigned int *)arg);
208 if (ret)
209 break;
210
211 wdt_setload(timeout);
212
213 wdt_enable();
214 /* Fall through */
215
216 case WDIOC_GETTIMEOUT:
217 ret = put_user(wdt->timeout, (unsigned int *)arg);
218 break;
219 case WDIOC_GETTIMELEFT:
220 ret = put_user(wdt_timeleft(), (unsigned int *)arg);
221 break;
222 }
223 return ret;
224}
225
226static int sp805_wdt_open(struct inode *inode, struct file *file)
227{
228 int ret = 0;
229
230 if (test_and_set_bit(WDT_BUSY, &wdt->status))
231 return -EBUSY;
232
233 ret = clk_enable(wdt->clk);
234 if (ret) {
235 dev_err(&wdt->adev->dev, "clock enable fail");
236 goto err;
237 }
238
239 wdt_enable();
240
241 /* can not be closed, once enabled */
242 clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
243 return nonseekable_open(inode, file);
244
245err:
246 clear_bit(WDT_BUSY, &wdt->status);
247 return ret;
248}
249
250static int sp805_wdt_release(struct inode *inode, struct file *file)
251{
252 if (!test_bit(WDT_CAN_BE_CLOSED, &wdt->status)) {
253 clear_bit(WDT_BUSY, &wdt->status);
254 dev_warn(&wdt->adev->dev, "Device closed unexpectedly\n");
255 return 0;
256 }
257
258 wdt_disable();
259 clk_disable(wdt->clk);
260 clear_bit(WDT_BUSY, &wdt->status);
261
262 return 0;
263}
264
265static const struct file_operations sp805_wdt_fops = {
266 .owner = THIS_MODULE,
267 .llseek = no_llseek,
268 .write = sp805_wdt_write,
269 .unlocked_ioctl = sp805_wdt_ioctl,
270 .open = sp805_wdt_open,
271 .release = sp805_wdt_release,
272};
273
274static struct miscdevice sp805_wdt_miscdev = {
275 .minor = WATCHDOG_MINOR,
276 .name = "watchdog",
277 .fops = &sp805_wdt_fops,
278};
279
280static int __devinit
281sp805_wdt_probe(struct amba_device *adev, struct amba_id *id)
282{
283 int ret = 0;
284
285 if (!request_mem_region(adev->res.start, resource_size(&adev->res),
286 "sp805_wdt")) {
287 dev_warn(&adev->dev, "Failed to get memory region resource\n");
288 ret = -ENOENT;
289 goto err;
290 }
291
292 wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
293 if (!wdt) {
294 dev_warn(&adev->dev, "Kzalloc failed\n");
295 ret = -ENOMEM;
296 goto err_kzalloc;
297 }
298
299 wdt->clk = clk_get(&adev->dev, NULL);
300 if (IS_ERR(wdt->clk)) {
301 dev_warn(&adev->dev, "Clock not found\n");
302 ret = PTR_ERR(wdt->clk);
303 goto err_clk_get;
304 }
305
306 wdt->base = ioremap(adev->res.start, resource_size(&adev->res));
307 if (!wdt->base) {
308 ret = -ENOMEM;
309 dev_warn(&adev->dev, "ioremap fail\n");
310 goto err_ioremap;
311 }
312
313 wdt->adev = adev;
314 spin_lock_init(&wdt->lock);
315 wdt_setload(DEFAULT_TIMEOUT);
316
317 ret = misc_register(&sp805_wdt_miscdev);
318 if (ret < 0) {
319 dev_warn(&adev->dev, "cannot register misc device\n");
320 goto err_misc_register;
321 }
322
323 dev_info(&adev->dev, "registration successful\n");
324 return 0;
325
326err_misc_register:
327 iounmap(wdt->base);
328err_ioremap:
329 clk_put(wdt->clk);
330err_clk_get:
331 kfree(wdt);
332 wdt = NULL;
333err_kzalloc:
334 release_mem_region(adev->res.start, resource_size(&adev->res));
335err:
336 dev_err(&adev->dev, "Probe Failed!!!\n");
337 return ret;
338}
339
340static int __devexit sp805_wdt_remove(struct amba_device *adev)
341{
342 misc_deregister(&sp805_wdt_miscdev);
343 iounmap(wdt->base);
344 clk_put(wdt->clk);
345 kfree(wdt);
346 release_mem_region(adev->res.start, resource_size(&adev->res));
347
348 return 0;
349}
350
351static struct amba_id sp805_wdt_ids[] __initdata = {
352 {
353 .id = 0x00141805,
354 .mask = 0x00ffffff,
355 },
356 { 0, 0 },
357};
358
359static struct amba_driver sp805_wdt_driver = {
360 .drv = {
361 .name = MODULE_NAME,
362 },
363 .id_table = sp805_wdt_ids,
364 .probe = sp805_wdt_probe,
365 .remove = __devexit_p(sp805_wdt_remove),
366};
367
368static int __init sp805_wdt_init(void)
369{
370 return amba_driver_register(&sp805_wdt_driver);
371}
372module_init(sp805_wdt_init);
373
374static void __exit sp805_wdt_exit(void)
375{
376 amba_driver_unregister(&sp805_wdt_driver);
377}
378module_exit(sp805_wdt_exit);
379
380module_param(nowayout, int, 0);
381MODULE_PARM_DESC(nowayout,
382 "Set to 1 to keep watchdog running after device release");
383
384MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
385MODULE_DESCRIPTION("ARM SP805 Watchdog Driver");
386MODULE_LICENSE("GPL");
387MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 458c499c1223..18cdeb4c4258 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
449 wdt->pdev = pdev; 449 wdt->pdev = pdev;
450 mutex_init(&wdt->lock); 450 mutex_init(&wdt->lock);
451 451
452 /* make sure that the watchdog is disabled */
453 ts72xx_wdt_stop(wdt);
454
452 error = misc_register(&ts72xx_wdt_miscdev); 455 error = misc_register(&ts72xx_wdt_miscdev);
453 if (error) { 456 if (error) {
454 dev_err(&pdev->dev, "failed to register miscdev\n"); 457 dev_err(&pdev->dev, "failed to register miscdev\n");
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index dcabe77ad141..b5045ca7e61c 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -190,6 +190,8 @@ static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
190 190
191 twl4030_wdt_dev = pdev; 191 twl4030_wdt_dev = pdev;
192 192
193 twl4030_wdt_disable(wdt);
194
193 ret = misc_register(&wdt->miscdev); 195 ret = misc_register(&wdt->miscdev);
194 if (ret) { 196 if (ret) {
195 dev_err(wdt->miscdev.parent, 197 dev_err(wdt->miscdev.parent,
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/wdt.c b/drivers/watchdog/wdt.c
index bfda2e99dd89..552a4381e78f 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(tachometer,
91static int type = 500; 91static int type = 500;
92module_param(type, int, 0); 92module_param(type, int, 0);
93MODULE_PARM_DESC(type, 93MODULE_PARM_DESC(type,
94 "WDT501-P Card type (500 or 501 , default=500)"); 94 "WDT501-P Card type (500 or 501, default=500)");
95 95
96/* 96/*
97 * Programming support 97 * Programming support
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 90ef70eb47d7..5c2521fc836c 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -63,7 +63,7 @@ static char expect_close;
63static DEFINE_SPINLOCK(spinlock); 63static DEFINE_SPINLOCK(spinlock);
64 64
65module_param(timeout, int, 0); 65module_param(timeout, int, 0);
66MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300), default=" 66MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300, default="
67 __MODULE_STRING(DEFAULT_TIMEOUT) ")"); 67 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
68module_param(testmode, int, 0); 68module_param(testmode, int, 0);
69MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0"); 69MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 7b22e3cdbc81..6130c88fa5ac 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -60,19 +60,6 @@
60 60
61#define PFX "wdt_pci: " 61#define PFX "wdt_pci: "
62 62
63/*
64 * Until Access I/O gets their application for a PCI vendor ID approved,
65 * I don't think that it's appropriate to move these constants into the
66 * regular pci_ids.h file. -- JPN 2000/01/18
67 */
68
69#ifndef PCI_VENDOR_ID_ACCESSIO
70#define PCI_VENDOR_ID_ACCESSIO 0x494f
71#endif
72#ifndef PCI_DEVICE_ID_WDG_CSM
73#define PCI_DEVICE_ID_WDG_CSM 0x22c0
74#endif
75
76/* We can only use 1 card due to the /dev/watchdog restriction */ 63/* We can only use 1 card due to the /dev/watchdog restriction */
77static int dev_count; 64static int dev_count;
78 65
@@ -743,7 +730,7 @@ static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
743static struct pci_device_id wdtpci_pci_tbl[] = { 730static struct pci_device_id wdtpci_pci_tbl[] = {
744 { 731 {
745 .vendor = PCI_VENDOR_ID_ACCESSIO, 732 .vendor = PCI_VENDOR_ID_ACCESSIO,
746 .device = PCI_DEVICE_ID_WDG_CSM, 733 .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
747 .subvendor = PCI_ANY_ID, 734 .subvendor = PCI_ANY_ID,
748 .subdevice = PCI_ANY_ID, 735 .subdevice = PCI_ANY_ID,
749 }, 736 },
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 89dd7b035295..b68d928c8f90 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -284,7 +284,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
284 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 284 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
285 285
286 if (!wm8350) { 286 if (!wm8350) {
287 dev_err(wm8350->dev, "No driver data supplied\n"); 287 pr_err("No driver data supplied\n");
288 return -ENODEV; 288 return -ENODEV;
289 } 289 }
290 290